Skip to content

Commit

Permalink
Add "Developer Mode" UI setting and client toolchain stats display.
Browse files Browse the repository at this point in the history
  • Loading branch information
xian committed Oct 1, 2022
1 parent 4fb1190 commit 6cff0b5
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 28 deletions.
12 changes: 7 additions & 5 deletions src/commonMain/kotlin/baaahs/util/Stats.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@ open class Stats {
ReadOnlyProperty<Stats, Statistic> { _, _ -> statistic }
}

fun summarize(): String = statistics.values.joinToString("\n") { it.summarize() }
val all = statistics.values

fun summarize(): String = all.joinToString("\n") { it.summarize() }

class Statistic(val name: String) {
var calls = 0
var elapsedTime = Interval(0)
val elapsedTimeMs get() = (elapsedTime / 1000).roundToInt()
val averageTime get() = if (calls > 0) elapsedTime / calls else null
val averageTimeMs get() = averageTime?.div(1000)?.roundToInt()

fun <T> time(block: () -> T): T {
val startTime = internalTimerClock.now()
Expand All @@ -40,10 +45,7 @@ open class Stats {
}

fun summarize(): String {
val avgTimeMs = if (calls > 0) {
(elapsedTime / calls * 1000).roundToInt()
} else ""
return "$name: $calls calls, avg ${avgTimeMs}ms, total ${(elapsedTime * 1000).roundToInt()}ms"
return "$name: $calls calls, avg ${averageTimeMs ?: "-"}ms, total ${elapsedTimeMs}ms"
}
}
}
3 changes: 2 additions & 1 deletion src/jsMain/kotlin/baaahs/app/settings/UiSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ data class UiSettings(
val darkMode: Boolean = true,
val useSharedContexts: Boolean = true,
val renderButtonPreviews: Boolean = true,
val appMode: AppMode = AppMode.Show
val appMode: AppMode = AppMode.Show,
val developerMode: Boolean = false
)
5 changes: 5 additions & 0 deletions src/jsMain/kotlin/baaahs/app/ui/AppToolbar.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package baaahs.app.ui

import baaahs.app.ui.dev.devModeToolbarMenu
import baaahs.app.ui.editor.SceneEditIntent
import baaahs.app.ui.editor.ShowEditIntent
import baaahs.client.document.DocumentManager
Expand Down Expand Up @@ -241,6 +242,10 @@ val AppToolbar = xComponent<AppToolbarProps>("AppToolbar") { props ->
}
}

if (appContext.uiSettings.developerMode) {
devModeToolbarMenu {}
}

help {
attrs.divClass = themeStyles.appToolbarHelpIcon.name
attrs.inject(HelpText.appToolbar)
Expand Down
3 changes: 2 additions & 1 deletion src/jsMain/kotlin/baaahs/app/ui/StyleConstants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ object StyleConstants {
object Layers {
val sharedGlCanvas = 5
val aboveSharedGlCanvas = 10
val floatingWindows = 100
val muiDialogs = 1200
val floatingWindows = 1300
}
}
3 changes: 3 additions & 0 deletions src/jsMain/kotlin/baaahs/app/ui/Styles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ class ThemeStyles(val theme: Theme) : StyleSheet("app-ui-theme", isStatic = true
h4 { margin = "unset" }
}

val appToolbarDevMenuIcon by css {
transform.translateY(1.em)
}
val appToolbarHelpIcon by css {
transform.translateY(1.em)
}
Expand Down
119 changes: 119 additions & 0 deletions src/jsMain/kotlin/baaahs/app/ui/dev/DevModeToolbarMenuView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package baaahs.app.ui.dev

import baaahs.app.ui.CommonIcons
import baaahs.app.ui.appContext
import baaahs.gl.RootToolchain
import baaahs.ui.components.palette
import baaahs.ui.unaryPlus
import baaahs.ui.withMouseEvent
import baaahs.ui.xComponent
import baaahs.window
import kotlinx.html.org.w3c.dom.events.Event
import kotlinx.js.jso
import materialui.icon
import mui.material.*
import org.w3c.dom.Element
import react.Props
import react.RBuilder
import react.RHandler
import react.dom.div
import react.dom.html.TdAlign
import react.dom.onClick
import react.useContext

private val DevModeToolbarMenuView = xComponent<DevModeToolbarMenuProps>("DevModeToolbarMenu") { props ->
val appContext = useContext(appContext)
val styles = appContext.allStyles.appUi

var menuAnchor by state<Element?> { null }
val showMenu by mouseEventHandler { event -> menuAnchor = event.target as Element? }
val hideMenu = callback { _: Event?, _: String? -> menuAnchor = null }

var showToolchainStats by state { false }
val handleToggleShowToolchainStats by handler { showToolchainStats = !showToolchainStats; menuAnchor = null }

onMount(showToolchainStats) {
if (showToolchainStats) {
val stats = (appContext.webClient.toolchain as RootToolchain).stats
var lastStats = emptyList<Int>()
val callback = window.setInterval({
val curStats = stats.all.map { it.calls }
if (curStats != lastStats) {
lastStats = curStats
forceRender()
}
}, timeout = 50)

withCleanup {
window.clearInterval(callback)
}
}
}

div(+styles.appToolbarDevMenuIcon) {
attrs.onClick = showMenu
icon(CommonIcons.Settings)
}

if (menuAnchor != null) {
Menu {
attrs.anchorEl = menuAnchor.asDynamic()
attrs.anchorOrigin = jso {
horizontal = "left"
vertical = "bottom"
}
attrs.open = menuAnchor != null
attrs.onClose = hideMenu

MenuItem {
attrs.onClick = handleToggleShowToolchainStats.withMouseEvent()
Checkbox { attrs.checked = showToolchainStats }
ListItemText { +if (showToolchainStats) "Hide Toolchain Stats" else "Show Toolchain Stats" }
}
}
}

if (showToolchainStats) {
palette {
attrs.title = "Toolchain Stats"
attrs.initialWidth = window.innerWidth / 4
attrs.initialHeight = window.innerHeight * 2 / 3
attrs.onClose = handleToggleShowToolchainStats

val stats = (appContext.webClient.toolchain as RootToolchain).stats
Table {
TableHead {
TableCell { +"Statistic" }
TableCell { +"Calls" }
TableCell { +"Average" }
TableCell { +"Total" }
}
TableBody {
stats.all.forEach { stat ->
TableRow {
TableCell { +stat.name }
TableCell {
attrs.align = TdAlign.right
+stat.calls.toString()
}
TableCell {
attrs.align = TdAlign.right
+(stat.averageTimeMs?.let { "${it}ms" } ?: "-")
}
TableCell {
attrs.align = TdAlign.right
+"${stat.elapsedTimeMs}ms"
}
}
}
}
}
}
}
}

external interface DevModeToolbarMenuProps : Props {
}

fun RBuilder.devModeToolbarMenu(handler: RHandler<DevModeToolbarMenuProps>) =
child(DevModeToolbarMenuView, handler = handler)
48 changes: 36 additions & 12 deletions src/jsMain/kotlin/baaahs/app/ui/settings/MainSettingsPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package baaahs.app.ui.settings
import baaahs.app.settings.UiSettings
import baaahs.app.ui.appContext
import baaahs.app.ui.dialog.DialogPanel
import baaahs.ui.*
import baaahs.ui.View
import baaahs.ui.renderWrapper
import baaahs.ui.typographyH6
import baaahs.ui.xComponent
import mui.material.*
import react.*

Expand All @@ -24,14 +27,17 @@ private val MainSettingsPanelView = xComponent<MainSettingsPanelProps>("MainSett
val appContext = useContext(appContext)
val uiSettings = appContext.uiSettings

val handleDarkModeChange by handler {
props.changeUiSettings { it.copy(darkMode = !it.darkMode) }
val handleDarkModeChange by switchEventHandler(uiSettings) { _, checked ->
props.changeUiSettings { it.copy(darkMode = checked) }
}
val handleRenderButtonPreviewsChange by handler(uiSettings) {
props.changeUiSettings { it.copy(renderButtonPreviews = !it.renderButtonPreviews) }
val handleRenderButtonPreviewsChange by switchEventHandler(uiSettings) { _, checked ->
props.changeUiSettings { it.copy(renderButtonPreviews = checked) }
}
val handleUseSharedContextsChange by handler(uiSettings) {
props.changeUiSettings { it.copy(useSharedContexts = !it.useSharedContexts) }
val handleUseSharedContextsChange by switchEventHandler(uiSettings) { _, checked ->
props.changeUiSettings { it.copy(useSharedContexts = checked) }
}
val handleDeveloperModeChange by switchEventHandler(uiSettings) { _, checked ->
props.changeUiSettings { it.copy(developerMode = checked) }
}


Expand All @@ -41,7 +47,7 @@ private val MainSettingsPanelView = xComponent<MainSettingsPanelProps>("MainSett
attrs.control = buildElement {
Switch {
attrs.checked = uiSettings.darkMode
attrs.onChange = handleDarkModeChange.withTChangeEvent()
attrs.onChange = handleDarkModeChange
}
}
attrs.label = buildElement { typographyH6 { +"Dark Mode" } }
Expand All @@ -57,7 +63,7 @@ private val MainSettingsPanelView = xComponent<MainSettingsPanelProps>("MainSett
attrs.control = buildElement {
Switch {
attrs.checked = uiSettings.renderButtonPreviews
attrs.onChange = handleRenderButtonPreviewsChange.withTChangeEvent()
attrs.onChange = handleRenderButtonPreviewsChange
}
}
attrs.label = buildElement { typographyH6 { +"Render Button Previews" } }
Expand All @@ -72,11 +78,29 @@ private val MainSettingsPanelView = xComponent<MainSettingsPanelProps>("MainSett
FormControlLabel {
attrs.control = buildElement {
Switch {
attrs.checked = uiSettings.useSharedContexts
attrs.onChange = handleUseSharedContextsChange.withTChangeEvent()
attrs.checked = uiSettings.developerMode
attrs.onChange = handleDeveloperModeChange
}
}
attrs.label = buildElement { typographyH6 { +"Developer Mode" } }
}
}
}

if (uiSettings.developerMode) {
Divider {}

List {
ListItem {
FormControlLabel {
attrs.control = buildElement {
Switch {
attrs.checked = uiSettings.useSharedContexts
attrs.onChange = handleUseSharedContextsChange
}
}
attrs.label = buildElement { typographyH6 { +"Use Shared Contexts" } }
}
attrs.label = buildElement { typographyH6 { +"Use Shared Contexts" } }
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/jsMain/kotlin/baaahs/mapper/MapperAppView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLImageElement
import org.w3c.dom.events.KeyboardEvent
import react.*
import react.dom.*
import react.dom.canvas
import react.dom.div
import react.dom.html.InputType
import react.dom.i
import react.dom.img
import styled.inlineStyles

val MapperAppView = xComponent<MapperAppViewProps>("baaahs.mapper.MapperAppView") { props ->
Expand Down Expand Up @@ -110,11 +113,10 @@ val MapperAppView = xComponent<MapperAppViewProps>("baaahs.mapper.MapperAppView"
attrs.tabIndex = "-1" // So we can receive key events.

palette {
attrs.title = "Mapping Tools"
attrs.initialWidth = 240
attrs.initialHeight = 500

header { +"Mapping Tools" }

div(+styles.controls) {
FormControlLabel {
attrs.control = buildElement {
Expand Down
6 changes: 6 additions & 0 deletions src/jsMain/kotlin/baaahs/ui/components/PaletteView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import react.PropsWithChildren
import react.RBuilder
import react.RHandler
import react.dom.div
import react.dom.header
import react.dom.onClick
import react.useContext
import styled.inlineStyles
Expand Down Expand Up @@ -86,6 +87,10 @@ private val PaletteView = xComponent<PaletteProps>("Palette") { props ->
attrs.classes = jso { root = -styles.paper }
attrs.elevation = 3

props.title?.let {
header { +it }
}

props.children()
}
}
Expand All @@ -103,6 +108,7 @@ private fun getUiComponentStyles(): UiComponentStyles {
}

external interface PaletteProps : PropsWithChildren {
var title: String?
var initialWidth: Int?
var initialHeight: Int?
var disablePortal: Boolean?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package baaahs.ui.diagnostics
import baaahs.app.ui.appContext
import baaahs.dmx.DmxUniverseListener
import baaahs.ui.components.palette
import baaahs.ui.typographyH6
import baaahs.ui.withMouseEvent
import baaahs.ui.xComponent
import baaahs.util.globalLaunch
Expand Down Expand Up @@ -32,12 +31,11 @@ val DmxDiagnosticsView = xComponent<DmxDiagnosticsProps>("DmxDiagnostics") { pro
}

palette {
attrs.title = "Dmx Diagnostics"
attrs.initialWidth = window.innerWidth / 3
attrs.initialHeight = window.innerHeight * 2 / 3
attrs.onClose = props.onClose

typographyH6 { +"Dmx Diagnostics" }

button {
attrs.onClick = handleUpdateChannels.withMouseEvent()
+"Update"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import baaahs.fixtures.RenderPlan
import baaahs.gl.glsl.GlslProgramImpl
import baaahs.ui.asTextNode
import baaahs.ui.components.palette
import baaahs.ui.typographyH6
import baaahs.ui.xComponent
import baaahs.util.Monitor
import baaahs.window
Expand Down Expand Up @@ -37,12 +36,11 @@ val PatchDiagnosticsView = xComponent<PatchDiagnosticsProps>("PatchDiagnostics")
}

palette {
attrs.title = "Patch Diagnostics"
attrs.initialWidth = window.innerWidth / 3
attrs.initialHeight = window.innerHeight * 2 / 3
attrs.onClose = props.onClose

typographyH6 { +"Patch Diagnostics" }

if (renderPlans == null) {
i { +"No patch!" }
} else {
Expand Down

0 comments on commit 6cff0b5

Please sign in to comment.