Nick
01/17/2024, 8:49 PMwasmJS build target. This means apps can also target WASM for the browser. The APIs/features for this new target are identical as those for the js target; which means code can be shared between apps targeting both. The only difference is that the application launchers need to be called from separate source sets (i.e. jsMain vs wasmJsMain).
Multi-window Support (Desktop)
Apps for Desktop can now create/manage multiple windows using a new WindowGroup instance. This instance can be injected into an app just like the Display. It then provides APIs for getting the main window and creating new ones. Single window apps continue to work as they did before. That is, an app that injects the Display will receive the main window display and can manipulate it as before. But apps that want to manage their window(s) will need to inject this new type.
class MyCoolApp(windows: WindowGroup /*, mainWindowDisplay: Display*/): Application {
init {
// main window's display, same as if injected
windows.main.apply {
title = "Main Window"
// manipulate main window's display
display += view {}
}
// create a new window
windows().apply {
title = "A New Window!"
size = Size(500)
enabled = false
resizable = false
triesToAlwaysBeOnTop = true
// manipulate the new window's display
display += view {}
display.layout = constrain(display.first(), fill)
closed += {
// handle window close
}
}
}
override fun shutdown() {}
}
Native Window Menus (Desktop)
Apps can now set up native menus for their windows. This looks a lot like working with the existing menu APIs, but it results in changes to the OS window decoration. These menus are just as interactive as the in-app ones as well, meaning they trigger events when the user interacts with them.
window.menuBar {
menu("Menu 1") {
action("Do action 2", pathIcon) { /*..*/ }
menu("Sub menu") {
action("Do action sub", icon = simpleIcon) { /*..*/ }
separator()
prompt("Some Prompt sub") { /*..*/ }
}
separator()
prompt("Some Prompt") { /*..*/ }
}
menu("Menu 2") {
// ...
}
}
Native Window Context Menus (Desktop)
Apps can now set up native context/popup menus for their windows. The API is very similar to native menus.
window.popupMenu(at = somePoint) {
action("Do action 2", pathIcon) { /*..*/ }
menu("Sub menu") {
action("Do action sub", icon = simpleIcon) { /*..*/ }
separator()
prompt("Some Prompt sub") { /*..*/ }
}
separator()
prompt("Some Prompt") { /*..*/ }
}
APIs
• General
◦ PathBuilder now supports moveTo
◦ Resizer can now avoid updating a View's cursor if manageCursor = false is provided to it at construct time.
◦ VerticalList and HorizontalList builders now take optional itemVisualizer.
◦ View.ClipPath.path can now be overridden by subclasses.
◦ SetPool no longer exposes a constructor, or underlying data structure, so it can be controlled.
◦ New PathModule to allow use of PathMetrics. PathMetricsImpl is now internal.
◦ New MenuFactoryModule to allow use of MenuFactory. MenuFactoryImpl is now internal.
◦ New UserPreferencesModule to allow use of UserPreferences. UserPreferencesImpl is now internal.
◦ Deprecations
▪︎ Old <http://io.nacular.doodle.controls.menu|io.nacular.doodle.controls.menu> package removed
▪︎ Label.horizontalAlignment removed
▪︎ TextVisualizer typealias removed
▪︎ Canvas.wrapped methods removed
▪︎ inscribed method removed from Polygon.kt
▪︎ PointerInputService.Listener.changed method removed
▪︎ PointerInputService.Preprocessor.preprocess method removed
• Browser
◦ Remove drag-drop support on IE
◦ Moved all DOM definitions to internal so they don't pollute the app space.
Fixes | Improvements
• General
◦ Issue where Carousel item not properly updated if skip called when there is no transitioner
◦ Issue where work done during View.addedToDisplay could cause unbroken loop.
◦ ModalManager now clears focus when a new modal is shown and returns focus to the previous focus owner when that modal is completed.
◦ Issue in FocusManagerImpl related to transitioning focus to a new View
◦ Issue in RenderManagerImpl where new Views could be rendered during an ongoing render. This would result in concurrent modification errors since the latest Kotlin version adds guards for this in JS InternalMap.
• Browser
◦ Fixed pointer handling of ENTER, which is called on scroll and new Views are added. This means pointer events are now delivered properly in these cases.
◦ Suppress scroll in native TextField behavior when element focused
◦ Issues with canvas clipping and transforms within custom FileSelector behavior
◦ Handle selection attempt for input types that do not support it
◦ Fix issue where native FileSelector would not trigger filesChanged if the same item was selected in subsequent viewings.
◦ Concurrent modification issue in SetPool addressed w/ copy-on-write semantics
◦ No longer having DOM types resolved via instance() in certain Kodein bindings since that results in WASM compiler crashes
◦ Avoiding concurrent modification issue with RenderManagerImpl.pendingBoundsChange
• Desktop
◦ Fixed crash on app shutdown
Build
• Fixed JS Source Maps
• Using TOML for buildSrc Kotlin version
Versions
• Kotlin -> 1.9.22
• Skiko -> 0.7.90
• DateTime -> 0.5.0
• Kodein -> 7.21.1
• Coroutines -> 1.8.0-RC
• Measured -> 0.4.0
• Kover -> 0.7.3
• Mockk -> 1.13.8
• Gradle -> 8.4Luc Girardin
01/17/2024, 9:48 PMayodele
01/18/2024, 6:26 AMNick
01/18/2024, 6:47 AMItemVisualizer. this is because ListBehaviors actually provide something similar for the List via ListBehavior.generator. Lists will actually use this to populate their children. the existence of an itemVisualizer for the List allows the Behavior a chance to wrap the visualizer's output (or use it directly). this makes alignment easier, since you can provide an ItemVisualizer for the List, and have the Behavior wrap it in a View that takes List.cellAlignment into account.