Broadened the scope of menus to include full widgets as items. Some menus benefit greatly from having extensible components, and previous attempts to extend items with input callbacks have gone nowhere.
The context now tracks two thimbles (tokens that represent keyboard focus). thimble1 is the original; thimble2 is for ephemeral controls, such as pop-up menus. thimble2 takes precedence over thimble1. Previously, the one thimble would be passed back and forth between concrete widgets and pop-ups, and the concrete widget would be “banked” in the root widget, to be restored once the pop-up was dismissed. This was a continual source of problems, as transactions could fail to restore the banked thimble, or assign it to a different widget. I made the change when I realized that “banked” widgets don’t necessarily know that their loss of keyboard focus was only a temporary interruption.
Changed the loops to detect hovered and pressed widgets. The widget callbacks ui_evaluateHover() and ui_evaluatePress() are more powerful now, having the ability to signal a positive result even if the mouse cursor is outside of the widget’s bounding rectangle.
Rewrote the event dispatch methods.
Previously, the vast majority of events bubbled up from the target widget to the root. A trickle-down method existed, but I don’t think I understood the purpose of trickling at the time, as it behaved more like a downward broadcast to all descendant widgets. (In any case, this method was not in use anywhere.)
Currently, most events trickle down from the root to the target, and then they bubble back up from the target to the root. Doing so allows finer control of how events are processed. Since trickling events always visit the root widget first, the latter can perform additional bookkeeping, and even stop the event from propagating further. Two examples that are better handled on the trip down: dismissing pop-up menus when the user has clicked on any widget that doesn’t belong to the menu chain; handling key-hooks, such that priority is given to hooks belonging to the most senior widget in the hierarchy.
Turned some source code comments into documentation. They are written in an ad hoc XML format until I figure out what I’m doing.
Rewrote modal frame code (one frame blocks interaction with another frame until it is dismissed) to take advantage of changes to event propagation.
Refactored skinning. The theme system now keeps a pristine copy of each skin, and exposes a processed (scaled, etc.) version to widgets.
Implemented a settings system for widgets. When refreshing a setting, a widget will check its own settings table, then its skin table, and finally a default_settings table in its widget def. The settings values are copied to the widget directly, so that it doesn’t have to check in multiple places for these values in normal widget code. This allows the skin to override the defaults, and the library user to override the skin, without a loss of information.
Added a general settings table to the context, and started consolidating typical options and measurements there (ie how far to scroll when pressing the arrow keys).
Rewrote the pageup and pagedown selection code in menus to land on the next item that is one “page” away, rather than just jumping over a set number of items.
Stopped text input carets from rendering when the application doesn’t have window focus.
Widgets
I have prototypes for the PropertiesBox and Dial widgets.
Window frames:
Merged the header bar widget with the frame widget.
Frame header size was controlled by assigning a skin; it’s now a proper widget setting. Also added a big header mode, intended for the main menus of utility applications.
Frames now handle resizing when the user clicks on their outer perimeters, rather than using a child sensor widget for this purpose.
Pop-up menus:
Added the option to swallow the first mouse press event outside of the menu (to prevent accidental clicks when dismissing it).
Tabular menus:
Refactored and cleaned up numerous rendering errors. It’s still frustrating to work with, and needs further changes.
WIMP Demo
Widget tree viewer: added the option to exclude itself from the tree that is presented to the user.