While editing an interface, the GUI Painter holds all attribute values of the application window and their containing widgets. This collection of attribute values fully represents a definition of the window application and is called window specification. In order to store that window specification, the GUI Painter generates a resource method of the window specification in the category window specs of the application class protocol, which returns a symbolic representation of the widgets and their properties. This window resource method is used to create and to initialize the view objects and the models objects of the widgets when your application is started. After each adding of a widget or a modification you can save the window specification on the resource method and start the application in order to get a preview of the interface. Later, if an interface needs some modification, the GUI Painter can be started on the window resource method of that interface.
The format of the ST/X's window
specification are designed to be upward compatible from VisualWorks
* - this means that existing window specifications should work in the
ST/X environment. (We depend on user feed backs through verbal descriptions
or existing specifications to validate and maintain this upward compatibility
- you are welcome to send a note or your window resource methods for validation,
when encountering incompatible specifications... .) Since ST/X's
views contain more attributes, their specifications may or may not be backward
compatible.
* VisualWorks is a trademark of ObjectShare, Inc.
The canvas window (with grid) for assembling your widgets
The gallery window with the widgets
The window for controlling the widgets
Window specification methods can also be useful outside the
ApplicationModel hierarchy.
This is useful for example, to open a constructed dialog or popupMenu.
However, in this case, the builder must be provided with additional
aspect-binding information (typically provided in a dictionary).
Examples for this kind of use can be found by searching for senders of
#openFor:interfaceSpec:withBindings:,
#openDialogInterface:withBindings: and similar messages.
When your application is opened, it fetches this specification (by sending
"self windowSpec", and passes the spec to its ui-builder.
The builder recursively
walks throughout the definition, and creates corresponding widgets on the fly.
As widgets are built, named widgets are placed into a dictionary,
and can later be accessed by the application via
"self builder componentAt: nameOfTheComponent".
For portability ST/X does not use native widgets of the working operating system. The widgets takes its visual attributes from a so called style sheet. This style sheet is a file (see directory "resources" for files *.rs) which lists all properties of the user interface. You are free to design you own user interface by copying an existing rs-file and modifying it. (For more details see chapter "Changing the view style appearance" in document "Configuration & Customization".) Some visual attributes of the widgets (font style, colors, borders) can individually be changed by the GUI Painter.
The GUI Painter of ST/X provides the interface developer with
all widgets for building a complete window application. The widgets are
accessible by the gallery window. Because the similar meaning of some widgets
they are divided into sections. The sections and their widgets are as following:
| Button Widgets | Menu Widgets | Text Widgets | List Widgets | Grouping Widgets | Misc Widgets |
| Button | Tool Bar | Label | List | Box | Arbitrary Component |
| Model Button | PopUp List | Entry Field | Table | Framed Box | SubSpecification |
| Arrow Button | Combo List | Text Editor | Tree List | Horizontal Panel | SubCanvas |
| Radio Button | Combo Box | HTML Browser | File Tree List | Vertical Panel | Slider |
| UpDown Button | Ext. ComboBox | Area Panel | Thumb Wheel | ||
| Toggle | Tab Header | Variable Horiz. Panel | Progress Indicator | ||
| Check Box | Note Book | Variable Vert. Panel | Separator | ||
| Check Toggle | Gallery | Region | |||
| Application Window (canvas) |
Besides the individual attributes of the widgets there are some common attributes:
Do not worry about the names of the view and specification classes of
the widgets. The class naming has historical reasons (for
portability to VW).
To avoid using 'complicated' names for the widgets,
user friendly names are used in this documentation and the within the UIPainter.
It offers a palette of common styles.
This palette can be modified in the class FontMenu.
After selecting the check toggle, an own font style can be chosen by selecting one of the Family/Face/Style/Size
buttons.
If the check toggle is left off,
the default font (from the viewStyle sheet) will be used.
It offers a palette of often used standard colors. This palette can
be modified in the class ColorMenu. After selecting the check
toggle, an own color can be chosen by selecting the desired colored button.
If no color is selected, the widgets take default colors from the style
sheet.
This is necessary if you want to change the contents of the view objects dynamically during the run time, and if you want to present the data in several view objects (on different clients) at the same time.
The value holders are acquired by the builder of the application during startup. For each model (or value holder), your application may provide a corresponding access method. These accessing methods are called aspect methods for short. The place of implementation depends on your application. The builder looks for it in different objects. These are in order:
The whole framework heavily depends on the model-view design pattern, so you should know and understand the Model class and especially the ValueHolder classes.
The following figure summarizes these relations:
The picture is not completely correct, in that the aspect access (from
the instance of the class UIBuilder) is actually via your application
- however, most applications use the fallBack via the "bindings"
dictionary which is provided by the class ApplicationModel; therefore,
the figure gives a picture of the typical setup.
For more details of value holders see document "Understanding
and Using ValueModels".
These attributes must be modified programatically - either during startup of the application (i.e. right before the window is made visible) or dynamically as a result of other activities.
During startup, a number of hook-methods are invoked, which can be redefined by the programmer. These hooks (i.e. messages sent to the application) are:
postBuildWith:aBuilder
|myButton|
"/ fetch a widget by its ID
myButton := aBuilder componentAt:#myButton.
myButton activeForegroundColor:Color red.
myButton activeBackgroundColor:Color yellow.
myAspect
myAspect isNil ifTrue:[
myAspect := ValueHolder new.
myAspect onChangeSend:#myAspectChanged to:self.
].
^ myAspect
the above example arranges for the #myAspectChanged method
to be invoked whenever the value in myAspcet changes
(due to some widget interaction or however).
Notice, that this is functionally the same setup as arranged when a callBack is installed in the GUI painter.
Normally, there is no need to redefine this method, unless you want to let the user confirm the close (for example, if there is any unsaved data); in this case, redefine the #closeRequest method as follows:
closeRequest
self hasAnyUnsavedData ifTrue:[
(self confirm:'Close without saving ?') ifFalse:[
^ self
]
].
super closeRequest
The above method suppresses the window-closing
if there is unsaved data, and the user does not confirm the dialog
with 'OK'.
This inherited closeRequest method simply invokes the closeDownViews method, which does a hard-shutdown. You are not supposed to redefined closeDownViews - but you may of course invoke it if you want your application to shutDown without a closeRequest.
If you dont want to add extra classes for this kind of dialog, you can still use the GUIBuilder and windowSpec framework.
First, construct the dialogs window spec using the GUIPainter,
and save it as some class method of your application.
The code to open the dialog (in your application) should be written as:
...
bindings := IdentityDictionar new.
for eachAspect do:[:aspect |
bindings at:#aspectSymbol put:theAspectHolder
].
(SimpleDialog
openDialogInterfaceSpec:(self class specSelectorsName)
withBindings:bindings)
ifTrue:[
...
].
...
i.e. provide all bindings as required by the GUI-dialog in a
single dictionary.
Notice, that in the above case can be used in any context - even if the
invoking object hs no relationship to the ApplicationModel framework.
If the dialog is to be opened from within an applicationModel instance,
you should use the following:
or, shorter:
(self
openDialogInterfaceSpec:(self class specSelectorsName)
withBindings:bindings)
In this case, the opened dialog gets the onvoking application as its
"masterApplication", which means that missing aspects (in the bindings dictionary)
and resources be requested from your application as a fallBack.
(self
openDialogInterface:#specSelectorsName
withBindings:bindings)
The #openDialog*: family of methods all return the value
of the acceptChannel (which need not be provided in the bindings dictionary,
since it is added by SimpleDialog).
Therefore, the code in the ifTrue: clause is evaluated
if the dialog was closed with an OK button.
In seldom cases, a postBuild action is required, to fix things before
the interface is opened (for example, to change certain widget attributes,
which are not controllable via the windowSpec).
To arrange for this callback, use the following code as a guide:
corresponding hook-blocks can be installed as preBuild and postOpen actions.
...
bindings := IdentityDictionar new.
...
dialog := SimpleDialog new.
dialog postBuildBlock:[:builder | .... do whatEver is required ...].
dialog
openFor:self "or nil"
spec:(self class specSelectorsName)
withBindings:bindings)
ifTrue:[
...
].
...
(pretty similar to the #postBuildWith: and #postOpenWith: methods which
are invoked for regular applications.)
For concrete examples in the system, look for senders of "open*withBindings" or references to the SimpleDialog class.
Copyright © 1998 eXept Software AG, all rights reserved