home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Muddweller 1.2 / source code / Externals / USizerView.impl.p < prev    next >
Encoding:
Text File  |  1992-02-26  |  43.7 KB  |  1,693 lines  |  [TEXT/MPS ]

  1. CONST
  2.     kMinLogHeight = 56;
  3.     kLineHeight = 12;
  4.  
  5. {$S AInit}
  6.  
  7. PROCEDURE InitUSizerView;
  8.  
  9.     BEGIN
  10.     SetVRect(gVertSBarSetback, 0, 0, kSBarSizeMinus1, 0);
  11.     SetVRect(gHorzSBarSetback, 0, 0, 0, kSBarSizeMinus1);
  12.     SetVRect(gBothSBarSetback, 0, 0, kSBarSizeMinus1, kSBarSizeMinus1);
  13.  
  14.     gNonPanes := NewIntegerArray(2);
  15.     gNonPanes.AddElement(GetClassIDFromName('TSScrollBar'));
  16.     gNonPanes.AddElement(GetClassIDFromName('TSplitter'));
  17.  
  18.     RegisterStdType('TSplitter', kStdSplitter);
  19.  
  20.     IF gDeadStripSuppression THEN BEGIN
  21.         IF Member(TObject(NIL), TSizerView) THEN;
  22.         IF Member(TObject(NIL), THorizontalSizer) THEN;
  23.         IF Member(TObject(NIL), TSplitter) THEN;
  24.         END;
  25.     END;
  26.  
  27. PROCEDURE ExcludeAsPane(obj: TObject);
  28. { Make the class of obj ineligible for pane-dom }
  29.  
  30.     VAR
  31.         itsClassId:        ObjClassId;
  32.  
  33.     BEGIN
  34.     IF obj <> NIL THEN BEGIN
  35.         itsClassId := GetClassID(obj);
  36.         gNonPanes.AddUnique(itsClassId);
  37.         END;
  38.     END;
  39.  
  40. {$S ADoCommand}
  41. FUNCTION CloneAView(aView: TView): TView;
  42. { Clone aView and all its subviews }
  43.  
  44.     VAR
  45.         newView:        TView;
  46.  
  47.     PROCEDURE CloneASubview(aSubView: TView);
  48.         VAR    newSubview:        TView;
  49.         BEGIN
  50.         newSubView := CloneAView(aSubView);
  51.         newView.AddSubView(newSubView);
  52.         END;
  53.  
  54.     PROCEDURE CreateIfScrollBar(aScroller: TScroller; dir: VHSelect);
  55.  
  56.         BEGIN
  57.         IF aScroller.fScrollBars[dir] <> NIL THEN BEGIN    { create the dir scroll bar }
  58.             aScroller.fScrollBars[dir] := NIL;
  59.             aScroller.CreateScrollBar(dir);
  60.             END;
  61.         END;
  62.  
  63.     BEGIN
  64.     newView := TView(aView.Clone);
  65.     newView.fNextHandler := NIL;                { will be set by AddSubView }
  66.     IF aView.fSubViews <> NIL THEN BEGIN
  67.         newView.fSubViews := NewList;
  68.         aView.EachSubView(CloneASubview);
  69.         END;
  70.     IF Member(aView, TScroller) THEN BEGIN        { aView is a TScroller }
  71.         CreateIfScrollBar(TScroller(newView), h);
  72.         CreateIfScrollBar(TScroller(newView), v);
  73.         END;
  74.     CloneAView := newView;
  75.     END;
  76.  
  77. {$S ARes}
  78. FUNCTION OtherDirection(direction: VHSelect): VHSelect;
  79.  
  80.     BEGIN
  81.     IF direction = v
  82.         THEN OtherDirection := h
  83.         ELSE OtherDirection := v;
  84.     END;
  85.  
  86. {-------------------------- TVRectList ----------------------}
  87.  
  88. {$S AOpen}
  89.  
  90. PROCEDURE TVRectList.IVRectList(initialSize: INTEGER);
  91.  
  92.     BEGIN
  93.     IDynamicArray(initialSize, SIZEOF(VRect));
  94.     END;
  95.  
  96. {$S ARes}
  97.  
  98. FUNCTION TVRectList.At(index: ArrayIndex): VRect;
  99. { Code stolen from TList.At }
  100.  
  101.     BEGIN
  102.     IF qRangeCheck & ((index <= kEmptyIndex) | (index > fSize)) THEN BEGIN
  103.         WRITELN('fSize = ', fSize: 1, '  index = ', index: 1);
  104.         ProgramBreak('Range Check in TVRectList.At');
  105.         END;
  106.  
  107.     At := VRectPtr(ComputeAddress(index))^;
  108.     END;
  109.  
  110. PROCEDURE TVRectList.AtPut(index: ArrayIndex; newItem: VRect);
  111. { Code stolen from TList.AtPut }
  112.  
  113.     BEGIN
  114.     WHILE index > fSize DO            { add items to list so index is valid }
  115.         InsertElementsBefore(fSize + 1, @gZeroVRect, 1);
  116.  
  117.     VRectPtr(ComputeAddress(index))^ := newItem;
  118.     END;
  119.  
  120. PROCEDURE TVrectList.AtCoordPut(index: ArrayIndex; whichCoord: Coordinate;
  121.                                 newCoord: VCoordinate);
  122. { Change a single coordinate of the specified VRect to the given value. }
  123.  
  124.     VAR
  125.         pVR:        VRectPtr;
  126.  
  127.     BEGIN
  128.     IF qRangeCheck & ((index <= kEmptyIndex) | (index > fSize)) THEN BEGIN
  129.         WRITELN('fSize = ', fSize: 1, '  index = ', index: 1);
  130.         ProgramBreak('Range Check in TVRectList.AtCoordPut');
  131.         END;
  132.  
  133.     pVR := VRectPtr(ComputeAddress(index));
  134.     CASE whichCoord OF
  135.         kLeftCoord:        pVR^.left := newCoord;
  136.         kRightCoord:    pVR^.right := newCoord;
  137.         kTopCoord:        pVR^.top := newCoord;
  138.         kBottomCoord:    pVR^.bottom := newCoord;
  139.         END;
  140.     END;
  141.  
  142. {$S ANever}
  143.  
  144. PROCEDURE TVrectList.AtSetVRect(index: ArrayIndex; left, top, right, bottom: VCoordinate);
  145. { Change the specified VRect’s coordinates to the given values. }
  146.  
  147.     VAR
  148.         pVR:        VRectPtr;
  149.  
  150.     BEGIN
  151.     IF qRangeCheck & ((index <= kEmptyIndex) | (index > fSize)) THEN BEGIN
  152.         WRITELN('fSize = ', fSize: 1, '  index = ', index: 1);
  153.         ProgramBreak('Range Check in TVRectList.AtSetVRect');
  154.         END;
  155.  
  156.     pVR := VRectPtr(ComputeAddress(index));
  157.     SetVRect(pVR^, left, top, right, bottom);
  158.     END;
  159.  
  160. {$S APane}
  161.  
  162. PROCEDURE TVRectList.InsertBefore(index: ArrayIndex; item: VRect);
  163.  
  164.     BEGIN
  165.     IF qRangeCheck & ((index <= kEmptyIndex) | (index > fSize + 1)) THEN
  166.         BEGIN
  167.         WRITELN('fSize = ', fSize: 1, '  index = ', index: 1);
  168.         ProgramBreak('Range Check in TVRectList.InsertBefore');
  169.         END;
  170.  
  171.     InsertElementsBefore(index, @item, 1);
  172.     END;
  173.  
  174. {$S AFields}
  175.  
  176. PROCEDURE TVRectList.Fields(PROCEDURE DoToField(fieldName: Str255;
  177.                                                 fieldAddr: Ptr;
  178.                                                 fieldType: INTEGER)); OVERRIDE;
  179.  
  180.     BEGIN
  181.     DoToField('TVRectList', NIL, bClass);
  182.     INHERITED Fields(DoToField);
  183.     END;
  184.  
  185. PROCEDURE TVRectList.DynamicFields(PROCEDURE DoToField(fieldName: Str255;
  186.                                                        fieldAddr: Ptr;
  187.                                                        fieldType: integer)); OVERRIDE;
  188.  
  189.     FUNCTION DoToElement(theIndex: ArrayIndex): Boolean;
  190.  
  191.         VAR
  192.             aString:            Str255;
  193.  
  194.         BEGIN
  195.         DoToElement := FALSE;
  196.         NumToString(theIndex, aString);
  197.         aString := CONCAT('[', aString, ']');
  198.         DoToField(aString, ComputeAddress(theIndex), bVRect);
  199.         END;
  200.  
  201.     BEGIN
  202.     DoToField('VRect Elements', NIL, bTitle);
  203.  
  204.     IF EachElementDoTil(DoToElement, kIterateForward) <> kEmptyIndex THEN;
  205.     END;
  206.  
  207. {-------------------------- TSizerView ----------------------}
  208.  
  209. {$S AOpen}
  210.  
  211. PROCEDURE TSizerView.Initialize; OVERRIDE;
  212.  
  213.     BEGIN
  214.     fPanes := NIL;
  215.     fSetbacks := NIL;
  216.     fSizerRects := NIL;
  217.     fSplitter := NIL;
  218.     fMinPaneSize := kMinSizerPane;
  219.     fSizerThickness := kSizerThickness;
  220.     END;
  221.  
  222. PROCEDURE TSizerView.IRes(itsDocument: TDocument; itsSuperView: TView; VAR itsParams: Ptr); OVERRIDE;
  223.  
  224.     BEGIN
  225.     IObject;                        (* shouldn’t this be called automagically? *)
  226.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  227.     InitLists;
  228.     END;
  229.  
  230. PROCEDURE TSizerView.ISizerView(itsDocument: TDocument;
  231.                                 itsSuperview: TView;
  232.                                 itsLocation: VPoint;
  233.                                 itsSize: VPoint;
  234.                                 itsHSizeDet, itsVSizeDet: SizeDeterminer);
  235.  
  236.     BEGIN
  237.     IObject;                        (* shouldn’t this be called automagically? *)
  238.     IView(itsDocument, itsSuperview, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
  239.     InitLists;
  240.     END;
  241.  
  242. PROCEDURE TSizerView.InitLists;
  243. { Create and initialize the various lists of subviews and VRects }
  244.  
  245.     VAR
  246.         aVRectList:        TVRectList;
  247.  
  248.     BEGIN
  249.     { Create a list for the subviews }
  250.     fPanes := NewList;
  251.     IF qDebug THEN fPanes.SetEltType('TView');
  252.  
  253.     { Initialize list of setback VRects }
  254.     NEW(aVRectList);
  255.     FailNIL(aVRectList);
  256.     aVRectList.IVRectList(2);        { big enough for two subpanes }
  257.     fSetbacks := aVRectList;
  258.  
  259.     { Initialize list of sizer VRects }
  260.     NEW(aVRectList);
  261.     FailNIL(aVRectList);
  262.     aVRectList.IVRectList(1);        { big enough for one sizer rectangle }
  263.     fSizerRects := aVRectList;
  264.     END;
  265.  
  266. {$S AOpen}
  267.  
  268. PROCEDURE TSizerView.FixupPanes(equalSpacing: BOOLEAN);
  269. { a/k/a “PostRes”; call after IRes (NewTemplateWindow).
  270.   If equalSpacing is TRUE, make the panes of equal size;
  271.   if equalSpacing is FALSE, try to locate the panes using their fSizes. }
  272.  
  273.     VAR
  274.         panes:                INTEGER;
  275.         sizers:                INTEGER;
  276.         i:                    INTEGER;
  277.         thePane:            TView;
  278.         aScroller:            TScroller;
  279.         aVRect:                VRect;
  280.         defaultSizerRects:    TVRectList;
  281.  
  282.     PROCEDURE GatherPanes(thePane: TView);
  283.     { Figure out which subviews are panes: all but those whose class id
  284.       is in the gNonPanes list. }
  285.  
  286.         BEGIN
  287.         IF NOT gNonPanes.Contains(GetClassId(thePane)) THEN
  288.             fPanes.InsertLast(thePane);
  289.         END;
  290.  
  291.     PROCEDURE InitSetbacks(thePane: TView);
  292.     { Initialize the setbacks according to whether each pane has scroll bars or not. }
  293.  
  294.         BEGIN
  295.         aVRect := gZeroVRect;            { assume subview fills pane }
  296.         IF Member(thePane, TScroller) THEN
  297.             BEGIN                        { subview is a scroller--check for scroll bars }
  298.             aScroller := TScroller(thePane);
  299.             IF aScroller.fScrollBars[v] <> NIL THEN
  300.                 IF aScroller.fScrollBars[h] <> NIL THEN
  301.                     aVRect := gBothSBarSetback
  302.                 ELSE
  303.                     aVRect := gVertSBarSetback
  304.             ELSE
  305.                 IF aScroller.fScrollBars[h] <> NIL THEN
  306.                     aVRect := gHorzSBarSetback;
  307.             END;
  308.         fSetbacks.AtPut(i, aVRect);
  309.         i := i + 1;
  310.         END;
  311.  
  312.     FUNCTION PaneCompare(item1, item2: TObject): CompareResult;
  313.  
  314.         BEGIN
  315.         { Pane comparison is direction dependent! }
  316.         PaneCompare := SELF.CompareViewLocations(TView(item1), TView(item2));
  317.         END;
  318.  
  319.     BEGIN                                { TSizerView.FixupPanes }
  320.     EachSubView(GatherPanes);            { make a list of the panes }
  321.     panes := fPanes.GetSize;
  322.     IF qDebug & (panes = 0) THEN
  323.         ProgramBreak('No panes, no gains!');
  324.     fPanes.SortBy(PaneCompare);            { order panes by location }
  325.  
  326.     i := 1;
  327.     fPanes.Each(InitSetbacks);            { initialize setback VRects }
  328.     sizers := panes - 1;                { number of sizers needed }
  329.  
  330.     { Create a list of sizer rectangles }
  331.     NEW(defaultSizerRects);
  332.     FailNIL(defaultSizerRects);
  333.     defaultSizerRects.IVRectList(sizers);
  334.  
  335.     IF equalSpacing THEN BEGIN            { Initialize the sizer rectangles… }
  336.         FOR i := 1 TO sizers DO BEGIN    { …to be evenly spaced }
  337.             aVRect := GetDefaultSizerRect(i);    { direction dependent! }
  338.             defaultSizerRects.AtPut(i, aVRect);
  339.             END;
  340.         END
  341.     ELSE BEGIN                            { Initialize the sizer rectangles… }
  342.         FOR i := 1 TO sizers DO BEGIN    { …from the panes’ locations and sizes }
  343.             thePane := TView(fPanes.At(i));
  344.             aVRect := GetNextSizerRect(thePane);
  345.             defaultSizerRects.AtPut(i, aVRect);
  346.             (* make another pass to check the sizer rects for consistency *)
  347.             END;
  348.         END;
  349.  
  350.     IF sizers > 0 THEN                    { Fit the subviews into the sizer rects }
  351.         SetPanes(defaultSizerRects, kDontInvalidate);
  352.     defaultSizerRects.Free;
  353.     END;
  354.  
  355. {$S AClose}
  356.  
  357. PROCEDURE TSizerView.Free; OVERRIDE;
  358.  
  359.     BEGIN
  360.     FreeIfObject(fSetbacks);
  361.     fSetbacks := NIL;
  362.     FreeIfObject(fSizerRects);
  363.     fSizerRects := NIL;
  364.  
  365.     INHERITED Free;
  366.     END;
  367.  
  368. {$S APane}
  369.  
  370. PROCEDURE TSizerView.AddPane(newPane: TView; itsLocation: VCoordinate; itsSetbacks: VRect);
  371. { Install thePane at the specified location, shrinking any existing pane accordingly. }
  372.  
  373.     VAR
  374.         itsPosition:    INTEGER;
  375.         itsSizerRect:    VRect;
  376.         newSizerRects:    TVRectList;
  377.  
  378.     BEGIN
  379.     IF (fSubViews = NIL) | (fSubViews.GetSameItemNo(newPane) = 0) THEN
  380.         AddSubView(newPane);
  381.     newSizerRects := NIL;
  382.  
  383.     IF GetNumberOfPanes = 0 THEN
  384.         itsPosition := 0
  385.     ELSE BEGIN        { need to add a sizer rect }
  386.         itsPosition := FindSizerPosition(itsLocation);
  387.         newSizerRects := TVRectList(fSizerRects.Clone);
  388.         END;
  389.  
  390.     { Add the new pane to the list }
  391.     fPanes.InsertBefore(itsPosition+1, newPane);
  392.  
  393.     { Add the new pane’s setbacks to the list }
  394.     fSetbacks.InsertBefore(itsPosition+1, itsSetbacks);
  395.  
  396.     IF newSizerRects <> NIL THEN BEGIN    { add the new sizer rect and resize panes }
  397.         itsSizerRect := MakeSizerRect(itsLocation);
  398.         newSizerRects.InsertBefore(itsPosition, itsSizerRect);
  399.         SetPanes(newSizerRects, kDontInvalidate);
  400.         newSizerRects.Free;                { discard temp sizerRects object }
  401.         END;
  402.     END;
  403.  
  404. PROCEDURE TSizerView.AddEqualPane(newPane: TView; itsPosition: INTEGER; itsSetbacks: VRect);
  405. { Install thePane at the specified position, resizing all panes equally. }
  406.  
  407.     VAR
  408.         existingPanes:    INTEGER;
  409.         itsSizerRect:    VRect;
  410.         newSizerRects:    TVRectList;
  411.         s:                INTEGER;
  412.  
  413.     BEGIN
  414.     IF (fSubViews = NIL) | (fSubViews.GetSameItemNo(newPane) = 0) THEN
  415.         AddSubView(newPane);
  416.  
  417.     existingPanes := fPanes.GetSize;
  418.     { constrain value of itsPosition to [1..existingPanes+1] }
  419.     IF itsPosition <= 0 THEN
  420.         itsPosition := 1
  421.     ELSE IF itsPosition > existingPanes+1 THEN
  422.         itsPosition := existingPanes + 1;
  423.     fPanes.InsertBefore(itsPosition, newPane);
  424.  
  425.     { Add the new pane’s setbacks to the list }
  426.     fSetbacks.InsertBefore(itsPosition, itsSetbacks);
  427.  
  428.     IF existingPanes > 0 THEN BEGIN        { need to add a sizer rect too }
  429.         newSizerRects := TVRectList(fSizerRects.Clone);
  430.         newSizerRects.AtPut(newSizerRects.GetSize+1, gZeroVRect);    { append a rect }
  431.         FOR s := 1 TO newSizerRects.GetSize DO BEGIN    { resize each rect }
  432.             itsSizerRect := GetDefaultSizerRect(s);
  433.             newSizerRects.AtPut(s, itsSizerRect);
  434.             END;
  435.         SetPanes(newSizerRects, kDontInvalidate);    { resize the panes to fit }
  436.         newSizerRects.Free;                { discard temp sizerRects object }
  437.         END;
  438.     END;
  439.  
  440. FUNCTION TSizerView.DeletePane(whichPane, whichSizer: INTEGER): TView;
  441.  
  442.     VAR
  443.         thePane:        TView;
  444.         changedPane:    TView;
  445.         scroller:        TScroller;
  446.         newSize:        VPoint;
  447.  
  448.     PROCEDURE RemoveIfSubView(sbar: TSScrollBar);
  449.  
  450.         BEGIN
  451.         IF sbar <> NIL THEN RemoveSubView(sbar);
  452.         END;
  453.  
  454.     BEGIN
  455.     thePane := TView(fPanes.At(whichPane));
  456.     IF whichPane > whichSizer THEN BEGIN        { deleting pane after sizer }
  457.         changedPane := TView(fPanes.At(whichPane-1));
  458.         END
  459.     ELSE BEGIN                                    { deleting pane before sizer }
  460.         { changedPane gets re-located and expanded }
  461.         changedPane := TView(fPanes.At(whichPane+1));
  462.  
  463.         { If changedPane has become the new first pane, leave room for splitter well }
  464.         IF (whichSizer = 1) & (Member(changedPane, TScroller)) THEN BEGIN
  465.             scroller := TScroller(changedPane);
  466.             IF GetSplitDirection = h
  467.                 THEN scroller.fSBarOffsets.top := scroller.fSBarOffsets.top + fSplitter.GetThickness
  468.                 ELSE scroller.fSBarOffsets.left := scroller.fSBarOffsets.left + fSplitter.GetThickness;
  469.             (* Locate will call AdjustScrollBars *)
  470.             END;
  471.  
  472.         changedPane.Locate(thePane.fLocation.h, thePane.fLocation.v, kInvalidate);
  473.         END;
  474.  
  475.     { Expand changedPane to include oldPane's area }
  476.     newSize := MergedSize(thePane, changedPane);
  477.     changedPane.Resize(newSize.h, newSize.v, kInvalidate);
  478.     DeletePane := changedPane;                    { return the expanded view }
  479.  
  480.     RemoveSubView(thePane);
  481.     IF Member(thePane, TScroller) THEN BEGIN    { remove the TSScrollBars, too }
  482.         scroller := TScroller(thePane);
  483.         RemoveIfSubView(scroller.fScrollBars[h]);
  484.         RemoveIfSubView(scroller.fScrollBars[v]);
  485.         END;
  486.     thePane.Free;                                { frees its TSScrollBars, if any }
  487.     fPanes.AtDelete(whichPane);
  488.     fSetbacks.DeleteElementsAt(whichPane, 1);
  489.     fSizerRects.DeleteElementsAt(whichSizer, 1);
  490.     END;
  491.  
  492. FUNCTION TSizerView.FindSizerPosition(VAR itsLocation: VCoordinate): INTEGER;
  493. { Given the desired coordinate for a new sizer rectangle, return its position
  494.   (index) in the list of sizers, modifying itsLocation if necessary. }
  495.  
  496.     VAR
  497.         sizers:                INTEGER;
  498.         itsPosition:        INTEGER;
  499.         s:                    INTEGER;
  500.         firstSizerCoord:    VCoordinate;
  501.         lastSizerCoord:        VCoordinate;
  502.  
  503.     BEGIN
  504.     sizers := GetNumberOfSizers;
  505.     itsPosition := 0;
  506.     s := 1;
  507.     REPEAT
  508.         firstSizerCoord := GetSizerCoord(s, kGetMinCoord);
  509.         lastSizerCoord := GetSizerCoord(s, kGetMaxCoord);
  510.         IF itsLocation < firstSizerCoord THEN        { precedes sizer s }
  511.             itsPosition := s
  512.         ELSE IF itsLocation <= lastSizerCoord THEN    { in sizer s }
  513.             BEGIN
  514.             itsPosition := s+1;
  515.             itsLocation := lastSizerCoord + fMinPaneSize;
  516.             END
  517.         ELSE                                        { follows sizer s }
  518.             s := s + 1;
  519.     UNTIL (itsPosition > 0) | (s > sizers);
  520.     IF itsPosition = 0 THEN itsPosition := s;
  521.  
  522.     FindSizerPosition := itsPosition;
  523.     END;
  524.  
  525. {$S AOpen}
  526.  
  527. PROCEDURE TSizerView.InstallSetbacks(whichPane: INTEGER; itsSetbacks: VRect);
  528.  
  529.     BEGIN
  530.     fSetbacks.AtPut(whichPane, itsSetbacks);
  531.     END;
  532.  
  533. {$S ASelCommand}
  534.  
  535. FUNCTION TSizerView.DoMouseCommand(VAR theMouse: Point; VAR info: EventInfo;
  536.                                    VAR hysteresis: Point): TCommand; OVERRIDE;
  537.  
  538.     VAR
  539.         aViewSizer:         TSizerCommand;
  540.         aViewDeSizer:        TDeSizerCommand;
  541.         whichSizer:            INTEGER;
  542.  
  543.     BEGIN
  544.     whichSizer := IsPointInSizer(theMouse);
  545.     IF whichSizer = 0 THEN                { not in a sizer rectangle }
  546.         DoMouseCommand := INHERITED DoMouseCommand(theMouse, info, hysteresis)
  547.     ELSE IF fSplitter = NIL THEN BEGIN    { ordinary resize }
  548.         NEW(aViewSizer);
  549.         FailNIL(aViewSizer);
  550.         aViewSizer.ISizerCommand(SELF, whichSizer, GetSplitDirection);
  551.         DoMouseCommand := aViewSizer;
  552.         END
  553.     ELSE BEGIN                            { resize or delete pane }
  554.         NEW(aViewDeSizer);
  555.         FailNIL(aViewDeSizer);
  556.         aViewDeSizer.IDeSizerCommand(SELF, whichSizer, GetSplitDirection);
  557.         DoMouseCommand := aViewDeSizer;
  558.         END;
  559.     END;
  560.  
  561. {$S ARes}
  562.  
  563. FUNCTION TSizerView.DoSetCursor(localPoint: Point; cursorRgn: RgnHandle): BOOLEAN; OVERRIDE;
  564.  
  565.     VAR
  566.         sizingCursNum:        Integer;
  567.  
  568.     BEGIN
  569.     IF IsPointInSizer(localPoint) > 0 THEN BEGIN
  570.         DoSetCursor := TRUE;
  571.         sizingCursNum := GetSizingCursor;
  572.         IF (GetCursor(sizingCursNum) <> NIL)
  573.             THEN SetCursor(GetCursor(sizingCursNum)^^)
  574.             ELSE SetCursor(arrow);
  575.         END
  576.     ELSE
  577.         DoSetCursor := FALSE;
  578.     END;
  579.  
  580. {$S ARes}
  581.  
  582. PROCEDURE TSizerView.Draw(area: Rect); OVERRIDE;
  583.  
  584.     VAR
  585.         bRect:                Rect;
  586.         aRect:                Rect;
  587.         tempRect:            VRect;
  588.         s:                    INTEGER;
  589.  
  590.     BEGIN
  591.     PenNormal;
  592.     FOR s := 1 TO GetNumberOfSizers DO BEGIN            { draw each sizerRect }
  593.         tempRect := GetSizerRect(s);
  594.         VRectToRect(tempRect, aRect);
  595.         IF SectRect(area, aRect, bRect) THEN
  596.             DrawSizerRect(aRect);
  597.         END;
  598.     END;
  599.  
  600. {$S ANever}
  601.  
  602. FUNCTION TSizerView.CompareViewLocations(view1, view2: TView): CompareResult;
  603.  
  604.     BEGIN
  605.     IF qDebug THEN ProgramBreak('CompareViewLocations must be overridden!');
  606.     END;
  607.  
  608. PROCEDURE TSizerView.DrawSizerRect(aRect: Rect);
  609.  
  610.     BEGIN
  611.     IF qDebug THEN ProgramBreak('DrawSizerRect must be overridden!');
  612.     END;
  613.  
  614. FUNCTION TSizerView.GetNextSizerRect(aPane: TView): VRect;
  615.  
  616.     BEGIN
  617.     IF qDebug THEN ProgramBreak('GetNextSizerRect must be overridden!');
  618.     END;
  619.  
  620. FUNCTION TSizerView.GetSizerCoord(whichSizer: INTEGER; min: BOOLEAN): VCoordinate;
  621. { Return the left/top (min=T) or right/bottom (min=F) coordinate of the specified sizer rect.
  622.   If whichSizer is larger than the number of sizers, return the width/height of the view.
  623.   If whichSizer is 0, return 0. }
  624.  
  625.     BEGIN
  626.     IF qDebug THEN ProgramBreak('GetSizerCoord must be overridden!');
  627.     END;
  628.  
  629. FUNCTION TSizerView.GetSizerRect(whichSizer: INTEGER): VRect;
  630.  
  631.     BEGIN
  632.     IF qDebug THEN ProgramBreak('GetSizerRect must be overridden!');
  633.     END;
  634.  
  635. FUNCTION TSizerView.GetSizingCursor: INTEGER;
  636.  
  637.     BEGIN
  638.     IF qDebug THEN ProgramBreak('GetSizingCursor must be overridden!');
  639.     GetSizingCursor := 0;
  640.     END;
  641.  
  642. FUNCTION TSizerView.IsValidSplitPt(aPoint: VPoint): BOOLEAN;
  643.  
  644.     BEGIN
  645.     IF qDebug THEN ProgramBreak('IsValidSplitPt must be overridden!');
  646.     END;
  647.  
  648. FUNCTION TSizerView.MakeSizerRect(itsLocation: VCoordinate): VRect;
  649.  
  650.     BEGIN
  651.     IF qDebug THEN ProgramBreak('MakeSizerRect must be overridden!');
  652.     END;
  653.  
  654. PROCEDURE TSizerView.TrackConstrain(anchorPoint, previousPoint: VPoint;
  655.                                     VAR nextPoint: VPoint); OVERRIDE;
  656. { Constrain mouse tracking to my interior, allowing for the minimum pane size }
  657.  
  658.     BEGIN
  659.     IF qDebug THEN ProgramBreak('TrackConstrain must be overridden!');
  660.     END;
  661.  
  662. {$S ADoCommand}
  663.  
  664. FUNCTION TSizerView.FindPane(aView: TView): INTEGER;
  665. { Return the position (index) of aView in the fPanes list }
  666.  
  667.     BEGIN
  668.     IF aView = NIL
  669.         THEN FindPane := 0
  670.         ELSE FindPane := fPanes.GetSameItemNo(aView);
  671.     END;
  672.  
  673. FUNCTION TSizerView.FindPaneAt(theCoords: VPoint): TView;
  674. { Return the pane at the given coordinates }
  675.  
  676.     FUNCTION ContainsCoords(aView: TView): BOOLEAN;
  677.  
  678.         VAR    viewFrame:    VRect;
  679.  
  680.         BEGIN
  681.         aView.GetFrame(viewFrame);
  682.         ContainsCoords := PtInVRect(theCoords, viewFrame);
  683.         END;
  684.  
  685.     BEGIN
  686.     FindPaneAt := TView(fPanes.FirstThat(ContainsCoords));
  687.     END;
  688.  
  689. {$S AOpen}
  690. FUNCTION TSizerView.GetDefaultSizerRect(whichSizer: INTEGER): VRect;
  691.  
  692.     VAR
  693.         paneLength:            LONGINT;
  694.         dir:                VHSelect;
  695.  
  696.     BEGIN
  697.     dir := OtherDirection(GetSplitDirection);
  698.     paneLength := fSize.vh[dir] DIV GetNumberOfPanes;
  699.     GetDefaultSizerRect := MakeSizerRect(paneLength * whichSizer);
  700.     END;
  701.  
  702. {$S ADoCommand}
  703.  
  704. FUNCTION TSizerView.GetMinPaneLength: VCoordinate;
  705. { Return the minimum width/height of a pane of this view. }
  706.  
  707.     BEGIN
  708.     GetMinPaneLength := fMinPaneSize;
  709.     END;
  710.  
  711. PROCEDURE TSizerView.SetMinPaneLength(minLength: VCoordinate);
  712.  
  713.     BEGIN
  714.     fMinPaneSize := minLength;
  715.     END;
  716.  
  717. {$S ADoCommand}
  718.  
  719. FUNCTION  TSizerView.GetNumberOfPanes: INTEGER;
  720.  
  721.     BEGIN
  722.     GetNumberOfPanes := fPanes.GetSize;
  723.     END;
  724.  
  725. FUNCTION  TSizerView.GetNumberOfSizers: INTEGER;
  726.  
  727.     BEGIN
  728.     GetNumberOfSizers := fSizerRects.GetSize;
  729.     END;
  730.  
  731. {$S ARes}
  732.  
  733. FUNCTION TSizerView.GetSizerThickness: INTEGER;
  734.  
  735.     BEGIN
  736.     GetSizerThickness := fSizerThickness;
  737.     END;
  738.  
  739. PROCEDURE TSizerView.SetSizerThickness(thickness: INTEGER);
  740.  
  741.     BEGIN
  742.     fSizerThickness := thickness;
  743.     END;
  744.  
  745. {$S ARes}
  746.  
  747. FUNCTION TSizerView.GetSplitDirection: VHSelect;
  748.  
  749.     BEGIN
  750.     GetSplitDirection := h;
  751.     END;
  752.  
  753. {$S ARes}
  754. PROCEDURE TSizerView.InvalidateFocus; OVERRIDE;
  755.  
  756.     BEGIN
  757.     gFocusedView := NIL;        { Eschew traversing all the subviews; just do it! }
  758.     END;
  759.  
  760. {$S ARes}
  761. FUNCTION TSizerView.IsPointInSizer(localPoint: Point): INTEGER;
  762. { Return the number of the sizer rect the point is in, or 0 if none. }
  763.  
  764.     VAR
  765.         aVPt:                VPoint;
  766.         tempRect:            VRect;
  767.         s:                    INTEGER;
  768.  
  769.     BEGIN
  770.     IsPointInSizer := 0;
  771.     PtToVPt(localPoint, aVPt);
  772.     FOR s := 1 TO GetNumberOfSizers DO BEGIN
  773.         tempRect := GetSizerRect(s);
  774.         IF PtInVRect(aVPt, tempRect) THEN BEGIN    { mouse is in sizer }
  775.             IsPointInSizer := s;
  776.             LEAVE;
  777.             END;
  778.         END;
  779.     END;
  780.  
  781. {$S APane}
  782. FUNCTION TSizerView.MergedSize(oldPane, changedPane: TView): VPoint;
  783. { Return the combined size of oldPane and changedPane }
  784.  
  785.     VAR
  786.         newSize:            VPoint;
  787.         myDir, opDir:        VHSelect;
  788.         sbar:                TSScrollBar;
  789.  
  790.     BEGIN
  791.     newSize := changedPane.fSize;
  792.     myDir := GetSplitDirection;
  793.     opDir := OtherDirection(myDir);
  794.     newSize.vh[opDir] := newSize.vh[opDir] + oldPane.fSize.vh[opDir] + fSizerThickness;
  795.     IF Member(oldPane, TScroller) THEN BEGIN    { allow for disappearing scrollbars }
  796.         sbar := TScroller(oldPane).fScrollBars[myDir];
  797.         IF sbar <> NIL THEN
  798.             newSize.vh[opDir] := newSize.vh[opDir] + sbar.fSize.vh[opDir] - 1;
  799.         END;
  800.     MergedSize := newSize;
  801.     END;
  802.  
  803. {$S ANonRes}
  804.  
  805. PROCEDURE TSizerView.SetPane(whichSizer: INTEGER; itsSizerRect: VRect);
  806.  
  807.     BEGIN
  808.     IF qDebug THEN ProgramBreak('SetPane must be overridden!');
  809.     END;
  810.  
  811. PROCEDURE TSizerView.SetPanes(newSizerRects: TVRectList; invalidate: BOOLEAN);
  812.  
  813.     BEGIN
  814.     IF qDebug THEN ProgramBreak('SetPanes must be overridden!');
  815.     END;
  816.  
  817. PROCEDURE TSizerView.SetSizerRect(whichSizer: INTEGER; itsSizerRect: VRect);
  818.  
  819.     VAR
  820.         aVRect:             VRect;
  821.         localRect:            VRect;
  822.         r:                    Rect;
  823.  
  824.     BEGIN
  825.     localRect := itsSizerRect;
  826.     aVRect := GetSizerRect(whichSizer);
  827.     IF IsShown & Focus THEN BEGIN                        { code from TView.InvalidVRect }
  828.         ViewToQDRect(localRect, r);
  829.         VisibleRect(r);
  830.         IF NOT EmptyRect(r) THEN
  831.             InvalidRect(r);
  832.         ViewToQDRect(aVRect, r);
  833.         VisibleRect(r);
  834.         IF NOT EmptyRect(r) THEN
  835.             InvalidRect(r);
  836.         END;
  837.     fSizerRects.AtPut(whichSizer, itsSizerRect);
  838.     END;
  839.  
  840. {$S ANonRes}
  841.  
  842. PROCEDURE TSizerView.SuperViewChangedSize(delta: VPoint; invalidate: BOOLEAN); OVERRIDE;
  843.  
  844.     VAR
  845.         lastCommand: TCommand;
  846.  
  847.     BEGIN
  848.     lastCommand := GetLastCommand;
  849.     IF lastCommand <> NIL THEN
  850.         IF (lastCommand.fCmdNumber = cSizeViews) & (lastCommand.fView = SELF) THEN
  851.             CommitLastCommand;
  852.     INHERITED SuperViewChangedSize(delta, invalidate);
  853.     END;
  854.  
  855.  
  856. {$S AFields}
  857.  
  858. PROCEDURE TSizerView.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  859.                                                 fieldType: INTEGER)); OVERRIDE;
  860.  
  861.     BEGIN
  862.     DoToField('TSizerView', NIL, bClass);
  863.     DoToField('fPanes', @fPanes, bObject);
  864.     DoToField('fSetbacks', @fSetbacks, bObject);
  865.     DoToField('fSizerRects', @fSizerRects, bObject);
  866.     DoToField('fMinPaneSize', @fMinPaneSize, bLongint);
  867.     DoToField('fSizerThickness', @fSizerThickness, bInteger);
  868.     DoToField('fSplitter', @fSplitter, bObject);
  869.     INHERITED Fields(DoToField);
  870.     END;
  871.  
  872. {-------------------------- THorizontalSizer ----------------------}
  873.  
  874. {$S AOpen}
  875.  
  876. FUNCTION THorizontalSizer.CompareViewLocations(view1, view2: TView): CompareResult; OVERRIDE;
  877.  
  878.     VAR
  879.         frame1, frame2:    VRect;
  880.  
  881.     BEGIN
  882.     view1.GetFrame(frame1);
  883.     view2.GetFrame(frame2);
  884.     IF frame1.top > frame2.top THEN
  885.         CompareViewLocations := kItem1GreaterThanItem2
  886.     ELSE IF frame1.top < frame2.top THEN
  887.         CompareViewLocations := kItem1LessThanItem2
  888.     ELSE
  889.         CompareViewLocations := kItem1EqualItem2;
  890.     END;
  891.  
  892. {$S ARes}
  893.  
  894. PROCEDURE THorizontalSizer.DrawSizerRect(aRect: Rect); OVERRIDE;
  895.  
  896.     BEGIN
  897.     WITH aRect DO BEGIN    { horizontal splitter }
  898.         MoveTo(left, top);
  899.         LineTo(right, top);
  900.         MoveTo(left, bottom-1);
  901.         LineTo(right, bottom-1);
  902.         END;
  903.     END;
  904.  
  905. {$S AOpen}
  906. FUNCTION THorizontalSizer.GetNextSizerRect(aPane: TView): VRect; OVERRIDE;
  907.  
  908.     VAR
  909.         vr:        VRect;
  910.  
  911.     BEGIN
  912.     aPane.GetFrame(vr);
  913.     GetNextSizerRect := MakeSizerRect(vr.bottom);
  914.     END;
  915.  
  916. {$S ADoCommand}
  917.  
  918. FUNCTION THorizontalSizer.GetSizerCoord(whichSizer: INTEGER;
  919.                                         min: BOOLEAN): VCoordinate; OVERRIDE;
  920.  
  921.     VAR
  922.         aSizerRect:        VRect;
  923.  
  924.     BEGIN
  925.     IF whichSizer = 0 THEN
  926.         GetSizerCoord := 0
  927.     ELSE IF whichSizer > fSizerRects.GetSize THEN
  928.         GetSizerCoord := fSize.v
  929.     ELSE BEGIN
  930.         aSizerRect := fSizerRects.At(whichSizer);
  931.         IF min
  932.             THEN GetSizerCoord := aSizerRect.top
  933.             ELSE GetSizerCoord := aSizerRect.bottom;
  934.         END;
  935.     END;
  936.  
  937. {$S ARes}
  938.  
  939. FUNCTION THorizontalSizer.GetSizingCursor: INTEGER; OVERRIDE;
  940.  
  941.     BEGIN
  942.     GetSizingCursor := kHorzSizingCursor;
  943.     END;
  944.  
  945. FUNCTION THorizontalSizer.GetSizerRect(whichSizer: INTEGER): VRect; OVERRIDE;
  946.  
  947.     VAR
  948.         vr:        VRect;
  949.  
  950.     BEGIN
  951.     IF whichSizer = 0 THEN BEGIN
  952.         SetVRect(vr, 0, 0, fSize.h, 0);
  953.         END
  954.     ELSE IF whichSizer > GetNumberOfSizers THEN BEGIN
  955.         SetVRect(vr, 0, fSize.v, fSize.h, fSize.v);
  956.         END
  957.     ELSE
  958.         vr := fSizerRects.At(whichSizer);
  959.  
  960.     GetSizerRect := vr;
  961.     END;
  962.  
  963. {$S ADoCommand}
  964. FUNCTION THorizontalSizer.IsValidSplitPt(aPoint: VPoint): BOOLEAN; OVERRIDE;
  965.  
  966.     BEGIN
  967.     IsValidSplitPt := (aPoint.v >= fMinPaneSize) &
  968.                       (aPoint.v <= fSize.v - fMinPaneSize - fSizerThickness);
  969.     END;
  970.  
  971. {$S ARes}
  972.  
  973. FUNCTION THorizontalSizer.MakeSizerRect(itsLocation: VCoordinate): VRect; OVERRIDE;
  974.  
  975.     VAR
  976.         aVRect:        VRect;
  977.  
  978.     BEGIN
  979.     SetVRect(aVRect, 0, itsLocation, fSize.h, itsLocation+fSizerThickness);
  980.     MakeSizerRect := aVRect;
  981.     END;
  982.  
  983. {$S ANonRes}
  984.  
  985. PROCEDURE THorizontalSizer.Resize(width, height: VCoordinate; invalidate: BOOLEAN); OVERRIDE;
  986.  
  987.     VAR
  988.         aSizerRect:         VRect;
  989.         oldHeight:            VCoordinate;
  990.         paneHeight:            VCoordinate;
  991.         previous:             VCoordinate;
  992.         panes:                INTEGER;
  993.         sizers:                INTEGER;
  994.         checkMinimum:        BOOLEAN;
  995.         newSizerRects:        TVRectList;
  996.         s:                    INTEGER;
  997.         delta:                VPoint;
  998.  
  999.     PROCEDURE NotifyNonPanes(theSubView: TView);
  1000.  
  1001.         BEGIN
  1002.         IF fPanes.GetSameItemNo(theSubView) = 0 THEN    { not a pane }
  1003.             theSubView.SuperViewChangedSize(delta, invalidate);
  1004.         END;
  1005.  
  1006.     BEGIN
  1007.     sizers := GetNumberOfSizers;
  1008.     panes := sizers + 1;
  1009.     checkMinimum := (((panes*fMinPaneSize) + (sizers*fSizerThickness)) <= height);
  1010.     {$IFC qDebug}
  1011.         IF NOT checkMinimum THEN
  1012.             ProgramBreak('THorizontalSizer.Resize: height too small for panes!!');
  1013.     {$ENDC}
  1014.  
  1015.     IF sizers = 0 THEN
  1016.         INHERITED Resize(width, height, invalidate)
  1017.     ELSE BEGIN
  1018.         oldHeight := fSize.v;
  1019.         IF (fSize.h <> width) OR (oldHeight <> height) THEN BEGIN
  1020.         (*    INHERITED Resize(width, height, FALSE);    { we’ll notify the subviews ourself } *)
  1021.             SetVPt(delta, width - fSize.h, height - fSize.v);
  1022.             fSize.h := width;
  1023.             fSize.v := height;
  1024.             InvalidateFocus;                                {Must re-focus because size changed}
  1025.             gApplication.InvalidateCursorRgn;                {Must re-calc cursor rgn.}
  1026.     
  1027.             IF sizers > 0 THEN BEGIN                        { subviews have been installed }
  1028.                 newSizerRects := TVRectList(fSizerRects.Clone);
  1029.                 IF oldHeight = height THEN BEGIN            { adjust width only }
  1030.                     FOR s := 1 TO sizers DO
  1031.                         newSizerRects.AtCoordPut(s, kRightCoord, width);
  1032.                     END
  1033.                 ELSE BEGIN                                    { need to adjust height as well }
  1034.                     previous := 0;
  1035.                     FOR s := 1 TO sizers DO BEGIN            { adjust each sizer rect }
  1036.                         aSizerRect := GetSizerRect(s);
  1037.                         paneHeight := aSizerRect.top + delta.v - previous;
  1038.                         IF checkMinimum & (paneHeight < fMinPaneSize) THEN
  1039.                             paneHeight := fMinPaneSize;
  1040.                         IF checkMinimum & (s = 1) & (paneHeight < kMinLogHeight) THEN
  1041.                             paneHeight := kMinLogHeight;
  1042.                         SetVRect(aSizerRect, 0, previous + paneHeight, width,
  1043.                             previous + paneHeight + fSizerThickness);
  1044.                         newSizerRects.AtPut(s, aSizerRect);
  1045.                         previous := aSizerRect.bottom;
  1046.                         END;
  1047.                     IF checkMinimum THEN BEGIN                { check last pane }
  1048.                         previous := height;
  1049.                         s := sizers;
  1050.                         REPEAT
  1051.                             aSizerRect := newSizerRects.At(s);
  1052.                             paneHeight := previous - aSizerRect.bottom;
  1053. (*                            paneHeight := fMinPaneSize + ((paneHeight - fMinPaneSize) DIV
  1054.                                 kLineHeight) * kLineHeight; *)
  1055.                             IF paneHeight < fMinPaneSize THEN paneHeight := fMinPaneSize;
  1056.                             SetVRect(aSizerRect, 0, previous - paneHeight - fSizerThickness, width,
  1057.                                 previous - paneHeight);
  1058.                             newSizerRects.AtPut(s, aSizerRect);
  1059.                             previous := aSizerRect.top;
  1060.                             s := s - 1;
  1061.                         UNTIL s = 0;
  1062.                         END;
  1063.                     END;
  1064.                 SetPanes(newSizerRects, invalidate);
  1065.                 newSizerRects.Free;                            { discard temp sizerRects object }
  1066.                 END;
  1067.     
  1068.             EachSubView(NotifyNonPanes);
  1069.             END;
  1070.         END;
  1071.     END;
  1072.  
  1073. {$S ADoCommand}
  1074.  
  1075. PROCEDURE THorizontalSizer.SetPane(whichSizer: INTEGER; itsSizerRect: VRect); OVERRIDE;
  1076. { A single sizer rectangle has moved, so adjust the panes above and below it }
  1077.  
  1078.     VAR
  1079.         oldSizerRect:        VRect;
  1080.         vp:                    VPoint;
  1081.         setbacks:             VRect;
  1082.         deltaV:                VCoordinate;
  1083.         firstView:            TView;
  1084.         secondView:            TView;
  1085.  
  1086.     BEGIN
  1087.     oldSizerRect := GetSizerRect(whichSizer);
  1088.     deltaV := itsSizerRect.top - oldSizerRect.top;
  1089.     SetSizerRect(whichSizer, itsSizerRect);
  1090.  
  1091.     firstView := TView(fPanes.At(whichSizer));
  1092.     vp := firstView.fSize;    (* can’t use GetExtent ’cause TScrollers add in translation *)
  1093.     firstView.Resize(vp.h, vp.v + deltaV, kInvalidate);
  1094.  
  1095.     secondView := TView(fPanes.At(whichSizer+1));
  1096.     vp := secondView.fSize;
  1097.     secondView.Resize(vp.h, vp.v - deltaV, kInvalidate);
  1098.     setbacks := fSetbacks.At(whichSizer+1);
  1099.     vp := secondView.fLocation;
  1100.     secondView.Locate(vp.h, itsSizerRect.bottom + setbacks.top, kInvalidate);
  1101.     END;
  1102.  
  1103. {$S ANonRes}
  1104.  
  1105. PROCEDURE THorizontalSizer.SetPanes(newSizerRects: TVRectList; invalidate: BOOLEAN); OVERRIDE;
  1106.  
  1107.     VAR
  1108.         itsSizerRect:        VRect;
  1109.         vr:                    VRect;
  1110.         setbacks:             VRect;
  1111.         theView:            TView;
  1112.         s:                    INTEGER;
  1113.         sizers:                INTEGER;
  1114.         pTop:                VCoordinate;
  1115.         pBottom:            VCoordinate;
  1116.  
  1117.     BEGIN
  1118.     sizers := newSizerRects.GetSize;
  1119.     pTop := 0;
  1120.     FOR s := 1 TO sizers+1 DO BEGIN
  1121.         IF s > sizers THEN
  1122.             pBottom := fSize.v                        { last pane }
  1123.         ELSE BEGIN                                    { not the last pane }
  1124.             IF invalidate THEN BEGIN                { invalidate old sizer rectangle }
  1125.                 itsSizerRect := GetSizerRect(s);
  1126.                 InvalidVRect(itsSizerRect);
  1127.                 END;
  1128.             itsSizerRect := newSizerRects.At(s);
  1129.             IF invalidate THEN                        { invalidate new sizer rectangle }
  1130.                 InvalidVRect(itsSizerRect);
  1131.             pBottom := itsSizerRect.top;
  1132.             fSizerRects.AtPut(s, itsSizerRect);
  1133.             END;                    
  1134.         theView := TView(fPanes.At(s));
  1135.         setbacks := fSetbacks.At(s);
  1136.         theView.Locate(itsSizerRect.left + setbacks.left, pTop + setbacks.top, invalidate);
  1137.         theView.Resize(itsSizerRect.right - setbacks.left - setbacks.right,
  1138.                        pBottom - pTop - setbacks.top - setbacks.bottom, invalidate);
  1139.         pTop := itsSizerRect.bottom;
  1140.         END;
  1141. (*    IF invalidate THEN ForceRedraw; *)
  1142.     END;
  1143.  
  1144. {$S ADoCommand}
  1145.  
  1146. PROCEDURE THorizontalSizer.TrackConstrain(anchorPoint, previousPoint: VPoint;
  1147.                                           VAR nextPoint: VPoint); OVERRIDE;
  1148. { Constrain mouse tracking to my interior, allowing for the minimum pane size }
  1149.  
  1150.     VAR
  1151.         theMin:                LONGINT;
  1152.         theMax:                LONGINT;
  1153.  
  1154.     BEGIN
  1155.     theMin := fMinPaneSize;
  1156.     theMax := fSize.v - theMin;
  1157.     IF nextPoint.v < theMin
  1158.         THEN nextPoint.v := theMin
  1159.         ELSE nextPoint.v := Min(nextPoint.v, theMax);
  1160.     END;
  1161.  
  1162. {-------------------------- TSizerCommand ----------------------}
  1163.  
  1164. {$S ASelCommand}
  1165.  
  1166. PROCEDURE TSizerCommand.ISizerCommand(itsSizerView: TSizerView; whichSizer: INTEGER;
  1167.                                       whichWay: VHSelect);
  1168.  
  1169.     VAR
  1170.         sizerRect:             VRect;
  1171.  
  1172.     BEGIN
  1173.     ICommand(cSizeViews, itsSizerView.fDocument, itsSizerView, NIL);
  1174.     fCausesChange := FALSE;
  1175.     fConstrainsMouse := TRUE;
  1176.     fSizerView := itsSizerView;
  1177.     fSplitDir := whichWay;
  1178.     fWhichSizer := whichSizer;
  1179.  
  1180.     sizerRect := fSizerView.GetSizerRect(whichSizer);
  1181.     fOldSizerRect := sizerRect;
  1182.     IF fSplitDir = kSplitVertically
  1183.         THEN fNewEdge := sizerRect.left
  1184.         ELSE fNewEdge := sizerRect.top;
  1185.     END;                                        { TSizerCommand.ISizerCommand }
  1186.  
  1187. {$S ADoCommand}
  1188.  
  1189. FUNCTION TSizerCommand.TrackMouse(aTrackPhase: TrackPhase; VAR anchorPoint, previousPoint,
  1190.                                   nextPoint: VPoint; mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  1191. { Arguments are in fSizerView coordinates }
  1192.  
  1193.     VAR
  1194.         aVRect:             VRect;
  1195.  
  1196.     BEGIN
  1197.     TrackMouse := SELF;                            { keep on trackin’ }
  1198.     IF fSplitDir = kSplitVertically
  1199.         THEN fNewEdge := nextPoint.h
  1200.         ELSE fNewEdge := nextPoint.v;
  1201.  
  1202.     IF aTrackPhase = trackRelease THEN BEGIN
  1203.         aVRect := fOldSizerRect;
  1204.         IF PtInVRect(nextPoint, aVRect) THEN
  1205.             TrackMouse := NIL;
  1206.         END;
  1207.     END;                                        { TSizerCommand.TrackMouse }
  1208.  
  1209. {$S ADoCommand}
  1210.  
  1211. PROCEDURE TSizerCommand.TrackFeedback(anchorPoint, nextPoint: VPoint; turnItOn,
  1212.                                       mouseDidMove: BOOLEAN); OVERRIDE;
  1213.  
  1214.     VAR
  1215.         viewedRect:         Rect;
  1216.         pState:             PenState;
  1217.         aQDPt:                Point;
  1218.  
  1219.     BEGIN
  1220.     IF mouseDidMove THEN
  1221.         BEGIN
  1222.         GetPenState(pState);
  1223.         SetPenForFeedback(nextPoint);
  1224.  
  1225.         fSizerView.GetQDExtent(viewedRect);
  1226.  
  1227.         IF fSplitDir = kSplitVertically THEN
  1228.             BEGIN
  1229.             MoveTo(nextPoint.h, viewedRect.top);
  1230.             Line(0, viewedRect.bottom - viewedRect.top);
  1231.             END
  1232.         ELSE
  1233.             BEGIN
  1234.             MoveTo(viewedRect.left, nextPoint.v);
  1235.             Line(viewedRect.right - viewedRect.left, 0);
  1236.             END;
  1237.         SetPenState(pState);
  1238.         END;
  1239.     END;                                                { TSizerCommand.TrackFeedback }
  1240.  
  1241. {$S ADoCommand}
  1242.  
  1243. PROCEDURE TSizerCommand.TrackConstrain(anchorPoint, previousPoint: VPoint;
  1244.                                        VAR nextPoint: VPoint); OVERRIDE;
  1245.  
  1246.     VAR
  1247.         theMin:                LONGINT;
  1248.         theMax:                LONGINT;
  1249.         temp:                LONGINT;
  1250.         minSizerPane:        VCoordinate;
  1251.  
  1252.     BEGIN
  1253.     minSizerPane := fSizerView.GetMinPaneLength + fSizerView.GetSizerThickness;
  1254.     theMin := (fWhichSizer * minSizerPane) + ((fWhichSizer-1) * fSizerView.GetSizerThickness);
  1255.     { don’t let sizer rect overlap preceding ones }
  1256.     temp := fSizerView.GetSizerCoord(fWhichSizer-1, kGetMaxCoord);
  1257.     theMin := Max(theMin, temp+minSizerPane);
  1258.     theMin := Max(theMin, kMinLogHeight);
  1259.  
  1260.     IF fSplitDir = kSplitVertically
  1261.         THEN temp := fSizerView.fSize.h
  1262.         ELSE temp := fSizerView.fSize.v;
  1263.  
  1264.     theMax := temp - ((fSizerView.GetNumberOfPanes-fWhichSizer) * minSizerPane);
  1265.     { don’t let sizer rect overlap following ones }
  1266.     temp := fSizerView.GetSizerCoord(fWhichSizer+1, kGetMinCoord);
  1267.     theMax := Min(theMax, temp-minSizerPane);
  1268.  
  1269.     IF fSplitDir = kSplitVertically THEN BEGIN
  1270.         IF nextPoint.h < theMin
  1271.             THEN nextPoint.h := theMin
  1272.             ELSE nextPoint.h := MIN(nextPoint.h, theMax);
  1273.         END
  1274.     ELSE BEGIN
  1275.         IF nextPoint.v < theMin THEN
  1276.             nextPoint.v := theMin
  1277.         ELSE
  1278.             nextPoint.v := MIN(nextPoint.v, theMax);
  1279.         END;
  1280. (*        nextPoint.v := theMax - ((theMax - nextPoint.v + (kLineHeight DIV 2)) DIV kLineHeight) *
  1281.             kLineHeight;
  1282.         IF nextPoint.v < theMin THEN nextPoint.v := nextPoint.v + kLineHeight; *)
  1283.     END;                                                { TSizerCommand.TrackConstrain }
  1284.  
  1285. {$S ADoCommand}
  1286.  
  1287. PROCEDURE TSizerCommand.DoIt; OVERRIDE;
  1288.  
  1289.     VAR
  1290.         tempRect:            VRect;
  1291.  
  1292.     BEGIN
  1293.     tempRect := fSizerView.MakeSizerRect(fNewEdge);
  1294.     fSizerView.SetPane(fWhichSizer, tempRect);
  1295.     END;                                                { TSizerCommand.DoIt }
  1296.  
  1297. {$S ADoCommand}
  1298.  
  1299. PROCEDURE TSizerCommand.UndoIt; OVERRIDE;
  1300.  
  1301.     VAR
  1302.         tempRect:            VRect;
  1303.         
  1304.     BEGIN
  1305.     tempRect := fOldSizerRect;
  1306.     fSizerView.SetPane(fWhichSizer, tempRect);
  1307.     END;                                                { TSizerCommand.UndoIt }
  1308.  
  1309. {$S ADoCommand}
  1310.  
  1311. PROCEDURE TSizerCommand.RedoIt; OVERRIDE;
  1312.  
  1313.     BEGIN
  1314.     DoIt;
  1315.     END;                                                { TSizerCommand.RedoIt }
  1316.  
  1317. PROCEDURE TSizerCommand.SetPenForFeedback(aPoint: VPoint);
  1318. { Set the pen pattern and size for showing feedback when tracking at the given point }
  1319.  
  1320.     BEGIN
  1321.     PenPat(black);
  1322.     PenSize(1, 1);
  1323.     END;
  1324.  
  1325. {$S AFields}
  1326.  
  1327. PROCEDURE TSizerCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  1328.                                                    fieldType: INTEGER)); OVERRIDE;
  1329.  
  1330.     BEGIN
  1331.     DoToField('TSizerCommand', NIL, bClass);
  1332.     DoToField('fSizerView', @fSizerView, bObject);
  1333.     DoToField('fNewEdge', @fNewEdge, bLongint);
  1334.     DoToField('fOldSizerRect', @fOldSizerRect, bVRect);
  1335.     DoToField('fSplitDir', @fSplitDir, bByte);
  1336.     DoToField('fWhichSizer', @fWhichSizer, bInteger);
  1337.     INHERITED Fields(DoToField);
  1338.     END;
  1339.  
  1340.  
  1341. {---------------------- TSplitterCommand ----------------------}
  1342.  
  1343. {$S ASelCommand}
  1344.  
  1345. PROCEDURE TSplitterCommand.ISplitterCommand(itsSizerView: TSizerView);
  1346. { Track over the entire SizerView }
  1347.  
  1348.     BEGIN
  1349.     ISizerCommand(itsSizerView, 0, itsSizerView.GetSplitDirection);
  1350.     fCanUndo := FALSE;        { Sorry, folks! }
  1351.     END;
  1352.  
  1353. {$S ADoCommand}
  1354.  
  1355. PROCEDURE TSplitterCommand.TrackConstrain(anchorPoint, previousPoint: VPoint;
  1356.                                           VAR nextPoint: VPoint); OVERRIDE;
  1357.  
  1358.     BEGIN
  1359.     { do nothing: tracking will be constrained to fSizerView. }
  1360.     END;
  1361.  
  1362. PROCEDURE TSplitterCommand.DoIt; OVERRIDE;
  1363.  
  1364.     VAR
  1365.         tempRect:        VRect;
  1366.         itsSetbacks:    VRect;
  1367.         paneToSplit:    TView;
  1368.         newPane:        TView;
  1369.         splitter:        TSplitter;
  1370.         scroller:        TScroller;
  1371.         whichPane:        INTEGER;
  1372.         temp:            LONGINT;
  1373.  
  1374.     BEGIN
  1375.     { figure out which pane the tracker stopped in }
  1376.     tempRect := fSizerView.MakeSizerRect(fNewEdge);
  1377.     {$Push} {$H-}
  1378.     paneToSplit := fSizerView.FindPaneAt(tempRect.topLeft);
  1379.     {$Pop}
  1380.  
  1381.     IF paneToSplit <> NIL THEN BEGIN    { found a pane to split }
  1382.         whichPane := fSizerView.FindPane(paneToSplit);
  1383.         newPane := CloneAView(paneToSplit);
  1384.         IF (Member(newPane, TScroller)) & (whichPane = 1) THEN
  1385.             BEGIN    { remove scrollbar offset for splitter control from new pane }
  1386.             splitter := fSizerView.fSplitter;
  1387.             scroller := TScroller(newPane);
  1388.             temp := splitter.GetThickness;
  1389.             WITH scroller.fSBarOffsets DO
  1390.                 IF fSplitDir = h
  1391.                     THEN top := top - temp
  1392.                     ELSE left := left - temp;
  1393.             END;
  1394.         itsSetbacks := fSizerView.fSetbacks.At(whichPane); { just copy split pane's setbacks }
  1395.         fSizerView.AddPane(newPane, fNewEdge, itsSetbacks);
  1396.         fSizerView.ForceRedraw;
  1397.         END;
  1398.     END;
  1399.  
  1400. {$S ADoCommand}
  1401.  
  1402. PROCEDURE TSplitterCommand.SetPenForFeedback(aPoint: VPoint); OVERRIDE;
  1403.  
  1404.     BEGIN
  1405.     IF fSizerView.IsValidSplitPt(aPoint)
  1406.         THEN PenPat(black)
  1407.         ELSE PenPat(ltGray);
  1408.     PenSize(1, 1);
  1409.     END;
  1410.  
  1411. FUNCTION TSplitterCommand.TrackMouse(aTrackPhase: TrackPhase;
  1412.                                      VAR anchorPoint, previousPoint, nextPoint: VPoint;
  1413.                                      mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  1414. { Arguments are in fSizerView coordinates }
  1415.  
  1416.     BEGIN
  1417.     TrackMouse := SELF;                            { keep on trackin’ }
  1418.     IF fSplitDir = kSplitVertically
  1419.         THEN fNewEdge := nextPoint.h
  1420.         ELSE fNewEdge := nextPoint.v;
  1421.  
  1422.     IF aTrackPhase = trackRelease THEN
  1423.         IF NOT fSizerView.IsValidSplitPt(nextPoint) THEN    { can’t split here }
  1424.             TrackMouse := NIL;                    { …so just forget it }
  1425.     END;                                        { TSplitterCommand.TrackMouse }
  1426.  
  1427. {$S AFields}
  1428.  
  1429. PROCEDURE TSplitterCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  1430.                                             fieldType: INTEGER)); OVERRIDE;
  1431.  
  1432.     BEGIN
  1433.     DoToField('TSplitterCommand', NIL, bClass);
  1434.     INHERITED Fields(DoToField);
  1435.     END;
  1436.  
  1437. {-------------------------- TSplitter ----------------------}
  1438.  
  1439. {$S AOpen}
  1440.  
  1441. PROCEDURE TSplitter.IRes(itsDocument: TDocument; itsSuperView: TView;
  1442.                          VAR itsParams: Ptr); OVERRIDE;
  1443.  
  1444.     BEGIN
  1445.     IF qDebug & (NOT Member(itsSuperView, TSizerView)) THEN
  1446.         ProgramBreak('Splitter’s superview must be a TSizerView!');
  1447.     fSizerView := NIL;
  1448.  
  1449.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1450.  
  1451.     IFinish(itsSuperView);
  1452.     END;
  1453.  
  1454. PROCEDURE TSplitter.ISplitter(itsDocument: TDocument; itsSuperview: TView;
  1455.                               itsLocation: VPoint; itsSize: VPoint);
  1456.  
  1457.     BEGIN
  1458.     IF qDebug & (NOT Member(itsSuperView, TSizerView)) THEN
  1459.         ProgramBreak('Splitter’s superview must be a TSizerView!');
  1460.  
  1461.     fSizerView := NIL;
  1462.     IControl(itsSuperView, itsLocation, itsSize, sizeRelSuperView, sizeRelSuperView);
  1463.  
  1464.     IFinish(itsSuperView);
  1465.     ViewEnable(TRUE, kDontRedraw);
  1466.     END;
  1467.  
  1468. PROCEDURE TSplitter.IFinish(itsSuperView: TView);
  1469. { Finish up initialization by setting the fSizerView and fLocDeterminer fields }
  1470.  
  1471.     BEGIN
  1472.     fSizerView := TSizerView(itsSuperView);
  1473.     IF fSizerView.GetSplitDirection = v THEN BEGIN
  1474.         fLocDeterminer[v] := kLocationVaries;
  1475.         fLocDeterminer[h] := kLocationFixed;
  1476.         END
  1477.     ELSE BEGIN    { h }
  1478.         fLocDeterminer[h] := kLocationVaries;
  1479.         fLocDeterminer[v] := kLocationFixed;
  1480.         END;
  1481.     fSizerView.fSplitter := SELF;
  1482.     END;
  1483.  
  1484. {$S ASelCommand}
  1485.  
  1486. FUNCTION TSplitter.DoMouseCommand(VAR theMouse: Point; VAR info: EventInfo;
  1487.                                   VAR hysteresis: Point): TCommand; OVERRIDE;
  1488. { Override to return a TSplitterCommand. theMouse is in local view coordinates }
  1489.  
  1490.     VAR
  1491.         aSplitterCommand:    TSplitterCommand;
  1492.  
  1493.     BEGIN
  1494.     IF fSizerView <> NIL THEN BEGIN
  1495.         NEW(aSplitterCommand);
  1496.         FailNIL(aSplitterCommand);
  1497.         aSplitterCommand.ISplitterCommand(fSizerView);
  1498.         DoMouseCommand := aSplitterCommand;
  1499.         END
  1500.     ELSE
  1501.         DoMouseCommand := INHERITED DoMouseCommand(theMouse, info, hysteresis);
  1502.     END;
  1503.  
  1504. {$S ARes}
  1505. PROCEDURE TSplitter.Draw(area: Rect); OVERRIDE;
  1506. { Default is just a black rectangle, like a splitter well }
  1507.  
  1508.     BEGIN
  1509.     ControlArea(area);
  1510.     PenPat(black);
  1511.     PenMode(patCopy);
  1512.     PaintRect(area);
  1513.  
  1514.     INHERITED Draw(area);
  1515.     END;
  1516.  
  1517. {$S ADoCommand}
  1518. FUNCTION TSplitter.GetThickness: LONGINT;
  1519.  
  1520.     BEGIN
  1521.     {$IFC qDebug}
  1522.     IF fSizerView = NIL THEN ProgramBreak('Splitter has no fSizerView!')
  1523.     ELSE
  1524.     {$ENDC}
  1525.  
  1526.     IF fSizerView.GetSplitDirection = h
  1527.         THEN GetThickness := fSize.v
  1528.         ELSE GetThickness := fSize.h;
  1529.     END;
  1530.  
  1531. {$S ANonRes}
  1532.  
  1533. PROCEDURE TSplitter.SuperViewChangedSize(delta: VPoint; invalidate: BOOLEAN); OVERRIDE;
  1534.  
  1535.     VAR
  1536.         loc:    VPoint;
  1537.  
  1538.     BEGIN
  1539.     IF fLocDeterminer[h] | fLocDeterminer[v] THEN BEGIN
  1540.         loc := fLocation;
  1541.         IF fLocDeterminer[h] THEN
  1542.             loc.h := loc.h + delta.h;        { compute its new horizontal position }
  1543.         IF fLocDeterminer[v] THEN
  1544.             loc.v := loc.v + delta.v;        { compute its new vertical position }
  1545.         Locate(loc.h, loc.v, invalidate);    { move it }
  1546.         END;
  1547.     END;
  1548.  
  1549. {$S AFields}
  1550.  
  1551. PROCEDURE TSplitter.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  1552.                                                fieldType: INTEGER)); OVERRIDE;
  1553.     CONST
  1554.         kFixedString = 'Fixed';
  1555.         kVariesString = 'Varies';
  1556.  
  1557.     VAR
  1558.         str:    Str255;
  1559.  
  1560.     BEGIN
  1561.     DoToField('TSplitter', NIL, bClass);
  1562.     DoToField('fSizerView', @fSizerView, bObject);
  1563.     IF fLocDeterminer[h]
  1564.         THEN str := kVariesString
  1565.         ELSE str := kFixedString;
  1566.     DoToField('fLocDeterminer[h]', @str, bString);
  1567.     IF fLocDeterminer[v]
  1568.         THEN str := kVariesString
  1569.         ELSE str := kFixedString;
  1570.     DoToField('fLocDeterminer[v]', @str, bString);
  1571.     INHERITED Fields(DoToField);
  1572.     END;
  1573.  
  1574. {---------------------- TDeSizerCommand ----------------------}
  1575.  
  1576. {$S ASelCommand}
  1577.  
  1578. PROCEDURE TDeSizerCommand.IDeSizerCommand(itsSizerView: TSizerView; whichSizer: INTEGER;
  1579.                                           whichWay: VHSelect);
  1580. { Track over the entire SizerView, but show gray when too close to neighboring panes,
  1581.   and show white when close to the SizerView ends. }
  1582.  
  1583.     VAR
  1584.         vr1, vr2:        VRect;
  1585.         minPaneSize:    VCoordinate;
  1586.  
  1587.     BEGIN
  1588.     ISizerCommand(itsSizerView, whichSizer, whichWay);
  1589.     fCanUndo := FALSE;                    { Sorry, folks! }
  1590.  
  1591.     fResizeOK := TRUE;
  1592.     { build the rectangle in which a valid resize can occur }
  1593.     vr1 := itsSizerView.GetSizerRect(whichSizer-1);
  1594.     vr2 := itsSizerView.GetSizerRect(whichSizer+1);
  1595.     minPaneSize := itsSizerView.GetMinPaneLength;
  1596.     IF whichWay = h THEN BEGIN
  1597.         fResizeRect.top := vr1.bottom + minPaneSize;
  1598.         fResizeRect.left := vr1.left;
  1599.         fResizeRect.bottom := vr2.top - minPaneSize;
  1600.         fResizeRect.right := vr2.right;
  1601.         END
  1602.     ELSE BEGIN { v }
  1603.         fResizeRect.left := vr1.right + minPaneSize;
  1604.         fResizeRect.top := vr1.top;
  1605.         fResizeRect.right := vr2.left - minPaneSize;
  1606.         fResizeRect.bottom := vr2.bottom;
  1607.         END;
  1608.     END;
  1609.  
  1610. {$S ADoCommand}
  1611.  
  1612. PROCEDURE TDeSizerCommand.TrackConstrain(anchorPoint, previousPoint: VPoint;
  1613.                                        VAR nextPoint: VPoint); OVERRIDE;
  1614.  
  1615.     BEGIN
  1616.     { Don’t change nextPoint, so tracking is constrained to fSizerView }
  1617.  
  1618.     { Determine whether nextPoint is a valid place to which to move the sizer bars }
  1619.     {$Push} {$H-}
  1620.     fResizeOK := PtInVRect(nextPoint, fResizeRect);    {$Pop}
  1621.     END;
  1622.  
  1623. PROCEDURE TDeSizerCommand.SetPenForFeedback(aPoint: VPoint); OVERRIDE;
  1624.  
  1625.     BEGIN
  1626.     {$Push} {$H-}
  1627.     IF PtInVRect(aPoint, fResizeRect) THEN    {$Pop}
  1628.         PenPat(black)
  1629.     ELSE IF fSizerView.IsValidSplitPt(aPoint) THEN
  1630.         PenPat(ltGray)
  1631.     ELSE
  1632.         PenPat(white);
  1633.     PenSize(1, 1);
  1634.     END;
  1635.  
  1636. PROCEDURE TDeSizerCommand.DoIt; OVERRIDE;
  1637. { If final mouse position was at either end of the SizerView, delete the sizer bars. }
  1638.  
  1639.     VAR
  1640.         tempRect:            VRect;
  1641.         paneToDelete:        INTEGER;
  1642.  
  1643.     FUNCTION IsVpt1LessThan2(vpt1, vpt2: VPoint): BOOLEAN;
  1644.  
  1645.         BEGIN
  1646.         IF fSplitDir = h
  1647.             THEN IsVpt1LessThan2 := (vpt1.v < vpt2.v)
  1648.             ELSE IsVpt1LessThan2 := (vpt1.h < vpt2.h);
  1649.         END;
  1650.  
  1651.     BEGIN
  1652.     tempRect := fSizerView.MakeSizerRect(fNewEdge);
  1653.     IF NOT fSizerView.IsValidSplitPt(tempRect.topLeft) THEN    { sizer dragged to end }
  1654.         BEGIN                                    { delete sizer rect and pane }
  1655.         {$Push} {$H-}
  1656.         IF IsVpt1LessThan2(tempRect.topLeft, fOldSizerRect.topLeft)    {$Pop}
  1657.             THEN paneToDelete := fWhichSizer        { delete pane before sizer }
  1658.             ELSE paneToDelete := fWhichSizer + 1;    { delete pane after sizer }
  1659.         IF fSizerView.DeletePane(paneToDelete, fWhichSizer) = NIL THEN ;
  1660.         END
  1661.     ELSE                                        { just move sizer rect }
  1662.         fSizerView.SetPane(fWhichSizer, tempRect);
  1663.     END;                                        { TDeSizerCommand.DoIt }
  1664.  
  1665. FUNCTION TDeSizerCommand.TrackMouse(aTrackPhase: TrackPhase; VAR anchorPoint, previousPoint,
  1666.                                     nextPoint: VPoint; mouseDidMove: BOOLEAN): TCommand; OVERRIDE;
  1667. { Arguments are in fSizerView coordinates }
  1668.  
  1669.     VAR
  1670.         cmd:             TCommand;
  1671.  
  1672.     BEGIN
  1673.     cmd := INHERITED TrackMouse(aTrackPhase, anchorPoint, previousPoint, nextPoint, mouseDidMove);
  1674.     IF aTrackPhase = trackRelease THEN
  1675.         IF (NOT fResizeOK) &                        { not a valid resizing area }
  1676.            (fSizerView.IsValidSplitPt(nextPoint))    { not a sizer deletion area }
  1677.             THEN cmd := NIL;
  1678.     TrackMouse := cmd;
  1679.     END;                                        { TDeSizerCommand.TrackMouse }
  1680.  
  1681. {$S AFields}
  1682.  
  1683. PROCEDURE TDeSizerCommand.Fields(PROCEDURE DoToField(fieldName: Str255; fieldAddr: Ptr;
  1684.                                         fieldType: INTEGER)); OVERRIDE;
  1685.  
  1686.     BEGIN
  1687.     DoToField('TDeSizerCommand', NIL, bClass);
  1688.     DoToField('fResizeRect', @fResizeRect, bVRect);
  1689.     DoToField('fResizeOK', @fResizeOK, bBoolean);
  1690.     INHERITED Fields(DoToField);
  1691.     END;
  1692.  
  1693.