
The user interface for the visualization program was created using the FORMS Library package included with Geomview (see the form source code). FORMS was created by Mark Overmar and is the interface toolkit in which Geomview was built upon. Using a collection of C-routines, forms are created that contain various objects the user can interact with. These objects include boxes, buttons, input fields, choice menus, browsers, and more. Each object on the form has a particular routine (called a callback function) assigned to it that, when the user interacts with the object (clicks on it with the mouse, enters text, etc.), automatically executes. An example would be a button labeled "Exit" that shuts down the program when clicked on with the mouse.
To create a form, the definition is begun with a call to the function:
Fl_FORM *fl_bgn_form (int type, float w, float h)
The parameter type refers to the background that will be drawn in the form. The
background is simply a type of box (which will be described in more detail
below). For the visualization program, the type of box used is an FL_UP_BOX,
which is a box that appears to come out of the screen. The float parameters
w and h define the width and height of the form, respectively. To
end the form definition, a call is made to the function:
void fl_end_form ()
Between these calls, the objects for the form are added.
All objects are placed on a form using a function call of the form:
FL_OBJECT *fl_add_NAME (int type, float x, float y, float w, float h, char label[])
The string "NAME" should be replaced with the type of object being added. The
return value, FL_OBJECT, is simply the FORMS Library object that was added. Each
object has different types, (for example, the button object has the types
FL_PUSH_BUTTON, FL_NORMAL_BUTTON, FL_RADIO_BUTTON, etc.). The integer parameter
type is used to specify which one should be used. The float parameters
x, y, w, and h define the x-coordinate of the bottom
left hand corner of the object, the corresponding y-coordinate, the width, and
the height of the object, respectively. The character array label is a
string that is placed inside or next to the object. To specify where to place
the label in relation to the object, a call must be made to the function
void fl_set_object_align (FL_OBJECT *obj, int align)
The parameter align can be one of the following choices:
FL_ALIGN_LEFT: to the left of the object
FL_ALIGN_RIGHT: to the right of the object
FL_ALIGN_TOP: above the object
FL_ALIGN_BOTTOM: below the object
FL_ALIGN_CENTER: centered on the object
If no label is required, the string label should be an empty string ("").
Each object (with exception to static objects) can be assigned a callback
function that will be executed when the user interacts with the object. Multiple
objects can be assigned to the same callback since one of the parameters to the
function is the object that called it. Multiple callbacks, however, cannot be
assigned to one object. Assigning a callback to an object is accomplished with
a call to:
void fl_set_call_back (FL_OBJECT *obj, void (*callback) (), long argument)
The parameter obj is the object the callback is being assigned to,
callback is the name of the callback function, and argument is
used to distinguish between different objects if more than one are assigned to
that callback (this parameter is not used in the ECOPHYS Visualization Program).
Areas of the form are often labeled using the label parameter in the fl_add_* function used to add objects to the form. Text differs in the fact that no object needs to be associated to it -- it is an object on its own.
FL_UP_BOX: a box that comes out of the screen
FL_FRAME_BOX: a flat box with no border
These types are entered as the type parameter when creating the boxes.
The form itself uses a box as the background. It has a the type FL_UP_BOX and is defined on line 18 of the code. Boxes are also useful for labeling areas of the form. For instance, creating a box that contains a label at its center provides a label with a frame around it, something not possible with text objects (see the "Leaf attributes" label in section 2 of the form.
FL_NORMAL_BUTTON: action only begins when the button is pressed and
released (for example, the exit button mentioned above).
FL_PUSH_BUTTON: the button stays pushed until the user pushes it
again.
FL_RADIO_BUTTON: a push button that, when grouped with other radio
buttons, only allows one button to be pushed in at a time. When one is pushed,
all others are popped out.
Radio buttons are a little more complex than the rest. Because only one button can be pushed in at a time, the buttons must be grouped together so the form knows which buttons to watch. To accomplish this, a two functions are called:
FL_OBJECT *fl_bgn_grp ()
FL_OBJECT *fl_end_grp ()
In between these two function calls, all the objects in the group should be added (in this case, the radio buttons in the group).
Adding a choice object puts it on the form, but it does not yet contain any choices. To dictate the available choices for this object, the following function is called:
void fl_addto_choice (FL_OBJECT *obj, char text[])
Here, obj is the choice object being added to and text is the string that represents the choice in the list.
FL_FLOAT_INPUT: only float values can be entered.
The other aspect of input fields that must be considered is when the input should return to the application program (when the callback should be executed). For the Visualization Program, the input is returned whenever the user types in a new value and then hits "Return". This is set through a call to the function:
void fl_set_input_return (FL_OBJECT *obj, int when);
The parameter when, in this case, would be the value FL_RETURN_END_CHANGED.
| Description | Object | Object type | Callback | Line |
| Form title | Box (with label) | FL_FRAME_BOX | none | 19 |
| Update Button | Button | FL_NORMAL_BUTTON | updateButton_cb | 24-25 |
| Exit Button | Button | FL_NORMAL_BUTTON | none | 26 |
| Description | Object | Object type | Callback | Line |
| Surrounding box | Box | FL_FRAME_BOX | none | 39 |
| Display for Tree 1 file name | Browser | FL_NORMAL_BROWSER | none | 40 |
| Tree 1 file label | Text | FL_NORMAL_TEXT | none | 41-42 |
| Display for Tree 2 file name | Browser | FL_NORMAL_BROWSER | none | 43 |
| Tree 2 file label | Text | FL_NORMAL_TEXT | none | 44-45 |
| Load button for Tree 1 | Button | FL_NORMAL_BUTTON | loadFile_cb | 46-47 |
| Load button for Tree 2 | Button | FL_NORMAL_BUTTON | loadFile_cb | 48-49 |
The last line of this section (line 50) contains a call to the function:
fl_deactivate_object (FL_OBJECT *obj)
The parameter obj is the object to deactivate. This function is used to prevent the user from using a particular object. When it is called, the object becomes frozen, and any interaction from the user has no affect (no callback is called). In Section 1 of the form, the Tree 2 load button is initially deactivated since Tree 1 is the default tree being displayed.
Objects can also be activated by a call to:
fl_activate_object (FL_OBJECT *obj)
The deactivate and activate functions are used extensively in the callback functions for the form.
| Description | Object | Object type | Callback | Line |
| Surrounding box | Box | FL_FRAME_BOX | none | 52 |
| Section title | Box (with label) | FL_FRAME_BOX | none | 53-54 |
| Leaf type choice | Choice | FL_NORMAL_CHOICE | leafType_cb | 55-62 |
| Leaf color choice | Choice | FL_NORMAL_CHOICE | leafColorChoice_cb | 64-71 |
| Minimum leaf attribute value | Input field | FL_FLOAT_INPUT | leafminValue_cb | 72-75 |
| Maximum leaf attribute value | Input field | FL_FLOAT_INPUT | leafmaxValue_cb | 76-79 |
| Reset attribute values button | Button | FL_NORMAL_BUTTON | resetLeaves_cb | 80-81 |
Line 54 contains a call to the function:
void fl_set_object_lsize (FL_OBJECT *obj, float size)
This function sets the size of the characters of the object label. The parameter obj is the object whose label is being sized and size is the size in pixels.
| Description | Object | Object type | Callback | Line |
| Surrounding box | Box | FL_FRAME_BOX | none | 84 |
| Section title | Box (with label) | FL_FRAME_BOX | none | 85-86 |
| Root type choice | Choice | FL_NORMAL_CHOICE | rootType_cb | 88-94 |
| Root color choice | Choice | FL_NORMAL_CHOICE | rootColorChoice_cb | 95-104 |
| Minimum root attribute value | Input field | FL_FLOAT_INPUT | rootminValue_cb | 107-109 |
| Maximum root attribute value | Input field | FL_FLOAT_INPUT | rootmaxValue_cb | 110-112 |
| Reset attribute values button | Button | FL_NORMAL_BUTTON | resetRoots_cb | 113-114 |
| Description | Object | Object type | Callback | Line |
| Surrounding box | Box | FL_FRAME_BOX | none | 117 |
| Display branches | Choice | FL_NORMAL_CHOICE | branchChoice_cb | 118-121 |
| Display roots | Choice | FL_NORMAL_CHOICE | rootChoice_cb | 122-125 |
| Display sunlight | Choice | FL_NORMAL_CHOICE | sunChoice_cb | 126-129 |
| Description | Object | Object type | Callback | Line |
| Surrounding box | Box | FL_FRAME_BOX | none | 28 |
| Tree 1 button | Button | FL_RADIO_BUTTON | treeButton_cb | 30-33 |
| Tree 2 button | Button | FL_RADIO_BUTTON | treeButton_cb | 34-36 |
Line 33 contains a call to a function that sets, or pushes down, the specified button:
void fl_set_button (FL_OBJECT *obj, int pushed)
The parameter obj is the button being set and pushed has the value "1" if the button is pushed in, "0" if it is released. There is also a function included here that sets the color of an object:
void fl_set_object_color (FL_OBJECT *obj, int col1, int col2)
Here, obj is the object whose color is being set and col1 and col2 are indices into the colormap. For a button object, col1 is the color of the button and col2 is the color of the button when it is pushed in.