GUI Dev Guide
GUI Dev Guide
Contents
13
Audience ................................................................................................................... 13
Conventions .............................................................................................................. 13
Typographic Conventions ............................................................................. 13
Special Symbols ........................................................................................... 14
Mouse Buttons and Menus .......................................................................... 14
Getting Help .............................................................................................................. 15
Commercial Licensees ................................................................................. 15
Before Contacting Technical Support .............................................. 15
Contacting Technical Support ......................................................... 16
Non-Commercial Licensees ......................................................................... 16
Additional Sources of Information ............................................................................. 17
Smalltalk Tutorial ....................................................................................................... 17
Online Help .................................................................................................. 17
VisualWorks FAQ ......................................................................................... 17
News Groups ............................................................................................... 18
VisualWorks Wiki ......................................................................................... 18
Commercial Publications .............................................................................. 18
Examples ..................................................................................................... 18
Chapter 1
19
UI Painter .................................................................................................................. 20
The Canvas .................................................................................................. 20
The Palette ................................................................................................... 21
GUI Painter Tool ........................................................................................... 21
Resource Finder ........................................................................................................ 23
Menu Editor ............................................................................................................... 24
Image Editor .............................................................................................................. 25
Hot Region Editor ...................................................................................................... 26
Contents
Chapter 2
27
VisualWorks
Contents
Chapter 3
52
Contents
Chapter 4
76
Menus
89
VisualWorks
Contents
Chapter 6
108
Dialogs
131
Custom Views
142
Contents
Configuring Widgets
153
VisualWorks
Contents
Contents
10
VisualWorks
Contents
11
Contents
Index
274
Method Index
282
12
VisualWorks
Audience
This guide assumes that you have at least a beginning familiarity with
object-oriented programming. The description of VisualWorks begins at
an elementary level, with an overview of the system tools and facilities,
and a description of Smalltalk syntax, but does not attempt to be a
tutorial.
For additional help, a large number of books and tutorials are available
from commercial book sellers and on the world-wide web. In addition,
Cincom and some of its partners provide VisualWorks training classes.
Conventions
We have followed a variety of conventions, which are standard in the
VisualWorks documentation.
Typographic Conventions
The following fonts are used to indicate special terms:
Example
Description
template
cover.doc
filename.xwd
13
Example
Description
windowSpec
Edit menu
Special Symbols
This book uses the following symbols to designate certain items or
relationships:
Examples
Description
File ! New
<Return> key
<Select> button
<Operate> menu
<Control>-<g>
<Escape> <c>
14
<Select> button
<Operate> button
<Window> button
VisualWorks
Getting Help
<Select>
3-Button
2-Button
1-Button
Left button
Left button
Button
Right button
<Option>+<Select>
Getting Help
There are many sources of technical help available to users of
VisualWorks. Cincom technical support options are available to users
who have purchased a commercial license. Public support options are
available to both commercial and non-commercial license holders.
Commercial Licensees
If, after reading the documentation, you find that you need additional help,
you can contact Cincom Technical Support. Cincom provides all
customers with help on product installation. For other problems there are
several service plans available. For more information, send email to
[email protected].
The version id, which indicates the version of the product you are
using. Choose Help ! About VisualWorks in the VisualWorks main
window. The version number can be found in the resulting dialog
under Version Id:.
15
The complete error message and stack trace, if an error notifier is the
symptom of the problem. To do so, select copy stack in the error notifier
window (or in the stack view of the spawned Debugger). Then paste
the text into a file that you can send to technical support.
Non-Commercial Licensees
VisualWorks Non-Commercial is provided as is, without any technical
support from Cincom. There are, however, on-line sources of help
available on VisualWorks and its add-on components. Be assured, you
are not alone. Many of these resources are valuable to commercial
licensees as well.
The University of Illinois at Urbana-Champaign very kindly provides
several resources on VisualWorks and Smalltalk:
16
VisualWorks
http://st-www.cs.uiuc.edu/
A Wiki (a user-editable web site) for discussing any and all things
VisualWorks related at:
http://wiki.cs.uiuc.edu/VisualWorks
Smalltalk Tutorial
A new VisualWorks Smalltalk tutorial is availalbe online at:
http://www.cincom.com/smalltalk/tutorial/
The tutorial information is growing, so revisit this site.
Online Help
VisualWorks includes an online help system. To display the online
documentation browser, open the Help pull-down menu from the
VisualWorks main menu bar and select one of the help options.
VisualWorks FAQ
An accumulating set of answers to frequently asked questions about
VisualWorks is being compiled in the VisualWorks FAQ, which
accompanies this release and is available from the Cincom Smalltalk
documentation site.
17
News Groups
The Smalltalk community is actively present on the internet, and willing to
offer helpful advice. A common meeting place is the comp.lang.smalltalk
news group. Discussion of VisualWorks and solutions to programming
issues are common.
VisualWorks Wiki
A wiki server for VisualWorks is running and can be accessed at:
http://wiki.cs.uiuc.edu:8080/VisualWorks
This is becoming an active place for exchanges of information about
VisualWorks. You can ask questions and, in most cases, get a reply in a
couple of days.
Commercial Publications
Smalltalk in general, and VisualWorks in particular, is supported by a
large library of documents published by major publishing houses. Check
your favorite technical bookstore or online book seller.
Examples
There are a number of examples in parcels, installed in the examples
subdirectory, under the VisualWorks install directory. These are referred
to frequently in this document, and provide additional help in
understanding GUI development in VisualWorks.
18
VisualWorks
1
The VisualWorks GUI Environment
The Graphical User Interface (GUI) building framework is what puts the
Visual in VisualWorks. Building a GUI is done by visually selecting,
placing, and arranging widgets on a canvas. We call the process
painting, and the tool you use is the UI Painter. The resulting canvas
specifies the application window.
Once you have designed the GUI, you connect it to your applications
model, so that input to the GUI is passed on to the model, and so that
relevant changes in the model are displayed in the GUI. This connecting
function is handled by a subclass of ApplicationModel specific to your
application. This model is generated by the UI Painter, including stub
methods for many essential aspects of the model, according to attributes
you specify for the GUI elements.
In this document we address the more mechanical aspects of building
and controlling a GUI in VisualWorks. For a lower-level description of how
the application framework works in connection with the rest of your
application, refer to the Application Framework chapter in the
Application Developers Guide.
19
UI Painter
The Visual in VisualWorks emphasizes the graphical approach to
Graphical User Interface (GUI) design and development. This is provided
by the UI Painter.
The UIPainter is initially unloaded from the base image. To load it, load
the UIPainter parcel (Tools ! Load Parcel in the Visual Launcher).
The Painter tool is in three parts:
The Canvas
The Canvas, which starts out blank, is where you place and arrange
widgets to paint your GUI.
20
VisualWorks
UI Painter
The canvas can be resized to define the size of the resulting window, and
settings allow you to specify its initial size when it opens in the
application, and to constrain its maximum and minimum sizes.
The widgets you place on the canvas have a number of properties that
define their appearance and interaction with your applications data
model. Positioning properties determine how the widgets scale or
distribute when the window is resized.
Once you have painted a GUI, you install it in your application. This
writes the canvas definition spec into an interface specification. The
specification is used by the application to open the window. You can also
edit the specification later by reopening it in the UI Painter.
The Canvas <Operate> menu provides configuration commands that are
also available in other parts of the UI Painter, notably those on the GUI
Painter Tool.
The Palette
The Palette has one button for each type of widget. Widgets are the
elements that you can include in a GUI, including simple elements like
labels and buttons, and more complex elements like hierarchical lists and
tables.
To add a component to your canvas, such as an input field, you simply
click on the Input Field icon in the Palette to select it, and then click in the
canvas to place the widget. You can then drag the widget around to
arrange its position relative to other widgets.
To add several copies of the same widget use the sticky widget picker.
Then, each time you click on the canvas you drop another copy of that
widget, without having to return to the canvas each time. To return to
single widget painting, select the not sticky picker.
The Palette also has several buttons for doing some basic widget
organizing, such as aligning and distributing widgets. These operations
are also available on the GUI Painter Tool menus, and in the Canvas
<Operate> menu.
21
While you may have several canvases open at any given time, there is
only one GUI Painter Tool, which is focused on the currently selected
canvas. To operate on another canvas, select it to update the GUI Painter
Tool.
The GUI Painter Tool has menus and buttons for configuring the canvas
and its widgets. These are described throughout this document as the
relevant task is discussed.
On the left is a hierarchical Tree View, the components in the current
canvas. The canvas itself is included at the top of the list, as Main Window.
Below it, indented to show inclusion, are any widgets you have placed on
the canvas. Each widget has a default name, which you may rename to
make more descriptive and useful. Composite parts, which are groups of
widgets, are further indented under the composite.
You can select a widget to configure by either clicking on the widget in the
canvas or in the widget list in the GUI Painter Tool. The widget list is
particularly useful in complex canvases, where a hidden widget may be
overlaid with another widget. It also simplifies selecting a nested widget
for configuration.
The widget list also shows the tab order between widgets for which
tabbing is enabled. Tab order is set from top to bottom. Moving a widget
in the list adjusts its place in the tabbing sequence.
The largest section of the GUI Painter tool is the collection of properties
pages. The specific pages and their contents vary from widget to widget,
but every widget has Basics, Details, Color, and Position pages. Additional
pages are added as required by the currently selected widget.
Common properties are described under Setting Properties in Chapter 2,
Building an Applications GUI. Additional properties are described
individually for each widget in Chapter 9, Configuring Widgets.
Once the canvas has been designed, you install it by clicking the Install
button, or by selecting the Edit ! Install menu item.
22
VisualWorks
Resource Finder
Resource Finder
Canvases, menus, and graphical images are stored in VisualWorks as
resources, and saved as specifications in class methods of the
Application Model. To find resources once they are created, select Browser
! Resources to open the Resource Finder.
Application classes are listed in the left-hand view. You can filter the list
to show tool classes, example classes, and other categories. To do so,
use the View ! All Classes submenu.
An application class can support multiple interfaces, each of which may
involve multiple canvases for the VisualWorks main window, secondary
windows, and dialogs. The right-hand view lists all of the resource
methods for the selected class. Double-click or click Edit to open that
resource in its editor.
23
Menu Editor
The Menu Editor provides an intuitive, visual way of building a menu. The
menu can be added to the GUI either as a standard, drop-down menu on
the menu bar, added to a menu Button widget, or as a pop-up (right-click)
menu to the window area.
Menu commands and buttons are provided for adding an item, adding a
sub-item, and for rearranging items. Sub-items are accessed as submenus off of the parent menu.
Menu levels are indicated by indenting. To change the level of an item,
select it and click on the left or right arrow button. To change the order of
an item, select it and click the up or down buttons.
There are also three properties pages for each menu item. The Basic
page specifies the displayed String menu label, the lookup key and
catalog, if used, the items return value, and its ID, for programmatically
accessing the item. The Details page specifies any modifier keys needed
for the item, the icon for the item, if any, and its help text. The Defaults
page sets the items initial state.
An application frequently needs to modify a menu or the state of its items
while running, either to indicate state or to activate and deactivate items.
Details on how to create menus and control them during runtime are
provided in Chapter 5, Menus.
24
VisualWorks
Image Editor
Image Editor
Your GUI is often enhanced by the inclusion of icons, simple graphics that
indicate a widgets function. Menu items and buttons, for example, are
often clearer with an icon to suggest visually what they do.
VisualWorks includes an Image Editor that you can use to draw an image
pixel by pixel, and then store it in a resource method. The Image Editor is
best suited for producing small images, such as icons and cursor shapes.
To open an Image Editor, choose Tools ! Image Editor in the GUI Painter
Tool or the VisualWorks main window.
Paint the desired image in the scrollable pixel grid. The controls are pretty
standard for simple paint programs.
To make the graphic available to your application, click the Install button,
then specify your application class as the class into which to install the
graphic, and a method name for the graphic. This installs the graphic as a
resource, which you can access in the resources browser. The method is
installed as a class method in a resource protocol of a selected class.
For more about graphics in VisualWorks, refer to Working With Graphics
and Colors in the Application Developers Guide. Instructions for
incorporating a graphic in your applications GUI are provided at relevant
points throughout the rest of this document.
25
Clickable images can give a very modern look to an otherwise dull GUI.
The Click Map widget allows you to add one to your canvase. The Hot
Regions Editor allows you to define clickable regions.
To define hot regions, you load a graphic resource into the Hot Regions
Editor as a back drop. Then, using drawing tools, draw and paint areas to
be included in the region, and specify a message selector to be sent
when the region is clicked.
For detailed instructions, refer to Click Map in Chapter 9, Configuring
Widgets.
26
VisualWorks
2
Building an Applications GUI
27
Painting a Window
You create windows by creating a visual specification using the UI
Painter. The painter tool provides a canvas, on which you arrange
widgets, a palette containing widgets, and a canvas tool, which gives
quick access to a number of common UI layout commands.
To open the Painter, click on the Canvas button in the Main Window
toolbar.
The UI Painter opens with three windows: the GUI Painter Tool (left), the
widget Palette (top right), and the canvas (bottom right).
The canvas is a work area in which you add and arrange visual
components until it looks like the window you want in your application. If
your application uses several windows, you create a separate canvas for
each window in the application. One window will be the main window, and
the rest will be sub-windows.
28
VisualWorks
You paint the blank canvas by placing and arranging widgets on it. To
place a widget, click on a widget in the palette, then move the mouse to
the canvas and click once. A representation of the widget is displayed at
the cursor. Move it where you want the widget, then click again to drop
the widget.
If you want to place several of the same widget on the canvas, select the
Sticky Select button before selecting the widget. Every time you drop one
widget, you can drop another, until you select another widget or reselect
the single-place button.
Setting Properties
Every window and widget has an associated collection of properties. A
few properties are common to all windows and widgets, but most vary
from object to object.
Properties define a variety of visual attributes, such as font, color,
borders, and so on. For some widgets, such as input fields, properties
also indicate the nature of the data to be displayed and how that data is to
be referenced by the application.
Properties are initially set using the Properties Pages in the GUI Painter
Tool while you are constructing the GUI.
29
The name of the property in the application model that represents the
value model for the widget. An instance variable and stub accessor
method for the aspect are created when you select Define for this
widget. The value model is typically a value holder, if the widget
reflects a property within the application model, or an aspect adaptor,
if the widget reflects a property in a separate domain model.
ID
The name of the widget. A default name is provided for each widget,
so you can easily identify it in the list of widgets. If you need to
access this widget programmatically, you also use this name to
identify the widget to the UIBuilder. You may change the default name
to something more descriptive or keep the default name.
Lookup Key
This is the message catalog lookup key. This field is displayed for
widgets that take a label, such as the label, action button, and radio
button. It is displayed when the Show UI for Globalization option is
activated on the UI Options page of the Settings Tool. For additional
information about message catalogs and their use, refer to the
VisualWorks Internationalization Guide (vwintlg.pdf).
Fly-by Help
The Fly-by Help page allows you to specify a String to display if the
user moves the cursor over the widget and pauses. This allows you to
give a hint to the user about what this widget does.
30
VisualWorks
For a new canvas, you need to enter a class name in the Install on Class
field. This can be a new class name or the name of an existing class. For
a new class, you will be asked for the appropriate superclass in a
subsequent dialog.
You must also either enter or select a method selector (message name)
for the specification. The default is windowSpec, which is the standard
name for the main window specification. If you are defining a secondary
window, you should pick another name. Click OK to save the specification.
If you specified a class that does not already exist, you are asked to
select a superclass and a name space for it. For an application, you
typically select ApplicationModel as the superclass. The name space is
typically one created for your application (refer to Name Spaces,
Chapter 6 in the Application Developers Guide, for more information).
31
The ApplicationModel superclass provides support functions for GUIoriented applications, so it is usually the right choice for an application.
SimpleDialog provides support features for dialogs (see Chapter 7,
Dialogs for more information). On the other hand, if the class must be a
subclass of some other class, select Other and enter its name.
The Category field sets the category for the new class. You can use an
existing category or a new category name that better identifies your work.
Reopening a Canvas
When you save the canvas, its specification is added to the resources for
the application. After youve closed the canvas, you can open it again for
editing using the Resource Browser (Browse ! Resources menu item in the
VisualWorks Main Window). In the Resource Browser, select the class
name containing the canvas, then select the specification for the canvas
and click Edit.
You can also select the specification method in a browser, and pick the
Edit Resource item on the <Operator> menu.
To save any changes you make to a canvas, you must reinstall it.
32
VisualWorks
In the list of models, each item that will be defined is marked with a check
mark. To remove the check mark, and so skip that method, click on the
item.
Unchecking an item is important in subsequent define operations,
because redefining will usually overwrite any custom changes you make
to the method.
The Add Initialization checkbox gives a little control over how much code is
generated for aspect methods. Without initialization, the instance variable
for the aspect is simply returned. With initialization, the method tests for
whether the variable has a value, and if not it assigns an initial value. The
type of value assigned depends on the widget.
GUI Developers Guide
33
Once the stub methods are generated, you can edit them to provide the
specific processing your application needs. For example, to connect the
UI to its domain model, you must redefine some aspect methods to use
aspect adaptors. Refer to Chapter 4, Adapting Domain Models to
Widgets for more information.
Formatting a Canvas
The following sections describe operations for formatting and arranging
widgets, to adjust how the window will appear in the application. Most of
the operations are performed in the canvas while assembling the GUI.
Some formatting can be set or changed programmatically, while the
application is running. Instructions are provided for doing this along with
the canvas instructions. For general instructions for accessing widgets
from a running application using the widgets ID, see Chapter 3,
Controlling the GUI Programmatically.
34
VisualWorks
Formatting a Canvas
At the bottom of are three sets of height and width dimensions. The
Specified dimensions give the default opening size. To set this to the
dimensions that you have sized the canvas, simply click the Specified
button, and the current dimensions are filled in. You may enter other
dimensions if you prefer.
It is also frequently useful to constrain a window to a certain size, so that
a user cannot change its size to larger or smaller than certain
dimensions. This is useful when the interface becomes unusable outside
of a range of values. These dimensions are provided by the Minimum and
Maximum dimensions. You can enter precise dimensions, but it is easier to
resize the canvas to the smallest usable size and click the Minimum
button. Similarly, resize the canvas to the largest desireable size, and
click the Maximum button.
If you allow the window to be resized, you will also want to decide how
widgets are sized. Refer to Sizing a Widget on page 38 for directions on
controlling widget sizes.
35
Cascade: Each time the window opens below and to the right of where it
last opened. This is useful especially if several copies of the window can
open in succession.
Specified Position: Opens with the top left corner at the specified
screen coordinate.
After selecting the option, Apply the change and Install the canvas.
On the Basics properties page, turn on the Enable switch for the Menu
Bar property.
You can use the Menu Editor to create the menu either before or after
enabling the canvas. Each first-level entry in the menu appears in the
menu bar, but only if it has a submenu.
36
VisualWorks
Formatting a Canvas
Foreground
Background
Selection foreground
Selection background
On the Color properties page, you can apply a color to any of these zones.
By default, each zone is set to none, which means that the window or
widget inherits its colors. A window inherits the platform window
managers colors, and widgets inherit from either a containing widget or
the window. Unless you specifically want to highlight some feature of the
GUI, you should leave all color selections at their default.
When you do select colors, be sensitive to good taste (unlike the above
example). Also, be aware that some forms of color blindness made
certain combinations useless. For example, many people cannot
distinguish between red and green, so a red foreground on a green
background ought to be avoided.
GUI Developers Guide
37
To change a color:
1
In a canvas, select the window or widget whose color you want to set.
On the Color properties page, select the desired color from the color
chart.
Sizing a Widget
These lists . . .
In the canvas, you can set a widgets size by dragging its selection
handles, stretching or shrinking the widgets dimensions.
You can make the widgets in a multiple selection all equal in height,
width, or both, using the Arrange ! Equalize... command in the GUI Painter
Tool menu. There are also buttons on the Palette for doing these
operations.
Widgets appear in their painted size when the window is opened. When
the window size is fixed, nothing more normally needs to be done.
However, when the windows size is variable, you may want to arrange for
the widget to adjust its size in relation to that of the window. You can use
the Layout ! Relative command on the Canvas Tool to arrange for
automatic resizing in both the vertical and the horizontal dimensions.
For more complicated situations, or for more precise control, you can set
properties on the Position properties page, as described in the following
sections.
38
VisualWorks
Formatting a Canvas
Set the Right Offset to the width of the widget added to the Left
Offset.
Set the Bottom Offset to the height of the widget added to the Top
Offset.
Set the Right Offset to the distance you want between the widgets
right edge and the imaginary line identified by the Right Proportion.
Set the Bottom Proportion to a value that is larger than the Top
Proportion.
Set the Bottom Offset to the distance between the widgets bottom
edge and the imaginary line representing the Bottom Proportion.
39
Positioning a Widget
The basic way to set a widgets position is by dragging it to the desired
position in the canvas. This determines the widgets initial position relative
to the windows upper left corner.
Widgets appear in their painted position when the window is opened.
When the window size is fixed, nothing more normally needs to be done.
However, when the windows size is variable, you may want to arrange for
the widget to adjust its position relative to the size of the window. You can
use the Layout ! Relative command on the GUI Painter Tool to arrange for
automatic repositioning in both the vertical and the horizontal dimensions.
Buttons are available on the Palette for the same operation.
For more complicated situations, or for more precise control, use the
settings on the Position properties page.
VisualWorks
Formatting a Canvas
Online example: Size1Example (start it and then resize the window to see
the effect)
1
On the Position properties page, set the Left and Top Proportions to 0.
These proportions control whether a widget moves relative to the
window size. Setting these properties to 0 causes the widgets origin
to remain fixed in place.
Set the Left Offset to the desired distance between the windows left
edge and the widgets left edge (in the example, 50 pixels).
Set the Top Offset to the desired distance between the windows top
edge and the widgets top edge (50).
On the Position properties page, set the Left Proportion to the fraction
of the windows width from which the Left Offset is to be measured.
(In the example, a left proportion of 0.5 causes the widget to remain
anchored at the windows midline.)
Set the Left Offset to the distance you want between the widgets left
edge and the imaginary line identified by the Left Proportion (50
pixels).
Set the Top Proportion to the fraction of the windows height from
which the Top Offset is to be measured. (In the example, a top
proportion of 0 anchors the widgets top edge at the top edge of the
window, which is the same as keeping the origin fixed in the vertical
dimension.)
41
Set the Top Offset to the distance you want between the widgets top
edge and the imaginary line identified by the Top Proportion (50
pixels).
42
Set the Y Proportion to the fraction of the widgets height at which the
reference point is to be positioned (0).
Set the X Proportion to the fraction of the windows width at which the
widgets reference point is to be anchored. (In the example, an X
Proportion of 0.25 keeps the widgets reference point anchored onefourth of the way across the window.)
Set the X Offset to the distance you want between the widgets
reference point and the imaginary line identified by the X proportion
(0).
Set the Y Offset to the fraction of the windows height at which the
widgets reference point is to be anchored. (In the example, a Y
proportion of 0 keeps the widgets reference point a fixed distance
from the windows top edge.)
VisualWorks
Formatting a Canvas
Grouping Widgets
Windows frequently have clusters of widgets that work closely together.
Such clusters are usefully dealt with, for formatting purposes, as a single
object. For this purpose, the widgets can be formed into a group.
Once grouped, the whole group can be moved on the canvas, retaining
its arrangement.
In the widgets list in the GUI Painter Tool, notice that a new pseudowidget, Composite1 (or some higher increment if there are already
composites) is added to the list. The component widgets are listed under
it and indented. The list can be collapsed or expanded as desired, to hide
or show the component widgets.
To ungroup a group of widgets, select Arrange ! Ungroup.
Aligning Widgets
43
described below. There are also a set of alignment buttons on the Palette,
giving quick access to the alignment functions. You can also use the
Position properties page to precisely position widgets, but would usually
choose to do so only due to scaling consideration
1
In the GUI Painter Tool or the Canvas <Operate> menu, select the
Arrange ! Align command.
In the Align dialog, select first selection when the widgets are to be
aligned with the first widget that was selected. Select merged box to
align the widgets on a line halfway between the two most extreme
positions within the group of widgets.
Distributing Widgets
44
In the GUI Painter Tool or Canvas <Operate> menu, select the Arrange
! Distribute command.
In the Distribute dialog, select left to right for widgets that are to be
spaced in a horizontal row. Select top to bottom for columnar
distribution.
VisualWorks
Formatting a Canvas
In the Distribute dialog, select the type of spacing. For constant spacing
between edges, you must specify the number of pixels to place between
each pair of widgets.
System, for a font that matches the current platforms system font,
when available. The font varies depending on platform and Look
policy. (Defined in the Look Policy classes.)
Default, for the default font for the widget. The font varies with the Look
The drop-down lists under Pixel and Standard also list any Named Fonts
you have defined.
Named Fonts
VisualWorks does not automatically add all fonts on your system to the
fonts list. However, you can selectively add these fonts and assign them a
name for use by name. Once defined, a named font is added to the fonts
list in the GUI Painter and other utilities.
45
Open the Named Fonts tool from the GUI Painter Tool, either by clicking
the Define Named Fonts button or selecting Edit ! Define Named Fonts.
Click Add New Named Font, and enter a descriptive name in the
prompter.
The named font can now be assigned to a text widget or field by selecting
it on the Details page.
The named font definitions are saved in the image the next time you save
it. You may also either file out the definitions using File ! Named Fonts !
File Out... in the GUI Painter Tool.
More importantly, you can install the named fonts into your application by
selecting File ! Named Fonts ! Install In Application... in the GUI Painter
Tool. This option adds a definedNamedFonts instance method to your
application model. Note that this option is only available when the current
application has already been installed.
46
VisualWorks
Use these buttons to shuffle the widgets to the desired tab order.
For composite parts, arrange the tabbing order within the group. Then,
move the group to the appropriate position.
47
48
Tell the builder which object will supply its menus, aspects, and other
resources by sending it a source: message. The argument is typically
the application model itself. (Alternatively, you can send a series of
aspectAt:put: messages to install the resources directly.)
Create the spec object and add the spec to the builder.
VisualWorks
openFinder
"Open the Search window. If already open, raise to top."
| bldr |
(self finderBuilder notNil and: [self finderBuilder window isOpen])
ifTrue: [self finderBuilder window raise]
ifFalse: [
self finderBuilder: (bldr := UIBuilder new).
bldr source: self.
bldr add: (self class
interfaceSpecFor: #finderSpec).
bldr window
application: self;
beSlave.
self adjustSearchScope.
self searchStatus value: 0.
(bldr componentAt: #searchStatus) widget
setMarkerLength: 5.
bldr openAt: (self
originFor: bldr window
nextTo: #findButton)].
(self wrapperAt: #listView) takeKeyboardFocus.
Ask the window to open with a specified size (extent), by sending the
window an openWithExtent: message.
| bldr win |
bldr := Editor2Example new allButOpenInterface: #windowSpec.
win := bldr window.
win openWithExtent: 500@220.
49
50
VisualWorks
changeRequest
^super changeRequest
ifFalse: [false]
ifTrue: [(self modified or: [self magnifiedBitView controller
updateRequest not])
ifTrue:
[Dialog confirm: 'The image has been altered, but not installed.
Do you wish to discard the changes?']
ifFalse: [true]]
Notice also in the example that the inherited version of changeRequest is
first invoked to preserve any precautions that a parent class may have
implemented.
Hiding a Window
A window is a relatively expensive object, because it holds a visual
component that is often bulky and because it allocates a display surface
using the window manager. When your application needs to open and
close a window repeatedly, it is not necessary to reconstruct it each time.
Instead, you can unmap it, which hides the window without disassembling
it. Then you can simply map it to redisplay it.
| win |
win := (Editor2Example open) window.
win display.
(Delay forSeconds: 1) wait.
win unmap.
(Delay forSeconds: 1) wait.
win map.
All windows also respond to an isMapped message, and keep their
mapped state as a Boolean in their mapped instance variable.
51
3
Controlling the GUI Programmatically
VisualWorks
Accessor Methods
The following methods allow easy lookup of widgets and widget
components without having to go through the applications builder object.
We suggest using these messgage instead of the self builder messages
commonly used in VisualWorks applications.
wrapperAt: aSymbol
Answer the value of the named component at aSymbol. Typically gets
a SpecWrapper or nil. In the case of a toolbar, it gets the actual ToolBar
instance. This method is the ApplicationModel direct replacement for
messages of the form:
self builder componentAt: aSymbol.
controllerAt: aSymbol
Answers the controller for the component associated with aSymbol.
The answer may be nil or a Controller. In the case of a toolbar, it will
be nil. This method is the ApplicationModel direct replacement for
messages of the form:
(self builder componentAt: aSymbol) controller.
widgetAt: aSymbol
Answer the widget associated with aSymbol. Typically answers a kind
of VisualPart, which may be nil. This method is the ApplicationModel
direct replacement for messages of the form:
(self builder componentAt: aSymbol) widget
mainWindow
Answer the main window associated with this ApplicationModel
instances. Typically answers a ApplicationWindow. May be nil if the
window is not created yet. This method is the ApplicationModel direct
replacement for messages of the form:
self builder window
windowMenuBar
Answers the instance of MenuBar associated with the main window.
May be nil if the window is not mapped and opened, or if there is no
menu bar associated with the main window.
53
Accessing a Window
Getting an Application Window
Your application code can manipulate the window programmatically by
obtaining the window from the application model and then sending it
messages. To get the main window, send a mainWindow message to the
application instance. For example, to get an applications window and
change its label, do:
| app win |
app := Editor2Example new.
app open.
win := app mainWindow.
win label: 'Editor'.
54
VisualWorks
Accessing a Window
| win |
win := ScheduledControllers
activeController view topComponent.
win moveTo: 20@20.
cursor
location
55
56
VisualWorks
57
Creating an Icon
An icon is an instance of Icon, and consists of an image (figure) and a
mask (shape), both of which are instances of CachedImage. The icon may
also be registered in the Icon class IconConstants dictionary.
To create an icon with a mask, send a figure:shape: message to an
instance of Icon, specifying the image and mask:
58
VisualWorks
| myIcon |
myIcon := Icon new
figure: VisualLauncher CGHelp24
shape: VisualLauncher CGHelp24Mask.
myIcon cleanFigure.
(The mask does not exist in the example, but can be created easily using
the Image Editor.)
If either the image or mask is an instance of Image, not CachedImage, send
asCachedImage to the image when assigning it to figure or shape.
The cleanFigure message is needed for color icons, to clean up some odd
behavior on Windows systems, and may not be required in all cases.
Registering an Icon
Icons that are reused frequently can be registered with the Icon class,
which stores icons in a dictionary.
To register an icon, send constantNamed:put: to the Icon class, with a
symbol for its name and the icon as arguments:
| myIcon |
myIcon := Icon new
figure: VisualLauncher CGHelp24
shape: VisualLauncher CGHelp24Mask.
myIcon cleanFigure.
Icon constantNamed: #HelpIcon put: myIcon
To later retrieve the icon, send constantNamed: to the Icon class:
| win |
win := ScheduledWindow new.
win icon: ( Icon constantNamed: #HelpIcon).
win open
Installing an Icon
Instances of ScheduledWindow and its subclasses store an icon in their
icon instance variable. To set an icon for a window, send an icon:
message to the window with the icon to use:
| win |
win := ScheduledWindow new.
win icon: ( Icon constantNamed: #HelpIcon).
win open
Windows other than instances of ScheduledWindow or its subclasses do
not hold onto the icon, and must ensure that the icon persists as long as
the window does. Registering the icon is sufficient.
59
Tell the slave window which application model will relay events from
the master window.
60
VisualWorks
| win1 win2|
win1 := ( Editor1Example new ) openInterface; mainWindow.
win1
label: 'Partner 1';
application: app;
bePartner.
win2 := (Editor2Example new) open; mainWindow.
win2
label: 'Partner 2';
application: app;
bePartner.
61
| masterWin slaveWin |
masterWin := ( Editor1Example new ) openInterface; mainWindow.
masterWin
label: 'Master';
application: app;
beMaster.
slaveWin := (Editor2Example new ) open; mainWindow.
slaveWin
label: 'Slave';
application: app;
beSlave;
receiveWindowEvents: #( #close).
Window Events
Unlike widgets, Windows and Dialogs trigger many events that are
directly related to Platform Operating System window events. Because of
this, not all events are triggered on all platforms. Therefore it is suggested
that you test your windows on all target platforms to assure that the
events you are registering for happen when and how you expect.
Windows and Dialogs also trigger events that are not coming in from the
platform operating system, these VisualWorks based events are available
to all Windows, without regard to the underlying operating system.
Platform based events are marked with the initial tag (Platform) in their
description. VisualWorks based events are marked with the initial tag
(VisualWorks) in their description.
An ApplicationModel can access the Window or Dialog by sending the
new #mainWindow message to itself. Once the window is in hand, the
developer can then set up its when:send:to: registration methods.
#activate
(Platform) When the underlying platform sends an activate
notification event to a VisualWorks window, the window triggers the
#activate event. On some platforms, only the enter event is sent.
#bounds
(Platform) When the underlying platform changes the size of the
VisualWorks window and sends the bounds notification event, the
window triggers the #bounds event.
#close
(Platform) When the underlying platform sends a close notification
event to a VisualWorks window, the window triggers the #close event.
62
VisualWorks
Window Events
#collapse
(Platform) When the underlying platform sends a collapse notification
event to a VisualWorks window, the window triggers the #collapse
event.
#deactivate
(Platform) When the underlying platform sends a deactivate
notification event to a VisualWorks window, the window triggers the
#deactivate event. On some platforms, only the exit event is sent.
#destroy
(Platform) When the underlying platform sends a destroy notification
event to a VisualWorks window, the window triggers the #destroy
event.
#enter
(Platform) When the underlying platform sends an enter notification
event to a VisualWorks window, the window triggers the #enter event.
#expand
(Platform) When the underlying platform sends an expand notification
event to a VisualWorks window, the window triggers the #expand
event.
#expose
(Platform) When the underlying platform sends an expose notification
event to a VisualWorks window, the window triggers the #expose
event.
#exit
(Platform) When the underlying platform sends an exit notification
event to a VisualWorks window, the window triggers the #exit event.
#move
(Platform) After a window is moved, the underlying platform sends a
move notification event to a VisualWorks window, the window in
response triggers the #move event.
#resize
(Platform) When the underlying platform sends a resize notification
event to a VisualWorks window, the window triggers the #resize event.
#unknownEvent
(Platform) There are many raw events that come into a VisualWorks
window from the underlying operating system. Any operating system
event that arrives at a VisualWorks window that VisualWorks does
not otherwise handle, is always sent to the main window as an
UnknownEvent. There are many ways of trapping these otherwise
unhandled events in the GUI framework. This event is triggerd as a
63
VisualWorks
Window Events
widget that handles the event, will cause the window to trigger the
#click event. This event is not triggered in the Menubar or Toolbar
areas. Labels and ViewHolders are examples of widgets that do not
handle mouse clicking, and for these, the underlying window will
trigger the #clicked event.
#rightClicked
(VisualWorks) As with the #clicked event, any window which is clicked
with the <Operate> mouse button on any area where there is not
another widget that handles the event, will cause the window to
trigger the #rightClicked event. This event is not triggered in the
Menubar or Toolbar areas. Labels and ViewHolders are examples of
widgets that do not handle mouse clicking, and for these, the
underlying window will trigger the #clicked event.
#doubleClicked
(VisualWorks) As with the #clicked event, any window which is double
clicked with the <Operate> mouse button on any area where there is
not another widget that handles the event, will cause the window to
trigger the #doubleClicked event. This event is not triggered in the
Menubar or Toolbar areas. Labels and ViewHolders are examples of
widgets that do not handle mouse clicking, and for these, the
underlying window will trigger the #doubleClicked event.
#middleClicked
(VisualWorks) As with the #clicked event, any window which is clicked
with the <Window> mouse button on any area where there is not
another widget that handles the event, will cause the window to
trigger the #middleClicked event. This event is not triggered in the
Menubar or Toolbar areas. Labels and ViewHolders are examples of
widgets that do not handle mouse clicking, and for these, the
underlying window will trigger the #middleClicked event. Windows and
Dialogs are the only visual objects in VisualWorks that trigger this
event.
#scrollLeft
(VisualWorks) If a window has horizontal scroll bars, and the window
view is made to scroll to the left, the window triggers the #scrollLeft
event.
#scrollRight
(VisualWorks) If a window has horizontal scroll bars, and the window
view is made to scroll to the right, the window triggers the #scrollRight
event.
65
#scrollUp
(VisualWorks) If a window has vertical scroll bars, and the window
view is made to scroll up, the window triggers the #scrollUp event.
#scrollDown
(VisualWorks) If a window has vertical scroll bars, and the window
view is made to scroll down, the window triggers the #scrollDown
event.
#menuBarCreated
(VisualWorks) At the time an ApplicationModel receives the
#postBuildWith: message, no menu bar has been created. This makes
it hard to register to a menu bar's events in the postBuildWith: method.
The developer has two choices, either register to a menu bar's events
in the postOpenWith: message, or register with the window's
#menuBarCreated event and do menu bar event registration at that
time. Once a menu bar is created, it can be access by the new
windowMenuBar method of the ApplicationModel.
#toolBarCreated
(VisualWorks) As with the menu bar, at the time an ApplicationModel
receives the postBuildWith: message, no tool bar has been created.
This makes it hard to register to a tool bar's events in the
postBuildWith: method. The developer has two choices, either register
to a menu bar's events in the postOpenWith: message, or register with
the window's #menuBarCreated event and do menu bar event
registration at that time. Once the tool bar is created, it can be
accessed by the widgetAt: method using the ID of the tool bar as
defined in the window properties page of the UIPainter tool.
Controlling Widgets
It is often useful for an application to be able to access the widgets in its
windows. Depending on the purpose of the access, a widget may be
accessed directly or through its wrapper. In either case, the widget is
identified by its ID, which is set in the Properties Tool in the Canvas.
Accessing a Widget
In a System Browser, edit a method in the application model (in this
example, alignCenter) so that it sends a widgetAt: message to the
application model. The argument is the ID.
66
VisualWorks
Controlling Widgets
alignCenter
| widget style |
widget := self widgetAt: #comment .
style := widget textStyle copy.
style alignment: 2.
widget textStyle: style.
widget invalidate.
67
Create a rectangle having the desired origin and extent, using the
widgets bounding rectangle to derive the new values.
68
Get the label from the widget by sending a label message; get the text
of the label by sending a text message to it. Then install a blank text
VisualWorks
Controlling Widgets
Hiding a Widget
Sometimes a widget is useful only under certain conditions and needs to
be hidden at other times to avoid confusing the user of your application.
Action buttons need to be hidden when their actions are not appropriate.
A widget may also be hidden when two alternative widgets are layered on
top of each other. For example, the Online Documentation window uses a
text editor on top of a list editor and hides the view that is unneeded at
any given time.
You can turn on a widgets Initially Invisible property to cause the widget to
be hidden when the window opens. You can also program the application
model to hide and show the widget while the application is running.
Online example: HideExample
69
changedListVisibility
| wrapper desiredState |
wrapper := self wrapperAt: #colorList.
desiredState := self listVisibility value.
desiredState == #hidden
ifTrue: [wrapper beInvisible].
desiredState == #disabled
ifTrue: [
wrapper beVisible.
wrapper disable].
desiredState == #normal
ifTrue: [
wrapper enable.
wrapper beVisible].
Disabling a Widget
Sometimes a widget is useful only under certain conditions, but making it
invisible would be confusing to the user of your application. You can
disable a widget, causing it to be displayed in gray. In addition, its
controller is inactivated so the widget does not respond to user input.
Action buttons are frequently grayed out when not needed.
You can turn on a widgets Initially Disabled property to cause the widget to
be disabled when the window opens. You can also program the
application model to disable and enable the widget while the application
is running.
Online example: HideExample
70
VisualWorks
Controlling Widgets
changedListVisibility
| wrapper desiredState |
wrapper := self wrapperAt: #colorList.
desiredState := self listVisibility value.
desiredState == #hidden
ifTrue: [wrapper beInvisible].
desiredState == #disabled
ifTrue: [
wrapper beVisible.
wrapper disable].
desiredState == #normal
ifTrue: [
wrapper enable.
wrapper beVisible].
Get the LookPreferences from the wrapper and create a copy with the
desired color. The copy is created when a color-zone message is
sent: foregroundColor:, backgroundColor:, selectionForegroundColor:, or
selectionBackgroundColor:. The argument is the desired new color.
71
You can also bypass the dependency when unusual circumstances arise.
For example, when two widgets depend on each other, one of them must
bypass the dependency mechanism to avoid infinite recursion.
Adding a Dependency
Online example: DependencyExample
In the application models initialize method (typically), send an
onChangeSend:to: message to the widgets value holder. The first argument
is a message, which will be sent to the second argument. The second
argument is typically the application model itself.
initialize
colorNames := SelectionInList with: ColorValue constantNames.
selectedColor := String new asValue.
fieldIsDependent := false asValue.
"Arrange for the application model to take action when the
check box is turned on or off."
fieldIsDependent
onChangeSend: #changedDependency to: self.
After the value has been changed, register the interest again.
changedDependency
"Turn on or off the dependency link between the list and
the input field, depending on the value of the check box."
| valueModel |
valueModel := self colorNames selectionIndexHolder.
self fieldIsDependent value
ifTrue:
[valueModel onChangeSend: #changedSelection to: self]
ifFalse:
[valueModel retractInterestsFor: self].
72
VisualWorks
Controlling Widgets
Get the widget from the application model and ask the widget to
update itself with the new value.
changedB
"Use setValue: to bypass dependents, thus avoiding circularity."
self bSquared setValue: (self b value raisedTo: 2).
"Since dependents were bypassed when the model was updated,
update the view manually."
(self widgetAt: #b2) update: #value.
Validation Properties
Frequently, only certain entries are valid for a particular widget. For
example, you might want to restrict input accepted by an input field to a
numeric range from 0 to 999, or check for incompatible checkbox
selections.
Validation properties specify messages a widget sends to its application
model asking for permission to proceed. In this way, validation provides
input flow control, for example, to prevent the user from entering invalid
data into an input field, or to prevent the user from entering a field before
filling in other prerequisite fields.
73
Property
Description
Entry
Change
Exit
D. Click
Validation methods, which you add to the application model, return either
true or false. On true, the widget proceeds with its action; on false, the
widget waits for new, valid input. You can implement the validation
method to redirect input focus or to disable and enable input widgets.
To create a validation method that inspects the widgets value, specify a
selector with a colon (selector:). The widget passes its controller object as
the argument to the method. The method can then ask the controller for
the widgets value. For certain widgets (input fields, text editors, and
combo boxes), you use statements such as the following to get and set
values through the controller:
input := aController editValue
Notification Properties
You specify Notification properties when you want a widget to inform its
application model that certain actions have taken place, namely, that the
widget has taken focus, changed internal state, or given up focus.
Notification properties are useful for facilitating complex flow of user
input.
Each notification property specifies the symbolic name of a notification
callback, which is the message you want the widget to immediately send
after the relevant action. For each notification callback you specify, you
74
VisualWorks
Controlling Widgets
Property
Description
Entry
Change
Exit
D. Click
75
4
Adapting Domain Models to Widgets
76
VisualWorks
77
initializeID
accountID := 0 asValue.
accountID onChangeSend: #changedID to: self.
Send a newString message to the ValueHolder class. This is equivalent to
the expression String new asValue, and the choice of which to use is a
matter of personal preference.
initializeName
name := ValueHolder newString.
name onChangeSend: #changedName to: self.
Send a newBoolean message to the ValueHolder class. This is equivalent to
the expression false asValue.
Send a newFraction message to the ValueHolder class. This is equivalent to
the expression 0.0 asValue.
aspect
Data widgets are commonly used for presenting data that is held by some
object in the application, such as a domain model. In such cases, the
appropriate value model is an AspectAdaptor, which is conceptually a
pointer to the remote data. An aspect adaptor has a subject, which is the
relevant domain model, and an aspect, which is the name of the instance
variable that holds the relevant data. An aspect adapter translates the
value and value: messages it receives into accessor and mutator
messages that are understood by its subject.
Subject channel: You can set up an aspect adaptor so that it obtains its
subject from a value holder, called a subject channel. A subject channel
provides indirect access to the subject, allowing you to programmatically
introduce a new subject for an existing aspect adaptor. This is useful
when you want particular data widget to display data held by successive
domain model instances.
78
VisualWorks
Defining an Adaptor
Online example: Adaptor2Example
This example shows how to set up an aspect adaptor with a subject
channela value holder from which the aspect adaptor will obtain its
subject.
1
Tell the aspect adaptor which aspect of the domain model to monitor
by sending a forAspect: message to the adaptor. The argument is a
Symbol, typically the name of the desired instance variable (accountID)
in the domain model.
initialize
customers := SelectionInList new.
customers selectionIndexHolder
onChangeSend: #changedCustomer to self.
selectedCustomer := Customer1Example new asValue
accountID
| adaptor |
adaptor := AspectAdaptor subjectChannel: self selectedCustomer.
adaptor forAspect: #accountID.
adaptor onChangeSend: #redisplayList to: self.
^adaptor
79
80
VisualWorks
81
82
VisualWorks
For each widget in the series, place the widgets value model in a
BufferedValueHolder by sending a subject:triggerChannel: message to the
BufferedValueHolder class. The first argument is the widgets value
model (in the example, an AspectAdaptor). The second argument is
the trigger channel (updateTrigger). This is typically done when the
widgets value model is initialized. Note that the buffered value holder
does not replace the widgets value modelrather, it contains that
value model.
accountID
| adaptor bufferedAdaptor |
adaptor:= AspectAdaptorsubjectChannel:self selectedCustomer.
adaptor forAspect: #accountID.
bufferedAdaptor := BufferedValueHolder
subject: adaptor
triggerChannel: self updateTrigger.
^bufferedAdaptor
83
accept
self updateTrigger value: true.
self redisplayList.
84
VisualWorks
Collection of customers
SelectionInList
85
86
VisualWorks
The getBlock: controls what happens when a value is fetched from the
model by the widget. In the example, the block translates the models
account number into a zero-padded string.
87
88
VisualWorks
5
Menus
Creating a Menu
You can create a menu either using the Menu Editor, or programmatically.
With the Menu Editor, you can create menus of messages or values. If a
more complex action is required, such as a compound message or an
action block, you can assemble the menu programmatically.
Complex actions are necessary, for example, for assigning a value to a
value holder from a menu bar or pop-up menu, or executing a command
from a button menu.
89
Chapter 5 - Menus
The Menu Editor provides both menu selections and buttons for several
design operations. In the following instructions, we refer to the menu
selections, but the button equivalent can be used.
Online example: MenuEditorExample
1
Add a top-level menu by selecting Edit ! New Item, and edit its
properties.
When you add a menu item, it is displayed as <new item>. Edit this
label in the Label Default property, giving the menu item the label you
want displayed.
To include a mnemonic for the menu item, insert an ampersand (&)
character in the label before the letter to use as the mnemonic. For
example, I&tem makes t the mnemonic letter for the item, and is
indicated in the menu by underlining the letter.
Subsequent uses of Edit ! New Item add items at the same level as
the selected item.
The new item is placed below and indented from the selected item.
90
VisualWorks
Creating a Menu
91
Chapter 5 - Menus
For each menu item, send an add: message to the menu builder with
an association as the argument.
The association relates the menu items label string and the block
that performs the required action. For value and command menus,
the value holder or message selector occur, as symbols, in place of
the block.
To include a mnemonic for the menu item, insert an ampersand (&)
character in the label before the letter to use as the mnemonic. For
example, I&tem makes t the mnemonic letter for the item, and is
indicated in the menu by underlining the letter.
To add a shortcut key sequence for the menu item, which displays on
the menu, specify the character key and the modifier key or keys.
(Note that this is not illustrated in the example code.)
For example, to specify <Ctrl>+<Shift>+A as the shortcut, add these
lines:
menuItem shortcutKeyCharacter: $A.
menuItem shortcutModifiers:
(InputState ctrlMask bitOr: InputState shiftMask).
The modifier keys can be specified individually (ctrlMask, shiftMask, or
altMask), or combined using bitOr: as shown above.
92
VisualWorks
Get the menu from the menu builder using a menu message and
return it as the result of the menu-creating method.
In this example, all menu items are added within a submenu. This is
necessary here because the menu is being added to the menu bar. The
submenu label is displayed in the menu bar.
The example also illustrates adding graphics and color programmatically.
templatesMenuForMenuBar
| mb menu submenu |
mb := MenuBuilder new.
mb
beginSubMenuLabeled: 'Templates';
add: ' ' -> [self letter value: self class firstNotice];
add: ' ' -> [self letter value: self class secondNotice];
add: ' ' -> [self letter value: self class finalNotice];
endSubMenu.
"Add graphic labels."
menu := mb menu.
submenu := (menu menuItemLabeled: 'Templates')
submenu.
(submenu menuItemAt: 1)
labelImage: (self class oneImage).
(submenu menuItemAt: 2)
labelImage: (self class twoImage).
(submenu menuItemAt: 3)
labelImage: (self class threeImage).
"Set the background color."
submenu backgroundColor: ColorValue chartreuse.
^menu
93
Chapter 5 - Menus
In a Properties Tool, turn on the Enable switch for the Menu Bar
property.
Create the menu definition resource method that you named in step
3, and any action methods that are invoked by the menu items.
menu button
94
VisualWorks
pop-up menu
Several widgets, notably lists and text editors, provide a pop-up menu in
response to the <Operate> mouse button.
The underlying menu is typically a menu of commands, sending the
associated symbol as a message to the application model.
Online example: MenuCommandExample
1
In the Menu property of the widget, enter the name of the menu
creation resource method (fileMenu).
Create the menu creation resource method (fileMenu), and any action
methods named in the menu of commands.
In the Menu property of the widget, enter the name of the method that
returns a menu of values (templatesMenuForPopUp).
95
Chapter 5 - Menus
| mb |
mb := MenuBuilder new.
mb
add: 'First Notice' -> [self letter value: self class firstNotice];
add: 'Second Notice' -> [self letter value: self class
secondNotice];
add: 'Final Notice' -> [self letter value: self class finalNotice].
^mb menu
Get the menu by sending a menuAt: message to the builder, with the
name of the menus resource method as argument.
name key (ID), by sending atNameKey: to the menu with the name
key as a symbol as the argument.
96
VisualWorks
configureMenu
"Disable or enable the menu items depending on whether
a file is selected."
| menu submenu |
menu := self builder menuAt: #fileMenu.
submenu := (menu menuItemLabeled: 'File') submenu.
self files selection isNil
ifTrue: [
(submenu menuItemLabeled: 'Open') disable.
(submenu menuItemLabeled: 'Delete') disable]
ifFalse: [
(submenu menuItemLabeled: 'Open') enable.
(submenu menuItemLabeled: 'Delete') enable]
It is simple to create its interface using the Menu Editor and assign ID
properties to the File menu and its items. The equivalent configureMenu
method could then be written (assuming the ID properties are the same
as the labels):
configureMenu
"Disable or enable the menu items depending on whether
a file is selected."
| menu submenu |
menu := self builder menuAt: #fileMenu.
submenu := (menu atNameKey: #File) submenu.
self files selection isNil
ifTrue: [
(submenu atNameKey: #Open) disable.
(submenu atNameKey: #Delete) disable]
ifFalse: [
(submenu atNameKey: #Open) enable.
(submenu atNameKey: #Delete) enable]
As a variation on this theme, you can operate on a collection of menu
items. In MenuEditorExample, the disableDarkColors method gets the menus
collection of menu items by sending a menuItems message to the menu. It
then sends a nameKey message to each menu item to obtain its name key,
and disables each menu item whose name key is in the darkColors array.
97
Chapter 5 - Menus
98
VisualWorks
To hide the item, send a hideItem: message to the menu, with the
menu item as the argument.
99
Chapter 5 - Menus
100
In the Menu property of the widget, enter the name of a method that
returns a value holder containing a menu (menuHolder).
VisualWorks
In the initialize method, get the starting menu, put it in a value holder,
and assign the holder to the instance variable.
initialize
colors := SelectionInList with: ColorValue constantNames.
colors selectionIndexHolder onChangeSend: #selectionChanged to:
self.
menuHolder := self nothingSelectedMenu asValue.
on/off indicator
101
Chapter 5 - Menus
102
VisualWorks
103
Chapter 5 - Menus
104
VisualWorks
To insert a new item between existing items, use a fractional part. For
example, using 10.025 would insert a new menu item between the
existing second and third items. Using 10.04 would append an item to the
group.
105
Chapter 5 - Menus
myMenuItem
<menuItem: My new action
nameKey: nil
menu: #(#listMenu)
position 40.1>
Since no icons are involved, this shorter version of the menu item pragma
can be used.
106
VisualWorks
#submenuClosed:
When a menu item has a sub-menu, and that sub-menu is closed
because of navigation by the keyboard or mouse, or a sub-menu item
being selected, the menu bar triggers the #submenuOpened: event.
The ID (menuKey) of the menu is sent as a parameter of this event if it
is defined. If no ID (menuKey) is defined, then nil is sent as the
parameter.
Toolbar Events
Toolbars have a simple event interface, that only triggers when one of the
tool bar buttons is pressed.
#toolBarButtonSelected:
When a toolbar button is pressed, the tool bar triggers the
#toolBarButtonSelected: event. If the toolbar button has no action
associated with it, then this event is not triggered. The ID (menuKey)
of the toolbar button is sent as a parameter of this event if it is
defined. If no ID (menuKey) is defined, then nil is sent as the
parameter.
107
6
Drag and Drop
aDropSource
aDragDropManager
aDragDropData
aConfigurableDropTarget
aDragDropContext
Drag and drop technology allows a user to select an object using the
mouse pointer, drag that object to another location on the screen, and
drop it. This is useful, for instance, for moving or copying items from one
list to another. This operation is common in some environments for
moving files (items) from one directory (a list) to another.
In VisualWorks, you implement drag and drop by setting one or more
widgets as drop sources and others as drop targets. Currently, only list
widgets can be a drop source, while a drop target can be any widget
except a linked or embedded dataform. Drop sources and drop targets
may be in the same interface, or they may be in the interfaces of different
applications.
You set up drop sources and drop targets by specifying various message
names in their properties, and then programming the relevant application
model(s) to respond to these messages.
108
VisualWorks
109
drop source
drop data
"no-drop" pointer
A drop source is a widget from which a drag can originate, and holding
the data to be transferred. Currently, only the List and Table widgets can
serve as a drop source.
You enable a list as a drop source by providing values for the Drag OK and
Drag Start properties on the Drop Source page of the Properties Tool. These
properties specify the messages that the widget sends when the user
starts a drag operation, by pressing a mouse button and moving the
mouse.
You program the widgets application model to respond to these
messages as follows:
110
Add a list widget to the canvas, set its Aspect and ID properties, install
the canvas and define its aspect instance variable and accessor
method, and initialize the SelectionInList, as usual for a list (refer to
Lists in Chapter 9, Configuring Widgets).
VisualWorks
In the lists Drag OK property, enter the name of the method that will
determine whether a drag can proceed from this list
(colorWantToDrag:).
The selector must end with a colon, because the widget sends this
message with its controller as argument. This is true even if the
controller isnt used.
In the lists Drag Start property, enter the name of the method that will
initiate drag and drop (colorDrag:)
This selector must also end with a colon, for the same reason.
111
Note that when the drag and drop completes, the doDragDrop message
returns a symbol which can be stored in a temporary variable and then
used to trigger further actions (such as cutting the dragged data out of
the drop source list). This symbol is ignored in the colorDrag: method.
112
VisualWorks
In the Properties Tool for the List widget, click the lists Multi Select
property.
113
The entry message is sent as soon as the pointer enters the widgets
bounds. The method typically saves the drop targets visual state for
restoring later, and/or toggles simple visual characteristics such as
highlighting.
The over message is sent immediately after the entry message, and
then every time the pointer moves within the widgets bounds. The
method typically adjusts the drop targets appearance in response to
pointer location or a modifier key press.
The exit message is sent wherever the pointer is dragged out of the
widgets bounds before the mouse button is released. The method
typically restores the widgets original appearance.
114
VisualWorks
Pointer Shapes
Each of the entry, over, and exit methods control the pointer shape by
returning an effect symbol. The DragDropManager passes each effect
symbol to the operations DropSource instance, which sets the pointer
shape accordingly. A standard DropSource recognizes these basic effect
symbols:
#dropEffectNone
Produces a pointer shaped like a circle with a slash through it; usually
indicates that no transfer is possible in the pointers current location.
#dropEffectMove
Produces an arrow-shaped pointer with an open box below it; usually
indicates a simple transfer such as a move (data is cut from the
source after the transfer).
#dropEffectCopy
Produces the same pointer as #dropEffectMove, but with a plus sign;
usually indicates a modified transfer such as a copy (data is left in the
source after the transfer).
In the canvas, select the Apply Color button, and set its ID property (in
this case, enter #applyColorButton).
On the Drop Target page of a Properties Tool, fill in the widgets Entry,
Over, and Exit properties with the names of the messages to be sent
during the drag (applyColorEnter:, applyColorOver:, and applyColorExit:,
respectively). Each selector must end with a colon. Apply the
properties and install the canvas.
In the entry method, test the dragged data to determine what kind of
feedback to provide (positive feedback if the data is a color choice,
and negative feedback otherwise). Send a key message to the
DragDropContext instance to obtain the identifying symbol that was
assigned when the drag started. If the datas key is not #colorChoice,
return an effect symbol (#dropEffectNone) to signal that a drop is not
allowed.
115
In the over method, test the dragged data and return the appropriate
effect symbols. No other processing is necessary in this method
because the buttons highlighting does not vary with the pointers
movement.
applyColorOver: aDragContext
"A drag is over the Apply Color button. Test whether a drop would be
permitted here with this data. If so, return a symbol that indicates the
feedback to be given to the user. The DragDropManager uses this symbol
to determine the pointer shape."
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
^#dropEffectMove
In the exit method, test the dragged data and return #dropEffectNone if
the dragged data is not a color choice.
10 If the dragged data is acceptable, reverse any visual effect that was
set in the entry method (in this case, unhighlight the button).
11 Return #dropEffectNone, to signal that no drop has occurred (this
method executes only if the pointer leaves the widget without
dropping).
116
VisualWorks
applyColorExit: aDragContext
"A drag has exited the Apply Color button without dropping. Test whether a
drop would have been permitted here with this data. If so, restore the
button to its former state, and return a symbol that indicates the feedback
to be given to the user."
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
(self widgetAt: #applyColorButton)
isInTransition: false.
^#dropEffectNone
In the canvas, select the Apply More Color button, and set its ID property
(in this case, enter #applyMoreColorButton).
On the Drop Target page of a Properties Tool, set the widgets Entry,
Over, and Exit properties (enter applyMoreColorEnter:, applyMoreColorOver:,
and applyMoreColorExit:).
117
change the button's label and return a symbol that indicates the feedback to
be given to the user."
| widget dict |
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
widget := self widgetAt: #applyMoreColorButton .
dict := IdentityDictionary new.
dict at: #widget put: widget.
dict at: #label put: widget label.
aDragContext dropTarget clientData: dict.
aDragContext shiftDown
ifTrue:
[widget labelString: 'Background'.
^#dropEffectCopy].
widget labelString: 'Foreground'.
^#dropEffectMove.
7
Retrieve the original label from the IdentityDictionary and put it back on
the button. (Note that argument of the label: message is a label
object, not a string.)
10 Remove the drop target data from the DragDropContext. This prepares
the DragDropContext for the next drop target the pointer may
encounter.
applyMoreColorExit: aDragContext
"A drag has exited the Apply More Color button without dropping. Test
whether a drop would have been permitted here with this data. If so, restore
the button to its former state, and return a symbol that indicates the
118
VisualWorks
In the canvas, select the list of color layers and set its ID property (in
this case, enter #colorLayerList).
On the Drop Target page of a Properties Tool, set the widgets Entry,
Over, and Exit properties (enter colorLayerEnter:, colorLayerOver:, and
colorLayerExit:).
Give focus to the list to prepare it for tracking the pointer with target
emphasis.
colorLayerEnter: aDragContext
"A drag has entered the bounds of the list of color layers. Test whether a drop
would be permitted here with this data. If so, save the initial state of the
color layer list, give focus to the list, and return a symbol that indicates the
119
120
VisualWorks
Responding to a Drop
11 Remove the drop target data from the DragDropContext. This prepares
the DragDropContext for the next drop target the pointer may
encounter.
colorLayerExit: aDragContext
"A drag has exited the list of color layers without dropping. Test whether a
drop would have been permitted here with this data. If so, restore the initial
state of the color layer list, and return a symbol that indicates the feedback
to be given to the user."
| dict widget |
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
dict := aDragContext dropTarget clientData.
widget := dict at: #widget.
widget targetIndex: (dict at: #targetIndex).
widget hasFocus: (dict at: #hasFocus).
aDragContext dropTarget clientData: nil.
^#dropEffectNone
Responding to a Drop
Dropping a color
here . . .
. . . changes the
background color
of the demonstration widgets
121
the Drop Target page of the Property Tool. This property specifies the name
of the message that the DragDropManager will send when a drop occurs in
the widget. You then create a corresponding method in the application
model to implement the response.
Like the entry, over, and exit methods, a drop method receives a
DragDropContext instance as an argument from the DragDropManager. The
method can examine this instance to determine whether to accept the
dragged data and, if so, how to process it.
A typical drop method adjusts the appearance of the drop target widget to
reverse any visual feedback caused by the enter or over method or to
provide visual evidence of the completed drop. The drop method may
also need to clean up any drop target data that was created by the entry
method.
A drop method returns an effect symbol for the DragDropManager to return
to the drag-start method that initiated the drag.
The example sets up the Apply Color button in ColorDDExample so that
dropping a color on this button applies that color to the foreground layer
of the demonstration widgets.
122
In the canvas, select the widget you want to use as a drop target. In
this case, select the Apply Color button.
On the Drop Target page of a Properties Tool, set the widgets Drop
property (applyColorDrop:). The selector must end with a colon. Apply
properties and install the canvas.
VisualWorks
Responding to a Drop
Return an effect symbol indicating the result of the drop. This symbol
is passed to the drag-start method (colorDrag:), where it can be used
to trigger further actions at the drop source.
applyColorDrop: aDragContext
"A drop has occurred in the Apply Color button. If the drop is permitted, set
the foreground color of the demonstration widgets to be the dragged color
choice. Restore the button to its former visual state and return an effect
symbol for possible use in the colorDrag method."
| dict aColor |
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
dict := aDragContext sourceData clientData.
aColor := ColorValue perform: (dict at: #colorChoice).
(self widgetAt: #applyColorButton)
isInTransition: false.
self foregroundColor: aColor.
^#dropEffectMove.
In the canvas, select the list of color layers and set its ID property (in
this case, enter #colorLayerList).
On the Drop Target page of a Properties Tool, set the widgets Entry, Over
and Drop properties (colorLayerEnter:, colorLayerOver:, and
colorLayerDrop:).
123
124
Send a targetIndex message to the list to get the index of the targeted
list item (the item containing the pointer when the drop occurs).
Get the color layer that is shown in the list at the targeted index.
VisualWorks
Responding to a Drop
index to be the targeted index). Alternatively, you could restore the list
to its original visual state, as is done in the colorLayerExit: method.
9
Use the targeted color layer to choose the appropriate message for
changing the color of the demonstration widgets.
colorLayerDrop: aDragContext
"A drop has occur in the list of color layers. If the drop is permitted, combine
the dragged color choice and the targeted color layer to change the color of
the appropriate parts of the demonstration widgets. Return an effect
symbol for possible use in the colorDrag method."
| dict aColor widget idx aLayer |
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
dict := aDragContext sourceData clientData.
aColor := ColorValue perform: (dict at: #colorChoice).
widget := aDragContext dropTarget clientData at: #widget.
idx := widget targetIndex.
idx = 0 ifTrue: [^#dropEffectNone].
aLayer := self colorLayer listHolder value at: idx.
self colorLayer selectionIndexHolder value: idx.
aDragContext dropTarget clientData: nil.
aLayer = 'Foreground'
ifTrue: [self foregroundColor: aColor].
aLayer = 'Background'
ifTrue: [self backgroundColor: aColor].
aLayer = 'Selection Foreground'
ifTrue: [self selectionForegroundColor: aColor].
aLayer = 'Selection Background'
ifTrue: [self selectionBackgroundColor: aColor].
^#dropEffectMove.
125
The example sets up the Apply More Color button in ColorDDExample so that
dragging changes the foreground color of the demonstration widgets,
while <Shift>-dragging changes the background color.
126
VisualWorks
In the canvas, select the list of color layers and set its ID property (in
this case, enter #applyMoreColorButton).
On the Drop Target page of a Properties Tool, set the widgets Entry,
Over, Exit and Drop properties (applyMoreColorEnter:, applyMoreColorOver:,
applyMoreColorExit:, and applyMoreColorDrop:). Apply properties and
install the canvas.
If the <Shift> key is not down, change the buttons label to indicate
that foreground colors will be set, and return an effect symbol
(#dropEffectMove) to signal a regular transfer.
applyMoreColorEnter: aDragContext
"A drag has entered the bounds of the Apply More Color button. Test whether
a drop would be permitted here with this data. If so, store the current label
of the button. Then test whether the shift key is down. Based on this test,
change the button's label and return a symbol that indicates the feedback to
be given to the user."
| widget dict |
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
widget := self widgetAt: #applyMoreColorButton .
dict := IdentityDictionary new.
dict at: #widget put: widget.
dict at: #label put: widget label.
aDragContext dropTarget clientData: dict.
aDragContext shiftDown
ifTrue:
[widget labelString: 'Background'.
^#dropEffectCopy].
widget labelString: 'Foreground'.
^#dropEffectMove.
127
If the <Shift> key is not down, test whether the buttons label needs to
change; if so, change it. Return the #dropEffectMove symbol.
applyMoreColorOver: aDragContext
"A drag is over the Apply More Color button. Test whether a drop would be
permitted here with this data. If so, test whether the shift key is down.
Based on this test, return a symbol that indicates the feedback to be given
to the user. The DragDropManager uses this symbol to determine the
pointer shape."
| widget |
aDragContext key == #colorChoice
ifFalse: [^#dropEffectNone].
widget := aDragContext dropTarget clientData at: #widget.
aDragContext shiftDown
ifTrue:
[widget label text string = 'Background'
ifFalse: [widget labelString: 'Background'].
^#dropEffectCopy].
widget label text string = 'Foreground
ifFalse: [widget labelString: 'Foreground'].
^#dropEffectMove.
128
VisualWorks
10 If the <Shift> key is down, apply the dragged color choice to the
background color layer of the demonstration widgets. Return
#dropEffectCopy to signal a modified transfer.
11 If the <Shift> key is not down, apply the dragged color choice to the
foreground color layer. Return #dropEffectMove to signal a regular
transfer. Note that a drag-start method could respond differently
depending on which symbol is returned.
applyMoreColorDrop: aDragContext
"A drop has occured in the Apply More Color button. If the drop is permitted,
obtain the dragged color. Then test whether the shift key is down. If so, set
the background color of the demonstration widgets. If not, set their
foreground color. Restore the button to its former visual state and return an
129
130
VisualWorks
7
Dialogs
Standard Dialogs
The standard dialogs provided in VisualWorks make it simple to display
commonly used dialogs from within an application. Typically, all you need
to do is send a message to the Dialog class that identifies the kind of
dialog and any specific information required, such as text.
The standard dialogs are demonstrated in the example DialogExample.
Displaying a Warning
131
Chapter 7 - Dialogs
132
VisualWorks
Standard Dialogs
Multiple-Choice Dialog
Frequently more choices than Yes/No, or other choices are required, but
still only a small number. The multiple-choice dialog provides this
capability. The choices are arrayed as a horizontal row of buttons.
The message that creates a multiple-choice dialog assigns a symbol to
each choice. When the user clicks a choice, the message returns the
corresponding symbol to the application.
To display a multiple-choice dialog, send a choose:labels:values:default:
message to the Dialog class. The choose argument is the question. The
labels argument is an array of strings to be displayed on the answer
buttons. The values argument is an array of Symbols to be used as return
values by the answer buttons. The default argument is the Symbol that is
associated with the desired default answer.
Dialog
choose: 'Which memory would you like to review first?'
labels: #( 'Swimming the Channel'
'Triumph at the Coliseum'
'Love & War #47')
values: #(#swim #triumph #love47)
default: #triumph
To prompt for a short, textual response, use the request dialog, which
displays a fill-in-the-blank input field and a label.
To open a request dialog, send request: to the Dialog class, with text
describing what is being requested:
Dialog request: 'Find all memories associated with...'
133
Chapter 7 - Dialogs
When the user enters a string and clicks OK, the dialog returns the userspecified string. If the user clicks Cancel, the default is to return an empty
string.
By default, an empty string appears in the input field. To specify a default
response, send request:initialAnswer: to Dialog, with the default answer as a
string:
Dialog
request: 'Find all memories associated with...'
initialAnswer: 'friend'
If an empty string is not an appropriate response to Cancel, you can
specify an alternate action or value. Send request:initialAnswer:onCancel: to
Dialog, with a block containing the action to be taken or the value to be
returned:
getText
| returnVal |
returnVal := Dialog
request: 'Find all memories associated with...'
initialAnswer: 'friend'
onCancel: [self defaultRuminationTopic].
"Update the text field in the main window."
self returnedValue value: returnVal printString.
Requesting a Filename
134
VisualWorks
Standard Dialogs
135
Chapter 7 - Dialogs
getFilename
| returnVal |
returnVal := Dialog
requestFileName: 'Open memory file named...'
default: 'hero01.mem'
version: #mustBeOld
ifFail: [Transcript show: 'Memory file access canceled'. ''].
"Update the text field in the main window."
self returnedValue value: returnVal printString.
136
VisualWorks
Standard Dialogs
| files response |
files := Filename defaultDirectory directoryContents
reject: [ :name | name asFilename isDirectory].
response := Dialog
choose: 'Edit which file?'
fromList: files
values: files
lines: 8
cancel: [^nil].
response asFilename edit.
| user pass |
(SimpleDialog initializedFor: nil)
setInitialGap;
addMessage: 'Username' textLine: (user := '' asValue) boundary: 0.4;
addGap;
addMessage: 'Password' textLine: (pass := '' asValue)
type: #password boundary: 0.4;
addGap;
addOK: [true];
openDialog.
user value -> pass value
137
Chapter 7 - Dialogs
138
VisualWorks
confirm
| returnVal |
returnVal := Dialog
confirm: 'Really erase all memories\of adolescent period?'
withCRs
initialAnswer: false
for: ScheduledControllers activeController view.
"Update the text field in the main window."
self returnedValue value: returnVal printString.
139
Chapter 7 - Dialogs
These
buttons . . .
When a standard dialog is not sufficient, you can create your own using
the canvas tool. You can then open the interface specification in a dialog
window.
The basic technique is send an openDialogInterface: message to the
application model, with the symbolic name of the dialogs interface
specification.
openDialogCanvas
| returnVal |
returnVal := self openDialogInterface: #memoryZonesDialog.
"Update the text field in the main window."
self returnedValue value: returnVal printString.
The dialog is created as an instance of SimpleDialog, which provides its
own interface builder for setting up the dialogs widgets. The dialog
builder obtains any needed value models, actions, and resources for its
widgets from the application model.
Note, however, that buttons whose Action properties are #accept or #cancel
obtain their actions from the SimpleDialog instance instead. These
predefined actions are useful for OK and Cancel buttons on the dialog.
Consequently, if you define methods named accept or cancel in the
application model, they will be ignored.
140
VisualWorks
Get the builder from the SimpleModel and preload it with one binding
for each active widget. The aspectAt: argument is the symbol you
specified in the widgets Aspect property. The put: argument is an
appropriate value model.
141
8
Custom Views
142
VisualWorks
The new view requires a class, which you create as a subclass of View or
one of its subclasses.
Online example: SketchView
1
In the template, specify the name space, class name, and superclass
name. The superclass is typically either View (as in the example, or a
subclass of View).
143
When a different
domain model
is selected . . .
A view displays text or graphics that communicate the state of its domain
model, or at least a portion of its domain model. Since a view must
communicate frequently with the domain model, it needs a way of
accessing that object. As a subclass of DependentPart, every view inherits
an instance variable for storing its model. Sending a model: message to
the view, typically when the view is created, stores the model in this
instance variable, where it can be accessed easily.
A side effect of the model: message is that the view is registered as a
dependent of the model. This link sets the stage for the view to update its
display when the model changes.
About the example: Although some views have the same domain model
for their whole lifetimes, SketchView changes its model each time the user
selects a different Sketch. For that reason, SketchView reimplements the
model: method so it can update its display after storing the new model.
Online example: CustomViewExample, SketchView
1
Tell the view which object to use as its domain model. This is done in
an initialization method or, as in the example, the application model
(CustomViewExample) can notify the view whenever the domain model
changes.
changedSketch
self sketchView model: self sketches selection.
144
VisualWorks
If the view needs to take action when its model is changed, such as
redisplaying itself, override the inherited model: method (as in
SketchView).
model: aModel
super model: aModel.
self invalidate.
"Tell the controller where to send menu messages."
self controller performer: aModel.
In the displayOn: method, get the required data from the model (in the
example, a set of line segments, each represented as a collection of
points).
145
dependents
self
changed
aModel
update
view1
view2
146
In any method in the domain model that changes the model in a way
that affects the view, send a variant of the changed:with: message to
the model. (In the example, Sketch sends three such messages, one
VisualWorks
when it adds a point and the others when it erases some or all of its
contents.)
add: aPoint
"Add aPoint to the current stroke."
self strokes last add: aPoint.
self changed: #stroke with: self currentLineSegment.
eraseLine
"Erase the last stroke that was drawn."
self strokes isEmpty
ifFalse: [
self strokes removeLast.
self changed: #erase with: nil].
eraseAll
"Erase my contents."
self strokes removeAll: self strokes copy.
self changed: #erase with: nil.
2
147
148
VisualWorks
Add accessor methods for the instance variables. The methods are
responsible for getting and setting the value of each instance
variable.
strokeInProgress
^strokeInProgress
strokeInProgress: aBoolean
strokeInProgress := aBoolean
keyboardProcessor
^keyboardProcessor
keyboardProcessor: kp
keyboardProcessor := kp
149
It the default behavior is not appropriate, you can also set the controllers
model explicitly. This is not necessary for our example. If it is necessary
for your application, simply send a model: message to the controller. The
argument is the model.
VisualWorks
The windows sensor keeps track of such damage rectangles and repairs
them in a batch to avoid repairing the same region twice. Sending
invalidate to a view causes the entire view to be treated as a damage
rectangle. Alternatively, you can limit the damage rectangle to a portion of
the window.
By default, damage rectangles are accumulated until the windows
controller reaches a certain point in its cycle of activity. That is sufficient
in most situations. However, when a competing process is monopolizing
the processor, the delay can be significant. In this case, you can force the
damage to be repaired immediately.
Invalidating a view is done in a view method, when the view updates its
model. It can also be done by an application model that has changed a
widgets data model in a way that bypasses the normal dependencies.
Redisplaying a View
Online example: SketchView
Send invalidate to the view. This is typically done in a view method that
changes the model (as in the example).
model: aModel
super model: aModel.
self invalidate.
"Tell the controller where to send menu messages."
self controller performer: aModel.
Redisplaying Immediately
Send invalidateRectangle:repairNow: to the view. The first argument is a
rectangle that represents all or part of a views bounding box. The second
argument is true when immediate redisplay is desired, and false for the
default behavior.
151
Select a View Holder from the Palette and place it on the canvas.
In the view holders View property, enter the name of the applicationmodel method that supplies an instance of the desired view
(sketchView).
If the application model will need to access the custom view while the
application is running, use a System Browser to create an instance
variable (sketchView) in which to store the custom view.
152
VisualWorks
9
Configuring Widgets
VisualWorks provides a rich set of widgets for building the GUI for your
application. The widgets are shown in the canvass palette and can be
selected and added to design a window, as described in Chapter 2,
Building an Applications GUI.
This chapter describes the widgets and how to connect them to your
application.
153
Buttons
Online example: ButtonExample
Radio button, checkboxes, and action buttons are common GUI elements
for setting standard parameters and starting actions. Radio buttons and
checkboxes are used to select one or more options. Action buttons
frequently begin an operation or invoke another window.
Radio Buttons
radio buttons
For each button, change the Label property to name the choice.
Enter the same Aspect property for each button in the group.
The common aspect is what makes a group.
154
Apply the properties and install the canvas, and use define to add an
instance variable and accessor method for the aspect.
VisualWorks
Buttons
155
#backTabbed
When a radio button has focus and the Back-Tab (Shift-Tab) key is
pressed causing focus move to the previous widget in the tab order,
the radio button triggers the #backTabbed event.
#turnedOn
After a radio button has its state changed from being not selected to
being selected, the radio button triggers the #turnedOn event.
#turnedOff
After a radio button has its state changed from being selected to not
being selected, the radio button triggers the #turnedOff event.
Check Boxes
check boxes
A check box is like a toggle button that allows the user to turn on or turn
off an attribute. Check boxes are often used in a group to represent a set
of related attributes.
Selecting one check box has no effect on others in the set, so users can
select as many as they want. When you want only one attribute to be
selected at a time, use radio buttons instead.
To add an check box:
1
156
Apply the properties and install the canvas, and use define to create
an instance variable and aspect accessor method.
VisualWorks
Buttons
initialize
super initialize.
outputMode := #dialog asValue.
showHours := true asValue.
showMinutes := true asValue.
showSeconds := true asValue.
Checkbox Events
A Check Box triggers events when its label is changing, when it gains and
looses focus and when the selection is checked or unchecked.
Check Boxes send the #labelChanging, #labelChanged, #checked and
#unchecked events only after the Check Box has been created and
displayed on the canvas. Thus, a Check Box that has its value initially set
to be checked or unchecked, will not trigger that event, since that value is
assigned before the Check Box is initially displayed on the canvas.
#labelChanging
When a check box's label is about to change, the check box triggers
the #labelChanging event.
#labelChanged
After a check box's label has changed, the check box triggers the
#labelChanged event.
#clicked
When a check box is clicked on by the mouse, without regard to the
checked or unchecked the check box, the check box triggers the
#clicked event.
#gettingFocus
When a check box receives focus, either by being tabbed to or by
clicking on by the mouse, the check box triggers the #gettingFocus
event.
#losingFocus
When a check box loses focus, either by being tabbed away from, or
by having another widget on the canvas gain focus, the check box
triggers the #losingFocus event.
#tabbed
When a check box has focus, and the Tab key is pressed in request
to have the focus to move to the next widget in the tab order, the
check box triggers the #tabbed event.
#backTabbed
When a check box has focus, and the Back-Tab (Shift-Tab) key is
pressed in request to have the focus move to the previous widget in
the tab order, the check box triggers the #backTabbed event.
GUI Developers Guide
157
#checked
After a check box has had its state changed from being unchecked to
being checked, the check box triggers the #checked event.
#unchecked
After a check box has its state changed from being checked to being
unchecked, the check box triggers the #unchecked event.
Action Buttons
action button
158
VisualWorks
Buttons
tellTime
| t tString |
t := Time now.
tString := String new.
"Assemble the time string based on the check boxes."
self showHours value
ifTrue: [tString := tString, t hours printString].
self showMinutes value
ifTrue: [tString := tString, ':', t minutes printString, ':']
ifFalse: [tString := tString, '::'].
self showSeconds value
ifTrue: [tString := tString, t seconds printString].
"Send the time string to the output channel set by the radio
buttons."
self outputMode value == #transcript
ifTrue: [Transcript show: tString; cr]
ifFalse: [DialogView warn: tString]
159
#losingFocus
When a button loses focus, either by being tabbed away from, or by
having another widget on the canvas gain focus, the button triggers
the #losingFocus event.
#tabbed
When a button has focus, and the Tab key is pressed in request to
have the focus to move to the next widget in the tab order, the button
triggers the #tabbed event.
#backTabbed
When a button has focus, and the Back-Tab (Shift-Tab) key is
pressed in request to have the focus move to the previous widget in
the tab order, the button triggers the #backTabbed event.
160
VisualWorks
161
Charts
The Chart widget supports a large variety of graphical representations
that are commonly used in business applications to represent numerical
data. The style and appearance of the chart are set by widget properties.
The application model provides the chart data in the form of a collection
of numerical data. A simple chart presents a single set or series of
values. A more complex chart, comparing two or more sets of data,
requires two or more collections of values, called a data series.
Adding a Chart
To add a bar chart to an application:
1
On the Basics property page, specify the charts Aspect, which is the
the name of the instance variable and accessor method that supplies
the data to the chart.
In the case of a simple chart with a single series of values, the aspect
returns a collection. For charts that compare multiple series of
values, you set up one or more data series, as described in Charting
Multiple Data Series.
Create a definition for the chart widgets aspect and edit it to return a
value holder on the collection containing the chart data.
VisualWorks
Charts
On the Basics property page for the chart, specify the Aspect for the
Chart.
On the Data Series page, click New to add a new data series, and
In the Name field, enter a descriptive name for the first set.
In the Aspect field, enter either the accessor method for the items
making up this data series, or the index of this item in the
subcollection.
Adding Labels
You add labels to your chart by including the label strings as another data
series.
To add labels:
1
On the Data Series property page, add a new data series with an
appropriate name. For the Aspect, enter the index for the labels in the
collection, or the name of the accessor method that returns the label
from the collection members.
163
Pareto
Picture
VisualWorks
Charts
For the labels to display, define two data series, and check the Label
checkbox for the series holding the labels.
To replace the default picture, enter the name of the graphic into the
Aspect field on the Picture section on the Options property page.
By default, the picture represents a unit of 20. To change the unit amount,
enter the desired amount in the Unit field under the Picture section of the
Options Properties.
XY
165
Pie Charts
A pie chart can only represent one data series, but may include labels:
#(#(25 'Jan') #(15 'Feb') #(40 'Mar') #(20 'Apr'))
Exploding Labels
In a pie chart, a slice can be designated to be exploded. For example,
enter Jan in the Labels to Explode field on the Options page. Only one label
can be exploded at a time.
Doughnut Labels
A doughnut label appears inside a circle in the center of a pie chart. To
create a doughnut label, enter the label name in the Doughnut Label field on
the Options page.
166
VisualWorks
Click Map
Click Map
The Click Map widget allows you to define areas of a graphic image and
specify the action to invoke if the user clicks on each area.
Using a Click Maps for a button bar makes it possible to use any graphic
image to represent the row of buttons. The image may include text,
graphics, and a variety of colors. All of the buttons may be part of a single
image, guaranteeing their relative layout.
the user clicks in an area for which no other action is specified. If left
empty, no action is taken.
3
In the canvas, resize the click map widget so that it closely outlines
the graphic image.
Install the canvas, and provide a class name and method name in
167
The four colors or patterns of ink allow you to select a color that
shows well when selecting a region. The color does not show in
the final click map.
Six brush sizes and shapes. The first four draw lines, the next
draws an ellipse, and the sixth draws a rectangle.
In the Selector input field, enter a method selector for the action to be
invoked when this slice is clicked and press <Return>.
The selector is added to the menu button in the middle of the Hot
Regions Editor. You can use the menu to switch between different
slices of the same hot region resource.
168
Repeat steps 4 and 5 to define all the slices for this hot region.
VisualWorks
Click Map
Install the hot region resource. You are prompted for the class
name and selector for the resource method that stores the hot
region mappings.
Note that interaction with the user is more limited in web applications than
in other applications. In particular, the only mouse events transmitted to
the application from the web browser are mouse clicks. Events based on
entry, mouse movement, and exit are ignored.
169
Combo Box
It is frequently useful for an input field to restrict the valid entries. This can
be done with validation methods, but the ComboBox is often informative
to a user.
On the Basics property page, in the Aspect field, enter a name for the
aspect accessor method (in the example, shipper).
In the Choices property, enter the name of the method that returns a
collection of entry choices (shipperChoices).
Apply the properties and install the canvas, and use Define to create
the aspect instance variable and accessing method.
170
Initialize the fields aspect variable with a value model containing data
of the type specified in the Type property for the widget.
Initialize the choices variable with a value holder containing the list of
valid entries.
VisualWorks
Combo Box
initialize
| list |
shipper := 'Courier' asValue.
list := List new.
list add: 'Courier';
add: 'FedEx';
add: 'UPS';
add: 'USPS'.
shipperChoices := list asValue.
On the Basics property page, set the Type property of the combo box
to Object.
Fill in the Print property with the name of a method for converting the
relevant objects to strings (in this example, employeeToString:). The
name must end with a colon.
Fill in the Read property with the name of a method for converting
strings to objects of the desired type (in this example,
stringToEmployee:). The name must end with a colon.
In the application model, create a print method with the name you
specified in step 2 (employeeToString:). This method accepts an object
from the choices list as an argument (in this case, an instance of
Employee).
In the print method, return a String that represents the object from the
choices list. In this example, display the name of the Employee. The
string is displayed in the combo boxs pull-down list and also in the
combo boxs field when the choice is selected.
171
employeeToString: anEmployee
"Return a String for representing the Employee in the combo boxs list
and field."
^anEmployee name.
6
In the read method, return an object for the given String. In this
example, determine whether the String is the name of an Employee in
the choices list; if so return that Employee. Otherwise, create a new
Employee and add it to the choices list.
stringToEmployee: aString
"Return an Employee corresponding to the given String. If the String
corresponds to the name of an Employee on the choices list, return that
Employee. Otherwise, create a new Employee and add it to the list."
| theEmp |
theEmp := self employeeChoices value
detect: [:each | each name = aString]
ifNone: [nil].
theEmp isNil
ifTrue:
[theEmp := Employee new name: aString.
self employeeChoices value addLast: theEmp].
^theEmp
VisualWorks
Combo Box
#clicked
When a combo box is clicked on with the <Select> mouse button, the
combo box triggers the #clicked event.
#rightClicked
When a combo box is right clicked on with the <Operate> mouse
button, the combo box triggers the #rightClicked event. This event will
occur without regard to whether there is a popup menu associated
with the combo box.
#doubleClicked
When a combo box is double clicked on with the <Select> mouse
button, the combo box triggers the #doubleClicked event. This event is
always immediately preceded by a #clicked event. Read-only combo
boxes do not respond to the double clicked event, but rather consider
the double click to be two separate clicks that open and immediately
close the combo box, and thus do not trigger the #doubleClicked event.
#gettingFocus
When a list box receives focus, either by being tabbed to or by
clicking on by the mouse, the list box triggers the #gettingFocus event.
#losingFocus
When a combo box loses focus, either by being tabbed away from, or
by having another widget on the canvas gain focus, the combo box
triggers the #losingFocus event.
#tabbed
When a combo box has focus, and the Tab key is pressed moving the
focus to the next widget in the tab order, the combo box triggers the
#tabbed event.
#backTabbed
When a combo box has focus, and the Back-Tab (Shift-Tab) key is
pressed moving the focus to the previous widget in the tab order, the
combo box triggers the #backTabbed event.
#listExposed
When a combo box has its selection list exposed, either by clicking
on the combo box or using the down arrow key to open the list, the
combo box triggers the #listExposed event.
#listClosed
When a combo box has its selection list closed, either by clicking on
another widget on the canvas, by clicking on the combo box when the
list is already exposed, or by selecting a new value in an exposed list,
the combo box triggers the #listClosed event.
173
Datasets
row labels
dataset widget
A dataset presents a list of similar objects for a user to edit. Datasets are
similar to tables, but cells in a dataset can be edited directly. Datasets are
best suited for presenting similar kinds of data.
A dataset uses a SelectionInList to hold the list of objects to be displayed,
along with information about the current selection. Each object in the list
is displayed in its own row, with individual aspects of the object displayed
in their own columns. The property pages specify the means by which
each column presents its data, whether using cells that contain read-only
fields, editable fields, combo boxes, or checkboxes.
Setting up a Dataset
Online example: Dataset1Example
The example displays instances of Employee, which consist of three
objects (name, empNo, and citizen), in three dataset columns.
1
On the Basics property page, in the datasets Aspect property, enter the
aspect name (dsvList). Apply the property and install the canvas.
Use define to add the dsvList instance variable and accessor method
to the application model.
The dsvList method returns a SelectionInList object that will hold the list
to be displayed. This method also sets up the SelectionInList so it will
cause a users selection to be put in a separate value holder
(selectedRow).
174
In the datasets properties, click the New Column button for each
column you want in the dataset.
VisualWorks
Datasets
Display the datasets Column property page. The properties you set on
this page will apply to the currently selected column.
On the Column page, enter Name as the Label property. This creates a
visual label above the selected column, which is to display employee
names.
On the Column page, select Input Field as the Type. This causes each
cell in the selected column to display its data in an editable input field.
Note that you can optionally specify nondefault characteristics for
these input fields by filling in properties on the Column Type page.
175
When you open the application, the dataset contains one empty row. You
can type a name and number in the Name and Employee Number columns,
and select the U.S. Citizen check box.
Note that the first part of the Aspect setting for each column must be the
same as the message sent by the SelectionInList to obtain a value holder
for storing the selected object. You used selectedRow in steps 8, 11, and
13, because that name is used in the generated dsvList method that sets
up the SelectionInList (step 3). To use a name other than selectedRow, you
must replace selectedRow with the desired name in each Aspect field and in
the code generated for dsvList in step 3. Use the define command (as in
step 15) to generate an instance variable and method with the new name.
selected column
You must select a column before you can set its properties. To select a
column:
1
Hold down the <Control> key while clicking the <Select> mouse
button.
176
Place the cursor near the top right or top left margin of the column.
VisualWorks
Datasets
Click and hold the mouse button. The cursor changes to indicate a
column width change operation when properly selected. If necessary,
move the pointer nearer the corner of the selected column until the
cursor changes appearance.
Place the cursor on the drag handle within the selected column.
Click and hold on the handle, and drag it toward the U.S. Citizen
column. The cursor changes to indicate the move operation when
properly selected.
To disable scrolling for a column (and all columns to the left of it),
select that column and click the Fixed check box in the Column
properties.
If you then select another widget on the canvas, you must repeat the
basic steps to reselect a dataset column.
177
Press <Control> while using the mouse to move the scroll bars on the
dataset.
On the Basics property page, enter number as the Label in the Column
properties.
Select the Image check box next to Label. This specifies that the
column label will come from the resource method named in the Label
property.
Similarly, to change the color of the column label, set the text color in the
number method:
number
^('Employee Number' asText emphasizeAllWith:
(Array with: #bold with: #color->ColorValue red))
asComposedText
178
VisualWorks
Datasets
Adding a Row
Online example: Dataset2Example
row marker
When the number of rows needed for a dataset is not predetermined, you
can program your application to add rows while it is running.
1
On the Basics property page, enter Add Row as the buttons Label
property and addRow as the buttons Action property. Apply the
properties and install the canvas.
179
Dataset Events
A Dataset triggers events when a selection is changing, when it gains
and looses focus, when it gets clicks from the mouse, and when it's view
scrolls.
#rightClicked
When a dataset is right clicked on with the <Operate> mouse button,
the dataset triggers the #rightClicked event. This event will occur
without regard to whether there is a popup menu associated with the
dataset.
180
VisualWorks
Datasets
#doubleClicked
When a dataset is double clicked on with the <Select> mouse button,
the dataset triggers the #doubleClicked event. This event is always
immediately preceded by a #clicked event.
#gettingFocus
When a dataset receives focus, either by being tabbed to or by
clicking on by the mouse, the dataset triggers the #gettingFocus event.
#losingFocus
When a dataset loses focus, either by being tabbed away from, or by
having another widget on the canvas gain focus, the dataset triggers
the #losingFocus event.
#tabbed
When a dataset has focus and the last cell in the dataset has focus,
and the Tab key is pressed to the focus to the next widget in the tab
order, and the dataset has its wrapping policy that allows it to tab out
to another widget, the dataset triggers the #tabbed event.
#backTabbed
When a dataset has focus and the first cell in the dataset has focus,
and the Back-Tab (Shift-Tab) key is pressed to movethe focus to the
previous widget in the tab order, and the dataset has its wrapping
policy that allows it to tab out to another widget, the dataset triggers
the #backTabbed event.
#scrollLeft
If while navigating with the keyboard or mouse, or manipulating a
horizontal scroll bar in a dataset, the dataset scrolls to the left, the
dataset triggers the #scrollLeft event.
#scrollRight
If while navigating with the keyboard or mouse, or manipulating a
horizontal scroll bar in a dataset, the dataset scrolls to the right, the
dataset triggers the #scrollRight event.
#scrollUp
If while navigating with the keyboard or mouse, or manipulating a
vertical scroll bar in a dataset, the dataset scrolls up, the dataset
triggers the #scrollUp event.
#scrollDown
If while navigating with the keyboard or mouse, or manipulating a
vertical scroll bar in a dataset, the dataset scrolls down, the dataset
triggers the #scrollDown event.
181
#cellGettingFocus
When an individual cell in a dataset receives focus, either by being
tabbed to or by clicking on by the mouse, the dataset triggers the
#cellGettingFocus event.
#cellLosingFocus
When an individual cell in a dataset loses focus, either by being
tabbed away from, or by having another widget on the canvas gain
focus, the dataset triggers the #cellLosingFocus event.
#cellTabbed
When an individual cell in a dataset has focus, and the and the Tab
key is pressed to move the focus either the next cell in the dataset or
to the next widget in the tab order, the dataset trigger the #cellTabbed
event.
#cellBackTabbed
When an individual call in a dataset has focus, and the Back-Tab
(Shift-Tab) key is pressed in request to mov the focus to either the
previous cell in the dataset or the previous widget in the tab order, the
dataset triggers the #cellBackTabbed event.
#cellValueChanged
If a cell is editable, and its value is changed, once the new value has
been accepted the dataset triggers the #cellValueChanged event. This
occurs when a the value of the underlying input field changes, the
selection of the underlying combo box changes, or the check or
unchecked value of the underlying check box changes.
#columnLabelClicked
If a dataset has column labels, and that column label is clicked on
with the mouse, then the dataset triggers the #columnLabelClicked
event.
#rowLabelClicked
If a dataset has row labels, and the row label is clicked on with the
mouse, then the dataset triggers the #rowLabelClicked event.
#rowSelectionsChanging
If a dataset has row labels and a row label is selected or unselected,
or in the case of multiple select datasets the selections change, or in
the case of a dataset where there are no row labels and the focus
changes from one row to another, then prior to the selection change
taking effect, the dataset triggers the #rowSelectionsChanging event.
#rowSelectionsChanged
If a dataset has row labels and a row label is selected or unselected,
or in the case of multiple select datasets the selections change, or in
the case of a dataset where there are no row labels and the focus
182
VisualWorks
Datasets
changes from one row to another, then after the to the selection
change has occured, the dataset triggers the #rowSelectionsChanged
event.
183
Input Fields
An input field is used for both entering and displaying data. You can also
use a field in read-only mode when you just want to display data.
When a field has a short list of valid entries, consider using a menu
button or a combo box instead.
A field uses a value model to manage its data (see Chapter 4, Adapting
Domain Models to Widgets). When the field accepts input from a user, it
sends this data to the value model for storage; when the field needs to
update its display, it asks its value model for the data to be displayed.
On the Basics property page, in the fields Aspect property, enter the
name of the get method for the fields value model.
On the Details page, select or assign values for the fields properties.
The size property takes an integer value for the maximum number of
characters allowed.
The following subsections describe other properties.
184
VisualWorks
Input Fields
Data Type
Description
String
Symbol
Text
Number
Password
Date
Time
Timestamp
FixedPoint(2)
Boolean
185
Data Type
Description
ByteArray
Object
186
VisualWorks
Input Fields
Validating Input
Frequently, only certain entries are valid for a particular field. For
example, you might want to restrict input to a numeric range such as 0 to
999 or check for undesirable characters.
For a general description of the Validation properties, refer to Validation
Properties in Chapter 3.
Data can be validated either a whole-field at a time, or character by
character. The following subsections describe a few variations on these
options.
On the Validation page of the GUI Painter Tool, enter the names of
validation methods for one or more of the validation points.
In the example, we use:
the Exit property, to determine whether the field can give up focus
Apply properties and install the canvas, and use define to add the
aspect instance variable (username) and aspect method (username) to
the application model. Initialize the instance variable with a value
model.
Because the Change validation needs to validate the data before it is sent
to the fields value holder, the validation method needs to get the entered
value from the widgets controller. By naming the method so its selector
ends in a colon, the widget sends the controller as an argument, which
the method can then use.
187
On the Basics property page, in the ID field, enter an identifier for the
field (codeField). Apply the property and install the canvas.
188
VisualWorks
Input Fields
postBuildWith: aBuilder
| ctrlr |
ctrlr := (self controllerAt: #codeField).
ctrlr keyboardHook: [ :ev :c |
self keyPress: ev].
3
Adding a Command
1
In the fields Menu property, enter the name of the method that you will
create to supply a custom menu (expandedMenu).
189
190
VisualWorks
Input Fields
191
Tell the fields controller the character position at which to place the
insertion point.
addPart2
"Put a template in the partID2 field, then position the insertion
point."
| wrapper |
self partID2 value: 'MW-'.
wrapper := self wraooerAt: #part2.
wrapper takeKeyboardFocus.
wrapper widget controller selectAt: 4.
192
VisualWorks
Input Fields
#changed
After the value of the input field has been accepted, the input field
triggers the #changed event.
#clicked
When a input field is clicked on with the <Select> mouse button, the
input field triggers the #clicked event.
#rightClicked
When a input field is right clicked on with the <Operate> mouse
button, the input field triggers the #rightClicked event. This event will
occur without regard to whether there is a popup menu associated
with the input field.
#doubleClicked
When a input field is double clicked on with the <Select> mouse
button, the input field will trigger the #doubleClicked event. This event
is always immediately preceded by a #clicked event.
#gettingFocus
When a input field receives focus, either by being tabbed to or by
clicking on by the mouse, the input field triggers the #gettingFocus
event.
#losingFocus
When a input field loses focus, either by being tabbed away from, or
by having another widget on the canvas gain focus, the input field
triggers the #losingFocus event.
#tabbed
When a input field has focus, and the Tab key is pressed in request to
have the focus to move to the next widget in the tab order, the input
field triggers the #tabbed event.
#backTabbed
When a input field has focus, and the Back-Tab (Shift-Tab) key is
pressed to move the focus to the previous widget in the tab order, the
input field triggers the #backTabbed event.
#scrollLeft
If while editing, navigating with the keyboard, or selecting text with the
keyboard or mouse in an input field, the view scrolls to the left, the
input field triggers the #scrollLeft event.
#scrollRight
If while editing, navigating with the keyboard or selecting text with the
keyboard or mouse in an input field, the view scrolls to the right, the
input field triggers the #scrollRight event.
193
Hierarchical Lists
Note: The Hierarchical List widget will be deprecated in a future
release, in favor of the Tree View widget. Unless you need
functionality in the Hierarchical List that is not currently provided by
Tree View, please use Tree View. The missing functionality will be
added to Tree View before Hierarchical List is deprecated.
A Hierarchical List widget is similar to a List widget, but its primary
component is an IndentedTreeSelectionInList. This object holds a tree object
representing the hierarchy.
For cases where the hierarchical list is displaying a natural hierarchy,
such as the class hierarchy, IndentedTreeSelectionInList provides instance
creation methods to create the tree. Otherwise, create the tree using
instances of AssociationTreeWithParent.
Retrieving the index and contents of a list item uses the same methods
as for a List widgets SelectionInList.
Adding a List
1
On the Basics property page, fill in the lists Aspect property with the
name of the method that will return an instance of
IndentedTreeSelectionInList.
Apply the change, install the canvas, and use define to add an instance
194
VisualWorks
Hierarchical Lists
initialize
theList := IndentedTreeSelectionInList
listObjectHierarchy: Object
childAccessor: #allSubclasses
childNameAccessor: #name.
^self
For other instance creation convenience methods, browse the instance
creation protocol.
Building a Tree
You can build a hierarchy of arbitrary objects using instances of
AssociationTree or AssociationTreeWithParent. Then use the tree as the
source of the hierarchy for the Hierarchical List widget.
This version of the initialize method creates a hierarchy:
initialize
tree := (AssociationTreeWithParent key: 'first' value: #first).
tree addChild:
((AssociationTreeWithParent
key: 'second'
value: #second)
addChild: (AssociationTreeWithParent
key: 'third'
value: #third);
addChild: (AssociationTreeWithParent
key: 'fourth'
value: #fourth));
addChild: ((AssociationTreeWithParent
key: 'fifth'
value: #fifth)
addChild: (AssociationTreeWithParent
key: 'sixth'
value: #sixth);
addChild: (AssociationTreeWithParent
key: 'seventh'
value: #seventh)).
myList := IndentedTreeSelectionInList
listObjectHierarchy: tree
childAccessor: #children
childNameAccessor: #displayString.
^self
195
196
VisualWorks
Hierarchical Lists
#scrollRight
If while navigating with the keyboard or manipulating a horizontal
scroll bar in a hierarchical list, the hierarchical list scrolls to the right,
the hierarchical list triggers the #scrollRight event.
#scrollUp
If while navigating with the keyboard or manipulating a vertical scroll
bar in a hierarchical list, the hierarchical list scrolls up, the
hierarchical list triggers the #scrollUp event.
#scrollDown
If while navigating with the keyboard or manipulating a vertical scroll
bar in a hierarchical list, the hierarchical list scrolls down, the
hierarchical list triggers the #scrollDown event.
#selectionChanging
When an item in a hierarchical list is selected or unselected, before
the change is applied, the hierarchical list triggers the
#selectionChanging event.
#selectionChanged
After an item in a hierarchical list is selected or unselected, the
hierarchical list triggers the #selectionChanged event.
#selectionListChanged
Whenever the list underlying a hierarchical list is manipulated, either
by changing a value, reordering, adding or removing items, or
changing the list as a whole, the hierarchical list triggers the
#selectionListChanged event.
#itemExpanded
When an item in the hierarchical list is visually toggled from its
collapsed view to its expanded view, the hierarchical list triggers the
#itemExpanded event.
#itemCollapsed
When an item in the hierarchical list is visually toggled from its
expanded view to its collapsed view, the hierarchical list triggers the
#itemCollapsed event.
197
Labels
Online example: LogoExample
A label is used as a title or a description for another widget or group of
widgets, such as a field. Since the text of a label can be changed while
the application is running, a label can also be used for read-only display.
A label accommodates only a single line of text. For a multiline label, use
a separate label for each line or use a read-only text widget.
On the Basics property page, in the labels Label property, enter the
name of the method that will supply the graphic image (in the
example, logo).
The method must be a class method, and by convention is placed in
the resources protocol.
198
VisualWorks
Labels
You can use the Image Editor to create the graphic image and install it in
the application model, using the method name from step 2. You can also
draw the image using graphics classes in VisualWorks, and create the
class method to return it in the application model.
199
postBuildWith: aBuilder
"Update the slogan's text, and make the company name bold and red."
| slogan txt emph label |
"Insert the years-in-business into the slogan."
slogan := 'Serving Shrimps For '
, (Date today year - 1869) printString, ' Years'.
( self wrapperAt: #slogan ) labelString: slogan.
"Make the company name bold and red."
txt := 'Many Hands Shrimppickers' asText
emph := Array
with: #bold
with: #color->ColorValue red.
txt emphasizeFrom: 1 to: 10 with: emph.
label := Label
with: txt
attributes: (TextAttributes styleNamed: #large).
(self wrapperAt: #textLogo) label: label.
200
VisualWorks
Labels
initialize
"LogoExample initialize"
"Register the graphic image for the trademark symbol."
ApplicationModel
visualAt: #trademark
put: self trademark.
"Register the textual version of the trademark symbol."
ApplicationModel
labelAt: #tm
put: '(TM)'.
Execute the initialization method to make the label available.
To remove a label from the registry, get the appropriate registry by
sending a visuals message to the ApplicationModel class for the graphics
registry, or a labels message for the string registry. Then send the
removeKey:ifAbsent: to the registry specifying the name of the label as the
first argument. The second argument is a block specifying the action to
be take if the label is not found, and can be empty.
"Visual registry"
| registry |
registry := ApplicationModel visuals.
registry removeKey: #trademark ifAbsent: [].
"Labels registry"
registry := ApplicationModel labels.
registry removeKey: #tm ifAbsent: [].
Label Events
Labels and Group Boxes trigger events only when their labels are
changing.
#labelChanging
When a label or group box's label is about to change, the widget
triggers the #labelChanging event.
#labelChanged
After a label or group box's label has changed, the widget triggers the
#labelChanged event.
201
Lists
Online example: List1Example
A list widget is useful for displaying a collection of objects or as an input
device, allowing the user to select one or more elements in the list.
A list widget depends on two value models, one to hold the collection of
objects to be displayed, and the other to hold the index of the current
selection. A SelectionInList is a complex object that contains both of the
required value holders.
The List collection is particularly well suited for use with the List widget,
rather than other sequenced collections. It is extensible, and propagates
change messages to its dependents.
The elements in the collection can be any objects, provided that they can
display themselves textually.
Adding a List
1
Use a Palette to add a list widget to the canvas. Leave the list
selected.
On the Basics property page, fill in the lists Aspect property with the
name of the method that will return an instance of SelectionInList.
VisualWorks
Lists
Clicks the <Select> mouse button to select a single item on the list
On the Details property page, check List widgets Multi Select property,
and make sure the Use Modifier Keys For Multi Select property is also
checked. Apply properties and install the canvas.
203
204
VisualWorks
Lists
changedClass
| cls |
self classes selection isNil
"No class is selected -- empty the selector list."
ifTrue: [
self methodNames list: List new.
self instances list: List new]
"A class is selected"
ifFalse: [
cls := Smalltalk at: self classes selection.
"Update the selectors list."
self methodNames list: cls selectors asSortedCollection.
"Update the instances list."
self instances list: cls allInstances].
Setting a Selection
It is sometimes useful for a program to set the selection.
To set a list selection, in the method that is to change the selection, get
the SelectionInList from the application model and send it a selectionIndex:
message with the desired index number as the argument. Alternatively,
send a selection: message with the desired object itself as the argument.
postOpenWith: aBuilder
super postOpenWith: aBuilder.
"Uncomment the line below to auto-select the first class."
self classes selectionIndex: 1.
"Uncomment the lines below to auto-select the last class."
"self classes selection: self classes list last.
(self controllerAt: #classes) cursorPointWithScrolling."
"In the classes list, use boxed highlighting instead of
reverse-video."
(self widgetAt: #classes) strokedSelection.
Note that, for a MultiSelectionInList, send selectionIndexes: or selections:,
supplying as argument a collection of indexes or a collection of objects in
the list.
To select all objects in a multiple-selection list, get the MultiSelectionInList
from the application model and send a selectAll message to it.
GUI Developers Guide
205
selectAll
self methodNames selectAll.
Similarly, to clear all selections, get the MultiSelectionInList from the
application model and send a clearAll message to it.
clearAll
self methodNames clearAll.
206
VisualWorks
Lists
List Events
A List Box triggers events when a selection is changing, when the
underlying list itself is changing, when it gains and looses focus, when it
gets clicks from the mouse, and when it's view scrolls.
#clicked
When a list box is clicked on with the <Select> mouse button, the list
box triggers the #clicked event.
#rightClicked
When a list box is right clicked on with the <Operate> mouse button,
the list box triggers the #rightClicked event. This event will occur
without regard to whether there is a popup menu associated with the
list box.
#doubleClicked
When a list box is double clicked on with the <Select> mouse button,
the list box triggers the #doubleClicked event. This event is always
immediately preceded by a #clicked event.
#gettingFocus
When a list box receives focus, either by being tabbed to or by
clicking on by the mouse, the list box trigger the #gettingFocus event.
#losingFocus
When a list box loses focus, either by being tabbed away from, or by
having another widget on the canvas gain focus, the list box triggers
the #losingFocus event.
#tabbed
When a list box has focus, and the Tab key is pressed in request to
have the focus to move to the next widget in the tab order, the list box
triggers the #tabbed event.
#backTabbed
When a list box has focus, and the Back-Tab (Shift-Tab) key is
pressed to move the focus to the previous widget in the tab order, the
list box triggers the #backTabbed event.
207
#scrollLeft
If while navigating with the keyboard or manipulating a horizontal
scroll bar in a list box, the list box scrolls to the left, the list box
triggers the #scrollLeft event.
#scrollRight
If while navigating with the keyboard or manipulating a horizontal
scroll bar in a list box, the list box scrolls to the right, the list box
triggers the #scrollRight event.
#scrollUp
If while navigating with the keyboard or manipulating a vertical scroll
bar in a list box, the list box scrolls up, the list box triggers the
#scrollUp event.
#scrollDown
If while navigating with the keyboard or manipulating a vertical scroll
bar in a list box, the list box scrolls down, the list box triggers the
#scrollDown event.
#selectionChanging
When an item in a list box is selected or unselected, or in the case of
a multiple select list box, the selections change, before the change is
applied, the list box triggers the #selectionChanging event.
#selectionChanged
After an item in a list box is selected or unselected, or in the case of a
multiple select list box, the selections have changed, the list box
triggers the #selectionChanged event.
#selectionListChanged
Whenever the list underlying a list box is manipulated, either by
changing a value, reordering, adding or removing items, or changing
the list as a whole, the list box triggers the #selectionListChanged event.
208
VisualWorks
Lists
209
Chapter -
Menu Button
menu button
Add a menu button widget to the canvas and open the Properties
Tool.
In the menu buttons Menu property, enter the name of the menu
creation resource method (templatesMenuForMenuButton).
In the buttons Aspect property, enter a name for the aspect (letter).
Leave the buttons Label property blank. You can enter a label, but it
will always be displayed in the menu. Leaving the Label blank displays
the current selection on the menu button while the application is
running. The initial (default) selection is set by initializing the aspect
variable, typically in the initialize method.
Use the define command to add the aspect instance variable and
accessor method (letter) to the application model.
210
VisualWorks
Menu Button
Create the menu resource method that you named in step 2, and any
action methods that are invoked by the menu items.
211
Chapter -
#losingFocus
When a menu button loses focus, either by being tabbed away from,
or by having another widget on the canvas gain focus, the menu
button triggers the #losingFocus event.
#tabbed
When a menu button has focus, and the Tab key is pressed in
request to have the focus to move to the next widget in the tab order,
the menu button triggers the #tabbed event.
#backTabbed
When a menu button has focus, and the Back-Tab (Shift-Tab) key is
pressed to move the focus to the previous widget in the tab order, the
menu button triggers the #backTabbed event.
#listExposed
When a menu button has its selection list exposed, either by clicking
on the menu button or using the down arrow key to open the list, the
menu button triggers the #listExposed event.
#listClosed
When a menu button has its selection list closed, either by clicking on
another widget on the canvas, by clicking on the menu button when
the list is already exposed, or by selecting a new value in an exposed
list, the menu button triggers the #listClosed event.
212
VisualWorks
Notebook
Notebook
Selecting a tab
causes a different page
of the notebook to be
displayed
Creating a Notebook
Online example: Notebook1Example
213
Apply the properties and install the canvas, and define the instance
variables and accessing methods for the notebooks major and minor
index labels.
Initialize the major and minor variable, either in the accessing method
or in an initialize method (as in the example), with a SelectionInList
containing either strings or associations.
214
VisualWorks
Notebook
postOpenWith: aBuilder
(self widgetAt: #pageHolder)
client: self
spec: #listSpec.
majorKeys selectionIndex: 1.
215
changedLetter
| chosenLetter list |
chosenLetter := self majorKeys selection last.
list := Smalltalk classNames
select: [ :name | name first == chosenLetter].
self classNames list: list.
216
On the Basics property page, fill in the notebooks Minor property with
the name of the method that returns a SelectionInList containing the
labels for the secondary tabs (in the example, minorKeys).
VisualWorks
Notebook
minorKeys
^minorKeys
3
217
"Minor key."
filter := self minorKeys selection value.
filter == #all
ifTrue: [filteredList := list]
ifFalse: [filteredList := list
select: [ :name | '*Example' match: name]].
self classNames list: filteredList.
218
VisualWorks
Notebook
changedDepartment
| subdepts sel |
sel := self majorKeys selection.
sel isNil ifTrue: [^self].
"Display the appropriate subdepartments as minor keys."
subdepts := self departments at: sel.
self minorKeys list: subdepts.
self minorKeys selectionIndex: 1.
3
219
220
VisualWorks
Notebook
Notebook Events
A Notebook triggers events when a tab selection is changing, when one
of its tabs gains or looses focus, and when it's tabs scroll.
#gettingFocus
When any of a notbook's tab groups (either horizontal or vertical)
receives focus by being clicked on by the mouse, or tabbed into by
the keyboard, when none of that group of tabs have had focus, the
notebook triggers the #gettingFocus event.
#losingFocus
When any of a notebook's tabs groups (either horizontal or vertical)
lose focus, by being clicked or tabbed away from, to anything except
another of the tabs in the same group, the notebook triggers the
#losingFocus event.
#tabbed
When a notebook tab group (either horizontal or vertical) has focus,
and the and the Tab key is pressed to move the focus to the next
widget in the tab order or another tab group on the notebook, the
notebook triggers the #tabbed event.
#backTabbed
When a notebook tab group (either horizontal or vertical) has focus,
and the Back-Tab (Shift-Tab) key is pressed to move the focus to the
previous widget in the tab order or another tab group on the
notebook, the notebook triggers the #backTabbed event.
#scrollLeft
If all of the tabs in a horizontal tab group of a notebook are not visible,
and the left double arrow icon is pressed to scroll additional
horizontal tabs into view, then the notebook triggers the #scrollLeft
event.
#scrollRight
If all tabs in a horizontal tab group of a notebook are not visible, and
the right double arrow icon is pressed to scroll additional horizontal
tabs into view, then the notebook triggers the #scrollRight event.
#scrollUp
If all tabs in a vertical tab group of a notebook are not visible, and the
up double arrow icon is pressed to scroll additional vertical tabs into
view, then the notebook trigger the #scrollUp event.
#scrollDown
If all tabs in a vertical tab group of a notebook are not visible, and the
down double arrow icon is pressed to scroll additional vertical tabs
into view, then the notebook triggers the #scrollDown event.
GUI Developers Guide
221
#horizontalTabChanging
When a new tab within a horizontal tab group is selected, either by
selection using the mouse or by keyboard navigation, before the view
changes to the newly selected tab the notebook triggers the
#horizontalTabChanging event.
#horizontalTabChanged
After a new tab within a horizontal tab group is selected, either by
selection using the mouse or by keyboard navigation, the notebook
triggers the #horizontalTabChanged event.
#verticalTabChanging
When a new tab within a vertical tab group is selected, either by
selection using the mouse or by keyboard navigation, before the view
changes to the newly selected tab the notebook triggers the
#verticalTabChanging event.
#verticalTabChanged
After a new tab within a vertical tab group is selected, either by
selection using the mouse or by keyboard navigation, the notebook
triggers the #verticalTabChanged event.
222
VisualWorks
Basic Properties
Only the Basic properties are specific to this widget.
Aspect
The instance variable that determines the percentage. The value is a
numeric value between 0 and 1.
Orientation
Horizontal indicates progress horizontally.
Vertical indicates progress vertically.
Both indicates progress both vertically and horizontally.
Area shows percentage in terms of area covered, rather than linearly.
Reverse reverses the horizontal and/or vertical direction.
Starting Point
The grid with five radio buttons sets the starting point: top, bottom, left,
right, or center. If Both is selected for the orientation, then the starting
point is either a corner or the center.
223
Add a Percent Done Bar widget to the canvas and select it.
Apply the properties and install the canvas. Use define to add the
aspect instance variable and accessor method.
224
VisualWorks
divider
Lines, group boxes, and regions (rectangles and ellipses) are used to
provide visual separation between sets of interface components. Using
appropriate dividers can greatly improve the usability of an interface.
On the Basics property page, select either Horizontal or Vertical for the
lines orientation property. Apply the property.
Lines are one pixel thick. For a thicker line, use a rectangular region and
set its Thick border property.
225
Chapter -
Use a Palette to add a box to the canvas. Leave the box selected.
A box line thickness is one pixel. For a thicker line, use a rectangular
region and set its border property to Thick. Also use a region if you want to
use color.
226
Set the regions Rectangle or Ellipse property, as desired, and apply the
properties.
VisualWorks
If desired, use the Color property page to apply color to the foreground
(border) and/or background (interior).
Region Events
A Region triggers events when one of its visible properties is changed
programmatically.
#changing
When a region is about to change its size, inside color, border color
or border size, before the change is applied the region triggers the
#changing event.
#changed
After a region has had its size, inside color, border color or border
size changed, the region triggers the #changed event.
227
Resizing Splitter
The Resizing Splitter widget allows users to resize widgets in the GUI.
For example, in the GUI Painter Tool, a Resizing Splitter is between the
hierarchical list of widgets and the tabbed notebook.
You can change the relative size of both by selecting and dragging the
area between them. The cursor shape changes while it is passing over a
Resizing Splitter, indicating that the border is movable.
Because this widget is really only intended for direct user manipulation,
no programmatic interface is described in this section.
Typically, the Resizing Splitter will be one of the last widgets you add to
the canvas, since you add it between other widgets whose size you want
to allow the user to control.
Select the Resizing Splitter and drop it on the canvas between the
widgets you want to resize.
In the Left/top widgets: properties field, enter the IDs of the widgets to
the left of or above the widget. Similarly, in the Right/bottom widgets:
field, enter the IDs of the widgets to the right or below the Resizing
Splitter.
Since there may be (frequently are) more than one widget on one
side of a widget, these fields take space-separated widget ID names.
Only widgets in the lists are resized as the Resizer Splitter is moved.
IDs can be listed either simply as identifiers (TreeView1 TextEditor2) or as
symbols (#TreeView1 #TextEditor2).
228
VisualWorks
Resizing Splitter
Set the positions as shown below (placement of the check boxes is left as
an exercise for the reader):
Position
Offset
Left (L)
Top (T)
Right (R)
0.5
-3
Bottom (B)
0.5
-7
Left (L)
0.5
Top (T)
Right (R)
-3
Bottom (B)
-3
Left (L)
Top (T)
TextEditor (right)
229
Position
Offset
Right (R)
0.5
-3
Bottom (B)
0.5
-7
Left (L)
26
Top (T)
0.5
-2
Right (R)
0.5
-26
Bottom (B)
0.5
Left (L)
0.5
-2
Top (T)
Right (R)
0.5
Bottom (B)
ResizingSplitter (horizontal)
RisizingSplitter (vertical)
For clarity, the positions are all given as relative either to a line shared by
a Resizing Splitter, or to an edge, but that is not necessary. The affected
widgets are identified in the Resizing Splitters Left/top widgets: and
Right/bottom widgets: lists.
230
VisualWorks
Sliders
Sliders
A slider simulates the sliding switch that some electronic devices use for
controlling volume, bass level, and other properties. A slider enables you
as the designer of an application to define a specific range of legal
values, and it enables the user to conveniently select a value within that
range.
Adding a Slider
Online example: Slider1Example
1
Apply the properties and install the canvas, and use define to add the
aspect instance variable and accessor method (destination).
Create or edit the initialize method to initialize the variable with a value
holder and an initial value.
initialize
"Destination"
destination := Date today year asValue.
"Current year"
currentYear := Date today year asValue.
"Trip meter"
tripRange := RangeAdaptor
on: currentYear
stop: 4000
grid: 1.
231
In the fields Aspect property, enter the same aspect name as for the
slider.
In the fields Aspect property, enter a different method name than the
sliders Aspect (month).
In the fields Type property, select the type that corresponds to the
transformed value (the example uses a String type).
Apply the properties and install the canvas, and use define to create
the aspect instance variable and accessing method.
232
VisualWorks
Sliders
changedDate
"Convert the y-axis value to a month."
|yx|
y := self dateRange value y.
y := (12 - (y * 12) asInteger) max: 1."(12 months)"
self month value: (Date nameOfMonth: y).
"Convert the x-axis value to a year."
x := self dateRange value x.
x := 1900 + (x * 100) asInteger."(100 years)"
self year value: x.
233
initialize
"Destination"
destination := Date today year asValue.
"Current year"
currentYear := Date today year asValue.
"Trip meter"
tripRange := RangeAdaptor
on: currentYear
start: 0
stop: 4000
grid: 1.
2
234
VisualWorks
Sliders
You can make a slider manipulate a point in two dimensions and then use
the x-axis and y-axis components of that point to control two separate
parameters.
In Slider2Example, a two-dimensional slider is used to alter two fields
simultaneously. The first field uses the y component to display one of the
12 months. The second field uses the x component to arrive at a year
between 1900 and 2000.
Online example: Slider2Example
1
In a postBuildWith: method, get the slider from the application and ask
it to beTwoDimensional.
postBuildWith: aBuilder
(self widgetAt: #dateRange)
beTwoDimensional;
setMarkerLength: 10.
235
Slider Events
A Slider triggers events when its value has changed or folded in half and
eaten whole (without regard to cheese). Unlike other widgets that interact
with the mouse, a Slider never gets focus and thus does not trigger focus
or mouse click events.
#changing
When a slider is about to change its value, the slider triggers the
#changing event.
#changed
After a slider has changed its value, the slider triggers the #changed
event.
236
VisualWorks
Spin Buttons
Spin Buttons
A spin button allows a user to select a value from a determined range.
The selected value is returned as a selectable object type and format.
A spin button model must represent a number, whenever its Type
property is set to either String, Text, or Symbol. In these cases the model
must respond to asNumber and not answer zero unless the model itself
represents 0.
For example, model values for a spin button, listed by Type, might be:
Type
String
'774.3'
Text
'12e-03' asText
Symbol
#'12'
The Low Value is the minimum setting the button will spin to, and the High
Value is the maximum setting. The spin button range is unbounded
unless these values are set.
The Interval is the amount each button press increments or decrements
the spin button value. Any number may be entered for the Interval, but
only positive numbers make sense. The default Interval value is 1.
For all spin button Types other than Date, Time, and Timestamp, the Low
Value and High Value properties expect only numeric entries; no nonnumeric symbols should appear in the entry.
If the Type property is set to Date, enter Low Value and High Value entries
as dates, such as 12/20/1988 or Sep 30 1990. The Interval expects values as
a number of days.
When Type is set to Time, format Low Value and High Value entries as
times, such as 12:34:23 pm. Do not set a High Value of 12:00:00 am, unless
you have the wrap around property set. The Interval entries are in units of
seconds.
If Type is a Timestamp, enter Low and High Values in Timestamp format,
such as 01/03/1999 0:00:00.000. Interval entries are in units of milliseconds.
237
The table below summarizes the acceptable spin button property values
for Date, Time, and Timestamp type.
Type
Interval Units
Date
Days
Time
Seconds
Timestamp
01/03/1999 0:00:00.000
Milliseconds
(Optional) Set the Type, Format, Low Value, High Value, and Intervale
properties
These properties set the returned object type and format, and the
range and increment for the presented values.
Apply the properties and install the canvas, and use define to add the
aspect instance variable and accessor method.
Create or edit the initialize method to initialize the aspect variable with
a value holder and an initial value.
238
VisualWorks
Spin Buttons
#rightClicked
When a spin button is right clicked on with the <Operate> mouse
button, the spin button triggers the #rightClicked event. This event will
occur without regard to whether there is a popup menu associated
with the spin button.
#doubleClicked
When a spin button is double clicked on with the <Select> mouse
button, the spin button will triggers the #doubleClicked event. This
event is always immediately preceded by a #clicked event.
#gettingFocus
When a spin button receives focus, either by being tabbed to or by
clicking on by the mouse, the spin button triggers the #gettingFocus
event.
#losingFocus
When a spin button loses focus, either by being tabbed away from, or
by having another widget on the canvas gain focus, the spin button
triggers the #losingFocus event.
#tabbed
When a spin button has focus, and the Tab key is pressed in request
to have the focus to move to the next widget in the tab order, the spin
button triggers the #tabbed event.
#backTabbed
When a spin button has focus, and the Back-Tab (Shift-Tab) key is
pressed in request to have the focus move to the previous widget in
the tab order, the spin button triggers the #backTabbed event.
#spinUp
When the up arrow button is pressed on a spin button, prior to
changing the value of the spin button, the spin button triggers the
#spinUp event. If the value of the spin button is changed, the #spinUp
event is always immediately followed by #changing, #changed and
#spunUp events. If the value of the spin button is not changed, the
#spinUp event may be followed by a #bounceTop event, depending on
the settings of the spin button.
#spunUp
After the up arrow button is pressed on a spin button, after changing
the value of the spin button, the spin button triggers the #spunUp
event. The #spunUp event is always immediately preceded by a
#changed event.
239
#spinDown
When the down arrow button is pressed on a spin button, prior to
changing the value of the spin button, the spin button triggers the
#spinDown event. If the value of the spin button is changed, the
#spinDown event is always immediately followed by #changing,
#changed and #spunDown events. If the value of the spin button is not
changed, the #spinDown event may be followed by a #bounceTop
event, depending on the settings of the spin button.
#spunDown
After the down arrow button is pressed on a spin button, after
changing the value of the spin button, the spin button triggers the
#spunDown event. The #spunDown event is always immediately
preceded by a #changed event.
#wrapAroundBottom
If a spin button has a low value set in its properties, and has the wrap
around property set, then when the spin button is asked to spin below
the lowest value, after the #spinDown, #changing, #changed and
#spunDown events are triggered, the spin button triggers the
#wrapAroundBottom event.
#wrapAroundTop
If a spin button has a high value set in its properties, and has the
wrap around property set, then when the spin button is asked to spin
above the highest value, after the #spinUp, #changing, #changed and
#spunUp events are triggered, the spin button triggers the
#wrapAroundTop event.
#bounceBottom
If a spin button has a low value set in its properties, and does not
have the wrap around property set, then when the spin button is
asked to spin below the lowest value, after the #spinDown event is
triggered, the spin button triggers the #bounceBottom event. Because
the value has not changed, the #changing, #changed and #spunDown
events will not trigger.
#bounceTop
If a spin button has a high value set in its properties, and does not
have the wrap around property set, then when the spin button is
asked to spin above the highest value, after the #spinUp event is
triggered, the spin button triggers the #bounceTop event. Because the
value has not changed, the #changing, #changed and #spunUp events
will not trigger.
240
VisualWorks
Subcanvases
Subcanvases
A subcanvas is a widget for displaying another canvas in the canvas you
are building. It is an effective way to build an application interface that
incorporates another application interface, or an entire application, into
itself.
There are three primary uses for subcanvases:
Inheriting an application
Within a hierarchy of application models, you can inherit an interface
and its value models.
Nesting an application
By placing an application in a subcanvas, you make its interface part
of your own applications interface, and effectively incorporate its
domain model into your application as well.
Reusing an interface only
You can incorporate another applications interface, but supply your
own domain model for it.
All three of these methods promote various levels of reuse. Using
subcanvases in these ways allow you to build a collection of reusable
interfaces.
Inheriting a Subcanvas
Subcanvases provide a way to extend the inheritance mechanism in
Smalltalk to building a user interface. By building an application model as
a subclass of another application model, the subclass will inherit standard
interface modules, value holders, and action methods.
For example, Subcanvas1Example is a subclass of List2Example, so it can
reuse the List2Example interface, value holders, and actions.
A subclass need not reimplement anything that the parent class has
implemented, but it can override an inherited action.
Note: A limitation of the inheritance approach is that if you use the
same inherited interface twice in a canvas, both will display the same
thing. This is because both reference the same value holder.
Online example: List2Example (parent) and Subcanvas1Example
1
241
Apply the property and install the inheriting canvas in its application
model (Subcanvas1Example).
242
VisualWorks
Subcanvases
The embedded application supplies its own value models and action
methods. Because the applications are not generally related by
inheritance, you cannot override an embedded applications action
methods.
You can embed the same application any number of times in the same
canvas. For example, you could reuse List2Example four times in creating
a System Browsers four list views.
Online example: List2Example embedded in Subcanvas2Example
1
application (listSpec).
3
Apply the properties and install the reusing canvas in its application
model (Subcanvas2Example).
243
(listSpec).
The Name property is not needed for reusing the interface only.
244
VisualWorks
Subcanvases
Apply the properties and install the reusing canvas in its application
model (Subcanvas2Example).
In the subcanvass Name property, enter the name of the method that
supplies the initial embedded application (embeddedApplication).
245
showComment
| selectedClass subcanvas spec application |
selectedClass := Smalltalk at: self classNames selection.
"Create the subapplication and initialize it."
application := Editor2Example new.
application text value: selectedClass comment.
"Get the spec object for the embedded canvas."
spec := Editor2Example interfaceSpecFor: #windowSpec.
"Get the subcanvas and install the editing application."
subcanvas := self widgetAt: #subcanvas.
subcanvas client: application spec: spec.
246
VisualWorks
Subcanvases
Subcanvas Events
A Subcanvas triggers events when its view scrolls due to activity via its
scroll bars or the Subcanvas builds and displays a new subcanvas.
#changing
When a subcanvas is sent a client:, client:spec:, or client:spec:builder:
message to have it host a new canvas, prior to the work of building
and displaying the new view, the subcanvas triggers the #changing
event. This event is only triggered once a subcanvas has been built
and displayed the first time. Thus the #changing event is not triggered
upon the initial creation of a subcanvas.
#changed
After a subcanvas is sent a client:, client:spec:, or client:spec:builder:
message to have it host a new canvas, and the new view is
completed being built and displayed, the subcanvas triggers the
#changed event. This event is only triggered once a subcanvas has
been built and displayed the first time. Thus the #changed event is not
triggered upon the initial creation of a subcanvas.
#scrollLeft
If while manipulating a horizontal scroll bar in a subcanvas, the
subcanvas to the left, the subcanvas triggers the #scrollLeft event.
#scrollRight
If while manipulating a horizontal scroll bar in a subcanvas, the
subcanvas scrolls to the right, the subcanvas triggers the #scrollRight
event.
#scrollUp
If while manipulating a vertical scroll bar in a subcanvas, the
subcanvas scrolls up, the subcanvas triggers the #scrollUp event.
#scrollDown
If while manipulating a vertical scroll bar in a subcanvas, the
subcanvas scrolls down, the subcanvas triggers the #scrollDown
event.
247
Tab Control
248
VisualWorks
Tab Control
Select the Tab Control on the Palette and drop it on the canvas.
In its Aspect property, enter an aspect name. Also enter an ID, or keep
the default. You will need the ID to identify the selected tab.
249
tabsChanged
"Every time, a tab is changed, a new sub canvas gets installed."
| index |
index := self tabs selectionIndex.
(self widgetAt: #tabbing)
client: self
spec: (self specArray at: index)
The change is made by the client:spec: message sent to the Tab
Control widget, which is retrieved from the builder.
For additional options and approaches, see Notebook above.
250
VisualWorks
Tab Control
251
#pageRight
If all of the tabs in a tab control are not visible, and the right arrow
button is pressed to scroll additional tabs into view while the Shift key
is pressed, then the tab control triggers the #pageRight event.
#tabChanging
When a new tab is selected in a tab control, either by selection using
the mouse or by keyboard navigation, before the view changes to the
newly selected tab, the tab control triggers the #tabChanging event.
#tabChanged
After a new tab is selected in a tab control, either by selection using
the mouse or by keyboard navigation, the tab control triggers the
#tabChanged event.
252
VisualWorks
Tables
Tables
A table displays data in a rows-and-columns structure. In appearance,
tables are similar to dataset widgets, except that tables do not support
direct editing, and tables can display dissimilar kinds of data. Data must
be stored in a collection that allows two-dimensional access.
TableInterface
A table requires a relatively complex auxiliary object as its value model,
which is provided by TableInterface. A TableInterface holds information about
row and column labeling and formatting, in addition to the table data itself.
Within a TableInterface, the table data is held by a composite object, an
instance of SelectionInTable, which stores the collection of cell contents
and the selection index. The collection is expected to be a TwoDList (twodimensional list), which converts a flat collection such as an array into a
matrix of rows and columns. Alternatively, you can use a TableAdaptor to
adapt a collection.
All of this interface machinery can be held by a single instance variable in
the application model, and you can simply send messages to that object
to fetch the table or the selection or any other aspect of it. However, you
may find it economical to create instance variables to hold onto various
aspects of the table interface. For example, the SelectionInTable is useful
when your application model will need to access the contents of the table
at run time.
Adding a Table
Online example: Table1Example
1
On the Basics property page, in the Aspect property, enter a name for
the aspect (e.g., tableInterface).
Set other property checkboxes as desired.
Apply the properties and install the canvas, and use define to add the
instance variable and accessor method for the aspect (tableInterface).
Initialization is done in an initialize method (step 5), rather than by
checking the include initialization option.
253
254
VisualWorks
Tables
changed cell
input field
Apply the change and install the canvas, and use define to add an
instance variable and accessor method for the aspect.
Add an instance method to update the table when the entry field
changes.
In the example we add changedCell in a change messages protocol:
changedCell
| cellLocation |
"Get the coordinates of the highlighted cell."
cellLocation := self sightingsTable selectionIndex.
"If a cell is selected, update its contents from the input field."
cellLocation = Point zero
ifFalse: [self sightingsTable table
at: cellLocation
put: self cellContents value]
255
initialize
| list |
super initialize.
"Create a collection of sightings data."
list := TwoDList
on: #('Vulcans' 188 173 192 'Romulans' 26 26 452) copy
columns: 4
rows: 2.
sightingsTable := SelectionInTable with: list.
"Create a table interface and load it with the sightings."
tableInterface := TableInterface new
selectionInTable: sightingsTable.
cellContents := String new asValue.
self cellContents onChangeSend: #changedCell to: self.
The application adds the input data into the selected cell.
Notice that when you select a new cell, its contents are not shown in the
input field. To make the field update its contents when the table selection
changes, you must register interest in the table selection with
onChangeSend: and trigger an update in the input field.
row labels
You can label one or more columns by sending an array of labels to the
table interface. For row labels, you need to send an array of labels and
also an indication of the width of those labels.
Online example: Table3Example
This example adds code to the end of Table2Examples initialize method that
initializes the row and column labels.
256
VisualWorks
Tables
tableInterface
columnLabelsArray: #('Visiting Race' '1992' '1993' '1994');
rowLabelsArray: #(1 2);
rowLabelsWidth: 20.
By default, all cells display their contents beginning at the left margin, and
all labels are centered. You can align data and labels using any of three
symbols: #left, #right, #centered, or #leftWrapped. Using these symbols, you
can control the alignment of a columns data, a columns labels, or a rows
labels.
Add code to the initialize method that initializes the label alignments.
tableInterface
elementFormats: #(#left #right #right #right);
columnLabelsFormats: #(#left #right #right #right);
rowLabelsFormat: #right.
As the example shows, you can set row labels to the same alignment by
passing a single symbol as argument, and the same applies to the
column alignments. For column data and labels, however, you also have
the option of setting each columns alignment individually, as we have
done, by passing an array of symbols.
Table Events
A Table triggers events when a selection is changing, when it gains and
looses focus, when it gets clicks from the mouse, and when it's view
scrolls.
#clicked
When a table is clicked on with the <Select> mouse button, the table
triggers the #clicked event.
#rightClicked
When a table is right clicked on with the <Operate> mouse button,
the table triggers the #rightClicked event. This event will occur without
regard to whether there is a popup menu associated with the table.
#doubleClicked
When a table is double clicked on with the <Select> mouse button,
the table triggers the #doubleClicked event. This event is always
immediately preceded by a #clicked event.
#gettingFocus
When a table receives focus, either by being tabbed to or by clicking
on by the mouse, the table triggers the #gettingFocus event.
257
#losingFocus
When a table loses focus, either by being tabbed away from, or by
having another widget on the canvas gain focus, the table trigger the
#losingFocus event.
#tabbed
When a table has focus, and the and the Tab key is pressed to move
the focus to the next widget in the tab order, the table triggers the
#tabbed event.
#backTabbed
When a table has focus, and the Back-Tab (Shift-Tab) key is pressed
to move the focus to the previous widget in the tab order, the table
triggers the #backTabbed event.
#scrollLeft
If while navigating with the keyboard or mouse, or manipulating a
horizontal scroll bar in a table, the table scrolls to the left, the table
triggers the #scrollLeft event.
#scrollRight
If while navigating with the keyboard or mouse, or manipulating a
horizontal scroll bar in a table, the table scrolls to the right, the table
triggers the #scrollRight event.
#scrollUp
If while navigating with the keyboard or mouse, or manipulating a
vertical scroll bar in a table, the table scrolls up, the table triggers the
#scrollUp event.
#scrollDown
If while navigating with the keyboard or mouse, or manipulating a
vertical scroll bar in a table, the table scrolls down, the table triggers
the #scrollDown event.
#rowSelectionChanged
If a table has its selection mode set to Row, and while navigating with
the mouse or keyboard, the selected row changes, the table triggers
the #rowSelectionChanged event.
#columnSelectionChanged
If a table has its selection mode set to Column, and while navigating
with the mouse or keyboard, the selected column changes, the table
triggers the #columnSelectionChanged event.
#cellSelectionChanged
If a table has its selection mode set to Cell, and while navigating with
the mouse or keyboard, the selected cell changes, the table triggers
the #cellSelectionChanged event.
258
VisualWorks
Text Editors
Text Editors
A text editor is useful for displaying and editing text that does not fit
comfortably within a field, especially when the text is expected to have
multiple lines. The text editor has built-in facilities for:
Line wrapping
Printing
On the Basics property page, in the Aspect field, enter a name for the
aspect.
Install the canvas, and use define to add an instance variable and
aspect accessor method to the application model.
Create or edit the initialize method to set the aspect variable to a value
holder containing the initial text to be displayed (usually an empty
string).
initialize
super initialize.
comment := '' asValue.
classes := SelectionInList with: Smalltalk classNames.
classes selectionIndexHolder
onChangeSend: #changedClass to: self.
textStyle := #plain asValue.
textStyle onChangeSend: #changedStyle to: self.
readOnly := false asValue.
readOnly onChangeSend: #changedReadOnly to: self
259
In an instance method, get the controller from the text editor widget,
and ask the controller for the selected text.
Ask the controllers view to reset its selections (to adjust for a
possible width change in the selection).
260
VisualWorks
Text Editors
Highlighting Text
It is occasionally useful for the application to highlight a text selection, for
example to indicate the result of a search.
To highlight text:
1
Write a method in the application model that gets the controller from
the widget.
Ask the controller to select the text between two endpoints (and ask it
to scroll the selection into view if necessary).
Aligning Text
By default, text in an editor is aligned at the left margin. For wordprocessing applications, you may want to center the text or align it at the
right margin. You can change the alignment by setting the text editors
Align property.
261
For the initial alignment setting, use the Details property page and set the
editors Align property to Left, Center, or Right.
Note: Alignment applies to the entire text. It cannot be applied
selectively to a portion of the text.
To change the alignment for the text editor widget programmatically:
1
In a method in the application model, get the widget from the builder.
Get a copy of the widgets text style. (Do not modify the widgets text
style directly, because that object is shared by many text editors in
the system.)
262
VisualWorks
Text Editors
#rightClicked
When a text editor is right clicked on with the <Operate> mouse
button, the text editor triggers the #rightClicked event. This event will
occur without regard to whether there is a popup menu associated
with the text editor.
#doubleClicked
When a text editor is double clicked on with the <Select> mouse
button, the text editor will trigger the #doubleClicked event. This event
is always immediately preceded by a #clicked event.
#gettingFocus
When a text editor receives focus, either by being tabbed to or by
clicking on by the mouse, the text editor triggers the #gettingFocus
event.
#losingFocus
When a text editor looses focus, either by being tabbed away from, or
by having another widget on the canvas gain focus, the text editor
triggers the #losingFocus event.
#tabbed
When a text editor has focus, and the Control-Tab key is pressed to
move the focus to the next widget in the tab order, the text editor
triggers the #tabbed event.
#scrollLeft
If while editing, navigating with the keyboard, selecting text with the
keyboard or mouse, or manipulating a horizontal scroll bar in a text
editor, the view scrolls to the left, the text editor triggers the #scrollLeft
event.
#scrollRight
If while editing, navigating with the keyboard, selecting text with the
keyboard or mouse, or manipulating a horizontal scroll bar in a text
editor, the view scrolls to the right, the text editor triggers the
#scrollRight event.
#scrollUp
If while editing, navigating with the keyboard, selecting text with the
keyboard or mouse, or manipulating a vertical scroll bar in a text
editor, the view scrolls up, the text editor triggers the #scrollUp event.
#scrollDown
If while editing, navigating with the keyboard, selecting text with the
keyboard or mouse, or manipulating a vertical scroll bar in a text
editor, the view scrolls down, the text editor triggers the #scrollDown
event.
263
Tree View
Description
Home
PageUp
Up
Ctrl+Up
Down
Ctrl+Down
264
PageDown
End
Left
Contract item
Contract item
Right
Expand item
Shift+Right
VisualWorks
Tree View
Key command
Description
Ctrl+Right
Expand item
Ctrl+W
any
Do string search
Basics
The properties on the Basics page are the usual ones.
Aspect
The name of the aspect instance variable and accessors. The aspect
must be either a SelectionInTree or a MultiSelectionInTree.
Details
The properties on the Details page are the same as for List, and are
mostly self-explanatory.
Advanced
The Item Text Emphasis items specify method selectors to specify text
formatting of a node label when the node is opened, closed, or a leaf
node.
Items
The Items page is specific to Tree View.
Display String
This property sets the selector to be sent to an item in order to retrieve its
textual representation.
GUI Developers Guide
265
Icons
None: Items will be displayed using the textual representation only.
Folders: Folder icons will be used.
User Defined: The selector that returns an items iconic representation.
Show Child Images: If checked, the TreeView will have a [+] image next
to child items, if expandable. If unchecked (the default), it will not have a
[+] next to the root item.
Show Root Image: If checked, the TreeView will have a [+] image next to
the Root item. If unchecked (the default), it will not have a [+] next to the
root item. Note that without the image, it is the applications responsibility
to show the root expanded.
Show Lines: If checked, includes connecting lines between parent and
child nodes.
In-Place Edited Selector: The selector that is used to notify an item
about a successful in-place edit. The corresponding method must take
one argument, which will be bound to the editing result (a String).
266
VisualWorks
Tree View
Programmatic Interface
Controller Interface
The TreeController supports these local menu items: expand, expandFully,
contractFully, and inplaceEdit.
The expand/contract methods operate on the currently selected item, the
current selectionIndex.
Also, Tree Views do not automatically expand upon opening. To expand
fully on open, define a postOpenWith: method in the application, such as
this:
postOpenWith: aBuilder
| treeWidget |
treeWidget := self widgetAt: #TreeView1.
treeWidget selectionIndex: 1.
treeWidget controller expandFully.
This opens the view with the first item selected. If you do not want to
leave an item selected, append this line:
treeWidget selectionIndex: 0
If the aspect is a MultiSelectionInTree, the expand/contract message is
applied to the first element in its OrderedCollection of elements. The order
of the elements is the order in which the elements were selected.
Model Interface
The widgets model is a TreeModel. The public interface consists of the
following methods to specify the root of a tree and its children. Both
instance methods and instance creation methods are provided.
Instance methods:
root: anObject
Set the root node and display it
root: anObject displayIt: aBoolean
Set the root node and determine whether the root itself should be
displayed or not
root: anObject displayIt: aBoolean childrenBlock: aBlock
Set the childrenBlock and the root node and determine whether the
root itself should be displayed or not
Class methods:
on: root
Provide a new instance initialized with the given root.
GUI Developers Guide
267
Use a Palette to add a Tree View widget to the canvas. Leave the list
selected.
On the Basics property page, fill in the lists Aspect property with the
name of the method that will return an instance of SelectionInTree.
Apply the change, install the canvas, and use define to add an instance
On the Advanced page in the GUI Painter Tool, enter a selector name
for each of the node conditions that you want to specify an emphasis
for. For example, to specify formatting for a closed node, enter a
selector name in the Opened Selector field. The selectors may be either
unary or single-argument keyword method names.
Install the canvas, and use Define to generate the new selectors.
The methods must return an Array of text emphases. For example, if the
unary selector is closedNode, and the emphasis is #italic, the method
would be:
closedNode
^#(#italic)
Standard text emphases are #bold, #italic, #serif, #underline, #strikeout,
#large, and #small.
268
VisualWorks
Tree View
269
#tabbed
When a tree view has focus, and the Tab key is pressed to move the
focus to the next widget in the tab order, the tree view triggers the
#tabbed event.
#backTabbed
When a tree view has focus, and the Back-Tab (Shift-Tab) key is
pressed in request to have the focus move to the previous widget in
the tab order, the tree view triggers the #backTabbed event.
#scrollLeft
If while navigating with the keyboard or manipulating a horizontal
scroll bar in a tree view, the tree view scrolls to the left, the tree view
triggers the #scrollLeft event.
#scrollRight
If while navigating with the keyboard or manipulating a horizontal
scroll bar in a tree view, the tree view scrolls to the right, the tree view
triggers the #scrollRight event.
#scrollUp
If while navigating with the keyboard or manipulating a vertical scroll
bar in a tree view, the tree view scrolls up, the tree view triggers the
#scrollUp event.
#scrollDown
If while navigating with the keyboard or manipulating a vertical scroll
bar in a tree view, the tree view scrolls down, the tree view triggers
the #scrollDown event.
#selectionChanging
When an item in a tree view is selected or unselected, or in the case
of a multiple select tree view, when the selections change, before the
change is applied, the tree view triggers the #selectionChanging event.
#selectionChanged
After an item in a tree view is selected or unselected, or in the case of
a multiple select tree view, when the selections have changed, the
tree view triggers the #selectionChanged event.
#selectionListChanged
Whenever the list underlying a tree view is manipulated, either by
changing a value, reordering, adding or removing items, or changing
the list as a whole, the tree view trigger the #selectionListChanged
event.
270
VisualWorks
Tree View
#itemExpanded
When an item in the tree view is visually toggled from its collapsed
view to its expanded view, the tree view triggers the #itemExpanded
event.
#itemCollapsed
When an item in the tree view is visually toggled from its expanded
view to its collapsed view, the tree view triggers the #itemCollapsed
event.
#itemEdited
If an item in a tree view has an in place editor defined, and that item
is edited, once the editing is completed the tree view triggers the
#itemEdited event.
271
View Holder
The View Holder widget places a custom view on the canvas. While the
interface to the View Holder widget is very simple, defining the custom
view can be quite complex. See Chapter 8, Custom Views, for more
information.
In the View Holders View: field, enter the selector for method that
returns an instance of the view, for example, #myView. Accept the
change and install the canvas.
272
VisualWorks
View Holder
#scrollRight
If while manipulating a horizontal scroll bar in a view holder, the view
holder scrolls to the right, the view holder triggers the #scrollRight
event.
#scrollUp
If while manipulating a vertical scroll bar in a view holder, the view
holder scrolls up, the view holder triggers the #scrollUp event.
#scrollDown
If while manipulating a vertical scroll bar in a view holder, the view
holder scrolls down, the view holder triggers the #scrollDown event.
273
Index
Symbols
& (menu mnemonic) 90, 92
<Operate> button 14
<Select> button 14
<Window> button 14
A
accessor method
adapting 78
widget aspect 30
action button 158
active window, accessing 54
adaptor
aspect of a model 78
buffered 81
custom 87
on a collection 85
on a collection element 86
value holder 77
Adaptor1Example 77
Adaptor2Example 79, 80
Adaptor3Example 83, 84
Adaptor4Example 85
Adaptor5Example 86
Adaptor6Example 87
adding
widgets to a canvas 29
AdvancedTreeViewExample class 264
aligning
widgets 43
application
model 31
nesting 242
Arrange menu
Align 44
Distribute 44
aspect adaptor 78
B
boolean
in a field 185
bordering a widget 29
bounded widget 40
BufferedValueHolder class 82
274
C
canvas
installing 31
opening an existing 32
tab order 47
Change Validation property 187
chart widget 162
check box
adding to UI 156
in menu 102
circle
See also ellipse
Click Map widget 167
closing a window 50
collapsing a window 58
collection
See also list widget 194, 202
adapting 85
adapting an element 86
color
label widget 198
ColorDDExample 110, 115, 117, 119, 122,
127
ColorExample 71
column widths
dataset 176
table 254
ComboBoxExample 170
ComboConversionExample 171
component, See widget
composite widget 43
VisualWorks
Index
D
damage
rectangle 150
window 57
data
formatting 186
types in input field 185
data series 162
labels 163
dataset columns
order 177
scrolling 177
widths 176
dataset widget
adding a row 179
row marker 179
Dataset1Example 174
Dataset2Example 179
Dataset3Example 180
date
in a field 185
dependency
adding 72
between widgets 71
bypassing 72
removing 72
DependencyExample 72
desiresFocus message 148
dialog
custom 140
get file name 134
textual 133
warning 131
yes-no 132
dimension
of a window 56
disabling
menus 98
widgets 70
displaying
in a view 145
domain model
adapting an aspect 78
connecting to view 144
updating view 146
doughnut labels 166
drag and drop 108130
adding 110
dropping on a list item 123
effect symbol 115
examining dragged data 126
framework classes 109
modifier keys 126
multiple selections 112
responding to a drop 121
visual feedback 114
Drag OK property 110
Drag Start property 110
DragDropContext class 109, 114
DragDropData class 109, 111
DragDropManager class 109, 112, 113, 122
Drop property 113, 121
drop source 108, 110
adding 110
setting up 108
drop target 108, 113
button 117
changing button label 117
examining dragged data 126
list item 119, 123
messages 114
providing visual feedback 114
responding to a drop 121
setting up 108
tracking a specific list item 119
using modifier keys 126
DropSource class 109, 112
275
Index
E
editing
a list 202
editor widget 259
Editor1Example 259
effect symbol 115, 122
See also target emphasis
electronic mail 16
elements
adapting 86
ellipse
grouping widgets 226
Ellipse property 226
embedded canvas
See subcanvas
Entry property 113, 114
events
activate 62
and dependents 76
backTabbed 156, 157, 160, 173, 181,
193, 196, 207, 212, 221, 239, 251, 258,
270
bounceBottom 240
bounceTop 240
bounds 62
cellBackTabbed 182
cellGettingFocus 182
cellLosingFocus 182
cellSelectionChanged 258
cellTabbed 182
cellValueChanged 182
changed 172, 193, 211, 224, 227, 236,
238, 247, 262
changing 172, 192, 211, 227, 236, 238,
247, 262
checked 158
clicked 64, 155, 157, 159, 169, 173, 193,
196, 207, 211, 230, 238, 257, 262, 269
close 62
closing 64
collapse 63
columnLabelClicked 182
columnSelectionChanged 258
deactivate 63
destroy 63
doubleClicked 65, 173, 181, 193, 196,
207, 239, 257, 263, 269
enter 63
exit 63
expand 63
expose 63
276
Index
spunUp 239
submenuClosed: 107
submenuOpened: 106
tabbed 155, 157, 160, 173, 181, 193,
196, 207, 212, 221, 239, 251, 258, 263,
270
tabChanged 252
tabChanging 252
toolBarButtonSelected: 107
toolBarCreated 66
turnedOff 156
turnedOn 156
unchecked 158
unknownEvent 63
unmapped 64
verticalTabChanged 222
verticalTabChanging 222
window 61
wrapAroundBottom 240
wrapAroundTop 240
examples 18
Exit property 113
Exit Validation property 187
expanding
windows 58
exploding labels 166
F
field
connecting to a field 191
creating 184
dialog 133
filtering and validating 187
formatting numbers 186
highlighting 192
menu 189
type restriction 185
widget, connecting to a slider 231
FieldConnectionExample 191
FieldMenuExample 189
FieldSelectionExample 192
FieldTypeExample 186
FieldValidation1Example 188
FieldValidInputExample 187
file name
dialog 134
fill-in-the-blank dialog 133
filtering
field input 187
resource list 23
fixed-point number
in a field 185
GUI Developers Guide
fly-by help 30
font
changing widgets 45
label 198
Font1Example 68
fonts 13
formatting
displayed data 186
numeric field 186
G
globalization 30
graphic image
in menu 101
graphic label 198
graphical user interface 2875
GraphicsContext class 145
graying out, See disabling
H
help
fly-by help 30
HideExample 69, 70
hiding
widgets 69
windows 51
Hierarchical List 194
highlighting
in a field 192
in a list 206
holder, See value holder
I
icon
assign to window 59
creating 58
in a menu 101
registering 59
iconifying a window 58
IdentityDictionary class 112
IndentedTreeSelectionInList class 194
IndexedAdaptor class 86
Initially Disabled property 70
Initially Invisible property 69
input field, See field
installing a canvas 31
instance
used in drag and drop 109
interface
integrating a custom view 152
reusing 244
interface component, See widget
interface specification 31
277
Index
internationalization 30
invalidateRectangle 151
invalidating a view 150
K
KeyboardProcessor 148
L
label
table columns 256
table rows 256
window 56
label widget
changing at runtime 199
color 198
creating 198
font 198
graphic 198
registry of labels 200
labels
adding to a chart 163
doughnut 166
exploding 166
Layout commands
Be Bounded 40
Relative 38, 40
Unbounded 40
LineExample 225
List class 202
list widget
adding 194, 202
connecting two lists 206
controlling textual representation 202
editing the list 202
highlighting style 206
List1Example 202
List2Example 241, 243, 244
LogoExample 198
LookPreferences class 71
lookup key 30
M
mail
electronic 16
marker in a slider 235
menu
check box in 102
creating 91
icon 101
in a field 189
item label 101
mnemonics 90, 92
modifying at runtime 98
278
pragma 103
shortcut character 91
menu bar 93
Menu Bar property 36, 94
menu button widget 94, 210
Menu Editor 89
MenuCommandExample 94, 95, 96, 98, 211
MenuEditorExample 90, 96, 97
MenuModifyExample 98, 99, 100
MenuSwapExample 100
MenuValueExample 92, 94, 95, 102, 210
message catalog 30
mnemonic 199, 226
model: message 150
mouse buttons 14
<Operate> button 14
<Select> button 14
<Window> button 14
Multi Select property 113
MultiSelectionInList class 113, 204
MultiSelectionInTree class 267
N
nesting applications 242
NoController class 150
nontextual collection 202
notational conventions 13
notebook widget
changing the page 219
index tabs 215
minor keys 216, 218
secondary tabs 216
starting page 161, 215
tab selection 215
Notebook1Example 213, 215
Notebook2Example 216
Notebook3Example 218
Notebook4Example 220
notification properties 7475
notifier
dialog 131
number
field formatting 186
in a field 185
NumberPrintPolicy class 186
O
object
in a field 186
opening
canvases 48
VisualWorks
Index
specs 48
windows 47
options
doughnut labels 166
exploding labels 166
order of tabbing 47
Over property 113, 114
P
page in a notebook 161, 215
pane, See view
Pareto chart 164
partner windows 60
password in a field 185
picture chart 164
sample data 164
pie chart 166
definition 166
doughnut labels 166
exploding labels 166
PluggableAdaptor class 87
pointer shape, See effect symbol
positioning a widget 40
Print property 171
properties of windows and widgets 29
R
radio button 154
range
in a slider 233
Read property 171
redisplaying a view 150
refreshing a window 57
region widget 225
registering an interest 71
registry
of labels 200
relative sizing of widget 39
Resource Finder 23
reuse techniques 241247
reusing an interface 244
row selector in a dataset 179
S
sample data
picture chart 164
XY chart 165
ScheduledControllers object 54
Screen 55
SelectionInList class 85, 174, 202, 213
SelectionInTable class 253
SelectionInTree class 268
SimpleDialog class 141
GUI Developers Guide
Size1Example 39, 41
Size2Example 40, 42
Size3Example 68
sizing widgets 38
Sketch 142, 146
SketchController 142, 150
SketchView 144, 145, 146, 150, 151, 152
slider widget
adding 231
connecting to field 231
marker length 235
modifying range 233
read-only 231
two-dimensional 235
Slider1Example 231, 233
Slider2Example 184, 232, 235
spacing
a group of widgets 44
special symbols 13
spin button widget
adding 238
StringPrintPolicy class 186
subcanvas
accessing embedded widget 246
in a notebook 219
Subcanvas1Example 241
Subcanvas2Example 243, 244
Subcanvas3Example 245, 246
subject of an adaptor 78
substituting a menu 100
support, technical
electronic mail 16
World Wide Web 16
symbol in a field 185
symbols used in documentation 13
synchronizing updates 81
T
tab order 47
tabbing
Can Tab property 47
order 47
TabControlExample 248
table widget
connecting to input field 255
labeling 256
updating 255
Table1Example 253
Table2Example 255
Table3Example 256
TableInterface class 253
target emphasis 119, 123
279
Index
technical support
electonic mail 16
World Wide Web 16
text
editor, See editor widget
in a field 185
TextAttributes 68
textual dialog 133
time
in a field 185
time stamp
in a field 185
TimestampPrintPolicy class 186
title, See window label
tools
Resource Finder 23
UIBuilder 48
traverse UI 47
TreeViewExample class 264
true-false dialog 132
two-dimensional slider 235
Type property 185
TypeConverter 186
typographic conventions 13
U
UIBuilder 48
unbounded widget 40, 42
updating
a table 255
a view 146
an aspect adaptor 79
buffered 81
V
validating field input 187
validation properties 73, 187
value holder 77
view
connecting to controller 147
connecting to model 144
creating 143
displaying 145
integrating in interface 152
invalidating 150
redisplaying 150
updating 146
with no controller 150
View Holder widget 152
visibility of a widget 69
visual component, See widget
280
W
warning dialog 131
widget
accessing programmatically 66
aligning 43, 44
border 29
bounding 40
disable 70
drop source, See drop source
drop target, See drop target
embedded in subcanvas 246
font 45
groups 43
hiding 69
notification property 74
positioning 40
region 225
sizing 38
spacing 44
tab order 47
unbounded 42
validating actions 73
validation property 73
widgets
composite 43
group 43
WidgetWrapper 67
width
of dataset columns 176
of table columns 254
window
active 54
at a location 55
closing 50
creating 28
events 61
expanding and collapsing 58
get dimensions 56
hiding 51
label 56
menu bar 93
opening 47
position 35
refreshing 57
set initial size 34
specification 48
World Wide Web 16
wrapper 67
VisualWorks
Index
X
XY chart 165
sample data 165
Y
yes-no dialog 132
281
Method Index
A
contextWidget: 111
contextWindow: 111
controller: 150
controllerAt: 53
accessWith:assignWith: 80
adapt:aspect:list:selection: 85
addItemLabel:value: 99
alignment: 262
applyColorDrop: 122
applyColorEnter: 115
applyColorExit: 115, 116
applyColorOver: 115, 116
applyMoreColorEnter: 117
applyMoreColorExit: 117
applyMoreColorOver: 117
asValue 77
atNameKey: 96
definedNamedFonts 46
disable 70
display 57
displayBox: 56
displayOn: 145
doDragDrop 112
drag-ok 110
drag-start 110
drop 122
backgroundColor: 71
beginSubMenuLabeled: 92
beInvisible 69
beMaster 60
beOff 103
beOn 103
bePartner 60
beSlave 60
beTwoDimensional 235
beVisible 69
bounds 68
C
changed: 80, 146
changed:with: 88, 146
changeRequest 50
choose:fromList:values:lines:cancel: 136
choose:labels:values:default: 133
clearAll 206
client:spec: 220, 245
clientData 123
closeRequest 50
collapse 58
colorDrag: 111, 123
colorLayerEnter: 119
colorLayerExit: 119
colorLayerOver: 119
colorWantToDrag: 111
contextApplication: 111
282
enable 70, 98
endSubMenu 93
expand 58
expandedMenu 190
F
forAspect: 79
foregroundColor: 71
forIndex: 86
G
getBlock:putBlock:updateBlock: 87
globalCursorPoint 55
grid: 234
H
hideItem: 99
I
icon: 59
interfaceSpecFor: 245
invalidate 260, 262
invalidateRectangle: 151
invalidateRectangle:repairNow: 151
K
key: 111
keyboardHook: 188
VisualWorks
Method Index
L
label: 56, 199
labelAt:put: 200
labelImage: 102
labelString: 69, 117, 199
subject: 80, 86
subject:triggerChannel: 83
subjectChannel: 79, 86
subjectSendsUpdates: 80
submenu 96
mainWindow 53
menuAt: 96
menuItems 97
model: 145
unhideItem: 99
update:with: 147
nameKey 97
newBoolean 78
newBounds: 68
newFraction 78
newString 78
O
onChangeSend:to: 72
openDialogInterface: 140
openIn: 50
openWithExtent: 49
openWithSpec: 48
U
V
visualAt:put: 200
visuals 201
W
widgetAt: 53, 66
windowAt: 55
windowMenuBar 53
windowSpec 48
wrapperAt: 53, 67
P
postBuildWith: 188, 191
R
rangeStart: 234
rangeStop: 234
removeItem: 100
replaceSelectionWith: 260
requestFileName: 134
resetSelections 260
retractInterestsFor: 72
S
selectAll 205
selectAndScrollFrom:to: 261
selection: 215
selectionBackgroundColor: 71
selectionForegroundColor: 71
selectionIndex: 215
selectionIndexes: 205
selections 113
selections: 205
setValue: 73
showDropFeedbackIn:allowScrolling: 120
source: 48
sourceData 122
styleNamed: 68
283
Date:
# Months
FAX
IT!
# Weekly # Monthly
# Daily
# No
# Yes
# No
# Yes
# Less
# Years
# Yes
# No
Please comment.
General comment:
P46-0136-01