Actions
Actions define the behaviours of Commands, i.e. the code that executed when a button, menu-item etc. is pressed. The Actions can then be used to build the buttons, menu items etc.
For example, we define Commands like so :
object MyApplicationCommands : Commands( myIcons ) {
val FILE_OPEN = define( "file_open", "Open", Key.O.control() )
val FILE_SAVE = define( "file_save", "Save", Key.S.control() )
}
Each Command has a key
(such as file_open
), which is never seen by the end-user. Next is the text that will appear in the menu-item, button etc. We can optionally add a keyboard shortcut and tooltip text.
Notice that Commands do NOT define the behavior. This is where Actions come in.
val action = Actions().apply {
// Attach to a node (often the root node) for keyboard-shortcuts.
// When input focus is elsewhere, the keyword-shortcuts won't apply.
attachTo( aNode )
MyApplicationCommands.FILE_OPEN { println( "Not implemented!" ) }
MyApplicationCommands.FILE_SAVE { println( "Not implemented!" ) }
}
Simple behaviours can be written in-line, but longer behaviours are usually function calls.
Now, we can start building our GUI :
fun myToolBar( actions : Action ) = toolBar {
actions.build {
+ button( MyApplicationCommands.FILE_OPEN )
+ button( MyApplicationCommands.FILE_SAVE )
}
}
fun myMenuBar( action : Actions ) = menuBar {
actions.build {
+ menuItem( MyApplicationCommands.FILE_OPEN )
+ menuItem( MyApplicationCommands.FILE_SAVE )
}
}
Note, it is tiresome to keep including MyApplicationCommands.
, so you could wrap them in a with
block instead.
It is typical for the GUI components (i.e. myToolBar() and myMenuBar()) to be in a separate source files, which is why I declared them as functions, and passed actions
to them.
See DemoActions.kt
in glok-demos subproject for real example code.
Missing from the example code :
Setting the size of icons. See NodeBuilder.iconSizeProperty
Enabling/disabling buttons/menu items. See Action.disable
Some applications have a single instance of Actions, but more complex application may have many (one for each part of the application).
For shortcuts to work, you must attachTo a node. The shortcuts will only work when the input focus is one of that node's descendants (or itself). Therefore, Scene.root is often a good choice.
Functions
Adds an onKeyPressed
event handler to node, which checks the KeyEvent against each action's Command.keyCombination and Command.additionalKeyCombinations.
Build nodes based on these Actions.
Removes the key handler added by attachTo.
Looks for the action matching command, checks that it isn't disabled, and then calls the Action.lambda.