parent previous next question (Smalltalk Textbook 23)

EngiViewBuilder

'EngiViewBuilder' is what is called an "interface builder." This class requires ObjectWorks 4.1 or VisualWorks 1.0 because it uses 'TextView' and 'ComposedTextView' (rather than the older 'CodeView' and 'StringHolderView').

VisualWorks has a feature called the "chameleon function" which lets you emulate the look and feel of several User Interface Standars on your native window system. ObjectWorks does not have this function. If you run VisualWorks, please evaluate the following message expressions to change the look an feel of the interface.

For Motif look and feel.
MotifLookPolicy installLookPreferences

For Mac.
MacLookPolicy installLookPreferences

For Windows.
Win3LookPolicy installLookPreferences

For OS2.
CUALookPolicy installLookPreferences

For Smalltalk original.
DefaultLookPolicy installLookPreferences

Furthermore VisualWorks has an interface builder, so 'EngiViewBuilder' is not necessary for VisualWorks users. However it will be worth your time to study this class to see how interface builders are constructed.

Let's take a look at Appendix 12. The inheritance tree for 'EngiViewBuilderModel ' is:

----------------------------------------------------------------------
Object()
. . Model('dependents')
. . . . EngiViewBuilderModel('views')
----------------------------------------------------------------------

There are only two instance variables, one is 'dependents' which stores dependent objects and the other is 'views' which stores the type and area of views which access this model. A set of 'Association' of the following types are stored in 'views'.

------------------------------------------------------
        aRectangle -> #boolView
        aRectangle -> #listView
        aRectangle -> #textView
------------------------------------------------------

'aRectangle' tracks the location and size of an instance of 'LabeledBooleanView,' 'SelectionInListView,' or 'TextView' in an instance of 'CompositePart'.

'EngiViewBuilderView' is a subclass of 'CompositeView' so it can participate in MVC relationships.

----------------------------------------------------------------------
Object()
. . VisualComponent()
. . . . VisualPart('container')
. . . . . . CompositePart('components' 'preferredBounds')
. . . . . . . . DependentComposite('model')
. . . . . . . . . . CompositeView('controller')
. . . . . . . . . . . . EngiViewBuilderView('wrappers' 'menuSelector')
----------------------------------------------------------------------

The inheritance of 'EngiViewBuilderController' is as follows and needs no explanation.

----------------------------------------------------------------------
Object()
. . Controller('model' 'view' 'sensor')
. . . . ControllerWithMenu('menuHolder' 'performer')
. . . . . . EngiViewBuilderController()
----------------------------------------------------------------------

Please 'file in' Appendix 12, then evaluate Program 23-1.


Program-23-01: (EngiViewBuilderModel, ValueHolder, ComposedTextView; 
addBoolViewIn:, addListViewIn:, addTextViewIn:)
----------------------------------------------------------------------
| viewBuilder |
viewBuilder := EngiViewBuilderModel new.
viewBuilder addBoolViewIn: (0.0 @ 0.0 corner: 0.4 @ 0.1).
viewBuilder addListViewIn: (0.0 @ 0.1 corner: 0.4 @ 1.0).
viewBuilder addTextViewIn: (0.4 @ 0.0 corner: 1.0 @ 1.0).
ComposedTextView open: (ValueHolder with: viewBuilder sourceCode).
---------------------------------------------------------------------

Program 23-1 instantiates an EngiViewBuilderModel, adds a few views to it and then displays its source code in a window. The source code you see is shown in Program 23-2:


Program-23-02: (EngiViewBuilderModel, BorderedWrapper, LabeledBooleanView,
PluggableAdaptor, CompositePart, LookPreferences, SelectionInListView, 
TextView; beToggle, beTriggerOnUp, 
on:aspect:change:list:menu:initialSelection:, on:aspect:change:menu:initialSelection:)
----------------------------------------------------------------------
| aModel topWindow topView |
aModel := EngiViewBuilderModel new.
topWindow := ScheduledWindow
                        model: aModel
                        label: ''
                        minimumSize: 300@200.
topView := CompositePart new.
topWindow component: topView.
topView
        addWrapper: (BorderedWrapper on:
                [| baseModel valueModel boolView |
                baseModel := (PluggableAdaptor on: aModel)
                                getSelector: #bool putSelector: #bool:.
                valueModel := (PluggableAdaptor on: baseModel)
                                selectValue: false.
                boolView := LabeledBooleanView model: valueModel.
                boolView label: ''.
                boolView beToggle.
                boolView controller beTriggerOnUp.
                boolView] value in: (0.0@0.0 corner: 0.4@0.1)).
topView
        add: (LookPreferences edgeDecorator on:
                        (SelectionInListView
                                        on: aModel
                                        aspect: #item
                                        change: #item:
                                        list: #list
                                        menu: #listMenu
                                        initialSelection: #item))
        in: (0.0@0.1 corner: 0.4@1.0).
topView
        add: (LookPreferences edgeDecorator on:
                        (TextView
                                        on: aModel
                                        aspect: #text
                                        change: #acceptText:from:
                                        menu: #textMenu
                                        initialSelection: nil))
        in: (0.4@0.0 corner: 1.0@1.0).
topWindow open
----------------------------------------------------------------------

Let me explain step by step what is happening. First of all evaluate Program 23-3 and you will see a blank window.


Program-23-03: (EngiViewBuilderModel; on:menu:)
---------------------------------------------------------------------
| viewBuilder topWindow subView |
viewBuilder := EngiViewBuilderModel new.
topWindow := ScheduledWindow
                        model: viewBuilder
                        label: 'View Builder'
                        minimumSize: 300 @ 200.
subView := EngiViewBuilderView on: viewBuilder menu: #menu.
topWindow component: subView.
topWindow open
---------------------------------------------------------------------

Now press the yellow button, and you should see a menu of 'source code', 'text view', 'list view', 'bool view', and 'remove view'. The blank window is the canvas upon which we will paint a user interface. Select 'text view' from the menu. A rectangle appears and moves with the mouse. To place it on the canvas, click once and then hold down the mouse to arrange the size of the view. 'list view' and 'bool view' behave similarly. Select 'source code' and you will see a window showing the source code necessary to programmatically generate the user interface you have just painted. To ckeck it out, just evaluate the window. Now use 'remove view' is to delete one of the views on the canvas and then do 'source code' to see that the source code is now differenct.

------------------------------------------------------------
| viewBuilder |
viewBuilder := EngiViewBuilderModel new.
------------------------------------------------------------

The viewBuilder created by the above expression supports adding three kinds of views:

---------------------------------------------------------------------
viewBuilder addBoolViewIn: decide a rectangular area interactively.
viewBuilder addListViewIn: decide a rectangular area interactively.
viewBuilder addTextViewIn: decide a rectangular area interactively.
----------------------------------------------------------------------

Then finally it generates the source code.

----------------------------------------------------------------------
ComposedTextView open: (ValueHolder with: viewBuilder sourceCode).
----------------------------------------------------------------------

User interface construction tools on the market or public domain today do not really do much more than this.


parent previous next question
Copyright (C) 1994-1996 by Atsushi Aoki
Translated by Kaoru Rin Hayashi & Brent N. Reeves