Important: The information in this document is obsolete and should not be used for new development.
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;TheMyDrawOutline
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 theMyDrawOutline
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, therefCon
field of the first list in a window contains a handle to the second list in a window; therefCon
field of the second list in a window contains a handle to the third, and so on, until therefCon
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 thegCurrentList
variable to the list referenced by that field. Without using such a strategy, your application would need to examine thegCurrentList
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 thegCurrentList
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 theMyTrackList
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 thegCurrentList
variable toNIL
before creating a ring for each window that uses multiple lists. In addition, SurfWriter stores the value of thegCurrentList
variable whenever a window containing multiple lists is deactivated and then resets it when the window is activated again. That way, thegCurrentList
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;TheMyUpdateListOutlines
procedure defined in Listing 4-25 simply calls theMyDrawOutline
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;TheMyOutlineNextList
andMyOutlinePreviousList
procedures defined in Listing 4-26 and Listing 4-27 work the same if a window contains exactly two lists.