home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sibdemo3.zip / SOURCE.DAT / SOURCE / SPCC / OUTLINE.PAS < prev    next >
Pascal/Delphi Source File  |  1998-05-21  |  75KB  |  2,618 lines

  1.  
  2. {╔══════════════════════════════════════════════════════════════════════════╗
  3.  ║                                                                          ║
  4.  ║     Sibyl Portable Component Classes                                     ║
  5.  ║                                                                          ║
  6.  ║     Copyright (C) 1995,97 SpeedSoft Germany,   All rights reserved.      ║
  7.  ║                                                                          ║
  8.  ╚══════════════════════════════════════════════════════════════════════════╝}
  9.  
  10. Unit OutLine;
  11.  
  12.  
  13. Interface
  14.  
  15. {$IFDEF OS2}
  16. Uses Os2Def,PmWin,PmStdDlg;
  17. {$ENDIF}
  18.  
  19. {$IFDEF Win95}
  20. Uses WinDef,WinUser,WinGDI,CommCtrl;
  21. {$ENDIF}
  22.  
  23. Uses Messages,SysUtils,Classes,Forms,Graphics;
  24.  
  25.  
  26. Const
  27.     InvalidIndex = {MaxLongInt;} -1;
  28.     tab = Chr(9);
  29.  
  30. Type
  31.     TAttachMode = (oaAdd, oaAddChild, oaInsert);
  32.  
  33.  
  34. Type
  35.     EOutlineError=Class(Exception);
  36.     EOutlineNodeError=Class(EOutlineError);
  37.     EOutlineIndexError=Class(EOutlineError);
  38.  
  39.     TOutline=Class;
  40.     TOutlineNode=Class;
  41.  
  42.     POutlineRecord=^TOutlineRecord;
  43.     TOutlineRecord=Record
  44.          {$IFDEF OS2}
  45.          RecordCore:RecordCore;
  46.          {$ENDIF}
  47.          {$IFDEF Win95}
  48.          RecordCore:TV_ITEM;
  49.          {$ENDIF}
  50.          Node:TOutlineNode;  {Extra Data}
  51.     End;
  52.  
  53.  
  54.     TOutlineNode=Class
  55.       Private
  56.          FTreeRec:POutlineRecord;
  57.          FCaption:PChar;
  58.          FData:Pointer;
  59.          FIndex:LongInt;
  60.          FExpanded:Boolean;
  61.          FParent:TOutlineNode;
  62.          FOutline:TOutline;
  63.          FSubNodes:TList;
  64.          FPictureLeaf:TBitmap;
  65.          FPictureOpen:TBitmap;
  66.          FPictureClosed:TBitmap;
  67.          Function GetCaption:String;
  68.          Procedure SetCaption(NewCaption:String);
  69.          Function Index2Node(idx:LongInt):TOutlineNode;
  70.          Function GetNode(idx:LongInt):TOutlineNode;
  71.          Function GetNodeCount:LongInt;
  72.          Function InsertNode(OldNode,NewNode:TOutlineNode):LongInt;
  73.          Function AddNode(NewNode:TOutlineNode):LongInt;
  74.          Procedure Setup(RecordOrder:Pointer);
  75.          Function HasChildren:Boolean;
  76.          Function GetLastIndex:LongInt;
  77.          Function GetTopItem:LongInt;
  78.          Function ReIndex(idx,Max:LongInt):LongInt;
  79.          Function HasVisibleParent:Boolean;
  80.          Function GetVisibleParent:TOutlineNode;
  81.          Function GetFullPath:String;
  82.          Function GetLevel:LongInt;
  83.          Function GetList:TList;
  84.          Procedure SetLastValidIndex;
  85.          Function GetDataItem(Value:Pointer):LongInt;
  86.          Function GetTextItem(Const Value:String):LongInt;
  87.          Procedure ClearSubNodes;
  88.          Procedure SetExpanded(Value:Boolean);
  89.          Procedure UpdatePicture;
  90.          Procedure UpdateChildPictures;
  91.          Procedure SetPictureLeaf(NewBitmap:TBitmap);
  92.          Procedure SetPictureOpen(NewBitmap:TBitmap);
  93.          Procedure SetPictureClosed(NewBitmap:TBitmap);
  94.          Function GetItemRect:TRect;
  95.       Protected
  96.          Constructor Create(Owner:TOutline);
  97.          Property OutLine:TOutline Read FOutline;
  98.          Property List:TList Read GetList;
  99.       Public
  100.          Property Items[Index:LongInt]:TOutlineNode Read GetNode;
  101.          Property ItemCount:LongInt Read GetNodeCount;
  102.          Destructor Destroy;Override;
  103.          Procedure FullExpand;
  104.          Procedure FullCollapse;
  105.          Procedure Expand;
  106.          Procedure Collapse;
  107.          Procedure Clear;
  108.          Function GetFirstChild:LongInt;
  109.          Function GetLastChild:LongInt;
  110.          Function GetNextChild(Value:LongInt):LongInt;
  111.          Function GetPrevChild(Value:LongInt):LongInt;
  112.          Property Text:String Read GetCaption Write SetCaption;
  113.          Property Data:Pointer Read FData Write FData;
  114.          Property parent:TOutlineNode Read FParent;
  115.          Property Index:LongInt Read FIndex;
  116.          Property IsVisible:Boolean Read HasVisibleParent;
  117.          Property HasItems:Boolean Read HasChildren;
  118.          Property Level:LongInt Read GetLevel;
  119.          Property Expanded:Boolean Read FExpanded Write SetExpanded;
  120.          Property FullPath:String Read GetFullPath;
  121.          Property TopItem:LongInt Read GetTopItem;
  122.          Property PictureLeaf:TBitmap Read FPictureLeaf Write SetPictureLeaf;
  123.          Property PictureClosed:TBitmap Read FPictureClosed Write SetPictureClosed;
  124.          Property PictureOpen:TBitmap Read FPictureOpen Write SetPictureOpen;
  125.          Property ItemRect:TRect read GetItemRect;
  126.     End;
  127.     TOutlineNodeClass = Class Of TOutlineNode;
  128.  
  129.  
  130. {$M+}
  131.     TOutLineItemFocusEvent=Procedure(Sender:TObject;Index:LongInt) Of Object;
  132.     TOutLineItemSelectEvent=Procedure(Sender:TObject;Index:LongInt) Of Object;
  133.     TOutlineChangeEvent=Procedure(Sender:TObject;Index:LongInt) Of Object;
  134. {$M-}
  135.  
  136.     TOutline=Class(TControl)
  137.       Private
  138.          FLines:TStrings;
  139.          FShowDragRects:Boolean;
  140.          FDragRectValid:Boolean;
  141.          FDragRect:TRect;
  142.          FDragSelected:TOutlineNode;
  143.          FInitLines:TStringList;
  144.          FNodeClass:TOutlineNodeClass;
  145.          FRootNode:TOutlineNode;
  146.          FGoodNode:TOutlineNode;
  147.          FUpdateCount:LongInt;
  148.          FSeparator:String;
  149.          FCurItem:TOutlineNode;
  150.          FStrings:TStrings;
  151.          FBorderStyle:TBorderStyle;
  152.          FPictureList:TBitmapList;
  153.          FPictureOpen:TBitmap;
  154.          FPictureClosed:TBitmap;
  155.          FPictureLeaf:TBitmap;
  156.          FInitNodes:TList;
  157.          FPlusMinusSize:TSize;
  158.          FPictureSize:TSize;
  159.          FShowTreeLines:Boolean;
  160.          FShowPlusMinus:Boolean;
  161.          FTreeLineWidth:LongInt;
  162.          FTreeIndent:LongInt;
  163.          FLineSpacing:LongInt;
  164.          FIndexInsert:Boolean;
  165.          FDragging:Boolean;
  166.          FFocusNode:TOutlineNode;
  167.          FPopupPos:TPoint;
  168.          {$IFDEF Win95}
  169.          FHim:HIMAGELIST;
  170.          FSelItem:Pointer;
  171.          {$ENDIF}
  172.          FOnExpand:TOutlineChangeEvent;
  173.          FOnCollapse:TOutlineChangeEvent;
  174.          FOnItemFocus:TOutLineItemFocusEvent;
  175.          FOnItemSelect:TOutLineItemSelectEvent;
  176.          FOnClick:TNotifyEvent;
  177.          FChangeLock:Boolean;
  178.          {$IFDEF OS2}
  179.          Procedure WMPaint(Var Msg:TMessage);Message WM_PAINT;
  180.          {$ENDIF}
  181.          Function AddPicture(NewBitmap:TBitmap):TBitmap;
  182.          Procedure SetBorderStyle(NewBorder:TBorderStyle);
  183.          Procedure SetPlusMinusSize(NewSize:TSize);
  184.          Procedure SetPictureSize(NewSize:TSize);
  185.          Procedure UpdateNode(Node:TOutlineNode);
  186.          Procedure SetCnrInfo;
  187.          Procedure SetShowTreeLines(NewValue:Boolean);
  188.          Procedure SetShowPlusMinus(NewValue:Boolean);
  189.          Procedure SetTreeLineWidth(NewValue:LongInt);
  190.          Procedure SetTreeIndent(Value:LongInt);
  191.          Procedure SetLineSpacing(Value:LongInt);
  192.          Procedure SetupTree;
  193.          Procedure SetupImageList;
  194.          Procedure SetupSubNodes(Node:TOutlineNode);
  195.          Function GetSelectedNode:TOutlineNode;
  196.          Procedure SetSelectedNode(NewSelected:TOutlineNode);
  197.          Function GetSelectedItem:LongInt;
  198.          Procedure SetSelectedItem(NewSelected:LongInt);
  199.          Function GetPictureClosed:TBitmap;
  200.          Procedure SetPictureClosed(NewBitmap:TBitmap);
  201.          Function GetPictureOpen:TBitmap;
  202.          Procedure SetPictureOpen(NewBitmap:TBitmap);
  203.          Function GetPictureLeaf:TBitmap;
  204.          Procedure SetPictureLeaf(NewBitmap:TBitmap);
  205.          Function Attach(idx:LongInt;Const Text:String;Data:Pointer;Mode:TAttachMode):LongInt;
  206.          Function Get(idx:LongInt):TOutlineNode;
  207.          Function GetItemCount:LongInt;
  208.          Procedure SetGoodNode(Node:TOutlineNode);
  209.          Function GetLines:TStrings;
  210.          Procedure SetLines(AStrings:TStrings);
  211.          Procedure DrawDragRect;
  212.       Protected
  213.          Procedure GetClassData(Var ClassData:TClassData);Override;
  214.          Procedure CreateParams(Var Params:TCreateParams);Override;
  215.          Procedure SetupComponent;Override;
  216.          Procedure Click;Virtual;
  217.          Procedure SetupShow;Override;
  218.          Procedure DestroyWnd;Override;
  219.          Procedure ParentNotification(Var Msg:TMessage);Override;
  220.          Procedure ItemFocus(Index:LongInt);Virtual;
  221.          Procedure ItemSelect(Index:LongInt);Virtual;
  222.          Procedure ScanEvent(Var KeyCode:TKeyCode;RepeatCount:Byte);Override;
  223.          Procedure MouseDown(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);Override;
  224.          Procedure MouseMove(ShiftState:TShiftState;X,Y:LongInt);Override;
  225.          Procedure MouseUp(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);Override;
  226.          Procedure MouseClick(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);Override;
  227.          Procedure MouseDblClick(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);Override;
  228.          Function AttachNode(Node:TOutlineNode;Const Text:String;Data:Pointer;Mode:TAttachMode):TOutlineNode;
  229.          Procedure indexerror;Virtual;
  230.          Procedure NodeError;Virtual;
  231.          Procedure ItemChanged(Var Msg:TMessage;Expanded:Boolean);Virtual;
  232.          Procedure Expand(Index:LongInt);Virtual;
  233.          Procedure Collapse(Index:LongInt);Virtual;
  234.          Procedure DragOver(Source:TObject;X,Y:LongInt;State:TDragState;Var Accept:Boolean);Override;
  235.          Procedure DragDrop(Source:TObject;X,Y:LongInt);Override;
  236.       Public
  237.          Destructor Destroy;Override;
  238.          Procedure BeginUpdate;
  239.          Procedure EndUpdate;
  240.          Function Add(Index:LongInt;Const Text:String):LongInt;
  241.          Function AddObject(Index:LongInt;Const Text:String;Data:Pointer):LongInt;
  242.          Function AddChild(Index:LongInt;Const Text:String):LongInt;
  243.          Function AddChildObject(Index:LongInt;Const Text:String;Data:Pointer):LongInt;
  244.          Function Insert(Index:LongInt;Const Text:String):LongInt;
  245.          Function InsertObject(Index:LongInt;Const Text:String;Data:Pointer):LongInt;
  246.          Procedure Delete(Index:LongInt);
  247.          Procedure FullExpand;
  248.          Procedure FullCollapse;
  249.          Function GetDataItem(Value:Pointer):LongInt;
  250.          Function GetTextItem(Const Value:String):LongInt;
  251.          Procedure Clear;
  252.          Function NodeFromPoint(pt:TPoint):TOutlineNode;
  253.          Procedure ReadSCUResource(Const ResName:TResourceName;Var Data;DataLen:LongInt);Override;
  254.          Function WriteSCUResource(Stream:TResourceStream):Boolean;Override;
  255.          Property NodeClass:TOutlineNodeClass Read FNodeClass Write FNodeClass;
  256.          Property SelectedNode:TOutlineNode Read GetSelectedNode Write SetSelectedNode;
  257.          Property SelectedItem:LongInt Read GetSelectedItem Write SetSelectedItem;
  258.          Property Items[Index:LongInt]:TOutlineNode Read Get; Default;
  259.          Property ItemCount:LongInt Read GetItemCount;
  260.          Property ItemSeparator:String Read FSeparator Write FSeparator;
  261.          Property XAlign;
  262.          Property XStretch;
  263.          Property YAlign;
  264.          Property YStretch;
  265.       Published
  266.          Property Align;
  267.          Property Color;
  268.          Property BorderStyle:TBorderStyle Read FBorderStyle Write SetBorderStyle;
  269.          Property PenColor;
  270.          Property DragCursor;
  271.          Property DragMode;
  272.          Property Enabled;
  273.          Property Font;
  274.          Property Lines:TStrings Read GetLines Write SetLines;
  275.          Property LineSpacing:LongInt Read FLineSpacing Write SetLineSpacing;
  276.          Property ParentColor;
  277.          Property ParentPenColor;
  278.          Property ParentFont;
  279.          Property ParentShowHint;
  280.          Property PictureClosed:TBitmap Read GetPictureClosed Write SetPictureClosed;
  281.          Property PictureLeaf:TBitmap Read GetPictureLeaf Write SetPictureLeaf;
  282.          Property PictureOpen:TBitmap Read GetPictureOpen Write SetPictureOpen;
  283.          Property PictureSize:TSize Read FPictureSize Write SetPictureSize;
  284.          Property PlusMinusSize:TSize Read FPlusMinusSize Write SetPlusMinusSize;
  285.          Property PopupMenu;
  286.          Property ShowDragRects:Boolean Read FShowDragRects Write FShowDragRects;
  287.          Property ShowHint;
  288.          Property ShowPlusMinus:Boolean Read FShowPlusMinus Write SetShowPlusMinus;
  289.          Property ShowTreeLines:Boolean Read FShowTreeLines Write SetShowTreeLines;
  290.          Property TabOrder;
  291.          Property TabStop;
  292.          Property TreeIndent:LongInt Read FTreeIndent Write SetTreeIndent;
  293.          Property TreeLineWidth:LongInt Read FTreeLineWidth Write SetTreeLineWidth;
  294.          Property Visible;
  295.          Property ZOrder;
  296.  
  297.          Property OnCanDrag;
  298.          Property OnClick:TNotifyEvent Read FOnClick Write FOnClick;
  299.          Property OnCollapse:TOutlineChangeEvent Read FOnCollapse Write FOnCollapse;
  300.          Property OnDblClick;
  301.          Property OnDragDrop;
  302.          Property OnDragOver;
  303.          Property OnEndDrag;
  304.          Property OnEnter;
  305.          Property OnExit;
  306.          Property OnExpand:TOutlineChangeEvent Read FOnExpand Write FOnExpand;
  307.          Property OnFontChange;
  308.          Property OnItemFocus:TOutLineItemFocusEvent Read FOnItemFocus Write FOnItemFocus;
  309.          Property OnItemSelect:TOutLineItemSelectEvent Read FOnItemSelect Write FOnItemSelect;
  310.          Property OnMouseClick;
  311.          Property OnMouseDblClick;
  312.          Property OnMouseDown;
  313.          Property OnMouseMove;
  314.          Property OnMouseUp;
  315.          Property OnSetupShow;
  316.          Property OnStartDrag;
  317.     End;
  318.  
  319.  
  320. Function InsertOutline(parent:TControl;Left,Bottom,Width,Height:LongInt;Hint:String):TOutline;
  321.  
  322.  
  323. Implementation
  324.  
  325.  
  326. Function InsertOutline(parent:TControl;Left,Bottom,Width,Height:LongInt;Hint:String):TOutline;
  327. Begin
  328.      Result.Create(parent);
  329.      Result.SetWindowPos(Left,Bottom,Width,Height);
  330.      Result.TabStop := True;
  331.      Result.Hint := Hint;
  332.      Result.parent := parent;
  333. End;
  334.  
  335.  
  336. Type
  337.     {$IFDEF OS2}
  338.     pRecordOrder=PRecordCore;
  339.     {$ENDIF}
  340.     {$IFDEF Win95}
  341.     pRecordOrder=POutlineRecord;
  342.     {$ENDIF}
  343.  
  344. {
  345. ╔═══════════════════════════════════════════════════════════════════════════╗
  346. ║                                                                           ║
  347. ║ Speed-Pascal/2 Version 2.0                                                ║
  348. ║                                                                           ║
  349. ║ Speed-Pascal Component Classes (SPCC)                                     ║
  350. ║                                                                           ║
  351. ║ This section: TOutlineBitmap Class Implementation                         ║
  352. ║                                                                           ║
  353. ║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited !       ║
  354. ║                                                                           ║
  355. ╚═══════════════════════════════════════════════════════════════════════════╝
  356. }
  357.  
  358. Type
  359.     TOutlineBitmap=Class(TBitmap)
  360.       {$IFDEF Win95}
  361.       Private
  362.          FHimlIndex:LongInt;
  363.       Private
  364.          Function CreateBitmapFromClass:LongWord;
  365.       {$ENDIF}
  366.     End;
  367.  
  368.  
  369. {$IFDEF Win95}
  370. Function TOutlineBitmap.CreateBitmapFromClass:LongWord;
  371. Begin
  372.      Result := CopyImage(Handle,IMAGE_BITMAP,Width,Height,LR_COPYRETURNORG);
  373. End;
  374. {$ENDIF}
  375.  
  376.  
  377. {
  378. ╔═══════════════════════════════════════════════════════════════════════════╗
  379. ║                                                                           ║
  380. ║ Speed-Pascal/2 Version 2.0                                                ║
  381. ║                                                                           ║
  382. ║ Speed-Pascal Component Classes (SPCC)                                     ║
  383. ║                                                                           ║
  384. ║ This section: TOutlineNode Class Implementation                           ║
  385. ║                                                                           ║
  386. ║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited !       ║
  387. ║                                                                           ║
  388. ╚═══════════════════════════════════════════════════════════════════════════╝
  389. }
  390.  
  391. {$IFDEF Win95}
  392. Const
  393.     CMA_FIRST:LongWord=0;
  394. {$ENDIF}
  395.  
  396.  
  397. Procedure SetupNode(Node:TOutlineNode);
  398. Begin
  399.      {$IFDEF OS2}
  400.      Node.FTreeRec^.RecordCore.pszTree := Node.FCaption;
  401.      {$ENDIF}
  402.      {$IFDEF Win95}
  403.      Node.FTreeRec^.RecordCore.Mask := TVIF_TEXT Or TVIF_PARAM;
  404.      Node.FTreeRec^.RecordCore.pszText := Node.FCaption;
  405.      If Node.FCaption <> Nil
  406.      Then Node.FTreeRec^.RecordCore.cchTextMax := Length(Node.FCaption^)+1
  407.      Else Node.FTreeRec^.RecordCore.cchTextMax := 0;
  408.      {$ENDIF}
  409.  
  410.      Node.UpdatePicture;
  411. End;
  412.  
  413.  
  414. Procedure RemoveRecord(Node:TOutlineNode; Update:Boolean);
  415. Var  Flags:LongWord;
  416.      TreeHandle:LongWord;
  417.      AParent:TOutlineNode;
  418. Begin
  419.      If Node = Nil Then Exit;
  420.      If Node.FTreeRec = Nil Then Exit;
  421.  
  422.      TreeHandle := Node.FOutline.Handle;
  423.      {$IFDEF OS2}
  424.      If Node.FTreeRec^.RecordCore.pTreeItemDesc <> Nil
  425.        Then Dispose(Node.FTreeRec^.RecordCore.pTreeItemDesc);
  426.      {$ENDIF}
  427.  
  428.      If TreeHandle <> 0 Then
  429.      Begin
  430.           {$IFDEF OS2}
  431.           Flags := CMA_FREE;
  432.           If Update Then Flags := Flags Or CMA_INVALIDATE;
  433.           WinSendMsg(TreeHandle,CM_REMOVERECORD,LongWord(@Node.FTreeRec),
  434.                      MPFROM2SHORT(1,Flags));
  435.           {$ENDIF}
  436.           {$IFDEF Win95}
  437.           SendMessage(TreeHandle,TVM_DELETEITEM,0,
  438.                       LongWord(Node.FTreeRec^.RecordCore.hItem));
  439.           {$ENDIF}
  440.      End;
  441.  
  442.      {$IFDEF Win95}
  443.      Dispose(Node.FTreeRec);
  444.      {$ENDIF}
  445.      Node.FTreeRec := Nil;
  446.  
  447.      {Update parent Bitmap}
  448.      AParent := Node.parent;
  449.      If AParent <> Nil Then
  450.        If AParent <> Node.FOutline.FRootNode Then
  451.          If AParent.ItemCount = 1 Then AParent.UpdatePicture; {Node Is the Last}
  452. End;
  453.  
  454.  
  455. Procedure InsertRecord(NewNode:TOutlineNode; AParentRecord:POutlineRecord;
  456.                        RecordOrder:Pointer);
  457. Var  TreeHandle:LongWord;
  458.      Tree:TOutline;
  459.      AParent:TOutlineNode;
  460.      {$IFDEF OS2}
  461.      aRecordInsert:RECORDINSERT;
  462.      {$ENDIF}
  463.      {$IFDEF Win95}
  464.      tvins:TV_INSERTSTRUCT;
  465.      {$ENDIF}
  466. Begin
  467.      NewNode.FTreeRec^.Node := NewNode;
  468.      {specify where To Insert}
  469.      Tree := NewNode.FOutline;
  470.      TreeHandle := Tree.Handle;
  471.  
  472.      {$IFDEF OS2}
  473.      aRecordInsert.cb := SizeOf(RECORDINSERT);
  474.      aRecordInsert.pRecordOrder := RecordOrder;
  475.      aRecordInsert.ZOrder := CMA_TOP;
  476.      aRecordInsert.cRecordsInsert := 1;     //Number Of records
  477.      aRecordInsert.fInvalidateRecord := 1;  //Invalidate records
  478.      aRecordInsert.pRecordParent := Pointer(AParentRecord);
  479.  
  480.      {Insert Record}
  481.      WinSendMsg(TreeHandle,CM_INSERTRECORD,
  482.                 LongWord(NewNode.FTreeRec),LongWord(@aRecordInsert));
  483.  
  484.      {Expand Status}
  485.      If NewNode.FExpanded
  486.      Then WinSendMsg(TreeHandle,CM_EXPANDTREE, LongWord(NewNode.FTreeRec),0)
  487.      Else WinSendMsg(TreeHandle,CM_COLLAPSETREE, LongWord(NewNode.FTreeRec),0);
  488.      {$ENDIF}
  489.  
  490.      {$IFDEF Win95}
  491.      {specify where To Insert}
  492.      FillChar(tvins,SizeOf(tvins),0);
  493.      NewNode.FTreeRec^.RecordCore.LParam:=LParam(NewNode);
  494.  
  495.      tvins.Item:=NewNode.FTreeRec^.RecordCore;
  496.      If ((RecordOrder=Nil)Or(LongWord(RecordOrder)=CMA_FIRST)) Then tvins.hInsertAfter:=TVI_FIRST
  497.      Else tvins.hInsertAfter:=POutlineRecord(RecordOrder)^.RecordCore.hItem;
  498.      If AParentRecord=Nil Then tvins.hParent:=TVI_ROOT
  499.      Else tvins.hParent:=AParentRecord^.RecordCore.hItem;
  500.      NewNode.FTreeRec^.RecordCore.hItem:=
  501.        HTREEITEM(SendMessage(TreeHandle,TVM_INSERTITEM,0,LongWord(@tvins)));
  502.  
  503.      {Expand Status}
  504.      If NewNode.FExpanded
  505.      Then SendMessage(TreeHandle,TVM_EXPAND,TVE_EXPAND,
  506.                       LongWord(NewNode.FTreeRec^.RecordCore.hItem))
  507.      Else SendMessage(TreeHandle,TVM_EXPAND,TVE_COLLAPSE,
  508.                       LongWord(NewNode.FTreeRec^.RecordCore.hItem));
  509.      {$ENDIF}
  510.  
  511.      {Update parent Bitmap}
  512.      AParent := NewNode.parent;
  513.      If AParent <> Nil Then
  514.        If AParent <> Tree.FRootNode Then
  515.          If AParent.ItemCount = 1 Then AParent.UpdatePicture; {NewNode Is the 1st}
  516. End;
  517.  
  518.  
  519. Procedure AllocateRecord(Handle:LongWord;Var porec:POutlineRecord);
  520. Begin
  521.      //allocate Memory
  522.      {$IFDEF OS2}
  523.      porec:=Pointer(WinSendMsg(Handle,
  524.                                CM_ALLOCRECORD,
  525.                                {additional Info For OutlineRecord}
  526.                                SizeOf(TOutlineRecord)-SizeOf(RecordCore),
  527.                                1));          {allocate one Record}
  528.      {$ENDIF}
  529.      {$IFDEF Win95}
  530.      New(porec);
  531.      {$ENDIF}
  532. End;
  533.  
  534.  
  535. Constructor TOutlineNode.Create(Owner:TOutline);
  536. Begin
  537.      Inherited Create;
  538.                  
  539.      If Owner Is TOutline Then FOutline := TOutline(Owner)
  540.      Else Raise EOutlineError.Create(LoadNLSStr(SInvalidOutlineNodeOwner));
  541. End;
  542.  
  543.  
  544. Function TOutlineNode.GetCaption:String;
  545. Begin
  546.      If FCaption=Nil Then Result:=''
  547.      Else Result:=FCaption^;
  548. End;
  549.  
  550.  
  551. Procedure TOutlineNode.SetCaption(NewCaption:String);
  552. Begin
  553.      If NewCaption = Text Then Exit;
  554.  
  555.      If FCaption <> Nil Then FreeMem(FCaption,Length(FCaption^)+1);
  556.      If NewCaption <> '' Then
  557.      Begin
  558.           GetMem(FCaption, Length(NewCaption)+1);
  559.           FCaption^ := NewCaption;
  560.      End
  561.      Else FCaption := Nil;
  562.  
  563.      {$IFDEF OS2}
  564.      If FTreeRec <> Nil Then FTreeRec^.RecordCore.pszTree := FCaption;
  565.      {$ENDIF}
  566.      {$IFDEF Win95}
  567.      If FTreeRec <> Nil Then
  568.      Begin
  569.           FTreeRec^.RecordCore.pszText := FCaption;
  570.           If FCaption <> Nil
  571.           Then FTreeRec^.RecordCore.cchTextMax := Length(FCaption^)+1
  572.           Else FTreeRec^.RecordCore.cchTextMax := 0;
  573.      End;
  574.      {$ENDIF}
  575.  
  576.      FOutline.UpdateNode(Self);
  577. End;
  578.  
  579.  
  580. Procedure TOutlineNode.UpdatePicture;
  581. Var  Picture:TBitmap;
  582.      PictureHandle:LongWord;
  583. Begin
  584.      PictureHandle := 0;
  585.  
  586.      If ItemCount > 0 Then
  587.      Begin
  588.           If Expanded Then
  589.           Begin
  590.                If FPictureOpen <> Nil Then Picture := FPictureOpen
  591.                Else Picture := FOutline.FPictureOpen;
  592.  
  593.                {$IFDEF OS2}
  594.                If Picture <> Nil Then PictureHandle := Picture.Handle;
  595.  
  596.                With FTreeRec^.RecordCore Do
  597.                Begin
  598.                     If PictureHandle = 0 Then
  599.                     Begin
  600.                          If pTreeItemDesc <> Nil Then Dispose(pTreeItemDesc);
  601.                          pTreeItemDesc := Nil;
  602.                     End
  603.                     Else
  604.                     Begin
  605.                          If pTreeItemDesc = Nil Then New(pTreeItemDesc);
  606.                          pTreeItemDesc^.hbmExpanded := PictureHandle;
  607.                     End;
  608.                End;
  609.                {$ENDIF}
  610.           End
  611.           Else
  612.           Begin
  613.                If FPictureClosed <> Nil Then Picture := FPictureClosed
  614.                Else Picture := FOutline.FPictureClosed;
  615.  
  616.                {$IFDEF OS2}
  617.                If Picture <> Nil Then PictureHandle := Picture.Handle;
  618.  
  619.                With FTreeRec^.RecordCore Do
  620.                Begin
  621.                     If PictureHandle = 0 Then
  622.                     Begin
  623.                          If pTreeItemDesc <> Nil Then Dispose(pTreeItemDesc);
  624.                          pTreeItemDesc := Nil;
  625.                     End
  626.                     Else
  627.                     Begin
  628.                          If pTreeItemDesc = Nil Then New(pTreeItemDesc);
  629.                          pTreeItemDesc^.hbmCollapsed := PictureHandle;
  630.                     End;
  631.                End;
  632.                {$ENDIF}
  633.           End;
  634.      End
  635.      Else
  636.      Begin
  637.           If FPictureLeaf <> Nil Then Picture := FPictureLeaf
  638.           Else Picture := FOutline.FPictureLeaf;
  639.      End;
  640.  
  641.      If Picture <> Nil Then PictureHandle := Picture.Handle;
  642.  
  643.      {$IFDEF OS2}
  644.      FTreeRec^.RecordCore.hbmBitmap := PictureHandle;
  645.      {$ENDIF}
  646.  
  647.      {$IFDEF Win95}
  648.      If Picture = Nil Then
  649.      Begin
  650.          FTreeRec^.RecordCore.Mask := FTreeRec^.RecordCore.Mask And not
  651.                                       (TVIF_IMAGE Or TVIF_SELECTEDIMAGE);
  652.          FTreeRec^.RecordCore.iImage := 0;
  653.          FTreeRec^.RecordCore.iSelectedImage := 0;
  654.      End
  655.      Else
  656.      Begin
  657.          FTreeRec^.RecordCore.Mask := FTreeRec^.RecordCore.Mask
  658.                                       Or TVIF_IMAGE Or TVIF_SELECTEDIMAGE;
  659.          FTreeRec^.RecordCore.iImage := TOutlineBitmap(Picture).FHimlIndex;
  660.          FTreeRec^.RecordCore.iSelectedImage := TOutlineBitmap(Picture).FHimlIndex;
  661.      End;
  662.      {$ENDIF}
  663. End;
  664.  
  665.  
  666. Procedure TOutlineNode.UpdateChildPictures;
  667. Var  Node:TOutlineNode;
  668.      T:LongInt;
  669. Begin
  670.      If FSubNodes = Nil Then Exit;
  671.      For T := 0 To FSubNodes.Count-1 Do
  672.      Begin
  673.           Node := FSubNodes.Items[T];
  674.           Node.UpdatePicture;
  675.           {$IFDEF WIN32}
  676.           Node.FOutLine.UpdateNode(Node);
  677.           {$ENDIF}
  678.           Node.UpdateChildPictures;
  679.      End;
  680. End;
  681.  
  682.  
  683. Procedure TOutlineNode.SetPictureLeaf(NewBitmap:TBitmap);
  684. Begin
  685.      FPictureLeaf := FOutline.AddPicture(NewBitmap);    {Get local Copy}
  686.      If Not HasItems Then
  687.      Begin
  688.           UpdatePicture;
  689.           FOutline.UpdateNode(Self);
  690.      End;
  691. End;
  692.  
  693.  
  694. Procedure TOutlineNode.SetPictureOpen(NewBitmap:TBitmap);
  695. Begin
  696.      FPictureOpen := FOutline.AddPicture(NewBitmap);    {Get local Copy}
  697.      If HasItems And Expanded Then
  698.      Begin
  699.           UpdatePicture;
  700.           FOutline.UpdateNode(Self);
  701.      End;
  702. End;
  703.  
  704.  
  705. Procedure TOutlineNode.SetPictureClosed(NewBitmap:TBitmap);
  706. Begin
  707.      FPictureClosed := FOutline.AddPicture(NewBitmap);    {Get local Copy}
  708.      If HasItems And Not Expanded Then
  709.      Begin
  710.           UpdatePicture;
  711.           FOutline.UpdateNode(Self);
  712.      End;
  713. End;
  714.  
  715.  
  716. Function TOutlineNode.GetNode(idx:LongInt):TOutlineNode;
  717. Begin
  718.      Result := FSubNodes.Items[idx];
  719. End;
  720.  
  721.  
  722. Function TOutlineNode.GetNodeCount;
  723. Begin
  724.      If FSubNodes <> Nil Then Result := FSubNodes.Count
  725.      Else Result := 0;
  726. End;
  727.  
  728.  
  729. Function TOutlineNode.HasChildren:Boolean;
  730. Begin
  731.      Result := GetNodeCount > 0;
  732. End;
  733.  
  734.  
  735. Function TOutlineNode.GetLastIndex:LongInt;
  736. Begin
  737.      If ItemCount = 0 Then Result := Index
  738.      Else Result := TOutlineNode(FSubNodes.Last).GetLastIndex;
  739. End;
  740.  
  741.  
  742. Function TOutlineNode.GetTopItem:LongInt;
  743. Var  Node:TOutlineNode;
  744. Begin
  745.      Result := 0;
  746.      Node := Self;
  747.      While Node <> FOutline.FRootNode Do
  748.      Begin
  749.           If Node.parent = FOutline.FRootNode
  750.           Then Result := Node.Index;
  751.           Node := Node.parent;
  752.      End;
  753. End;
  754.  
  755.  
  756. Function TOutlineNode.Index2Node(idx:LongInt):TOutlineNode;
  757. Var  Node:TOutlineNode;
  758.      LastNode:TOutlineNode;
  759.      I:LongInt;
  760. Begin
  761.      If idx = Index Then
  762.      Begin
  763.           Result := Self;
  764.           Exit;
  765.      End;
  766.  
  767.      {Find Last Node, where Index <= idx}
  768.      LastNode := Nil;
  769.      For I := 0 To ItemCount-1 Do
  770.      Begin
  771.           Node := Items[I];
  772.           If Node.Index = InvalidIndex Then break;
  773.           If Node.Index > idx Then break;
  774.           LastNode := Node;
  775.      End;
  776.  
  777.      If LastNode <> Nil Then
  778.      Begin
  779.           Result := LastNode.Index2Node(idx);
  780.           Exit;
  781.      End;
  782.  
  783.      FOutline.indexerror;
  784. End;
  785.  
  786.  
  787. Function TOutlineNode.ReIndex(idx,Max:LongInt):LongInt;
  788. Var  Node:TOutlineNode;
  789.      I:LongInt;
  790. Begin
  791.      FIndex := idx;
  792.      FOutline.FGoodNode := Self;
  793.  
  794.      For I := 0 To ItemCount-1 Do
  795.      Begin
  796.           Node := Items[I];
  797.           idx := Node.ReIndex(idx+1,Max);
  798.  
  799.           If idx > Max Then                  {Stop reindexing}
  800.           Begin      {Next sibling Of Node gets invalid Index}
  801.                If I < ItemCount-1 Then Items[I+1].FIndex := InvalidIndex;
  802.                break;
  803.           End;
  804.      End;
  805.      Result := idx;
  806. End;
  807.  
  808.  
  809. Procedure TOutlineNode.SetLastValidIndex;
  810. Var  NextSibl:TOutlineNode;
  811.      idx:LongInt;
  812. Begin
  813.      idx := parent.FSubNodes.IndexOf(Self);
  814.  
  815.      If idx < parent.FSubNodes.Count-1 Then NextSibl := parent.Items[idx+1]
  816.      Else NextSibl := Nil;
  817.  
  818.      If NextSibl <> Nil Then NextSibl.FIndex := InvalidIndex;
  819.  
  820.      If parent <> FOutline.FRootNode Then parent.SetLastValidIndex;
  821. End;
  822.  
  823.  
  824. Function TOutlineNode.HasVisibleParent:Boolean;
  825. Begin
  826.      If parent = FOutline.FRootNode Then Result := True
  827.      Else If Parent<>Nil Then Result := parent.FExpanded And parent.HasVisibleParent
  828.      Else Result:=False;
  829. End;
  830.  
  831.  
  832. Function TOutlineNode.GetVisibleParent:TOutlineNode;
  833. Begin
  834.      If IsVisible Then Result := Self
  835.      Else If Parent<>Nil Then Result := parent.GetVisibleParent
  836.      Else Result:=Nil;
  837. End;
  838.  
  839.  
  840. Procedure TOutlineNode.SetExpanded(Value:Boolean);
  841. Begin
  842.      If Value = FExpanded Then Exit;
  843.  
  844.      If Value Then Expand
  845.      Else Collapse;
  846. End;
  847.  
  848.  
  849. Function TOutlineNode.GetFullPath:String;
  850. Begin
  851.    If Parent <> Nil Then
  852.    Begin
  853.       If Parent.Parent <> Nil Then
  854.         Result := Parent.GetFullPath + FOutline.FSeparator + Text
  855.       Else
  856.         Result := Text
  857.    End
  858.    Else Result := '';
  859. End;
  860.  
  861.  
  862. Procedure TOutlineNode.FullExpand;
  863. Var  Node:TOutlineNode;
  864.      I:LongInt;
  865. Begin
  866.      For I := 0 To ItemCount-1 Do
  867.      Begin
  868.           Node := Items[I];
  869.           Node.FullExpand;
  870.      End;
  871.      Expand;
  872. End;
  873.  
  874.  
  875. Procedure TOutlineNode.FullCollapse;
  876. Var  Node:TOutlineNode;
  877.      I:LongInt;
  878. Begin
  879.      Collapse;
  880.      For I := 0 To ItemCount-1 Do
  881.      Begin
  882.           Node := Items[I];
  883.           Node.FullCollapse;
  884.      End;
  885. End;
  886.  
  887.  
  888. Procedure TOutlineNode.Expand;
  889. Begin
  890.      FExpanded := True;
  891.      FOutline.Expand(FIndex);
  892.      If ItemCount = 0 Then Exit;
  893.      If FTreeRec = Nil Then Exit;
  894.      If FOutline.Handle = 0 Then Exit;
  895.  
  896.      FOutline.FChangeLock:=True;
  897.      {$IFDEF OS2}
  898.      WinSendMsg(FOutline.Handle,CM_EXPANDTREE,LongWord(FTreeRec),0);
  899.      {$ENDIF}
  900.  
  901.      {$IFDEF Win95}
  902.      SendMessage(FOutline.Handle,TVM_EXPAND,TVE_EXPAND,LongWord(FTreeRec^.RecordCore.hItem));
  903.      {$ENDIF}
  904.  
  905.      FOutline.FChangeLock:=False;
  906.  
  907.      If FTreeRec <> Nil Then UpdatePicture;
  908.  
  909.      FOutline.UpdateNode(Self);
  910. End;
  911.  
  912. Procedure TOutlineNode.Collapse;
  913. Begin
  914.      FExpanded := False;
  915.      FOutline.Collapse(FIndex);
  916.      If ItemCount = 0 Then Exit;
  917.      If FTreeRec = Nil Then Exit;
  918.      If FOutline.Handle = 0 Then Exit;
  919.  
  920.      FOutline.FChangeLock:=True;
  921.  
  922.      {$IFDEF OS2}
  923.      WinSendMsg(FOutline.Handle,CM_COLLAPSETREE,LongWord(FTreeRec),0);
  924.      {$ENDIF}
  925.  
  926.      {$IFDEF Win95}
  927.      SendMessage(FOutline.Handle,TVM_EXPAND,TVE_COLLAPSE,LongWord(FTreeRec^.RecordCore.hItem));
  928.      {$ENDIF}
  929.  
  930.      FOutline.FChangeLock:=False;
  931.  
  932.      If FTreeRec <> Nil Then UpdatePicture;
  933.  
  934.      FOutline.UpdateNode(Self);
  935. End;
  936.  
  937.  
  938. Function TOutlineNode.GetFirstChild:LongInt;
  939. Begin
  940.      Result := InvalidIndex;
  941.      If ItemCount = 0 Then Exit;
  942.      Result := Items[0].Index;
  943. End;
  944.  
  945.  
  946. Function TOutlineNode.GetLastChild:LongInt;
  947. Begin
  948.      Result := InvalidIndex;
  949.      If ItemCount = 0 Then Exit;
  950.      Result := Items[ItemCount-1].Index;
  951. End;
  952.  
  953.  
  954. Function TOutlineNode.GetNextChild(Value:LongInt):LongInt;
  955. Var  idx:LongInt;
  956. Begin
  957.      Result := InvalidIndex;
  958.      If FSubNodes = Nil Then Exit;
  959.  
  960.      For idx := 0 To ItemCount - 2 Do  {0,1,2,...,N-2,_not_}
  961.      Begin
  962.           If Items[idx].Index = Value Then
  963.           Begin
  964.                Result := Items[idx + 1].Index;
  965.                Exit;
  966.           End;
  967.      End;
  968. End;
  969.  
  970.  
  971. Function TOutlineNode.GetPrevChild(Value:LongInt):LongInt;
  972. Var  idx:LongInt;
  973. Begin
  974.      Result := InvalidIndex;
  975.      If FSubNodes = Nil Then Exit;
  976.  
  977.      For idx := 1 To ItemCount - 1 Do  {_not_,1,2,...,N-1}
  978.      Begin
  979.           If Items[idx].Index = Value Then
  980.           Begin
  981.                Result := Items[idx + 1].Index;
  982.                Exit;
  983.           End;
  984.      End;
  985. End;
  986.  
  987.  
  988. Function TOutlineNode.GetLevel:LongInt;
  989. Begin
  990.      If Self = FOutline.FRootNode Then Result := 0
  991.      Else Result := parent.GetLevel + 1;
  992. End;
  993.  
  994.  
  995. Function TOutlineNode.GetList:TList;
  996. Begin
  997.      If FSubNodes = Nil Then FSubNodes.Create;
  998.      Result := FSubNodes;
  999. End;
  1000.  
  1001.  
  1002. Function TOutlineNode.InsertNode(OldNode,NewNode:TOutlineNode):LongInt;
  1003. Var  RecordOrder:pRecordOrder;
  1004.      I:LongInt;
  1005. Begin
  1006.      NewNode.FParent := Self;
  1007.  
  1008.      I := List.IndexOf(OldNode);
  1009.      List.Insert(I, NewNode);
  1010.  
  1011.      If I > 0 Then RecordOrder := Pointer(TOutlineNode(List.Items[I-1]).FTreeRec)
  1012.      Else LongWord(RecordOrder) := CMA_FIRST;
  1013.  
  1014.      If FOutline.FIndexInsert Then
  1015.      Begin
  1016.           NewNode.FIndex := OldNode.Index;
  1017.           FOutline.SetGoodNode(NewNode);
  1018.      End
  1019.      Else NewNode.FIndex := InvalidIndex;
  1020.      Result := NewNode.Index;
  1021.  
  1022.      NewNode.Setup(RecordOrder);
  1023. End;
  1024.  
  1025.  
  1026. Function TOutlineNode.AddNode(NewNode:TOutlineNode):LongInt;
  1027. Var  PrevNode:TOutlineNode;
  1028.      RecordOrder:pRecordOrder;
  1029. Begin
  1030.      NewNode.FParent := Self;
  1031.  
  1032.      If List.Count > 0 Then
  1033.      Begin
  1034.           PrevNode := TOutlineNode(List.Last);
  1035.           RecordOrder := Pointer(PrevNode.FTreeRec);
  1036.      End
  1037.      Else LongWord(RecordOrder) := CMA_FIRST;
  1038.  
  1039.      List.Add(NewNode);
  1040.  
  1041.      If FOutline.FIndexInsert Then
  1042.      Begin
  1043.           FOutline.SetGoodNode(Self);
  1044.           {force NewNode And successors have A correct Index}
  1045.           ReIndex(Index,MaxLongInt); {Time!}
  1046.           Result := NewNode.Index;
  1047.      End
  1048.      Else Result := InvalidIndex;
  1049.  
  1050.      NewNode.Setup(RecordOrder);
  1051. End;
  1052.  
  1053.  
  1054. Procedure TOutlineNode.Setup(RecordOrder:Pointer);
  1055. Var  TreeRec:POutlineRecord;
  1056. Begin
  1057.      If FOutline.Handle = 0 Then
  1058.      Begin
  1059.           {Show it With SetupTree}
  1060.           FOutline.FInitNodes := FOutline.FRootNode.FSubNodes;
  1061.           Exit;
  1062.      End;
  1063.      If FTreeRec = Nil Then AllocateRecord(FOutline.Handle,FTreeRec);
  1064.      SetupNode(Self);
  1065.  
  1066.      If parent = FOutline.FRootNode Then TreeRec := Nil
  1067.      Else TreeRec := parent.FTreeRec;
  1068.  
  1069.      InsertRecord(Self,TreeRec, pRecordOrder(RecordOrder));
  1070.      FOutline.SetupSubNodes(Self);
  1071. End;
  1072.  
  1073.  
  1074. Procedure TOutlineNode.ClearSubNodes;
  1075. Var  T:LongInt;
  1076. Begin
  1077.      If FSubNodes = Nil Then Exit;
  1078.      For T := FSubNodes.Count-1 DownTo 0 Do
  1079.      Begin
  1080.           Items[T].FParent := Nil;
  1081.           Items[T].Destroy;
  1082.      End;
  1083.  
  1084.      FSubNodes.Destroy;
  1085.      FSubNodes := Nil;
  1086. End;
  1087.  
  1088.  
  1089. Procedure TOutlineNode.Clear;
  1090. Begin
  1091.      FOutline.BeginUpdate;
  1092.      ClearSubNodes;
  1093.      FOutline.EndUpdate;
  1094. End;
  1095.  
  1096.  
  1097. Destructor TOutlineNode.Destroy;
  1098. Begin
  1099.      ClearSubNodes;
  1100.  
  1101.      If Self <> FOutline.FRootNode Then
  1102.      Begin
  1103.           RemoveRecord(Self, True);
  1104.  
  1105.           If FCaption <> Nil Then
  1106.           Begin
  1107.                FreeMem(FCaption,Length(FCaption^)+1);
  1108.                FCaption := Nil;
  1109.           End;
  1110.  
  1111.           If FParent <> Nil Then
  1112.             If FParent.FSubNodes <> Nil Then FParent.FSubNodes.Remove(Self);
  1113.  
  1114.           If FOutline.FCurItem = Self
  1115.           Then FOutline.FCurItem := FOutline.FRootNode;
  1116.      End;
  1117.  
  1118.      Inherited Destroy;
  1119. End;
  1120.  
  1121.  
  1122. Function TOutlineNode.GetDataItem(Value:Pointer):LongInt;
  1123. Var  I:LongInt;
  1124.      Node:TOutlineNode;
  1125. Begin
  1126.      If FData = Value Then
  1127.      Begin
  1128.           Result := FIndex;
  1129.           Exit;
  1130.      End;
  1131.  
  1132.      For I := 0 To ItemCount-1 Do
  1133.      Begin
  1134.           Node := Items[I];
  1135.           Result := Node.GetDataItem(Value);
  1136.           If Result > 0 Then Exit;
  1137.      End;
  1138.      Result := 0;
  1139. End;
  1140.  
  1141.  
  1142. Function TOutlineNode.GetTextItem(Const Value:String):LongInt;
  1143. Var  I:LongInt;
  1144.      Node:TOutlineNode;
  1145. Begin
  1146.      If Text = Value Then
  1147.      Begin
  1148.           Result := FIndex;
  1149.           Exit;
  1150.      End;
  1151.  
  1152.      For I := 0 To ItemCount-1 Do
  1153.      Begin
  1154.           Node := Items[I];
  1155.           Result := Node.GetTextItem(Value);
  1156.           If Result > 0 Then Exit;
  1157.      End;
  1158.      Result := 0;
  1159. End;
  1160.  
  1161. Function TOutlineNode.GetItemRect:TRect;
  1162. {$IFDEF OS2}
  1163. Var RecRect:QUERYRECORDRECT;
  1164. {$ENDIF}
  1165. Begin
  1166.      FillChar(result,sizeof(TRect),0);
  1167.      {$IFDEF OS2}
  1168.      RecRect.cb:=sizeof(QUERYRECORDRECT);
  1169.      RecRect.pRecord:=@FTreeRec^.RecordCore;
  1170.      RecRect.fRightSplitWindow:=0;
  1171.      RecRect.fsExtent:=CMA_ICON OR CMA_TEXT;
  1172.      WinSendMsg(FOutline.Handle,CM_QUERYRECORDRECT,LongWord(@Result),LongWord(@RecRect));
  1173.      {$ENDIF}
  1174. End;
  1175.  
  1176.  
  1177.  
  1178. {
  1179. ╔═══════════════════════════════════════════════════════════════════════════╗
  1180. ║                                                                           ║
  1181. ║ Speed-Pascal/2 Version 2.0                                                ║
  1182. ║                                                                           ║
  1183. ║ Speed-Pascal Component Classes (SPCC)                                     ║
  1184. ║                                                                           ║
  1185. ║ This section: TOutline Class Implementation                               ║
  1186. ║                                                                           ║
  1187. ║ (C) 1995,97 SpeedSoft. All rights reserved. Disclosure probibited !       ║
  1188. ║                                                                           ║
  1189. ╚═══════════════════════════════════════════════════════════════════════════╝
  1190. }
  1191.  
  1192. Type
  1193.     TOutlineStrings=Class(TStrings)
  1194.       Private
  1195.          OutLine:TOutline;
  1196.       Protected
  1197.          Function GetCount: LongInt; Override;
  1198.          Function Get(Index: LongInt): String; Override;
  1199.          Function GetObject(Index: LongInt): TObject; Override;
  1200.          Procedure PutObject(Index: LongInt; AObject: TObject); Override;
  1201.          Procedure indexerror;
  1202.       Public
  1203.          Procedure Assign(AStrings:TStrings); Override;
  1204.          Function Add(Const S: String): LongInt; Override;
  1205.          Procedure Delete(Index: LongInt); Override;
  1206.          Procedure Insert(Index: LongInt; Const S: String); Override;
  1207.          Procedure Clear; Override;
  1208.     End;
  1209.  
  1210.  
  1211. Function TOutlineStrings.GetCount:LongInt;
  1212. Begin
  1213.      Result := OutLine.ItemCount;
  1214. End;
  1215.  
  1216.  
  1217. Function TOutlineStrings.Get(Index:LongInt):String;
  1218. Var  Node:TOutlineNode;
  1219.      Level,I:LongInt;
  1220. Begin
  1221.      Node := OutLine.Items[Index+1];
  1222.      Level := Node.Level;
  1223.      Result := '';
  1224.      For I := 0 To Level-2 Do Result := Result + tab;
  1225.      Result := Result + Node.Text;
  1226. End;
  1227.  
  1228.  
  1229. Function TOutlineStrings.GetObject(Index:LongInt):TObject;
  1230. Begin
  1231.      Result := TObject(OutLine[Index + 1].Data);
  1232. End;
  1233.  
  1234.  
  1235. Procedure TOutlineStrings.PutObject(Index:LongInt; AObject:TObject);
  1236. Var  Node:TOutlineNode;
  1237. Begin
  1238.      Node := OutLine[Index + 1];
  1239.      Node.Data := Pointer(AObject);
  1240. End;
  1241.  
  1242.  
  1243. Procedure TOutlineStrings.Assign(AStrings:TStrings);
  1244. Begin
  1245.      OutLine.BeginUpdate;
  1246.      Inherited Assign(AStrings);
  1247.      OutLine.EndUpdate;
  1248. End;
  1249.  
  1250.  
  1251. Function TOutlineStrings.Add(Const S:String):LongInt;
  1252. Var  LastNode:TOutlineNode;
  1253.      s1:String;
  1254.      CountNodes,Level,LastLevel,I:LongInt;
  1255. Begin
  1256.      {Get Level from S}
  1257.      s1 := S;
  1258.      Level := 1;
  1259.      For I := 1 To Length(S) Do
  1260.      Begin
  1261.           If s1[1] In [' ',tab] Then
  1262.           Begin
  1263.                Inc(Level);
  1264.                System.Delete(s1,1,1);
  1265.           End
  1266.           Else break;
  1267.      End;
  1268.      {Get Last Node With Level-1 To Add A New Child}
  1269.      CountNodes := OutLine.ItemCount;
  1270.      If CountNodes > 0 Then LastNode := OutLine[CountNodes]
  1271.      Else LastNode := OutLine.FRootNode;
  1272.  
  1273.      LastLevel := LastNode.Level;
  1274.      If (Level - LastLevel > 1) Or (LastNode = OutLine.FRootNode) Then
  1275.      Begin
  1276.           If Level - LastLevel > 1 Then OutLine.NodeError;
  1277.      End
  1278.      Else
  1279.      Begin
  1280.           For I := LastLevel DownTo Level Do
  1281.           Begin
  1282.                LastNode := LastNode.parent;
  1283.                If LastNode = Nil Then OutLine.NodeError;
  1284.           End;
  1285.      End;
  1286.  
  1287.      Result := OutLine.AddChild(LastNode.Index, s1) - 1;
  1288. End;
  1289.  
  1290.  
  1291. Procedure TOutlineStrings.Delete(Index:LongInt);
  1292. Begin
  1293.      OutLine.Delete(Index + 1);
  1294. End;
  1295.  
  1296.  
  1297. Procedure TOutlineStrings.Insert(Index:LongInt;Const S:String);
  1298. Begin
  1299.      OutLine.Insert(Index + 1, S);
  1300. End;
  1301.  
  1302.  
  1303. Procedure TOutlineStrings.Clear;
  1304. Begin
  1305.      OutLine.Clear;
  1306. End;
  1307.  
  1308.  
  1309. Procedure TOutlineStrings.indexerror;
  1310. Begin
  1311.      OutLine.indexerror;
  1312. End;
  1313.  
  1314. /////////////////////////////////////////////////////////////////////////////
  1315.  
  1316. Procedure TOutline.SetBorderStyle(NewBorder:TBorderStyle);
  1317. Begin
  1318.      FBorderStyle := NewBorder;
  1319.      {$IFDEF OS2}
  1320.      SetCnrInfo;
  1321.      Invalidate;
  1322.      {$ENDIF}
  1323.      {$IFDEF Win95}
  1324.      RecreateWnd;
  1325.      {$ENDIF}
  1326. End;
  1327.  
  1328.  
  1329. Function TOutline.AddPicture(NewBitmap:TBitmap):TBitmap;
  1330. Var  idx:LongInt;
  1331. Begin
  1332.      If NewBitmap = Nil Then
  1333.      Begin
  1334.           Result := Nil;
  1335.           Exit;
  1336.      End;
  1337.  
  1338.      If FPictureList = Nil Then
  1339.      Begin
  1340.           FPictureList.Create;
  1341.           FPictureList.BitmapClass := TOutlineBitmap;
  1342.           FPictureList.Duplicates := False;
  1343.      End;
  1344.  
  1345.      idx := FPictureList.IndexOfOrigin(NewBitmap);
  1346.      If idx < 0 Then                                     {Not found}
  1347.      Begin
  1348.           idx := FPictureList.Add(NewBitmap);  {Create local Bitmap}
  1349.           SetupImageList;
  1350.      End;
  1351.      Result := TBitmap(FPictureList.Bitmaps[idx]);
  1352. End;
  1353.  
  1354.  
  1355. Procedure TOutline.SetPictureLeaf(NewBitmap:TBitmap);
  1356. Begin
  1357.      FPictureLeaf := AddPicture(NewBitmap);    {Get local Copy}
  1358.      SetCnrInfo;
  1359.      FRootNode.UpdateChildPictures;
  1360. End;
  1361.  
  1362.  
  1363. Procedure TOutline.SetPictureOpen(NewBitmap:TBitmap);
  1364. Begin
  1365.      FPictureOpen := AddPicture(NewBitmap);    {Get local Copy}
  1366.      SetCnrInfo;
  1367.      FRootNode.UpdateChildPictures;
  1368. End;
  1369.  
  1370.  
  1371. Procedure TOutline.SetPictureClosed(NewBitmap:TBitmap);
  1372. Begin
  1373.      FPictureClosed := AddPicture(NewBitmap);    {Get local Copy}
  1374.      SetCnrInfo;
  1375.      FRootNode.UpdateChildPictures;
  1376. End;
  1377.  
  1378.  
  1379. Function TOutline.GetPictureClosed:TBitmap;
  1380. Begin
  1381.      If FPictureClosed = Nil Then
  1382.      Begin
  1383.           FPictureClosed := TOutlineBitmap.Create;
  1384.           Include(FPictureClosed.ComponentState, csDetail);
  1385.      End;
  1386.      Result := FPictureClosed;
  1387. End;
  1388.  
  1389.  
  1390. Function TOutline.GetPictureOpen:TBitmap;
  1391. Begin
  1392.      If FPictureOpen = Nil Then
  1393.      Begin
  1394.           FPictureOpen := TOutlineBitmap.Create;
  1395.           Include(FPictureOpen.ComponentState, csDetail);
  1396.      End;
  1397.      Result := FPictureOpen;
  1398. End;
  1399.  
  1400.  
  1401. Function TOutline.GetPictureLeaf:TBitmap;
  1402. Begin
  1403.      If FPictureLeaf = Nil Then
  1404.      Begin
  1405.           FPictureLeaf := TOutlineBitmap.Create;
  1406.           Include(FPictureLeaf.ComponentState, csDetail);
  1407.      End;
  1408.      Result := FPictureLeaf;
  1409. End;
  1410.  
  1411.  
  1412. Procedure TOutline.GetClassData(Var ClassData:TClassData);
  1413. Begin
  1414.      Inherited GetClassData(ClassData);
  1415.  
  1416.      {$IFDEF OS2}
  1417.      ClassData.ClassULong := WC_CONTAINER;
  1418.      {$ENDIF}
  1419.      {$IFDEF Win95}
  1420.      CreateSubClass(ClassData,WC_TREEVIEW);
  1421.      {$ENDIF}
  1422. End;
  1423.  
  1424.  
  1425. Procedure TOutline.DestroyWnd;
  1426. Begin
  1427.      {Store Tree Items -> Linear List}
  1428.      If Handle <> 0 Then
  1429.        If FInitLines <> Nil Then FInitLines.Assign(FLines);
  1430.  
  1431.      If FRootNode <> Nil Then FRootNode.ClearSubNodes;
  1432.  
  1433.      Inherited DestroyWnd;
  1434. End;
  1435.  
  1436.  
  1437. Destructor TOutline.Destroy;
  1438. Begin
  1439.      FLines.Destroy;
  1440.      FLines := Nil;
  1441.      FInitLines.Destroy;
  1442.      FInitLines := Nil;
  1443.      FRootNode.Destroy;
  1444.      FRootNode := Nil;
  1445.  
  1446.      If FPictureList <> Nil Then
  1447.      Begin
  1448.           FPictureList.Destroy;  {Destroy local Bitmaps}
  1449.           FPictureList := Nil;
  1450.      End;
  1451.  
  1452.      {$IFDEF Win95}
  1453.      If FHim <> Nil Then ImageList_Destroy(FHim);
  1454.      FHim := Nil;
  1455.      {$ENDIF}
  1456.  
  1457.      Inherited Destroy;
  1458. End;
  1459.  
  1460.  
  1461. Procedure TOutline.SetupComponent;
  1462. Begin
  1463.      Inherited SetupComponent;
  1464.  
  1465.      Ownerdraw := False;
  1466.      Name := 'Outline';
  1467.      FRootNode.Create(Self);
  1468.      FRootNode.FIndex := 0;
  1469.      FRootNode.FParent := Nil;
  1470.      FGoodNode := FRootNode;
  1471.      FCurItem := FRootNode;
  1472.      FUpdateCount := 0;
  1473.      FSeparator := '\';
  1474.      FNodeClass := TOutlineNode;
  1475.  
  1476.      FLines := TOutlineStrings.Create;
  1477.      TOutlineStrings(FLines).OutLine := Self;
  1478.      FInitLines.Create;
  1479.  
  1480.      Height:=100;
  1481.      Width:=100;
  1482.      color:=clWindow;
  1483.      ParentPenColor:=False;
  1484.      ParentColor:=False;
  1485.      FBorderStyle:=bsSingle;
  1486.      FPlusMinusSize.CX:=16;
  1487.      FPlusMinusSize.CY:=16;
  1488.      FPictureSize.CX:=20;
  1489.      FPictureSize.CY:=20;
  1490.      FTreeLineWidth:=1;
  1491.      FShowTreeLines:=True;
  1492.      FShowPlusMinus:=True;
  1493.      FTreeIndent:=20;
  1494.      FLineSpacing:=0;
  1495. End;
  1496.  
  1497. Procedure TOutline.SetupShow;
  1498. Begin
  1499.      Inherited SetupShow;
  1500.      CreateCanvas;
  1501.  
  1502.      {Get information from StringList If available, Else Use invisible Tree}
  1503.      If FInitLines.Count > 0 Then
  1504.      Begin
  1505.           FLines.Assign(FInitLines);
  1506.           FInitLines.Clear;
  1507.      End;
  1508.  
  1509.      If Handle=0 Then Exit;
  1510.      {Set Options}
  1511.      SetCnrInfo;
  1512.      SetupImageList;
  1513.      SetupTree;
  1514. End;
  1515.  
  1516. {$IFDEF OS2}
  1517. Procedure TOutline.WMPaint(Var Msg:TMessage);
  1518. Var  rc1,rcupdate:TRect;
  1519. Begin
  1520.      If FBorderStyle = bsSingle Then
  1521.      Begin {Exclude border from Redraw area}
  1522.           rc1 := ClientRect;
  1523.           {????????????+-1}
  1524.           Inc(rc1.Right);
  1525.           Inc(rc1.Top);
  1526.           InflateRect(rc1,-2,-2);
  1527.  
  1528.           WinQueryUpdateRect(Handle,RECTL(rcupdate));
  1529.           WinValidateRect(Handle,RECTL(rcupdate),False);
  1530.           rcupdate := IntersectRect(rcupdate,rc1);
  1531.           WinInvalidateRect(Handle,RECTL(rcupdate),False);
  1532.      End;
  1533.  
  1534.      DefaultHandler(Msg);       {Do Default Action}
  1535.  
  1536.      If FBorderStyle = bsSingle Then
  1537.      Begin
  1538.           rc1 := ClientRect;
  1539.           DrawSystemBorder(Self,rc1,FBorderStyle); {overpaint Text ON the border}
  1540.      End;
  1541. End;
  1542. {$ENDIF}
  1543.  
  1544.  
  1545. Procedure TOutline.SetShowTreeLines(NewValue:Boolean);
  1546. Begin
  1547.      FShowTreeLines:=NewValue;
  1548.      SetCnrInfo;
  1549. End;
  1550.  
  1551.  
  1552. Procedure TOutline.SetShowPlusMinus(NewValue:Boolean);
  1553. Begin
  1554.      FShowPlusMinus:=NewValue;
  1555.      SetCnrInfo;
  1556. End;
  1557.  
  1558.  
  1559. Procedure TOutline.SetTreeLineWidth(NewValue:LongInt);
  1560. Begin
  1561.      FTreeLineWidth:=NewValue;
  1562.      SetCnrInfo;
  1563. End;
  1564.  
  1565.  
  1566. Procedure TOutline.SetPlusMinusSize(NewSize:TSize);
  1567. Begin
  1568.      FPlusMinusSize:=NewSize;
  1569.      SetCnrInfo;
  1570. End;
  1571.  
  1572.  
  1573. Procedure TOutline.SetPictureSize(NewSize:TSize);
  1574. Begin
  1575.      FPictureSize:=NewSize;
  1576.      SetCnrInfo;
  1577. End;
  1578.  
  1579.  
  1580. Procedure TOutline.SetTreeIndent(Value:LongInt);
  1581. Begin
  1582.      FTreeIndent:=Value;
  1583.      SetCnrInfo;
  1584. End;
  1585.  
  1586.  
  1587. Procedure TOutline.SetLineSpacing(Value:LongInt);
  1588. Begin
  1589.      FLineSpacing:=Value;
  1590.      SetCnrInfo;
  1591. End;
  1592.  
  1593.  
  1594. Procedure TOutline.SetCnrInfo;
  1595. {$IFDEF OS2}
  1596. Var acnrInfo:CNRINFO;
  1597.     Flags:LongWord;
  1598. {$ENDIF}
  1599. {$IFDEF Win95}
  1600. Var WinStyle:LongWord;
  1601. {$ENDIF}
  1602. Begin
  1603.      If Handle = 0 Then Exit;
  1604.  
  1605.      {$IFDEF OS2}
  1606.      FillChar(acnrInfo,SizeOf(CNRINFO),0);
  1607.      Flags:=CMA_FLWINDOWATTR;
  1608.  
  1609.      With acnrInfo Do
  1610.      Begin
  1611.           cb:=SizeOf(CNRINFO);
  1612.           If (FPictureClosed <> Nil) Or (FPictureOpen <> Nil) Or
  1613.              (FPictureLeaf <> Nil) Then
  1614.           Begin
  1615.                If Not FShowPlusMinus Then
  1616.                Begin
  1617.                     flWindowAttr:=CV_TREE Or CV_NAME;
  1618.                End
  1619.                Else flWindowAttr:=CV_TREE Or CV_ICON;
  1620.           End
  1621.           Else
  1622.           Begin
  1623.                If Not FShowPlusMinus Then
  1624.                Begin
  1625.                     flWindowAttr:=CV_TREE Or CV_NAME
  1626.                End
  1627.                Else flWindowAttr:=CV_TREE Or CV_TEXT;
  1628.           End;
  1629.  
  1630.           If FShowTreeLines Then flWindowAttr:=flWindowAttr Or CA_TREELINE;
  1631.  
  1632.           slTreeBitmapOrIcon.CX:=FPlusMinusSize.CX;
  1633.           slTreeBitmapOrIcon.CY:=FPlusMinusSize.CY;
  1634.           Flags:=Flags Or CMA_SLTREEBITMAPORICON;
  1635.  
  1636.           If (FPictureClosed <> Nil) Or (FPictureOpen <> Nil) Or
  1637.              (FPictureLeaf <> Nil) Then
  1638.           Begin
  1639.                slBitmapOrIcon.CX:=FPictureSize.CX;
  1640.                slBitmapOrIcon.CY:=FPictureSize.CY;
  1641.                Flags:=Flags Or CMA_SLBITMAPORICON;
  1642.                flWindowAttr:=flWindowAttr Or CA_DRAWBITMAP;
  1643.           End;
  1644.  
  1645.           { grayed
  1646.           If FCaption<>Nil Then
  1647.           Begin
  1648.                flWindowAttr:=flWindowAttr Or CA_CONTAINERTITLE Or CA_TITLESEPARATOR;
  1649.                pszCnrTitle:=FCaption;
  1650.                Flags:=Flags Or CMA_CNRTITLE;
  1651.           End;
  1652.           }
  1653.  
  1654.           If FTreeIndent<>0 Then
  1655.           Begin
  1656.                cxTreeIndent:=FTreeIndent;
  1657.                Flags:=Flags Or CMA_CXTREEINDENT;
  1658.           End;
  1659.  
  1660.           If FLineSpacing<>0 Then
  1661.           Begin
  1662.                cyLineSpacing:=FLineSpacing;
  1663.                Flags:=Flags Or CMA_LINESPACING;
  1664.           End;
  1665.  
  1666.           If FTreeLineWidth<>0 Then
  1667.           Begin
  1668.                cxTreeLine:=FTreeLineWidth;
  1669.                Flags:=Flags Or CMA_CXTREELINE;
  1670.           End;
  1671.      End;
  1672.      WinSendMsg(Handle,CM_SETCNRINFO,LongWord(@acnrInfo),Flags);
  1673.      {$ENDIF}
  1674.  
  1675.      {$IFDEF Win95}
  1676.      WinStyle:=GetWindowLong(Handle,GWL_STYLE);
  1677.      If FShowTreeLines Then WinStyle:=WinStyle Or TVS_HASLINES Or TVS_LINESATROOT
  1678.      Else WinStyle:=WinStyle And Not (TVS_HASLINES Or TVS_LINESATROOT);
  1679.      If FShowPlusMinus Then WinStyle:=WinStyle Or TVS_HASBUTTONS
  1680.      Else WinStyle:=WinStyle And Not TVS_HASBUTTONS;
  1681.      SetWindowLong(Handle,GWL_STYLE,WinStyle);
  1682.      Invalidate;
  1683.      {$ENDIF}
  1684. End;
  1685.  
  1686.  
  1687. Procedure TOutline.SetupSubNodes(Node:TOutlineNode);
  1688. Var T:LongInt;
  1689.     WorkNode,ParentNode,PrevNode:TOutlineNode;
  1690.     P:Pointer;
  1691. Begin
  1692.      If Handle=0 Then Exit;
  1693.      If Node.FSubNodes=Nil Then Exit;
  1694.      {Create All subnodes}
  1695.      ParentNode:=Node;
  1696.      PrevNode:=Nil;
  1697.      For T:=0 To Node.FSubNodes.Count-1 Do
  1698.      Begin
  1699.           WorkNode:=Node.FSubNodes.Items[T];
  1700.           If WorkNode.FTreeRec=Nil Then
  1701.           Begin
  1702.                AllocateRecord(Handle,WorkNode.FTreeRec);
  1703.                SetupNode(WorkNode);
  1704.           End;
  1705.  
  1706.           If PrevNode=Nil
  1707.           Then
  1708.           Begin
  1709.                LongWord(P):=CMA_FIRST;
  1710.                InsertRecord(WorkNode,ParentNode.FTreeRec,P)
  1711.           End
  1712.           Else InsertRecord(WorkNode,ParentNode.FTreeRec,Pointer(PrevNode.FTreeRec));
  1713.           SetupSubNodes(WorkNode);
  1714.           PrevNode:=WorkNode;
  1715.      End;
  1716. End;
  1717.  
  1718.  
  1719. Procedure TOutline.SetupTree;
  1720. Var T:LongInt;
  1721.     Node,PrevNode:TOutlineNode;
  1722.     P:Pointer;
  1723. Begin
  1724.      If Handle=0 Then Exit;
  1725.      If FInitNodes=Nil Then Exit;
  1726.      {Create All main Nodes}
  1727.      PrevNode:=Nil;
  1728.      For T:=0 To FInitNodes.Count-1 Do  {the subnodes Of the root Node}
  1729.      Begin
  1730.           Node:=FInitNodes.Items[T];
  1731.           If Node.FTreeRec=Nil Then
  1732.           Begin
  1733.                AllocateRecord(Handle,Node.FTreeRec);
  1734.                SetupNode(Node);
  1735.           End;
  1736.  
  1737.           If PrevNode=Nil Then
  1738.           Begin
  1739.                LongWord(P):=CMA_FIRST;
  1740.                InsertRecord(Node,Nil,P);
  1741.           End
  1742.           Else InsertRecord(Node,Nil,Pointer(PrevNode.FTreeRec));
  1743.           SetupSubNodes(Node);
  1744.           PrevNode:=Node;
  1745.      End;
  1746.      FInitNodes:=Nil;
  1747. End;
  1748.  
  1749.  
  1750. Procedure TOutline.SetupImageList;
  1751. {$IFDEF Win95}
  1752. Var  Count:LongInt;
  1753.      T:LongInt;
  1754.      Bitmap:TOutlineBitmap;
  1755.      BitHandle:LongWord;
  1756. Label NoBmps;
  1757. {$ENDIF}
  1758. Begin
  1759.      {$IFDEF Win95}
  1760.      If Handle=0 Then Exit;
  1761.  
  1762.      If FPictureList=Nil Then
  1763.      Begin
  1764. NoBmps:
  1765.          SendMessage(Handle,TVM_SETIMAGELIST,TVSIL_NORMAL,0);
  1766.          If FHim<>Nil Then ImageList_Destroy(FHim);
  1767.          FHim:=Nil;
  1768.          exit;
  1769.      End;
  1770.  
  1771.      Count:=FPictureList.Count;
  1772.  
  1773.      If Count=0 Then goto NoBmps;
  1774.  
  1775.      If FHim<>Nil Then ImageList_Destroy(FHim);
  1776.      FHim:=ImageList_Create(FPictureSize.CX,FPictureSize.CY,ILC_COLOR4,Count,0);
  1777.  
  1778.      For T:=0 To FPictureList.Count-1 Do
  1779.      Begin
  1780.           Bitmap:=TOutlineBitmap(FPictureList.Bitmaps[T]);
  1781.           BitHandle:=Bitmap.CreateBitmapFromClass;
  1782.           Bitmap.FHimlIndex:=ImageList_Add(FHim,BitHandle,0);
  1783.           DeleteObject(BitHandle);
  1784.      End;
  1785.  
  1786.      SendMessage(Handle,TVM_SETIMAGELIST,TVSIL_NORMAL,LongWord(FHim));
  1787.      {$ENDIF}
  1788. End;
  1789.  
  1790.  
  1791. Procedure TOutline.CreateParams(Var Params:TCreateParams);
  1792. Begin
  1793.      Inherited CreateParams(Params);
  1794.  
  1795.      {$IFDEF OS2}
  1796.      Params.Style := Params.Style Or CCS_AUTOPOSITION Or CCS_EXTENDSEL;
  1797.      {$ENDIF}
  1798.  
  1799.      {$IFDEF Win95}
  1800.      Params.Style := Params.Style Or WS_CHILD;
  1801.      If FShowTreeLines
  1802.      Then Params.Style := Params.Style Or TVS_HASLINES Or TVS_LINESATROOT;
  1803.      If FShowPlusMinus Then Params.Style := Params.Style Or TVS_HASBUTTONS;
  1804.  
  1805.      If FBorderStyle = bsSingle Then
  1806.      Begin
  1807.           Params.Style := Params.Style Or WS_BORDER;             {Single}
  1808.           Params.ExStyle := Params.ExStyle Or WS_EX_CLIENTEDGE;  {Double}
  1809.      End;
  1810.      {$ENDIF}
  1811. End;
  1812.  
  1813.  
  1814. Procedure TOutline.UpdateNode(Node:TOutlineNode);
  1815. Begin
  1816.      If Handle = 0 Then Exit;
  1817.      {$IFDEF OS2}
  1818.      WinSendMsg(Handle,CM_INVALIDATERECORD,LongWord(@Node.FTreeRec),
  1819.                 MPFROM2SHORT(1,0));
  1820.      {$ENDIF}
  1821.      {$IFDEF Win95}
  1822.      SendMessage(Handle,TVM_SETITEM,0,LongWord(@Node.FTreeRec^.RecordCore));
  1823.      {$ENDIF}
  1824. End;
  1825.  
  1826.  
  1827. Function TOutline.GetSelectedNode:TOutlineNode;
  1828. {$IFDEF OS2}
  1829. Var RecordCore:POutlineRecord;
  1830. {$ENDIF}
  1831. {$IFDEF Win95}
  1832. Var tvItem:TV_ITEM;
  1833. {$ENDIF}
  1834. Begin
  1835.      Result:=Nil;
  1836.      If Handle=0 Then Exit;
  1837.      {$IFDEF OS2}
  1838.      RecordCore:=Pointer(WinSendMsg(Handle,CM_QUERYRECORDEMPHASIS,
  1839.                          CMA_FIRST,CRA_SELECTED));
  1840.      If RecordCore<>Nil Then Result:=RecordCore^.Node;
  1841.      {$ENDIF}
  1842.      {$IFDEF Win95}
  1843.      FillChar(tvItem,SizeOf(TV_ITEM),0);
  1844.      tvItem.hItem:=FSelItem;
  1845.      tvItem.Mask:=TVIF_PARAM;
  1846.      SendMessage(Handle,TVM_GETITEM,0,LongWord(@tvItem));
  1847.      Result:=TOutlineNode(tvItem.LParam);
  1848.      {$ENDIF}
  1849. End;
  1850.  
  1851.  
  1852. Procedure TOutline.SetSelectedNode(NewSelected:TOutlineNode);
  1853. Begin
  1854.      If Handle=0 Then Exit;
  1855.      If NewSelected=Nil Then Exit;
  1856.  
  1857.      If Not NewSelected.IsVisible
  1858.      Then NewSelected := NewSelected.GetVisibleParent;
  1859.      If NewSelected=Nil Then exit;
  1860.  
  1861.      {$IFDEF OS2}
  1862.      WinSendMsg(Handle,CM_SETRECORDEMPHASIS,LongWord(NewSelected.FTreeRec),
  1863.                 MPFROM2SHORT(1,CRA_SELECTED));
  1864.      {$ENDIF}
  1865.      {$IFDEF Win95}
  1866.      SendMessage(Handle,TVM_SELECTITEM,TVGN_CARET,
  1867.                  LongWord(NewSelected.FTreeRec^.RecordCore.hItem));
  1868.      {$ENDIF}
  1869. End;
  1870.  
  1871.  
  1872. Function TOutline.GetSelectedItem:LongInt;
  1873. Var  Node:TOutlineNode;
  1874. Begin
  1875.      Node := GetSelectedNode;
  1876.      If Node <> Nil Then Result := Node.Index
  1877.      Else Result := InvalidIndex;
  1878. End;
  1879.  
  1880.  
  1881. Procedure TOutline.SetSelectedItem(NewSelected:LongInt);
  1882. Var  Node:TOutlineNode;
  1883. Begin
  1884.      Node := Get(NewSelected);
  1885.      If Node <> Nil Then SetSelectedNode(Node);
  1886. End;
  1887.  
  1888.  
  1889. Function TOutline.GetDataItem(Value:Pointer):LongInt;
  1890. Begin
  1891.      Result := FRootNode.GetDataItem(Value);
  1892. End;
  1893.  
  1894.  
  1895. Function TOutline.GetTextItem(Const Value:String):LongInt;
  1896. Begin
  1897.      Result := FRootNode.GetTextItem(Value);
  1898. End;
  1899.  
  1900.  
  1901. Procedure TOutline.ItemFocus(Index:LongInt);
  1902. Begin
  1903.      If OnItemFocus <> Nil Then OnItemFocus(Self,Index);
  1904.      If SelectedItem<>InvalidIndex Then Click;
  1905. End;
  1906.  
  1907.  
  1908. Procedure TOutline.ItemSelect(Index:LongInt);
  1909. Begin
  1910.      If OnItemSelect <> Nil Then OnItemSelect(Self,Index);
  1911. End;
  1912.  
  1913.  
  1914. {$HINTS OFF}
  1915. Procedure TOutline.ScanEvent(Var KeyCode:TKeyCode;RepeatCount:Byte);
  1916. Var  Node1,Node2:TOutlineNode;
  1917. Begin
  1918.      Case KeyCode Of
  1919.        kbCUp,kbCDown,kbHome,kbEnd,kbPageUp,kbPageDown:
  1920.        Begin
  1921.             Node1 := SelectedNode;
  1922.             LastMsg.CallDefaultHandler; //!
  1923.             Node2 := SelectedNode;
  1924.             If Node1 <> Node2 Then
  1925.               If Node2 Is TOutlineNode Then ItemFocus(Node2.Index);
  1926.        End;
  1927.        Else Inherited ScanEvent(KeyCode,RepeatCount);
  1928.      End;
  1929. End;
  1930.  
  1931. Procedure TOutline.MouseDown(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);
  1932. Begin
  1933.      {$IFDEF WIN32}
  1934.      If Button=mbRight Then
  1935.      Begin
  1936.           LastMsg.Handled:=True;
  1937.           exit;
  1938.      End;
  1939.      {$ENDIF}
  1940.  
  1941.      Inherited MouseDown(Button,ShiftState,X,Y);
  1942.  
  1943.      If Button = mbLeft Then
  1944.      Begin
  1945.           FDragging := True;
  1946.           FFocusNode := SelectedNode;
  1947.      End;
  1948. End;
  1949.  
  1950. Procedure TOutline.MouseMove(ShiftState:TShiftState;X,Y:LongInt);
  1951. Var  Node:TOutlineNode;
  1952. Begin
  1953.      Inherited MouseMove(ShiftState,X,Y);
  1954.  
  1955.      If FDragging Then
  1956.      Begin
  1957.           Node := SelectedNode;
  1958.           If Node <> FFocusNode Then
  1959.             If Node Is TOutlineNode Then
  1960.             Begin
  1961.                  FFocusNode := Node;
  1962.                  ItemFocus(Node.Index);
  1963.             End;
  1964.      End;
  1965. End;
  1966.  
  1967.  
  1968. Procedure TOutline.MouseUp(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);
  1969. Var Node:TOutlineNode;
  1970. Begin
  1971.      {$IFDEF WIN32}
  1972.      If Button=mbRight Then
  1973.      Begin
  1974.           LastMsg.Handled:=True;
  1975.           exit;
  1976.      End;
  1977.      {$ENDIF}
  1978.  
  1979.      Inherited MouseUp(Button,ShiftState,X,Y);
  1980.  
  1981.      If FDragging Then
  1982.      Begin
  1983.           FDragging := False;
  1984.           Node := SelectedNode;
  1985.           If Node <> FFocusNode Then
  1986.             If Node Is TOutlineNode Then
  1987.             Begin
  1988.                  FFocusNode := Node;
  1989.                  ItemFocus(Node.Index);
  1990.             End;
  1991.      End;
  1992. End;
  1993.  
  1994. Procedure TOutline.MouseDblClick(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);
  1995. Begin
  1996.      Inherited MouseDblClick(Button,ShiftState,X,Y);
  1997.  
  1998.      {$IFDEF WIN32}
  1999.      If SelectedNode<>Nil Then ItemSelect(SelectedNode.Index);
  2000.      {$ENDIF}
  2001. End;
  2002.  
  2003. Procedure TOutline.MouseClick(Button:TMouseButton;ShiftState:TShiftState;X,Y:LongInt);
  2004. Begin
  2005.      {$IFDEF OS2}
  2006.      If OnMouseClick <> Nil Then OnMouseClick(Self,Button,ShiftState,X,Y);
  2007.      {no Inherited because Of CN_CONTEXTMENU, but Store the mouse Pos}
  2008.      FPopupPos := Point(X,Y);
  2009.      {$ENDIF}
  2010.      {$IFDEF WIN32}
  2011.      FPopupPos := Point(X,Y);
  2012.      Inherited MouseClick(Button,ShiftState,X,Y);
  2013.      {$ENDIF}
  2014. End;
  2015. {$HINTS ON}
  2016.  
  2017. Procedure TOutline.Expand(Index:LongInt);
  2018. Begin
  2019.     If FOnExpand <> Nil Then FOnExpand(Self,Index);
  2020. End;
  2021.  
  2022. Procedure TOutline.Collapse(Index:LongInt);
  2023. Begin
  2024.     If FOnCollapse <> Nil Then FOnCollapse(Self,Index);
  2025. End;
  2026.  
  2027. Procedure TOutline.Click;
  2028. Begin
  2029.     If FOnClick<>Nil Then FOnClick(Self);
  2030. End;
  2031.  
  2032. Procedure TOutline.ItemChanged(Var Msg:TMessage;Expanded:Boolean);
  2033. Var  Node:TOutlineNode;
  2034.      {$IFDEF OS2}
  2035.      RecordCore:POutlineRecord;
  2036.      {$ENDIF}
  2037.      {$IFDEF Win95}
  2038.      DispInfo:^NM_TREEVIEW;
  2039.      Item:TV_ITEM;
  2040.      {$ENDIF}
  2041. Begin
  2042.      {$IFDEF OS2}
  2043.      RecordCore := Pointer(Msg.Param2);
  2044.      Node := RecordCore^.Node;
  2045.      If Node = Nil Then Exit;
  2046.      {$ENDIF}
  2047.  
  2048.      {$IFDEF Win95}
  2049.      DispInfo := Pointer(Msg.Param2);
  2050.      Item := DispInfo^.ItemNew;
  2051.      Node := TOutlineNode(Item.LParam);
  2052.      If Node = Nil Then Exit;
  2053.  
  2054.      Node.UpdatePicture{(Node.FPictureLeaf)???};
  2055.      {$ENDIF}
  2056.  
  2057.      Node.FExpanded := Expanded;
  2058.      Node.UpdatePicture;
  2059.      If Node.Expanded Then
  2060.      Begin
  2061.           If not FChangeLock Then
  2062.           Begin
  2063.                If Node.FIndex=InvalidIndex Then FRootNode.ReIndex(FRootNode.Index,MaxLongInt);
  2064.                If Node.FIndex<>InvalidIndex Then Expand(Node.FIndex);
  2065.           End;
  2066.      End
  2067.      Else
  2068.      Begin
  2069.           If not FChangeLock Then
  2070.           Begin
  2071.               If Node.FIndex=InvalidIndex Then FRootNode.ReIndex(FRootNode.Index,MaxLongInt);
  2072.               If Node.FIndex<>InvalidIndex Then Collapse(Node.FIndex);
  2073.           End;
  2074.      End;
  2075.  
  2076.      UpdateNode(Node);
  2077. End;
  2078.  
  2079.  
  2080. Procedure TOutline.BeginUpdate;
  2081. Begin
  2082.      If FUpdateCount = 0 Then
  2083.      Begin
  2084.           If Handle <> 0 Then
  2085.           {$IFDEF OS2}
  2086.           WinEnableWindowUpdate(Handle,False);
  2087.           {$ENDIF}
  2088.           {$IFDEF Win95}
  2089.           SendMessage(Handle,WM_SETREDRAW, 0, 0);
  2090.           {$ENDIF}
  2091.      End;
  2092.      Inc(FUpdateCount);
  2093. End;
  2094.  
  2095.  
  2096. Procedure TOutline.EndUpdate;
  2097. Begin
  2098.      Dec(FUpdateCount);
  2099.      If FUpdateCount = 0 Then
  2100.      Begin
  2101.           If Handle <> 0 Then
  2102.           Begin
  2103.                {$IFDEF OS2}
  2104.                WinEnableWindowUpdate(Handle,True);
  2105.                {$ENDIF}
  2106.                {$IFDEF Win95}
  2107.                SendMessage(Handle,WM_SETREDRAW, 1, 0);
  2108.                {$ENDIF}
  2109.           End;
  2110.           FRootNode.ReIndex(FRootNode.Index,MaxLongInt);
  2111.      End;
  2112. End;
  2113.  
  2114.  
  2115. Procedure TOutline.ParentNotification(Var Msg:TMessage);
  2116. {$IFDEF OS2}
  2117. Var  Node:TOutlineNode;
  2118.      RecordCore:POutlineRecord;
  2119.      RecEnter:PNOTIFYRECORDENTER;
  2120.      RecEmp:PNOTIFYRECORDEMPHASIS;
  2121.      SaveCount:LongInt;
  2122. {$ENDIF}
  2123. {$IFDEF WIN32}
  2124. Var DispInfo:^NM_TREEVIEW;
  2125.     Expanded:Boolean;
  2126.     KeyDown:^TV_KEYDOWN;
  2127. {$ENDIF}
  2128. CONST CN_TEST=0;
  2129. Begin
  2130.      {$IFDEF OS2}
  2131.      Case Msg.Param1Hi Of
  2132.        CN_SCROLL:
  2133.        Begin
  2134.             Inherited ParentNotification(Msg);
  2135.  
  2136.             {!! Update BitBlt area Of the Ownerdraw Frame}
  2137.             If FBorderStyle = bsSingle Then Invalidate;
  2138.        End;
  2139.        CN_ENTER:      {Enter & DoubleClick}
  2140.        Begin
  2141.             If Designed Then Exit;
  2142.             Inherited ParentNotification(Msg);
  2143.  
  2144.             RecEnter := Pointer(Msg.Param2);
  2145.             If RecEnter = Nil Then Exit;
  2146.             RecordCore := Pointer(RecEnter^.pRecord);
  2147.             If RecordCore = Nil Then Exit;
  2148.             Node := RecordCore^.Node;
  2149.  
  2150.             If Node Is TOutlineNode Then ItemSelect(Node.Index);
  2151.        End;
  2152.        CN_COLLAPSETREE,CN_EXPANDTREE:
  2153.        Begin
  2154.             If Designed Then Exit;
  2155.             Inherited ParentNotification(Msg);
  2156.  
  2157.             RecordCore := Pointer(Msg.Param2);
  2158.             Node := RecordCore^.Node;
  2159.  
  2160.             If Node Is TOutlineNode Then
  2161.             Begin
  2162.                  If Msg.Param1Hi = CN_COLLAPSETREE
  2163.                  Then ItemChanged(Msg,False)
  2164.                  Else ItemChanged(Msg,True)
  2165.             End;
  2166.             {!! Update area Of the Ownerdraw Frame}
  2167.             If FBorderStyle = bsSingle Then Invalidate;
  2168.        End;
  2169.        CN_CONTEXTMENU:
  2170.        Begin
  2171.             If Designed Then Exit;
  2172.             CheckMenuPopup(FPopupPos);
  2173.        End;
  2174. (* Cut no effect
  2175.        CN_REALLOCPSZ:
  2176.        Begin
  2177.        End;
  2178.        CN_ENDEDIT:
  2179.        Begin
  2180.             CnrEdit := Pointer(Msg.Param2);
  2181.             RecordCore := POutlineRecord(CnrEdit^.pRecord);
  2182.             Node := RecordCore^.Node;
  2183.             ppc := CnrEdit^.ppszText;
  2184.             pc := ppc^;
  2185.             S := pc^;
  2186.             ErrorBox2(S+' <> '+RecordCore^.RecordCore.pszTree^);
  2187.             Msg.Handled := True;
  2188.             Msg.Result := 0;
  2189.        End;
  2190. *)
  2191.        CN_EMPHASIS:
  2192.        Begin
  2193.             Inherited ParentNotification(Msg);
  2194.  
  2195.             RecEmp := Pointer(Msg.Param2);
  2196.             If RecEmp = Nil Then Exit;
  2197.             RecordCore := Pointer(RecEmp^.pRecord);
  2198.             If RecordCore = Nil Then Exit;
  2199.             Node := RecordCore^.Node;
  2200.             DefaultHandler(Msg);
  2201.  
  2202.             If (RecEmp^.fEmphasisMask And 5)=5 Then
  2203.              If SelectedNode=Node Then
  2204.             Begin
  2205.                  PostMsg(Parent.Handle,WM_CONTROL,
  2206.                          Msg.Param1Lo OR (CN_TEST SHL 16),
  2207.                          LONGWORD(Node));
  2208.             End;
  2209.        End;
  2210.        CN_TEST:
  2211.        BEGIN
  2212.             Node := Pointer(Msg.Param2);
  2213.             If (LongWord(Node) And $80000000)=0 Then
  2214.               If LongWord(Node)>$10000 Then
  2215.             Begin
  2216.                Try
  2217.                  If FUpdateCount>0 Then FRootNode.ReIndex(FRootNode.Index,MaxLongInt);
  2218.                  SaveCount:=FUpdateCount;
  2219.                  FUpdateCount:=0;
  2220.                  If Node IS TOutlineNode Then ItemFocus(Node.Index);
  2221.                  FUpdateCount:=FUpdateCount+SaveCount;
  2222.                Except
  2223.                End;
  2224.             End;
  2225.             Msg.Handled:=True;
  2226.        END;
  2227.        Else
  2228.        Begin
  2229.             Inherited ParentNotification(Msg);
  2230.        End;
  2231.      End;
  2232.      {$ENDIF}
  2233.  
  2234.      {$IFDEF Win95}
  2235.      If Msg.Msg<>WM_NOTIFY Then
  2236.      Begin
  2237.           Inherited ParentNotification(Msg);
  2238.           exit;
  2239.      End;
  2240.  
  2241.      DispInfo:=Pointer(Msg.Param2);
  2242.      If DispInfo=Nil Then Exit;
  2243.      Case DispInfo^.hdr.Code Of
  2244.          TVN_ITEMEXPANDED:
  2245.          Begin
  2246.               Expanded:=DispInfo^.Action And TVE_EXPAND=TVE_EXPAND;
  2247.  
  2248.               ItemChanged(Msg,Expanded);
  2249.  
  2250.               Msg.Handled:=True;
  2251.               Msg.Result:=0;
  2252.          End;
  2253.          TVN_KEYDOWN:
  2254.          Begin
  2255.               KeyDown:=Pointer(Msg.Param2);
  2256.  
  2257.               If KeyDown^.wVKey=VK_RETURN Then
  2258.                If SelectedNode<>Nil Then ItemSelect(SelectedNode.Index);
  2259.          End;
  2260.          TVN_SELCHANGED:
  2261.          Begin
  2262.               FSelItem:=DispInfo^.ItemNew.hItem;
  2263.          End;
  2264.          Else Inherited ParentNotification(Msg);
  2265.      End; {Case}
  2266.      {$ENDIF}
  2267. End;
  2268.  
  2269.  
  2270. Procedure TOutline.indexerror;
  2271. Begin
  2272.      Raise EOutlineIndexError.Create(LoadNLSStr(SInvalidOutlineNodeIndex));
  2273. End;
  2274.  
  2275.  
  2276. Procedure TOutline.NodeError;
  2277. Begin
  2278.      Raise EOutlineNodeError.Create(LoadNLSStr(SInvalidOutlineNode)+' (NIL)');
  2279. End;
  2280.  
  2281.  
  2282. Function TOutline.AttachNode(Node:TOutlineNode;Const Text:String;Data:Pointer;
  2283.                              Mode:TAttachMode):TOutlineNode;
  2284. Var  NewNode:TOutlineNode;
  2285. Begin
  2286.      If Node = Nil Then Node := FRootNode;
  2287.  
  2288.      NewNode := FNodeClass.Create(Self);
  2289.      NewNode.Data := Data;
  2290.      NewNode.Text := Text;
  2291.      NewNode.FIndex := InvalidIndex;
  2292.      NewNode.FExpanded := False;
  2293.  
  2294.      Case Mode Of
  2295.        oaAddChild: Node.AddNode(NewNode);
  2296.        oaAdd:      Node.parent.AddNode(NewNode);
  2297.        oaInsert:   Node.parent.InsertNode(Node,NewNode);
  2298.      End;
  2299.      Result := NewNode;
  2300. End;
  2301.  
  2302.  
  2303. Function TOutline.Add(Index:LongInt;Const Text:String):LongInt;
  2304. Begin
  2305.      Result := AddObject(Index,Text,Nil);
  2306. End;
  2307.  
  2308.  
  2309. {Add To the same Level like idx Node}
  2310. Function TOutline.AddObject(Index:LongInt;Const Text:String;Data:Pointer):LongInt;
  2311. Begin
  2312.      If Index >= 0 Then
  2313.      Begin
  2314.           If Index = 0 Then Result := AddChildObject(Index,Text,Data)
  2315.           Else Result := Attach(Index,Text,Data,oaAdd);
  2316.      End
  2317.      Else indexerror;
  2318. End;
  2319.  
  2320.  
  2321. {Add As Child Of the idx Node}
  2322. Function TOutline.AddChild(Index:LongInt;Const Text:String):LongInt;
  2323. Begin
  2324.      Result := AddChildObject(Index,Text,Nil);
  2325. End;
  2326.  
  2327.  
  2328. Function TOutline.AddChildObject(Index:LongInt;Const Text:String;Data:Pointer):LongInt;
  2329. Begin
  2330.      If Index >= 0 Then Result := Attach(Index,Text,Data,oaAddChild)
  2331.      Else indexerror;
  2332. End;
  2333.  
  2334.  
  2335. Function TOutline.Insert(Index:LongInt;Const Text:String):LongInt;
  2336. Begin
  2337.      Result := InsertObject(Index,Text,Nil);
  2338. End;
  2339.  
  2340.  
  2341. Function TOutline.InsertObject(Index:LongInt;Const Text:String;Data:Pointer):LongInt;
  2342. Begin
  2343.      If Index >= 0 Then
  2344.      Begin
  2345.           If Index = 0 Then Result := AddChildObject(Index,Text,Data)
  2346.           Else Result := Attach(Index,Text,Data,oaInsert);
  2347.      End
  2348.      Else indexerror;
  2349. End;
  2350.  
  2351.  
  2352. {Create the Node And Insert it}
  2353. Function TOutline.Attach(idx:LongInt;Const Text:String;Data:Pointer;
  2354.                          Mode:TAttachMode):LongInt;
  2355. Var  Node:TOutlineNode;
  2356. Begin
  2357.      If idx = 0 Then Node := FRootNode
  2358.      Else Node := Get(idx);
  2359.      If Node = Nil Then NodeError;
  2360.  
  2361.      FIndexInsert := True;   {force To Update Index}
  2362.      Node := AttachNode(Node,Text,Data,Mode);
  2363.      FIndexInsert := False;  {Index Update Mode = OFF}
  2364.  
  2365.      If Node <> Nil Then Result := Node.FIndex
  2366.      Else Result := InvalidIndex;
  2367. End;
  2368.  
  2369.  
  2370. Procedure TOutline.Delete(Index:LongInt);
  2371. Var  ANode:TOutlineNode;
  2372.      AParent:TOutlineNode;
  2373. Begin
  2374.      If Index > 0 Then
  2375.      Begin
  2376.           ANode := Get(Index);
  2377.           AParent := ANode.parent;
  2378.           ANode.Destroy;
  2379.  
  2380.           SetGoodNode(AParent);
  2381.      End
  2382.      Else indexerror;
  2383. End;
  2384.  
  2385.  
  2386. Procedure TOutline.SetGoodNode(Node:TOutlineNode);
  2387. Begin
  2388.      If FUpdateCount > 0 Then
  2389.      Begin
  2390.           FGoodNode := Node;
  2391.           If FGoodNode <> FRootNode Then FGoodNode.SetLastValidIndex;
  2392.      End
  2393.      Else FRootNode.ReIndex(FRootNode.Index,MaxLongInt);
  2394. End;
  2395.  
  2396.  
  2397. Function TOutline.GetLines:TStrings;
  2398. Begin
  2399.      If Handle <> 0 Then Result := FLines
  2400.      Else Result := FInitLines;
  2401. End;
  2402.  
  2403.  
  2404. Procedure TOutline.SetLines(AStrings:TStrings);
  2405. Begin
  2406.      If Lines <> AStrings Then Lines.Assign(AStrings);
  2407. End;
  2408.  
  2409.  
  2410. Function TOutline.Get(idx:LongInt):TOutlineNode;
  2411. Begin
  2412.      If FCurItem.Index = idx Then
  2413.      Begin
  2414.           Result := FCurItem;
  2415.           Exit;
  2416.      End;
  2417.      If FGoodNode.Index = idx Then
  2418.      Begin
  2419.           Result := FGoodNode;
  2420.           Exit;
  2421.      End;
  2422.  
  2423.      If FGoodNode.Index < idx Then
  2424.      Begin
  2425.           FRootNode.ReIndex(FRootNode.Index,idx);
  2426.      End;
  2427.  
  2428.      Result := FRootNode.Index2Node(idx);
  2429.      FCurItem := Result;
  2430. End;
  2431.  
  2432.  
  2433. Function TOutline.GetItemCount:LongInt;
  2434. Begin
  2435.      FRootNode.ReIndex(FRootNode.Index,MaxLongInt);
  2436.  
  2437.      Result := FRootNode.GetLastIndex;
  2438. End;
  2439.  
  2440.  
  2441. Procedure TOutline.FullExpand;
  2442. Begin
  2443.      FRootNode.FullExpand;
  2444. End;
  2445.  
  2446.  
  2447. Procedure TOutline.FullCollapse;
  2448. Begin
  2449.      FRootNode.FullCollapse;
  2450. End;
  2451.  
  2452.  
  2453. Procedure TOutline.Clear;
  2454. Begin
  2455.      BeginUpdate;
  2456.      FRootNode.ClearSubNodes;
  2457.      EndUpdate;
  2458. End;
  2459.  
  2460.  
  2461. Function TOutline.WriteSCUResource(Stream:TResourceStream):Boolean;
  2462. Var  aText:PChar;
  2463. Begin
  2464.      Result := Inherited WriteSCUResource(Stream);
  2465.      If Not Result Then Exit;
  2466.  
  2467.      If (FPictureLeaf <> Nil) And Not FPictureLeaf.Empty
  2468.      Then Result := FPictureLeaf.WriteSCUResourceName(Stream,rnPictureLeaf);
  2469.      If Not Result Then Exit;
  2470.  
  2471.      If (FPictureOpen <> Nil) And Not FPictureOpen.Empty
  2472.      Then Result := FPictureOpen.WriteSCUResourceName(Stream,rnPictureOpen);
  2473.      If Not Result Then Exit;
  2474.  
  2475.      If (FPictureClosed <> Nil) And Not FPictureClosed.Empty
  2476.      Then Result := FPictureClosed.WriteSCUResourceName(Stream,rnPictureClosed);
  2477.      If Not Result Then Exit;
  2478.  
  2479.      aText := Lines.GetText;
  2480.      If aText <> Nil Then
  2481.      Begin
  2482.           Result := Stream.NewResourceEntry(rnLines,aText^,Length(aText^)+1);
  2483.           StrDispose(aText);
  2484.           If Not Result Then Exit;
  2485.      End;
  2486. End;
  2487.  
  2488.  
  2489. Procedure TOutline.ReadSCUResource(Const ResName:TResourceName;Var Data;DataLen:LongInt);
  2490. Var  aText:PChar;
  2491. Begin
  2492.      If ResName = rnLines Then
  2493.      Begin
  2494.           aText := @Data;
  2495.           Lines.SetText(aText);
  2496.      End Else
  2497.      If ResName = rnPictureLeaf Then
  2498.      Begin
  2499.           If DataLen <> 0
  2500.           Then PictureLeaf.ReadSCUResource(rnBitmap,Data,DataLen);
  2501.      End Else
  2502.      If ResName = rnPictureOpen Then
  2503.      Begin
  2504.           If DataLen <> 0
  2505.           Then PictureOpen.ReadSCUResource(rnBitmap,Data,DataLen);
  2506.      End Else
  2507.      If ResName = rnPictureClosed Then
  2508.      Begin
  2509.           If DataLen <> 0
  2510.           Then PictureClosed.ReadSCUResource(rnBitmap,Data,DataLen);
  2511.      End
  2512.      Else Inherited ReadSCUResource(ResName,Data,DataLen)
  2513. End;
  2514.  
  2515. Function TOutline.NodeFromPoint(pt:TPoint):TOutlineNode;
  2516. Var t:LongInt;
  2517.     rec:TRect;
  2518. Begin
  2519.     For t:=0 To ItemCount-1 Do
  2520.     Begin
  2521.         result:=Items[t];
  2522.         rec:=result.ItemRect;
  2523.         If ((pt.X>=rec.Left)And(pt.X<=rec.Right)) Then
  2524.           If ((pt.Y>=rec.Bottom)And(pt.Y<=rec.Top)) Then exit;
  2525.     End;
  2526.     result:=Nil;
  2527. End;
  2528.  
  2529. Procedure TOutline.DrawDragRect;
  2530. Begin
  2531.      If Canvas = Nil Then Exit;
  2532.      Canvas.Pen.Mode:=pmNot;
  2533.      Canvas.Pen.color:=clBlack;
  2534.      Canvas.Pen.Style:=psDot;
  2535.      Canvas.Rectangle(FDragRect);
  2536.      Canvas.Pen.Mode:=pmCopy;
  2537. End;
  2538.  
  2539. Procedure TOutline.DragOver(Source:TObject;X,Y:LongInt;State:TDragState;Var Accept:Boolean);
  2540. Var Node:TOutlineNode;
  2541. Label invalid;
  2542. Begin
  2543.      Node:=Nil;
  2544.      Inherited DragOver(Source,X,Y,State,Accept);
  2545.      If FShowDragRects Then
  2546.      Begin
  2547.           If Accept Then
  2548.           Begin
  2549.                Node:=NodeFromPoint(Point(X,Y));
  2550.                If Node<>Nil Then
  2551.                Begin
  2552.                     Case State Of
  2553.                        dsDragEnter:
  2554.                        Begin
  2555.                             CreateDragCanvas;
  2556.                             If FDragRectValid Then DrawDragRect; //Delete old
  2557.                             FDragRect := Node.ItemRect;
  2558.                             FDragRectValid:=True;
  2559.                             DrawDragRect;  //Draw New
  2560.                             DeleteDragCanvas;
  2561.                        End;
  2562.                        dsDragMove:
  2563.                        If Node<>FDragSelected Then
  2564.                        Begin
  2565.                             CreateDragCanvas;
  2566.                             If FDragRectValid Then DrawDragRect; //Delete old
  2567.                             FDragRect := Node.ItemRect;
  2568.                             FDragRectValid:=True;
  2569.                             DrawDragRect; //Draw New
  2570.                             DeleteDragCanvas;
  2571.                        End;
  2572.                        dsDragLeave:
  2573.                        Begin
  2574.                             If FDragRectValid Then
  2575.                             Begin
  2576.                                  FDragRectValid:=False;
  2577.                                  CreateDragCanvas;
  2578.                                  DrawDragRect; //Delete old
  2579.                                  DeleteDragCanvas;
  2580.                             End;
  2581.                        End;
  2582.                     End; //Case
  2583.                End
  2584.                Else Goto invalid;
  2585.           End
  2586.           Else
  2587.           Begin
  2588. invalid:
  2589.                If FDragRectValid Then
  2590.                Begin
  2591.                     FDragRectValid:=False;
  2592.                     CreateDragCanvas;
  2593.                     DrawDragRect; //Delete old
  2594.                     DeleteDragCanvas;
  2595.                End;
  2596.           End;
  2597.           FDragSelected:=Node;
  2598.      End;
  2599. End;
  2600.  
  2601. Procedure TOutline.DragDrop(Source:TObject;X,Y:LongInt);
  2602. Begin
  2603.      If FDragRectValid Then
  2604.      Begin
  2605.           CreateDragCanvas;
  2606.           DrawDragRect; //Delete old
  2607.           DeleteDragCanvas;
  2608.           FDragRectValid:=False;
  2609.      End;
  2610.      Inherited DragDrop(Source,X,Y);
  2611. End;
  2612.  
  2613.  
  2614.  
  2615. Begin
  2616. End.
  2617.  
  2618.