3.  Configuration Pages and Wizards

Configuration pages are somewhat more complex than any of the other types of hookable object. This is reflected in the complexity of the items and callbacks involved.

Essentially, the EConfig object is used in combination to both instrument existing windows and building new content. Each configuration window comprises of several basic elements with some minor variations allowed. It consists of a number of pages in a specific order, each containing a number of titled sections in a specific order, each containing a number of items. The variations are that the top-level widget may be a GtkNotebook or a GnomeDruid; and each section may instrument a GtkBox, or a GtkTable. The definition of the available hooks will define what form they take.

The EConfig manager uses the description of all the items supplied to it to build the complete window. It can also drive various aspects of the UI, such as navigating through a druid or handling instant-apply vs. modify-and-save dialogues.

Figure 3.3. Event and Data Flow in EMConfig

The flow of information and control signals in the
		configuration management object.

3.1. Defining a configuration page hook

Not sure if this fits here as such. Probably temporary placeholder.

	    
<hook class="com.ximian.evolution.mail.config:1.0">
 <group
  id="window id"
  target="targettype"
  check="function spec"?
  commit="function spec"?
  abort="function spec"?>
  <item
   type="book | druid | page | page_start | page_finish | section | section_table | item"
   path="/absolute/path"
   label="name" | factory="function  spec"
  /> *
 </menu> *
</hook>

3.1.1. Group Element Properties

id
The name of the configuration window to which this hook applies.
target
The type of target this configuration window applies too. This will normally be tied directly to the specific configuration window itself.
check

A callback which will be invoked to validate the configuration or a specific page of the configuration. It will be invoked with a EConfigHookPageCheckData structure, and is expected to return a non-NULL value if the page validates.

The callback will be expected to handle all pageid's present in the configuration window, and should return TRUE for pages it does not recognise. If pageid="" (an empty string), then the check function should validate all settings. See also ???.

commit
A callback which will be invoked to commit the configuration data, if the configuration page isn't an instant-apply one. This callback can write any configuration changes to permanent storage. It is not used for instant-apply windows.
abort
A callback which will be invoked to abort the configuration process. This callback is called when the Cancel button is pressed on stateful configuration windows.

3.1.2. Item Element Properties

type
The menu item type. The type maps directly to the corresponding EConfigItem types. Only one of book and druid may be supplied for the entire configuration page, and this will usually already be defined by the application.
path
The path to the configuration item in question. This is a simple string that when sorted using an ASCII sort will place the items in the right order. That is, sections before items before pages before the root object.
label
The textual label of this item. This may only be supplied for the section and page types. For sections it will be the section frame text. For pages this will be the druid page title or the notebook tab text. If a factoryis supplied then this value is not used. This will be translated based on the plugin translation domain.
factory
If supplied, the factory method used to create the GtkWidget elements for this configuration item. Factories may be supplied for any of the item types. If no label is set then the factory must be set.

3.2. Generating Configuration Pages

Configuration items essentially spam 3 dimensions, but are merged in a similar fashion to the way Popup items are merged. The main difference is that there are no target qualifiers used to select which items are shown, it is up to the item factory to either create or not create the item as it sees fit. The EConfig manager takes care of the rest, including removing un-used sections or pages.

All items for a given configuration screen are converted into a list and sorted based on the path. The configuration builder then goes through each item, creating container widgets or calling factories as required. If a given page or section is empty, then it is removed automatically. This process isn't only a one-off process. For certain complex configuration screens, items or even pages and sections need to be dynamic based on a previous setting. EConfig supports this mode of operation too, in which case it re-builds the configuration screen the same way, and automatically destroys the old widgets [5] and even re-orders pages and sections where appropriate to make the user-interface consistent.

The following few examples some of the flexibility of the EConfig system.

Figure 3.4. The application defined, unaltered configuration page.

Shows the original HTML Mail settings page.

First we have the original configuration window. This is defined by the application, the application uses EConfig to build this window, and in the process EConfig instruments the sections that the application defines. This allows plugins to add new pages/sections/items anywhere on the page - to a granularity as defined by the application. For example the application may at minimum merely define the top-level notebook or druid object and a number of pages. When the pages are created the application could add as much content as it wants, which would still allow plugins to extend the user interface, but only by adding options to the end of each page. At the other end of the scale the application could enumerate every single item (i.e. row) in every section on every page, allowing plugins to put new items anywhere in the display.

Figure 3.5. A plugin adding a new section to an existing page.

Shows the HTML Mail settings page with a new section
		  and item added by a plugin.

In this case the plugin has merely added a new section on the bottom of the HTML Mail settings page. When the factory is called the plugin has a parent GtkTable (in this case, it could be a VBox) and borderless frame already defined, and it just has to instantiate its own control widgets, add them to the table, and return one of the widgets. The returned widget is used later if the window needs to be reconfigured, although this particular configuration page is static so it isn't needed.

Figure 3.6. A plugin inserting a new page for its settings.

Shows the plugin adding a new page for its setting as
		  an alternative.

And finally we have exactly the same plugin, which has exactly the same code. But a small change to the plugin definition allows the plugin to add an arbitrary new page (in an arbitrary position) into the whole window. If this was a druid, then new druid pages can also be inserted at arbitrary locations, and page navigation (in a strictly linear manner) is automatically controlled by EConfig as per Figure 3.3, “Event and Data Flow in EMConfig”.

In practice, EConfig provides more than it takes the application to use - generally little or no extra application code is required to use it. It also [6] enforces and simplifies HIG compliance. And as a side-benefit to the application it transparently provides extension hooks for external code to provide a seamlessly integrated user experience.



[5] In most cases, in some cases additional manual processing is required in the factory callback.

[6] Or it will - the code needs some tweaking.