Listening to Model Changes
Widgets and other bits of code can listen and receive function invocations whenever a model changes. This is the means by which a widget knows when and what to draw, and by the same token, it's how models can communicate changes to your application.
The IOU application uses a single listener, to listen on the model for the list to determine when a list item is selected. It does this using a focus listener, which receives events whenever the list's model receives changes with regard to which item has focus. It's important to realize that the focus listener isn't listening to the model of the list, but the model of the view for the list. There's a subtle but important difference: the list model contains the items of the list; the list's view model is the model for the view, and keeps track of things such as who has focus. The focus listener has been set using the code at the end of Listing 1, indicating that when the list model changes, the system will invoke the listener function Menu_ListenerFocus (Listing 3).
Unlike event handlers, you’re not responsible for chaining listenersthe BREW UI Toolkit will do that for you. Thus, Menu_ListenerFocus need only handle the menu selection action (an EVT_MDL_FOCUS_SELECT event) and populate the text models for the input form that needs to be shown before popping the menu form and pushing the appropriate edit form to the top of the form stack.
Managing the Models
When initializing a screen, you must be sure to put the appropriate contents in each widget's models. For some widgets, like labels, this is easy. A quick IWIDGET_SetText call may be all that's necessary. For other widgets, you may need to harvest data from a data store, such as a BREW database, file, or another model. Listing 3 does this, using the ITextModel instances associated with each of the input lines for a specific form. The ITextModel is a subclass of IModel, and provides information about the contents, current selection, and cursor position in a text input line. This information is provided by the TextInfo structure, which you can obtain from any text model by calling its ITEXTMODEL_GetTextInfo method. You can use this method to obtain a model's text info, select all of the text currently in the model by setting a selection range from zero to the count of characters, and then replacing the current text with the new text. This replacement metaphor is the standard one when working with text models; using replacement you can insert, delete, or append text to the contents of a text model.
SaveIOUForm gets the text in each of the two models by obtaining the model's text info and copying it from the TextInfo's pwText parameter. It then builds the string that will appear in the menu with the entered person and debt. Once the menu string is constructed, it's either added to the end of the menu (if the form was brought up for a save command) or used to replace the old value in the menu.
Of course, using the menu model as the data store is only a stopgap while the application is running. On application launch, initialize the model with the contents of a file, and on application exit, commit the contents to the same file (Listing 6). This code represents the IOUs as an array of fixed-length fields in wide string format, making them almost a carbon copy of the actual menu model’s contents. It's crude, but it works. A more robust application probably deserves a database, and storage of the debt amounts as numbers so that cumulative debts can be managed as actual accounts, rather than as simple textual notes.
You've learned how widgets and forms replace the existing BREW IControl metaphor for user interface development. You've learned the basics of constructing and configuring widgets, attaching them to containers, and managing application flow through forms and event handlers. Now, it's your turn: contact Qualcomm to get a pre-release of the BREW UI Toolkit, and start building your next generation application!