One of the things that’s been bugging me about Woopsi is the naming system I used for things-that-happen to gadgets. Not events, strictly; just stuff that happens. A stylus click is a thing-that-happens, as is a vertical blank, as is a keypress and a stylus release.
All of these things-that-happen were dealt with in the gadget classes by “handleX()” functions, where X is the name of the thing-that-happened. In the case of a click, the function was “handleClick(s16 x, s16 y)”.
This naming system did kind of make sense, in that the gadget was being passed an event of some sort (a click), and had to handle it appropriately, either by passing it on to a child or processing it itself. Each “handleX()” function then fired the EventHandler’s “handleX()” function.
The problem with it was that it began to fall apart. The naming scheme just seemed clumsy - why would a function that claimed to be an event handler then send that event to another event handler? It had structural problems, too, in that some gadgets needed to send their events to other event handlers, and some just needed to process them themselves.
Where it really collapsed was when you needed to work with the gadgets via the API. If you wanted to simulate a click, you’d call the “handleClick()” function. There is no click to handle, though. The whole structure has been unsettling me for the past couple of weeks, so I decided I had to improve it.
To that end, I have split all of the “handleX()” functions up into two functions. The first is the “x()” function - “click()”, “release()”, “keyPress()”, etc. If I want to click a button, I call “button->click(x, y)”. It contains all of the code needed to perform the gadget’s click/release/keypress operations. Much more sensible. The second function sends the event to the EventHandler, and follows the naming scheme “raiseXEvent()” - “raiseClickEvent()”, “raiseReleaseEvent()”, “raiseKeyPressEvent()”, etc. The “raiseXEvent()” methods cannot be overridden, whilst the “x()” methods can - this was another problem in the initial design.
This has made the code longer, but considerably tidier. It’s also made the API a hell of a lot easier to follow. Instead of the naming system suggesting that gadgets are handling something that might or not be a real or simulated event, developers can now do things to the gadgets - click them, release them, blur them, etc.
Tied in with this, I’ve made a few other improvements. Clicking a gadget now automatically notifies the gadget’s parent that it has become the clicked gadget; this is important, since we’re now assuming that people can call “gadget->click()” as well as wait for the stylus to hit the screen. The notification automatically bubbles up the hierarchy.
The EventHandler base class no longer defines its event handler methods as pure virtual; they’re just plain old virtual now instead. As the number of events that Woopsi can handle increases, it was getting more and more annoying to have to explicitly override all of the base methods even if I wasn’t going to use all of the events.
I’ve split the TextViewer class into two. One of the classes retains the user interface side of the TextViewer; the other, a “Text” class, now contains all of the text data manipulation code. It handles text wrapping, stores the char array pointer, and can produce useful information about the text - number of lines, maximum line length in pixels, total height in pixels, etc. It means that any text-based gadget (such as the console gadget, when I get around to it) can have the same text manipulation features as the TextViewer.
Gadgets can now be enabled and disabled. By default, they don’t change their appearance, but disabled gadgets stop receiving the majority of events (things like lid close and blur still get sent through) and can’t be interacted with either via the API or the GUI until they’re re-enabled.
Couple of new gadget functions - “resize()” and “moveTo()”. I’ve written a custom resize function for windows (currently only accessible through the API rather than the GUI), so that’s one of the features knocked off the version 2 list. The “moveTo()” function has allowed me to tidy up the window drag code a bit. I’ve created a new event for each of the functions; I’ve also added a “value change” event that gets triggered when a gadget’s value changes.
Lastly, I’ve started looking into requesters. I initially made a Requester base class and inherited from that - the plan was to include an instance of the Window class, populate it with gadgets, and implement the EventHandler class to tie it all together. This turned out to be a mistake, though, as the Requester class couldn’t be added to the screen’s gadget list (obviously enough). I’ve gone down the route of inheriting from the Window class instead, and having the class’ constructor pre-populate it with gadgets.
The requesters should work well. I’m currently working on an “Alert” requester, which consists of a textbox and an “OK” button. I’m trying to get the requester to resize itself based on the size of the text in the textbox - this was the real reason for stripping the text manipulation out of the TextWriter and the addition of the “resize()” method. One unexpected benefit of having requesters that resize based on text size is that they will automatically adjust for different sized fonts.