# GEL: A definition-based graphical environment language for EDEN

#### Antony Harfield
Empirical Modelling Research Group
http://www.dcs.warwick.ac.uk/modelling/

#### 27th October 2006

Also available as pdf.

## Introduction

The Empirical Modelling tool `tkeden` is an environment for creating and experimenting with computer-based artefacts. It contains a number of definition-based notations that can be used for displaying graphical artefacts. The SCreen layOUT (SCOUT) notation is used for the layout of simple graphical components (buttons, labels and textboxes) on a canvas. The Definitive Notation for Line Drawing (DoNaLD) is used for placing points, lines, and other shapes on a canvas.

The subject of this paper is a notation for graphical user interface (GUI) components. The Graphical Environment Language (GEL) is a definition-based notation for creating and modifying GUIs. The components in the GUI are based on common components found in libraries for programming languages (for example: the Tk toolkit in Tcl, Perl and C, Swing in Java, etc).

The current GEL notation is called %angel (ANt's prototype GEL) which is an experimental version being developed using the Agent-Oriented Parser (AOP).

## Definition-based notations

In order to understand definition-based notations (sometimes referred to as 'definitive notations'), it is first neccessary to be familiar with the Empirical Modelling principles of observables and dependencies. Where traditional procedural programming languages use variables and procedures for describing computer-based artefacts, Empirical Modelling describes artefacts in terms of what observables and dependencies they embody. An observable is a feature, property or value; for example, a bird might have a length and a colour associated with it. A dependency is a relationship between one or more observables; for example, the speed at which a bird can fly at is dependent on it's wing span. In Empirical Modelling, artefacts are developed by a series of observations and experimentations: experimenting with the observables and dependencies and then observing the effect which in turn may inform further experimentation.

A definition-based notation is a language that supports the creation and experimentation of observables and dependencies. EDEN is the general purpose definition-based notation in tkeden for defining observables and dependencies. In EDEN, observables can be thought of as variables containing regular values like integers, strings, lists. Dependencies are definitions for the relationship between observables. Consider the example of an artefact modelling the weight of a car. We might create observables for the weight of the passengers, and the weight of the chassis and engine. Then a dependency could be created to represent the overall weight as a sum of the observables. In a procedural programming language you could define the artefact as:

> `passenger_weight := 140
> car_weight := 3000
> total_weight := passenger_weight + car_weight`

The problem with this is that there is a relationship at the point of assignment, there is no persistent dependency between the overall weight and the weight of the car and passengers. If at any point the weight of the passengers changes then the relationship is no longer consistent. Procedural programmers avoid this by writing explicit dependency maintaining procedures that ensure whenever the passenger or car weight are updated then the overall weight is also re-assigned. In a definition-based notation the dependencies are maintained automatically in the tool, much like the dependency between cells in a spreadsheet. The equivalent description of our artefact could be described as:

> `passenger_weight = 140
> car_weight = 3000
> total_weight = passenger_weight + car_weight`

A collection or list of definitions is called a script. Note that instead of the assignment operator ':=', the definition operator '=' is used. This is to differentiate between assignments and dependency definitions. In the tkeden environment, as with a spreadsheet, if any changes (redefinitions) are made to either the passenger or car weight then the change will also be reflected in the value of the total weight.

Observables and dependencies become even more powerful when the types of observables become more complicated. The DoNaLD notation (Definitive Notation for Line Drawing) supports observables that can be points, lines, circles and other shapes. In the DoNaLD notation, dependency can be used to define particular points, lines and shapes to be dependent on other points, lines and shapes. Complex objects can be moved, rotated and resized with simple redefinitions of single observables which propagates changes to the entire object.

The agent-oriented parser (AOP) is a notation that supports the development of new notations in the `tkeden` environment. GEL was developed using the AOP notation. For more information on constructing notations see the guide to the AOP at: http://www2.warwick.ac.uk/fac/sci/dcs/research/em/notations/aop/.

To summarise, definition-based notations are languages that allow the investigation, creation and manipulation of observables and dependencies.

## Notation specification

The GEL notation is designed to be independent of the implementation language. However, given that the first implementation %angel is in Tcl/Tk, there are some properties in the language that are fairly specific to Tk (i.e. the way packing is managed). For further information on the properties of components see the Tcl/Tk man pages.

### Definitions

A GEL script is a list of definitions. Each definition has on the left hand side a definition name and on the right hand side a definition formula, separated by the definition operator (an equals sign in GEL) and terminated by a semicolon.

>     script:
>         definition script
>     definition:
>         definition_name = definition_formula;

A definition name can be the name of an instance of a component. It can be an identifier consisting of a sequence of letters and digits. The first character must be a letter. The underscore character _ is considered a letter. You cannot use EDEN reserved words as identifiers.

A definition name can also represent a property within a component. In this case, there are two identifiers, separated by a dot. The first identifier is the name of the component, and the second identifier is the name of the property with the component.

>     definition_name:
>         identifier
>         identifier.identifier

Valid definition names are: `mywindow`, `mybutton.text`, `frame5`, `a_label`. Invalid definition names are: `4thframe`, `else`, `mywin.mybut.mytext`.

There is no variable declaration or type declaration in GEL. This means that you can create and redefine a definition with the same statement construction.

A definition formula is the recipe for the GEL observable. The observable should have an observable type if it is a GEL component. GEL components consist of a number of properties (also observables). For example, a `button` can have a colour, a text string and a border.

>     definition_formula:
>         observable_type ( argument_list )
>         observable_type { property_list }
>         eden_expression

Examples of valid definition formulae include:

>     window ( "My Window Title" )  /* not yet implemented */
>     window { title = "My Window Title" }
>     "This is only a string"

An observable type is one of the supported components or containers in GEL. Types currently support are: `window`, `frame`, `button`, `textbox`, `label`, `checkbutton`, `radiobutton`, `scrollbar`, `scale`, `scout`, `html`, `image`.

An argument list is a sequence of property expressions separated by commas.

A property list is a sequence of property definitions separated by semicolons.

>     argument_list:
>         property_expression
>         property_expression, argument_list
>     property_list:
>         property_definition
>         property_definition; property_list
>     property_definition:
>         identifier = property_expression
>     property_expression:
>         eden_expression
>         [ identifier_list ]
>     identifier_list:
>         identifier
>         identifier, identifier_list

An EDEN expression is any combination of EDEN functions, observables or values. EDEN values have can be of type: boolean (false is represented by `0` and everything else is true), integer (e.g. `1234`), real (e.g. `9.876`), string (e.g. `"a string"`), and list (e.g. `[ 1, 5, "string", 6.78 ]`).

### Containers

There are two types of components that can contain other components: the `window` and the `frame`. The `window` is a special case as it is the only component that cannot be placed inside other containers.

The special property that containers possess is the `content` property. This specifies what components are contained with the `window` or `frame`. For more information on how components are arranged within containers see the next section on 'packing properties'.

#### The `window`

Special properties: `content`, `title`, and `visible`.

The `window` component is a container and therefore it has the property `content` to define the components that are inside the component. This property can only be set to a list of identifiers that represent GEL component observables.

The following example creates a new `window` called `mywindow` with a specific `title`, `height` and `width`. The `content` of the window is two components named `myframe` and `anotherframe`.

>     %angel
>     mywindow = window {
>         title = "New window";
>         height = 200;
>         width = 400;
>         content = [ myframe, anotherframe ] };

A `window` can have a `title` which is a string that is displayed in the title bar. Windows can be hidden and unhidden with the `visible` boolean property -- set this to `0` to hide the window (e.g. `mywindow.visible = 0` ).

#### The `frame`

Special properties: `content`.

A `frame` is a basic container whose contents are set with the `content` property. Frames are useful for grouping and arranging components together.

The next example defines a `frame` called `myframe` which contains three components.

>     myframe = frame {
>         content = [ mybutton, mylabel, mytextbox ] };

### Components

The currently implemented components are described below. Each component has some special properties. The properties that are standard to all components are described in the next section.

#### The `button`

Special properties: `text`.

The `button` is a basic component that allows the user to perform a mouse click on the component that results in an action. A button has a special property called `text` which specifies the label (i.e. a string) that is placed on the button. When the user interacts with the button there are two observables which represent the current state: `mybutton_mouseover` and `mybutton_mouseclick` (where 'mybutton' is the name of the button). If the cursor is within the boundary of the button then `mybutton_mouseover` has the value 1, else it has the value 0 (zero). If the mouse button is pressed down on the button then `mybutton_mouseclick` has the value 1, else if the mouse button is up then it has the value 0 (zero).

>     %eden
>     /* Example of triggered procedure that performs an action on a mouse click */
>     proc mybutton_mouseclick_trigger : mybutton_mouseclick {
>        if (mybutton_mouseclick == 0) {
>           writeln("the user pressed mybutton");
>        }
>     }

#### The `textbox`

Special properties: `text`, `height`, and `width`.

A `textbox` is a component for text entry. The size of the textbox can be defined by the `width` and `height` properties (specifying the size in characters, as opposed to pixels in other components). The observable `mytb_text` (where mytb is the name of the textbox), or the property `text`, represents the text in the textbox. If the user enters or modifies the text in the textbox then the observable mytb_text will always be representative of the current value (and it updates after each keypress). Also, if the user changes the string value of mytb_text, then textbox is likewise updated.

>     %angel
>     /* Example of a textbox */
>     mytb = textbox {
>        text = "some initial text" };

#### The `label`

Special properties: `text`.

A `label` is a simple component for displaying text. It has only one special property, `text`, which defines the text to be displayed in the component.

>     %angel
>     /* Example of a label */
>     mylabel = label {
>        text = "white";
>        foreground = "white";
>        background = "black" };

#### The `checkbutton`

Special properties: `text`, `variable`, `offvalue`, `onvalue`, `indicatoron`, and `selectcolor`.

The `checkbutton` is a special type of button which can be toggled on or off. The state of the button (whether it is on or off) is represented by the observable specified by the `variable` property.

#### The `radiobutton`

Special properties: `text`, `variable`, `value`, `indicatoron`, and `selectcolor`.

The `radiobutton` is a special type of button that can be used to select from a group of options. The radio buttons are grouped by an observable which is specified by `variable`. When a radio button is selected, the `variable` is set to the `value` of that particular radio button. The `indicatoron` property (set to 1) defines which radio button in a group is switched on.

#### The `scrollbar`

Special properties: `scrolls`, `activerelief`, `elementborderwidth`, `jump`, `orient`, `repeatdelay`, `repeatinteval`, `takefocus`, and `troughcolor`.

The `scrollbar` component is used to scroll other components, e.g. `textbox`, `html`, and `scout`. Every scrollbar must have an orientation, which can be set by the `orient` property to either `"vertical"` or `"horizontal"`. The property `scrolls` determines which component the scrollbar effects, and should be a string containing the name of the component to be scrolled.

>     %angel
>     /* Example of a scrollbar on a textbox */
>     scrollbarexample = window {
>        title = "Scrollbar Example";
>        content = [mys,myt] };
>     mys = scrollbar {
>        scrolls = "myt";
>        orient = "vertical";
>        side = "right";
>        fill = "y" };
>     myt = textbox {
>        side = "right";
>        fill = "both";
>        expand = 1 };

Scrollbars are usually packed on the right. If you want your scrolled component to stick to the scrollbar then you should also pack your scrolled component to the right also. Scrollbars can have a specific height but more often they expand the entirety of the axis. So in the above example the scrollbar has `fill = "y"` to indicate it stretches the y-axis.

#### The `scale` component

Special properties: `bigincrement`, `digits`, `from`, `label`, `length`, `orient`, `repeatdelay`, `repeatinteval`, `resolution`, `showvalue`, `sliderlength`, `sliderrelief`, `state`, `takefocus`, `tickinteval`, `to`, and `troughcolor`.

The `scale` component is similar to the scrollbar except that, instead of scrolling a component, it has a value. Like the scrollbar, the `orient`property can be set to either `"horizontal"` or `"vertical"`. The extent of a `scale` can be set by the `from` and `to` properties. The `value` of a scale component is a number representing the current value, which can be used in a dependency/trigger (as below) or to set the current value.``

>     %angel
>     /* Example of a window containing a scale component */
>     mywin = window {
>        content = [myscale] };
>     myscale = scale {
>        from = 0;
>        to = 100;
>        orient = "horizontal";
>        showvalue = 1;
>        fill = "x" };
>     %eden
>     proc myscale_value_trigger : myscale_value {
>        writeln("myscale_value = "//str(myscale_value));
>     }

#### The `scout` component

Special properties: `display`.

The `scout` component can be used to display SCOUT inside GEL. The `display` property can be set to a string that is the name of any SCOUT display (e.g. "screen").

In order to display DoNaLD inside GEL, a `scout` component must be created and a DoNaLD window placed in the SCOUT display. The size of the DoNaLD window can be made dependent on the `scout` component size using the `width` and `height` properties.

#### The `html` component

Special properties: `text`, `appletcommand`, `fontcommand`, `formcommand`, `framecommand`, `hyperlinkcommand`, `imagecommand`, `isvisitedcommand`, `rulerelief`, `scriptcommand`, `tablerelief`, `unvisitedcolor`, `underlinehyperlinks`, and `visitedcolor`.

The `html` component is a text component that displays fully formatted HTML. The `text` property sets the HTML text to display in the component.

This component is based on the Tkhtml widget. The documentation for Tkhtml provides further information on how to use the special properties (configuration options) of this component.

#### The `image`

Special properties: `file`.

The `image` component has only one special property which specifies the `file` to be displayed. It must be a filename as a string, either a full path name or a relative path.

#### The `listbox`

Special properties: `items`, `selecteditems`, and `selectmode`.

The `selectmode` property specifies the style for manipulating the selection and takes any of the accepted values: `"single"`, `"browse"`, `"multiple"`, or `"extended"`. The default style is `"browse"`, which enables the user to select one item from the list. The `"multiple"` and `"extended"` styles enable the user to select more than one list item.

The `items` property specifies the items in the listbox. The value of this property must be a list of strings. The `selecteditems` property specifies the selected items in the listbox component. The value of this property should be a list of strings which are a subset of the `items` property. When the user modifies the selection in the listbox then this observable is updated.

### Standard properties

This section describes the properties that can be used with any component. Properties that relate to the layout of components in a container are described in the next section.

- activebackground -- Specifies the background color to use when drawing active component. A component is active if the mouse cursor is positioned over the component and pressing a mouse button will cause some action to occur.
- activeborderwidth -- Specifies a non-negative value indicating the width of the 3-D border drawn around active elements.
- activeforeground -- Specifies the foreground color to use when drawing active elements.
- anchor -- Specifies how the text or bitmap is to be displayed in the component. Must be one of the values n, ne, e, se, s, sw, w, nw, or center.
- background -- Specifies the normal background color to use when displaying the component.
- bitmap -- Specifies a bitmap to display in the widget. [not implemented]
- borderwidth -- Specifies the width in pixels of the border around the outside of the component.
- cursor -- Specifies the mouse cursor to be used for the component.
- disabledforeground -- Specifies the foreground color to use when drawing a disabled component.
- font -- Specifies the font to use when drawing text inside the component. For example: Times 10 bold
- foreground -- Specifies the normal foreground color to use when displaying the component.
- height -- Specifies the component width in pixels.
- highlightbackground -- Specifies the color to display in the traversal highlight region when the component does not have the input focus.
- highlightcolor -- Specifies the color to use for the traversal highlight rectangle that is drawn around the component when it has the input focus.
- highlightthickness -- Specifies a non-negative value indicating the width of the highlight rectangle to draw around the outside of the component when it has the input focus.
- justify -- Specifies the justification of the text in the component. Acceptable values are left, right, or centre
- relief -- Specifies the 3-D effect. Acceptable values are raised, sunken, flat, ridge, solid, and groove.
- width -- Specifies the component width in pixels.

### Layout properties

This section describes the properties relating to the layout of components within a container.

The content of frames and windows are arranged by the GEL packer. The %angel packer is based on the Tcl/Tk Pack Geometry Manager. The basic rules are:

- arrange components vertically using side="top" or side="bottom"
- arrange components horizontally using side="left" or side="right"
- for complex layouts use frames to group components together

The full list of layout properties are:

- side -- Specifies which side of the master the slave(s) will be packed against. Must be left, right, top, or bottom. Defaults to top.
- packanchor -- Anchor must be a valid anchor position such as n or sw; it specifies where to position each slave in its parcel. Defaults to center.
- expand -- Specifies whether the slaves should be expanded to consume extra space in their master. Boolean may have any proper boolean value, such as 1 or no. Defaults to 0.
- fill -- If a slave's parcel is larger than its requested dimensions, this option may be used to stretch the slave. Acceptable values are none, x, y, and both. Defaults to none.
- ipadx -- Specifies how much horizontal internal padding to leave on each side of the component.
- ipady -- Specifies how much vertical internal padding to leave on each side of the component.
- padx -- Specifies how much horizontal external padding to leave on each side of the slave.
- pady -- Specifies how much vertical external padding to leave on each side of the slave.

### Bindings property

The `bindings` property is used to define bindings for user interactions. Several default bindings are setup for some components, for example, if a textbox changes then the `mytextbox_text` observable is updated. The `bindings` property enables new bindings to be created to respond to keyboard, mouse and other user events.

The `bindings` property must be specified as a list of bind pairs separated by commas and surrounded by square brackets. The first item in a bind pair is the action to 'bind to' (usually surrounded in chevons <>). The second item should be surrounded by curly braces and can contaion any EDEN code to be executed when this action occurs.

Some standard bind event types are: Activate, Deactivate, MouseWheel, KeyPress, KeyRelease, ButtonPress, ButtonRelease, Motion, Destroy, FocusIn, FocusOut, Enter, Leave.

Some of these event types (i.e. KeyPress, KeyRelease, ButtonPress, ButtonRelease) can be modified with: Control, Alt, Shift, Button1, B1, Button2, B2, Button3, B3, Double, Triple, Quadruple.

Combinations take on the form <modifier-modifier-type-detail>. Some examples: <KeyPress-a>, <Escape>, <B1-Motion>, <Control-ButtonPress-1>.

For example, the following binds two actions, holding Ctrl with a button press, and a double click.

>     %angel
>     /* Binding example */
>     mywin = window {
>        title = "Click me!";
>        bindings = [
>           { writeln("You pressed control with mouse button 1"); },
>           { writeln("You double clicked mouse button 1"); } ] };

## Examples

The example below explains how to use some basic components to create an interface, and how GEL can be linked to EDEN. Further examples containing other components can be found in the `examples` directory of the GEL package.

### Baby Eden

This example is a baby version of the tkeden input window. It contains a textbox for entering definitions, a button for accepting definitions, and a button for exiting from the application.

The first part of the script defines a window, with a title, and containing three components. This is defined in the GEL notation (%angel).

>     %angel

>     babyedenwin = window {
>        title = "Baby Eden";
>        content = [accept,txt,exit] };

And then the three components are created. One textbox for the input, one button for accepting the input, and one button for exiting tkeden.

>     accept = button {
>        text = "Accept";
>        side = "left" };

>     txt = textbox {
>        width = 30;
>        height = 1;
>        side = "left" };

>     exit = button {
>        text = "Quit";
>        side = "left" };

After entering the above GEL definitions, the interface is displayed but the components are only a collection of observables (i.e. the buttons do not have any behaviour). In the following script, EDEN is used to define triggered procedures on each of button click actions.

>     %eden

>     proc trigger_execute : accept_mouseclick {
>        if (accept_mouseclick == 0) {
>           if (txt_text != @)
>              execute(txt_text);
>           txt_text = "";
>        }
>     }

>     proc trigger_exit : exit_mouseclick {
>        if (exit_mouseclick == 0) {
>           exit();
>        }
>     }

## References

- Edward Yung. EDEN language reference. Empirical Modelling Research Group. http://www2.warwick.ac.uk/fac/sci/dcs/research/em/software/eden/langref/ (last accessed 09/08/2006).
- Antony Harfield. Agent-Oriented Parser (AOP) documentation. Empirical Modelling Research Group. http://www2.warwick.ac.uk/fac/sci/dcs/research/em/notations/aop/ (last accessed 09/08/2006).
- Brent Welch, Ken Jones, and Jeffrey Hobbs (2003). Practical Programming in Tcl and Tk (fourth edition). Prentice Hall.
- Roger E. Critchlow Jr. Tcl/Tk Manual Pages. http://www.tcl.tk/man/tcl8.4/ (last accessed 09/08/2006).
- D. Richard Hipp. Tkhtml widget documentation and specification. http://www.hwaci.com/sw/tkhtml/spec.html (last accessed 27/10/2006).