Desktop
Coming from Form Controls, let's look at the handful of things that only make sense once your app is actually running as a native Desktop window.
Multi-window apps
Back on Displays, you saw that a multi-window app gives each window its own Display. This is the API that actually manages those windows: WindowGroup. Inject it to get going — it hands you the app's main window, plus everything you need to create more.
package display
import io.nacular.doodle.application.Application
import io.nacular.doodle.core.WindowGroup
import io.nacular.doodle.core.view
import io.nacular.doodle.geometry.Size
import io.nacular.doodle.layout.constraints.constrain
import io.nacular.doodle.layout.constraints.fill
//sampleStart
class MyCoolApp(windows: WindowGroup): Application {
init {
// main window's display, same as if Display were injected
windows.main.apply {
title = "Main Window"
// manipulate main window's display
display += view {}
}
// create a new window
windows {
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() {}
}
//sampleEnd
No need to inject Display separately if you're already injecting WindowGroup — the injected Display is exactly equivalent to WindowGroup.main.display.
Native window menus
Apps can give a window a genuine native menu — the kind that lives in the OS's own window chrome, not drawn by Doodle itself. The API will look familiar: it's built the same way as the in-app Menu control you've already met, just installed onto a Window instead of the Display. These menus are just as interactive as their in-app counterparts too — they fire the same kind of events when the user interacts with them.
package display
import io.nacular.doodle.controls.popupmenu.MenuBehavior.ItemInfo
import io.nacular.doodle.core.Icon
import io.nacular.doodle.core.Window
fun example(window: Window, icon1: Icon<ItemInfo>, icon2: Icon<ItemInfo>) {
//sampleStart
window.menuBar {
menu("Menu 1") {
action("Do action 2", icon1) { /*..*/ }
menu("Sub menu") {
action("Do action sub", icon = icon2) { /*..*/ }
separator()
prompt("Some Prompt sub") { /*..*/ }
}
separator()
prompt("Some Prompt") { /*..*/ }
}
menu("Menu 2") {
// ...
}
}
//sampleEnd
}
Native context menus
Context/popup menus work the same way — genuinely native, and built with an API that mirrors the menu bar above almost exactly:
package display
import io.nacular.doodle.controls.popupmenu.MenuBehavior.ItemInfo
import io.nacular.doodle.core.Icon
import io.nacular.doodle.core.Window
import io.nacular.doodle.geometry.Point
fun contextMenu(window: Window, icon1: Icon<ItemInfo>, icon2: Icon<ItemInfo>) {
//sampleStart
window.popupMenu(at = Point()) {
action("Do action 2", icon1) { /*..*/ }
menu("Sub menu") {
action("Do action sub", icon = icon2) { /*..*/ }
separator()
prompt("Some Prompt sub") { /*..*/ }
}
separator()
prompt("Some Prompt") { /*..*/ }
}
//sampleEnd
}
Recap
WindowGroupmanages multiple windows — inject it instead ofDisplayonce your app needs more than one, and you getDisplayaccess for free throughWindowGroup.main.display.- Native window menus and native context menus both use an API that closely mirrors the in-app
Menucontrol, just installed on aWindowrather than theDisplay.
Next: on to Web for what's unique to running in the browser.