Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: More Macintosh Toolbox /
Chapter 4 - List Manager / Using the List Manager


Outlining the Current List

If a window in your application contains two lists, or contains one list and an editable text item, then your application should place a 2-pixel outline around a list whenever the list is the current list and active, that is, whenever typing would affect the list. Your application should outline the current list so that the user knows that typing affects the list.

Listing 4-23 shows an application-defined procedure that checks whether a list is the current list. If it is both current and active, it draws a 2-pixel outline around the list. Otherwise, it draws in the background color of the dialog box to remove the outline.

Listing 4-23 Drawing an outline around a list

PROCEDURE MyDrawOutline (myList: ListHandle);
CONST
   kScrollBarWidth = 15;         {width of scroll bar}
VAR
   myOutlineRect:    Rect;       {rectangle for outline border}
   myPenState:       PenState;   {current status of pen}
BEGIN
   {get list's visible rectangle}
   myOutlineRect := myList^^.rView;
   {compensate for scroll bars}
   IF myList^^.vScroll <> NIL THEN
      myOutlineRect.right := myOutlineRect.right 
                              + kScrollBarWidth;
   IF myList^^.hScroll <> NIL THEN
      myOutlineRect.bottom := myOutlineRect.bottom 
                              + kScrollBarWidth;
   {draw 2-pixel outline 3 pixels from border}
   SetPort(myList^^.port);       {set port to list's port}
                                 {move out 4 pixels}
   InsetRect(myOutlineRect, -4, -4);
   GetPenState(myPenState);      {store pen state}
   IF (myList = gCurrentList) AND myList^^.lActive THEN
      PenPat(black)              {draw border}
   ELSE
      PenPat(white);             {remove border}
   PenSize(2, 2);                {use 2-pixel pen}
   FrameRect(myOutlineRect);     {draw outline}
   SetPenState(myPenState);      {restore old pen state}
END;
The MyDrawOutline procedure defined in Listing 4-23 determines the rectangle to draw in by adjusting the list's visible rectangle to compensate for scroll bars and by then moving each side of the rectangle 4 pixels. (One pixel is already taken by the list border, an additional pixel is needed for space between the border and the outline, and the pen size for the outline is 2 pixels.) The list determines whether to draw or remove a list by comparing the list passed in with an an application-defined global variable, gCurrentList. If the variable indicates that a list is the current list, and the MyDrawOutline procedure determines that the list is active, then it draws the outline; otherwise, it removes it.

Your application can use the refCon field of the list record to create a linked ring list of all of the lists in a window to make it easier to support outlining. That is, the refCon field of the first list in a window contains a handle to the second list in a window; the refCon field of the second list in a window contains a handle to the third, and so on, until the refCon field of the last list in a window contains a handle to the first.

The advantage of implementing such a ring list is that it makes it easy to change which list is the current list. In response to a Tab-key event, your application need only find the next list in a window by looking at the current list's refCon field and setting the gCurrentList variable to the list referenced by that field. Without using such a strategy, your application would need to examine the gCurrentList variable, determine which of a window's lists the variable corresponded to, determine which list in the window is the next list, and then set the gCurrentList variable to this next list.

Listing 4-24 shows an application-defined procedure that adds a list to a ring being maintained for a particular window.

Listing 4-24 Adding a list to the ring

PROCEDURE MyTrackList (myList: ListHandle);
VAR
   aList:      ListHandle;
BEGIN
   aList := gCurrentList;
   IF aList = NIL THEN
      gCurrentList := myList     {first ListHandle to be tracked}
   ELSE
   BEGIN
      {look for last ListHandle in ring}
      WHILE (ListHandle(aList^^.refCon) <> gCurrentList) DO
         {move to next ListHandle in ring}
         aList^^.refCon := ListHandle(aList^^.refCon)^^.refCon;
      {insert myList into ring}
      ListHandle(aList^^.refCon) := myList;
   END;
   {add link from myList to current list}
   ListHandle(myList^^.refCon) := gCurrentList;
END;
The SurfWriter application calls the MyTrackList procedure defined in Listing 4-24 once for each list in a window when it first opens that window. The first list added to the ring is automatically set to be the current list. SurfWriter initializes the gCurrentList variable to NIL before creating a ring for each window that uses multiple lists. In addition, SurfWriter stores the value of the gCurrentList variable whenever a window containing multiple lists is deactivated and then resets it when the window is activated again. That way, the gCurrentList variable always stores a handle to the current list of the active window.

Once all the lists in a window are linked in a ring, it is easy to write a routine that ensures that only the current list is outlined. Listing 4-25 illustrates such a routine.

Listing 4-25 Updating the outline of all lists in a window

PROCEDURE MyUpdateListOutlines;
VAR
   listToUpdate:     ListHandle;
BEGIN
   listToUpdate := gCurrentList;
   IF listToUpdate <> NIL THEN
   REPEAT
      {move to next list in ring}
      listToUpdate := ListHandle(listToUpdate^^.refCon);
      MyDrawOutline(listToUpdate);
   UNTIL listToUpdate = gCurrentList;
END;
The MyUpdateListOutlines procedure defined in Listing 4-25 simply calls the MyDrawOutline procedure for each list in the active window's ring of lists. The SurfWriter application calls this procedure each time your application changes which list is current.

Listing 4-26 shows an application-defined procedure that responds to the user's pressing the Tab key when the Shift key is not also pressed.

Listing 4-26 Moving the outline to the next list in a window

PROCEDURE MyOutlineNextList;
BEGIN
   gCurrentList := ListHandle(gCurrentList^^.refCon);
   MyUpdateListOutlines;
END;
If the user presses Shift-Tab, your application should respond by changing the current list to the previous list. Listing 4-27 shows an application-defined procedure that does this.

Listing 4-27 Moving the outline to the previous list in a window

PROCEDURE MyOutlinePreviousList;
VAR
   previousList:     ListHandle;
BEGIN
   {compute the coordinates of the list before the current list}
   previousList := gCurrentList;
   WHILE (ListHandle(previousList^^.refCon) <> gCurrentList) DO
      previousList := ListHandle(previousList^^.refCon);
   {now switch the outline to this list}
   gCurrentList := previousList;
   MyUpdateListOutlines;
END;
The MyOutlineNextList and MyOutlinePreviousList procedures defined in Listing 4-26 and Listing 4-27 work the same if a window contains exactly two lists.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
6 JUL 1996