Capturing User Preferences
Widget engines save you from implementing capabilities (like user-preference management) commonly required for applications. The engine includes a framework that automatically manages the storage/retrieval of a user's preferences for all of the user's widgets, and provides a simple mechanism that lets widget developers customize the preferences available to their widgets, and define the effect of changing each preference. All customized and default preferences are accessible via the same preferences dialog of the widget displayed when you right-click the widget and select "Widget Preferences..."
The engine also provides each widget with a default set of preferences that affect the widget window's behavior. These preferences let you adjust the level of the window (always on top), opacity, and whether the window position is locked.
Customizing the preferences available for widgets requires two additions to the widget specification. You must define one or more preference elements as a child of the widget, then add JavaScript that applies its values to the widget. The specification of preference elements causes new fields to appear in the widget preference dialog. Each preference can be assigned a name, type, and default value among optional attributes. The following lets users modify the font size of the widget:
<preference name="fontSizePref" title="Size" type="slider" defaultValue="18" ticks="10" minLength="5" maxLength="35" description="Select the text size"/>
A key attribute to the preference element is the type attribute, which establishes the type of preference being captured (color, font, or file). The widget preference dialog uses the specified type when deciding what type of control to use to capture the preference. For example, if the preference captured is a color, the preference widget brings up a color palette that users can choose from, rather than make users type in a six-digit hexadecimal number for the color.
As you start adding preferences to widgets, you may need to separate them into different panels on the preference dialog. You do this by adding a preferenceGroup element as a child of the widget, and including a reference to the preferenceGroup element in the preference element with the group attribute. Although useful, it's not always necessary to define a preference group for widget preferences. If you decide not to define your preferences within a specific group, they're automatically placed in a group named "General."
Returning to Listing Two, we've defined three preferences in a single group for the Clip Notes widget on lines 37-43. These let users modify the background color, and the font and color of the text as in Figure 3.
In Listing Two, the external function updateFromPreferences is called when the widget is loaded (line 29) and the preference is changed (line 34). This function is defined in ClipNotes.js (see Listing Three). The updateFromPreferences function updates the look of the widget based on values provided by users. If no value is provided, the default is automatically used. To do this, the function accesses a global preferences object available to the widget. The preferences object has a separate property for each preference object defined for the widget. Each preference object includes properties that describe the preference, such as the value and defaultValue, among others. The Widget Engine manages the preferences objects, so they always reflect the user's most recent selections, and are even automatically saved and reloaded when the machine is restarted or the widget is reloaded.