ActionsAndCommands
This interface is NOT USED, it is only here for Documentation.
Glok includes 4 utility classes help separate how : Action
, Actions
, Command
and Commands
.
Actions
let you define the text, graphics, tooltip and shortcuts for every button, menu and menu item. Commands
lets you add the behaviour for a subset of those Actions
, and then use it to build the controls.
So instead of :
toolBar {
button( "Save", theSaveGraphic ) { onAction{ saveTheFile() } }
button( "Load", theLoadGraphic ) { onAction{ loadAFile() } } }
subMenu {
menuItem( "Save", theSaveGraphic ) { onAction{ saveTheFile() } }
menuItem( "Load", theLoadGraphic ) { onAction{ loadAFile() } } }
You'd have something like :
val commands = Commands().apply { with( myActions ) { FILE_SAVE { saveTheFile() } FILE_LOAD { loadAFile() } } }
toolBar { with(commands) { with(myActions) {
button(FILE_SAVE)
button(FILE_LOAD) } } }
menuBar { with(commands) { with(myActions) {
menuItem(FILE_SAVE)
menuItem(FILE_LOAD) } } }
Key points :
We have split how buttons behave from how they appear. The GUI building code has no logic code in it.
There is no duplication.
saveTheFile()
is only called from one place.I didn't show the extra work needed to handle keyboard shortcuts. Using the first approach, is a PITA, with yet more duplication of calls to
saveTheFile()
etc. In the seconds approach, it's as simple as :commands.attachTo( myNode )
. The shortcuts will work whenever the input focus is withinmyNode
's subtree.Tooltips and menu items will automatically include the keyboard shortcuts. If the user customises these shortcuts, the tooltips and menu items will reflect those changes.
Notes
with(myActions)
is only there so that you don't have to use the repetitive :myActions.FILE_SAVE
,myActions.FILE_LOAD
etc.button
andmenuItem
are methods ofCommands
, which take anAction
as their argument.When writing an I18N application, there is provision for changing language on the fly. Each
Action
has a singletextProperty
, that buttons' and menu items' textProperty is bound to. So to change languages, you need to update textProperty for eachAction
. I suggest you bind it like so :action.textProperty.bindTo( translation(languageProperty, text) )
Wheretranslation
is aStringUnaryFunction
using resource bundles.To allow users to customise keyboard shortcuts, you'll need to write that GUI yourself. There is no one size fits all solution for this, so I don't intend providing one.