Basic Concepts - Events
GUI programming is different to videogame programming. In videogames, everything is driven by the vertical blank. Each time the screen redraws the code needs to do something. By contrast, GUI programming is event-driven. If the user isn't manipulating the screen - isn't dragging windows or clicking buttons - the GUI doesn't need to do anything.
Events turn the control of a GUI-based application upside-down. In games, we need to check all of our sprites to see if they have collided with something, and if so, we need to run a piece of code that processes the collision. The onus is on the program to check if something has happened every time the screen refreshes. In GUI-based applications, it works the other way around. We don't need to check if a button has been clicked or a window has been dragged - the gadgets automatically *tell* us when those events have happened. This is called an "event system".
Woopsi's Events
Woopsi implements a fairly simple event system. Each gadget can contain an instance of an "EventHandler" class, which defines a specific set of functions that are executed when an event occurs. The appropriate function is executed for each different type of event.
Events currently implemented in Woopsi are:
- Click - fired when a gadget is pressed by the stylus
- Double-click - fired when a gadget is tapped twice by the stylus within a short period of time
- Shift-click - fired when a gadget is pressed by the stylus whilst the user holds down one or both of the shoulder buttons
- Drag - fired when a gadget is dragged by the stylus
- Release - fired when the stylus is removed from the touch screen
- VBL - fired when a vertical blank occurs
- Key press - fired when one of the DS' buttons is pressed
- Key release - fired when one of the DS' buttons is released
- Lid opened - fired when the DS is opened up
- Lid closed - fired when the DS is closed
- Focus - fired when a gadget gains focus
- Blur - fired when a gadget loses focus
- Hide - fired when a gadget is hidden
- Show - fired when a gadget is shown
- Shelve - fired when a gadget is shelved
- Unshelve - fired when a gadget is unshelved
- Close - fired when a gadget is closed
- Resize - fired when a gadget is resized
- Move - fired when a gadget is moved
- Value changed - fired when a gadget's value changes
- Enable - fired when a gadget is enabled
- Disable - fired when a gadget is disabled
- Context menu selection - fired when a context menu belonging to a gadget has a new selection made
- Scroll - fired when a scrolling gadget scrolls
Not every gadget will fire every event. The "value changed" event only makes sense for textboxes, radio buttons, and so on. Windows do not have their values changed, since they do not store an internal value to change.
User Actions
User actions are detected by the main Woopsi class and distributed through the gadget hierarchy to any relevant gadgets. They are distributed differently depending on the nature of the action. Clicks, for example, are routed to the gadget that was clicked; the clicked gadget then raises a "clicked" event that can be processed by an EventHandler. Conversely, lid opening or closing is sent to all gadgets so that they can perform any halt operations.
User actions are distributed through the Woopsi hierarchy like this:
- Stylus clicks are sent to the gadget that was clicked
- Stylus releases are sent only to the gadget that was released
- Vertical blanks are sent to gadgets that have been set up to listen for them
- Key presses are sent to the gadget that currently has focus and its parents
- Key releases are sent to all gadgets that currently has focus and its parents
- Lid opened events are sent to all gadgets
- Lid closed events are sent to all gadgets