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.
- 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()
- 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')
- 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)
- 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()
- 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')
- 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)
- 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')))
- 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()
- 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.
- 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.
- 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
- 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)
- 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
- 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)
- 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
|