CHAPTER 2 Subjects and Views

The Value program


Having examined some basic subject-view interaction, let's explore a slightly more complicated program called "value" which is shown in figure 2-5.

Here, when the user manipulates the scrollbar, the values appear in the "field editor" positioned below the scrollbar. Also, the user can now enter values in the field editor. If 25 is entered, for example, the scrollbar's thumb-button will move to the center of the slider. If zero (or some negative number) is entered, the thumb-button moves to the bottom. Similarly, if 50 (or some large number) is entered, then the thumb-button moves to the top. The object diagram for the value program is shown in figure 2-6.

This program involves two subjects--the BoundedFloat and a Fresco CharString--and three views--the scrollbar, the FloatView (similar to the SimpleView), and the newly added field editor viewer. The field editor, like the scrollbar, comes from the WidgetKit. The code for the FloatView object is shown in listing 2-2. For brevity, the code that combines these objects together is not shown. It is quite similar, however, to the code in main() in listing 2-1, and it goes like this. First, the subjects are created--a BoundedFloat and a CharString--and then the views. A scrollbar viewer is created and passed the BoundedFloat subject. A field editor is created and passed the CharString subject. Finally, a FloatView is created and passed both the BoundedFloat and CharString. The viewers are then laid out visually to appear as they do in figure 2-5.

As seen in listing 2-2, FloatView has a constructor and two callback functions. The first callback function, string_update, is called when the CharString subject notifies its views (see figure 2-6.) Similarly, the second callback, adjustment_update, is called when the BoundedFloat subject notifies its views. Recall that the mechanism for a subject notifying a view is for the subject to call update() on that view. (An example is update() of SimpleView in listing 2-1.) This hints as to the reason why FloatView uses callbacks for update notification: since only update() is called for notification, if a view were attached to multiple subjects (like FloatView), that view would have no mechanism to determine which subject had made that call. FloatView solves this problem by using two callback objects which act as "proxy" views. These objects are created on lines 4 and 7 of listing 2-2. Each callback object attaches itself to the given subject, which is passed as the third argument. When update() is called on the first proxy, it immediately calls string_update(), and, similarly, when update() is called on the second proxy, it immediately calls adjustment_update().

This callback technique can be used whenever a view needs to observe multiple subjects.

Let's now examine how the two views behave in the value program. Refer to the object diagram in figure 2-6 and suppose that the user enters a number inside the field editor. The field editor will change the subject CharString and this causes the CharString to call update() on its views. Since one of these views is the FloatView's callback proxy, it, in turn, calls string_update on the FloatView. The FloatView defines string_update (listing 2-2) just as you might expect. It reads the value from the string, converts it to a float, and calls scroll_to() on the BoundedFloat subject. Since the BoundedFloat will notify its views, the slider on the srollbar will change to the appropriate position.

Now suppose, instead, that the user manipulates the scrollbar. A similar process happens but in the opposite direction. The scrollbar changes the BoundedFloat which calls update on its views. This results in a call to adjustment_update which FloatView defines to:

* get the current value from the BoundedFloat

* convert it into a string

* change the CharString subject

This causes the attached field editor to update its appearance to reflect the new string.

You may have noticed the potential for an infinite loop here. This is because an update from either subject causes the FloatView to change the other subject. And this, in turn, could result in another update on the FloatView. To illustrate this, suppose the user manipulates the scrollbar causing the BoundedFloat to change. The following sequence shows how the infinite loop might occur.

(1) The BoundedFloat notifies observers causing a call to adjustment_update().

(2) Adjustment_update converts the new value to a string, then causes the CharString to change (line 27, listing 2-2) and thus notify its observers.

(3) The CharString notifies observers causing a call to string_update().

(4) String_update converts the string into a float and then sets BoundedFloat using scroll_to().

(5) Go to step 1...

The loop doesn't occur because the BoundedFloat subject has been designed with enough smarts to prevent it: the BoundedFloat only notifies observers when its value actually changes. Since scroll_to() in step 4 is, in this case, passed the current value of the BoundedFloat, its observers are not notified--and thus the loop is avoided. A well-behaved subject will not notify its observers unless its value actually changes.


Copyright (c) 1994 by Steve Churchill
Comments or questions? Contact Steve Churchill (stevec@faslab.com)

Generated with CERN WebMaker