GUI

In GUI design, it is useful to distinguish between a GUI's visual elements and the behavioral properties associated with these elements. Visual elements are typically called widgets, which are of different types and support different events. The behavioral properties of the different widgets are defined by the actions associated to the events that they support.

The GUI metamodel shown below defines a language for modeling the behavioral properties of GUIs. In a nutshell, GUIs consist of widgets that are displayed inside containers, which are themselves widgets. Each widget has a set of events associated to it: these are the events supported by the widget. Each event is in turn associated with a set of actions: these are the actions triggered by the event. Events' actions are of two types: widget actions (which are actions on GUI widgets) and model actions (also denoted as data actions), which are actions on the application data.

The type of widgets, events, and actions that are considered in this metamodel correspond to those currently supported by our code generator. In fact, the associated invariants are of two types:

Constraints (GUI):
They specify constraints that every GUI model must satisfy.
Constraints (Code generator):
They specify constraints that GUI models must satisfy to be valid inputs for our code generator.

GUI metamodel

Button

Description
Buttons are a type of widgets. Buttons' events typically trigger actions either on application data or on other widgets. Buttons can not be used to show information related to application data.
Generalization
Attributes
None
Associations
None
Constraints (GUI)
Buttons's events do not trigger read-actions on application data
context Button buttonsDoNotTriggerAtomicReadActions
    inv: self.widgetEvents.firedActions->select(a|a.oclIsTypeOf(ModelAction)).oclAsType(ModelAction)
    ->forAll(a|a.modelAction.substring(a.modelAction.length()- 9, a.modelAction.length()) <> 'AtomicRead')
    
Constraints (Code generator)
Buttons only support (if any) onclick-events
context Button buttonOnlySupportIfAnyClickEvents
    inv: self.widgetEvents->reject(ev|ev.event = EventEnum::onClick)->isEmpty()
    

ComboEntry

Description
Combo-entries are a type of widgets. Combo-entries are contained by combo-boxes. If we understand combo-boxes as tables, each combo-entry owned by a combo-box defines the type of information which is showed in a one of the columns of the corresponding table.
Generalization
Attributes
  • text: String. This is the text held by this combo-entry.
Associations
  • comboOwner: ComboBox. This is the combo-box which owns this combo-entry.
Constraints (GUI)
Every combo-entry triggers exactly one action: namely, a read-action on application data.
  	context ComboEntry everyComboEntryExactlyTriggersOneReadAction
  	inv: self.widgetEvents.firedActions->one(a|
  		       a.oclIsTypeOf(ModelAction)
               and a.modelAction.substring(a.modelAction.length()- 9, a.modelAction.length()) = 'AtomicRead')
  	

ComboBox

Description
Combo-boxes are a type of widgets. Combo-boxes contain combo-entries. Combo-boxes can be understood as tables. Each combo-entry owned by a combo-box defines the type of information which is showed in a one of the columns of the corresponding table. Each element in the collection associated to a combo-box defines a row in the corresponding table. Combo-boxes are contained by windows.
Generalization
Attributes
collection: String. This is the expression which specifies the collection associated to this combo-box.
Associations
  • hasEntry: ComboEntry. These are the combo-entries owned by this combo-box.
Constraints (GUI)
Every combo-box is contained by one window
context ComboBox everyComboBoxIsContainedByOneWindow
    inv: self.container->exists(c|c.oclIsTypeOf(Window))
    
Constraints (Code generator)
Every combo-box contains exactly one combo-entry.
context ComboBox everyComboBoxContainsExactlyOneComboEntry
    inv: self.hasEntry->size(one)
    

Container

Description
Containers are an abstract type of widgets. Containers contain other widgets. Containers may have variables, which hold information that can be used by actions triggered by events supported by widgets contained by these containers.
Attributes
None
Associations
  • variables: WidgetVariable [0..*]. These are the variables associated to this container.
  • contained: Widget [0..*]. These are the widgets contained by this container.
Constraints (GUI)
No container can contain itself
context Container noContainerContainsItself
    inv: self.widgetsContainedAux()->excludes(self))
    
All variables associated to the same container have different names
context Container allVariableOfSameContainerHaveDifferentNames
    inv: self.variables->forAll(wv1, wv2| wv1 <> wv2 implies wv1.name <> wv2.name)
Constraints (Code generator)
There is at most one variable name 'data' associated to each container
context Container thereIsAtMostOneDataVariableForEachContainer
    inv: self.variables->one(v | v.name = 'data') or self.variables->forAll(v | v.name <> 'data')
    
Containers only support onCreate-events
context Container containersOnlySupportOnCreateEvents
    inv self.widgetEvents->reject(ev|ev.event = EventEnum::onCreate)->isEmpty()
  

Entry

Description
Entries are a type of widgets. Users can introduce text on an entry. Entries can also show information about application data. Text held by an entry can be used by actions (either on widgets or on application data) triggered by events supported by other widgets contained by the same window that this entry.
Generalization
Attributes
  • text: String. This is the text held by this entry.
Associations
None.
Constraints (Code generator)
Entry widgets only support (if any) onCreate-events
context Entry entriesOnlySupportIfAnyOnCreateEvents
    inv: self.widgetEvents->reject(ev|ev.event = EventEnum::onCreate)->isEmpty()
    
Entry widgets trigger (if any) one AtomicRead action
context Entry entriesTriggerIfAnyOneAtomicReadAction
    inv: self.widgetEvents.firedActions->size()<= 1
    and self.widgetEvents.firedActions->forAll(a|a.oclIsTypeOf(ModelAction))
    and self.widgetEvents.firedActions->select(a|a.oclIsTypeOf(ModelAction)).oclAsType(ModelAction)
    ->forAll(a|a.modelAction.substring(a.modelAction.length()- 9, a.modelAction.length()) = 'AtomicRead')
    

Event

Description
Events are supported by widgets. Events trigger actions either on widgets or on application data. Events are of different types, each one representing a different type of user's actions on the widget supporting the event.
Attributes
  • event: EventEnum. This is the type of this event.
  • name: String. This is the name of this event.
Associations
  • firedActions: GAction [0..*]. These are the actions (either on widgets or on application data) triggered by this events.
  • holder: Widget. This is the widget supporting this event.
Constraints (Code generator)
Events of type oncreate can trigger read-actions (on application-data) or set-action (on widgets), but not both.
context Event onCreateCanTriggerReadorSetActionsButNotBoth
    inv: self.event = EventEnum::onCreate implies
    (self.firedActions->select(w|w.oclIsTypeOf(ModelAction))
    ->select(m|m.oclAsType(ModelAction).modelAction.endsWith('atomicRead'))->size()
    + self.firedActions->select(w|w.oclIsTypeOf(WidgetAction))
    ->select(w|w.oclAsType(WidgetAction).guiAction.=(GUIAction::set))->size() <= 1)
    

GAction

Description
This is an abstract class of actions. Actions are either widget actions (i.e., actions on widgets) or model actions (i.e., actions on application data). Actions are triggered by events. Actions may take parameters.
Attributes
  • name: String. This is the name of this action.
Associations
  • parameters: Parameter [0..*]. These are the parameters associated to this action.
  • triggeredBy: Event. This is the event that triggers this action.
Constraints (Code generator)
Only open-actions, set-actions, and update-actions take parameters
context GAction onlyOpenAndSetAndAtomicUpdateActionsTakeParameters
    inv: self.parameters->notEmpty() implies
    (self.oclIsTypeOf(WidgetAction) implies 
    		(self.oclAsType(WidgetAction).guiAction = GUIAction::open 
    		or (self.oclAsType(WidgetAction).guiAction = GUIAction::set))
    or (self.oclIsTypeOf(ModelAction) implies (self.oclAsType(ModelAction)
    	.modelAction.substring(self.oclAsType(ModelAction).modelAction.length()- 11, 
    			self.oclAsType(ModelAction).modelAction.length()) = 'AtomicUpdate')))
    

Label

Description
Labels are a type of widgets. Labels are used to show information. Users can not type in their own text on labels.
Generalization
Attributes
  • text: String. This is the text showed by this label.
Associations
None
Constraints (Code generator)
Labels only support oncreate-events.
context Label labelsOnlySupportOnCreateEvents
    inv: self.widgetEvents->reject(ev|ev.event = EventEnum::onCreate)->isEmpty()
	

ModelAction

Description
Model actions are actions on application data.
Generalization
Attributes
  • modelAction: String. This is the name of this model action.
Associations
  • subject: Subject. This is subject of the model action, i.e., the data upon which this model action acts.

Parameter

Description
Actions may take parameters. These parameters provide, for example, the values to be assigned to the widget's variables when opening a widget. Parameters include the expressions that define their concrete values when actions are taken.
Attributes
  • expression: String. This is the expressión defining the value of the parameter.
  • name: String. This is the name of this parameter.
  • type: String. This is the type of the parameter.
Associations
  • instantiate: WidgetVariable [0..*]. These are the widget's variables whose values will be provided by this parameter when calling the appropriate actions.
  • parameterOn: GAction. This the action that takes this parameter.

Subject

Description
Subjects are data upon which model actions act.
Attributes
  • expression: String. This is the expression defining the subject data.
  • type: String. This is the type of this subject data.
Associations
  • subjectOn: ModelAction. This is the action that act upon this subject data

Widget

Description
Widgets are graphical elements. Widgets support events, i.e., user actions. Widgets may be contained by other widgets.
Attributes
  • name: String. This is the name of this widget.
Associations
  • container: Container [0..1]. This is the widget (if any) containing this widget.
  • widgetActions: WidgetAction [0..*]. These are the actions acting on this widget.
  • widgetEvents: Event [0..*]. These the events supported by this widget.
Constraints (GUI)
Every non container widget is contained by exactly one container widget
context Widget everyNonContainerWidgetIsContainedByExactlyOneContainer
    inv: (not self.oclIsKindOf(Container)) implies self.container->size()=1
Every widget supports at most one event of each type
context Widget everyWidgetSupportsAtMostOneEventOfEachType
  inv: self.widgetEvents->forAll(ev1, ev2| ev1 <> ev2 implies ev1.event <> ev2.event)
  

WidgetAction

Description
Widget actions are a type of actions. Widget actions are actions on widgets triggered by events. Widgets actions are of different kinds.
Generalization
Attributes
  • guiAction: GUIAction. The kind of this widget action.
Associations
  • actionOn: Widget [0..1]. The widget (if any) upon which this widget action acts.
Constraints (Code generator)
Set-actions are only supported by onclick-events or oncreate-events
context WidgetActions setOnlyIsSupportedByOnCreateOrOnClickEvents
    inv self.guiAction = GUIAction::set implies
    self.triggeredBy.event = EventEnum::onCreate or self.triggeredBy.event = EventEnum::onClick
    

WidgetVariable

Description
Widget variables are variables associated to widget containers that hold information that can be used by actions triggered by events supported by widgets inside these containers.
Attributes
  • name: String. The name of the widget variable.
  • type: String. The type of the information held by this variable.
Associations
  • instantiateBy: Parameter [1..*]. The actions' parameters that may provide the information held by this variable.
  • scope: Container. The widget container that owns this variable.
Constraints (GUI)
Variables associated to the same container have different names
context WidgetVariable VariablesofSameContainerHaveDifferentNames
    inv: self.scope.variables->excluding(self)->forAll(v|v.name <> self.name)
	

Window

Description
Windows are a type of widgets. Windows can contain other widgets. Windows are organized in a tree-like hierarchy, with a root (also called main) window.
Generalization
Attributes
  • main: Boolean. Whether this is the main window or not.
Associations
Constraints
There is exactly one main window
    context Window thereIsExactlyOneMainWindow
    inv: Window.allInstances()->select(w|w.main)->size()=1
    
Constraints (Code generator)
From the main window every other window can be reached eventually.
    context Window fromTheMainWindowEveryOtherWindowCanBeEventuallyReached
    inv: self.main implies Window::allInstances()->excluding(self)->asSet() =
    self.allWidgetsOpenRecFrom()->select(wd|wd.oclIsTypeOf(Window)).oclAsType(Window)->asSet())
    
No window can be reached from itself
    context Window noWindowCanBeReachedFromItself
    inv: self.allWindowsOpenRecFrom()->excludes(self)
    
Windows are not contained by any other widget
context Window windowsAreNotContainedByAnyOtherWidget
    inv: self.container->isEmpty()
    
TBC

Example