<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="09-widgets.css" type="text/css" title="Widgets" charset="UTF-8"?>
<XML>
<Heading1>
<A ID="pgfId-1042365"></A>
<A ID="Widgets"></A>
Widgets</Heading1>
<Heading2>
<A ID="pgfId-1040346"></A>
Widget Basics</Heading2>
<Heading3>
<A ID="pgfId-1040873"></A>
<A ID="Place a widget on a canvas"></A>
Place a widget on a canvas</Heading3>
<Body1>
<A ID="pgfId-1040874"></A>
Use the <A href="03-tools.xml#id(Palette)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Palette</A> to choose the widget you would like to add to the canvas, and then click once on the canvas. A representation of the widget appears at the cursor point; click a second time to drop it into place on the canvas.</Body1>
<Body1>
<A ID="pgfId-1042198"></A>
To place multiple copies of the same widget, use the <Glossary>
multi-place</Glossary>
 button (upper-right corner of the Palette Tool). With this button on, each subsequent click on the canvas will generate a new copy of the selected widget.</Body1>
<Heading3>
<A ID="pgfId-1040885"></A>
<A ID="Change the size of a widget"></A>
Change the size of a widget</Heading3>
<Body1>
<A ID="pgfId-1040886"></A>
To modify a resizable widget, drag its selection handles to resize it on the canvas (note that check boxs, labels, and radio buttons cannot be resized by dragging.) To make a multiply-selected group of widgets all equal in height, width, or both, use the <UI-Label>
Arrange-&gt;Equalize...</UI-Label>
 command in the <A href="03-tools.xml#id(GUI Painter Tool)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">GUI Painter Tool</A> menu (or one of the iconic equalize buttons.)</Body1>
<Body1>
<A ID="pgfId-1040887"></A>
To arrange for a widget to adjust its size in relation to that of the window, use the <UI-Label>
Layout-&gt;Relative</UI-Label>
 command in the Canvas Tool menu. Both the horizontal and vertical dimensions of the widget are adjusted when the widget size is set to be <UI-Label>
Relative</UI-Label>
.</Body1>
<Body1>
<A ID="pgfId-1040888"></A>
To set a widget&#39;s size to be fixed in relation to that of the window, use the <UI-Label>
Layout-&gt;Fixed</UI-Label>
 command in the Canvas Tool.</Body1>
<Heading3>
<A ID="pgfId-1040899"></A>
Set a widget&#39;s boundaries</Heading3>
<Body1>
<A ID="pgfId-1040900"></A>
To convert an unbounded widget into a bounded one, use the <UI-Label>
Layout-&gt;Be Bounded</UI-Label>
 command in the <A href="03-tools.xml#id(GUI Painter Tool)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">GUI Painter Tool</A> menu.</Body1>
<Body1>
<A ID="pgfId-1042350"></A>
Alternately, select the <UI-Label>
Bounded</UI-Label>
 button in the GUI Painter Tool, <UI-Label>
Position</UI-Label>
 page:</Body1>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-1.gif" show="embed" actuate="auto"/>
</DIV>
<Body1>
<A ID="pgfId-1052277"></A>
To reverse the operation, use the <UI-Label>
Layout-&gt;Be Unbounded</UI-Label>
 command in the Canvas Tool menu.</Body1>
<Heading3>
<A ID="pgfId-1041074"></A>
Set a widget&#39;s properties</Heading3>
<Body1>
<A ID="pgfId-1041078"></A>
To focus the <A href="03-tools.xml#id(GUI Painter Tool)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">GUI Painter Tool</A> on a particular widget, select the widget. The GUI Painter Tool can also be used to set properties on a group of widgets, or a multiple selection.</Body1>
<Heading2>
<A ID="pgfId-1041069"></A>
Positioning Widgets</Heading2>
<Heading3>
<A ID="pgfId-1041068"></A>
Position a widget</Heading3>
<Body1>
<A ID="pgfId-1040912"></A>
Use click-and-drag to position a widget on the canvas. To toggle a fence around the edge of the canvas, preventing any element from being dragged outside its bounding box, use the <UI-Label>
Grid -&gt; Keep In Window</UI-Label>
 command in the <A href="03-tools.xml#id(GUI Painter Tool)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">GUI Painter Tool</A>.</Body1>
<Body1>
<A ID="pgfId-1040913"></A>
To arrange for a widget to adjust its position in relation to that of the window, use the <UI-Label>
Layout-&gt;Relative</UI-Label>
 command in the Canvas Tool menu. Both the horizontal and vertical positioning of the widget are adjusted when the widget location is set to be <UI-Label>
Relative</UI-Label>
.</Body1>
<Heading3>
<A ID="pgfId-1040925"></A>
<A ID="Align a group of widgets"></A>
Align a group of widgets</Heading3>
<Body1>
<A ID="pgfId-1040926"></A>
To adjust the alignment of widgets on the canvas, select a series of widgets, and use the <UI-Label>
Arrange-&gt;Align...</UI-Label>
 command in the &lt;Operate&gt; menu.</Body1>
<Body1>
<A ID="pgfId-1041887"></A>
In the Align dialog, use <UI-Label>
on horizontal line</UI-Label>
 when aligning widgets side-by-side, and <UI-Label>
on vertical line</UI-Label>
 when aligning widgets in a column. Select <UI-Label>
first selection</UI-Label>
 to align the widgets using the first selected widget; select <UI-Label>
merged box</UI-Label>
 to align the widgets using the merged bounding box of all the selected widgets. Widgets are aligned through edges or centers.</Body1>
<Body1>
<A ID="pgfId-1041783"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041787"></A>
<A href="09-widgets.xml#id(Adjust the space between widgets)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Adjust the space between widgets</A></Bullet1>
<Heading3>
<A ID="pgfId-1040941"></A>
<A ID="Adjust the space between widgets"></A>
Adjust the space between widgets</Heading3>
<Body1>
<A ID="pgfId-1040942"></A>
To adjust the spacing of widgets on the canvas, select a series of widgets, and use the <UI-Label>
Arrange-&gt;Distribute...</UI-Label>
 command in the &lt;Operate&gt; menu.</Body1>
<Body1>
<A ID="pgfId-1041890"></A>
In the Distribute dialog, use <UI-Label>
left to right</UI-Label>
 when spacing widgets side-by-side, and <UI-Label>
top to bottom</UI-Label>
 when spacing widgets in a column. Specify whether widgets should be spaced between edges or centers. For <UI-Label>
constant spacing between edges</UI-Label>
 you must specify the number of pixels to place between each pair of widgets.</Body1>
<Body1>
<A ID="pgfId-1041804"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041808"></A>
<A href="09-widgets.xml#id(Align a group of widgets)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Align a group of widgets</A></Bullet1>
<Heading3>
<A ID="pgfId-1040956"></A>
Group a number of widgets</Heading3>
<Body1>
<A ID="pgfId-1040957"></A>
To group a number of widgets, use &lt;Shift&gt; click or click-and-drag to select them, and then select <UI-Label>
Arrange-&gt;Group</UI-Label>
 in the &lt;Operate&gt; menu.</Body1>
<Body1>
<A ID="pgfId-1041891"></A>
To ungroup the widgets, select <UI-Label>
Arrange-&gt;Ungroup</UI-Label>
.</Body1>
<Heading3>
<A ID="pgfId-1041104"></A>
Make a widget&#39;s origin fixed</Heading3>
<Body1>
<A ID="pgfId-1041105"></A>
Making a widget fixed is useful when the window&#39;s size is fixed. When the window&#39;s size is variable, this approach works best for a button or other fixed-size widget that is located along the left or top edges of the window. </Body1>
<StepStart>
<A ID="pgfId-1041107"></A>
Select the widget and go to the <UI-Label>
Position</UI-Label>
 page in the GUI Painter Tool.</StepStart>
<StepCont>
<A ID="pgfId-1041108"></A>
Set the (<UI-Label>
L</UI-Label>
)eft and (<UI-Label>
T</UI-Label>
)op <UI-Label>
Proportions</UI-Label>
 to 0. </StepCont>
<StepCont>
<A ID="pgfId-1041109"></A>
Set the (<UI-Label>
L</UI-Label>
)eft and (<UI-Label>
T</UI-Label>
)op <UI-Label>
Offsets</UI-Label>
 to the desired distance from the window&#39;s left and top edges, specified in pixels.</StepCont>
<StepCont>
<A ID="pgfId-1041110"></A>
Set the (<UI-Label>
R</UI-Label>
)ight and (<UI-Label>
B</UI-Label>
)ottom proportion and offset parameters to give the desired size and scaling behavior:</StepCont>
<Bullet1>
<A ID="pgfId-1041111"></A>
For a fixed-size widget, set right and left, and top and bottom proportions equal, and the size specified by offsets.</Bullet1>
<Bullet1>
<A ID="pgfId-1041112"></A>
For a variable size widget, set the right and bottom proportions larger than the left and top, and make additional size adjustments with offsets.</Bullet1>
<StepCont>
<A ID="pgfId-1041113"></A>
<UI-Label>
Apply</UI-Label>
 the properties.</StepCont>
<Body1>
<A ID="pgfId-1041823"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Size1.pcl" show="embed" actuate="auto">
Size1Example
</CodeExample>
(start the example and then resize the window to see the effect)</Body1>
<Heading3>
<A ID="pgfId-1041114"></A>
Make a widget&#39;s origin relative</Heading3>
<Body1>
<A ID="pgfId-1041115"></A>
To allow the size of widgets to scale as the window changes size, use a relative origin.</Body1>
<Body1>
<A ID="pgfId-1041906"></A>
This causes the widget to move farther away from the left and/or top edges of the window when the window grows, and closer when the window shrinks. </Body1>
<StepStart>
<A ID="pgfId-1041117"></A>
Select the widget and go to the <UI-Label>
Position</UI-Label>
 page in the GUI Painter Tool.</StepStart>
<StepCont>
<A ID="pgfId-1041118"></A>
Set the (<UI-Label>
L</UI-Label>
)eft and (<UI-Label>
T</UI-Label>
)op <UI-Label>
Proportions</UI-Label>
 to the scaling factor for the widget to the window. This sets vertical and horizontal baselines for the widget&#39;s orgin. </StepCont>
<StepCont>
<A ID="pgfId-1041119"></A>
Set the (<UI-Label>
L</UI-Label>
)eft and (<UI-Label>
T</UI-Label>
)op <UI-Label>
Offsets</UI-Label>
 to shift the widget from that vertical and horizontal baselines.</StepCont>
<StepCont>
<A ID="pgfId-1041120"></A>
Set the (<UI-Label>
R</UI-Label>
)ight and (<UI-Label>
B</UI-Label>
)ottom proportion and offset parameters to give the desired size and scaling behavior:</StepCont>
<Bullet1>
<A ID="pgfId-1041121"></A>
For a fixed-size widget, set right and left, and top and bottom proportions equal, and the size specified by offsets.</Bullet1>
<Bullet1>
<A ID="pgfId-1041122"></A>
For a variable size widget, set the right and bottom proportions larger than the left and top, and make additional size adjustments with offsets.</Bullet1>
<StepCont>
<A ID="pgfId-1041123"></A>
<UI-Label>
Apply</UI-Label>
 the properties.</StepCont>
<Body1>
<A ID="pgfId-1041829"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Size1.pcl" show="embed" actuate="auto">
Size1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041322"></A>
Position a widget relative to the right or bottom edge</Heading3>
<Body1>
<A ID="pgfId-1041323"></A>
You can fix a widget&#39;s position relative to the right and/or bottom edge of its containing window. Typically, the widget itself is a fixed size.</Body1>
<StepStart>
<A ID="pgfId-1041324"></A>
Select a widget and go to the <UI-Label>
Position</UI-Label>
 page in the GUI Painter Tool.</StepStart>
<StepCont>
<A ID="pgfId-1052217"></A>
Set the <UI-Label>
Bounded</UI-Label>
 positioning button, if necessary (for labels and buttons).</StepCont>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-2.gif" show="embed" actuate="auto"/>
</DIV>
<Body1>
<A ID="pgfId-1052229"></A>
Set the proportions:</Body1>
<Bullet1>
<A ID="pgfId-1041331"></A>
To follow the right edge, set the <I>
right</I>
 and <I>
left</I>
 <UI-Label>
Proportion</UI-Label>
 values to 1.0. </Bullet1>
<Bullet1>
<A ID="pgfId-1041332"></A>
To follow the bottom edge, set the <I>
top</I>
 and <I>
bottom</I>
 <UI-Label>
Proportion</UI-Label>
 values to 1.0.</Bullet1>
<StepCont>
<A ID="pgfId-1041333"></A>
Set the offsets:</StepCont>
<Bullet1>
<A ID="pgfId-1041334"></A>
To set a fixed space from the right edge, set the right offset to a negative number of pixels (e.g., -5), and the left offset to an appropriate value to set the width.</Bullet1>
<Bullet1>
<A ID="pgfId-1041335"></A>
To set a fixed space from the bottom edge, set the bottom offset to a negative number of pixels (e.g., -5), and the top offset to an appropriate value to set the height.</Bullet1>
<StepCont>
<A ID="pgfId-1041336"></A>
<UI-Label>
Apply</UI-Label>
 the changes.</StepCont>
<Body1>
<A ID="pgfId-1041337"></A>
For example, a reasonably sized action button that stays five pixels from the right bottom corner would have these settings:</Body1>
<Bullet1>
<A ID="pgfId-1041338"></A>
All proportions set to 1</Bullet1>
<Bullet1>
<A ID="pgfId-1041339"></A>
Left offset: -55</Bullet1>
<Bullet1>
<A ID="pgfId-1041340"></A>
Top offset: -30</Bullet1>
<Bullet1>
<A ID="pgfId-1041341"></A>
Right offset: -5</Bullet1>
<Bullet1>
<A ID="pgfId-1041342"></A>
Bottom offset: -5</Bullet1>
<Heading3>
<A ID="pgfId-1041124"></A>
Set an unbounded widget&#39;s position</Heading3>
<Body1>
<A ID="pgfId-1041125"></A>
Unbounded widgets (such as buttons and labels) do not have fixed left, right, top, and bottom edges, because they adjust their sizes to fit a changing label. Instead of positioning these widgets by edge position, you position them by a reference point, which is, by default, the widget&#39;s origin (top-left corner).</Body1>
<StepStart>
<A ID="pgfId-1041126"></A>
Select an unbounded widget and go to the <UI-Label>
Position</UI-Label>
 page in the GUI Painter Tool.</StepStart>
<StepCont>
<A ID="pgfId-1041127"></A>
Set the <UI-Label>
Unbounded</UI-Label>
 positioning button, if necessary:</StepCont>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-3.gif" show="embed" actuate="auto"/>
</DIV>
<StepCont>
<A ID="pgfId-1041128"></A>
Set the reference point for the widget by changing the <UI-Label>
x</UI-Label>
 and <UI-Label>
y</UI-Label>
 values. The most common reference points are:</StepCont>
<Body1>
<A ID="pgfId-1052305"></A>
0.0, 0.0 -- top-left corner (origin)
0.5, 0.5 -- center
1.0, 1.0 -- bottom right corner</Body1>
<StepCont>
<A ID="pgfId-1041150"></A>
Set the <UI-Label>
X</UI-Label>
 and <UI-Label>
Y</UI-Label>
 <UI-Label>
Proportions</UI-Label>
 to 0 to give the widget a fixed position, or to a scaling factor to cause it to move in a dimension as the window scales. </StepCont>
<StepCont>
<A ID="pgfId-1041151"></A>
Set the <UI-Label>
X</UI-Label>
 and <UI-Label>
Y</UI-Label>
 <UI-Label>
Offsets</UI-Label>
 to adjust the widget&#39;s position relative to the scaling position.</StepCont>
<StepCont>
<A ID="pgfId-1041152"></A>
<UI-Label>
Apply</UI-Label>
 the properties.</StepCont>
<Heading3>
<A ID="pgfId-1041153"></A>
Set a widget&#39;s position programmatically</Heading3>
<StepStart>
<A ID="pgfId-1041157"></A>
Get the widget&#39;s wrapper from the application model&#39;s builder.</StepStart>
<StepCont>
<A ID="pgfId-1041159"></A>
For a relative shift in position, send a <Code>
moveBy:</Code>
 message to the wrapper. The argument is a <Code>
Point</Code>
 whose <Code>
x</Code>
 and <Code>
y</Code>
 values indicate the number of pixels by which the widget is to be shifted.</StepCont>
<CodeSample>
<A ID="pgfId-1041160"></A>
moveArrowUp
		| wrapper |
		wrapper := (self builder componentAt: #arrow).

		&quot;If the arrow is not too high, raise it another notch.&quot;
		wrapper bounds origin y &gt; 30
			ifTrue: [wrapper moveBy: 0@-5]</CodeSample>
<StepCont>
<A ID="pgfId-1041168"></A>
To apply an absolute position, send a <Code>
moveTo:</Code>
 message to the wrapper. The argument is a <Code>
Point</Code>
 whose coordinates are the desired position of the widget.</StepCont>
<CodeSample>
<A ID="pgfId-1041169"></A>
resetArrow
		| wrapper |
		wrapper := (self builder componentAt: #arrow).
		wrapper moveTo: self arrowOrigin</CodeSample>
<Body1>
<A ID="pgfId-1041835"></A>
In <Code>
MoveExample</Code>
, a graphic label is repositioned by three buttons, giving the effect of a pointer on a meter. The <UI-Label>
Up</UI-Label>
 and <UI-Label>
Down</UI-Label>
 buttons shift the position relative to the prior position, while the <UI-Label>
Reset</UI-Label>
 button moves the widget to an absolute position.</Body1>
<Body1>
<A ID="pgfId-1041852"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Move.pcl" show="embed" actuate="auto">
MoveExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041173"></A>
<A ID="Align a group of widgets"></A>
Align a group of widgets</Heading3>
<StepStart>
<A ID="pgfId-1041175"></A>
In a canvas, select the widgets to be aligned.</StepStart>
<StepCont>
<A ID="pgfId-1041176"></A>
In the Canvas Tool, select the <UI-Label>
Arrange-&gt;Align</UI-Label>
 command.</StepCont>
<StepCont>
<A ID="pgfId-1041177"></A>
In the Align dialog, select <UI-Label>
on horizontal line</UI-Label>
 when aligning side-by-side widgets. When aligning widgets in a column, select <UI-Label>
on vertical line</UI-Label>
.</StepCont>
<StepCont>
<A ID="pgfId-1041178"></A>
In the Align dialog, select <UI-Label>
first selection</UI-Label>
 when the widgets are to be aligned with the first widget that was selected. Select <UI-Label>
merged box</UI-Label>
 to align the widgets on a line halfway between the two most extreme positions within the group of widgets.</StepCont>
<StepCont>
<A ID="pgfId-1041179"></A>
In the Align dialog, select the edges, or the centers, to be aligned.</StepCont>
<StepCont>
<A ID="pgfId-1041180"></A>
<UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1041181"></A>
Distribute a group of widgets</Heading3>
<Body1>
<A ID="pgfId-1041182"></A>
To make the spaces between a group of widgets equal:</Body1>
<StepStart>
<A ID="pgfId-1041183"></A>
In a canvas, select the widgets to be spaced.</StepStart>
<StepCont>
<A ID="pgfId-1041184"></A>
In the Canvas Tool, select the <UI-Label>
Align-&gt;Distribute</UI-Label>
 command.</StepCont>
<StepCont>
<A ID="pgfId-1041185"></A>
In the Distribute dialog, select <UI-Label>
left to right</UI-Label>
 for widgets that are to be spaced in a horizontal row. Select <UI-Label>
top to bottom</UI-Label>
 for columnar distribution.</StepCont>
<StepCont>
<A ID="pgfId-1041186"></A>
In the Distribute dialog, select the type of spacing. For <UI-Label>
constant spacing between edges</UI-Label>
, you must specify the number of pixels to place between each pair of widgets.</StepCont>
<StepCont>
<A ID="pgfId-1041187"></A>
<UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading2>
<A ID="pgfId-1041194"></A>
Sizing Widgets</Heading2>
<Heading3>
<A ID="pgfId-1041195"></A>
Size a widget on the canvas</Heading3>
<Body1>
<A ID="pgfId-1041196"></A>
When a widget is placed on the canvas and selected, it has selection &#34;handles.&#34;</Body1>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-4.gif" show="embed" actuate="auto"/>
</DIV>
<Body1>
<A ID="pgfId-1041202"></A>
To resize the widget visually, select and drag one of its handles until the widget is the correct size.</Body1>
<Heading3>
<A ID="pgfId-1041203"></A>
Set a widget&#39;s size in pixels</Heading3>
<StepStart>
<A ID="pgfId-1041205"></A>
Select the widget in the canvas, and open the <UI-Label>
Position</UI-Label>
 page in the GUI Painter Tool (or use <UI-Label>
Layout-&gt;Constrained...</UI-Label>
).</StepStart>
<StepCont>
<A ID="pgfId-1041206"></A>
Select the <UI-Label>
Bounded</UI-Label>
 widget positioning button if there&#39;s an option (for buttons and labels only):</StepCont>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-5.gif" show="embed" actuate="auto"/>
</DIV>
<StepCont>
<A ID="pgfId-1041207"></A>
Set all <UI-Label>
Proportion</UI-Label>
 settings to 0. </StepCont>
<StepCont>
<A ID="pgfId-1041208"></A>
Set (<UI-Label>
L</UI-Label>
)eft, (<UI-Label>
R</UI-Label>
)ight, (<UI-Label>
T</UI-Label>
)op, and (<UI-Label>
B</UI-Label>
)ottom <UI-Label>
Offset</UI-Label>
 values to set the widget&#39;s size:</StepCont>
<Body1>
<A ID="pgfId-1041216"></A>
width in pixels = <UI-Label>
R - L</UI-Label>
</Body1>
<Body1>
<A ID="pgfId-1052246"></A>
height in pixels = <UI-Label>
B - T</UI-Label>
</Body1>
<Body1>
<A ID="pgfId-1052247"></A>
The width and height must each be at least 1.</Body1>
<StepCont>
<A ID="pgfId-1041217"></A>
Click <UI-Label>
Apply</UI-Label>
 to accept the change.</StepCont>
<Body1>
<A ID="pgfId-1041218"></A>
The widget&#39;s size is currently fixed. To make it relative but keeping this current size, select <UI-Label>
Layout-&gt;Relative</UI-Label>
.</Body1>
<Heading3>
<A ID="pgfId-1041219"></A>
Make widget sizes equal</Heading3>
<Body1>
<A ID="pgfId-1041220"></A>
To make several widgets all be the same size:</Body1>
<StepStart>
<A ID="pgfId-1041221"></A>
Select the widgets to equalize. You can drag a selection box around the widgets, or shift-click to add widgets to the selection.</StepStart>
<StepCont>
<A ID="pgfId-1041222"></A>
Select <UI-Label>
Arrange-&gt;Equalize...</UI-Label>
 in the canvas menu.</StepCont>
<StepCont>
<A ID="pgfId-1041223"></A>
Select the equalization options in the dialog and click <UI-Label>
OK</UI-Label>
. </StepCont>
<Heading3>
<A ID="pgfId-1041224"></A>
Make a widget&#39;s size and position fixed</Heading3>
<Body1>
<A ID="pgfId-1041225"></A>
To make a widget&#39;s <I>
size</I>
 and <I>
origin</I>
 constant when the window changes size:</Body1>
<StepStart>
<A ID="pgfId-1041226"></A>
In a canvas, select the widget whose size is to be fixed.</StepStart>
<StepCont>
<A ID="pgfId-1041227"></A>
Select <UI-Label>
Layout-&gt;Fixed</UI-Label>
 in the canvas menu.</StepCont>
<Body1>
<A ID="pgfId-1042339"></A>
This sets all proportion parameters for the widget to 0, and sets its size in terms of offsets only. You can make these settings manually in the GUI Painter Tool or using the <UI-Label>
Layout-&gt;Constrained...</UI-Label>
 dialog.</Body1>
<Heading3>
<A ID="pgfId-1042341"></A>
<A ID="Make a widget’s size and position relative"></A>
Make a widget&#39;s size and position relative</Heading3>
<Body1>
<A ID="pgfId-1041231"></A>
To make a widget&#39;s <I>
size</I>
 and <I>
origin</I>
 relative when the window changes size:</Body1>
<StepStart>
<A ID="pgfId-1041232"></A>
In a canvas, select the widget whose size is to be fixed.</StepStart>
<StepCont>
<A ID="pgfId-1041233"></A>
Select <UI-Label>
Layout-&gt;Relative</UI-Label>
 in the canvas menu.</StepCont>
<Body1>
<A ID="pgfId-1041234"></A>
This sets all offset parameters for the widget to 0, and sets its size in terms of proportions only. You can make these settings manually in the GUI Painter Tool or using the <UI-Label>
Layout-&gt;Constrained...</UI-Label>
 dialog.</Body1>
<Heading3>
<A ID="pgfId-1041235"></A>
Set a widget&#39;s origin and size</Heading3>
<Body1>
<A ID="pgfId-1041236"></A>
Use the <UI-Label>
Proportion</UI-Label>
 and <UI-Label>
Offset</UI-Label>
 settings in the <UI-Label>
Position</UI-Label>
 page of the GUI Painter Tool to adjust a widget&#39;s size and position.</Body1>
<Body1>
<A ID="pgfId-1041237"></A>
The <UI-Label>
Proportion</UI-Label>
 identifies a vertical (for <UI-Label>
R</UI-Label>
 and <UI-Label>
L</UI-Label>
) or horizontal (for <UI-Label>
T</UI-Label>
 and <UI-Label>
B</UI-Label>
) line the specified percentage between the extremes (0 and 1). Offsets are specified relative to that line, and may be positive or negative integers. </Body1>
<StepStart>
<A ID="pgfId-1041238"></A>
Select the widget and go to the GUI Painter Tool <UI-Label>
Position</UI-Label>
 page.</StepStart>
<StepCont>
<A ID="pgfId-1041239"></A>
Set the <UI-Label>
Bounded</UI-Label>
 positioning button, if necessary (for labels and buttons).</StepCont>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-6.gif" show="embed" actuate="auto"/>
</DIV>
<StepCont>
<A ID="pgfId-1041244"></A>
Set <UI-Label>
Proportion</UI-Label>
 values between 0 and 1 (inclusive) to set the baseline for the widget&#39;s edges between the window&#39;s (<UI-Label>
L</UI-Label>
)eft, (<UI-Label>
R</UI-Label>
)ight, (<UI-Label>
T</UI-Label>
)op, and (<UI-Label>
B</UI-Label>
)ottom border. For example, 0.3 sets the baseline 1/3 of the way between the window borders.</StepCont>
<StepCont>
<A ID="pgfId-1041245"></A>
To make a widget&#39;s size <I>
fixed</I>
, set the <UI-Label>
Proportion</UI-Label>
 values for the top and bottom equal, and for the right and left equal. </StepCont>
<Body1>
<A ID="pgfId-1041246"></A>
Vertical and horizontal proportions can be different. The widget&#39;s size will be specified entirely by offsets.</Body1>
<StepCont>
<A ID="pgfId-1041247"></A>
Set the position of each of the widget&#39;s edges relative to its baseline using offset values, in pixels. Positive values are to the right or below the baseline; negative values are to the left or above the baseline.</StepCont>
<StepCont>
<A ID="pgfId-1041248"></A>
<UI-Label>
Apply</UI-Label>
 the changes. </StepCont>
<Heading3>
<A ID="pgfId-1041270"></A>
Make a widget&#39;s size relative</Heading3>
<Body1>
<A ID="pgfId-1041272"></A>
To allow a widget to expand and shrink as with the window, set the widget size to be relative.</Body1>
<Body1>
<A ID="pgfId-1041273"></A>
To set a widget to size itself in 1-to-1 ratio with the window, simply select the widget and pick the <UI-Label>
Layout-&gt;Relative</UI-Label>
 command.</Body1>
<Body1>
<A ID="pgfId-1041274"></A>
For more complicated situations, or for more precise control, you can set properties on the <UI-Label>
Position</UI-Label>
 page of the GUI Painter Tool.</Body1>
<Body1>
<A ID="pgfId-1041941"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Size1.pcl" show="embed" actuate="auto">
Size1Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041932"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041936"></A>
<A href="09-widgets.xml#id(Make a widget’s size and position relative)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Make a widget&#39;s size and position relative</A> </Bullet1>
<Heading3>
<A ID="pgfId-1041275"></A>
Make widget bounded/unbounded</Heading3>
<Body1>
<A ID="pgfId-1041277"></A>
You can make an unbounded widget bounded, so its size and position can be managed precisely. Care must be taken, however, because font (especially of different platforms) or label changes may cause the label to expand beyond the widget&#39;s boundaries.</Body1>
<StepStart>
<A ID="pgfId-1041279"></A>
In a canvas, select the unbounded widget.</StepStart>
<StepCont>
<A ID="pgfId-1041280"></A>
Select <UI-Label>
Layout-&gt;Be Bounded</UI-Label>
. </StepCont>
<Body1>
<A ID="pgfId-1041281"></A>
Alternatively, select the Bounded button in the GUI Painter Tool, <UI-Label>
Position</UI-Label>
 page, and <UI-Label>
Apply</UI-Label>
 the change. </Body1>
<Body1>
<A ID="pgfId-1041282"></A>
To return the widget to unbounded, select <UI-Label>
Layout-&gt;Unbounded</UI-Label>
, or select the <UI-Label>
Unbounded</UI-Label>
 button:</Body1>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-7.gif" show="embed" actuate="auto"/>
</DIV>
<Heading3>
<A ID="pgfId-1041289"></A>
Change widget&#39;s size programmatically</Heading3>
<Body1>
<A ID="pgfId-1041290"></A>
To resize a widget at runtime:</Body1>
<StepStart>
<A ID="pgfId-1041292"></A>
Set the widget&#39;s <UI-Label>
ID</UI-Label>
 property.</StepStart>
<StepCont>
<A ID="pgfId-1041293"></A>
Get the widget&#39;s wrapper from the application model&#39;s builder, by sending a <Code>
componentAt:</Code>
 message to the builder, with the widget&#39;s <UI-Label>
ID</UI-Label>
 as argument.</StepCont>
<StepCont>
<A ID="pgfId-1041294"></A>
Send a <Code>
bounds</Code>
 message to the wrapper to get the widget&#39;s existing size.</StepCont>
<StepCont>
<A ID="pgfId-1041295"></A>
Create a rectangle having the desired origin and extent, using the widget&#39;s bounding rectangle to derive the new values.</StepCont>
<StepCont>
<A ID="pgfId-1041296"></A>
Send a <Code>
newBounds:</Code>
 message to the wrapper, with the rectangle as the argument.</StepCont>
<CodeSample>
<A ID="pgfId-1041297"></A>
expandBox
		| wrapper oldSize newSize |
		wrapper := <CodeEmp>
self builder componentAt: #box</CodeEmp>
.
		oldSize := <CodeEmp>
wrapper bounds</CodeEmp>
.

		&quot;If the box is bigger than the window already, do nothing.&quot;
		oldSize origin x &lt; 0
			ifTrue: [^nil].

		&quot;Expand the bounding rectangle by 10 pixels on each side.&quot;
		newSize := Rectangle
			origin: oldSize origin - 10
			<CodeEmp>
corner: oldSize corner + 10</CodeEmp>
.

		&quot;Assign the new bounding rectangle to the widget wrapper.&quot;
		<CodeEmp>
wrapper newBounds: newSize</CodeEmp>
.</CodeSample>
<Body1>
<A ID="pgfId-1041957"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Size3.pcl" show="embed" actuate="auto">
Size3Example</CodeExample>
</Body1>
<Heading2>
<A ID="pgfId-1041091"></A>
Widget Appearance</Heading2>
<Heading3>
<A ID="pgfId-1041747"></A>
Set a widget&#39;s label</Heading3>
<StepStart>
<A ID="pgfId-1041748"></A>
Edit the <UI-Label>
Label</UI-Label>
 properties on the <UI-Label>
Basics</UI-Label>
 page.</StepStart>
<StepCont>
<A ID="pgfId-1042243"></A>
Set <UI-Label>
String</UI-Label>
 to contain the label that appears on the widget, and <UI-Label>
Message</UI-Label>
 to be the action method.</StepCont>
<StepCont>
<A ID="pgfId-1042244"></A>
To have the application provide the text of the label, enable the <UI-Label>
Supplied By Application</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1042245"></A>
Select <UI-Label>
Apply &amp; Close</UI-Label>
.</StepCont>
<Heading3>
<A ID="pgfId-1041090"></A>
Change a widget&#39;s font</Heading3>
<StepStart>
<A ID="pgfId-1040984"></A>
Select the widget.</StepStart>
<StepCont>
<A ID="pgfId-1042252"></A>
Choose the desired font on the <UI-Label>
Details</UI-Label>
 page of the GUI Painter Tool.</StepCont>
<Heading3>
<A ID="pgfId-1041353"></A>
Set or remove a widget&#39;s border</Heading3>
<StepStart>
<A ID="pgfId-1041355"></A>
Select a widget in a canvas.</StepStart>
<StepCont>
<A ID="pgfId-1041356"></A>
To apply a border to the widget, turn on its <UI-Label>
Border</UI-Label>
 property on the <UI-Label>
Details</UI-Label>
 panel of the GUI Painter Tool.</StepCont>
<StepCont>
<A ID="pgfId-1041357"></A>
To remove the border, turn off the <UI-Label>
Border</UI-Label>
 property on the <UI-Label>
Details</UI-Label>
 panel of the GUI Painter Tool.</StepCont>
<StepCont>
<A ID="pgfId-1041358"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1041359"></A>
Set a widget&#39;s font property</Heading3>
<Body1>
<A ID="pgfId-1041360"></A>
You can use the <UI-Label>
Font</UI-Label>
 menu in the widget&#39;s properties to choose an alternative font. The built-in fonts are:</Body1>
<Bullet1>
<A ID="pgfId-1041361"></A>
<UI-Label>
Default</UI-Label>
 </Bullet1>
<Bullet1>
<A ID="pgfId-1041362"></A>
<UI-Label>
Fixed</UI-Label>
, for a fixed-width font that is useful when you want to align text in columns</Bullet1>
<Bullet1>
<A ID="pgfId-1041363"></A>
<UI-Label>
Large</UI-Label>
, for a font that is slightly larger than the default</Bullet1>
<Bullet1>
<A ID="pgfId-1041364"></A>
<UI-Label>
Small</UI-Label>
, for a font that is slightly smaller than the default</Bullet1>
<Bullet1>
<A ID="pgfId-1041365"></A>
<UI-Label>
System</UI-Label>
, for a font that matches the current platform&#39;s system font, when available</Bullet1>
<Heading3>
<A ID="pgfId-1041366"></A>
Set a widget&#39;s font programmatically</Heading3>
<StepStart>
<A ID="pgfId-1041369"></A>
In a method in the application model, get the widget from the application model&#39;s builder.</StepStart>
<StepCont>
<A ID="pgfId-1041371"></A>
Create an instance of <Code>
TextAttributes</Code>
 corresponding to the new font. If the font exists in the fonts menu, you can send a <Code>
styleNamed:</Code>
 message to the <Code>
TextAttributes</Code>
 class. The argument is the name of the font (for example, <Code>
#large</Code>
 for the system&#39;s <UI-Label>
Large</UI-Label>
 font).</StepCont>
<StepCont>
<A ID="pgfId-1041373"></A>
Get the label from the widget by sending a <Code>
label</Code>
 message; get the text of the label by sending a <Code>
text</Code>
 message to it. Then install a blank text temporarily as a means of erasing the old label if the new font is smaller.</StepCont>
<StepCont>
<A ID="pgfId-1041375"></A>
Install the new font in the widget by sending a <Code>
textStyle:</Code>
 message to the widget. The argument is the <Code>
TextAttributes</Code>
 you created in step 2.</StepCont>
<StepCont>
<A ID="pgfId-1041377"></A>
Reinstate the original label by sending a <Code>
labelString:</Code>
 message to the widget.</StepCont>
<CodeSample>
<A ID="pgfId-1041378"></A>
changedFont
		| widget newStyle oldLabel |
		widget := (self builder componentAt: #label) widget.
		newStyle := TextAttributes styleNamed: (self labelFont value).

	&quot;Erase the existing label in case its font is larger than the new one.&quot;
		oldLabel := widget label text.
		widget labelString: &#39;&#39;.

		&quot;Install the new font.&quot;
		widget textStyle: newStyle.&quot;

		&quot;Reinstate the original label.&quot;
		widget labelString: oldLabel.</CodeSample>
<Body1>
<A ID="pgfId-1041981"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Font1.pcl" show="embed" actuate="auto">
Font1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041392"></A>
Hide/display a widget</Heading3>
<StepStart>
<A ID="pgfId-1041395"></A>
Select the widget.</StepStart>
<StepCont>
<A ID="pgfId-1041396"></A>
On the <UI-Label>
Details</UI-Label>
 page of the GUI Painter Tool, set the <UI-Label>
Initially Invisible</UI-Label>
 property to set the widget&#39;s visibility when the window opens.</StepCont>
<StepCont>
<A ID="pgfId-1041397"></A>
Get the widget&#39;s wrapper by sending <Code>
componentAt:</Code>
 to the builder.</StepCont>
<StepCont>
<A ID="pgfId-1041398"></A>
To hide the widget, send a <Code>
beInvisible</Code>
 message to the wrapper.</StepCont>
<StepCont>
<A ID="pgfId-1041399"></A>
To make the widget visible again, send a <Code>
beVisible</Code>
 message to the wrapper.</StepCont>
<CodeSample>
<A ID="pgfId-1041400"></A>
changedListVisibility
		| wrapper desiredState |
		wrapper := <CodeEmp>
self builder componentAt: #colorList</CodeEmp>
.
		desiredState := self listVisibility value.

		desiredState == #hidden
			ifTrue: [<CodeEmp>
wrapper beInvisible</CodeEmp>
].

		desiredState == #disabled
			ifTrue: [
				<CodeEmp>
wrapper beVisible</CodeEmp>
.
				wrapper disable].

		desiredState == #normal
			ifTrue: [
				wrapper enable.
				wrapper beVisible].</CodeSample>
<Body1>
<A ID="pgfId-1042001"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Hide.pcl" show="embed" actuate="auto">
HideExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041417"></A>
Disable/enable a widget</Heading3>
<Body1>
<A ID="pgfId-1041419"></A>
You can disable a widget, causing it to be displayed in gray.</Body1>
<Body1>
<A ID="pgfId-1042269"></A>
This deactivates the controller so the widget does not respond to user input.</Body1>
<StepStart>
<A ID="pgfId-1041420"></A>
Select the widget.</StepStart>
<StepCont>
<A ID="pgfId-1041421"></A>
On the <UI-Label>
Details</UI-Label>
 page of the GUI Painter Tool, set the <UI-Label>
Initially Disabled</UI-Label>
 property to set the widget&#39;s visibility when the window opens.</StepCont>
<StepCont>
<A ID="pgfId-1041422"></A>
Get the widget&#39;s wrapper by sending <Code>
componentAt:</Code>
 to the builder.</StepCont>
<StepCont>
<A ID="pgfId-1041424"></A>
To disable the widget, send a <Code>
disable</Code>
 message to the wrapper.</StepCont>
<StepCont>
<A ID="pgfId-1041426"></A>
To make the widget active again, send an <Code>
enable</Code>
 message to the wrapper.</StepCont>
<CodeSample>
<A ID="pgfId-1041427"></A>
changedListVisibility
		| wrapper desiredState |
		wrapper := <CodeEmp>
self builder componentAt: #colorList</CodeEmp>
.
		desiredState := self listVisibility value.

		desiredState == #hidden
			ifTrue: [wrapper beInvisible].

		desiredState == #disabled
			ifTrue: [
				wrapper beVisible.
				<CodeEmp>
wrapper disable</CodeEmp>
].

		desiredState == #normal
			ifTrue: [
				<CodeEmp>
wrapper enable</CodeEmp>
.
				wrapper beVisible].</CodeSample>
<Body1>
<A ID="pgfId-1042024"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Hide.pcl" show="embed" actuate="auto">
HideExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041756"></A>
Set a widget&#39;s icon</Heading3>
<StepStart>
<A ID="pgfId-1042279"></A>
Select the widget.</StepStart>
<StepCont>
<A ID="pgfId-1041757"></A>
On the Basics Page of the GUI Painter Tool, set the <UI-Label>
Label</UI-Label>
 properties to be the name of a method that supplies a graphic, enable the <UI-Label>
Label Is Image</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1042286"></A>
Select <UI-Label>
Apply &amp; Close</UI-Label>
.</StepCont>
<Heading3>
<A ID="pgfId-1041444"></A>
Set the widget tab order</Heading3>
<Body1>
<A ID="pgfId-1041445"></A>
By default, the tab order between widgets is the order in which they were added.</Body1>
<Body1>
<A ID="pgfId-1041446"></A>
You should disable tabbing for a text editor if the editor should interpret the Tab key as a character.</Body1>
<StepStart>
<A ID="pgfId-1041447"></A>
To add a widget to the tab sequence, check its <UI-Label>
Can Tab</UI-Label>
 property on the <UI-Label>
Details</UI-Label>
 page of the GUI Painter Tool.</StepStart>
<StepCont>
<A ID="pgfId-1041448"></A>
To set the tab order, select the first widget in the sequence, then hold down the Shift key while you select each widget in the desired tabbinbg order.</StepCont>
<StepCont>
<A ID="pgfId-1041449"></A>
Select the <UI-Label>
Arrange-&gt;Bring To Front</UI-Label>
 command. </StepCont>
<StepCont>
<A ID="pgfId-1041450"></A>
<UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading2>
<A ID="pgfId-1041348"></A>
Coloring Widgets</Heading2>
<Heading3>
<A ID="pgfId-1041482"></A>
<A ID="Set a widget’s colors"></A>
Set a widget&#39;s colors</Heading3>
<StepStart>
<A ID="pgfId-1041484"></A>
In a canvas, select a widget(s) you wish to color.</StepStart>
<StepCont>
<A ID="pgfId-1113126"></A>
In the GUI Painter Tool, select the <UI-Label>
Color</UI-Label>
 page in the GUI Painter Tool. </StepCont>
<StepCont>
<A ID="pgfId-1041485"></A>
Widgets have four color zones: <UI-Label>
Foreground</UI-Label>
, <UI-Label>
Background</UI-Label>
, <UI-Label>
Selection foreground</UI-Label>
, and <UI-Label>
Selection background</UI-Label>
. By default, these are set to <UI-Label>
none</UI-Label>
, which means that the widget inherits its colors from its window).</StepCont>
<StepCont>
<A ID="pgfId-1042291"></A>
Select the desired color from the color chart and click on the zone you wish to define. To revert the zone to <UI-Label>
none</UI-Label>
, click on the zone a second time. Use the slider controls to fine-adjust the color. The vertical slider work with a color-cube model, while the horizontal sliders work with a hue-saturation-value model.</StepCont>
<StepCont>
<A ID="pgfId-1041487"></A>
Repeat for each color zone.</StepCont>
<StepCont>
<A ID="pgfId-1041661"></A>
To display the policy for the most recently active User-Interface Painter window or currently selected widget, toggle the <UI-Label>
Read</UI-Label>
 button. The policy will be displayed in the color zones at the bottom of the tool.</StepCont>
<StepCont>
<A ID="pgfId-1041488"></A>
Apply the properties.</StepCont>
<Heading3>
<A ID="pgfId-1041489"></A>
Set a widget&#39;s colors programmatically</Heading3>
<StepStart>
<A ID="pgfId-1041491"></A>
Get the widget&#39;s wrapper by sending a <Code>
componentAt:</Code>
 message.</StepStart>
<StepCont>
<A ID="pgfId-1041492"></A>
Get the widget&#39;s <Code>
LookPreferences</Code>
 from its wrapper. </StepCont>
<StepCont>
<A ID="pgfId-1041493"></A>
Create a copy of the preferences by setting a color zone value, by sending <Code>
foregroundColor:</Code>
, <Code>
backgroundColor:</Code>
, <Code>
selectionForegroundColor:</Code>
, or <Code>
selectionBackgroundColor:</Code>
, with a color as argument.</StepCont>
<StepCont>
<A ID="pgfId-1041495"></A>
Install the new <Code>
LookPreferences</Code>
 by sending a <Code>
lookPreferences:</Code>
 message to the wrapper. </StepCont>
<CodeSample>
<A ID="pgfId-1041496"></A>
foregroundColor: aColor
		&quot;For each sample widget, change the indicated color layer.&quot;

		| wrapper lookPref |
		self sampleWidgets do: [ :widgetID |
			wrapper := (<CodeEmp>
self builder componentAt: widgetID</CodeEmp>
).
			lookPref := wrapper 
				<CodeEmp>
lookPreferences foregroundColor: aColor</CodeEmp>
.
			<CodeEmp>
wrapper lookPreferences: lookPref</CodeEmp>
].</CodeSample>
<Body1>
<A ID="pgfId-1042051"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Color.pcl" show="embed" actuate="auto">
ColorExample</CodeExample>
</Body1>
<Heading2>
<A ID="pgfId-1040869"></A>
Accessing Widgets</Heading2>
<Heading3>
<A ID="pgfId-1041510"></A>
Make a widget &lt;Tab&gt; selectable</Heading3>
<StepStart>
<A ID="pgfId-1041511"></A>
Select the widget.</StepStart>
<StepCont>
<A ID="pgfId-1042302"></A>
Enable the <UI-Label>
Can Tab</UI-Label>
 setting on the <UI-Label>
Details</UI-Label>
 page of the GUI Painter Tool.</StepCont>
<Body1>
<A ID="pgfId-1042064"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042068"></A>
<A href="09-widgets.xml#id(Change tabbing order)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Change tabbing order</A> </Bullet1>
<Heading3>
<A ID="pgfId-1041529"></A>
<A ID="Change tabbing order"></A>
Change tabbing order</Heading3>
<Body1>
<A ID="pgfId-1041530"></A>
To set the order of tab-selectable widgets on a canvas, hold down the &lt;Shift&gt; key and select the desired order of all the widgets; then select the <UI-Label>
Arrange-&gt;Bring To Front</UI-Label>
 command in the Canvas Tool. The new tabbing order will take effect when you <UI-Label>
Install</UI-Label>
 the canvas.</Body1>
<Heading3>
<A ID="pgfId-1040347"></A>
Access a widget programmatically</Heading3>
<StepStart>
<A ID="pgfId-1040350"></A>
Using the GUI Painter Tool, set the widget&#39;s <UI-Label>
ID</UI-Label>
 property to an identifying name for the widget (in the example, <Code>
#comment</Code>
). Apply the properties and install the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040352"></A>
In a method in the application model that needs to access the widget, send a <Code>
componentAt:</Code>
 message to the application model&#39;s builder with the widget&#39;s <UI-Label>
ID</UI-Label>
. </StepCont>
<StepCont>
<A ID="pgfId-1040354"></A>
Send a <Code>
widget</Code>
 message to the object returned by step 2.</StepCont>
<CodeSample>
<A ID="pgfId-1040355"></A>
alignCenter
		| widget style |
		widget := <CodeEmp>
(self builder componentAt: #comment) widget</CodeEmp>
.
		style := widget textStyle copy.
		style alignment: 2.
		widget textStyle: style.
		widget invalidate.</CodeSample>
<Body1>
<A ID="pgfId-1040362"></A>
In some cases, the application model must send messages to the <A href="10-glossary.xml#id(wrapper)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">wrapper</A> instead of the widget.</Body1>
<Body1>
<A ID="pgfId-1042098"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Editor1.pcl" show="embed" actuate="auto">
Editor1Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1042089"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042093"></A>
<A href="09-widgets.xml#id(Access a widget’s wrapper programmatically)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Access a widget&#39;s wrapper programmatically</A> </Bullet1>
<Heading3>
<A ID="pgfId-1040363"></A>
Refresh a widget programmatically</Heading3>
<Body1>
<A ID="pgfId-1040364"></A>
To force a widget to redraw itself, send the message <Code>
#invalidate</Code>
 to the widget. </Body1>
<StepStart>
<A ID="pgfId-1040366"></A>
Using the GUI Painter Tool, set the widget&#39;s <UI-Label>
ID</UI-Label>
 property to an identifying name for the widget (in the example, <Code>
#comment</Code>
). Apply the properties and install the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040367"></A>
In a method in the application model that needs to access the widget, send a <Code>
componentAt:</Code>
 message to the application model&#39;s builder with the widget&#39;s <UI-Label>
ID</UI-Label>
. </StepCont>
<StepCont>
<A ID="pgfId-1040368"></A>
Send a <Code>
widget</Code>
 message to the object returned by step 2.</StepCont>
<CodeSample>
<A ID="pgfId-1040369"></A>
alignCenter
		| widget style |
		widget := (self builder componentAt: #comment) widget.
		style := widget textStyle copy.
		style alignment: 2.
		widget textStyle: style.
		widget invalidate.</CodeSample>
<Body1>
<A ID="pgfId-1042109"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Editor1.pcl" show="embed" actuate="auto">
Editor1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040378"></A>
<A ID="Access a widget’s wrapper programmatically"></A>
Access a widget&#39;s wrapper programmatically</Heading3>
<Body1>
<A ID="pgfId-1040379"></A>
Some widget properties are controlled by the widget&#39;s wrapper rather than the widget itself.</Body1>
<StepStart>
<A ID="pgfId-1040381"></A>
Using the GUI Painter Tool, set the widget&#39;s <UI-Label>
ID</UI-Label>
 property to an identifying name for the widget. Apply the properties and install the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040382"></A>
In a method in the application model, send a <Code>
componentAt:</Code>
 message to the application model&#39;s builder with the widget&#39;s <UI-Label>
ID</UI-Label>
.</StepCont>
<StepCont>
<A ID="pgfId-1040383"></A>
Send appropriate messages to the wrapper object.</StepCont>
<CodeSample>
<A ID="pgfId-1040384"></A>
changedListVisibility
		| wrapper desiredState |
		wrapper := <B>
self builder componentAt: #colorList</B>
.
		desiredState := self listVisibility value.

		desiredState == #hidden
			ifTrue: [wrapper beInvisible].

		desiredState == #disabled
			ifTrue: [
				wrapper beVisible.
				wrapper disable].
		desiredState == #normal
			ifTrue: [wrapper enable; beVisible].</CodeSample>
<Body1>
<A ID="pgfId-1042122"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Hide.pcl" show="embed" actuate="auto">
HideExample</CodeExample>
</Body1>
<Heading2>
<A ID="pgfId-1040724"></A>
Widget Dependencies</Heading2>
<Heading3>
<A ID="pgfId-1040726"></A>
Add a dependency</Heading3>
<Body1>
<A ID="pgfId-1040730"></A>
To declare a dependency, send an <Code>
onChangeSend:to:</Code>
 message to the widget&#39;s <A href="10-glossary.xml#id(value holder)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value holder</A>. The first argument is a message selector to send to the second argument, which is typically the application model itself.</Body1>
<Body1>
<A ID="pgfId-1040731"></A>
A dependency is typically declared in the <Code>
initialize</Code>
 method.</Body1>
<CodeSample>
<A ID="pgfId-1040732"></A>
initialize
		colorNames := SelectionInList with: ColorValue constantNames.
		selectedColor := String new asValue.
		fieldIsDependent := false asValue.

		&quot;Arrange for the application model to take action when the
		check box is turned on or off.&quot;
		fieldIsDependent 
			onChangeSend: #changedDependency to: self.</CodeSample>
<Body1>
<A ID="pgfId-1042142"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Depend.pcl" show="embed" actuate="auto">
DependencyExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040741"></A>
Remove a dependency </Heading3>
<StepStart>
<A ID="pgfId-1040746"></A>
Send a <Code>
retractInterestsFor:</Code>
 message to the widget&#39;s value holder. The argument is the object that registered the interest, typically the application model itself.</StepStart>
<StepCont>
<A ID="pgfId-1040747"></A>
To re-establish the dependency, register the interest again.</StepCont>
<CodeSample>
<A ID="pgfId-1040748"></A>
changedDependency
		&quot;Turn on or off the dependency link between the list and
		the input field, depending on the value of the check box.&quot;

		| valueModel |
		valueModel := self colorNames selectionIndexHolder.

		self fieldIsDependent value
			ifTrue:
				[<CodeEmp>
valueModel onChangeSend: #changedSelection
					to: self</CodeEmp>
]
			ifFalse: 
				[<CodeEmp>
valueModel retractInterestsFor: self</CodeEmp>
].</CodeSample>
<Body1-Keep>
<A ID="pgfId-1042161"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Depend.pcl" show="embed" actuate="auto">
DependencyExample</CodeExample>
</Body1-Keep>
<Heading3>
<A ID="pgfId-1040761"></A>
Bypass all dependencies</Heading3>
<Body1>
<A ID="pgfId-1040762"></A>
Your application can bypass dependencies, but since this disables the automatic update features of value models you must explicitly update views programmatically. </Body1>
<StepStart>
<A ID="pgfId-1040765"></A>
Send a <Code>
setValue:</Code>
 message to the widget&#39;s <A href="10-glossary.xml#id(value holder)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value holder</A> instead of the usual <Code>
value:</Code>
 message. The argument is the widget&#39;s new value.</StepStart>
<StepCont>
<A ID="pgfId-1040767"></A>
Get the widget from the application model&#39;s builder and ask the widget to update itself with the new value.</StepCont>
<CodeSample>
<A ID="pgfId-1040768"></A>
changedB
		&quot;Use setValue: to bypass dependents,
		thus avoiding circularity.&quot;
		self bSquared setValue: (self b value raisedTo: 2).

		&quot;Since dependents were bypassed
		when the model was updated,
		update the view manually.&quot;
		(self builder componentAt: #b2) widget update: #value.</CodeSample>
<Body1>
<A ID="pgfId-1042182"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="FldCon.pcl" show="embed" actuate="auto">
FieldConnectionExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1040057"></A>
</Body1>
<Heading2>
<A ID="pgfId-1041039"></A>
Labels</Heading2>
<Heading3>
<A ID="pgfId-1040892"></A>
<A ID="Add a label to a canvas"></A>
Add a label to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040893"></A>
Use a label widget to place a single line label on a canvas. </Body1>
<StepStart>
<A ID="pgfId-1040896"></A>
Place a label widget on the canvas, and select it. </StepStart>
<StepCont>
<A ID="pgfId-1066760"></A>
On the Basics page of the GUI Painter Tool, enter the label text in its <UI-Label>
Label</UI-Label>
 property field.</StepCont>
<StepCont>
<A ID="pgfId-1040897"></A>
Click <UI-Label>
Apply</UI-Label>
, and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1071182"></A>
For formatted text, use a <Code>
ComposedText</Code>
 or <Code>
Text</Code>
 object in a graphic label.</Body1>
<Body1>
<A ID="pgfId-1066749"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Logo.pcl" show="embed" actuate="auto">
LogoExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1066694"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1066730"></A>
<A href="09-widgets.xml#id(Add a multi-line label to a canvas)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a multi-line label to a canvas</A> </Bullet1>
<Bullet1>
<A ID="pgfId-1066734"></A>
<A href="09-widgets.xml#id(Change a text label at runtime)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Change a text label at runtime</A></Bullet1>
<Bullet1>
<A ID="pgfId-1066739"></A>
<A href="09-widgets.xml#id(Add a graphic label to a canvas)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a graphic label to a canvas</A></Bullet1>
<Heading3>
<A ID="pgfId-1066736"></A>
<A ID="Add a multi-line label to a canvas"></A>
Add a multi-line label to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040899"></A>
To add a multi-line label to a canvas, either use a separate label widget for each line, or use a read-only text widget.</Body1>
<Body1>
<A ID="pgfId-1071003"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1071004"></A>
<A href="09-widgets.xml#id(Add a label to a canvas)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a label to a canvas</A></Bullet1>
<Bullet1>
<A ID="pgfId-1071009"></A>
<A href="09-widgets.xml#id(81736)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a text editor to a canvas</A></Bullet1>
<Heading3>
<A ID="pgfId-1040900"></A>
<A ID="Add a graphic label to a canvas"></A>
Add a graphic label to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040901"></A>
Use a graphic label to add a graphical element to an interface. The graphic can be static, or can change while the application is running.</Body1>
<StepStart>
<A ID="pgfId-1040906"></A>
Place a label widget on the canvas, and select it. </StepStart>
<StepCont>
<A ID="pgfId-1071027"></A>
On the Basics page of the GUI Painter Tool, enter the name of the resource method for the graphic in in the <UI-Label>
Label</UI-Label>
 field. </StepCont>
<StepCont>
<A ID="pgfId-1040907"></A>
Check the <UI-Label>
Label is Image</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1040908"></A>
Click <UI-Label>
Apply</UI-Label>
, and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040909"></A>
Create the graphic image resource method using the Image Editor or other means, and install it in the application model. Name the resource method with the name in the <UI-Label>
Label</UI-Label>
 property.</StepCont>
<Body1>
<A ID="pgfId-1071088"></A>
For a large graphic, insert the graphic in a view holder.</Body1>
<Body1>
<A ID="pgfId-1071016"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Logo.pcl" show="embed" actuate="auto">
LogoExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1071064"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1071070"></A>
<A href="09-widgets.xml#id(Add a label to a canvas)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a label to a canvas</A></Bullet1>
<Bullet1>
<A ID="pgfId-1071073"></A>
&#34;Working with Graphics and Images&#34; in the VisualWorks GUI Developer&#39;s Guide.</Bullet1>
<Heading3>
<A ID="pgfId-1071067"></A>
<A ID="Change a text label at runtime"></A>
Change a text label at runtime</Heading3>
<Body1>
<A ID="pgfId-1040911"></A>
You can change the content of a text label while the application is running. </Body1>
<StepStart>
<A ID="pgfId-1071149"></A>
Get the widget from the application model&#39;s builder with a <Code>
componentAt:</Code>
 message.</StepStart>
<StepCont>
<A ID="pgfId-1040915"></A>
Send a <Code>
labelString:</Code>
 message to the widget, with the new label string as argument.</StepCont>
<Body1>
<A ID="pgfId-1040916"></A>
For formatted text, use a <Code>
ComposedText</Code>
 or <Code>
Text</Code>
 object in a graphic label.</Body1>
<Body1>
<A ID="pgfId-1071109"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Logo.pcl" show="embed" actuate="auto">
LogoExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1071114"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1071168"></A>
<A href="09-widgets.xml#id(Change a graphic label at runtime)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Change a graphic label at runtime</A></Bullet1>
<Heading3>
<A ID="pgfId-1040939"></A>
<A ID="Change a graphic label at runtime"></A>
Change a graphic label at runtime</Heading3>
<StepStart>
<A ID="pgfId-1071153"></A>
Get the widget from the application model&#39;s builder with a <Code>
componentAt:</Code>
 message.</StepStart>
<StepCont>
<A ID="pgfId-1040942"></A>
Send a <Code>
label:</Code>
 message to it, with the new graphic as argument.</StepCont>
<CodeSample>
<A ID="pgfId-1040943"></A>
animateLogo
		&quot;Display the logo in successively larger sizes
		(as a way of demonstrating dynamic updating
		of a graphic label).&quot;

		| logo widget view animationRegion |
		logo := self class logo.
		widget := self builder componentAt: #logo.
		animationRegion := widget bounds.
		view := self builder composite.

		10 to: 1 by: -1 do: [ :factor |
			(Delay forMilliseconds: 100) wait.
			widget label: (logo shrunkenBy: factor @ factor).
			view invalidateRectangle: animationRegion repairNow: true]</CodeSample>
<Body1>
<A ID="pgfId-1071133"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Logo.pcl" show="embed" actuate="auto">
LogoExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040958"></A>
Set a label&#39;s font, emphasis, and color</Heading3>
<Body1>
<A ID="pgfId-1040959"></A>
You can set certain font characteristics programmatically, and change them dynamically, by setting the label text to a <Code>
Text</Code>
 or <Code>
ComposedText</Code>
 object.</Body1>
<Body1>
<A ID="pgfId-1040961"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Logo.pcl" show="embed" actuate="auto">
LogoExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1071160"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1071161"></A>
<A href="09-widgets.xml#id(Change a graphic label at runtime)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Change a graphic label at runtime</A></Bullet1>
<Heading3>
<A ID="pgfId-1071185"></A>
<A ID="Reuse a label"></A>
Reuse a label</Heading3>
<Body1>
<A ID="pgfId-1071192"></A>
If you plan to use the same label repeatedly, such as a company name or logo, you can store it in a registry.</Body1>
<Body1>
<A ID="pgfId-1071209"></A>
To use a label in a registry, enter the label&#39;s lookup key in place of the resource method name in the widget&#39;s <UI-Label>
Label</UI-Label>
 property. </Body1>
<Body1>
<A ID="pgfId-1071215"></A>
The system checks a registry if it does not find a resource method.</Body1>
<Body1>
<A ID="pgfId-1071199"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1071200"></A>
<A href="09-widgets.xml#id(Build a registry of labels)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Build a registry of labels</A></Bullet1>
<Heading3>
<A ID="pgfId-1071186"></A>
<A ID="Build a registry of labels"></A>
Build a registry of labels</Heading3>
<Body1>
<A ID="pgfId-1040993"></A>
There are two label registries, one for strings, and another for graphics, including <Code>
Text</Code>
 and <Code>
ComposeText</Code>
 objects. </Body1>
<Body1>
<A ID="pgfId-1071245"></A>
Labels are usually registered in a class-initialization method, so the registration occurs whenever the class is loaded into an image.</Body1>
<Bullet1>
<A ID="pgfId-1040997"></A>
To register a graphic image, send a <Code>
visualAt:put:</Code>
 message to <Code>
ApplicationModel</Code>
. The first argument is the lookup key for the label, and the second is the graphic resource method.</Bullet1>
<Bullet1>
<A ID="pgfId-1040999"></A>
To register a string label, send a <Code>
labelAt:put:</Code>
 message to <Code>
ApplicationModel</Code>
. The first argument is the lookup key for the label, and the second argument is the label string.</Bullet1>
<CodeSample>
<A ID="pgfId-1041000"></A>
initialize
		&quot;LogoExample initialize&quot;

		&quot;Register the graphic image for the trademark symbol.&quot;
		ApplicationModel 
			visualAt: #trademark 
			put: self trademark.

		&quot;Register the textual version of the trademark symbol.&quot;
		ApplicationModel 
			labelAt: #tm 
			put: &#39;(TM)&#39;.</CodeSample>
<Body1>
<A ID="pgfId-1041012"></A>
Execute the initialization method to update the registry.</Body1>
<Body1>
<A ID="pgfId-1071231"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Logo.pcl" show="embed" actuate="auto">
LogoExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1071267"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1071268"></A>
<A href="09-widgets.xml#id(Reuse a label)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Reuse a label</A></Bullet1>
<Bullet1>
<A ID="pgfId-1071273"></A>
<A href="09-widgets.xml#id(Remove a label registry entry)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Remove a registered label</A></Bullet1>
<Heading3>
<A ID="pgfId-1041013"></A>
<A ID="Remove a label registry entry"></A>
Remove a registered label</Heading3>
<Body1>
<A ID="pgfId-1041014"></A>
To save memory, you should remove unneeded labels from the registry. </Body1>
<StepStart>
<A ID="pgfId-1041015"></A>
Get the desired registry by sending a <Code>
visuals</Code>
 message to the <Code>
ApplicationModel</Code>
 class for the graphic labels registry, or a <Code>
labels</Code>
 message for string labels.</StepStart>
<StepCont>
<A ID="pgfId-1041016"></A>
Send a <Code>
removeKey:ifAbsent:</Code>
 message to the registry. The first argument is the name of the label, and the second argument is an action block, which may be empty.</StepCont>
<CodeSample>
<A ID="pgfId-1041017"></A>
&quot;Visual registry&quot;
| registry |
registry := ApplicationModel visuals.
registry removeKey: #trademark ifAbsent: [].

&quot;Labels registry&quot;
registry := ApplicationModel labels.
registry removeKey: #tm ifAbsent: [].</CodeSample>
<Body1>
<A ID="pgfId-1075531"></A>
</Body1>
<Heading2>
<A ID="pgfId-1042089"></A>
Input Fields</Heading2>
<Heading3>
<A ID="pgfId-1042090"></A>
Add an input field to a canvas</Heading3>
<Body1>
<A ID="pgfId-1042091"></A>
Use an input field for both entering and displaying data. A value model manages the field&#39;s data.</Body1>
<StepStart>
<A ID="pgfId-1042092"></A>
Select the <UI-Label>
Input Field</UI-Label>
 widget in the palette and place it on a canvas. Use the widget handles to size and position the field.</StepStart>
<StepCont>
<A ID="pgfId-1042093"></A>
On the Basics page of the GUI Painter Tool,  enter the field&#39;s <UI-Label>
Aspect</UI-Label>
 property with the name of the method that will return the field&#39;s value model.</StepCont>
<StepCont>
<A ID="pgfId-1040943"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040944"></A>
Use the canvas&#39;s <UI-Label>
define</UI-Label>
 command to add an instance variable and accessor method for the field&#39;s aspect property. Check the <UI-Label>
Add Initialization</UI-Label>
 box if lazy initialization is acceptable.</StepCont>
<StepCont>
<A ID="pgfId-1040946"></A>
To set an appropriate initial value, add an <Code>
initialize</Code>
 method.</StepCont>
<CodeSample>
<A ID="pgfId-1040948"></A>
initialize
		month := (Date nameOfMonth: 1) asValue.
		year := 1900 asValue.

		dateRange := (0@1) asValue.
		dateRange onChangeSend: #changedDate to: self.</CodeSample>
<Body1>
<A ID="pgfId-1041826"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider2.pcl" show="embed" actuate="auto">
Slider2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040954"></A>
Align an input field&#39;s contents</Heading3>
<Body1>
<A ID="pgfId-1040955"></A>
Set the field&#39;s <UI-Label>
Align</UI-Label>
 property to <UI-Label>
Left</UI-Label>
 (to start the data at the left side of the field), <UI-Label>
Center</UI-Label>
 (to center the data), or <UI-Label>
Right</UI-Label>
 (to place the data against the right margin).</Body1>
<Heading3>
<A ID="pgfId-1040956"></A>
Make an input field read-only</Heading3>
<Body1>
<A ID="pgfId-1040957"></A>
Turn on the field&#39;s <UI-Label>
Read Only</UI-Label>
 property.</Body1>
<Heading3>
<A ID="pgfId-1040958"></A>
Restrict a field&#39;s input size</Heading3>
<Body1>
<A ID="pgfId-1040959"></A>
In the field&#39;s <UI-Label>
Size</UI-Label>
 property, enter the number of characters that you want to allow. (When the user tries to enter characters beyond that limit, they are ignored.)</Body1>
<Body1>
<A ID="pgfId-1041929"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041933"></A>
<A href="09-widgets.xml#id(49650)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Restrict a field&#39;s input type</A></Bullet1>
<Heading3>
<A ID="pgfId-1040960"></A>
<A ID="49650"></A>
Restrict a field&#39;s input type</Heading3>
<Body1>
<A ID="pgfId-1040961"></A>
You can set the specific data type to be entered in an input field, and the display format that will be used.</Body1>
<StepStart>
<A ID="pgfId-1040962"></A>
Select the input field widget.</StepStart>
<StepCont>
<A ID="pgfId-1040963"></A>
On the Basics page of the GUI Painter Tool, select the acceptable input data type in the <UI-Label>
Type</UI-Label>
 property combo box. This property converts the user&#39;s input string to the selected object type.</StepCont>
<StepCont>
<A ID="pgfId-1040964"></A>
Optionally, select a <UI-Label>
Format</UI-Label>
 property provides, which formats the displayed data as selected.</StepCont>
<StepCont>
<A ID="pgfId-1040965"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1040997"></A>
<A ID="23084"></A>
Format displayed data in an input field</Heading3>
<Body1>
<A ID="pgfId-1041956"></A>
You can format the string represention of a field&#39;s value model for specific purposes (e.g., phone numbers, monetary units, and percentages).</Body1>
<StepStart>
<A ID="pgfId-1041974"></A>
Select the input field widget.</StepStart>
<StepCont>
<A ID="pgfId-1041001"></A>
On the Basics property page, set the field&#39;s <UI-Label>
Format</UI-Label>
 property as desired. Note that the field&#39;s <UI-Label>
Type</UI-Label>
 property setting determines the kinds of available formats, if any.</StepCont>
<StepCont>
<A ID="pgfId-1041002"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1041003"></A>
Specify a custom display format</Heading3>
<Body1>
<A ID="pgfId-1041005"></A>
Use a <Code>
TypeConverter</Code>
 to display a number in a specified format. Specify the format as a string that uses the same conventions as the predefined formats.</Body1>
<StepStart>
<A ID="pgfId-1041515"></A>
Use a Palette to add a field to the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1041516"></A>
Enter <UI-Label>
Aspect</UI-Label>
 property name. <UI-Label>
Apply</UI-Label>
 the property and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1041010"></A>
Use the <UI-Label>
define</UI-Label>
 command to create the instance variable and aspect accessor method for the aspect.</StepCont>
<StepCont>
<A ID="pgfId-1041011"></A>
Edit the aspect accessor method to initialize the value to a <Code>
TypeConverter</Code>
 that uses the desired format string.</StepCont>
<CodeSample>
<A ID="pgfId-1041012"></A>
price
		^price isNil 
			ifTrue: [price := (TypeConverter 
				onNumberValue: 0 asValue 
				format: &#39;$###,###,###.##&#39;)] 
			ifFalse: [price]</CodeSample>
<Body1>
<A ID="pgfId-1041836"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="FldType.pcl" show="embed" actuate="auto">
FieldTypeExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1042004"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042000"></A>
Class comments for the <Code>
NumberPrintPolicy</Code>
, <Code>
TimestampPrintPolicy</Code>
, and <Code>
StringPrintPolicy</Code>
 classes.</Bullet1>
<Heading3>
<A ID="pgfId-1041999"></A>
Validate an input field</Heading3>
<Body1>
<A ID="pgfId-1042017"></A>
To restrict and validate an input field, you can arrange for a typed entry to be validated either when the user accepts it, or immediately after an invalid character is typed.</Body1>
<Body1>
<A ID="pgfId-1042024"></A>
Use a <Glossary>
change validation callback</Glossary>
 to prevent input from being passed to a value model, and an <Glossary>
exit validation callback</Glossary>
 to keep focus in the field until the input is corrected.</Body1>
<Body1>
<A ID="pgfId-1041847"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041852"></A>
&#34;Configuring Widgets&#34; in the VisualWorks GUI Developer&#39;s Guide.</Bullet1>
<Heading3>
<A ID="pgfId-1041180"></A>
<A ID="98269"></A>
Change an input field&#39;s pop-up menu</Heading3>
<Body1>
<A ID="pgfId-1041181"></A>
You can substitute a custom menu for the default menu.</Body1>
<StepStart>
<A ID="pgfId-1041184"></A>
Select the input field.</StepStart>
<StepCont>
<A ID="pgfId-1041185"></A>
Enter the name of the method that will supply a custom menu in the field&#39;s <UI-Label>
Menu</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1041186"></A>
Create the menu-creating method named in step 2, adding it to the application model in a <Code>
menu messages</Code>
 protocol.</StepCont>
<Body1>
<A ID="pgfId-1041187"></A>
You can create the menu using the Menu Editor, or by using any <Code>
MenuBuilder</Code>
 messages. </Body1>
<StepCont>
<A ID="pgfId-1041188"></A>
Create any new methods named in the custom menu, adding them in the <Code>
menu messages</Code>
 protocol.</StepCont>
<Body1>
<A ID="pgfId-1041866"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="FldMenu.pcl" show="embed" actuate="auto">
FieldMenuExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1042048"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042049"></A>
Menu Editor</Bullet1>
<Bullet1>
<A ID="pgfId-1042068"></A>
<A href="09-widgets.xml#id(94854)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Disable an input field&#39;s pop-up menu</A></Bullet1>
<Heading3>
<A ID="pgfId-1042428"></A>
<A ID="94854"></A>
Disable an input field&#39;s pop-up menu</Heading3>
<StepStart>
<A ID="pgfId-1042429"></A>
Select the input field.</StepStart>
<StepCont>
<A ID="pgfId-1042430"></A>
Enter the name of the method that will return an empty menu (such as <Code>
noMenu</Code>
) in the field&#39;s <UI-Label>
Menu</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1041192"></A>
Create the method to return a block containing <Code>
nil</Code>
.</StepCont>
<CodeSample>
<A ID="pgfId-1041193"></A>
noMenu
		^[nil]</CodeSample>
<Body1>
<A ID="pgfId-1041195"></A>
When asked for its menu, the field will evaluate this block, and no menu will be displayed.</Body1>
<Body1>
<A ID="pgfId-1042075"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042076"></A>
<A href="09-widgets.xml#id(98269)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Change an input field&#39;s pop-up menu</A></Bullet1>
<Heading2>
<A ID="pgfId-1041196"></A>
Dependencies Between Fields</Heading2>
<Heading3>
<A ID="pgfId-1041197"></A>
Create a One-Way Connection</Heading3>
<StepStart>
<A ID="pgfId-1041200"></A>
Add a <Code>
postBuildWith:</Code>
 method to the application model in an <Code>
interface opening</Code>
 protocol.</StepStart>
<StepCont>
<A ID="pgfId-1041202"></A>
In the <Code>
postBuildWith:</Code>
 method, register an interest in the field that originates updates, naming a method to be invoked when that field is changed (<Code>
changedA</Code>
).</StepCont>
<CodeSample>
<A ID="pgfId-1041203"></A>
postBuildWith: aBuilder
		self a onChangeSend: #changedA to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1041206"></A>
Add the change method (<Code>
changedA</Code>
) to the application model in a <Code>
change messages</Code>
 protocol. That method updates the dependent field&#39;s model.</StepCont>
<CodeSample>
<A ID="pgfId-1041207"></A>
changedA
		self aSquared value: (self a value raisedTo: 2).</CodeSample>
<Body1>
<A ID="pgfId-1041872"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="FldCon.pcl" show="embed" actuate="auto">
FieldConnectionExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041209"></A>
Create a Two-Way Connection</Heading3>
<StepStart>
<A ID="pgfId-1041212"></A>
Add a <Code>
postBuildWith:</Code>
 method to the application model (<Code>
FieldConnectionExample</Code>
) in an <Code>
interface opening</Code>
 protocol.</StepStart>
<StepCont>
<A ID="pgfId-1041214"></A>
In the <Code>
postBuildWith:</Code>
 method, register interests in both fields, naming the method to be invoked when each field is changed (<Code>
changedB</Code>
, <Code>
changedBSquared</Code>
).</StepCont>
<CodeSample>
<A ID="pgfId-1041215"></A>
postBuildWith: aBuilder
		self b onChangeSend: #changedB to: self.
		self bSquared onChangeSend: #changedBSquared to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1041219"></A>
Add the change methods (<Code>
changedB</Code>
, <Code>
changedBSquared</Code>
) to the application model in a <Code>
change messages</Code>
 protocol.</StepCont>
<CodeSample>
<A ID="pgfId-1041220"></A>
changedB
		&quot;Use setValue: to bypass dependents,
		thus avoiding circularity.&quot;

		self bSquared setValue: (self b value raisedTo: 2).

		&quot;Since dependents were bypassed when
		the model was updated, update the view manually.&quot;
		(self builder componentAt: #b2) widget update: #value.

changedBSquared
		&quot;Use setValue: to bypass dependents,
		thus avoiding circularity.&quot;

		self b setValue: (self bSquared value raisedTo: (1/2)).

		&quot;Since dependents were bypassed when
		the model was updated, update the view manually.&quot;

		(self builder componentAt: #b) widget update: #value.</CodeSample>
<Body1>
<A ID="pgfId-1041878"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="FldCon.pcl" show="embed" actuate="auto">
FieldConnectionExample</CodeExample>
</Body1>
<Heading2>
<A ID="pgfId-1041235"></A>
Combination Box</Heading2>
<Heading3>
<A ID="pgfId-1041236"></A>
Add a combo box to a canvas</Heading3>
<Body1>
<A ID="pgfId-1041237"></A>
Use a combo Box widget when you need an input field restricted to a set of standard entries. </Body1>
<StepStart>
<A ID="pgfId-1041240"></A>
Add a combo box widget to the canvas, leaving it selected.</StepStart>
<StepCont>
<A ID="pgfId-1042325"></A>
On the Basics page of the GUI Painter Tool,  fill in the combo box&#39;s <UI-Label>
Aspect</UI-Label>
 property with the name of the method (in the example, <Code>
shipper</Code>
) that returns a value model for the combo box.</StepCont>
<StepCont>
<A ID="pgfId-1041242"></A>
In the combo box&#39;s <UI-Label>
Choices</UI-Label>
 property, enter the name of the method (<Code>
shipperChoices</Code>
) that returns a collection of entry choices. </StepCont>
<StepCont>
<A ID="pgfId-1041621"></A>
In the combo box&#39;s <UI-Label>
Type</UI-Label>
 property, choose the type of input the widget is to accept (see: <A href="09-widgets.xml#id(49650)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Restrict a field&#39;s input type</A>.) Set the <UI-Label>
Format</UI-Label>
 property, as appropriate (see: <A href="09-widgets.xml#id(23084)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Format displayed data in an input field</A>.)</StepCont>
<StepCont>
<A ID="pgfId-1041622"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1041624"></A>
Use the <UI-Label>
Define</UI-Label>
 button to create the instance variable (<Code>
shipper</Code>
) and accessing method (<Code>
shipper</Code>
) for the aspect.</StepCont>
<CodeSample>
<A ID="pgfId-1041248"></A>
shipper
		^shipper</CodeSample>
<StepCont>
<A ID="pgfId-1041251"></A>
Create the method that you named in step 3 (<Code>
shipperChoices</Code>
). The method returns a value holder containing the list of valid entries. The value holder can be held in an instance variable (as in the example).</StepCont>
<CodeSample>
<A ID="pgfId-1041252"></A>
shipperChoices
		^shipperChoices</CodeSample>
<StepCont>
<A ID="pgfId-1041255"></A>
Create an <Code>
initialize</Code>
 method to set the field&#39;s aspect and choices variables. Initialize these variables with a value model and a value holder containing data of the type specified in step 3.  The value holder contains a list of valid entries.</StepCont>
<CodeSample>
<A ID="pgfId-1041258"></A>
initialize

		| list |
		shipper := &#39;Courier&#39; asValue. 

		list := List new.
		list add: &#39;Courier&#39;;
		add: &#39;FedEx&#39;;
		add: &#39;UPS&#39;;
		add: &#39;USPS&#39;.
		shipperChoices := list asValue.</CodeSample>
<Body1>
<A ID="pgfId-1041884"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Combo.pcl" show="embed" actuate="auto">
ComboBoxExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1042328"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042332"></A>
<A href="09-widgets.xml#id(73722)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Set a combo box to display a list of objects</A></Bullet1>
<Heading3>
<A ID="pgfId-1042343"></A>
<A ID="73722"></A>
Set a combo box to display a list of objects</Heading3>
<Body1>
<A ID="pgfId-1042344"></A>
You can arrange for a combo box to display a list of choices that are arbitrary objects. You do this by supplying a print method and a read method that translate the relevant objects into displayable elements and back.</Body1>
<StepStart>
<A ID="pgfId-1041272"></A>
On the Basics page of the GUI Painter Tool, set the <UI-Label>
Type</UI-Label>
 property of the combo box to <Code>
Object</Code>
.</StepStart>
<StepCont>
<A ID="pgfId-1041274"></A>
Fill in the <UI-Label>
Print</UI-Label>
 property with the name of a method that converts the relevant objects to strings (in this example, <Code>
employeeToString:</Code>
). The name must end with a colon. </StepCont>
<StepCont>
<A ID="pgfId-1041276"></A>
Fill in the <UI-Label>
Read</UI-Label>
 property with the name of a method for converting strings to objects of the desired type (in this example, <Code>
stringToEmployee:</Code>
). The name must end with a colon.</StepCont>
<StepCont>
<A ID="pgfId-1041278"></A>
In the application model, create a print method with the name you specified in step 2 (<Code>
employeeToString:</Code>
). This method accepts an object from the choices list as an argument (in this case, an instance of <Code>
Employee</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1041280"></A>
In the print method, return a <Code>
String</Code>
 that represents the object from the choices list. In this example, display the name of the <Code>
Employee</Code>
. The string is displayed in the combo box&#39;s pull-down list and also in the combo box&#39;s field when the choice is selected.</StepCont>
<CodeSample>
<A ID="pgfId-1041281"></A>
employeeToString: anEmployee
		&quot;Return a String for representing the Employee in
		the combo box&#39;s list and field.&quot;

		^anEmployee name.</CodeSample>
<StepCont>
<A ID="pgfId-1041287"></A>
Create a read method with the name you specified in step 3 (<Code>
stringToEmployee:</Code>
). This method accepts a <Code>
String</Code>
 argument.</StepCont>
<StepCont>
<A ID="pgfId-1041289"></A>
In the read method, return an object for the given <Code>
String</Code>
. In this example, determine whether the <Code>
String</Code>
 is the name of an <Code>
Employee</Code>
 in the choices list; if so return that <Code>
Employee</Code>
. Otherwise, create a new <Code>
Employee</Code>
 and add it to the choices list. </StepCont>
<CodeSample>
<A ID="pgfId-1041290"></A>
stringToEmployee: aString
		&quot;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.&quot;

	| 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</CodeSample>
<Body1>
<A ID="pgfId-1041890"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="ComboCon.pcl" show="embed" actuate="auto">
ComboConversionExample</CodeExample>
</Body1>
<Heading2>
<A ID="pgfId-1041307"></A>
Controlling Input Field Display</Heading2>
<Heading3>
<A ID="pgfId-1041308"></A>
<A ID="78061"></A>
Highlight part or all of the input field</Heading3>
<StepStart>
<A ID="pgfId-1041311"></A>
In a method in the application model, ask the field&#39;s wrapper to <Code>
takeKeyboardFocus</Code>
. This highlights the entire field contents.</StepStart>
<StepCont>
<A ID="pgfId-1041313"></A>
Tell the field&#39;s controller the indices (character positions) of the substring that is to be highlighted.</StepCont>
<CodeSample>
<A ID="pgfId-1041314"></A>
addPart
		&quot;Put a template in the partID field,
		then highlight the suffix.&quot;

		| wrapper |
		self partID value: &#39;MW-0000&#39;.

		wrapper := self builder componentAt: #part1.
		wrapper takeKeyboardFocus.
		wrapper widget controller selectFrom: 4 to: 7.</CodeSample>
<Body1>
<A ID="pgfId-1041896"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="FldSel.pcl" show="embed" actuate="auto">
FieldSelectionExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1042352"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042356"></A>
<A href="09-widgets.xml#id(64913)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Position the insertion point</A></Bullet1>
<Heading3>
<A ID="pgfId-1041323"></A>
<A ID="64913"></A>
Position the insertion point</Heading3>
<StepStart>
<A ID="pgfId-1041325"></A>
In a method in the application model, ask the field&#39;s wrapper to <Code>
takeKeyboardFocus</Code>
.</StepStart>
<StepCont>
<A ID="pgfId-1041327"></A>
Tell the field&#39;s controller the character position at which to place the insertion point.</StepCont>
<CodeSample>
<A ID="pgfId-1041328"></A>
addPart2
	&quot;Put a template in the partID2 field, then position
	the insertion point.&quot;

	| wrapper |
		self partID2 value: &#39;MW-&#39;.

		wrapper := self builder componentAt: #part2.
		wrapper takeKeyboardFocus.
		wrapper widget controller selectAt: 4.</CodeSample>
<Body1>
<A ID="pgfId-1042361"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1042365"></A>
<A href="09-widgets.xml#id(78061)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Highlight part or all of the input field</A></Bullet1>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-958971"></A>
Spin Buttons</Heading2>
<Heading3>
<A ID="pgfId-956612"></A>
About Spin Buttons</Heading3>
<Body1>
<A ID="pgfId-962118"></A>
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. </Body1>
<Body1>
<A ID="pgfId-956613"></A>
A spin button model must represent a number, whenever its Type property is set to either <UI-Label>
String</UI-Label>
, <UI-Label>
Text</UI-Label>
, or <UI-Label>
Symbol</UI-Label>
. In these cases the model must respond to <Code>
asNumber</Code>
 and not answer <Code>
zero</Code>
 unless the model itself represents 0. </Body1>
<Body1>
<A ID="pgfId-956632"></A>
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. </Body1>
<Body1>
<A ID="pgfId-956633"></A>
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.  </Body1>
<Heading3>
<A ID="pgfId-956665"></A>
<A ID="marker-956664"></A>
Adding a Spin Button</Heading3>
<StepStart>
<A ID="pgfId-956666"></A>
Add a spin button widget to the canvas.</StepStart>
<StepCont>
<A ID="pgfId-956667"></A>
In the <UI-Label>
Aspect</UI-Label>
 property, enter a name for the aspect.</StepCont>
<StepCont>
<A ID="pgfId-956668"></A>
(Optional) Set the <UI-Label>
Type</UI-Label>
, <UI-Label>
Format</UI-Label>
, <UI-Label>
Low Value</UI-Label>
, <UI-Label>
High Value</UI-Label>
, and <UI-Label>
Intervale</UI-Label>
 properties</StepCont>
<Body1>
<A ID="pgfId-956669"></A>
These properties set the returned object type and format, and the range and increment for the presented values.</Body1>
<StepCont>
<A ID="pgfId-956670"></A>
<UI-Label>
Apply</UI-Label>
 the properties and install the canvas, and use <UI-Label>
define</UI-Label>
 to add the aspect instance variable and accessor method.</StepCont>
<StepCont>
<A ID="pgfId-957352"></A>
Create or edit the <Code>
initialize</Code>
 method to initialize the aspect variable with a value holder and an initial value.</StepCont>
<Heading2>
<A ID="pgfId-1040891"></A>
Buttons and Check Boxes</Heading2>
<Heading3>
<A ID="pgfId-1040892"></A>
<A ID="68158"></A>
Add a set of radio buttons to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040893"></A>
Use radio buttons to select exactly one item from a limited set of choices.</Body1>
<StepStart>
<A ID="pgfId-1040895"></A>
Select a group of new radio buttons on the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1041442"></A>
On the Basics page of the GUI Painter Tool, change the <UI-Label>
Label</UI-Label>
 property for each to name its particular choice (in the example, &#34;Dialog&#34; and &#34;Transcript&#34;).</StepCont>
<StepCont>
<A ID="pgfId-1040897"></A>
For all buttons, enter the same <UI-Label>
Aspect</UI-Label>
 property (<Code>
outputMode</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040898"></A>
For each button, enter a different <UI-Label>
Select</UI-Label>
 property (<Code>
#dialog</Code>
 and <Code>
#transcript</Code>
). This is the symbol that is stored in the <UI-Label>
Aspect</UI-Label>
 value holder whenever the button is selected.</StepCont>
<StepCont>
<A ID="pgfId-1041115"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1041116"></A>
Use the canvas&#39;s <UI-Label>
define</UI-Label>
 command to add an instance variable for the aspect that is shared by the buttons (<Code>
outputMode</Code>
), and to create a method for accessing the aspect variable (<Code>
outputMode</Code>
), in an <Code>
aspects</Code>
 protocol.</StepCont>
<StepCont>
<A ID="pgfId-1040904"></A>
Create an <Code>
initialize</Code>
 method to assign the aspect variable to hold a value holder containing one of the valid <UI-Label>
Select</UI-Label>
 symbols (<Code>
#dialog</Code>
). Your choice of symbol determines which radio button will be selected as a default.</StepCont>
<CodeSample>
<A ID="pgfId-1040905"></A>
outputMode
		^outputMode

initialize
		super initialize.
		outputMode := #dialog asValue.
		showMinutes := true asValue.
		showHours := true asValue.
		showSeconds := true asValue.</CodeSample>
<Body1>
<A ID="pgfId-1041138"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Button.pcl" show="embed" actuate="auto">
ButtonExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041339"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041340"></A>
<A href="09-widgets.xml#id(72303)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a check box to a canvas</A></Bullet1>
<Bullet1>
<A ID="pgfId-1041352"></A>
<A href="09-widgets.xml#id(63312)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add an action button to a canvas</A></Bullet1>
<Heading3>
<A ID="pgfId-1040913"></A>
Relocate a default widget label</Heading3>
<Body1>
<A ID="pgfId-1040914"></A>
All labeled widgets provide for a fixed, default label location. To place the label in a different location, turn off the widget&#39;s <UI-Label>
Label</UI-Label>
 property and use a separate label widget.</Body1>
<Heading3>
<A ID="pgfId-1040915"></A>
<A ID="72303"></A>
Add a check box to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040916"></A>
Use a check box to turn on or off an attribute.</Body1>
<StepStart>
<A ID="pgfId-1040918"></A>
Use a Palette to add a check box to the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040919"></A>
For each check box, enter a descriptive name in its <UI-Label>
Label</UI-Label>
 property (for example, &#34;Hours&#34;).</StepCont>
<StepCont>
<A ID="pgfId-1040921"></A>
For each checkbox, fill in its <UI-Label>
Aspect</UI-Label>
 property with the name of the method that accesses the check box&#39;s value holder (<Code>
showHours</Code>
). This value holder will contain <Code>
true</Code>
 when the check box is selected and <Code>
false</Code>
 when it is not selected.</StepCont>
<StepCont>
<A ID="pgfId-1040922"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040923"></A>
Use the canvas&#39;s <UI-Label>
define</UI-Label>
 command to create an instance variable in which to store the check box&#39;s value holder (<Code>
showHours</Code>
), and the method(s) named in step 3 (<Code>
showHours</Code>
) in an aspects protocol.</StepCont>
<CodeSample>
<A ID="pgfId-1040926"></A>
showHours
		^showHours</CodeSample>
<StepCont>
<A ID="pgfId-1040929"></A>
In the <Code>
initialize</Code>
 method, initialize the variable to a value holder containing <Code>
true</Code>
 if you want the check box to be selected by default and <Code>
false</Code>
 otherwise.</StepCont>
<CodeSample>
<A ID="pgfId-1040930"></A>
initialize
		super initialize.
		outputMode := #dialog asValue.
		showHours := true asValue.
		showMinutes := true asValue.
		showSeconds := true asValue.</CodeSample>
<Body1>
<A ID="pgfId-1041148"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Button.pcl" show="embed" actuate="auto">
ButtonExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041357"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041361"></A>
<A href="09-widgets.xml#id(68158)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a set of radio buttons to a canvas</A></Bullet1>
<Bullet1>
<A ID="pgfId-1041368"></A>
<A href="09-widgets.xml#id(63312)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add an action button to a canvas</A></Bullet1>
<Heading3>
<A ID="pgfId-1040936"></A>
<A ID="63312"></A>
Add an action button to a canvas</Heading3>
<StepStart>
<A ID="pgfId-1040939"></A>
Use a Palette to add an action button to the canvas, leaving it selected.</StepStart>
<StepCont>
<A ID="pgfId-1040940"></A>
In the GUI Painter Tool, fill in the button&#39;s <UI-Label>
Label</UI-Label>
 property with a descriptive label (in the example, &#34;Tell time&#34;).</StepCont>
<StepCont>
<A ID="pgfId-1040942"></A>
Fill in the button&#39;s <UI-Label>
Action</UI-Label>
 property with the name of the method that performs the action (<Code>
#tellTime</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040943"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040945"></A>
Create the method named in step 3 (<Code>
tellTime</Code>
) in an <Code>
actions</Code>
 protocol.</StepCont>
<CodeSample>
<A ID="pgfId-1040946"></A>
tellTime
		 | t tString |
		t := Time now.
		tString := String new.

		&quot;Assemble the time string based on the check boxes.&quot;
		self showHours value
			ifTrue: [tString := tString, t hours printString].
		self showMinutes value
			ifTrue: [tString := tString, &#39;:&#39;, t minutes printString, &#39;:&#39;]
			ifFalse: [tString := tString, &#39;::&#39;].
		self showSeconds value
			ifTrue: [tString := tString, t seconds printString].

		&quot;Send the time string to the output channel set by
		the radio buttons.&quot;
		self outputMode value == #transcript
			ifTrue: [Transcript show: tString; cr]
			ifFalse: [Dialog warn: tString]</CodeSample>
<Body1>
<A ID="pgfId-1041154"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Button.pcl" show="embed" actuate="auto">
ButtonExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041372"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041376"></A>
<A href="09-widgets.xml#id(68158)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a set of radio buttons to a canvas</A></Bullet1>
<Bullet1>
<A ID="pgfId-1041380"></A>
<A href="09-widgets.xml#id(72303)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a check box to a canvas</A></Bullet1>
<Bullet1>
<A ID="pgfId-1041387"></A>
<A href="09-widgets.xml#id(24286)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a placeholder action</A></Bullet1>
<Heading3>
<A ID="pgfId-1040964"></A>
<A ID="24286"></A>
Add a placeholder action</Heading3>
<Body1>
<A ID="pgfId-1040965"></A>
To cause an action button to display a dialog reminding you that the method has not yet been implemented, enter <Code>
unimplemented</Code>
 in the button&#39;s <UI-Label>
Action</UI-Label>
 property. </Body1>
<Heading3>
<A ID="pgfId-1040966"></A>
Designate a default button</Heading3>
<Body1>
<A ID="pgfId-1040967"></A>
To make a button the default action in a dialog (e.g., the button activatedby pressing &lt;Return&gt;) , enable the button&#39;s <UI-Label>
Be Default</UI-Label>
 property.</Body1>
<Body1>
<A ID="pgfId-1041392"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041396"></A>
<A href="09-widgets.xml#id(66950)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Size a button as the default</A></Bullet1>
<Heading3>
<A ID="pgfId-1040968"></A>
<A ID="66950"></A>
Size a button as the default</Heading3>
<Body1>
<A ID="pgfId-1040969"></A>
In some window managers, such as Windows and OSF Motif, a default button has a different appearance from other buttons which may affect the button&#39;s dimensions and alignment with other widgets. </Body1>
<Body1>
<A ID="pgfId-1040970"></A>
To make a nondefault button take on the sizing of a default button, turn on the button&#39;s <UI-Label>
Size as Default</UI-Label>
 property.</Body1>
<Heading3>
<A ID="pgfId-1040971"></A>
Supply a graphic label for a button</Heading3>
<StepStart>
<A ID="pgfId-1040973"></A>
Select the button in the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040974"></A>
In the GUI Painter Tool, turn on the button&#39;s <UI-Label>
Label is Image</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1040975"></A>
In the <UI-Label>
Message</UI-Label>
 property field, enter the name of the method that returns a graphic image (usually a resource method).</StepCont>
<StepCont>
<A ID="pgfId-1040976"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1040977"></A>
Turn off a button&#39;s highlighting</Heading3>
<Body1>
<A ID="pgfId-1040978"></A>
You can disable highlighting of a button when the user clicks on it or tabs to it.</Body1>
<StepStart>
<A ID="pgfId-1040980"></A>
Select the button in the canvas. </StepStart>
<StepCont>
<A ID="pgfId-1041451"></A>
In the GUI Painter Tool, turn off the button&#39;s <UI-Label>
Bordered</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1041026"></A>
In a method in the application model (typically <Code>
postBuildWith:</Code>
), get the widget from the application model&#39;s builder and send a <Code>
hiliteSelection:</Code>
 message to it. The argument is <Code>
false</Code>
.</StepCont>
<CodeSample>
<A ID="pgfId-1040983"></A>
postBuildWith: aBuilder
		| oddButtons |

		&quot;Make the main window a master window.&quot;
		aBuilder window
			application: self;
			beMaster.

		&quot;Turn off highlighting for the nonrectangular buttons.&quot;
		oddButtons := #( #prevPageButton #nextPageButton ).
		oddButtons do: [ :buttonName |
			(aBuilder componentAt: buttonName) 
				widget hiliteSelection: false].
		&quot;Disable the appropriate buttons.&quot;
		self adjustButtons.

		&quot;Set keyboard hook for special shortcut keys.&quot;
		aBuilder keyboardProcessor keyboardHook: [ :ev :ctrl |
			self keyPress: ev]. </CodeSample>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-1040883"></A>
Lines, Boxes, and Ovals</Heading2>
<Heading3>
<A ID="pgfId-1040885"></A>
Separate widgets with a line</Heading3>
<Body1>
<A ID="pgfId-1040886"></A>
Use a dividing line to visually separate sets of widgets. Lines are one pixel thick. For a thicker line, use a filled region widget.</Body1>
<StepStart>
<A ID="pgfId-1040887"></A>
Use a Palette to add a divider to the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040888"></A>
On the Basics page of the GUI Painter Tool, select either <UI-Label>
Horizontal</UI-Label>
 or <UI-Label>
Vertical</UI-Label>
 for the orientation property. <UI-Label>
Apply</UI-Label>
 the property.</StepCont>
<StepCont>
<A ID="pgfId-1040889"></A>
Use the widget handles to size and position the divider.</StepCont>
<StepCont>
<A ID="pgfId-1040890"></A>
<UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1040958"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1040962"></A>
<A href="09-widgets.xml#id(82183)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a region widget to a canvas</A></Bullet1>
<Heading3>
<A ID="pgfId-1040892"></A>
Group widgets with a box</Heading3>
<Body1>
<A ID="pgfId-1040893"></A>
Use boxes to cluster widgets in logical groups.  Box lines are one pixel thick. For a thicker line, use a filled region widget.</Body1>
<StepStart>
<A ID="pgfId-1040894"></A>
Use a Palette to add a box to the canvas, leaving the box selected.</StepStart>
<StepCont>
<A ID="pgfId-1040895"></A>
Use the widget handles to size and position the box.</StepCont>
<StepCont>
<A ID="pgfId-1040896"></A>
To provide a label,  fill in the <UI-Label>
Label</UI-Label>
 property field in the GUI Painter Tool. </StepCont>
<StepCont>
<A ID="pgfId-1041037"></A>
<UI-Label>
Apply</UI-Label>
 the change and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1040997"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041001"></A>
<A href="09-widgets.xml#id(82183)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">Add a region widget to a canvas</A></Bullet1>
<Heading3>
<A ID="pgfId-1040899"></A>
<A ID="82183"></A>
Add a region widget to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040900"></A>
Use rectangular and elliptical regions for grouping other widgets.</Body1>
<StepStart>
<A ID="pgfId-1040901"></A>
Use a Palette to add a region to the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040902"></A>
On the Basics page of the GUI Painter Tool, select either <UI-Label>
Rectangle</UI-Label>
 or <UI-Label>
Ellipse</UI-Label>
 as the widget&#39;s shape.</StepCont>
<StepCont>
<A ID="pgfId-1040903"></A>
Set the desired <UI-Label>
Border Thickness</UI-Label>
 property. </StepCont>
<StepCont>
<A ID="pgfId-1040904"></A>
On the <UI-Label>
Color</UI-Label>
 page, select any colors for the region.</StepCont>
<StepCont>
<A ID="pgfId-1040905"></A>
Use the widget handles to size and position the region.</StepCont>
<StepCont>
<A ID="pgfId-1040906"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1040907"></A>
To label the region, use a label widget. </Body1>
<Body1>
<A ID="pgfId-1041009"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041013"></A>
Label widget</Bullet1>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-957972"></A>
Resizing Splitter</Heading2>
<Heading3>
<A ID="pgfId-962118"></A>
About the Resizing Splitter</Heading3>
<Body1>
<A ID="pgfId-957988"></A>
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.</Body1>
<Body1>
<A ID="pgfId-961615"></A>
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.</Body1>
<Body1>
<A ID="pgfId-957996"></A>
Because this widget is really only intended for direct user manipulation, no programmatic interface is described in this section. </Body1>
<Body1>
<A ID="pgfId-958011"></A>
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.</Body1>
<Heading3>
<A ID="pgfId-957999"></A>
Adding a Resizing Splitter</Heading3>
<StepStart>
<A ID="pgfId-958003"></A>
Select the Resizing Splitter and drop it on the canvas between the widgets you want to resize.</StepStart>
<StepCont>
<A ID="pgfId-958010"></A>
Initially the widget is proportioned horizontally, and the the <UI-Label>
Horizontal</UI-Label>
 check box is marked, for separating widgets top to bottom. To separate widgets left to right, uncheck the <UI-Label>
Horizontal</UI-Label>
 check box and resize the widget accordingly.</StepCont>
<StepCont>
<A ID="pgfId-958027"></A>
In the <UI-Label>
Left/top widgets:</UI-Label>
 properties field, enter the IDs of the widgets to the left of or above the widget. Similarly, in the <UI-Label>
Right/bottom widgets:</UI-Label>
 field, enter the IDs of the widgets to the right or below the Resizing Splitter.</StepCont>
<Body1>
<A ID="pgfId-958040"></A>
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 (<UI-Entry>
TreeView1 TextEditor2</UI-Entry>
) or as symbols (<UI-Label>
#TreeView1 #TextEditor2</UI-Label>
). </Body1>
<StepCont>
<A ID="pgfId-958041"></A>
<UI-Label>
Accept</UI-Label>
 and install the canvas.</StepCont>
<Heading3>
<A ID="pgfId-958059"></A>
Setting Widget Positioning</Heading3>
<Body1>
<A ID="pgfId-958063"></A>
To make sure the widgets resize appropriately as the ResizIng Splitter is moved, you will need to set the widget positions carefully. Use the <UI-Label>
Position</UI-Label>
 pages for the affected widgets&#39; properties for precise control.</Body1>
<Body1>
<A ID="pgfId-958068"></A>
The Resizing Splitter can either have a border or be borderless. With a border it can double as a separator line, and so enhance the look of your GUI. Without a border it is invisible, and so simply serves as an area to grab for resizing. Even if you want it to be invisible in the final product, leaving it with a border can be useful while arranging your GUI.</Body1>
<Body1>
<A ID="pgfId-958862"></A>
</Body1>
<Heading2>
<A ID="pgfId-1040897"></A>
Sliders</Heading2>
<Heading3>
<A ID="pgfId-1040899"></A>
Add a slider to a canvas</Heading3>
<StepStart>
<A ID="pgfId-1040902"></A>
Add a slider widget to the canvas, leaving it selected.</StepStart>
<StepCont>
<A ID="pgfId-1041260"></A>
In the GUI Painter Tool, fill in the slider&#39;s <UI-Label>
Aspect</UI-Label>
 property with the name of the method (<Code>
destination</Code>
) that will supply a value model for the slider.</StepCont>
<StepCont>
<A ID="pgfId-1040904"></A>
Set the slider&#39;s orientation, to either <UI-Label>
Vertical</UI-Label>
 or <UI-Label>
Horizontal</UI-Label>
, on the <UI-Label>
Details</UI-Label>
 page.</StepCont>
<StepCont>
<A ID="pgfId-1040905"></A>
Optionally change the <UI-Label>
Start</UI-Label>
 (0), <UI-Label>
Stop</UI-Label>
 (4000), and <UI-Label>
Step</UI-Label>
 (10) properties, which control the endpoints of the range and the increment by which the marker will move. The default <UI-Label>
Start</UI-Label>
 is <Code>
0</Code>
 and the default <UI-Label>
Stop</UI-Label>
 is <Code>
1</Code>
. The default <UI-Label>
Step</UI-Label>
 is <Code>
nil</Code>
, giving the effect of continuous marker motion.</StepCont>
<StepCont>
<A ID="pgfId-1040906"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040907"></A>
Use the canvas&#39;s <UI-Label>
define</UI-Label>
 command to create an instance variable to hold the slider&#39;s <A href="10-glossary.xml#id(value model)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value model</A> (<Code>
destination</Code>
), and to create a corresponding access method.</StepCont>
<StepCont>
<A ID="pgfId-1040913"></A>
Create an <Code>
initialize</Code>
 method which assigns the variable with a value holder whose initial value is the current year.</StepCont>
<CodeSample>
<A ID="pgfId-1040914"></A>
initialize
		&quot;Destination&quot;
		destination := Date today year asValue.

		&quot;Current year&quot;
		currentYear := Date today year asValue.

		&quot;Trip meter&quot;
		tripRange := RangeAdaptor
			on: currentYear
			stop: 4000
			grid: 1.</CodeSample>
<Body1>
<A ID="pgfId-1041264"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider1.pcl" show="embed" actuate="auto">
Slider1Example</CodeExample>
 (the <Code>
Destination</Code>
 slider)</Body1>
<Heading3>
<A ID="pgfId-1040926"></A>
Make a slider vertical/horizontal</Heading3>
<StepStart>
<A ID="pgfId-1041221"></A>
In the GUI Painter Tool,  check the slider&#39;s <UI-Label>
Vertical</UI-Label>
 property on the <UI-Label>
Details</UI-Label>
 page (by default, a slider has a horizontal orientation.)</StepStart>
<StepCont>
<A ID="pgfId-1041222"></A>
On the canvas, size and scale the slider to appropriate dimensions for its new orientation.</StepCont>
<StepCont>
<A ID="pgfId-1041223"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1041224"></A>
Make a slider read-only</Heading3>
<Body1>
<A ID="pgfId-1040932"></A>
Sliders are normally input devices, but can be used purely as an output device.</Body1>
<StepStart>
<A ID="pgfId-1040933"></A>
In the GUI Painter Tool,  fill in the slider&#39;s <UI-Label>
ID</UI-Label>
 property with an identifying name (<Code>
tripRange</Code>
).</StepStart>
<StepCont>
<A ID="pgfId-1040936"></A>
In a method in the application model (typically <Code>
postBuildWith:</Code>
), get the slider component from the builder and disable it.</StepCont>
<CodeSample>
<A ID="pgfId-1040937"></A>
postBuildWith: aBuilder
		&quot;Disable the trip meter, making it read-only.&quot;
		(aBuilder componentAt: #tripRange) disable.</CodeSample>
<Body1>
<A ID="pgfId-1041494"></A>
In <Code>
Slider1Example</Code>
, we use a read-only slider as a meter to display the progress of the user&#39;s time-traveling adventure.</Body1>
<Body1>
<A ID="pgfId-1041505"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider1.pcl" show="embed" actuate="auto">
Slider1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040940"></A>
Connect a slider to an input field</Heading3>
<Body1>
<A ID="pgfId-1040941"></A>
A slider provides only approximate values. Frequently, an input field is used to display or accept an exact value. </Body1>
<StepStart>
<A ID="pgfId-1040943"></A>
Add a field to the canvas, leaving it selected. </StepStart>
<StepCont>
<A ID="pgfId-1041597"></A>
In the GUI Painter Tool, fill in the field&#39;s <UI-Label>
Aspect</UI-Label>
 property with the same name that the slider uses for its <UI-Label>
Aspect</UI-Label>
 (<Code>
destination</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040945"></A>
In the field&#39;s <UI-Label>
Type</UI-Label>
 property, select <UI-Label>
Number</UI-Label>
.</StepCont>
<StepCont>
<A ID="pgfId-1040946"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1041276"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider1.pcl" show="embed" actuate="auto">
Slider1Example</CodeExample>
 (the <Code>
Destination</Code>
 slider and field)</Body1>
<Heading3>
<A ID="pgfId-1040947"></A>
Display a transformed value in the field</Heading3>
<Body1>
<A ID="pgfId-1040948"></A>
A slider always manipulates a numeric value, but you can make it simulate a nonnumeric value (such as months in the year) by using a field to display a transformed value. </Body1>
<StepStart>
<A ID="pgfId-1040950"></A>
In the field&#39;s <UI-Label>
Aspect</UI-Label>
 property, enter a different method name than the slider&#39;s <UI-Label>
Aspect</UI-Label>
 (in the example, the slider&#39;s <UI-Label>
Aspect</UI-Label>
 is <Code>
dateRange</Code>
 while the field&#39;s <UI-Label>
Aspect</UI-Label>
 is <Code>
month</Code>
).</StepStart>
<StepCont>
<A ID="pgfId-1040951"></A>
In the field&#39;s <UI-Label>
Type</UI-Label>
 property, select the type that corresponds to the transformed value (in the example, a month name will be displayed, so we use a <Code>
String</Code>
 type field).</StepCont>
<StepCont>
<A ID="pgfId-1040953"></A>
Use the canvas&#39; <UI-Label>
define</UI-Label>
 command to create the field&#39;s instance variable (<Code>
month</Code>
) and accessing method (<Code>
month</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040957"></A>
In a method in the application model (typically <Code>
initialize</Code>
), initialize the field&#39;s variable. </StepCont>
<StepCont>
<A ID="pgfId-1040959"></A>
In the <Code>
initialize</Code>
 method, arrange for a change message (<Code>
changedDate</Code>
) to be sent to the application model when the slider&#39;s value changes.</StepCont>
<CodeSample>
<A ID="pgfId-1040960"></A>
initialize
		month :=(Date nameOfMonth: 1) asValue.
		year := 1900 asValue.

		dateRange := (0@1) asValue.
		dateRange onChangeSend: #changedDate to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1040967"></A>
Create the change method (<Code>
changedDate</Code>
) in the application model. This method is responsible for changing the field&#39;s value based on the slider&#39;s new value.</StepCont>
<CodeSample>
<A ID="pgfId-1040968"></A>
changedDate
		&quot;Convert the y-axis value to a month.&quot;
		| y x |
		y := self dateRange value y.
		y := (12 - (y * 12) asInteger) max: 1.
		self month value: (Date nameOfMonth: y).

		&quot;Convert the x-axis value to a year.&quot;
		x := self dateRange value x.
		x := 1900 + (x * 100) asInteger.									&quot;(100 years)&quot;
		self year value: x.</CodeSample>
<Body1>
<A ID="pgfId-1041513"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider2.pcl" show="embed" actuate="auto">
Slider2Example</CodeExample>
 (the <Code>
Month</Code>
 field)</Body1>
<Heading3>
<A ID="pgfId-1040979"></A>
Change a slider&#39;s range dynamically</Heading3>
<Body1>
<A ID="pgfId-1040980"></A>
When the slider&#39;s range is unchanging, you can use the slider&#39;s <UI-Label>
Start</UI-Label>
, <UI-Label>
Stop</UI-Label>
, and <UI-Label>
Step</UI-Label>
 properties to set the range and the step value.</Body1>
<StepStart>
<A ID="pgfId-1041382"></A>
In a method in the application model (typically in an <Code>
initialize</Code>
 method), initialize the slider&#39;s aspect variable with a <Code>
RangeAdaptor</Code>
 by sending the instance creation message (<Code>
on:start:stop:grid:</Code>
). The first argument (<Code>
currentYear</Code>
) is a <A href="10-glossary.xml#id(value holder)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value holder</A> containing the number that the slider manipulates. The <Code>
grid</Code>
 argument is the step value.</StepStart>
<CodeSample>
<A ID="pgfId-1041383"></A>
initialize
		&quot;Destination&quot;
		destination := Date today year asValue.

		&quot;Current year&quot;
		currentYear := Date today year asValue.

		&quot;Trip meter&quot;
		tripRange := RangeAdaptor
			on: currentYear
			start: 0
			stop: 4000
			grid: 1.</CodeSample>
<StepCont>
<A ID="pgfId-1040998"></A>
Whenever the range or step must change, send a <Code>
rangeStart:</Code>
, <Code>
rangeStop:</Code>
, or <Code>
grid:</Code>
 message to the adaptor. (In the example, this is done in the <Code>
engage</Code>
 method.)</StepCont>
<CodeSample>
<A ID="pgfId-1040999"></A>
engage
		&quot;Start the time trip.&quot;

		| startingYear destinationYear direction |
		startingYear := self currentYear value.
		destinationYear := self destination value.

		destinationYear == startingYear
			ifTrue: [^Dialog warn: &#39;Please select a new destination.&#39;].

		&quot;Set the endpoints on the trip meter.&quot;
		self tripRange
			rangeStart: startingYear;
			rangeStop: destinationYear;
			grid: 1.

		&quot;Reset the meter to the starting position.&quot;
		currentYear value: startingYear.

		&quot;Set up a step value for the loop that follows (-1 = backward in time).&quot;
		destinationYear &gt; startingYear
			ifTrue: [direction := 1]
			ifFalse: [direction := -1].

		&quot;For each year of time travel, update the current year.&quot;
		startingYear to: destinationYear by: direction do: [ :yr |
			currentYear value: yr].</CodeSample>
<Body1>
<A ID="pgfId-1041290"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider1.pcl" show="embed" actuate="auto">
Slider1Example</CodeExample>
 (the <Code>
Trip Meter</Code>
 slider)</Body1>
<Heading3>
<A ID="pgfId-1041026"></A>
Change the slider marker length</Heading3>
<Body1>
<A ID="pgfId-1041030"></A>
In a message in the application model (typically <Code>
postBuildWith:</Code>
), get the slider widget from the builder and send a <Code>
setMarkerLength:</Code>
 message to it, with the length in pixels as argument. </Body1>
<CodeSample>
<A ID="pgfId-1041031"></A>
postBuildWith: aBuilder

		(aBuilder componentAt: #dateRange) widget 
			beTwoDimensional;
			setMarkerLength: 10.</CodeSample>
<Body1>
<A ID="pgfId-1041296"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider2.pcl" show="embed" actuate="auto">
Slider2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041036"></A>
Make a two-dimensional slider</Heading3>
<Body1>
<A ID="pgfId-1041037"></A>
By default, a slider operates in one dimension. You can arrange for a slider to manipulate a point in two dimensions and then use the x-axis and y-axis components of that point to control two separate parameters. </Body1>
<StepStart>
<A ID="pgfId-1041040"></A>
In a method in the application model (typically <Code>
initialize</Code>
), initialize the slider&#39;s variable to an instance of <Code>
Point</Code>
 that is held by a <A href="10-glossary.xml#id(value holder)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value holder</A>.</StepStart>
<CodeSample>
<A ID="pgfId-1041041"></A>
initialize
		month := (Date nameOfMonth: 1) asValue.
		year := 1900 asValue.
		dateRange := (0@1) asValue.
		dateRange onChangeSend: #changedDate to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1041047"></A>
In a <Code>
postBuildWith:</Code>
 method, get the slider from the builder and ask it to <Code>
beTwoDimensional</Code>
.</StepCont>
<CodeSample>
<A ID="pgfId-1041048"></A>
postBuildWith: aBuilder

		(aBuilder componentAt: #dateRange) widget 
			beTwoDimensional;&quot;
			setMarkerLength: 10.</CodeSample>
<Body1>
<A ID="pgfId-1041302"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Slider2.pcl" show="embed" actuate="auto">
Slider2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041053"></A>
Connect a two-dimensional slider to two fields</Heading3>
<StepStart>
<A ID="pgfId-1041055"></A>
In a method in the application model (typically <Code>
initialize</Code>
), arrange for a change message (<Code>
changedDate</Code>
) to be sent to the application model when the slider&#39;s value changes.</StepStart>
<CodeSample>
<A ID="pgfId-1041056"></A>
initialize
		month :=(Date nameOfMonth: 1) asValue.
		year := 1900 asValue.

		dateRange := (0@1) asValue.
		dateRange onChangeSend: #changedDate to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1041063"></A>
Use a System Browser to create the change method (<Code>
changedDate</Code>
) in the application model. This method splits the slider&#39;s value into its x-axis and y-axis components. Each component is a value between <Code>
0</Code>
 and <Code>
1</Code>
 and is transformed as needed to produce a suitable value for the related field. </StepCont>
<CodeSample>
<A ID="pgfId-1041064"></A>
changedDate
		&quot;Convert the y-axis value to a month.&quot;
		| y x |
		y := self dateRange value y.
		y := (12 - (y * 12) asInteger) max: 1.									&quot;12 months&quot;
		self month value: (Date nameOfMonth: y).

		&quot;Convert the x-axis value to a year.&quot;
		x := self dateRange value x.
		x := 1900 + (x * 100) asInteger.
		self year value: x.</CodeSample>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-956611"></A>
Percent Done Bar</Heading2>
<Heading3>
<A ID="pgfId-958972"></A>
About the Percent Done Bar</Heading3>
<Body1>
<A ID="pgfId-962113"></A>
Also sometimes called a Progress Bar, this widget gives a visual indication of how far a process has advanced. It&#39;s commonly used for file copy procedures, but can be useful for any number of lengthy processes to give the user an indication of how much work has been done and how much more there is to go. </Body1>
<Heading3>
<A ID="pgfId-958973"></A>
Basic Properties</Heading3>
<Body1>
<A ID="pgfId-958990"></A>
Only the Basic properties are specific to this widget.</Body1>
<Heading4>
<A ID="pgfId-958998"></A>
Aspect</Heading4>
<Body1>
<A ID="pgfId-959002"></A>
The instance variable that determines the percentage. The value is a numeric value between 0 and 1. </Body1>
<Heading4>
<A ID="pgfId-959003"></A>
Orientation</Heading4>
<Body1>
<A ID="pgfId-959007"></A>
<UI-Label>
Horizontal</UI-Label>
 indicates progress horizontally. </Body1>
<Body1>
<A ID="pgfId-959008"></A>
<UI-Label>
Vertical</UI-Label>
 indicates progress vertically.</Body1>
<Body1>
<A ID="pgfId-959009"></A>
<UI-Label>
Both</UI-Label>
 indicates progress both vertically and horrizontally.</Body1>
<Body1>
<A ID="pgfId-959010"></A>
<UI-Label>
Area</UI-Label>
 shows percentage in terms of area covered, rather than linearly.</Body1>
<Body1>
<A ID="pgfId-959011"></A>
<UI-Label>
Reverse</UI-Label>
 reverses the horizontal and/or vertical direction.</Body1>
<Heading4>
<A ID="pgfId-959031"></A>
Starting Point</Heading4>
<Body1>
<A ID="pgfId-959035"></A>
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.</Body1>
<Heading3>
<A ID="pgfId-959040"></A>
Adding a Percent Done Bar</Heading3>
<StepStart>
<A ID="pgfId-959046"></A>
Add a Percent Done Bar widget to the canvas and select it.</StepStart>
<StepCont>
<A ID="pgfId-959047"></A>
In the <UI-Label>
Aspect</UI-Label>
 property, enter a name for the aspect.</StepCont>
<StepCont>
<A ID="pgfId-959048"></A>
Set the progress orientation: <UI-Label>
Horizontal</UI-Label>
, <UI-Label>
Vertical</UI-Label>
, or <UI-Label>
Both</UI-Label>
.</StepCont>
<Body1>
<A ID="pgfId-959049"></A>
Optionally, select <UI-Label>
Reverse</UI-Label>
, to reverse the direction of progress indication. Select Area to indicate progress as the percentage of area filled.</Body1>
<StepCont>
<A ID="pgfId-959050"></A>
Select a starting point radio button.</StepCont>
<StepCont>
<A ID="pgfId-959082"></A>
<UI-Label>
Apply</UI-Label>
 the properties and install the canvas. Use <UI-Label>
define</UI-Label>
 to add the aspect instance variable and accessor method.</StepCont>
<Heading2>
<A ID="pgfId-954864"></A>
<A ID="94531"></A>
Click Map</Heading2>
<Heading3>
<A ID="pgfId-954867"></A>
About the Click Map</Heading3>
<Body1>
<A ID="pgfId-962132"></A>
<A ID="BM559843"></A>
The <A ID="marker-954866"></A>
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.</Body1>
<Body1>
<A ID="pgfId-954868"></A>
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.</Body1>
<Heading3>
<A ID="pgfId-954869"></A>
Adding a Click Map</Heading3>
<Body1>
<A ID="pgfId-954871"></A>
<A ID="BM560106"></A>
To add a click map widget to a canvas:</Body1>
<StepStart>
<A ID="pgfId-954877"></A>
<A ID="BM560109"></A>
Choose the <A ID="click map widget"></A>
click map widget in the Palette and place it on a canvas.</StepStart>
<StepCont>
<A ID="pgfId-954879"></A>
Set the following <UI-Label>
Basic</UI-Label>
 properties and <UI-Label>
Apply</UI-Label>
 them: </StepCont>
<Body1>
<A ID="pgfId-954881"></A>
<UI-Label>
ID</UI-Label>
<A ID="BM560124"></A>
: A unique identifier for the widget, which will be used to access the widget. </Body1>
<Body1>
<A ID="pgfId-954883"></A>
<UI-Label>
Visual Message</UI-Label>
<A ID="BM560125"></A>
: The message selector that returns the image, which is typically an image resource method. </Body1>
<Body1>
<A ID="pgfId-954885"></A>
<A ID="BM559907"></A>
<UI-Label>
Mappings Selector</UI-Label>
: The message that returns the mapping between an area and the action for that location. You define mapping using the Hot Regions Editor. </Body1>
<Body1>
<A ID="pgfId-954887"></A>
<UI-Label>
Default Click Message</UI-Label>
<A ID="BM560482"></A>
: (optional) Specifies the action to be invoked when the user clicks in an area for which no other action is specified. If left empty, no action is taken.</Body1>
<StepCont>
<A ID="pgfId-954889"></A>
<A ID="BM560130"></A>
In the canvas, resize the click map widget so that it closely outlines the graphic image. </StepCont>
<StepCont>
<A ID="pgfId-954891"></A>
<A ID="BM560354"></A>
<UI-Label>
Install</UI-Label>
 the canvas, and provide a class name and method name in which to install the canvas when prompted. </StepCont>
<Heading3>
<A ID="pgfId-954895"></A>
<A ID="BM560139"></A>
Defining the <A ID="hot region mappings"></A>
Hot Region Mappings<A ID="Hot Regions Editor"></A>
</Heading3>
<StepStart>
<A ID="pgfId-954897"></A>
<A ID="BM560140"></A>
Select the click map widget in the canvas. </StepStart>
<StepCont>
<A ID="pgfId-954901"></A>
<A ID="BM560144"></A>
In the GUI Painter Tool, choose <UI-Label>
Tools </UI-Label>
<Dingbat>
ﬁ</Dingbat>
<UI-Label>
 Hot Regions Editor</UI-Label>
.</StepCont>
<StepCont>
<A ID="pgfId-954910"></A>
<A ID="BM560365"></A>
<A ID="BM560154"></A>
Choose <UI-Entry>
Regions </UI-Entry>
<Dingbat>
ﬁ</Dingbat>
<UI-Entry>
 Read</UI-Entry>
 to display the selected click widget&#39;s image as the background in the Hot Regions Editor. Resize the window to display the entire image.</StepCont>
<StepCont>
<A ID="pgfId-954914"></A>
Choose <UI-Label>
Edit </UI-Label>
<Dingbat>
ﬁ</Dingbat>
<UI-Label>
 New Slice</UI-Label>
 to begin defining a region. </StepCont>
<Body1>
<A ID="pgfId-954917"></A>
<A ID="BM560170"></A>
A slice is comprised of one or more areas that invoke the same action when clicked. The areas in a slice do not need to be contiguous. Identify areas in the Hot Regions Editor using tools similar to other bitmap editors: </Body1>
<Bullet1>
<A ID="pgfId-954919"></A>
<A ID="BM560175"></A>
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. </Bullet1>
<Bullet1>
<A ID="pgfId-954921"></A>
<A ID="BM560176"></A>
Six brush sizes and shapes. The first four draw lines, the next draws an ellipse, and the sixth draws a rectangle. </Bullet1>
<Bullet1>
<A ID="pgfId-954923"></A>
<A ID="BM560177"></A>
A fill-mode bucket that fills the entire image. </Bullet1>
<StepCont>
<A ID="pgfId-954925"></A>
<A ID="BM560193"></A>
In the <UI-Label>
Selector</UI-Label>
 input field, enter a method selector for the action to be invoked when this slice is clicked and press &lt;Return&gt;. </StepCont>
<Body1>
<A ID="pgfId-954926"></A>
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. </Body1>
<StepCont>
<A ID="pgfId-954928"></A>
<A ID="BM560207"></A>
Repeat steps 4 and 5 to define all the slices for this hot region. </StepCont>
<StepCont>
<A ID="pgfId-954932"></A>
<A ID="BM560218"></A>
Choose <UI-Label>
Regions </UI-Label>
<Dingbat>
ﬁ</Dingbat>
<UI-Label>
 Apply</UI-Label>
 to: </StepCont>
<Bullet1>
<A ID="pgfId-954935"></A>
<A ID="BM560219"></A>
Install the hot region resource. You are prompted for the class name and selector for the resource method that stores the hot region mappings. </Bullet1>
<Bullet1>
<A ID="pgfId-954937"></A>
<A ID="BM560220"></A>
Insert the resource&#39;s selector into the <UI-Label>
Mapping Selector</UI-Label>
 property of the click map widget that is selected in the canvas. </Bullet1>
<StepCont>
<A ID="pgfId-954939"></A>
<A ID="BM560221"></A>
Close the Hot Regions Editor. </StepCont>
<StepCont>
<A ID="pgfId-954941"></A>
<A ID="BM560476"></A>
Install the canvas. </StepCont>
<Heading3>
<A ID="pgfId-954944"></A>
<A ID="BM560461"></A>
Using <A ID="custom views"></A>
Custom Views and Controllers</Heading3>
<Body1>
<A ID="pgfId-954946"></A>
<A ID="BM560462"></A>
If you have an application that uses custom views and controllers, you can make it work as a VisualWave application:</Body1>
<StepStart>
<A ID="pgfId-954948"></A>
<A ID="BM560463"></A>
Make the custom view a subclass of <Code>
ClickWidget</Code>
. </StepStart>
<StepCont>
<A ID="pgfId-954950"></A>
<A ID="BM560464"></A>
In the custom view, implement a <Code>
mouseReleaseAt:</Code>
 method that specifies what to do when the user clicks in the custom view. </StepCont>
<StepCont>
<A ID="pgfId-954952"></A>
<A ID="BM560465"></A>
Disconnect the custom controller from your application. Move any custom behavior to the custom view&#39;s<Code>
 mouseReleaseAt:</Code>
 method. </StepCont>
<Body1>
<A ID="pgfId-954954"></A>
<A ID="BM560466"></A>
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. </Body1>
<Heading-Anchor>
<A ID="pgfId-946478"></A>
</Heading-Anchor>
<Heading2>
<A ID="pgfId-1040903"></A>
<A ID="98255"></A>
Notebooks</Heading2>
<Heading3>
<A ID="pgfId-1040905"></A>
Add a notebook to a canvas</Heading3>
<Body1>
<A ID="pgfId-1041268"></A>
Use a notebook to provide a set of index tabs, and possibly subtabs.</Body1>
<Body1>
<A ID="pgfId-1041299"></A>
Selecting a tab is similar to selecting an item in a list. A notebook typically contains a subcanvas, which displays a different interface for each index tab.</Body1>
<Body1>
<A ID="pgfId-1040907"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk1.pcl" show="embed" actuate="auto">
Notebook1Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041283"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041288"></A>
&#34;Working with Notebooks&#34; in the <I>
VisualWorks GUI Developer&#39;s Guide</I>
.</Bullet1>
<Heading3>
<A ID="pgfId-1040945"></A>
Get the selected notebook tab</Heading3>
<Body1>
<A ID="pgfId-1040948"></A>
To get the selected index tab&#39;s string or association, send a <Code>
selection</Code>
 message to the notebook&#39;s major <Code>
SelectionInList</Code>
.</Body1>
<CodeSample>
<A ID="pgfId-1040949"></A>
changedLetter
		| chosenLetter list |
			chosenLetter := self majorKeys selection last.
			list := Smalltalk classNames
				select: [ :name | name first == chosenLetter].
			self classNames list: list.</CodeSample>
<Body1>
<A ID="pgfId-1041307"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk1.pcl" show="embed" actuate="auto">
Notebook1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040955"></A>
Get a notebook tab&#39;s value</Heading3>
<Body1>
<A ID="pgfId-1040956"></A>
If you associate an object with each notebook tab, you need to retrieve that value. The associated object is typically a <Code>
Symbol</Code>
 that identifies a method to be performed, a canvas to be installed, or an application-specific attribute.</Body1>
<Body1>
<A ID="pgfId-1040957"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk2.pcl" show="embed" actuate="auto">
Notebook2Example</CodeExample>
</Body1>
<StepStart>
<A ID="pgfId-1040958"></A>
In a method in the application model, get the selected tab&#39;s association by sending a <Code>
selection</Code>
 message to the <Code>
SelectionInList</Code>
 (in the example, <Code>
minorKeys</Code>
, to which the <Code>
initialize</Code>
 method assigned a <Code>
SelectionInList</Code>
 with a collection of associations.)</StepStart>
<StepCont>
<A ID="pgfId-1041435"></A>
Send a <Code>
value</Code>
 message to the resulting association. (In the example, the <Code>
value</Code>
 is a <Code>
Symbol</Code>
--<Code>
#all</Code>
 or <Code>
#examples</Code>
--which is used to filter the list of class names.)</StepCont>
<CodeSample>
<A ID="pgfId-1041436"></A>
changedPage
		| chosenLetter list filter filteredList |
		chosenLetter := self majorKeys selection last.
		filter := self minorKeys selection value.

		list := Smalltalk classNames
			select: [ :name | name first == chosenLetter].

		filter == #all
			ifTrue: [filteredList := list]
			ifFalse: [filteredList := list 
				select: [ :name | &#39;*Example&#39; match: name]].

		self classNames list: filteredList.</CodeSample>
<Heading3>
<A ID="pgfId-1040975"></A>
Get a notebook tab&#39;s index</Heading3>
<Body1>
<A ID="pgfId-1040977"></A>
To get the index number, send <Code>
selectionIndex</Code>
 to the notebook&#39;s <Code>
SelectionInList</Code>
.</Body1>
<Heading3>
<A ID="pgfId-1040978"></A>
Change the notebook binding location</Heading3>
<Body1>
<A ID="pgfId-1040979"></A>
A solid color strip at the left or top edge of a notebook is used to simulate the appearance of a book binding. By default, the binding is along the left edge.</Body1>
<Body1>
<A ID="pgfId-1040981"></A>
To set the binding location</Body1>
<StepStart>
<A ID="pgfId-1040982"></A>
Select the notebook in the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040983"></A>
In the GUI Painter Tool, go to the notebook&#39;s <UI-Label>
Binding</UI-Label>
 property (<UI-Label>
Details</UI-Label>
 page) and select <Code>
top</Code>
. This moves the binding to the top edge. (To move it back, select <Code>
left</Code>
.)</StepCont>
<StepCont>
<A ID="pgfId-1040984"></A>
<UI-Label>
Apply</UI-Label>
 properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1041338"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk3.pcl" show="embed" actuate="auto">
Notebook3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040985"></A>
Change the notebook binding width</Heading3>
<Body1>
<A ID="pgfId-1040986"></A>
By default, the binding strip is 18 pixels wide. A width of zero can be used to eliminate the binding strip altogether.</Body1>
<Body1>
<A ID="pgfId-1040988"></A>
To set the binding width, in the <UI-Label>
Width</UI-Label>
 field of the notebook&#39;s <UI-Label>
Binding</UI-Label>
 property, enter the desired number of pixels of width.</Body1>
<Body1>
<A ID="pgfId-1041344"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk3.pcl" show="embed" actuate="auto">
Notebook3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040989"></A>
Set the notebook tab axis</Heading3>
<Body1>
<A ID="pgfId-1040990"></A>
By default, the major index tabs are aligned along the right-hand edge of the notebook, and the minor tabs are along the bottom. </Body1>
<Body1>
<A ID="pgfId-1040992"></A>
To change the tab orientataion:</Body1>
<StepStart>
<A ID="pgfId-1040993"></A>
Select the notebook in the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040994"></A>
In the GUI Painter Tool, go to the notebook&#39;s <UI-Label>
Major Tabs</UI-Label>
 property (<UI-Label>
Details</UI-Label>
 page) and select <Code>
bottom</Code>
. (The minor tabs, if any, will move to the right-hand edge.)</StepCont>
<StepCont>
<A ID="pgfId-1040995"></A>
<UI-Label>
Apply</UI-Label>
 the property and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1041350"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk3.pcl" show="embed" actuate="auto">
Notebook3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040996"></A>
Set the notebook tab size</Heading3>
<Body1>
<A ID="pgfId-1040997"></A>
By default, the right-hand tabs are 60 pixels wide and the bottom tabs are 24 pixels high. These values are called insets.</Body1>
<Body1>
<A ID="pgfId-1040999"></A>
To change the inset values:</Body1>
<StepStart>
<A ID="pgfId-1041000"></A>
In <UI-Label>
Right</UI-Label>
 field of the notebook&#39;s <UI-Label>
Insets</UI-Label>
 property (<UI-Label>
Details</UI-Label>
 page), enter the number of pixels of width for the right-hand index tabs. (The height adjusts automatically to fit the label font).</StepStart>
<StepCont>
<A ID="pgfId-1041001"></A>
In <UI-Label>
Bottom</UI-Label>
 field of the notebook&#39;s <UI-Label>
Insets</UI-Label>
 property, enter the number of pixels for the bottom tabs to be offset from the bottom edge of the page. (The width adjusts to fit each tab&#39;s label.)</StepCont>
<Body1>
<A ID="pgfId-1041356"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk3.pcl" show="embed" actuate="auto">
Notebook3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041002"></A>
Set the notebook starting page</Heading3>
<Body1>
<A ID="pgfId-1041005"></A>
To set the start page by index, send a <Code>
selectionIndex:</Code>
 message to the <Code>
SelectionInList</Code>
 that holds the major keys, with the index number as argument. </Body1>
<CodeSample>
<A ID="pgfId-1041006"></A>
postOpenWith: aBuilder
		(aBuilder componentAt: #pageHolder) widget
			client: self
			spec: #listSpec.
		majorKeys selectionIndex: 1.</CodeSample>
<Body1>
<A ID="pgfId-1041011"></A>
If the notebook has minor keys, also set the selection index in the <Code>
SelectionInList</Code>
 that contains the minor keys.</Body1>
<Body1>
<A ID="pgfId-1041012"></A>
To set the start page by specifying the list element itself, rather than by index, send a <Code>
selection:</Code>
 message to the <Code>
SelectionInList</Code>
, with the desired element.</Body1>
<Body1>
<A ID="pgfId-1041362"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk1.pcl" show="embed" actuate="auto">
Notebook1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041013"></A>
Add secondary tabs (minor keys)</Heading3>
<Body1>
<A ID="pgfId-1041014"></A>
Minor keys, or secondary tabs, can be used for subdivisions within the major keys, or to filter the content of the notebook along a separate dimension. </Body1>
<StepStart>
<A ID="pgfId-1041016"></A>
Select the notebook in the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1041017"></A>
In the GUI Painter Tool, fill in the notebook&#39;s <UI-Label>
Minor</UI-Label>
 property with the name of the method that returns a <Code>
SelectionInList</Code>
 containing the labels for the secondary tabs (in the example, <Code>
minorKeys</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1041019"></A>
Use the canvas&#39;s <UI-Label>
define</UI-Label>
 command to create the instance variable (<Code>
minorKeys</Code>
) and accessing method (<Code>
minorKeys</Code>
) for the notebook&#39;s list of index labels. </StepCont>
<StepCont>
<A ID="pgfId-1041023"></A>
Initialize the variable, either in the accessing method or in an <Code>
initialize</Code>
 method (as in the example), with a <Code>
SelectionInList</Code>
 containing either strings or associations (the example uses associations).</StepCont>
<StepCont>
<A ID="pgfId-1041025"></A>
In the <Code>
initialize</Code>
 method, use an <Code>
onChangeSend:to:</Code>
 message to arrange for the notebook to send a message (<Code>
changedPage</Code>
) to the application model when the user selects a secondary tab. (In the example, both the major and minor tabs trigger the same message: <Code>
changedPage</Code>
.)</StepCont>
<CodeSample>
<A ID="pgfId-1041026"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1041027"></A>
		| letters |</CodeSample>
<CodeSample>
<A ID="pgfId-1041028"></A>
		letters := #( &#39; A&#39; &#39; B&#39; &#39; C&#39; &#39; D&#39; &#39; E&#39; &#39; F&#39; &#39; G&#39; &#39; H&#39; &#39; I&#39; &#39; J&#39; &#39; K&#39; &#39; L&#39; &#39; M&#39; </CodeSample>
<CodeSample>
<A ID="pgfId-1041029"></A>
				&#39; N&#39; &#39; O&#39; &#39; P&#39; &#39; Q&#39; &#39; R&#39; &#39; S&#39; &#39; T&#39; &#39; U&#39; &#39; V&#39; &#39; W&#39; &#39; X&#39; &#39; Y&#39; &#39; Z&#39; ).</CodeSample>
<CodeSample>
<A ID="pgfId-1041030"></A>
		majorKeys := SelectionInList with: letters.</CodeSample>
<CodeSample>
<A ID="pgfId-1041031"></A>
		majorKeys selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041032"></A>
			onChangeSend: #changedPage to: self.</CodeSample>
<CodeSample>
<A ID="pgfId-1041033"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041034"></A>
		minorKeys := SelectionInList with: (Array</CodeSample>
<CodeSample>
<A ID="pgfId-1041035"></A>
			with: &#39;All classes&#39;-&gt; #all</CodeSample>
<CodeSample>
<A ID="pgfId-1041036"></A>
			with: &#39;Examples only&#39; -&gt; #examples).</CodeSample>
<CodeSample>
<A ID="pgfId-1041037"></A>
		minorKeys selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041038"></A>
			onChangeSend: #changedPage to: self.</CodeSample>
<CodeSample>
<A ID="pgfId-1041039"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041040"></A>
		classNames := SelectionInList new.</CodeSample>
<StepCont>
<A ID="pgfId-1041042"></A>
Create the change message (<Code>
changedPage</Code>
) in which the subcanvas is updated based on the selected index tab. (In the example, the <Code>
classNames</Code>
 list is updated with all class names or only example classes, based on the minor key.)</StepCont>
<CodeSample>
<A ID="pgfId-1041043"></A>
changedPage</CodeSample>
<CodeSample>
<A ID="pgfId-1041044"></A>
		| chosenLetter list filter filteredList |</CodeSample>
<CodeSample>
<A ID="pgfId-1041045"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041046"></A>
		&quot;Major key.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041047"></A>
		chosenLetter := self majorKeys selection last.</CodeSample>
<CodeSample>
<A ID="pgfId-1041048"></A>
		list := Smalltalk classNames </CodeSample>
<CodeSample>
<A ID="pgfId-1041049"></A>
			select: [ :name | name first == chosenLetter].</CodeSample>
<CodeSample>
<A ID="pgfId-1041050"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041051"></A>
		&quot;Minor key.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041052"></A>
		filter := self minorKeys selection value.</CodeSample>
<CodeSample>
<A ID="pgfId-1041053"></A>
		filter == #all</CodeSample>
<CodeSample>
<A ID="pgfId-1041054"></A>
			ifTrue: [filteredList := list]</CodeSample>
<CodeSample>
<A ID="pgfId-1041055"></A>
			ifFalse: [filteredList := list </CodeSample>
<CodeSample>
<A ID="pgfId-1041056"></A>
				select: [ :name | &#39;*Example&#39; match: name]].</CodeSample>
<CodeSample>
<A ID="pgfId-1041057"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041058"></A>
		self classNames list: filteredList.</CodeSample>
<Body1>
<A ID="pgfId-1041376"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk2.pcl" show="embed" actuate="auto">
Notebook2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041059"></A>
Connect minor tabs to major tabs</Heading3>
<Body1>
<A ID="pgfId-1041060"></A>
You can set the minor keys to depend on the major keys.</Body1>
<StepStart>
<A ID="pgfId-1041063"></A>
In the application model&#39;s <Code>
initialize</Code>
 method, use <Code>
onChangeSend:to:</Code>
 messages to arrange for the two <Code>
SelectionInList</Code>
s to notify the application model when their selections are changed.</StepStart>
<CodeSample>
<A ID="pgfId-1041064"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1041065"></A>
		self initializeDepartments.</CodeSample>
<CodeSample>
<A ID="pgfId-1041066"></A>
		self initializeEmployees.</CodeSample>
<CodeSample>
<A ID="pgfId-1041067"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041068"></A>
		majorKeys := SelectionInList with: departments keys asArray.</CodeSample>
<CodeSample>
<A ID="pgfId-1041069"></A>
		majorKeys selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041070"></A>
			onChangeSend: #changedDepartment </CodeSample>
<CodeSample>
<A ID="pgfId-1041071"></A>
			to: self.</CodeSample>
<CodeSample>
<A ID="pgfId-1041072"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041073"></A>
		minorKeys := SelectionInList new.</CodeSample>
<CodeSample>
<A ID="pgfId-1041074"></A>
		minorKeys selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041075"></A>
			onChangeSend: #changedSubdepartment </CodeSample>
<CodeSample>
<A ID="pgfId-1041076"></A>
			to: self.</CodeSample>
<CodeSample>
<A ID="pgfId-1041077"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041078"></A>
		employeeList := SelectionInList new.</CodeSample>
<StepCont>
<A ID="pgfId-1041080"></A>
Create the change message (<Code>
changedDepartment</Code>
) for the major keys. In this method, get the selection from the major <Code>
SelectionInList</Code>
 and verify that it is not <Code>
nil</Code>
. Then use that selection as the basis for choosing the new labels for the minor tabs. Typically, this method will also reset the minor key selection so the notebook displays the first subpage.</StepCont>
<CodeSample>
<A ID="pgfId-1041081"></A>
changedDepartment</CodeSample>
<CodeSample>
<A ID="pgfId-1041082"></A>
		| subdepts sel |</CodeSample>
<CodeSample>
<A ID="pgfId-1041083"></A>
		sel := self majorKeys selection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041084"></A>
		sel isNil ifTrue: [^self].</CodeSample>
<CodeSample>
<A ID="pgfId-1041085"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041086"></A>
		&quot;Display the appropriate subdepartments as minor keys.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041087"></A>
		subdepts := self departments at: sel.</CodeSample>
<CodeSample>
<A ID="pgfId-1041088"></A>
		self minorKeys list: subdepts.</CodeSample>
<CodeSample>
<A ID="pgfId-1041089"></A>
		self minorKeys selectionIndex: 1.</CodeSample>
<StepCont>
<A ID="pgfId-1041091"></A>
Create the change message (<Code>
changedSubdepartment</Code>
) for the minor keys. In this method, get the minor selection and verify that it is not <Code>
nil</Code>
. Then use that selection as the basis for updating the canvas in the notebook or, as in the example, its model (<Code>
employeeList</Code>
).</StepCont>
<CodeSample>
<A ID="pgfId-1041092"></A>
changedSubdepartment</CodeSample>
<CodeSample>
<A ID="pgfId-1041093"></A>
		&quot;Display the appropriate employees in the list.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041094"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041095"></A>
		| emps sel |</CodeSample>
<CodeSample>
<A ID="pgfId-1041096"></A>
		sel := self minorKeys selection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041097"></A>
		sel isNil ifTrue: [^self].</CodeSample>
<CodeSample>
<A ID="pgfId-1041098"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041099"></A>
		emps := self employees at: sel.</CodeSample>
<CodeSample>
<A ID="pgfId-1041100"></A>
		self employeeList list: emps.</CodeSample>
<Body1>
<A ID="pgfId-1041384"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk3.pcl" show="embed" actuate="auto">
Notebook3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041101"></A>
Change the notebook layout (subcanvas)</Heading3>
<Body1>
<A ID="pgfId-1041102"></A>
You can use a notebook to present a different interface on each page.</Body1>
<StepStart>
<A ID="pgfId-1041105"></A>
In the application model&#39;s <Code>
initialize</Code>
 method, arrange for the <Code>
SelectionInList</Code>
 that holds the major keys to notify the application model when a tab is selected. (In the example, a <Code>
changedExample</Code>
 message is triggered.)</StepStart>
<CodeSample>
<A ID="pgfId-1041106"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1041107"></A>
		| exampleClasses |</CodeSample>
<CodeSample>
<A ID="pgfId-1041108"></A>
		exampleClasses := OrderedCollection new.</CodeSample>
<CodeSample>
<A ID="pgfId-1041109"></A>
		exampleClasses := Smalltalk keys select: [ :c |</CodeSample>
<CodeSample>
<A ID="pgfId-1041110"></A>
			((&#39;*Example&#39; match: c) </CodeSample>
<CodeSample>
<A ID="pgfId-1041111"></A>
					and: [(Smalltalk at: c) isVisualStartable])</CodeSample>
<CodeSample>
<A ID="pgfId-1041112"></A>
					and: [(&#39;Notebook*&#39; match: c) not]].</CodeSample>
<CodeSample>
<A ID="pgfId-1041113"></A>
		majorKeys := SelectionInList </CodeSample>
<CodeSample>
<A ID="pgfId-1041114"></A>
			with: exampleClasses asSortedCollection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041115"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041116"></A>
		majorKeys selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041117"></A>
			onChangeSend: #changedExample to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1041119"></A>
In the change method (<Code>
changedExample</Code>
), get the notebook widget from the application model&#39;s builder by sending a <Code>
componentAt:</Code>
 message.</StepCont>
<StepCont>
<A ID="pgfId-1041121"></A>
Still in the change method, send a <Code>
client:spec:</Code>
 message to the notebook. The first argument is an instance of the desired application model (in the example, <Code>
exampleClass</Code>
). The second argument is the name of the desired canvas (in the example, each example class&#39;s <Code>
windowSpec</Code>
 is used).</StepCont>
<CodeSample>
<A ID="pgfId-1041122"></A>
changedExample</CodeSample>
<CodeSample>
<A ID="pgfId-1041123"></A>
		| sel exampleClass |</CodeSample>
<CodeSample>
<A ID="pgfId-1041124"></A>
		sel := self majorKeys selection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041125"></A>
		sel isNil ifTrue: [^self].</CodeSample>
<CodeSample>
<A ID="pgfId-1041126"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041127"></A>
		exampleClass := Smalltalk at: sel value.</CodeSample>
<CodeSample>
<A ID="pgfId-1041128"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041129"></A>
		(self builder componentAt: #pageHolder) widget</CodeSample>
<CodeSample>
<A ID="pgfId-1041130"></A>
			client: exampleClass new</CodeSample>
<CodeSample>
<A ID="pgfId-1041131"></A>
			spec: #windowSpec.</CodeSample>
<Body1>
<A ID="pgfId-1041397"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk4.pcl" show="embed" actuate="auto">
Notebook4Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041132"></A>
Connect a notebook to a text editor</Heading3>
<StepStart>
<A ID="pgfId-1041136"></A>
In the application model&#39;s initialize method, arrange for the <Code>
SelectionInList</Code>
 that holds the lowest level of selections to notify the application model when a text is selected. (In the example, a <Code>
changedClass</Code>
 message is triggered by a selection in the <Code>
classNames</Code>
 list.)</StepStart>
<CodeSample>
<A ID="pgfId-1041137"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1041138"></A>
		| letters |</CodeSample>
<CodeSample>
<A ID="pgfId-1041139"></A>
		letters := #( &#39; A&#39; &#39; B&#39; &#39; C&#39; &#39; D&#39; &#39; E&#39; &#39; F&#39; &#39; G&#39; &#39; H&#39; &#39; I&#39; &#39; J&#39; &#39; K&#39; &#39; L&#39; &#39; M&#39; </CodeSample>
<CodeSample>
<A ID="pgfId-1041140"></A>
				&#39; N&#39; &#39; O&#39; &#39; P&#39; &#39; Q&#39; &#39; R&#39; &#39; S&#39; &#39; T&#39; &#39; U&#39; &#39; V&#39; &#39; W&#39; &#39; X&#39; &#39; Y&#39; &#39; Z&#39; ).</CodeSample>
<CodeSample>
<A ID="pgfId-1041141"></A>
		majorKeys := SelectionInList with: letters.</CodeSample>
<CodeSample>
<A ID="pgfId-1041142"></A>
		majorKeys selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041143"></A>
			onChangeSend: #changedLetter to: self.</CodeSample>
<CodeSample>
<A ID="pgfId-1041144"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041145"></A>
		classNames := SelectionInList new.</CodeSample>
<CodeSample>
<A ID="pgfId-1041146"></A>
		classNames selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-1041147"></A>
			onChangeSend: #changedClass to: self.</CodeSample>
<CodeSample>
<A ID="pgfId-1041148"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041149"></A>
		classComment := &#39;&#39; asValue.</CodeSample>
<StepCont>
<A ID="pgfId-1041151"></A>
In the change method (<Code>
changedClass</Code>
), get the selection from the lowest-level <Code>
SelectionInList</Code>
 (<Code>
classNames</Code>
). Then use that selection as the basis for choosing the text and install the new text in the text holder (<Code>
classComment</Code>
).</StepCont>
<CodeSample>
<A ID="pgfId-1041152"></A>
changedClass</CodeSample>
<CodeSample>
<A ID="pgfId-1041153"></A>
		| chosenClass newText |</CodeSample>
<CodeSample>
<A ID="pgfId-1041154"></A>
		chosenClass := self classNames selection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041155"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041156"></A>
		newText := chosenClass isNil </CodeSample>
<CodeSample>
<A ID="pgfId-1041157"></A>
			ifTrue: [&#39;&#39;]</CodeSample>
<CodeSample>
<A ID="pgfId-1041158"></A>
			ifFalse: [(Smalltalk at: chosenClass) comment].</CodeSample>
<CodeSample>
<A ID="pgfId-1041159"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041160"></A>
		self classComment value: newText.</CodeSample>
<Body1>
<A ID="pgfId-1041407"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Notebk5.pcl" show="embed" actuate="auto">
Notebook5Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041410"></A>
</Body1>
<Heading2>
<A ID="pgfId-959979"></A>
Tab Control</Heading2>
<Heading3>
<A ID="pgfId-962113"></A>
About the Tab Control</Heading3>
<Body1>
<A ID="pgfId-959981"></A>
<TopicText>
Online example:</TopicText>
 <Code>
TabControlExample</Code>
<A ID="marker-959980"></A>
</Body1>
<Body1>
<A ID="pgfId-959982"></A>
The TabControl is an alternative to the Notebook widget, providing a tabbed folder look. To change the contents of the subpane below the row of tabs, click a tab, or select the tab using cursor keys and press <UI-Label>
Enter</UI-Label>
.</Body1>
<Body1>
<A ID="pgfId-959807"></A>
The Tab Control shows two scroller buttons, if there are more tabs than can be displayed in the available header space. Press the buttons to scroll the tabs.</Body1>
<Heading3>
<A ID="pgfId-959819"></A>
Compatibility with Notebook </Heading3>
<Body1>
<A ID="pgfId-959686"></A>
The Tab Control is largely, but not completely, protocol-compatible with the Notebook widget.</Body1>
<Body1>
<A ID="pgfId-959838"></A>
In many cases, you can chang from a Notebook to a Tab Control simply by editing the application&#39;s windowSpec, replacing the <Code>
#NoteBookSpec</Code>
 symbol to <Code>
#TabControlSpec</Code>
. This conversion method works, for example, with <Code>
Notebook1Example</Code>
, <Code>
Notebook4Example</Code>
, and <Code>
Notebook5Example</Code>
.</Body1>
<Body1>
<A ID="pgfId-959826"></A>
One limitation is that Tab Control does not support secondary tabs, as does Notebook. For this reason, the above conversion does not work for <Code>
Notebook2Example</Code>
 or <Code>
Notebook3Example</Code>
.</Body1>
<Body1>
<A ID="pgfId-959906"></A>
For an example specifically using the Tab Control, load the TabControlExample parcel.</Body1>
<Heading3>
<A ID="pgfId-959691"></A>
Adding a Tab Control</Heading3>
<StepStart>
<A ID="pgfId-959694"></A>
Select the Tab Control on the Palette and drop it on the canvas.</StepStart>
<StepCont>
<A ID="pgfId-959875"></A>
In its <UI-Label>
Aspect</UI-Label>
 property, enter an aspect name. Also enter an <UI-Label>
ID</UI-Label>
, or keep the default. You will need the ID to identify the selected tab.</StepCont>
<StepCont>
<A ID="pgfId-959893"></A>
Define the accessor method for the aspect. </StepCont>
<Body1>
<A ID="pgfId-959897"></A>
The model should be a <Code>
SelectionInList</Code>
 on either <Code>
Strings</Code>
, which make up textual tab labels, or <Code>
Associations</Code>
 of a <Code>
VisualComponent</Code>
 to a (optional) <Code>
String</Code>
. In <Code>
TabControlExample</Code>
, this is handled in two methods:</Body1>
<CodeSample>
<A ID="pgfId-959912"></A>
tabs</CodeSample>
<CodeSample>
<A ID="pgfId-959913"></A>
	tabs isNil</CodeSample>
<CodeSample>
<A ID="pgfId-959914"></A>
		ifTrue:</CodeSample>
<CodeSample>
<A ID="pgfId-959915"></A>
			[(tabs := SelectionInList with: self labelArray) </CodeSample>
<CodeSample>
<A ID="pgfId-960018"></A>
				selectionIndex: 1.</CodeSample>
<CodeSample>
<A ID="pgfId-959916"></A>
			tabs selectionIndexHolder </CodeSample>
<CodeSample>
<A ID="pgfId-960019"></A>
				onChangeSend: #tabsChanged</CodeSample>
<CodeSample>
<A ID="pgfId-960020"></A>
				to: self].</CodeSample>
<CodeSample>
<A ID="pgfId-959907"></A>
	^tabs</CodeSample>
<CodeSample>
<A ID="pgfId-959924"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-959927"></A>
labelArray</CodeSample>
<CodeSample>
<A ID="pgfId-959928"></A>
	&quot;Private - The list of tab names (and/or icons). See also #specArray.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-959929"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-959930"></A>
	^Array</CodeSample>
<CodeSample>
<A ID="pgfId-959931"></A>
		with: &#39;Appearance&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-959932"></A>
		with: self class colorsImage -&gt; &#39;Colors&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-959925"></A>
		with: self class printerImage -&gt; &#39;&#39;</CodeSample>
<StepCont>
<A ID="pgfId-960032"></A>
Paint subcanvases for each page (See the <Code>
appearanceSpec</Code>
, <Code>
colorsSpec</Code>
, and <Code>
fontsSpec</Code>
 class methods in TabControlExample for examples.)</StepCont>
<Body1>
<A ID="pgfId-960061"></A>
So the canvas can be identified by an index, which will be retrieved from labelArray, TabControlExample defines a specAttay method:</Body1>
<CodeSample>
<A ID="pgfId-960070"></A>
specArray</CodeSample>
<CodeSample>
<A ID="pgfId-960071"></A>
	&quot;Private - The list of associated sub canvaes. See also #labelArray.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-960072"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-960065"></A>
	^#(#appearanceSpec #fontsSpec #colorsSpec)</CodeSample>
<StepCont>
<A ID="pgfId-960033"></A>
Define a method that will respond by changing subcanvases when the tab selection has changed. This message is sent when the <Code>
SelectionInList</Code>
 changes, as is defined in the <Code>
tabs</Code>
 method.</StepCont>
<CodeSample>
<A ID="pgfId-960048"></A>
tabsChanged</CodeSample>
<CodeSample>
<A ID="pgfId-960049"></A>
	&quot;Every time, a tab is changed, a new sub canvas gets installed.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-960050"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-960051"></A>
	| index |</CodeSample>
<CodeSample>
<A ID="pgfId-960052"></A>
	index := self tabs selectionIndex.</CodeSample>
<Code2-In1-Last-Only>
<A ID="pgfId-960040"></A>
	(self builder componentAt: #tabbing) widget </Code2-In1-Last-Only>
<CodeSample>
<A ID="pgfId-960059"></A>
		client: self </CodeSample>
<CodeSample>
<A ID="pgfId-960060"></A>
		spec: (self specArray at: index)</CodeSample>
<Body1>
<A ID="pgfId-960169"></A>
The change is made by the <Code>
client:spec:</Code>
 message sent to the Tab Control widget, which is retrieved from the builder. </Body1>
<Body1>
<A ID="pgfId-960037"></A>
For additional options and approaches, see <A href="09-widgets.xml#id(98255)" xml:link="simple" show="replace" actuate="user" CLASS="XRef"><Hyperlink-reference>
Notebooks</Hyperlink-reference>
</A>.</Body1>
<Heading3>
<A ID="pgfId-960082"></A>
Defining Initial Labels</Heading3>
<Body1>
<A ID="pgfId-960188"></A>
The above example defines the set of tab labels in code. You have the option of defining labels directly in the <UI-Label>
Details</UI-Label>
 property page. This can be convenient, especially when there is no need to add pages dynamically. </Body1>
<Body1>
<A ID="pgfId-960198"></A>
To add a label, enter it into the Entry Field below the List and click <UI-Label>
Add</UI-Label>
. To change a label, select it, edit it in the Entry Field, and click <UI-Label>
Change</UI-Label>
. To delete, click Delete. To change the order of lables, select a label and drag it to its new position in the list.</Body1>
<Body1>
<A ID="pgfId-960205"></A>
When you click <UI-Label>
Apply</UI-Label>
, your labels are shown in the canvas, unlike when you provide labels in code.</Body1>
<Body1>
<A ID="pgfId-960209"></A>
You access the label by index as before, and so can change subcanvases in the same way. So, within the Application Model, for a Tab Control with aspect name <Code>
tabs</Code>
, send:</Body1>
<Code1-Last-Only>
<A ID="pgfId-960212"></A>
self tabs selectionIndex</Code1-Last-Only>
<Body1>
<A ID="pgfId-960218"></A>
returns the index of the currently selected tab.</Body1>
<Heading3>
<A ID="pgfId-960187"></A>
Placing an Icon on a Tab</Heading3>
<Body1>
<A ID="pgfId-960088"></A>
Each tab label can be a string, an icon, or an icon and a string. To use an icon, the <Code>
SelectionInList</Code>
 must be an <Code>
Association</Code>
. The tabs method invokes labelArray to provide the labels, as follows:</Body1>
<CodeSample>
<A ID="pgfId-960104"></A>
labelArray</CodeSample>
<CodeSample>
<A ID="pgfId-960105"></A>
	&quot;Private - The list of tab names (and/or icons). See also #specArray.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-960106"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-960107"></A>
	^Array</CodeSample>
<CodeSample>
<A ID="pgfId-960108"></A>
		with: &#39;Appearance&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-960109"></A>
		with: self class colorsImage -&gt; &#39;Colors&#39;</CodeSample>
<Code1-Last-Only>
<A ID="pgfId-960099"></A>
		with: self class printerImage -&gt; &#39;&#39;</Code1-Last-Only>
<Body1>
<A ID="pgfId-960116"></A>
If the label is only a string, then it is provided simply as a String, as in the case with the first tab, &#39;Appearance&#39;.</Body1>
<Body1>
<A ID="pgfId-960128"></A>
If the label includes an icon, then the label is specified by an <Code>
Association</Code>
 between the icon and a <Code>
String</Code>
. The second tab label is an <Code>
Association</Code>
 between the graphic returned by <Code>
self colorsImage</Code>
 and the <Code>
String</Code>
 &#39;Colors&#39;.</Body1>
<Body1>
<A ID="pgfId-960158"></A>
The third tab is an icon without a <Code>
String</Code>
, so the <Code>
String</Code>
 is empty.</Body1>
<Heading-Anchor>
<A ID="pgfId-946478"></A>
</Heading-Anchor>
<Heading2>
<A ID="pgfId-1040890"></A>
Text Editors</Heading2>
<Heading3>
<A ID="pgfId-1040892"></A>
<A ID="81736"></A>
Add a text editor to a canvas</Heading3>
<StepStart>
<A ID="pgfId-1040895"></A>
Use a Palette to add a text editor to the canvas, leaving it selected.</StepStart>
<StepCont>
<A ID="pgfId-1040896"></A>
In the GUI Painter Tool,  fill in the editor&#39;s <UI-Label>
Aspect</UI-Label>
 property with the name of the method (<Code>
comment</Code>
) that will return the value model for the text editor.</StepCont>
<StepCont>
<A ID="pgfId-1041198"></A>
Use the <UI-Label>
define</UI-Label>
 command to add an instance variable (<Code>
comment</Code>
) and accessor method to the application model for storing the text editor&#39;s value model.</StepCont>
<StepCont>
<A ID="pgfId-1040903"></A>
Create an <Code>
initialize</Code>
 method that initializes the aspect variable (<Code>
comment</Code>
) with a <A href="10-glossary.xml#id(value holder)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value holder</A> containing the initial text to be displayed (an empty string).</StepCont>
<CodeSample>
<A ID="pgfId-1040904"></A>
initialize
		super initialize.

		comment := &#39;&#39; 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</CodeSample>
<Body1>
<A ID="pgfId-1041158"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Editor1.pcl" show="embed" actuate="auto">
Editor1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040918"></A>
Access and modify selected text</Heading3>
<Body1>
<A ID="pgfId-1041230"></A>
Your application can access and modify a selected (highlighted) portion of text in an editor. </Body1>
<StepStart>
<A ID="pgfId-1040921"></A>
In a method in the application model, get the widget&#39;s controller by sending a <Code>
controller</Code>
 message to the widget. </StepStart>
<StepCont>
<A ID="pgfId-1040923"></A>
Get the selected text from the controller by sending a <Code>
selection</Code>
 message to the widget.</StepCont>
<StepCont>
<A ID="pgfId-1040924"></A>
Make any changes to the selected text, such as format changes.</StepCont>
<StepCont>
<A ID="pgfId-1040925"></A>
Replace the original text with the modified text, by sending a <Code>
replaceSelectedText:</Code>
 message to the controller.</StepCont>
<StepCont>
<A ID="pgfId-1040926"></A>
Send <Code>
resetSelections</Code>
 and <Code>
invalidate</Code>
 messages to the controller&#39;s view to update the display.</StepCont>
<CodeSample>
<A ID="pgfId-1040927"></A>
changedStyle
		&quot;A text style was selected -- apply it to the current selection in
		the comment.&quot;

		| c selectedText style |

		&quot;Get the selected text.&quot;
		c := (builder componentAt: #comment) widget controller.
		selectedText := c selection.

		&quot;If nothing is selected, take no action.&quot;
		selectedText isEmpty ifTrue: [^self].

		&quot;If &#39;Plain&#39; was selected, remove all emphases;
		otherwise add the new emphasis.&quot;
		style := self textStyle value.
		style == #plain
			ifTrue: [selectedText emphasizeAllWith: nil]
			ifFalse: [
				selectedText addEmphasis: (Array with: style)
					removeEmphasis: nil
					allowDuplicates: false].

		&quot;Ask the controller to insert the modified text, then
		update the view.&quot;
		c replaceSelectionWith: selectedText.
		c view resetSelections.
		c view invalidate.</CodeSample>
<Body1>
<A ID="pgfId-1041168"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Editor1.pcl" show="embed" actuate="auto">
Editor1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040954"></A>
Highlight text programmatically</Heading3>
<Body1>
<A ID="pgfId-1040955"></A>
Your application can highlight text for the user (e.g., as part of spell checking.)</Body1>
<StepStart>
<A ID="pgfId-1041118"></A>
In a method in the application model, get the controller from the widget.</StepStart>
<StepCont>
<A ID="pgfId-1041120"></A>
Ask the controller to select the text between two endpoints (and ask it to scroll the selection into view if necessary).</StepCont>
<StepCont>
<A ID="pgfId-1040963"></A>
Ask the builder&#39;s component to take the keyboard focus, so the highlighting will be displayed.</StepCont>
<CodeSample>
<A ID="pgfId-1040964"></A>
changedClass
		&quot;When the list selection changes, update the comment view.&quot;

		| selectedClass txt start wrapper |
		selectedClass := self classes selection.

		selectedClass isNil
			ifTrue: [self comment value: &#39;&#39; asText]
			ifFalse: [
				txt := (Smalltalk at: selectedClass) comment.

				self comment 
					value: txt.

				&quot;Find and highlight the class name in the text.&quot;
				start := txt 
					indexOfSubCollection: selectedClass asString 
					startingAt: 1.
				start &gt; 0 ifTrue: [
					wrapper := (self builder componentAt: #comment).
					wrapper widget controller
						selectAndScrollFrom: start 
						to: start + selectedClass asString size - 1.
					wrapper takeKeyboardFocus]].</CodeSample>
<Body1>
<A ID="pgfId-1041174"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Editor1.pcl" show="embed" actuate="auto">
Editor1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040988"></A>
Set text alignment</Heading3>
<Body1>
<A ID="pgfId-1040989"></A>
To change the default alignment in an editor, set the <UI-Label>
Align</UI-Label>
 property in the GUI Painter Tool.</Body1>
<Heading3>
<A ID="pgfId-1040990"></A>
Change text alignment programmatically</Heading3>
<StepStart>
<A ID="pgfId-1040992"></A>
In a method in the application model, get the widget from the builder.</StepStart>
<StepCont>
<A ID="pgfId-1040994"></A>
Get a copy of the widget&#39;s text style. (Do not modify the widget&#39;s text style directly, because that object is shared by many text editors in the system.)</StepCont>
<StepCont>
<A ID="pgfId-1040996"></A>
Set the alignment of the text style to <Code>
0</Code>
, <Code>
1</Code>
, or <Code>
2</Code>
 (<Code>
0</Code>
 is flush left, <Code>
1</Code>
 is flush right, and <Code>
2</Code>
 is centered).</StepCont>
<StepCont>
<A ID="pgfId-1040998"></A>
<UI-Label>
Install</UI-Label>
 the new text style in the widget.</StepCont>
<StepCont>
<A ID="pgfId-1041000"></A>
Ask the widget to redisplay itself.</StepCont>
<CodeSample>
<A ID="pgfId-1041001"></A>
alignRight
		| widget style |
		widget := (self builder componentAt: #comment) widget.
		style := widget textStyle copy.
		style alignment: 1.
		widget textStyle: style.
		widget invalidate.</CodeSample>
<Heading3>
<A ID="pgfId-1041188"></A>
Set a text editor to be read-only</Heading3>
<Body1>
<A ID="pgfId-1041189"></A>
To make the editor read-only, set the editor&#39;s <UI-Label>
Read Only</UI-Label>
 property in the GUI Painter Tool.</Body1>
<Heading3>
<A ID="pgfId-1041010"></A>
Change the read-only setting programmatically</Heading3>
<StepStart>
<A ID="pgfId-1041012"></A>
In a method in the application model, get the widget&#39;s controller.</StepStart>
<StepCont>
<A ID="pgfId-1041013"></A>
Set the controller&#39;s read-only setting to <Code>
true</Code>
 or <Code>
false</Code>
.</StepCont>
<CodeSample>
<A ID="pgfId-1041014"></A>
makeReadOnly
		| c |
		c := (self builder componentAt: #comment) widget controller.
		c readOnly: true.</CodeSample>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-1040334"></A>
Lists</Heading2>
<Heading3>
<A ID="pgfId-1040336"></A>
Add a list to a canvas</Heading3>
<Body1>
<A ID="pgfId-1040337"></A>
Use a list widget to display a collection of objects and to allow the user to select one or more elements in the list.</Body1>
<Body1>
<A ID="pgfId-1040967"></A>
A list widget depends on two value holders: a collection of objects and the index of the current selection. A <Code>
SelectionInList</Code>
 object contains both of these value holders.</Body1>
<StepStart>
<A ID="pgfId-1040339"></A>
Add a list widget to the canvas, leaving it selected. </StepStart>
<StepCont>
<A ID="pgfId-1041093"></A>
On the Basics page of the GUI Paitner Tool, fill in the list&#39;s Aspect property with the name of the method that will return an instance of <Code>
SelectionInList</Code>
.</StepCont>
<StepCont>
<A ID="pgfId-1040343"></A>
Use the canvas&#39;s define command to add an instance variable (<Code>
classes</Code>
) to the application model, and to create a corresponding aspect method. This instance variable will hold the <Code>
SelectionInList</Code>
.</StepCont>
<StepCont>
<A ID="pgfId-1040347"></A>
Create an <Code>
initialize</Code>
 method to assign a default value to the instance variable you created in step 2 (<Code>
classes</Code>
). Initialize the variable with an instance of <Code>
SelectionInList</Code>
 that is itself initialized with a list of Smalltalk class names.</StepCont>
<CodeSample>
<A ID="pgfId-1040348"></A>
initialize
		super initialize.
		classes := SelectionInList with: Smalltalk classNames.
		classes selectionIndexHolder onChangeSend:
			 #changedClass to: self.

		methodNames := MultiSelectionInList new.

		instances := SelectionInList new.</CodeSample>
<Body1>
<A ID="pgfId-1040686"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040358"></A>
Display a list of non-textual elements</Heading3>
<Body1>
<A ID="pgfId-1040360"></A>
Create a new <Code>
displayString</Code>
 method in the class of the element to be listed. The list will send this message to each element at display time. (The following method is implemented in the <Code>
Association</Code>
 class.)</Body1>
<CodeSample>
<A ID="pgfId-1040361"></A>
displayString
		&quot;Allows a value to be quietly associated with the key that is 
		displayed in a SequenceView.&quot;

		^key displayString</CodeSample>
<Heading3>
<A ID="pgfId-1040366"></A>
Edit a list of elements</Heading3>
<Body1>
<A ID="pgfId-1040367"></A>
To change the list of elements, give the <Code>
SelectionInList</Code>
 a new collection of elements. </Body1>
<StepStart>
<A ID="pgfId-1040370"></A>
In the method that is responsible for updating the list, get the <Code>
SelectionInList</Code>
 from the application model </StepStart>
<StepCont>
<A ID="pgfId-1040371"></A>
Send a <Code>
list:</Code>
 message to the <Code>
SelectionInList</Code>
 with the new collection as the argument.</StepCont>
<CodeSample>
<A ID="pgfId-1040372"></A>
changedClass
		| cls |
		self classes selection isNil

			&quot;No class is selected -- empty the selector list.&quot;
			ifTrue: [
				self methodNames list: List new.
				self instances list: List new]

			&quot;A class is selected&quot;
			ifFalse: [
				cls := Smalltalk at: self classes selection.

				&quot;Update the selectors list.&quot;
				self methodNames list: cls selectors asSortedCollection.

				&quot;Update the instances list.&quot;
				self instances list: cls allInstances].</CodeSample>
<Body1>
<A ID="pgfId-1040696"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040390"></A>
Allow multiple list selections</Heading3>
<Body1>
<A ID="pgfId-1040391"></A>
You can select more than one item in a list as targets for an action. A list allows multiple selections when its Multi Select property is turned on. </Body1>
<Body1>
<A ID="pgfId-1040392"></A>
The Use Modifier Keys For Multi Select property determines how modifier keys behave in selecting. When set (the default):</Body1>
<Bullet1>
<A ID="pgfId-1040393"></A>
The &lt;Select&gt; mouse button to selects a single item on the list</Bullet1>
<Bullet1>
<A ID="pgfId-1040394"></A>
&lt;Shift&gt;-click selects additional contiguous items</Bullet1>
<Bullet1>
<A ID="pgfId-1040395"></A>
&lt;Control&gt;-click selects an additional noncontiguous item</Bullet1>
<StepStart>
<A ID="pgfId-1040397"></A>
Select the list widget in the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040398"></A>
In the GUI Painter Tool, turn on the list widget&#39;s Multi Select property. </StepCont>
<StepCont>
<A ID="pgfId-1040399"></A>
Apply properties and Install the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040401"></A>
In the application model&#39;s <Code>
initialize</Code>
 method, initialize the list widget&#39;s aspect variable to hold a <Code>
MultiSelectionInList</Code>
.</StepCont>
<CodeSample>
<A ID="pgfId-1040402"></A>
initialize
		super initialize.
		classes := SelectionInList with: Smalltalk classNames.
		classes selectionIndexHolder onChangeSend: #changedClass to: self.

		methodNames := MultiSelectionInList new.
		instances := SelectionInList new.</CodeSample>
<Body1>
<A ID="pgfId-1040702"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040409"></A>
Get a list selection</Heading3>
<Body1>
<A ID="pgfId-1040410"></A>
You can ask a <Code>
SelectionInList</Code>
 for the selected object or for the index of the selected object in the list. For a multiselect list, the application model must be able to handle a collection of objects.</Body1>
<Body1>
<A ID="pgfId-1040411"></A>
When nothing is selected, a <Code>
SelectionInList</Code>
 returns <Code>
nil</Code>
 as the selection and zero as the index; a <Code>
MultiSelectionInList</Code>
 returns an empty collection for both the selections and the indexes.</Body1>
<StepStart>
<A ID="pgfId-1040413"></A>
Get the <Code>
SelectionInList</Code>
 (or <Code>
MultiSelectionInList</Code>
) from the application model.</StepStart>
<StepCont>
<A ID="pgfId-1040414"></A>
To get the selected item(s) and send a <Code>
selection</Code>
 (or <Code>
selections</Code>
) message.</StepCont>
<StepCont>
<A ID="pgfId-1040415"></A>
To get the index(es), send a <Code>
selectionIndex </Code>
(<Code>
selectionIndexes</Code>
) message.</StepCont>
<CodeSample>
<A ID="pgfId-1040416"></A>
changedClass
		| cls |
		<CodeEmp>
self classes selection</CodeEmp>
 isNil

			&quot;No class is selected -- empty the selector list.&quot;
			ifTrue: [
				self methodNames list: List new.
				self instances list: List new]

			&quot;A class is selected&quot;
			ifFalse: [
				cls := Smalltalk at: self classes selection.

				&quot;Update the selectors list.&quot;
				self methodNames list: cls selectors asSortedCollection.

				&quot;Update the instances list.&quot;
				self instances list: cls allInstances].</CodeSample>
<Body1>
<A ID="pgfId-1040708"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040434"></A>
Set list selections programmatically</Heading3>
<StepStart>
<A ID="pgfId-1040436"></A>
Get the <Code>
SelectionInList</Code>
 from the application model</StepStart>
<StepCont>
<A ID="pgfId-1040437"></A>
To select by index, send it a <Code>
selectionIndex:</Code>
 message with the index number as argument. </StepCont>
<StepCont>
<A ID="pgfId-1040438"></A>
To select by item, send it a <Code>
selection:</Code>
 message with the object as argument.</StepCont>
<CodeSample>
<A ID="pgfId-1040439"></A>
postOpenWith: aBuilder

		super postOpenWith: aBuilder.

		&quot;Uncomment the line below to auto-select the first class.&quot;
		self classes selectionIndex: 1.

		&quot;Uncomment the lines below to auto-select the last class.&quot;
		&quot;self classes selection: self classes list last.
		(aBuilder componentAt: #classes) widget controller 
			cursorPointWithScrolling.&quot;

	&quot;In the classes list, use boxed highlighting instead of reverse-
video.&quot;
		(aBuilder componentAt: #classes) widget strokedSelection.</CodeSample>
<Body1>
<A ID="pgfId-1040454"></A>
For a <Code>
MultiSelectionInList</Code>
, send <Code>
selectionIndexes:</Code>
 or <Code>
selections:</Code>
, with the appropriate collection as argument.</Body1>
<Body1>
<A ID="pgfId-1040714"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040455"></A>
Select all objects in a multiple-selection list</Heading3>
<StepStart>
<A ID="pgfId-1040456"></A>
Get the <Code>
MultiSelectionInList</Code>
 from the application model.</StepStart>
<StepCont>
<A ID="pgfId-1040457"></A>
Send a <Code>
selectAll</Code>
 message to it.</StepCont>
<CodeSample>
<A ID="pgfId-1040458"></A>
selectAll
		self methodNames selectAll.</CodeSample>
<Heading3>
<A ID="pgfId-1040460"></A>
Clear all selections in a multiple-selection list</Heading3>
<StepStart>
<A ID="pgfId-1040461"></A>
Get the <Code>
MultiSelectionInList</Code>
 from the application model</StepStart>
<StepCont>
<A ID="pgfId-1040462"></A>
Send a <Code>
clearAll</Code>
 message to it.</StepCont>
<CodeSample>
<A ID="pgfId-1040463"></A>
clearAll
		self methodNames clearAll.</CodeSample>
<Heading3>
<A ID="pgfId-1040465"></A>
Add a menu to a list</Heading3>
<Body1>
<A ID="pgfId-1040466"></A>
By default, a list does not have a pop-up menu, but it is sometimes useful to have a menu that includes:</Body1>
<Bullet1>
<A ID="pgfId-1040467"></A>
Commands that act on the selection(s).</Bullet1>
<Bullet1>
<A ID="pgfId-1040468"></A>
Commands that act on the list itself, usually by updating or filtering its contents.</Bullet1>
<Body1>
<A ID="pgfId-1040470"></A>
To add a menu:</Body1>
<StepStart>
<A ID="pgfId-1040471"></A>
Select the list widget in the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040472"></A>
In the GUI Painter Tool, fill in the list widget&#39;s Menu property with the name of the method that will supply the menu.</StepCont>
<StepCont>
<A ID="pgfId-1040473"></A>
<UI-Label>
Apply</UI-Label>
 the property and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040474"></A>
Use a Menu Editor to create the menu method.</StepCont>
<StepCont>
<A ID="pgfId-1040476"></A>
Create the methods that are invoked by the menu.</StepCont>
<Body1>
<A ID="pgfId-1040720"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
 (Instances view)</Body1>
<Heading3>
<A ID="pgfId-1040477"></A>
Change the highlighting style</Heading3>
<Body1>
<A ID="pgfId-1040478"></A>
By default, selected items are highlighted with reverse video. To change this to a check mark, set the list&#39;s Selection Type property in the GUI Painter Tool. </Body1>
<Body1>
<A ID="pgfId-1040479"></A>
You can programmatically arrange for selected items to be surrounded by a rectangular border.</Body1>
<StepStart>
<A ID="pgfId-1040481"></A>
In a method in the application model (typically <Code>
postBuildWith: </Code>
or <Code>
postOpenWith:</Code>
), get the list widget from the application model&#39;s builder.</StepStart>
<StepCont>
<A ID="pgfId-1040482"></A>
Send a <Code>
strokedSelection</Code>
 message to the widget. (Send a <Code>
normalSelection</Code>
 message to revert to normal highlighting.)</StepCont>
<CodeSample>
<A ID="pgfId-1040483"></A>
postOpenWith: aBuilder

		super postOpenWith: aBuilder. 

		&quot;Uncomment the line below to auto-select the first class.&quot;
		self classes selectionIndex: 1.

		&quot;Uncomment the lines below to auto-select the last class.&quot;
		&quot;self classes selection: self classes list last.
		(aBuilder componentAt: #classes) widget controller 
			cursorPointWithScrolling.&quot;

		&quot;In the classes list, use boxed highlighting instead of 
		reverse-video.&quot;
		(aBuilder componentAt: #classes) widget strokedSelection.</CodeSample>
<Body1>
<A ID="pgfId-1041035"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040498"></A>
Connect two lists</Heading3>
<Body1>
<A ID="pgfId-1040499"></A>
As for any interaction between widgets, lists may be connected by declaring dependencies between them.</Body1>
<StepStart>
<A ID="pgfId-1040502"></A>
In the application model&#39;s <Code>
initialize</Code>
 method, arrange for a change message (<Code>
changedClass</Code>
) to be sent when the selection is changed in the first list.</StepStart>
<CodeSample>
<A ID="pgfId-1040503"></A>
initialize
		super initialize.
		classes := SelectionInList with: Smalltalk classNames.
		classes selectionIndexHolder 
			onChangeSend: #changedClass to: self. 

		methodNames := MultiSelectionInList new.
		instances := SelectionInList new.</CodeSample>
<StepCont>
<A ID="pgfId-1040511"></A>
Create the change method (<Code>
changedClass</Code>
) in the application model to update the second list (<Code>
methodNames</Code>
) when appropriate.</StepCont>
<CodeSample>
<A ID="pgfId-1040512"></A>
changedClass
		| cls |
		self classes selection isNil

			&quot;No class is selected -- empty the selector list.&quot;
			ifTrue: [
				self methodNames list: List new.
				self instances list: List new]

			&quot;A class is selected&quot;
			ifFalse: [
				cls := Smalltalk at: self classes selection.

				&quot;Update the selectors list.&quot;
				self methodNames list: cls selectors asSortedCollection.

				&quot;Update the instances list.&quot;
				self instances list: cls allInstances].</CodeSample>
<Body1>
<A ID="pgfId-1040726"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List1.pcl" show="embed" actuate="auto">
List1Example</CodeExample>
 </Body1>
<Heading3>
<A ID="pgfId-1040530"></A>
Connect a list to a text editor</Heading3>
<StepStart>
<A ID="pgfId-1040534"></A>
In the application model&#39;s <Code>
initialize</Code>
 method, arrange for a change message (<Code>
changedClass</Code>
) to be sent to the application model whenever the list selection is changed. </StepStart>
<CodeSample>
<A ID="pgfId-1040535"></A>
initialize
		super initialize.

		comment := &#39;&#39; 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.</CodeSample>
<StepCont>
<A ID="pgfId-1040549"></A>
Create the change method (<Code>
changedClass</Code>
) in the application model to update the text editor&#39;s value holder (<Code>
comment</Code>
) appropriately.</StepCont>
<CodeSample>
<A ID="pgfId-1040550"></A>
changedClass
		&quot;When the list selection changes, update
			the comment view.&quot;

		| selectedClass txt start wrapper |
		selectedClass := self classes selection.

		selectedClass isNil
			ifTrue: [self comment value: &#39;&#39; asText]
			ifFalse: [
				txt := (Smalltalk at: selectedClass) comment.

				self comment 
					value: txt.

				&quot;Find and highlight the class name in the text.&quot;
				start := txt 
					indexOfSubCollection: selectedClass asString 
					startingAt: 1.
				start &gt; 0
					ifTrue: [
						wrapper := (self builder componentAt: #comment).
						wrapper widget controller
							selectAndScrollFrom: start 
							to: start + selectedClass asString size - 1.
						wrapper takeKeyboardFocus]].</CodeSample>
<Body1>
<A ID="pgfId-1040732"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Editor1.pcl" show="embed" actuate="auto">
Editor1Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1040057"></A>
</Body1>
<Heading2>
<A ID="pgfId-959419"></A>
Hierarchical Lists</Heading2>
<Heading3>
<A ID="pgfId-962115"></A>
About Hierarchical Lists</Heading3>
<Note1List>
<Note1>
<A ID="pgfId-961426"></A>
</Note1>
<DIV>
<IMAGE xml:link="simple" href="09-widgets-8.gif" show="embed" actuate="auto"/>
</DIV>
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.<DIV>
<IMAGE xml:link="simple" href="09-widgets-9.gif" show="embed" actuate="auto"/>
</DIV>
</Note1List>
<Body1>
<A ID="pgfId-954174"></A>
A <A ID="marker-954173"></A>
Hierarchical List widget is similar to a List widget, but its primary component is an <Code>
IndentedTreeSelectionInList</Code>
<A ID="marker-954175"></A>
. This object holds a tree object representing the hierarchy.</Body1>
<Body1>
<A ID="pgfId-954176"></A>
For cases where the hierarchical list is displaying a natural hierarchy, such as the class hierarchy, <Code>
IndentedTreeSelectionInList</Code>
 provides instance creation methods to create the tree. Otherwise, create the tree using instances of <Code>
AssociationTreeWithParent</Code>
.</Body1>
<Body1>
<A ID="pgfId-954177"></A>
Retrieving the index and contents of a list item uses the same methods as for a List widget&#39;s <Code>
SelectionInList</Code>
.</Body1>
<Heading3>
<A ID="pgfId-954180"></A>
<A ID="marker-954179"></A>
Adding a List</Heading3>
<StepStart>
<A ID="pgfId-954181"></A>
Use a Palette to add a Hierarchical List widget to the canvas. Leave the list selected.</StepStart>
<StepCont>
<A ID="pgfId-960232"></A>
On the <UI-Label>
Basics</UI-Label>
 property page, fill in the list&#39;s <UI-Label>
Aspect</UI-Label>
 property with the name of the method that will return an instance of <Code>
IndentedTreeSelectionInList</Code>
.</StepCont>
<StepCont>
<A ID="pgfId-960233"></A>
<UI-Label>
Apply</UI-Label>
 the change, install the canvas, and use <UI-Label>
define </UI-Label>
to add an instance variable and aspect accessor method to the application model. This instance variable will hold the <Code>
SelectionInList</Code>
.</StepCont>
<StepCont>
<A ID="pgfId-954187"></A>
Write an <Code>
initialize</Code>
 method to initialize the <Code>
IndentedTreeSelectionInList</Code>
.</StepCont>
<Heading3>
<A ID="pgfId-954188"></A>
Create a List for a Natural Tree</Heading3>
<Body1>
<A ID="pgfId-954189"></A>
The <Code>
IndentedTreeSelectionInList</Code>
 class has a few instance creation methods that make it easy to create a tree out of an object with a natural hierarchy. For instance, the class method <Code>
#listObjectHierarchy:childAccessor:childNameAccessor:</Code>
 can create an appropriate list object as follows:</Body1>
<CodeSample>
<A ID="pgfId-954190"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-954191"></A>
	theList := IndentedTreeSelectionInList</CodeSample>
<CodeSample>
<A ID="pgfId-954192"></A>
				listObjectHierarchy: Object</CodeSample>
<CodeSample>
<A ID="pgfId-954193"></A>
				childAccessor: #allSubclasses</CodeSample>
<CodeSample>
<A ID="pgfId-954194"></A>
				childNameAccessor: #name.</CodeSample>
<Code1-Last-Only>
<A ID="pgfId-954195"></A>
	^self</Code1-Last-Only>
<Body1>
<A ID="pgfId-954196"></A>
For other instance creation convenience methods, browse the instance creation protocol.</Body1>
<Heading3>
<A ID="pgfId-954197"></A>
Building a Tree</Heading3>
<Body1>
<A ID="pgfId-954198"></A>
You can build a hierarchy of arbitrary objects using instances of <Code>
AssociationTree</Code>
 or <Code>
AssociationTreeWithParent</Code>
. Then use the tree as the source of the hierarchy for the Hierarchical List widget.</Body1>
<Body1>
<A ID="pgfId-954199"></A>
This version of the initialize method creates a hierarchy:</Body1>
<CodeSample>
<A ID="pgfId-954200"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-954201"></A>
	tree := (AssociationTreeWithParent key: &#39;first&#39; value: #first).</CodeSample>
<CodeSample>
<A ID="pgfId-954202"></A>
	tree addChild: </CodeSample>
<CodeSample>
<A ID="pgfId-954203"></A>
		((AssociationTreeWithParent </CodeSample>
<CodeSample>
<A ID="pgfId-954204"></A>
			key: &#39;second&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-954205"></A>
			value: #second)</CodeSample>
<CodeSample>
<A ID="pgfId-954206"></A>
			addChild: (AssociationTreeWithParent </CodeSample>
<CodeSample>
<A ID="pgfId-954207"></A>
				key: &#39;third&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-954208"></A>
				value: #third);</CodeSample>
<CodeSample>
<A ID="pgfId-954209"></A>
			addChild: (AssociationTreeWithParent </CodeSample>
<CodeSample>
<A ID="pgfId-954210"></A>
				key: &#39;fourth&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-954211"></A>
				value: #fourth));</CodeSample>
<Code1-Last-Only>
<A ID="pgfId-959239"></A>
</Code1-Last-Only>
<CodeSample>
<A ID="pgfId-954212"></A>
		addChild: ((AssociationTreeWithParent </CodeSample>
<CodeSample>
<A ID="pgfId-954213"></A>
			key: &#39;fifth&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-954214"></A>
			value: #fifth)</CodeSample>
<CodeSample>
<A ID="pgfId-954215"></A>
			addChild: (AssociationTreeWithParent </CodeSample>
<CodeSample>
<A ID="pgfId-954216"></A>
				key: &#39;sixth&#39; </CodeSample>
<CodeSample>
<A ID="pgfId-954217"></A>
				value: #sixth);</CodeSample>
<CodeSample>
<A ID="pgfId-954218"></A>
			addChild: (AssociationTreeWithParent </CodeSample>
<CodeSample>
<A ID="pgfId-954219"></A>
				key: &#39;seventh&#39;</CodeSample>
<CodeSample>
<A ID="pgfId-954220"></A>
				value: #seventh)).</CodeSample>
<Code1-Last-Only>
<A ID="pgfId-954221"></A>
</Code1-Last-Only>
<CodeSample>
<A ID="pgfId-954222"></A>
	myList := IndentedTreeSelectionInList</CodeSample>
<CodeSample>
<A ID="pgfId-954223"></A>
				listObjectHierarchy: tree</CodeSample>
<CodeSample>
<A ID="pgfId-954224"></A>
				childAccessor: #children</CodeSample>
<CodeSample>
<A ID="pgfId-954225"></A>
				childNameAccessor: #displayString.</CodeSample>
<CodeSample>
<A ID="pgfId-954226"></A>
</CodeSample>
<Code1-Last-Only>
<A ID="pgfId-954227"></A>
	^self</Code1-Last-Only>
<Heading2>
<A ID="pgfId-957371"></A>
Charts</Heading2>
<Heading3>
<A ID="pgfId-962118"></A>
About Charts</Heading3>
<Body1>
<A ID="pgfId-957059"></A>
The <A ID="marker-957058"></A>
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. </Body1>
<Body1>
<A ID="pgfId-954758"></A>
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 <A ID="marker-954759"></A>
<New-Term>
data series</New-Term>
. </Body1>
<Body1>
<A ID="pgfId-954760"></A>
To use this widget, load the BGOK parcel.</Body1>
<Heading3>
<A ID="pgfId-954764"></A>
Adding a Chart</Heading3>
<Body1>
<A ID="pgfId-954765"></A>
To add a bar chart to an application:</Body1>
<StepStart>
<A ID="pgfId-954766"></A>
Select the Chart widget in the Palette, and drop it on a canvas. </StepStart>
<StepCont>
<A ID="pgfId-954767"></A>
On the <UI-Label>
Basics</UI-Label>
 property page, specify the chart&#39;s <UI-Label>
Aspect</UI-Label>
, which is the the name of the instance variable and accessor method that supplies the data to the chart.</StepCont>
<Body1>
<A ID="pgfId-954768"></A>
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 <A href="09-widgets.xml#id(19271)" xml:link="simple" show="replace" actuate="user" CLASS="XRef"><Hyperlink-reference>
&#34;Charting Multiple Data Series&#34;</Hyperlink-reference>
</A>.</Body1>
<StepCont>
<A ID="pgfId-954772"></A>
Select the chart type and click <UI-Label>
Apply</UI-Label>
</StepCont>
<StepCont>
<A ID="pgfId-954773"></A>
Install the canvas.</StepCont>
<StepCont>
<A ID="pgfId-954774"></A>
Create a definition for the chart widget&#39;s aspect and edit it to return a value holder on the collection containing the chart data.</StepCont>
<Heading3>
<A ID="pgfId-954776"></A>
<A ID="19271"></A>
Charting Multiple Data Series</Heading3>
<Body1>
<A ID="pgfId-954777"></A>
A more complex chart, such as one that compares performance of two or more entities over time, needs to plot more than a single series of data points. To do this, you declare the multiple data series. </Body1>
<Body1>
<A ID="pgfId-954778"></A>
The <UI-Label>
Aspect</UI-Label>
 for your chart declared on the <UI-Label>
Basics</UI-Label>
 property page is still the instance variable for your chart data, but it now is a collection of items with some additional structure. </Body1>
<Body1>
<A ID="pgfId-954779"></A>
The simplest case is that it is a collection of simple collections of numbers, such as the following array of arrays:</Body1>
<Code1-Last-Only>
<A ID="pgfId-954780"></A>
#(#(60 40) #(20 55) #(35 10) #(75 50))</Code1-Last-Only>
<Body1>
<A ID="pgfId-954781"></A>
The data series can be identified by index within the subcollections. (See <Code>
BG_EzChart</Code>
 for an example of this approach.)</Body1>
<Body1>
<A ID="pgfId-954782"></A>
More typically, the collection will consist of structured objects, such as an Employee object, defined in a class other than the application model. In this case the data series will require accessor methods defined in the relevant class to return the collections required for charting. (See <Code>
BG_Company</Code>
 for an example of this approach.)</Body1>
<Body1>
<A ID="pgfId-954783"></A>
In either case, you must specify the data series for the chart. </Body1>
<StepStart>
<A ID="pgfId-954784"></A>
Add a Chart widget to a canvas.</StepStart>
<StepCont>
<A ID="pgfId-954785"></A>
On the <UI-Label>
Basics</UI-Label>
 property page for the chart, specify the <UI-Label>
Aspect</UI-Label>
 for the Chart.</StepCont>
<StepCont>
<A ID="pgfId-954787"></A>
<A ID="23026"></A>
On the Data Series page, click <UI-Label>
New</UI-Label>
 to add a new data series, and</StepCont>
<Bullet1>
<A ID="pgfId-954788"></A>
In the <UI-Entry>
Name</UI-Entry>
 field, enter a descriptive name for the first set.</Bullet1>
<Bullet1>
<A ID="pgfId-954789"></A>
In the <UI-Label>
Aspect</UI-Label>
 field, enter either the accessor method for the items making up this data series, or the index of this item in the subcollection. </Bullet1>
<StepCont>
<A ID="pgfId-954792"></A>
Repeat step <A href="09-widgets.xml#id(23026)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">3</A> for each additional data series.</StepCont>
<StepCont>
<A ID="pgfId-954794"></A>
<UI-Label>
Apply</UI-Label>
 your changes.</StepCont>
<StepCont>
<A ID="pgfId-954795"></A>
Using a source browser, ensure that the chart widget&#39;s aspect instance variable is initialized to the collection, and that its accessor method returns the collection as a value holder. </StepCont>
<Heading3>
<A ID="pgfId-954797"></A>
Adding Labels<A ID="marker-954796"></A>
</Heading3>
<Body1>
<A ID="pgfId-954798"></A>
You add labels to your chart by including the label strings as another data series. </Body1>
<Body1>
<A ID="pgfId-954799"></A>
To add labels:</Body1>
<StepStart>
<A ID="pgfId-954801"></A>
On the <UI-Label>
Data Series</UI-Label>
 property page, add a new data series with an appropriate name. For the <UI-Label>
Aspect</UI-Label>
, enter the index for the labels in the collection, or the name of the accessor method that returns the label from the collection members. </StepStart>
<StepCont>
<A ID="pgfId-954802"></A>
<UI-Label>
Apply</UI-Label>
 your changes.</StepCont>
<StepCont>
<A ID="pgfId-954803"></A>
Edit the application code as necessary to include the label in the collection stored in the chart widget&#39;s aspect instance variable.</StepCont>
<Heading3>
<A ID="pgfId-954804"></A>
Special Requirements for Charts</Heading3>
<Body1>
<A ID="pgfId-954805"></A>
Most of the charts are configured as described in the preceding sections. A few charts have special requirements for formatting their data, and are described here.</Body1>
<Heading4>
<A ID="pgfId-954811"></A>
<A ID="14725"></A>
Pareto<A ID="marker-954807"></A>
</Heading4>
<Body1>
<A ID="pgfId-954812"></A>
A Pareto chart consists of a bar chart in descending order of item magnitude, with the overlay graph of cumulative percentages. Used with multiple data series, it is useful for pinpointing the data series that accounts for the greatest number.</Body1>
<Body1>
<A ID="pgfId-954813"></A>
The Pareto chart can take either a single or multiple data series, as described previously.</Body1>
<Body1>
<A ID="pgfId-954814"></A>
A Pareto chart does not accept labels.</Body1>
<Heading4>
<A ID="pgfId-954820"></A>
<A ID="89757"></A>
Picture<A ID="marker-954816"></A>
</Heading4>
<Body1>
<A ID="pgfId-954821"></A>
A picture chart represents the unit of a numeric item with a meaningful picture or symbol. A picture chart can represent only a single data series, but may include the labels:<A ID="marker-954822"></A>
</Body1>
<Code1-Last-Only>
<A ID="pgfId-954823"></A>
#(#(60 &#39;Jan&#39;) #(20 &#39;Feb&#39;) #(35 &#39;Mar&#39;) #(75 &#39;Apr&#39;))</Code1-Last-Only>
<Body1>
<A ID="pgfId-954824"></A>
For the labels to display, define two data series, and check the <UI-Label>
Label</UI-Label>
 checkbox for the series holding the labels.</Body1>
<Body1>
<A ID="pgfId-954825"></A>
To replace the default picture, enter the name of the graphic into the <UI-Label>
Aspect</UI-Label>
 field on the <UI-Label>
Picture</UI-Label>
 section on the <UI-Label>
Options</UI-Label>
 property page.</Body1>
<Body1>
<A ID="pgfId-954826"></A>
By default, the picture represents a unit of 20. To change the unit amount, enter the desired amount in the <UI-Label>
Unit</UI-Label>
 field under the <UI-Label>
Picture</UI-Label>
 section of the Options Properties.</Body1>
<Heading4>
<A ID="pgfId-954832"></A>
<A ID="17669"></A>
XY<A ID="marker-954828"></A>
</Heading4>
<Body1>
<A ID="pgfId-954833"></A>
An XY chart indicates any correlations between two characteristics derived from the scattering status of points plotted in the chart.</Body1>
<Body1>
<A ID="pgfId-954835"></A>
<A ID="marker-954834"></A>
The XY chart expects points as its data. For example, an XY chart with two data series could be set up as follows:</Body1>
<CodeSample>
<A ID="pgfId-954836"></A>
dataPointXY</CodeSample>
<CodeSample>
<A ID="pgfId-954837"></A>
	</CodeSample>
<CodeSample>
<A ID="pgfId-954838"></A>
	| array1 array2 array3|</CodeSample>
<CodeSample>
<A ID="pgfId-954839"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-954840"></A>
	array1 := Array with: 20@60 with: 20@40.</CodeSample>
<CodeSample>
<A ID="pgfId-954841"></A>
	array2 := Array with: 40@40 with: 40@10.</CodeSample>
<CodeSample>
<A ID="pgfId-954842"></A>
	array3 := Array with: 60@75 with: 60@35.</CodeSample>
<CodeSample>
<A ID="pgfId-954843"></A>
</CodeSample>
<Code1-Last-Only>
<A ID="pgfId-954844"></A>
	^(Array with: array1 with: array2 with: array3) asValue</Code1-Last-Only>
<Heading4>
<A ID="pgfId-954849"></A>
Pie Charts<A ID="marker-954845"></A>
</Heading4>
<Body1>
<A ID="pgfId-954850"></A>
A pie chart can only represent one data series, but may include labels:</Body1>
<Code1-Last-Only>
<A ID="pgfId-954851"></A>
#(#(25 &#39;Jan&#39;) #(15 &#39;Feb&#39;) #(40 &#39;Mar&#39;) #(20 &#39;Apr&#39;))</Code1-Last-Only>
<Heading4>
<A ID="pgfId-954853"></A>
Exploding Labels<A ID="marker-954852"></A>
</Heading4>
<Body1>
<A ID="pgfId-954854"></A>
In a pie chart, a slice can be designated to be exploded. For example, enter <UI-Entry>
Jan</UI-Entry>
 in the <UI-Label>
Labels to Explode</UI-Label>
 field on the Options page. Only one label can be exploded at a time.</Body1>
<Heading4>
<A ID="pgfId-954856"></A>
Doughnut Labels<A ID="marker-954855"></A>
</Heading4>
<Body1>
<A ID="pgfId-954857"></A>
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 <UI-Label>
Doughnut Label</UI-Label>
 field on the Options page. </Body1>
<Heading-Anchor>
<A ID="pgfId-946478"></A>
</Heading-Anchor>
<Heading2>
<A ID="pgfId-1040890"></A>
Tables</Heading2>
<Heading3>
<A ID="pgfId-1040896"></A>
Add a table</Heading3>
<Body1>
<A ID="pgfId-1040897"></A>
Use a table to display data in a rows-and-columns format.</Body1>
<Body1>
<A ID="pgfId-1040898"></A>
A table uses a <Code>
TableInterface</Code>
 to store its collection of cells, which is stored in an instance variable of the application model.</Body1>
<StepStart>
<A ID="pgfId-1040900"></A>
Use a Palette to add a table widget to the canvas, leaving it selected.</StepStart>
<StepCont>
<A ID="pgfId-1040901"></A>
On the Basics page of the GUI Painter Tool, enter <Code>
tableInterface</Code>
 as the <UI-Label>
Aspect</UI-Label>
. Turn on both horizontal and vertical grid lines.</StepCont>
<StepCont>
<A ID="pgfId-1041127"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040902"></A>
Use the canvas&#39; <UI-Label>
define</UI-Label>
 command to add the instance variables and aspect methods <Code>
sightingsTable</Code>
 and <Code>
tableInterface</Code>
.</StepCont>
<StepCont>
<A ID="pgfId-1040910"></A>
Create an <Code>
initialize</Code>
 method in the application model to give a default value to the <Code>
SelectionInTable</Code>
.</StepCont>
<CodeSample>
<A ID="pgfId-1040911"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1040912"></A>
		| list |</CodeSample>
<CodeSample>
<A ID="pgfId-1040913"></A>
		super initialize.</CodeSample>
<CodeSample>
<A ID="pgfId-1040914"></A>
		&quot;Create a collection of sightings data.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040915"></A>
		list := TwoDList</CodeSample>
<CodeSample>
<A ID="pgfId-1040916"></A>
			on: #(&#39;Vulcans&#39; 188 173 192 &#39;Romulans&#39; 26 26 452) copy</CodeSample>
<CodeSample>
<A ID="pgfId-1040917"></A>
			columns: 4</CodeSample>
<CodeSample>
<A ID="pgfId-1040918"></A>
			rows: 2.</CodeSample>
<CodeSample>
<A ID="pgfId-1040919"></A>
		sightingsTable := SelectionInTable with: list.</CodeSample>
<CodeSample>
<A ID="pgfId-1040920"></A>
		&quot;Create a table interface and load it with the sightings.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040921"></A>
		tableInterface := TableInterface new</CodeSample>
<CodeSample>
<A ID="pgfId-1040922"></A>
			selectionInTable: sightingsTable.</CodeSample>
<Body1>
<A ID="pgfId-1041114"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Table1.pcl" show="embed" actuate="auto">
Table1Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040923"></A>
Control table column widths</Heading3>
<Body1>
<A ID="pgfId-1040924"></A>
By default, all columns have an equal width that expand and shrink according to the window size. </Body1>
<Body1>
<A ID="pgfId-1040925"></A>
To set specific widths for the columns, send a <Code>
columnWidths:</Code>
 message to the table interface, with an array of column widths specified in pixels. </Body1>
<CodeSample>
<A ID="pgfId-1040926"></A>
tableInterface columnWidths: #(100 40).</CodeSample>
<Body1>
<A ID="pgfId-1040927"></A>
In this example, the first two columns are assigned fixed sizes. These widths remain fixed even if the window is expanded.</Body1>
<Heading3>
<A ID="pgfId-1040928"></A>
Select by cell, row, or column</Heading3>
<Body1>
<A ID="pgfId-1040929"></A>
By default, a single cell in the table is highlighted when the user clicks in it. In some applications, it is more appropriate to highlight the entire row or column in which the cell is located. </Body1>
<Body1>
<A ID="pgfId-1040930"></A>
To set the extent of a user selection, select either <UI-Label>
Cell</UI-Label>
, <UI-Label>
Row</UI-Label>
, or <UI-Label>
Column</UI-Label>
 in the <UI-Label>
Selection</UI-Label>
 set on the <UI-Label>
Details</UI-Label>
 page of the GUI Painter Tool.</Body1>
<Heading3>
<A ID="pgfId-1040931"></A>
Connect a table to an input field</Heading3>
<Body1>
<A ID="pgfId-1040932"></A>
To allow the user to change values in a table cell, the entry needs to be input some other way, such as in an input field. The input can then be added to the table.</Body1>
<StepStart>
<A ID="pgfId-1040934"></A>
Add an input field below the table, leaving the field selected.</StepStart>
<StepCont>
<A ID="pgfId-1041193"></A>
 On Basics page of the GUI Painter Tool,  enter <Code>
cellContents</Code>
 as the field&#39;s <UI-Label>
Aspect</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1040937"></A>
Use the canvas&#39; <UI-Label>
define</UI-Label>
 command to add an instance variable named <Code>
cellContents</Code>
 to the <Code>
UFOtable</Code>
 class, and to create a corresponding aspect method (<Code>
cellContents</Code>
).</StepCont>
<CodeSample>
<A ID="pgfId-1040940"></A>
cellContents</CodeSample>
<CodeSample>
<A ID="pgfId-1040941"></A>
		^cellContents</CodeSample>
<StepCont>
<A ID="pgfId-1040943"></A>
Add the instance method <Code>
changedCell</Code>
 in a <Code>
change</Code>
 messages protocol.</StepCont>
<CodeSample>
<A ID="pgfId-1040944"></A>
changedCell</CodeSample>
<CodeSample>
<A ID="pgfId-1040945"></A>
		| cellLocation |</CodeSample>
<CodeSample>
<A ID="pgfId-1040946"></A>
		&quot;Get the coordinates of the highlighted cell.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040947"></A>
		cellLocation := self sightingsTable selectionIndex.</CodeSample>
<CodeSample>
<A ID="pgfId-1040948"></A>
		&quot;If a cell is selected, update its contents from</CodeSample>
<CodeSample>
<A ID="pgfId-1041042"></A>
		the input field.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040949"></A>
		cellLocation = Point zero</CodeSample>
<CodeSample>
<A ID="pgfId-1040950"></A>
			ifFalse: [self sightingsTable table</CodeSample>
<CodeSample>
<A ID="pgfId-1040951"></A>
				at: cellLocation</CodeSample>
<CodeSample>
<A ID="pgfId-1040952"></A>
				put: self cellContents value]</CodeSample>
<StepCont>
<A ID="pgfId-1040954"></A>
In the application model&#39;s <Code>
initialize</Code>
 method, initialize the input field (<Code>
cellContents</Code>
).</StepCont>
<CodeSample>
<A ID="pgfId-1040955"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1040956"></A>
		| list |</CodeSample>
<CodeSample>
<A ID="pgfId-1040957"></A>
		super initialize.</CodeSample>
<CodeSample>
<A ID="pgfId-1040958"></A>
		&quot;Create a collection of sightings data.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040959"></A>
		list := TwoDList</CodeSample>
<CodeSample>
<A ID="pgfId-1040960"></A>
			on: #(&#39;Vulcans&#39; 188 173 192 &#39;Romulans&#39; 26 26 452) copy</CodeSample>
<CodeSample>
<A ID="pgfId-1040961"></A>
			columns: 4</CodeSample>
<CodeSample>
<A ID="pgfId-1040962"></A>
			rows: 2.</CodeSample>
<CodeSample>
<A ID="pgfId-1040963"></A>
		sightingsTable := SelectionInTable with: list.</CodeSample>
<CodeSample>
<A ID="pgfId-1040964"></A>
		&quot;Create a table interface and load it with the sightings.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040965"></A>
		tableInterface := TableInterface new</CodeSample>
<CodeSample>
<A ID="pgfId-1040966"></A>
			selectionInTable: sightingsTable.</CodeSample>
<CodeSample>
<A ID="pgfId-1040967"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040968"></A>
		cellContents := String new asValue.</CodeSample>
<CodeSample>
<A ID="pgfId-1040969"></A>
		self cellContents onChangeSend: #changedCell to: self.</CodeSample>
<StepCont>
<A ID="pgfId-1040970"></A>
To update the table cell, register interest in the table selection with <Code>
onChangeSend:</Code>
 and trigger an update in the input field. </StepCont>
<Body1>
<A ID="pgfId-1041217"></A>
For code sample, see Table2Example.</Body1>
<Body1>
<A ID="pgfId-1041147"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Table2.pcl" show="embed" actuate="auto">
Table2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040972"></A>
Label columns and rows</Heading3>
<Body1>
<A ID="pgfId-1040973"></A>
To assign labels to columns, send an array of labels to the table interface. For row labels, you send an array of labels and specify the width of those labels.</Body1>
<StepStart>
<A ID="pgfId-1040975"></A>
To assign column labels, send a <Code>
columnLabelsArray:</Code>
 message to the table interface with an array of label strings.</StepStart>
<StepCont>
<A ID="pgfId-1040976"></A>
To assign row labels, send a <Code>
rowLabelsArray:</Code>
 message to the table interface with an array of label strings, and a <Code>
rowLabelsWidth:</Code>
 message with a width in pixels.</StepCont>
<CodeSample>
<A ID="pgfId-1040977"></A>
tableInterface</CodeSample>
<CodeSample>
<A ID="pgfId-1040978"></A>
		columnLabelsArray: #(&#39;Visiting Race&#39; &#39;1992&#39; &#39;1993&#39; &#39;1994&#39;);</CodeSample>
<CodeSample>
<A ID="pgfId-1040979"></A>
		rowLabelsArray: #(1 2);</CodeSample>
<CodeSample>
<A ID="pgfId-1040980"></A>
		rowLabelsWidth: 20.</CodeSample>
<Body1>
<A ID="pgfId-1041155"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Table3.pcl" show="embed" actuate="auto">
Table3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040981"></A>
Align table data and labels</Heading3>
<Body1>
<A ID="pgfId-1040982"></A>
By default, all cells contents are left aligned, and all labels are centered. You can align data and labels using one of the following symbols: <Code>
#left</Code>
, <Code>
#right</Code>
, <Code>
#centered</Code>
, or <Code>
#leftWrapped</Code>
. </Body1>
<StepStart>
<A ID="pgfId-1040983"></A>
To set the alignment for column labels, edit the <Code>
initialize</Code>
 method to send a <Code>
columnLabelsFormats:</Code>
 message to the table interface with the format for each column label.</StepStart>
<StepCont>
<A ID="pgfId-1040984"></A>
To set the alignment for column data, send a <Code>
columnFormats:</Code>
 message to the table interface with the format for each column.</StepCont>
<StepCont>
<A ID="pgfId-1040985"></A>
To set the alignment for row labels, send a <Code>
rowLabelsFormat:</Code>
 message to the table interface with the format.</StepCont>
<CodeSample>
<A ID="pgfId-1040986"></A>
tableInterface</CodeSample>
<CodeSample>
<A ID="pgfId-1040987"></A>
		columnFormats: #(#left #right #right #right);</CodeSample>
<CodeSample>
<A ID="pgfId-1040988"></A>
		columnLabelsFormats: #(#left #right #right #right);</CodeSample>
<CodeSample>
<A ID="pgfId-1040989"></A>
		rowLabelsFormat: #right.</CodeSample>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-1040893"></A>
Datasets</Heading2>
<Heading3>
<A ID="pgfId-1040895"></A>
Add a dataset</Heading3>
<Body1>
<A ID="pgfId-1040897"></A>
Use a dataset to present a table of similar objects for a user to edit. Datasets allow data to be edited directly. </Body1>
<Body1>
<A ID="pgfId-1040898"></A>
A dataset uses a <Code>
SelectionInList</Code>
 to hold the list of objects to be displayed, along with information about the current selection.</Body1>
<Body1>
<A ID="pgfId-1040899"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dataset1.pcl" show="embed" actuate="auto">
Dataset1Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041095"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041099"></A>
&#34;Datasets&#34; in the <I>
VisualWorks GUI Developer&#39;s Guide</I>
 </Bullet1>
<Heading3>
<A ID="pgfId-1040931"></A>
Change column widths</Heading3>
<Body1>
<A ID="pgfId-1040932"></A>
By default, all columns have a width of 80 pixels. You can set specific widths in the dataset&#39;s <UI-Label>
Column</UI-Label>
 properties. </Body1>
<Body1>
<A ID="pgfId-1040933"></A>
You can also change the column widths by editing the dataset in the canvas: </Body1>
<StepStart>
<A ID="pgfId-1040934"></A>
In the canvas, &lt;Control&gt;-click a column to select it.</StepStart>
<StepCont>
<A ID="pgfId-1040935"></A>
Place the cursor near the right margin of the column.</StepCont>
<StepCont>
<A ID="pgfId-1040936"></A>
&lt;Control&gt;-click and hold down the mouse button. If necessary, move the pointer toward the right margin of the selected column until the cursor changes appearance. </StepCont>
<StepCont>
<A ID="pgfId-1040937"></A>
Drag the cursor to the right to widen the column; drag the cursor to the left to make the column narrower. </StepCont>
<StepCont>
<A ID="pgfId-1040938"></A>
<UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1040939"></A>
Change column order</Heading3>
<Body1>
<A ID="pgfId-1040940"></A>
You can switch the order of a dataset&#39;s columns by editing it in the canvas. </Body1>
<StepStart>
<A ID="pgfId-1040941"></A>
In the canvas, &lt;Control&gt;-click a column to select it.</StepStart>
<StepCont>
<A ID="pgfId-1040942"></A>
Place the cursor on the drag handle within the selected column.</StepCont>
<StepCont>
<A ID="pgfId-1040943"></A>
Click on the handle and drag it to its new position. </StepCont>
<StepCont>
<A ID="pgfId-1040944"></A>
<UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1040945"></A>
Disable column scrolling</Heading3>
<Body1>
<A ID="pgfId-1040946"></A>
You can set a dataset&#39;s columns so that they cannot be scrolled horizontally.</Body1>
<Body1>
<A ID="pgfId-1041106"></A>
This is useful if you want to keep one or more columns displayed on the dataset at all times, while the others continue to scroll. </Body1>
<StepStart>
<A ID="pgfId-1040947"></A>
Select that column.</StepStart>
<StepCont>
<A ID="pgfId-1040948"></A>
In the GUI Painter Tool, click the <UI-Label>
Fixed</UI-Label>
 check box on the <UI-Label>
Column</UI-Label>
 page.</StepCont>
<StepCont>
<A ID="pgfId-1040949"></A>
<UI-Label>
Apply</UI-Label>
 the change and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Heading3>
<A ID="pgfId-1040951"></A>
Select a column while painting</Heading3>
<StepStart>
<A ID="pgfId-1040952"></A>
Select the dataset on the canvas.</StepStart>
<StepCont>
<A ID="pgfId-1040953"></A>
Place the cursor inside one of the columns of the dataset.</StepCont>
<StepCont>
<A ID="pgfId-1040954"></A>
Hold down the &lt;Control&gt; key while clicking the &lt;Select&gt; mouse button.</StepCont>
<Heading3>
<A ID="pgfId-1040955"></A>
Move the selection to another column</Heading3>
<StepStart>
<A ID="pgfId-1040956"></A>
Select a column in the dataset.</StepStart>
<StepCont>
<A ID="pgfId-1040957"></A>
Click the &lt;Select&gt; mouse button for subsequent column selections. </StepCont>
<Heading3>
<A ID="pgfId-1040958"></A>
Scroll dataset columns</Heading3>
<StepStart>
<A ID="pgfId-1040959"></A>
Select a column in the dataset.</StepStart>
<StepCont>
<A ID="pgfId-1040960"></A>
Press &lt;Control&gt; while using the mouse to move the scroll bars on the dataset.</StepCont>
<Heading3>
<A ID="pgfId-1040961"></A>
Add rows programmatically</Heading3>
<Body1>
<A ID="pgfId-1040962"></A>
You can add rows to the dataset programmatically. This is necessary when the size of a dataset cannot be determined prior to runtime.</Body1>
<StepStart>
<A ID="pgfId-1040964"></A>
Use the Palette to add an action button to a canvas containing a dataset. Leave the button selected.</StepStart>
<StepCont>
<A ID="pgfId-1040965"></A>
In the GUI Painter Tool, enter <Code>
Add Row</Code>
 as the button&#39;s <UI-Label>
Label</UI-Label>
 property and <Code>
addRow</Code>
 as the button&#39;s <UI-Label>
Action</UI-Label>
 property. <UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<StepCont>
<A ID="pgfId-1040967"></A>
Using the <UI-Label>
define</UI-Label>
 command or a System Browser, add the instance method <Code>
addRow</Code>
 in the <Code>
actions</Code>
 protocol. This method adds a new object to the list displayed by the dataset. This, in turn, adds a new row to the dataset.</StepCont>
<CodeSample>
<A ID="pgfId-1040968"></A>
addRow</CodeSample>
<CodeSample>
<A ID="pgfId-1040969"></A>
		(dsvList list) add: Employee new</CodeSample>
<Body1>
<A ID="pgfId-1041110"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dataset2.pcl" show="embed" actuate="auto">
Dataset2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040970"></A>
Add a row marker</Heading3>
<Body1>
<A ID="pgfId-1040971"></A>
A row marker indicates which row is selected within a dataset. It is used in place of row highlighting.</Body1>
<Body1>
<A ID="pgfId-1041113"></A>
To add a row marker, select <UI-Label>
Row Selector</UI-Label>
 on the dataset&#39;s <UI-Label>
Details</UI-Label>
 properties. The marker appears as the first column within the dataset.</Body1>
<Heading3>
<A ID="pgfId-1040973"></A>
Connect data to a dataset</Heading3>
<Body1>
<A ID="pgfId-1040974"></A>
Your application can arrange for a dataset to display data initially.</Body1>
<Body1>
<A ID="pgfId-1040976"></A>
In the application model, create an <Code>
initialize</Code>
 method that provides the data for your dataset.</Body1>
<CodeSample>
<A ID="pgfId-1040977"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1040978"></A>
		| aList anEmp |</CodeSample>
<CodeSample>
<A ID="pgfId-1040979"></A>
		aList := List new.</CodeSample>
<CodeSample>
<A ID="pgfId-1040980"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040981"></A>
		&quot;The aspect for the dataset should be a list of Employee instances.</CodeSample>
<CodeSample>
<A ID="pgfId-1040982"></A>
		Create an employee to put in the list.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040983"></A>
		anEmp := Employee new initialize.</CodeSample>
<CodeSample>
<A ID="pgfId-1040984"></A>
		anEmp name: &#39;Tami Hayes&#39;; empNo: &#39;341-2&#39;; citizen: true.</CodeSample>
<CodeSample>
<A ID="pgfId-1040985"></A>
		aList add: anEmp.</CodeSample>
<CodeSample>
<A ID="pgfId-1040986"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040987"></A>
		&quot;Create an employee to put in the list.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040988"></A>
		anEmp := Employee new initialize.</CodeSample>
<CodeSample>
<A ID="pgfId-1040989"></A>
		anEmp name: &#39;Leo Mazon&#39;; empNo: &#39;786-9&#39;; citizen: false.</CodeSample>
<CodeSample>
<A ID="pgfId-1040990"></A>
		aList add: anEmp.</CodeSample>
<CodeSample>
<A ID="pgfId-1040991"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040992"></A>
		&quot;Set the list for the dataset aspect. This list appears when you start.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040993"></A>
		self dsvList list: aList.</CodeSample>
<CodeSample>
<A ID="pgfId-1040994"></A>
		super initialize.</CodeSample>
<Body1>
<A ID="pgfId-1041123"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dataset3.pcl" show="embed" actuate="auto">
Dataset3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040995"></A>
Enhance column labels</Heading3>
<Body1>
<A ID="pgfId-1040996"></A>
The standard <UI-Label>
Label</UI-Label>
 property supports a one line string. For multiple-line or formatted labels, you can use composed text.</Body1>
<StepStart>
<A ID="pgfId-1040998"></A>
Create a class method in a <Code>
resources</Code>
 protocol of the application model that returns a <Code>
ComposedText</Code>
 object. Apply appropriate formatting to the object.</StepStart>
<CodeSample>
<A ID="pgfId-1040999"></A>
number</CodeSample>
<CodeSample>
<A ID="pgfId-1041000"></A>
		^(&#39;Employee</CodeSample>
<CodeSample>
<A ID="pgfId-1041001"></A>
Number&#39; asText allBold) asComposedText</CodeSample>
<StepCont>
<A ID="pgfId-1041002"></A>
In the canvas, select the column to be labelled.</StepCont>
<StepCont>
<A ID="pgfId-1041003"></A>
In the GUI Painter Tool, enter the <Code>
label</Code>
 method in the <UI-Label>
Label</UI-Label>
 field on the <UI-Label>
Column</UI-Label>
 page.</StepCont>
<StepCont>
<A ID="pgfId-1041004"></A>
Select the <UI-Label>
Image</UI-Label>
 check box next to <UI-Label>
Label</UI-Label>
. </StepCont>
<StepCont>
<A ID="pgfId-1041005"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1041129"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dataset4.pcl" show="embed" actuate="auto">
Dataset4Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
<Heading2>
<A ID="pgfId-1040336"></A>
Dialogs</Heading2>
<Heading3>
<A ID="pgfId-1040337"></A>
Display a warning</Heading3>
<Body1>
<A ID="pgfId-1040342"></A>
Send a <Code>
warn:</Code>
 message to the <Code>
Dialog</Code>
 class, with a string specifying the message.</Body1>
<Body1>
<A ID="pgfId-1040937"></A>
When the user clicks <UI-Label>
OK</UI-Label>
, the message returns the value <Code>
nil</Code>
. Backslash characters in the string are converted to carriage returns by the <Code>
withCRs</Code>
 message.</Body1>
<CodeSample>
<A ID="pgfId-1040343"></A>
warn
		| returnVal |
		returnVal := <CodeEmp>
Dialog</CodeEmp>
 
			warn: &#39;The memory named\&#39;&#39;FirstKiss&#39;&#39;\was not found.\&#39;
				withCRs.

		&quot;Update the text field in the main window.&quot;
		self returnedValue value: returnVal printString.</CodeSample>
<Body1>
<A ID="pgfId-1040720"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dialog.pcl" show="embed" actuate="auto">
DialogExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040351"></A>
Prompt for a Yes/No answer</Heading3>
<StepStart>
<A ID="pgfId-1040354"></A>
Send a <Code>
confirm:</Code>
 message to the <Code>
Dialog</Code>
 class. The argument is the question to be asked.</StepStart>
<CodeSample>
<A ID="pgfId-1040355"></A>
Dialog <CodeEmp>
confirm: &#39;Really erase all memories\of adolescent
			period?\&#39;</CodeEmp>
 withCRs.</CodeSample>
<StepCont>
<A ID="pgfId-1040357"></A>
To specify a different default answer, send a <Code>
confirm:initialAnswer:</Code>
 message to <Code>
Dialog</Code>
 instead, with the as either true or false.</StepCont>
<CodeSample>
<A ID="pgfId-1040358"></A>
Dialog 
		confirm: &#39;Really erase all memories\of adolescent period?&#39;
			withCRs
		initialAnswer: false</CodeSample>
<StepCont>
<A ID="pgfId-1040362"></A>
To adopt the look of a master window, send a <Code>
confirm:initialAnswer:for:</Code>
 message, with the master window as the third argument:</StepCont>
<CodeSample>
<A ID="pgfId-1040363"></A>
		returnVal := Dialog 
			confirm: &#39;Really erase all memories\of adolescent period?&#39;
				withCRs
			initialAnswer: false
			<CodeEmp>
for: ScheduledControllers activeController view</CodeEmp>
.</CodeSample>
<Heading3>
<A ID="pgfId-1040368"></A>
Ask a multiple-choice question</Heading3>
<Body1>
<A ID="pgfId-1040370"></A>
Send a <Code>
choose:labels:values:default:</Code>
 message to the <Code>
Dialog</Code>
 class. The <Code>
choose:</Code>
 argument is the question, the <Code>
labels:</Code>
 argument is an array of <Code>
String</Code>
s for the button labels, the <Code>
values:</Code>
 argument is an array of <Code>
Symbol</Code>
s to return values for each buttons, and the <Code>
default:</Code>
 argument is the <Code>
Symbol</Code>
 for the default answer.</Body1>
<CodeSample>
<A ID="pgfId-1040371"></A>
Dialog
		choose: &#39;Which memory would you like to review first?&#39;
		labels: #( &#39;Swimming the Channel&#39; &#39;Triumph at the Coliseum&#39; 
			&#39;Love &amp; War #47&#39;)
		values: #(#swim #triumph #love47)
		default: #triumph</CodeSample>
<Body1>
<A ID="pgfId-1040377"></A>
To adopt the look of a master window, send a <Code>
choose:labels:values:default:for:</Code>
 message instead, with the master window as the <Code>
for:</Code>
 argument.</Body1>
<CodeSample>
<A ID="pgfId-1040378"></A>
		returnVal := Dialog
			choose: &#39;Which memory would you like to review first?&#39;
			labels: #( &#39;Swimming the Channel&#39; 
				&#39;Triumph at the Coliseum&#39; 
				&#39;Love &amp; War #47&#39;)
			values: #(#swim #triumph #love47)
			default: #triumph
			<CodeEmp>
for: ScheduledControllers activeController view</CodeEmp>
.</CodeSample>
<Heading3>
<A ID="pgfId-1040386"></A>
Prompt for a textual response</Heading3>
<Body1>
<A ID="pgfId-1040388"></A>
Send a <Code>
request:initialAnswer:</Code>
 message to <Code>
Dialog</Code>
, with a prompt string and a default answer string.</Body1>
<CodeSample>
<A ID="pgfId-1040389"></A>
Dialog
		request: &#39;Find all memories associated with...&#39; 
		initialAnswer: &#39;friend&#39;</CodeSample>
<Body1>
<A ID="pgfId-1040392"></A>
If there is no default answer, you can use the shorter <Code>
request:</Code>
, and provide the question string only.</Body1>
<Heading3>
<A ID="pgfId-1040393"></A>
Supply a cancel action</Heading3>
<Body1>
<A ID="pgfId-1040394"></A>
A text prompter, by default, returns an empty string when the user clicks <UI-Label>
Cancel</UI-Label>
. To provide a specific action on cancel, use the <Code>
request:initialAnswer:cancel:</Code>
 message. The argument for <Code>
cancel:</Code>
 is a block that returns a value or initiates some further action.</Body1>
<CodeSample>
<A ID="pgfId-1040396"></A>
getText
		| returnVal |
		returnVal := Dialog
			request: &#39;Find all memories associated with...&#39; 
			initialAnswer: &#39;friend&#39; 
			onCancel: [self defaultRuminationTopic].</CodeSample>
<Body1>
<A ID="pgfId-1040738"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dialog.pcl" show="embed" actuate="auto">
DialogExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040402"></A>
Prompt for a file name</Heading3>
<Body1>
<A ID="pgfId-1040404"></A>
Send a <Code>
requestFileName:default:</Code>
 message to <Code>
Dialog</Code>
, with a prompter string and the name of the default file as a string.</Body1>
<CodeSample>
<A ID="pgfId-1040405"></A>
Dialog 
		requestFileName: &#39;Open memory file named...&#39; 
		<CodeEmp>
default: &#39;hero01.mem&#39;</CodeEmp>
</CodeSample>
<Body1>
<A ID="pgfId-1040408"></A>
If a default file name isn&#39;t needed, use the shorter <Code>
requestFileName:</Code>
 message.</Body1>
<Heading3>
<A ID="pgfId-1040409"></A>
Check whether a file exists</Heading3>
<Body1>
<A ID="pgfId-1040410"></A>
The a <Code>
requestFileName:default:version:</Code>
 message to <Code>
Dialog</Code>
 supports various test symbols for the third argument to check the file existence status: </Body1>
<Bullet1>
<A ID="pgfId-1040411"></A>
<Code>
#new</Code>
 indicates that you expect the file to be new</Bullet1>
<Bullet1>
<A ID="pgfId-1040412"></A>
<Code>
#old</Code>
 indicates that you expect the file to exist</Bullet1>
<Bullet1>
<A ID="pgfId-1040413"></A>
<Code>
#mustBeNew</Code>
 cancels if the file exists</Bullet1>
<Bullet1>
<A ID="pgfId-1040414"></A>
<Code>
#mustBeOld</Code>
 cancels if the file does not exist</Bullet1>
<CodeSample>
<A ID="pgfId-1040415"></A>
Dialog 
			requestFileName: &#39;Open memory file named...&#39; 
			default: &#39;hero01.mem&#39; 
			version: #new</CodeSample>
<Body1>
<A ID="pgfId-1040419"></A>
To supply a specific cancellation action, use the longer <Code>
requestFileName:default:version:ifFail:</Code>
 message, with a block containing the action.</Body1>
<CodeSample>
<A ID="pgfId-1040420"></A>
getFilename
		| returnVal |
		returnVal := Dialog 
			requestFileName: &#39;Open memory file named...&#39; 
			default: &#39;hero01.mem&#39; 
			version: #mustBeOld 
			ifFail: [Transcript show: &#39;Memory file access canceled&#39;. &#39;&#39;].															
		&quot;Update the text field in the main window.&quot;
		self returnedValue value: returnVal printString.</CodeSample>
<Heading3>
<A ID="pgfId-1040637"></A>
Prompt with a list of items</Heading3>
<Body1>
<A ID="pgfId-1040638"></A>
To display a dialog with a list of commands or data values, send a <Code>
choose:fromList:values:lines:cancel:</Code>
 message to <Code>
Dialog</Code>
. The <Code>
choose:</Code>
 argument contains the prompt string; the <Code>
fromList:</Code>
 argument contains a collection of strings (command names or value descriptions); the <Code>
values:</Code>
 argument, a collection of values associated with the <Code>
fromList:</Code>
 items; <Code>
lines:</Code>
 contains the maximum number of list items to display; and <Code>
cancel:</Code>
 passes a block containing the cancel action.</Body1>
<Body1>
<A ID="pgfId-1040643"></A>
Each item in the list is associated with a value which can insert the selected value in a value holder or trigger an action.</Body1>
<CodeSample>
<A ID="pgfId-1040437"></A>
| files response |
files := Filename defaultDirectory directoryContents
		reject: [ :name | name asFilename isDirectory].

response := Dialog
		choose: &#39;Edit which file?&#39;
		fromList: files
		values: files
		lines: 8
		cancel: [^nil].

response asFilename edit.</CodeSample>
<Body1>
<A ID="pgfId-1040449"></A>
To Supply extra buttons to the list prompter, send a <Code>
choose:fromList:values:buttons:values:lines:cancel:</Code>
 message instead, where the <Code>
buttons:</Code>
 argument is a collection of strings to be used as button labels and the <Code>
values:</Code>
 argument is a collection of values to associate with the button labels.</Body1>
<CodeSample>
<A ID="pgfId-1040450"></A>
response := Dialog
		choose: &#39;Edit which file?&#39;
		fromList: files
		values: files
		buttons: #(&#39;Count Files&#39;)
		values: #(#count)
		lines: 12
		cancel: [^nil].</CodeSample>
<Heading3>
<A ID="pgfId-1040458"></A>
Link a dialog to a master window</Heading3>
<Body1>
<A ID="pgfId-1040459"></A>
To open dialogs that mimic the colors and UI Look of a master window, use the instance opening protocol including a for: argument ( e.g., <Code>
warn:for:</Code>
) to specify the UI Look.</Body1>
<Body1>
<A ID="pgfId-1040461"></A>
To change the colors used, send a <Code>
useColorOveridesFromParent: true</Code>
 message to <Code>
SimpleDialog</Code>
.</Body1>
<StepStart>
<A ID="pgfId-1040463"></A>
Send a <Code>
useColorOveridesFromParent: true</Code>
 message to the <Code>
SimpleDialog</Code>
 class. Subsequently opened dialogs will adopt the colors of their master window. </StepStart>
<StepCont>
<A ID="pgfId-1040465"></A>
Send a <Code>
warn:for:</Code>
 message to the <Code>
Dialog</Code>
 class. The first argument is the message string, and the second argument is the master window.</StepCont>
<CodeSample>
<A ID="pgfId-1040466"></A>
| masterWindow |
	SimpleDialog useColorOveridesFromParent: true.
	masterWindow := ScheduledWindow new.
	masterWindow background: ColorValue yellow.
	masterWindow open.

	Dialog
		warn: &#39;This dialog has a yellow background, too.&#39; 
		for: masterWindow.

masterWindow sensor eventQuit: nil.</CodeSample>
<Body1>
<A ID="pgfId-1040477"></A>
To reset the <Code>
SimpleDialog</Code>
 class to its default behavior, send it the <Code>
useColorOveridesFromParent: false</Code>
 message with the argument .</Body1>
<Heading3>
<A ID="pgfId-1040478"></A>
Create a custom dialog</Heading3>
<Body1>
<A ID="pgfId-1040692"></A>
Create a subclass of <Code>
SimpleDialog</Code>
, reusing its protocol for <Code>
#accept </Code>
or <Code>
#cancel</Code>
. In the method that is to open the dialog, send an <Code>
openDialogInterface:</Code>
 message to the application model. The argument is the dialog&#39;s interface specification.</Body1>
<CodeSample>
<A ID="pgfId-1040482"></A>
openDialogCanvas
		| returnVal |
		returnVal := self openDialogInterface: #memoryZonesDialog.
		&quot;Update the text field in the main window.&quot;
		self returnedValue value: returnVal printString.</CodeSample>
<Body1>
<A ID="pgfId-1040874"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dialog.pcl" show="embed" actuate="auto">
DialogExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040487"></A>
Request actions for OK and Cancel buttons</Heading3>
<Body1>
<A ID="pgfId-1040489"></A>
When a custom dialog has <UI-Label>
OK</UI-Label>
 and <UI-Label>
Cancel</UI-Label>
 buttons, you can arrange for them to invoke predefined methods that close the dialog and return the appropriate value (<Code>
true</Code>
 or <Code>
false</Code>
). </Body1>
<StepStart>
<A ID="pgfId-1040490"></A>
In the canvas for the dialog, select the action button that is to accept the dialog (typically labeled <UI-Label>
OK</UI-Label>
).</StepStart>
<StepCont>
<A ID="pgfId-1040491"></A>
In the GUI Painter Tool, enter <Code>
accept</Code>
 in the button&#39;s <UI-Label>
Action</UI-Label>
 property. </StepCont>
<StepCont>
<A ID="pgfId-1040492"></A>
In the canvas, select the button that is to cancel the dialog (typically labeled <UI-Label>
Cancel</UI-Label>
).</StepCont>
<StepCont>
<A ID="pgfId-1040493"></A>
In the GUI Painter Tool, enter <Code>
cancel</Code>
 in the button&#39;s <UI-Label>
Action</UI-Label>
 property.</StepCont>
<StepCont>
<A ID="pgfId-1040494"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the canvas.</StepCont>
<Body1>
<A ID="pgfId-1040891"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dialog.pcl" show="embed" actuate="auto">
DialogExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040495"></A>
Store a dialog builder for reference</Heading3>
<StepStart>
<A ID="pgfId-1040498"></A>
In the method that is to open the dialog, create an instance of <Code>
SimpleDialog</Code>
.</StepStart>
<StepCont>
<A ID="pgfId-1040500"></A>
Get the builder from the <Code>
SimpleDialog</Code>
 and store it, typically in an instance variable of the application model (<Code>
dialogBuilder</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040502"></A>
Send an <Code>
openFor:interface:</Code>
 message to the <Code>
SimpleDialog</Code>
. The first argument is the application model so that the dialog&#39;s widgets can obtain their value models, actions, and resources from it. The second argument is the name of the dialog&#39;s interface specification.</StepCont>
<CodeSample>
<A ID="pgfId-1040503"></A>
openDialogStoreBuilder
		| returnVal dialogModel |
		dialogModel := SimpleDialog new.
		self dialogBuilder: dialogModel builder.

		returnVal := dialogModel 
			openFor: self 
			interface: #memoryZonesDialog.

		&quot;Update the text field in the main window.&quot;
		self returnedValue value: returnVal printString.</CodeSample>
<Body1>
<A ID="pgfId-1040897"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dialog.pcl" show="embed" actuate="auto">
DialogExample</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040514"></A>
Provide a temporary model for a dialog</Heading3>
<StepStart>
<A ID="pgfId-1040517"></A>
In the method that is to open the dialog, create an instance of <Code>
SimpleDialog</Code>
.</StepStart>
<StepCont>
<A ID="pgfId-1040519"></A>
Get the builder from the <Code>
SimpleModel</Code>
 and preload it with one binding for each active widget. The <Code>
aspectAt:</Code>
 argument is the symbol you specified in the widget&#39;s <UI-Label>
Aspect</UI-Label>
 property. The <Code>
put:</Code>
 argument is an appropriate value model.</StepCont>
<StepCont>
<A ID="pgfId-1040521"></A>
Ask the <Code>
SimpleDialog</Code>
 to open the interface.</StepCont>
<CodeSample>
<A ID="pgfId-1040522"></A>
openTempModelDialog
		| returnVal dialogModel list |
		dialogModel := SimpleDialog new.
		dialogBuilder := dialogModel builder.

		&quot;Since the simple model does not respond to a #memoryZones message,
		its builder must be preloaded with a multilist.&quot;
		list := MultiSelectionInList new 
			list: self memoryZones list copy.
		dialogBuilder aspectAt: #memoryZones put: list.

		&quot;Open the interface.&quot;
		returnVal := dialogModel 
			openFor: self 
			interface: #memoryZonesDialog.
		&quot;Update the text field in the main window.&quot;
		self returnedValue value: returnVal printString.</CodeSample>
<Body1>
<A ID="pgfId-1040915"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Dialog.pcl" show="embed" actuate="auto">
DialogExample</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1040057"></A>
</Body1>
<Heading2>
<A ID="pgfId-1040896"></A>
Subcanvases</Heading2>
<Heading3>
<A ID="pgfId-1040898"></A>
Inherit an application&#39;s interface</Heading3>
<Body1>
<A ID="pgfId-1041120"></A>
You can include an entire application within a new application by making the new application a subclass of the original.</Body1>
<Body1>
<A ID="pgfId-1041123"></A>
To include its user interface, the new application inserts the old user interface into a subcanvas. The new application can override an inherited action, though it need not.</Body1>
<StepStart>
<A ID="pgfId-1040902"></A>
Create a new application model (<Code>
Subcanvas1Example</Code>
) as a subclass of the application model from which it is to inherit (<Code>
List2Example</Code>
).</StepStart>
<StepCont>
<A ID="pgfId-1040903"></A>
Use a Palette to place a subcanvas widget on the inheriting canvas (the canvas for <Code>
Subcanvas1Example</Code>
). Leave the subcanvas widget selected.</StepCont>
<StepCont>
<A ID="pgfId-1040904"></A>
In the subcanvas&#39;s <Code>
Canvas</Code>
 property, enter the name of the inherited interface specification to be used by the subcanvas (<Code>
listSpec</Code>
). This name must be unique within the inheritance chain--for example, you could not embed an inherited canvas named <Code>
windowSpec</Code>
 in a local canvas named <Code>
windowSpec</Code>
.</StepCont>
<StepCont>
<A ID="pgfId-1040905"></A>
Apply the property and <UI-Label>
Install</UI-Label>
 the inheriting canvas in its application model (<Code>
Subcanvas1Example</Code>
).</StepCont>
<Body1>
<A ID="pgfId-1041129"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="List2.pcl" show="embed" actuate="auto">
List2Example</CodeExample>
 (parent) and <CodeExample xml:link="simple" href="Subcan1.pcl" show="embed" actuate="auto">
Subcanvas1Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1041151"></A>
<B>
See also:</B>
</Body1>
<Bullet1>
<A ID="pgfId-1041152"></A>
&#34;Subcanvas&#34; in the <I>
VisualWorks GUI Developer&#39;s Guide</I>
 </Bullet1>
<Heading3>
<A ID="pgfId-1040906"></A>
Installing a different value in an inherited widget</Heading3>
<Body1>
<A ID="pgfId-1040907"></A>
You can reuse widgets by providing a local value in a subclass.</Body1>
<StepStart>
<A ID="pgfId-1040910"></A>
Create an <Code>
initialize</Code>
 method in the application model, and first invoke the inherited <Code>
initialize</Code>
 method with a message to super.</StepStart>
<StepCont>
<A ID="pgfId-1040912"></A>
In the <Code>
initialize</Code>
 method, use the inherited aspect message to access the desired <A href="10-glossary.xml#id(value model)" xml:link="simple" show="replace" actuate="user" CLASS="XRef">value model</A>. Then send an accessing message to the value model to install the desired value.</StepCont>
<CodeSample>
<A ID="pgfId-1040913"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1040914"></A>
		&quot;Install a different list (cursor names) than </CodeSample>
<CodeSample>
<A ID="pgfId-1040915"></A>
		the inherited default (color names).&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040916"></A>
		| cursorNames |</CodeSample>
<CodeSample>
<A ID="pgfId-1040917"></A>
		super initialize.</CodeSample>
<CodeSample>
<A ID="pgfId-1040918"></A>
		cursorNames := Cursor class organization </CodeSample>
<CodeSample>
<A ID="pgfId-1040919"></A>
			listAtCategoryNamed: #constants.</CodeSample>
<CodeSample>
<A ID="pgfId-1040920"></A>
		self selectionInList list: cursorNames.</CodeSample>
<Heading3>
<A ID="pgfId-1040921"></A>
Nest one application in another</Heading3>
<Body1>
<A ID="pgfId-1040922"></A>
Using a subcanvas, you can embed one application in another even though they are not related by inheritance. This is a convenient way to create a set of application modules to plug into a larger. </Body1>
<Body1>
<A ID="pgfId-1040923"></A>
The embedded application supplies its own value models and action methods. Since there is no inheritance, you cannot override these actions and values. </Body1>
<StepStart>
<A ID="pgfId-1040925"></A>
Use a Palette to place a subcanvas in the reusing canvas, leaving it selected.</StepStart>
<StepCont>
<A ID="pgfId-1040926"></A>
In the subcanvas&#39;s <UI-Label>
Name</UI-Label>
 property, enter the name of the method that will supply an instance of the embedded application.</StepCont>
<StepCont>
<A ID="pgfId-1040927"></A>
In the subcanvas&#39;s <UI-Label>
Class</UI-Label>
 property, enter the name of the application that you are embedding.</StepCont>
<StepCont>
<A ID="pgfId-1040928"></A>
In the subcanvas&#39;s <UI-Label>
Canvas</UI-Label>
 property, enter the name of the interface specification that you are using from the embedded application.</StepCont>
<StepCont>
<A ID="pgfId-1040929"></A>
<UI-Label>
Apply</UI-Label>
 the properties and <UI-Label>
Install</UI-Label>
 the reusing canvas in its application model.</StepCont>
<StepCont>
<A ID="pgfId-1040931"></A>
Create an instance variable in the reusing application model, for holding onto the embedded application.</StepCont>
<StepCont>
<A ID="pgfId-1040933"></A>
Create an <Code>
initialize</Code>
 method in the reusing application model, in which the embedded application is created and assigned to the variable that you created in step 6.</StepCont>
<CodeSample>
<A ID="pgfId-1040934"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1040935"></A>
		&quot;Reusing List2Example&#39;s interface only -- initialize the list holder.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040936"></A>
		selectionInList := SelectionInList with: Smalltalk classNames.</CodeSample>
<CodeSample>
<A ID="pgfId-1040937"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040938"></A>
		&quot;Reusing List2Example application -- initialize the application instance.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040939"></A>
		classNames := List2Example new.</CodeSample>
<CodeSample>
<A ID="pgfId-1040940"></A>
		classNames list: Smalltalk classNames.</CodeSample>
<Body1>
<A ID="pgfId-1041180"></A>
<B>
Online example: </B>
<Code>
List2Example</Code>
 embedded in <CodeExample xml:link="simple" href="Subcan2.pcl" show="embed" actuate="auto">
Subcanvas2Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1040941"></A>
Install a value in an embedded widget</Heading3>
<Body1>
<A ID="pgfId-1040942"></A>
An embedded widget uses the value with which its host application initializes it. </Body1>
<StepStart>
<A ID="pgfId-1040944"></A>
In the <Code>
initialize</Code>
 method, send a message to the embedded application installing the desired value. </StepStart>
<CodeSample>
<A ID="pgfId-1040945"></A>
initialize</CodeSample>
<CodeSample>
<A ID="pgfId-1040946"></A>
		&quot;Reusing List2Example&#39;s interface only -- initialize the </CodeSample>
<CodeSample>
<A ID="pgfId-1040947"></A>
		list holder.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040948"></A>
		selectionInList := SelectionInList with: Smalltalk classNames.</CodeSample>
<CodeSample>
<A ID="pgfId-1040949"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040950"></A>
		&quot;Reusing List2Example application -- initialize the application</CodeSample>
<CodeSample>
<A ID="pgfId-1040951"></A>
		instance.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040952"></A>
		classNames := List2Example new.</CodeSample>
<CodeSample>
<A ID="pgfId-1040953"></A>
		classNames list: Smalltalk classNames.</CodeSample>
<StepCont>
<A ID="pgfId-1040955"></A>
In some situations, as in the example, you will have to create a method (<Code>
list:</Code>
) in the embedded application model that enables an outside application to supply a new value.</StepCont>
<CodeSample>
<A ID="pgfId-1040956"></A>
list: aCollection</CodeSample>
<CodeSample>
<A ID="pgfId-1040957"></A>
		&quot;Install aCollection in the list. This message is</CodeSample>
<CodeSample>
<A ID="pgfId-1041101"></A>
		provided so reusers can install a list that is different</CodeSample>
<CodeSample>
<A ID="pgfId-1041104"></A>
		than the default list (color names).&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040960"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040961"></A>
		self selectionInList list: aCollection.</CodeSample>
<Heading3>
<A ID="pgfId-1040962"></A>
Reuse an application&#39;s interface only </Heading3>
<Body1>
<A ID="pgfId-1040963"></A>
You can use another application&#39;s interface in your application without inheriting from that application. Your application must supply all value models and methods supporting the interface.</Body1>
<Body1>
<A ID="pgfId-1040964"></A>
Because your application is supplying value models, you can reuse an interface only once on a canvas.</Body1>
<StepStart>
<A ID="pgfId-1040966"></A>
Use a Palette to place a subcanvas in the reusing canvas (the canvas for <Code>
Subcanvas2Example</Code>
).</StepStart>
<StepCont>
<A ID="pgfId-1040967"></A>
In the subcanvas&#39;s <UI-Label>
Class</UI-Label>
 property, enter the name of the application (<Code>
List2Example</Code>
) that defines the interface to be embedded.</StepCont>
<StepCont>
<A ID="pgfId-1040968"></A>
In the subcanvas&#39;s <UI-Label>
Canvas</UI-Label>
 property, enter the name of the interface specification (<Code>
listSpec</Code>
) to be embedded.</StepCont>
<StepCont>
<A ID="pgfId-1040969"></A>
Apply the properties and install the reusing canvas in its application model (<Code>
Subcanvas2Example</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1041252"></A>
Use a System Browser to edit the reusing application model (<Code>
Subcanvas2Example</Code>
), creating instance variables (<Code>
selectionInList</Code>
) and methods (<Code>
selectionInList</Code>
, <Code>
initialize</Code>
, <Code>
add</Code>
, and <Code>
delete</Code>
) to support the embedded interface. These instance variables and methods must have the same names as the corresponding ones in the reused class (<Code>
List2Example</Code>
). Modify values and action methods as desired.</StepCont>
<Body1>
<A ID="pgfId-1041253"></A>
<B>
Online example:</B>
 <CodeExample xml:link="simple" href="Subcan2.pcl" show="embed" actuate="auto">
Subcanvas2Example</CodeExample>
 (which reuses <CodeExample xml:link="simple" href="List2.pcl" show="embed" actuate="auto">
List2Example</CodeExample>
&#39;s <Code>
listSpec</Code>
)</Body1>
<Heading3>
<A ID="pgfId-1041197"></A>
Change interfaces during run-time</Heading3>
<Body1>
<A ID="pgfId-1041198"></A>
You can use a subcanvas to change the widgets or collections of widgets that appear in a larger canvas.</Body1>
<StepStart>
<A ID="pgfId-1040974"></A>
Use a Palette to place a subcanvas in the reusing canvas (the canvas for <Code>
Subcanvas3Example</Code>
).</StepStart>
<StepCont>
<A ID="pgfId-1040976"></A>
In the subcanvas&#39;s <UI-Label>
Name</UI-Label>
 property, enter the name of the method (<Code>
embeddedApplication</Code>
) that supplies the embedded application at startup time.</StepCont>
<StepCont>
<A ID="pgfId-1040977"></A>
Apply the properties and install the reusing canvas in its application model (<Code>
Subcanvas3Example</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040979"></A>
Use a System Browser to create the method (<Code>
embeddedApplication</Code>
) that you named in step 2. You create this method in the reusing application model (<Code>
Subcanvas3Example</Code>
). This method can supply either a <Code>
nil</Code>
 value (for a blank subcanvas) or one of the subapplications.</StepCont>
<CodeSample>
<A ID="pgfId-1040980"></A>
embeddedApplication</CodeSample>
<CodeSample>
<A ID="pgfId-1040981"></A>
		^nil asValue</CodeSample>
<StepCont>
<A ID="pgfId-1040983"></A>
In a change message (presumably triggered by a change in some other widget such as a button), create an instance of the desired application model (<Code>
Editor2Example</Code>
) and initialize it. (Or you can create and initialize the application model once at startup and store it in an instance variable.)</StepCont>
<StepCont>
<A ID="pgfId-1040985"></A>
Continuing in the change message, get the spec object for the interface you want to use by sending an <Code>
interfaceSpecFor:</Code>
 message to the embedded application model&#39;s class (<Code>
Editor2Example</Code>
). The argument is the name of the interface specification (<Code>
#windowSpec</Code>
).</StepCont>
<StepCont>
<A ID="pgfId-1040987"></A>
Continuing in the change message, get the subcanvas from the builder and send a <Code>
client:spec:</Code>
 message to it. The first argument is the application you created in step 5. The second argument is the spec object you obtained in step 6.</StepCont>
<CodeSample>
<A ID="pgfId-1040988"></A>
showComment</CodeSample>
<CodeSample>
<A ID="pgfId-1040989"></A>
		| selectedClass subcanvas spec application |</CodeSample>
<CodeSample>
<A ID="pgfId-1040990"></A>
		selectedClass := Smalltalk at: self classNames selection.</CodeSample>
<CodeSample>
<A ID="pgfId-1040991"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040992"></A>
		&quot;Create the subapplication and initialize it.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040993"></A>
		application := Editor2Example new.</CodeSample>
<CodeSample>
<A ID="pgfId-1040994"></A>
		application text value: selectedClass comment.</CodeSample>
<CodeSample>
<A ID="pgfId-1040995"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040996"></A>
		&quot;Get the spec object for the embedded canvas.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1040997"></A>
		spec := Editor2Example interfaceSpecFor: #windowSpec.</CodeSample>
<CodeSample>
<A ID="pgfId-1040998"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1040999"></A>
		&quot;Get the subcanvas and install the editing application.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041000"></A>
		subcanvas := (self builder componentAt: #subcanvas) widget.</CodeSample>
<CodeSample>
<A ID="pgfId-1041001"></A>
		subcanvas client: application spec: spec.</CodeSample>
<Body1>
<A ID="pgfId-1041213"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Subcan3.pcl" show="embed" actuate="auto">
Subcanvas3Example</CodeExample>
 (which swaps <CodeExample xml:link="simple" href="Editor2.pcl" show="embed" actuate="auto">
Editor2Example</CodeExample>
 and <CodeExample xml:link="simple" href="List2.pcl" show="embed" actuate="auto">
List2Example</CodeExample>
)</Body1>
<Heading3>
<A ID="pgfId-1041002"></A>
Make a subcanvas blank</Heading3>
<Body1>
<A ID="pgfId-1041003"></A>
You can empty a subcanvas at run time.</Body1>
<StepStart>
<A ID="pgfId-1041004"></A>
Get the subcanvas from the builder. </StepStart>
<StepCont>
<A ID="pgfId-1041005"></A>
Send a <Code>
client:</Code>
 message to the subcanvas with a <Code>
nil</Code>
 argument.</StepCont>
<CodeSample>
<A ID="pgfId-1041006"></A>
showNothing</CodeSample>
<CodeSample>
<A ID="pgfId-1041007"></A>
		| subcanvas |</CodeSample>
<CodeSample>
<A ID="pgfId-1041008"></A>
		subcanvas := (self builder componentAt: #subcanvas) widget.</CodeSample>
<CodeSample>
<A ID="pgfId-1041009"></A>
		subcanvas client: nil.</CodeSample>
<Body1>
<A ID="pgfId-1041217"></A>
In <Code>
Subcanvas3Example</Code>
, the subcanvas goes blank when no class is selected.</Body1>
<Body1>
<A ID="pgfId-1041226"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Subcan3.pcl" show="embed" actuate="auto">
Subcanvas3Example</CodeExample>
</Body1>
<Heading3>
<A ID="pgfId-1041010"></A>
Accessing an embedded widget</Heading3>
<Body1>
<A ID="pgfId-1041011"></A>
Frequently an embedded or inherited interface contains more than you need. For example, when an embedded action button is not appropriate in the local application, you could make it invisible or disable it. Before you can manipulate embedded widgets, however, you need to access them.</Body1>
<StepStart>
<A ID="pgfId-1041014"></A>
Before installing the new subapplication using <Code>
client:spec:</Code>
, initialize the subapplication&#39;s builder to <Code>
nil</Code>
. (Otherwise, the subapplication will continue to hold the old builder even after a new builder is created to assemble the new interface.)</StepStart>
<StepCont>
<A ID="pgfId-1041016"></A>
Ask the subapplication for its builder and then send <Code>
componentAt:</Code>
 to that builder. The argument is the <UI-Label>
ID</UI-Label>
 of the desired widget.</StepCont>
<CodeSample>
<A ID="pgfId-1041017"></A>
showMethods</CodeSample>
<CodeSample>
<A ID="pgfId-1041018"></A>
		| selectedClass subcanvas spec |</CodeSample>
<CodeSample>
<A ID="pgfId-1041019"></A>
		selectedClass := Smalltalk at: self classNames selection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041020"></A>
		spec := List2Example interfaceSpecFor: #listSpec.</CodeSample>
<CodeSample>
<A ID="pgfId-1041021"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041022"></A>
		&quot;Install the method names as the collection in the list application.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041023"></A>
		self listApplication list: selectedClass selectors asSortedCollection.</CodeSample>
<CodeSample>
<A ID="pgfId-1041024"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041025"></A>
		&quot;Set the subbuilder to nil to discard the old builder. This is only </CodeSample>
<CodeSample>
<A ID="pgfId-1041026"></A>
		necessary when the application uses the builder later to access widgets.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041027"></A>
		listApplication builder: nil.</CodeSample>
<CodeSample>
<A ID="pgfId-1041028"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041029"></A>
		&quot;Get the subcanvas and install the list application.&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041030"></A>
		subcanvas := (self builder componentAt: #subcanvas) widget.</CodeSample>
<CodeSample>
<A ID="pgfId-1041031"></A>
		subcanvas client: listApplication spec: spec.</CodeSample>
<CodeSample>
<A ID="pgfId-1041032"></A>
</CodeSample>
<CodeSample>
<A ID="pgfId-1041033"></A>
		&quot;Disable the embedded buttons (just to show that we can).&quot;</CodeSample>
<CodeSample>
<A ID="pgfId-1041034"></A>
		(listApplication builder componentAt: #addButton) disable.</CodeSample>
<CodeSample>
<A ID="pgfId-1041035"></A>
		(listApplication builder componentAt: #deleteButton) disable.</CodeSample>
<Body1>
<A ID="pgfId-1041234"></A>
<B>
Online example: </B>
<CodeExample xml:link="simple" href="Subcan3.pcl" show="embed" actuate="auto">
Subcanvas3Example</CodeExample>
</Body1>
<Body1>
<A ID="pgfId-1029452"></A>
</Body1>
</XML>
