Split Windows
Volume Number: 5
Issue Number: 6
Column Tag: Pascal Procedures
Related Info: Window Manager
Have Your Window Do The Splits
By Kirk Chase, Anaheim, CA
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Split Personality
As I was looking in chapter two of Inside Macintosh, Vol. I, I saw a sweet little
interface under the heading “Splitting a Window.” I thought about that interface and
decided it would be nice to create a split bar in a window. So, I set out to write a
control definition for the split bar and a short little demo to see what additional
support was needed by the application.
The Split Bar Interface
A split bar is used to divide a window into two or more views of a document. The
split bar creates and readjusts scroll bars on top and bottom of the split bar as it is
moved. This allows the user to scroll each view, called a “pane,” to different areas
(See Figure 1). Many word processing and spreadsheet applications use split bars.
For example, at program start up, there is one scroll bar and a black rectangle
(the split bar) directly above it and beneath the drag bar of the window. The user then
clicks on the split bar and drags it across the top of the scroll bar. As he releases the
split bar, the scroll bar’s top is brought down on the screen just under the split bar
again and another scroll bar above the split bar fills the space left by moving the split
bar. As the user continues to move the split bar up or down, the top and bottom scroll
bars are adjusted in height accordingly.
Figure 1.
The Split Bar CDEF
The split bar functions like a scroll bar with only a thumb. In some ways, it is
easier than a normal scroll bar to create. For example, there is no concern for page
up/down or line up/down-- only a thumb routine (which is not very easy until you
know how). I include two variations of the CDEF for both horizontal (1) and vertical
(2) split bars.
The CDEF for a split bar is somewhere between the complexity of a normal button
and a scroll bar. If you read up on defining your own controls (Inside Macintosh, Vol.
I, Chapter 10), there are nine routines that your control function may or may not need
to handle. Most of the routines I, and others, have covered before in previous issues of
MacTutor (Vol. 5, No. 1 and 4). I will only examine those parts that apply to the split
bar.
calcCRgns Message
This message asks the CDEF to calculate the region of the control or indicators and
store it in the region handle supplied in the param parameter. Upon entry, you test
param to see if the high bit is set. If it is, you give the region for the indicator, and if
not, you give the region of the control.
The region of the control is its enclosing rectangle. This rectangle extends the
length of the window. This area is the same, except for a few areas, as the area the two
scroll bars occupy. (See Figure 2).
Figure 2 Scroll and Split Bars
Stacking controls is not a good idea (how do you know which control you are in?).
But, since the Split Bar CDEF only reports a mouse down in the indicator, which is not
covered, we have no problem knowing which control was pressed.
Now if the message wants the region of the thumb indicator, it is because it is
about to be dragged around the screen with DragGrayRgn. Rather than just the region
of the thumb, I decided to give additional, visual interface to the user by dragging a
rectangular gray region across the window along with the thumb. In the application, I
draw a couple lines across the screen to separate the panes, and this gives the feel that
these two lines are part of the control. Calculating this other region is easy since all
points are known.
thumbCntl Message
This message is another routine used as a precursor to dragging an image of the
thumb. The param parameter is a pointer to the following record:
thumbinfo = record;
limitRect : Rect;
trackRect : Rect;
axis : integer;
end;
This record has the same meaning as that of the DragControl procedure.
limitRect confines the movement of the indicator itself; trackRect defines the rectangle
where the indicator will track with the mouse (these two are just the control’s
rectangle); and axis determines tracking constraints-- 1 for horizontal, 2 for
vertical, and 0 for none. Notice that the axis constraints are the same as the variation
of the control (I did not implement a 0 variation).
posCntl Message
After the thumb has been dragged all over, the CDEF is called again with a posCntl
message to reposition the thumb. You must erase the old position of the indicator
which I do with a flag sent to my draw routine and invalidating the place where the
indicator was.
The next step is to figure out the new value of the control. Our friend, param, is
typecasted to a point and holds the relative offset both horizontal and vertical. The new
value of the control is the old value plus the offset, minus any amount that goes out of
bounds. Finally, the control is drawn at its new value.
Other Messages
The initCntl message just sets the contrlAction field of the control to nil. The
drawCntl message holds nothing mysterious that hasn’t been covered before. There is
nothing done for the dispCntl, dragCntl, and autoTrack messages. The latter two
messages are for further customizing your control.
The Split Bar Demo
I decided to write a simple Text Edit demo using a vertical split bar. The user
could pull the split bar up and down, resize the window, scroll each pane
independently, do editing in either pane, and see updates if applicable in both panes.
This was certainly a mouthful.
I tried to think about how to handle text in the two panes. I could keep two Text
Edit records identical except for view and destination rectangles, or I could use one
record and just switch the view and destination rectangles when needed. I decided to
implement the latter version. Although separate TE records would have made it