
and synchronizes the children views of P to match the
stepChildren
array. Specifically, any child view whose template is no longer in the
stepChildren
array is closed, a child view is constructed for any new
template in
stepChildren
, and remaining views are redrawn if their
template
viewBounds
have changed. Conceptually, to make P scroll
down by one item, P only has to remove the template for the first item from
the
stepChildren
array and add a new template to the end of
stepChildren
for the new item to be displayed. The view system will
close the unneeded child view, shift remaining children up, and open a new
view at the bottom.
In practice, this method works well for scrolling down. P’s
viewSetupChildrenScript
uses a single call to
ArrayMunger
to
splice all but the first element of the
stepChildren
array into the
beginning of a new array containing only the new template. Newton’s view
system closes the top-most view, redraws remaining views just above their
previous position, and opens the new view at the bottom of the display.
However, scrolling up does not work as expected. Following the pattern
used for scrolling down, P removes the last template from its
stepChildren
array with a call to
SetLength
and adds a new template
to the beginning using
ArrayMunger
. Surprisingly, the view system
closes the obsolete view at the bottom and draws the new view in its place
without shifting the remaining views downward. To make this work, P can
recreate the entire
stepChildren
array when scrolling up. This forces the
view system to close and reopen each child view.
This approach alleviates both the worst properties of the first
implementation. P opens much more quickly (only 1.1 seconds) and requires
much less heap (only 5K). The drawback is that it scrolls very slowly taking
32.4 seconds to scroll up and down by 10 items. This time is unevenly
divided between the fast down scrolling (when one view is closed and one
opened) and the slow up scrolling (when S views are closed and opened).
USING AN AGGREGATE PROTO AND AN UPDATE MESSAGE
An obvious third alternative is to avoid closing and reopening any children
views. Using a parent view P with S children as before, when P receives the
viewScrollUpScript
and
viewScrollDownScript
messages it sends
an update message to each of its S children views passing an index for a new
item to display. To scroll the display up by one, each child view is sent an
index one larger than it had before. To scroll down, an index one smaller.
Implementing this is slightly more complex than the first approach using
setOrigin
. P must keep track of the index of the first item currently
displayed. The proto for the children must respond also to an update
message and suitably initialize its components (the checkbox, picture view,
static texts, and gauge). The proto could do this by sending itself a
redoChildren
message leaving the components to initialize themselves
with their
viewSetupFormScripts
. A slightly faster alternative is for
each component to have an update method that resets its part of the display,
probably by calling
SetValue
. If the user is going to be allowed to scroll
until the last item is at the top of the display (and the remainder of the
display is blank), then the proto must also be able to handle the case where
there is no item to be displayed at all.
This complexity yields an implementation that is almost as fast opening
as the one using
syncChildren
and uses less heap (4K versus 5K).
However, it scrolls more slowly. Even if we pre-compute the length of the
array of items and cache
childViewFrames
in P’s
viewSetupDoneScript
, it still takes 36.5 seconds to scroll down by 10
and back up by 10 items. The reduction in scrolling speed is a direct result
of the extra messages sent to the S children views and to their grandchildren
views, including the
SetValue
calls.
These approaches represent extremes. The approach using
setOrigin
exhibits aggressive computation; it computes all results at the first opportunity
and then relies on a cache of these results. The cache takes time to construct
and uses space but is fast in subsequent use. In contrast, the approaches
using
syncChildren
and an update message exhibit lazy computation; they
do a minimum of computation initially and compute only what is needed
later. They pay no penalty for a cache but enjoy no benefit either.
To get better scrolling performance out of the update message approach,
we need to avoid the recomputation entailed in each round of update
messages. When the user scrolls, only one new item is displayed, and all but
one of the previous items are re-displayed. In our example 14 items are
displayed at one time. Each time the user scrolls, 13 old items are re-
displayed. Nearly 93% of the computation is repeated!
USING A SIMPLE PROTO AND A
viewDrawScript
We can speed up scrolling with a lazy computation involving simpler views.
Instead of building a proto with multiple child views, we’ll use a
drawShape
message within a
viewDrawScript
to draw a comparable
visual representation . What was once a child check box view is now one of
two bit maps: either a checked or an unchecked bit map. The icon becomes
a bit map, and its border a
MakeRoundRect
shape. The static texts
become
MakeText
shapes. The gauge becomes a pair of
MakeRect
shapes.
We can optimize this slightly by taking advantage of the fact that the
drawShape
message is sufficiently flexible to draw an array of shapes at
once. So the proto will send
drawShape
once to image all seven of its
shapes to save on the overhead of repeated message sends. To further
minimize drawing, the checked and unchecked bit maps can be combined
with a bit map that looks like a round rectangle eliminating the need for a
separate call to
MakeRoundRect
. The gray rectangle underlying the
gauge could also be combined if the application was a fixed width and the
distance between the gauge and checkbox were known at compile time.
The base view must still pass the
viewScrollDownScript
and
viewScrollUpScript
messages along to the parent view P. As before, P
must pass along an update message to each of the S children. The update
message includes the index of the item a specific child is to display. The
proto just sends itself the “dirty” message instead of passing the update
message to its components. The “dirty” message in turn triggers the proto’s
viewDrawScript
.
This approach opens the application very quickly (1.3 seconds) but is still
about twice as slow at scrolling as the
setOrigin
implementation (21.9
versus 9.8 seconds). However, it is quite a bit faster than the update method
with aggregate protos. Newton’s view system is able to execute drawing
commands faster than it is able to update a comparable number of views.
That the aggregate proto is slower should not be too surprising since the
view system is doing quite a bit of work for each child of the proto sending
viewSetupFormScript
,
viewSetupChildrenScript
,
viewSetupDoneScript
, and other messages. Another advantage of a
simple proto with a
viewDrawScript
is that it uses very little heap
because there are very few views active. In our example shown in Figure 1,
at least 5x14 = 70 views are used with aggregate protos but only 14 with
simple protos. This estimate of a 5-fold savings in heap is comparable to the
Newton Technology Journal June 1996
19
Comentarios a estos manuales