GUI Table Suggestion


Below is a possible table layout to store GUI components. (It is actually a Control Table and may also be considered a form of Data Dictionary.) A similar table could perhaps store window definitions (if enough windows to warrant a table). Some complain about the empty fields for non-relevent items, but I fail to see how this is a bigger problem than the 1-dimensional stretched structure of most codified OOP component definitions. I don't see why the 1-D approach is so popular. Storing GUI components like this also makes the layout less language dependant and easier for 3rd party tools to view and manipulate the screen layouts. (Actually, the Data Dictionary can often be used to directly generate a data entry/edit screen without a separate screen-building step.)

  1. Item Name - Reference name
  2. Window ID - Which window the component belongs to.
  3. Item Type - Code for type of item, such as Button, Grid, Textbox, etc.
  4. Group - (optional) group name if grouped. Alternatively you could have a Parent_ID if you wish to use hierarchies for grouping.
  5. Coordinates - These could be based on pixels or perhaps percentage location on window. The parts are x1, y1, x2, y2.
  6. Relative To - Name of item if coordinates relative to it instead of window, which is the default if blank.
  7. Color Scheme - Color and/or style scheme. May reference another table.
  8. Caption - Title or caption
  9. Content - Value or text contained in item (perhaps only default text if linked to a text file, see RefSource).
  10. Help Text - Text to describe item if help is activated, or perhaps shown on a status bar.
  11. Field Link - Field specification if linked to a persistent table. Example: "Tablex.field2"
  12. Maxlines - Maximum lines. No limit or N/A if blank.
  13. MaxChars - Maximum characters. No limit, dependant on table field, or N/A if blank.
  14. Font -
  15. Status - Active, ReadOnly, or Hidden
  16. TabOrder -
  17. RefSource - If item is a picklist or other type of list or image, this is the source of the list/image (usually a table or file). If both a list and an image can be displayed at the same time (yikes!), then perhaps two separate fields would be better.
  18. Param1 - Item-specific parameter. These could optionally be farmed out to another table.
  19. Value1 - Item-specific value depending on parameter
  20. Param2 - see Param1 above
  21. Value2 - see Value1 above
  22. OnClick - Function name or snippet when clicked. (Perhaps events should have their own table.)
  23. OnMouseOver - Function name or snippet when mouse is over item
  24. OnDoubleClk - Function name or snippet when double-clicked
  25. Entity - Database entity that widget is bound or linked to
  26. Field - Database field name that a widget is bound or linked to
  27. Depth - Overlap order ranking. (Sometimes called "Z value".)

Note that FoxPro 2.6 actually used tables to store GUI items. Although the FoxPro approach may not have been the ultimate showpiece for the concept, it is an example of a real product that used the idea. Unfortunately, the table was not meant to be viewed by developers, and therefore was poorly documented. (The VB-like screen editor was the intended tool for GUI editing.)

Actually, most GUI application programmers almost never see the code structure that makes up their screens. They simply click on a screen item in the IDE, an event selection box comes up (Events like: on_click, on_exit, on_keyboard, etc.), and then a "code snippet" box comes up to edit the event code. Whether that event code is in a method, subroutine, or XML does not matter that much to the programmer. If you changed the generated code implementation from OOP to procedural and/or tables, the programmer may never even know the difference. (There are variations on the given editing theme/steps, but most are very similar.)

Some developers claim that "real programmers" don't use visual designers (IDE's), but instead use direct code. This is a controversial topic that can fill an entire website. I find that the flow-based (nested) code-centric approach is sometimes hard to fine-tune to customer/user expectations. A visual coordinate approach has drawbacks, but at least you can usually adjust stuff to exacting, demanding requirements. Customers/users often want as much as possible packed into a single screen. Doing such with a flow-based approach is tougher in my experience. Plus, it is less WYSIWYG. Perhaps if IDE's provided "stretch zones" which would be a vertical and horizontal line upon which a given widget can optionally stretch between when the window is resized.
Even if you don't like the table idea itself, how does sub-classing help for GUI's? Why not just have any widget have a bunch of potential features? If you need feature X, you select (toggle) feature X. How does a hierarchy or a dichotomy help it? It seems that you can get more combinations without the tree in the middle. (Sure, some combinations may not be valid, but such combinations probably fit complex set theory and not hierarchical patterns.) For example, one may want a hybrid picture-box and button. Click on the picture to do something.

One nice thing about tables, or at least an independent-feature-based (non-sub-typed) system, is that if you set an attribute and then change to a "kind" of widget that doesn't use that particular attribute, it is still there if and when you change it back. I have had problems with such attributes in sub-typed-based API's. For example, suppose you have a pull-down list widget, and then change it to a text-box. The list of user value option data may require removal or automatically be deleted because it is not an attribute of the text-box. Thus, if you then change it back to a pull-down list, your list of pull-down data (or it's reference ID) is gone.

Multiple Viewpoints

Another nice thing about tables is that you can get just about any view you want from it. Typical code-based GUI arrangements resemble this:
  form_1: new form(...)
     panel_1: new panel(...)
        text_1: new textbox(...)
        text_2: new textbox(...)
        text_3: new textbox(...)
        cancel_but: new button(...)
        ok_but: new new button(...)
     panel_2: new panel(...)
        text_4: new textbox(...)
        check_1: new checkbox(...)
        but_3: new button(...)
  form_2: new form(...)
     but_4: new button(...)
     but_5: new button(...)
     etc....
This provides a hierarchical view and relationship of the layout. There is nothing wrong with having a hierarchical view, but it should not be the only view that is readily obtainable.

Suppose you wanted to look at only and all of the "bound" widgets? ("Bound" means it has a formal link to the database in this case.) Or, suppose we just wanted to look at all the buttons on 3 given forms? Or need to view/filter only the textboxes and the "font" column because you need to change the fonts from "Courier" to "Arial" for the longer textboxes? (Arial is usually narrower for the same point size.)

Just the other day I had to change the name of a database table because it conflicted with a reserved word. I thus had to find all the GUI widgets that were linked or bound to that table, and change the name. If this information was in a table, it would be a simple one-time Update query. Instead, I had to open and inspect each widget one-by-one.

I repeatedly find tables better able to handle multiple viewpoints of items, both for development purposes and within an application itself. Basic queries (like SQL) can instantly provide many different viewpoints. Even OOP patterns seem to hard-wire a single relationships or viewpoint into the larger structure of program code in a similar fashion. I find this a bit archaic. The future should be leading toward virtual organizational viewpoints, and tables and Boolean filters come closer to this.

The product Oracle Forms apparently has the ability to store its GUI layouts in table form. However, I have not verified this myself so far. Thus, I cannot comment on the quality of their effort. However, from an interface standpoint, its "window" and "canvas" and "block" features overlap too much and create confusion. I recommend against intermediate structures between widgets and "form", except as an optional set-based grouping mechanism instead of direct nesting. Such devices can create aspect conflicts if over-emphasized by the GUI system. For example, some groups are based on the primary table of data association, and some groups are based on physical proximity. These can be orthogonal traits. I may post more on this product soon.

Putting It All Together

diagram
Basic flow of a table-driven GUI

So how would a table-driven GUI system actually work? The first step would be to create the "master" or "virgin" GUI widget table (see above schema layout description). Ideally, a Visual Basic or Delphi-like IDE would be available to draw the master GUI. When a user logs in, a copy of the master is created for that user. Making a copy allows widgets to be altered for that user without harming the original. In other words, the GUI can be dynamic. Whether all application forms are copied or only those activated, is an open design decision.

Here are the basic event round-trip steps, based on the above diagram.

  1. Client sends an event, and any needed content, to the server. See SCGUI draft protocol for some suggestions about how to manage event and content responses, especially for remote clients.

  2. The server looks up the appropriate event snippet(s) using an event table. (See Multi-dispatch GUI Event example.) The selected event code snippet(s) are then executed. The table can either store the code snippets, or reference them as say subroutine names. An "event structure", such as an associative array, can be sent as a parameter to communicate info about the event. Again, ideally the IDE would manage the naming and storing of these. Event snippets can both read and change the active Persistent View Table.

  3. When all event snippets are done processing, any requested refreshes (redraws) of the view model are then sent to the client. The refresh engine reads the specified record(s) from the View Table. Commands may tell it to refresh a given widget(s), a given form(s), or the entire application.

For related information about some of these processes, see Report Manager Example.


See Also:
Driver Pattern Items
Components
Dealing with Many Attributes
Multitasking Screens (ch. 30)
Event Dispatching Table (organizing event handling)
Drop-down List Example and Set/Get Reduction
Array Issues
Aspects
SCGUI (Remote GUI's)
Report Manager Example
Data Dictionary Examples
Web Development Stifled
Dynamic Relational


Main | OOP Criticism | Table Oriented Programming
Updated: 9/18/2004