Re: How to clip under BlackBox?

From: [at]} <pfister{>
Date: Thu, 11 Feb 1999 17:43:12 +0100

>for such a simple task looks like a cannon to kill a mosquito. Then I found
>Ports.Rider, and in particular SetRect, which looks like the perfect
>solution. But if you actually try the module below, it is less than
perfect.

One problem is the use of Views.Frame.SetOffset. This method is mainly for
internal
use of the framework, you don't need it here.

Ports.Rider.SetRect is indeed the right way to do clipping. Like all rider
operations, it uses global coordinates measured in pixels.
The Ports.Frame operations on the other hand use local coordinates
measured in universal units.
Frames are thus a device-independent higher-level abstraction that
builds upon a device-dependent lower-level abstraction. They are
"mappers", in the BlackBox terminology. If you want to work with
pixels, you may directly use the rider contained in the frame that you get.
Note that the clipping rectangle of a rider is a state that is managed by
the framework, normally you don't need to touch it. If you change it,
it's a good idea to restore the old state afterwards.

The reason why your Restore method still behaves strangely has
nothing to do with the lazy update mechanism of BlackBox. This
mechanism allows to decouple changes in a model data structure
from actual redrawing, to reduce flicker and to simplify the
construction of interactive views. After you have changed your
model, you simply call Views.Update or Views.UpdateIn. This
invalidates a geometrical region (in the simplest case, this is
the bounding box of the area affected by the model changes).
The Update procedures simply register the geometry information,
they don't cause any drawing. Later, when the command has
completed (and thus the model data structure is consistent again),
the framework checks whether there are invalid regions. If so,
it causes a restore of the invalidated frames. As a result, your
view's Restore method is called.

This Restore method should simply redraw everything within the
rectangle given by (l, t, r, b). It must *not* assume anything about
when it is being called, how often, in what order, etc.
Your code contains an IF statement that sometimes draws the
inner grey rectangle, and sometimes it doesn't. Basically, it
only redraws the inner rectangle if the view size has changed.
Thus the view redraws incorrectly when an obscured window
is brought to the top, since this operation hasn't changed the view size.
What's less obvious is the reason why the view draws incorrectly
when the window is opened. After all, this could be regarded as a change
in size. In fact, it *is* drawn correctly. But because of some intricate
low-level issues with the Windows API, BlackBox immediately updates
an opened window again. But since the view size hasn't changed again,
the inner rectangle is not drawn this time, and what you see is incorrect.

The remedy is simple: when Restore is called, restore the invalid rectangle
unconditionally, without making assumptions when this is really necessary
or when it might not be necessary.

Hope this helps

Cuno Pfister

Oberon microsystems, Inc.
Received on Thu Feb 11 1999 - 17:59:38 UTC

This archive was generated by hypermail 2.3.0 : Thu Sep 26 2013 - 06:27:42 UTC