home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kolekce / d456 / DCSLIB25.ZIP / DCKnots.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-28  |  221KB  |  7,688 lines

  1. {
  2.  BUSINESS CONSULTING
  3.  s a i n t - p e t e r s b u r g
  4.  
  5.          Components Library for Borland Delphi 4.x, 5.x
  6.          Copyright (c) 1998-2001 Alex'EM
  7.  
  8. }
  9. unit DCKnots;
  10.  
  11. interface
  12. {$I DCConst.inc}
  13.  
  14. uses
  15.   Windows, SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Menus,
  16.   Controls, Dialogs, Forms, StdCtrls, Buttons, ExtCtrls, ImgList,
  17.   ComCtrls, DB, DCGrids, grids, DCDBGrids, DCChoice, DCPopupWindow, DCEditTools,
  18.   DCConst
  19.   {$IFDEF DELPHI_V5UP}, DCADOCtrl {$ENDIF};
  20.  
  21. type
  22.   TKnotsColumnValue  = (cvColor, cvWidth, cvFont, cvAlignment, cvReadOnly, cvTitleColor,
  23.     cvTitleCaption, cvTitleAlignment, cvTitleFont, cvComment, cvDisplayFormat);
  24.   TKnotsColumnValues = set of TKnotsColumnValue;
  25.  
  26. const
  27.   ColumnTitleValues = [cvTitleColor..cvTitleFont];
  28.  
  29. type
  30.   TDCCustomTreeGrid = class;
  31.   TKnotColumn = class;
  32.  
  33.   TKnotColumnTitle = class(TPersistent)
  34.   private
  35.     FColumn: TKnotColumn;
  36.     FCaption: string;
  37.     FFont: TFont;
  38.     FColor: TColor;
  39.     FAlignment: TAlignment;
  40.     procedure FontChanged(Sender: TObject);
  41.     function GetAlignment: TAlignment;
  42.     function GetColor: TColor;
  43.     function GetCaption: string;
  44.     function GetFont: TFont;
  45.     function IsAlignmentStored: Boolean;
  46.     function IsColorStored: Boolean;
  47.     function IsFontStored: Boolean;
  48.     function IsCaptionStored: Boolean;
  49.     procedure SetAlignment(Value: TAlignment);
  50.     procedure SetColor(Value: TColor);
  51.     procedure SetFont(Value: TFont);
  52.     procedure SetCaption(const Value: string); virtual;
  53.   protected
  54.     procedure RefreshDefaultFont;
  55.   public
  56.     constructor Create(Column: TKnotColumn);
  57.     destructor Destroy; override;
  58.     procedure Assign(Source: TPersistent); override;
  59.     function DefaultAlignment: TAlignment;
  60.     function DefaultColor: TColor;
  61.     function DefaultFont: TFont;
  62.     function DefaultCaption: string;
  63.     procedure RestoreDefaults; virtual;
  64.     property Column: TKnotColumn read FColumn;
  65.   published
  66.     property Alignment: TAlignment read GetAlignment write SetAlignment stored
  67.       IsAlignmentStored;
  68.     property Caption: string read GetCaption write SetCaption stored
  69.       IsCaptionStored;
  70.     property Color: TColor read GetColor write SetColor stored IsColorStored;
  71.     property Font: TFont read GetFont write SetFont stored IsFontStored;
  72.   end;
  73.  
  74.   TKnotColumnFooter = class(TDCFooter)
  75.   public
  76.     property Index;
  77.   published
  78.     property AutoSize;
  79.     property Style;
  80.     property Height;
  81.     property Visible;
  82.   end;
  83.  
  84.   TKnotColumnFooterPanel = class(TDCFooterTextPanel)
  85.   protected
  86.     function GetColIndex: integer; override;
  87.     procedure SetColIndex(const Value: integer); override;
  88.   published
  89.     property Visible default False;
  90.     property Style default beLowered;
  91.   end;
  92.  
  93.   TKnotOption  = (kcIndexed, kcReadOnly, kcShowEdit, kcSizing, kcVisible, kcDrawTreeCell);
  94.   TKnotOptions = set of TKnotOption;
  95.   TKnotColumnClass = class of TKnotColumn;
  96.  
  97.   TKnotColumn  = class(TCollectionItem)
  98.   private
  99.     FAlignment: TAlignment;
  100.     FAssignedValues: TKnotsColumnValues;
  101.     FColor: TColor;
  102.     FComment: string;
  103.     FDisplayFormat: string;
  104.     FFont: TFont;
  105.     FFooterPanel: TKnotColumnFooterPanel;
  106.     FItemIndex: integer;
  107.     FIndexStyle: TColumnIndexStyle;
  108.     FName: string;
  109.     FOptions: TKnotOptions;
  110.     FTitle: TKnotColumnTitle;
  111.     FWidth: TWidth;
  112.     procedure SetColor(const Value: TColor);
  113.     procedure SetFont(const Value: TFont);
  114.     procedure SetTitle(const Value: TKnotColumnTitle);
  115.     function GetAlignment: TAlignment;
  116.     function GetColor: TColor;
  117.     function GetFont: TFont;
  118.     procedure FontChanged(Sender: TObject);
  119.     procedure SetItemIndex(const Value: integer);
  120.     procedure SetIndexStyle(const Value: TColumnIndexStyle);
  121.     function GetWidth: TWidth;
  122.     procedure SetAlignment(const Value: TAlignment);
  123.     procedure SetName(const Value: string);
  124.     procedure SetWidth(const Value: TWidth);
  125.     procedure SetDisplayFormat(const Value: string);
  126.     function IsAlignmentStored: Boolean;
  127.     function IsColorStored: Boolean;
  128.     function IsFontStored: Boolean;
  129.     function IsWidthStored: Boolean;
  130.     function IsCommentStored: Boolean;
  131.     procedure SetOptions(const Value: TKnotOptions);
  132.     procedure SetComment(const Value: string);
  133.     function GetComment: string;
  134.     function GetActualWidth: TWidth;
  135.     procedure SetFooterPanel(const Value: TKnotColumnFooterPanel);
  136.   protected
  137.     procedure Changed(AllItems: Boolean);
  138.     function GetDisplayName: string; override;
  139.     procedure RefreshDefaultFont;
  140.     procedure SetIndex(Value: Integer); override;
  141.   public
  142.     constructor Create(Collection: TCollection); override;
  143.     destructor Destroy; override;
  144.     procedure Assign(Source: TPersistent); override;
  145.     function GetGrid: TDCCustomTreeGrid;
  146.     function DefaultAlignment: TAlignment;
  147.     function DefaultColor: TColor;
  148.     function DefaultFont: TFont;
  149.     function DefaultWidth: Integer;
  150.     function DefaultComment: string;
  151.     procedure RestoreDefaults; virtual;
  152.     property AssignedValues: TKnotsColumnValues read FAssignedValues;
  153.     property Grid: TDCCustomTreeGrid read GetGrid;
  154.   published
  155.     property ActualWidth:TWidth read GetActualWidth stored False;
  156.     property Alignment: TAlignment read GetAlignment write SetAlignment stored
  157.       IsAlignmentStored;
  158.     property Color: TColor read GetColor write SetColor stored  IsColorStored;
  159.     property Comment: string read GetComment write SetComment stored IsCommentStored;
  160.     property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
  161.     property Font: TFont read GetFont write SetFont stored IsFontStored;
  162.     property FooterPanel: TKnotColumnFooterPanel read FFooterPanel write SetFooterPanel;
  163.     property ItemIndex: integer read FItemIndex write SetItemIndex default -1;
  164.     property IndexStyle: TColumnIndexStyle read FIndexStyle write SetIndexStyle default idxNone;
  165.     property Name: string read FName write SetName;
  166.     property Options: TKnotOptions read FOptions write SetOptions default
  167.       [kcShowEdit, kcSizing, kcVisible];
  168.     property Title: TKnotColumnTitle read FTitle write SetTitle;
  169.     property Width: TWidth read GetWidth write SetWidth stored IsWidthStored;
  170.   end;
  171.  
  172.   TKnotColumns = class(TCollection)
  173.   private
  174.     FGrid: TDCCustomTreeGrid;
  175.     function GetItem(Index: Integer): TKnotColumn;
  176.     procedure SetItem(Index: Integer; Value: TKnotColumn);
  177.   protected
  178.     function GetOwner: TPersistent; override;
  179.     procedure Update(Item: TCollectionItem); override;
  180.   public
  181.     constructor Create(AGrid: TDCCustomTreeGrid; AKnotColumnClass: TKnotColumnClass);
  182.     function Add: TKnotColumn;
  183.     property Grid: TDCCustomTreeGrid read FGrid;
  184.     property Items[Index: Integer]: TKnotColumn read GetItem write SetItem; default;
  185.   end;
  186.  
  187. {
  188.   < 0 if Item1 is less and Item2
  189.     0 if they are equal
  190.   > 0 if Item1 is greater than Item2
  191. }
  192.   TGridSortCompare = function (Sender: TObject; Item1, Item2: Pointer; Data: integer): Integer;
  193.   TKnotState = (ksBrowse, ksInsert, ksEdit, ksUpdate, ksCreate);
  194.  
  195.   TKnotItems = class;
  196.   TKnotItem = class;
  197.   TKnotItemClass = class of TKnotItem;
  198.  
  199.   TKnotItem  = class(TObject)
  200.   private
  201.     FFlag: WORD;
  202.     FOwner: TKnotItems;
  203.     FParent: TKnotItem;
  204.     FName: string;
  205.     FData: Pointer;
  206.     FKnotID: integer;
  207.     FChildKnots: TList;
  208.     FIndex: integer;
  209.     FNormalImage: shortint;
  210.     FSelectImage: shortint;
  211.     FState: TKnotState;
  212.     FLastIndex: integer;
  213.     function GetChildCount: integer;
  214.     procedure SetData(const Value: Pointer);
  215.     procedure SetName(const Value: string);
  216.     procedure SetState(const Value: TKnotState);
  217.     function GetFlagValue(const Index: Integer): boolean;
  218.     procedure SetFlagValue(const Index: Integer; const Value: boolean);
  219.     procedure SetValueEx(const Index: Integer; const Value: boolean);
  220.     function GetVisibleChildCount: integer;
  221.     function GetVisibleKnotCount: integer;
  222.     procedure SetNormalImage(const Value: shortint);
  223.     procedure SetSelectImage(const Value: shortint);
  224.     function GetLevel: integer;
  225.     procedure SetVisible(const Value: boolean);
  226.     function GetVisible: boolean;
  227.   protected
  228.     function GetChild(Index: integer): TKnotItem;
  229.     function GetGrid: TDCCustomTreeGrid;
  230.     function GetOwner: TKnotItems;
  231.     function GetParent: TKnotItem;
  232.     procedure SetChild(Index: integer; const Value: TKnotItem);
  233.     procedure SetParent(const Value: TKnotItem);
  234.   public
  235.     constructor Create(AOwner: TKnotItems; AParent: TKnotItem; AName: string); virtual;
  236.     procedure Clear;
  237.     procedure Collapse(Recurse: boolean);
  238.     destructor Destroy; override;
  239.     function DisplayRect(TextOnly: boolean): TRect;
  240.     procedure Expand(Recurse: boolean);
  241.     procedure EditText;
  242.     procedure EndEdit(Cancel: boolean);
  243.     function GetNext: TKnotItem;
  244.     function GetNextSibling: TKnotItem;
  245.     function GetNextVisible: TKnotItem;
  246.     function GetNextSiblingVisible: TKnotItem;
  247.     function GetPrev: TKnotItem;
  248.     function GetPrevSibling: TKnotItem;
  249.     function GetPrevVisible: TKnotItem;
  250.     function GetPrevSiblingVisible: TKnotItem;
  251.     property Changed: boolean index 5 read GetFlagValue write SetFlagValue;
  252.     property ChildCount: integer read GetChildCount;
  253.     property Childs[Index: integer]: TKnotItem read GetChild write SetChild;
  254.     property Data: Pointer read FData write SetData;
  255.     property Enabled: boolean index 2 read GetFlagValue write SetValueEx;
  256.     property Expanded: boolean index 0 read GetFlagValue write SetValueEx;
  257.     property Grid: TDCCustomTreeGrid read GetGrid;
  258.     property Owner: TKnotItems read GetOwner;
  259.     property Index: integer read FIndex;
  260.     property HasChildren: boolean index 3 read GetFlagValue write SetValueEx;
  261.     property KnotID: integer read FKnotID;
  262.     property Level: integer read GetLevel;
  263.     property LockItems: boolean index 4 read GetFlagValue write SetFlagValue;
  264.     property Name: string read FName write SetName;
  265.     property NormalImage: shortint read FNormalImage write SetNormalImage;
  266.     property Parent: TKnotItem read GetParent write SetParent;
  267.     property SelectImage: shortint read FSelectImage write SetSelectImage;
  268.     property State: TKnotState read FState write SetState;
  269.     property Visible: boolean read GetVisible write SetVisible;
  270.     property VisibleChilds: integer read GetVisibleChildCount;
  271.     property VisibleKnotCount: integer read GetVisibleKnotCount;
  272.   end;
  273.  
  274.   TKnotItems = class(TPersistent)
  275.   private
  276.     FKnotItemClass: TKnotItemClass;
  277.     FLastKnotID: integer;
  278.     FOwner: TDCCustomTreeGrid;
  279.     FState: TKnotState;
  280.     FRootKnot: TKnotItem;
  281.     FUpdateCount: integer;
  282.     function GetCount: integer;
  283.     function GetVisibleKnotCount: integer;
  284.     procedure UpdateTreeGrid;
  285.     function GetUpdateingState: boolean;
  286.     procedure SetUpdateState(Updating: Boolean);
  287.     procedure DeleteChildKnot(KnotItem: TKnotItem; KnotIndex: integer);
  288.     function GetRootKnot: TKnotItem;
  289.   protected
  290.     function ComparePos(KnotItem1, KnotItem2: TKnotItem): integer;
  291.     function GetItem(Index: integer): TKnotItem;
  292.     procedure SetItem(Index: integer; const Value: TKnotItem);
  293.   public
  294.     constructor Create(AOwner: TDCCustomTreeGrid; AKnotItemClass: TKnotItemClass);
  295.     destructor Destroy; override;
  296.     function Add(Name: string; Position: integer = KNOT_END): TKnotItem;
  297.     function AddChild(ParentKnot: TKnotItem; Name: string;
  298.       Position: integer = KNOT_END): TKnotItem;
  299.     function Delete(Knot: TKnotItem): boolean;
  300.     procedure Move(KnotItem, DestKnot: TKnotItem; Position: integer = KNOT_END);
  301.     procedure Exchange(KnotItem1, KnotItem2: TKnotItem);
  302.     procedure Clear;
  303.     function SelectKnot(KnotItem: TKnotItem; Offset: integer): TKnotItem;
  304.     function GetFirstNode: TKnotItem;
  305.     function GetFirstVisibleNode: TKnotItem;
  306.     function GetKnot(KnotID: integer; var KnotItem: TKnotItem): boolean;
  307.     procedure BeginUpdate(LockScreen: boolean = False);
  308.     procedure EndUpdate;
  309.     procedure SetState(Value: TKnotState);
  310.     procedure RebuildIndexes(ParentKnot: TKnotItem; FirstIndex: integer);
  311.     procedure LockRebuilds(KnotItem: TKnotItem; Lock: boolean);
  312.     property Owner: TDCCustomTreeGrid read FOwner;
  313.     property Grid: TDCCustomTreeGrid read FOwner;
  314.     property Items[Index: integer]: TKnotItem read GetItem write SetItem;
  315.     property Count:integer read GetCount;
  316.     property LastKnotID: integer read FLastKnotID;
  317.     property VisibleKnotCount: integer read GetVisibleKnotCount;
  318.     property State: TKnotState read FState;
  319.     property Updating: boolean read GetUpdateingState;
  320.     property Root: TKnotItem read GetRootKnot;
  321.     property First: TKnotItem read GetFirstNode;
  322.   end;
  323.  
  324.   TKnotBookmarkList = class
  325.   private
  326.     FList: TList;
  327.     FGrid: TDCCustomTreeGrid;
  328.     FCache: integer;
  329.     FCacheIndex: Integer;
  330.     FCacheFind: boolean;
  331.     FSortItems: boolean;
  332.     function GetCount: integer;
  333.     procedure ListChanged;
  334.     function GetItem(Index: Integer): integer;
  335.     function Compare(const KnotID1, KnotID2: integer): Integer;
  336.   public
  337.     constructor Create(AGrid: TDCCustomTreeGrid);
  338.     destructor Destroy; override;
  339.     procedure Clear;
  340.     procedure Delete;
  341.     procedure Sort;
  342.     procedure Select(KnotItem: TKnotItem; Value: boolean);
  343.     procedure SelectAll;
  344.     function Find(const KnotID: integer; var Index: Integer): Boolean;
  345.     function IndexOf(const KnotID: integer): Integer;
  346.     function KnotSelected(const KnotID: integer): Boolean;
  347.     property Count: Integer read GetCount;
  348.     property Items[Index: Integer]: integer read GetItem; default;
  349.     property SortItems: boolean read FSortItems write FSortItems;
  350.   end;
  351.  
  352.   TTreeGridOption = (tgEditing, tgAlwaysShowEditor, tgTitles, tgIndicator,
  353.     tgColumnResize, tgColLines, tgRowLines, tgColMoving, tgRowMoving, tgTabs,
  354.     tgRowSelect,  tgAlwaysShowSelection, tgConfirmDelete, tgCancelOnExit,
  355.     tgMultiSelect, tgMarker, tgTreePath, tgTitleClicked, tgUserRowHeight,
  356.     tgRowSizing, tgHighlightRow, tgFlatButtons, tgTreePathResize, tgFixedLines,
  357.     tgCompleteLines, tgColumnSizing, tgGrouping, tgTreePathCompletion,
  358.     tgDoubleBuffered, tgDrawFixedLine, tgAutoSize);
  359.  
  360.   TTreeGridOptionEx =(tgeInsertSelect, tgeMarkerMenu, tgeShadowSelection,
  361.     tgeRightClickSelect, tgeTreeSelect, tgeShowLines, tgeShowButtons);
  362.  
  363.   TTreeGridMessageType = (mtLoadData, mtEmptyColumns);
  364.  
  365.   TTreeGridOptions   = set of TTreeGridOption;
  366.   TTreeGridOptionsEx = set of TTreeGridOptionEx;
  367.  
  368.   TTreeDrawCollumnCellEvent = procedure (Sender: TObject; const Rect: TRect;
  369.     Canvas: TCanvas; DataCol: Integer; Column: TKnotColumn; KnotItem: TKnotItem;
  370.     State: TGridDrawState) of object;
  371.   TTreeCellTextEvent  = procedure (Sender: TObject; KnotItem: TKnotItem; var
  372.     Text: string; var DefaultDraw: boolean) of object;
  373.   TTreeGridClickEvent = procedure (Column: TKnotColumn) of object;
  374.   TTreeGridClipEvent  = procedure (Sender: TObject; X, Y : LongInt;
  375.     var Show: boolean) of object;
  376.   TTreeGridKnotEvent  = procedure (KnotItem: TKnotItem;
  377.     var Apply: boolean) of object;
  378.   TTreeGridEditEvent  = procedure (KnotItem: TKnotItem;
  379.     var Edit: TDCCustomChoiceEdit; Column: TKnotColumn; var CanCreate: boolean) of object;
  380.   TTreeGridUpdateEvent  = procedure (KnotItem: TKnotItem;
  381.     var Edit: TDCCustomChoiceEdit; Column: TKnotColumn) of object;
  382.   TTreeGridKnotDeleteEvent = procedure (KnotItem: TKnotItem;
  383.     var Apply: boolean; ComponentState: TComponentState) of object;
  384.   TTreeGridCommentEvent = procedure(Sender: TObject; Mode: integer;
  385.     Column: TKnotColumn) of object;
  386.   TTreeGridSelectKnot  = procedure(Sender: TObject; KnotItem: TKnotItem) of object;
  387.   TPaintMessageEvent   = procedure(Sender: TObject; Canvas: TCanvas; ARect: TRect;
  388.     MessageType: TTreeGridMessageType; UpdateMessage: string) of object;
  389.   TTreeGridExpanded    = procedure(Sender: TObject; KnotItem: TKnotItem) of object;
  390.  
  391.   TTreeGridHitTest    = (htNowere, htOnButton, htOnIcon, htOnLabel);
  392.   TFixedCell = (fcNone, fcIndicator, fcMarker, fcTreePath, fcColumn);
  393.  
  394.   TTreePathValue  = (tpColor, tpFont);
  395.   TTreePathValues = set of TTreePathValue;
  396.  
  397.   TTreePath = class(TPersistent)
  398.   private
  399.     FColor: TColor;
  400.     FAssignedValues: TTreePathValues;
  401.     FGrid: TDCCustomTreeGrid;
  402.     FFont: TFont;
  403.     function DefaultColor: TColor;
  404.     function DefaultFont: TFont;
  405.     function GetColor: TColor;
  406.     function IsColorStored: Boolean;
  407.     function IsFontStored: Boolean;
  408.     procedure FontChanged(Sender: TObject);
  409.     procedure SetColor(const Value: TColor);
  410.     function GetFont: TFont;
  411.     procedure SetFont(const Value: TFont);
  412.   public
  413.     procedure Assign(Source: TPersistent); override;
  414.     constructor Create(AGrid: TDCCustomTreeGrid);
  415.     property AssignedValues: TTreePathValues read FAssignedValues;
  416.   published
  417.     property Color: TColor read GetColor write SetColor stored
  418.       IsColorStored;
  419.     property Font: TFont read GetFont write SetFont stored IsFontStored;
  420.   end;
  421.  
  422.   TDCCustomTreeGrid = class(TDCCustomGrid)
  423.   private
  424.     FActiveKnot: TKnotItem;
  425.     FBookMarkSize: integer;
  426.     FBookmarks: TKnotBookmarkList;
  427.     FColumnFooter: TKnotColumnFooter;
  428.     FClipDown: boolean;
  429.     FClipPopup: TObject;
  430.     FColumnCell: integer;
  431.     FColumns: TKnotColumns;
  432.     FCurrentCol: Integer;
  433.     FCurrentPos: array[1..2] of TBookmark;
  434.     FDefaultDrawing: boolean;
  435.     FEditorMode: boolean;
  436.     FEditTimerID: integer;
  437.     FFirstGridCell: integer;
  438.     FFirstIndex: integer;
  439.     FFirstVisible: TKnotItem;
  440.     FHintRow: integer;
  441.     FHintWindow: TDCMessageWindow;
  442.     FImageChangeLink: TChangeLink;
  443.     FImages: TImageList;
  444.     FIndent: integer;
  445.     FInplaceCol: longint;
  446.     FInplaceEdit: TDCCustomChoiceEdit;
  447.     FInplaceRow: longint;
  448.     FIsModified: boolean;
  449.     FIsESCKey: boolean;
  450.     FKnots: TKnotItems;
  451.     FKnotCount: integer;
  452.     FLayoutLock: Byte;
  453.     FLockScreen: boolean;
  454.     FLockScroll: boolean;
  455.     FLockWindow: boolean;
  456.     FMouseDownRow: integer;
  457.     FMousePoint: TPoint;
  458.     FOnCellClick: TTreeGridClickEvent;
  459.     FOnCellDblClick: TTreeGridClickEvent;
  460.     FOnClipButtonClick: TNotifyEvent;
  461.     FOnClipClick: TTreeGridClipEvent;
  462.     FOnCollapsed: TTreeGridExpanded;
  463.     FOnColumnComment: TTreeGridCommentEvent;
  464.     FOnColumnMoved: TMovedEvent;
  465.     FOnCreateCellEdit: TTreeGridEditEvent;
  466.     FOnDelete: TTreeGridKnotDeleteEvent;
  467.     FOnDestroyCellEdit: TNotifyEvent;
  468.     FOnDrawColumnCell: TTreeDrawCollumnCellEvent;
  469.     FOnExpanded: TTreeGridExpanded;
  470.     FOnInsert: TTreeGridKnotEvent;
  471.     FOnPaintMessage: TPaintMessageEvent;
  472.     FOnRowMoved: TMovedEvent;
  473.     FOnSelectCell: TSelectCellEvent;
  474.     FOnSelectKnot: TTreeGridSelectKnot;
  475.     FOnTitleClick:TTreeGridClickEvent;
  476.     FOnTopLeftChanged: TNotifyEvent;
  477.     FOnTreeCellText: TTreeCellTextEvent;
  478.     FOnUpdate: TTreeGridUpdateEvent;
  479.     FOptions: TTreeGridOptions;
  480.     FOptionsEx: TTreeGridOptionsEx;
  481.     FPopupTitle: TPopupMenu;
  482.     FRowUpdated: boolean;
  483.     FSelectedKnot: TKnotItem;
  484.     FSelecting: boolean;
  485.     FSelectionKnot: TKnotItem;
  486.     FSelfChangingTitleFont: Boolean;
  487.     FSizingIndex: integer;
  488.     FSizingOff: integer;
  489.     FTitleFont: TFont;
  490.     FTitleOffset, FIndicatorOffset: Byte;
  491.     FTreeImages: TImageList;
  492.     FTreePathWidth: integer;
  493.     FTreePathSizing: boolean;
  494.     FTreePath: TTreePath;
  495.     FUpdateLock: Byte;
  496.     function AlwaysShowSelection: boolean;
  497.     procedure SetColumns(const Value: TKnotColumns);
  498.     procedure InternalLayout;
  499.     procedure MoveCol(RawCol, Direction: Integer);
  500.     procedure SetOptions(Value: TTreeGridOptions);
  501.     procedure TitleFontChanged(Sender: TObject);
  502.     procedure DoSelection(Select: Boolean; Shift: TShiftState; Direction: Integer);
  503.     procedure UpdateRowCount;
  504.     procedure UpdateActive;
  505.     function AcquireFocus: Boolean;
  506.     procedure DataChanged;
  507.     procedure UpdateEditData;
  508.     procedure SetTitleFont(const Value: TFont);
  509.     procedure SetTreePathWidth(const Value: integer);
  510.     procedure SetTitleHeight;
  511.     procedure SetClipDown(const Value: boolean);
  512.     function GetSelectedIndex: Integer;
  513.     procedure SetSelectedIndex(Value: Integer);
  514.     function GetTreePathWidth: integer;
  515.     function HideEditor: boolean;
  516.     function Modified: boolean;
  517.     procedure SetImages(const Value: TImageList);
  518.     function GetHintTreeOffset(KnotItem: TKnotItem; Hint: TTreeGridHitTest): integer;
  519.     procedure SetPopupTitle(const Value: TPopupMenu);
  520.     procedure InsertKnot(ParentKnot: TKnotItem; lChild: boolean; Shift: TShiftState);
  521.     procedure MarkKnot;
  522.     procedure NextRow(Select: Boolean; Insert: boolean; Shift: TShiftState;
  523.       AOffset: integer = 1);
  524.     procedure PrevRow(Select: Boolean; Shift: TShiftState; AOffset: integer = 1);
  525.     procedure ClearSelection;
  526.     function Eof: boolean;
  527.     function BoxRectEx(ALeft, ATop, ARight, ABottom: Longint): TRect;
  528.     procedure ImageListChange(Sender: TObject);
  529.     procedure SetSelectedKnot(KnotItem: TKnotItem);
  530.     procedure SetSelected(const Value: TKnotItem);
  531.     function GetPosition: TBookMark;
  532.     procedure SetPosition(const Value: TBookMark);
  533.     function GetTreeLableOffset(KnotItem: TKnotItem): integer;
  534.     procedure FreeEditTimer;
  535.     function CalcMaxTopLeft(const Coord: TGridCoord;
  536.       const DrawInfo: TGridDrawInfo): TGridCoord;
  537.     function CanModifyHScrollBar(ScrollBar, ScrollCode, Pos: Cardinal;
  538.       UseRightToLeft: Boolean; var NewLeft: integer): boolean;
  539.     procedure SetOptionsEx(const Value: TTreeGridOptionsEx);
  540.     procedure SetIndent(const Value: integer);
  541.     procedure InitGridPos;
  542.     procedure SetColumnFooter(const Value: TKnotColumnFooter);
  543.     procedure SetTreePath(const Value: TTreePath);
  544.   protected
  545.     function  AcquireLayoutLock: Boolean;
  546.     procedure BeginLayout; override;
  547.     procedure BeginUpdate;
  548.     function BookmarksEqual(Bookmark1, Bookmark2: TBookmark): boolean; virtual;
  549.     procedure CalcSizingState(X, Y: Integer; var State: TGridState;
  550.       var Index: Longint; var SizingPos, SizingOfs: Integer;
  551.       var FixedInfo: TGridDrawInfo); override;
  552.     function CanColResize(ACol: integer): boolean; override;
  553.     function CanEditModify: Boolean; override;
  554.     procedure CellClick(Column: TKnotColumn); dynamic;
  555.     procedure CellDblClick(Column: TKnotColumn); dynamic;
  556.     procedure ClipButtonClick(Sender: TObject); virtual;
  557.     procedure ClipClick(ACellType: TFixedCell); dynamic;
  558.     procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
  559.     procedure CMExit(var Message: TMessage); message CM_EXIT;
  560.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  561.     procedure CMInvalidValue(var Message: TMessage); message CM_INVALIDVALUE;
  562.     procedure CMKnotChanged(var Message: TMessage); message CM_KNOTCHANGED;
  563.     procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  564.     procedure CMParentFontChanged(var Message: TMessage); message CM_PARENTFONTCHANGED;
  565.     procedure CMPopupHintInfo(var Message: TMessage); message CM_POPUPHINTINFO;
  566.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  567.     procedure ColumnMoved(FromIndex, ToIndex: Longint); override;
  568.     procedure ColWidthsChanged; override;
  569.     function CreateColumns: TKnotColumns; virtual;
  570.     function CreateKnots: TKnotItems; virtual;
  571.     procedure CreateParams(var Params: TCreateParams); override;
  572.     procedure CreateWnd; override;
  573.     function  DataToRawColumn(ACol: Integer): Integer;
  574.     function DataVisible: boolean; virtual;
  575.     procedure DblClick; override;
  576.     function DeletePrompt: boolean; virtual;
  577.     procedure DeleteRecords(AtOnce: boolean);
  578.     procedure DoCollapse(KnotItem: TKnotItem); dynamic;
  579.     procedure DoColumnClick(Shift: TShiftState; ColIndex: integer); override;
  580.     procedure DoColumnComment(Mode: integer; Column: TKnotColumn); virtual;
  581.     procedure DoCreateCellEdit(Column: TKnotColumn;
  582.       var Edit: TDCCustomChoiceEdit; var CanCreate: boolean); virtual;
  583.     procedure DoDelete(KnotItem: TKnotItem; var Apply: boolean;
  584.       ComponentState: TComponentState); virtual;
  585.     procedure DoDestroyCellEdit; virtual;
  586.     procedure DoDrawColumnCell(Canvas: TCanvas; ARect: TRect; ACol: integer;
  587.       AColumn: TKnotColumn; AKnot: TKnotItem; AState: TGridDrawState); virtual;
  588.     procedure DoExpand(KnotItem: TKnotItem); dynamic;
  589.     procedure DoInsert(KnotItem: TKnotItem; var Apply: boolean); virtual;
  590.     function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  591.     function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  592.     procedure DoSelectCell(Sender: TObject; ACol, ARow: Longint;
  593.       var CanSelect: Boolean); virtual;
  594.     procedure DoUpdate(KnotItem: TKnotItem; var Edit: TDCCustomChoiceEdit;
  595.       Column: TKnotColumn); virtual;
  596.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
  597.     function DrawTitleCell(ACanvas: TCanvas; ACol, ARow: Integer; ARect: TRect;
  598.       BorderState: TDrawBorerState; AFillRect, ADraw: boolean): TPoint; override;
  599.     procedure EndLayout; override;
  600.     procedure EndUpdate;
  601.     function FlatButtons: boolean; override;
  602.     function GetBookmark(KnotItem: TKnotItem): TBookmark;
  603.     procedure GetBookmarkData(KnotItem: TKnotItem; Data:Pointer); virtual;
  604.     function GetBorderStyle: TEdgeBorderStyle; override;
  605.     function GetClientRect: TRect; override;
  606.     function GetCellByType(ACellType: TFixedCell): integer;
  607.     function GetFixedCellType(ACol, AOffset: integer): TFixedCell;
  608.     function GetKnots: TKnotItems;
  609.     function GetPopupMenu: TPopupMenu; override;
  610.     function GetRealColWidth(ColIndex: integer): integer; override;
  611.     function GetTopLeft: TGridCoord;
  612.     function GetTreePathCaption(KnotItem: TKnotItem; var Text: string): boolean; virtual;
  613.     procedure GotoBookmark(Bookmark: TBookmark); virtual;
  614.     procedure GroupBoxChanged; override;
  615.     procedure HideHintWindow;
  616.     function  HighlightCell(DataCol, DataRow: Integer;
  617.       AState: TGridDrawState; KnotItem: TKnotItem): Boolean; virtual;
  618.     procedure InvalidateTitles;
  619.     procedure InvalidateSelected;
  620.     procedure LayoutChanged; virtual;
  621.     procedure Loaded; override;
  622.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  623.       X, Y: Integer); override;
  624.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  625.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  626.       X, Y: Integer); override;
  627.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  628.     function  RawToDataColumn(ACol: Integer): Integer; override;
  629.     procedure ResizeColWidth(ACol, AWidth: integer); override;
  630.     procedure RowMoved(FromIndex, ToIndex: Longint); override;
  631.     function SelectCell(ACol, ARow: Longint): Boolean; override;
  632.     procedure SetColumnAttributes; virtual;
  633.     procedure SetKnots(const Value: TKnotItems);
  634.     procedure ShowHintWindow(X, Y, ALeft, ATop, AOff: integer; Text: string);
  635.     function ShowEditorChar(Ch: Char): boolean;
  636.     procedure TitleClick(Column: TKnotColumn); dynamic;
  637.     procedure TopLeftChanged; override;
  638.     procedure WMChar(var Msg: TWMChar); message WM_CHAR;
  639.     procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  640.     procedure WMKillFocus(var Message: TMessage); message WM_KillFocus;
  641.     procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL;
  642.     procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
  643.     procedure WMNCLButtonDown(var Message: TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
  644.     procedure WMNCPaint(var Message: TMessage); message WM_NCPAINT;
  645.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  646.     procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
  647.     procedure WMSetFocus(var Message: TWMSetFocus); message WM_SetFOCUS;
  648.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  649.     procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  650.     procedure WMTimer(var Msg: TWMTimer); message WM_TIMER;
  651.     property BookmarkSize: integer read FBookmarkSize write FBookmarkSize;
  652.     property DefaultDrawing: Boolean read FDefaultDrawing write FDefaultDrawing default True;
  653.     property IndicatorOffset: Byte read FIndicatorOffset;
  654.     property Indent: integer read FIndent write SetIndent;
  655.     property Knots: TKnotItems read GetKnots write SetKnots;
  656.     property Options: TTreeGridOptions read FOptions write SetOptions
  657.       default [tgEditing, tgTitles, tgIndicator, tgColumnResize, tgColLines,
  658.       tgRowLines, tgTabs, tgConfirmDelete, tgCancelOnExit, tgTreePathResize,
  659.       tgFixedLines, tgColMoving];
  660.     property OptionsEx: TTreeGridOptionsEx read FOptionsEx write SetOptionsEx
  661.       default [tgeInsertSelect, tgeMarkerMenu, tgeShadowSelection, tgeShowButtons];
  662.     property TitleFont: TFont read FTitleFont write SetTitleFont;
  663.     property UpdateLock: Byte read FUpdateLock;
  664.     property TreePathWidth: integer read GetTreePathWidth write SetTreepathWidth;
  665.     property LayoutLock: Byte read FLayoutLock;
  666.     property SelectedRows: TKnotBookmarkList read FBookmarks;
  667.     property OnColumnMoved: TMovedEvent read FOnColumnMoved write FOnColumnMoved;
  668.     property OnCellClick: TTreeGridClickEvent read FOnCellClick write FOnCellClick;
  669.     property OnCellDblClick: TTreeGridClickEvent read FOnCellDblClick write FOnCellDblClick;
  670.     property OnTitleClick: TTreeGridClickEvent read FOnTitleClick write FOnTitleClick;
  671.     property OnClipClick: TTreeGridClipEvent read FOnClipClick write FOnClipClick;
  672.     property OnDelete: TTreeGridKnotDeleteEvent read FOnDelete write FOnDelete;
  673.     property OnInsert: TTreeGridKnotEvent read FOnInsert write FOnInsert;
  674.     property OnUpdate: TTreeGridUpdateEvent read FOnUpdate write FOnUpdate;
  675.     property SelectedKnot: TKnotItem read FSelectedKnot write SetSelected;
  676.     property SelectedIndex: Integer read GetSelectedIndex write SetSelectedIndex;
  677.     property OnDrawColumnCell: TTreeDrawCollumnCellEvent read FOnDrawColumnCell write FOnDrawColumnCell;
  678.     property OnTreeCellText: TTreeCellTextEvent read FOnTreeCellText write FOnTreeCellText;
  679.     property OnRowMoved: TMovedEvent read FOnRowMoved write FOnRowMoved;
  680.     property OnSelectCell: TSelectCellEvent read FOnSelectCell write FOnSelectCell;
  681.     property OnTopLeftChanged: TNotifyEvent read FOnTopLeftChanged write FOnTopLeftChanged;
  682.     property OnCreateCellEdit: TTreeGridEditEvent read FOnCreateCellEdit write FOnCreateCellEdit;
  683.     property OnDestroyCellEdit: TNotifyEvent read FOnDestroyCellEdit write FOnDestroyCellEdit;
  684.     property OnClipButtonClick: TNotifyEvent read FOnClipButtonClick write FOnClipButtonClick;
  685.     property OnColumnComment: TTreeGridCommentEvent read FOnColumnComment write FOnColumnComment;
  686.     property PopupTitle: TPopupMenu read FPopupTitle write SetPopupTitle;
  687.     property RowModified: boolean read Modified;
  688.     property OnSelectKnot: TTreeGridSelectKnot read FOnSelectKnot write FOnSelectKnot;
  689.     property OnPaintMessage: TPaintMessageEvent read FOnPaintMessage write FOnPaintMessage;
  690.     property OnExpanded: TTreeGridExpanded read FOnExpanded write FOnExpanded;
  691.     property OnCollapsed: TTreeGridExpanded read FOnCollapsed write FOnCollapsed;
  692.     property Footer: TKnotColumnFooter read FColumnFooter write SetColumnFooter;
  693.     property TreePath: TTreePath read FTreePath write SetTreePath;
  694.   public
  695.     procedure SetModified(Value: boolean);
  696.     constructor Create(AOwner: TComponent); override;
  697.     destructor Destroy; override;
  698.     procedure RowHeightsChanged; override;
  699.     function GetHitTestInfoAt(KnotItem: TKnotItem; X,Y: integer): TTreeGridHitTest;
  700.     property ClipDown: boolean read FClipDown write SetClipDown;
  701.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  702.     procedure KeyPress(var Key: Char); override;
  703.     procedure ShowClipPopup(ACellType: TFixedCell; AClipPopup: TObject); virtual;
  704.     procedure HideClipPopup;
  705.     procedure Paint; override;
  706.     procedure ShowEditor;
  707.     procedure ShowTreePathEditor;
  708.     procedure SavePosition;
  709.     procedure RestPosition;
  710.     procedure Update; override;
  711.     procedure SelectItems(Mode: TSelectMode);
  712.     procedure Sort(Level: integer; Compare: TGridSortCompare; Data: integer);
  713.     function GroupingEnabled: boolean; override;
  714.     property ColumnFooter: TKnotColumnFooter read FColumnFooter;
  715.     property Columns: TKnotColumns read FColumns write SetColumns;
  716.     property Font;
  717.     property Images: TImageList read FImages write SetImages;
  718.     property InEditorMode: boolean read FEditorMode;
  719.     property Position: TBookMark read GetPosition write SetPosition;
  720.   end;
  721.  
  722.   TDCTreeGrid = class(TDCCustomTreeGrid)
  723.   public
  724.     property Canvas;
  725.     property Knots;
  726.     property ScrollBars;
  727.     property SelectedRows;
  728.     property SelectedKnot;
  729.     property SelectedIndex;
  730.     property Col;
  731.     property Row;
  732.     property RowCount;
  733.     property ColCount;
  734.     property RowModified;
  735.     property GroupBox;
  736.   published
  737.     property Align;
  738.     property Anchors;
  739.     property BiDiMode;
  740.     property BorderStyle;
  741.     property Color;
  742.     property Columns;
  743.     property Constraints;
  744.     property Ctl3D;
  745.     property DefaultDrawing;
  746.     property DragCursor;
  747.     property DragKind;
  748.     property DragMode;
  749.     property Enabled;
  750.     property FixedColor;
  751.     property Font;
  752.     property Indent;
  753.     property Options;
  754.     property OptionsEx;
  755.     property ParentBiDiMode;
  756.     property ParentColor;
  757.     property ParentCtl3D;
  758.     property ParentFont;
  759.     property ParentShowHint;
  760.     property PopupMenu;
  761.     property ShowHint;
  762.     property TabOrder;
  763.     property TabStop;
  764.     property Visible;
  765.     property OnColumnMoved;
  766.     property OnDblClick;
  767.     property OnDragDrop;
  768.     property OnDragOver;
  769.     property OnEndDock;
  770.     property OnEndDrag;
  771.     property OnEnter;
  772.     property OnExit;
  773.     property OnKeyDown;
  774.     property OnKeyPress;
  775.     property OnKeyUp;
  776.     property OnStartDock;
  777.     property OnStartDrag;
  778.     property Images;
  779.     property DefaultRowHeight;
  780.     property OnMouseDown;
  781.     property OnMouseMove;
  782.     property OnMouseUp;
  783.     property OnCellClick;
  784.     property OnCellDblClick;
  785.     property OnTitleClick;
  786.     property OnClipClick;
  787.     property OnDelete;
  788.     property OnInsert;
  789.     property OnUpdate;
  790.     property OnDrawColumnCell;
  791.     property OnTreeCellText;
  792.     property TreePathWidth;
  793.     property OnRowMoved;
  794.     property OnSelectCell;
  795.     property OnTopLeftChanged;
  796.     property OnCreateCellEdit;
  797.     property OnDestroyCellEdit;
  798.     property OnClipButtonClick;
  799.     property OnColumnComment;
  800.     property PopupTitle;
  801.     property OnSelectKnot;
  802.     property OnPaintMessage;
  803.     property OnExpanded;
  804.     property OnCollapsed;
  805.     property OnGroupBoxInsert;
  806.     property OnGroupBoxRemove;
  807.     property OnGroupBoxMove;
  808.     property Footer;
  809.     property TreePath;
  810.   end;
  811.  
  812.   {Inplace Editors}
  813.   TSelection = record
  814.     StartPos, EndPos: Integer;
  815.   end;
  816.  
  817.   TDCInplaceChoiceEdit = class(TDCChoiceEdit)
  818.   private
  819.     FGrid: TDCCustomTreeGrid;
  820.     procedure SetGrid(Value: TDCCustomTreeGrid);
  821.   protected
  822.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  823.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  824.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  825.       MousePos: TPoint): Boolean; override;
  826.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  827.   public
  828.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  829.     procedure KeyPress(var Key: Char); override;
  830.     procedure ChoiceClick(Sender:TObject); override;
  831.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  832.   end;
  833.  
  834.   TDCInplaceDateEdit = class(TDCDateEdit)
  835.   private
  836.     FGrid: TDCCustomTreeGrid;
  837.     procedure SetGrid(Value: TDCCustomTreeGrid);
  838.   protected
  839.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  840.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  841.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  842.       MousePos: TPoint): Boolean; override;
  843.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  844.   public
  845.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  846.     procedure KeyPress(var Key: Char); override;
  847.     procedure ChoiceClick(Sender:TObject); override;
  848.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  849.   end;
  850.  
  851.   TDCInplaceFloatEdit = class(TDCFloatEdit)
  852.   private
  853.     FGrid: TDCCustomTreeGrid;
  854.     procedure SetGrid(Value: TDCCustomTreeGrid);
  855.   protected
  856.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  857.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  858.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  859.       MousePos: TPoint): Boolean; override;
  860.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  861.   public
  862.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  863.     procedure KeyPress(var Key: Char); override;
  864.     procedure ChoiceClick(Sender:TObject); override;
  865.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  866.   end;
  867.  
  868.   TDCInplaceGridEdit = class(TDCGridEdit)
  869.   private
  870.     FGrid: TDCCustomTreeGrid;
  871.     procedure SetGrid(Value: TDCCustomTreeGrid);
  872.   protected
  873.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  874.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  875.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  876.       MousePos: TPoint): Boolean; override;
  877.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  878.   public
  879.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  880.     procedure KeyPress(var Key: Char); override;
  881.     procedure ChoiceClick(Sender:TObject); override;
  882.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  883.   end;
  884.  
  885.   TDCInplaceTreeEdit = class(TDCTreeEdit)
  886.   private
  887.     FGrid: TDCCustomTreeGrid;
  888.     procedure SetGrid(Value: TDCCustomTreeGrid);
  889.   protected
  890.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  891.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  892.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  893.       MousePos: TPoint): Boolean; override;
  894.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  895.   public
  896.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  897.     procedure KeyPress(var Key: Char); override;
  898.     procedure ChoiceClick(Sender:TObject); override;
  899.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  900.   end;
  901.  
  902.   TDCInplaceComboBox = class(TDCComboBox)
  903.   private
  904.     FGrid: TDCCustomTreeGrid;
  905.     procedure SetGrid(Value: TDCCustomTreeGrid);
  906.   protected
  907.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  908.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  909.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  910.       MousePos: TPoint): Boolean; override;
  911.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  912.   public
  913.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  914.     procedure KeyPress(var Key: Char); override;
  915.     procedure ChoiceClick(Sender:TObject); override;
  916.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  917.   end;
  918.  
  919. {$IFDEF DELPHI_V5UP}
  920.   TDCInplaceADOGridEdit = class(TDCADOGridEdit)
  921.   private
  922.     FGrid: TDCCustomTreeGrid;
  923.     procedure SetGrid(Value: TDCCustomTreeGrid);
  924.   protected
  925.     procedure CMWantSpecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  926.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  927.     function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  928.       MousePos: TPoint): Boolean; override;
  929.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  930.   public
  931.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  932.     procedure KeyPress(var Key: Char); override;
  933.     procedure ChoiceClick(Sender:TObject); override;
  934.     property Grid: TDCCustomTreeGrid read FGrid write SetGrid;
  935.   end;
  936. {$ENDIF}
  937.  
  938. implementation
  939. uses
  940.   DCEditButton;
  941.  
  942. {$R *.RES}
  943. type
  944.  
  945.   TKnotClipPopup = class(TDBClipPopup)
  946.   private
  947.     FCellType: TFixedCell;
  948.   protected
  949.     procedure ButtonClick(Sender: TObject); override;
  950.   public
  951.     procedure AddButtons; override;
  952.     property CellType: TFixedCell read FCellType write FCellType;
  953.   end;
  954.  
  955. const
  956.   NE_EMPTY_KNOT = '$Empty Knot';
  957.   NE_ROOT_KNOT  = '$DC.sp_ROOT';
  958.   TreeIconWidth = 20;
  959.  
  960. const
  961.   bmExpand     = 'DC_TGEXPAND'    ; nbmExpand     = 0;
  962.   bmCollapse   = 'DC_TGCOLLAPSE'  ; nbmCollapse   = 1;
  963.   bmExpandR    = 'DC_TGEXPANDR'   ; nbmExpandR    = 2;
  964.   bmCollapseR  = 'DC_TGCOLLAPSER' ; nbmCollapseR  = 3;
  965.  
  966.   pmSelectAll   = 0;
  967.   pmDeselectAll = 1;
  968.  
  969. var
  970.   DrawBitmap, TempBitmap: TBitmap;
  971.   UserCount: Integer;
  972.  
  973. function LongMulDiv(Mult1, Mult2, Div1: Longint): Longint; stdcall;
  974.   external 'kernel32.dll' name 'MulDiv';
  975.  
  976. procedure UsesBitmap;
  977. begin
  978.   if UserCount = 0 then
  979.   begin
  980.     DrawBitmap := TBitmap.Create;
  981.     TempBitmap := TBitmap.Create;
  982.   end;
  983.   Inc(UserCount);
  984. end;
  985.  
  986. procedure ReleaseBitmap;
  987. begin
  988.   Dec(UserCount);
  989.   if UserCount = 0 then begin
  990.     DrawBitmap.Free;
  991.     TempBitmap.Free;
  992.   end;
  993. end;
  994.  
  995. procedure KillMessage(Wnd: HWnd; Msg: Integer);
  996. // Delete the requested message from the queue, but throw back
  997. // any WM_QUIT msgs that PeekMessage may also return
  998. var
  999.   M: TMsg;
  1000. begin
  1001.   M.Message := 0;
  1002.   if PeekMessage(M, Wnd, Msg, Msg, pm_Remove) and (M.Message = WM_QUIT) then
  1003.     PostQuitMessage(M.wparam);
  1004. end;
  1005.  
  1006. procedure InplaceUpdateLoc(Sender: TDCCustomChoiceEdit; R: TRect; Canvas: TCanvas);
  1007. begin
  1008.   if Sender.DrawStyle <> fsNone then
  1009.   begin
  1010.     InflateRect(R, 1, 1);
  1011.     Dec(R.Left, 3);
  1012.   end;
  1013.   Sender.SetBounds(R.Left, R.Top, R.Right-R.Left, R.Bottom-R.Top);
  1014.   Canvas.Brush.Color := Sender.Color;
  1015.   R.Right := R.Right - Sender.ButtonWidth;
  1016.   Canvas.FillRect(R);
  1017.   Sender.Show;
  1018.   Sender.SetFocus;
  1019.   Sender.Repaint;
  1020. end;
  1021.  
  1022. procedure InplaceKeyDown(Sender:  TDCCustomChoiceEdit; Grid: TDCCustomTreeGrid;
  1023.   var Key: Word; Shift: TShiftState);
  1024.  
  1025.   procedure SendToParent;
  1026.   begin
  1027.     Grid.KeyDown(Key, Shift);
  1028.   end;
  1029.  
  1030.   procedure ParentEvent;
  1031.   var
  1032.     GridKeyDown: TKeyEvent;
  1033.   begin
  1034.     if Assigned(Grid) then
  1035.     begin
  1036.       GridKeyDown := Grid.OnKeyDown;
  1037.       if Assigned(GridKeyDown) then GridKeyDown(Grid, Key, Shift);
  1038.     end;
  1039.   end;
  1040.  
  1041.   function ForwardMovement: Boolean;
  1042.   begin
  1043.     Result := tgAlwaysShowEditor in Grid.Options;
  1044.   end;
  1045.  
  1046.   function Ctrl: Boolean;
  1047.   begin
  1048.     Result := ssCtrl in Shift;
  1049.   end;
  1050.  
  1051.   function Selection: TSelection;
  1052.   begin
  1053.     SendMessage(Sender.Handle, EM_GETSEL, Longint(@Result.StartPos), Longint(@Result.EndPos));
  1054.   end;
  1055.  
  1056.   function RightSide: Boolean;
  1057.   begin
  1058.     with Selection do
  1059.       Result := ((StartPos = 0) or (EndPos = StartPos)) and
  1060.         (EndPos = Sender.GetTextLen);
  1061.    end;
  1062.  
  1063.   function LeftSide: Boolean;
  1064.   begin
  1065.     with Selection do
  1066.       Result := (StartPos = 0) and ((EndPos = 0) or (EndPos = Sender.GetTextLen));
  1067.   end;
  1068. begin
  1069.   case Key of
  1070.     VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT:
  1071.       begin
  1072.         if not(ssAlt in Shift) then
  1073.         begin
  1074.           SendToParent;
  1075.           Key := 0;
  1076.         end;
  1077.       end;
  1078.     VK_ESCAPE:
  1079.       begin
  1080.         SendToParent;
  1081.         Key := 0;
  1082.       end;
  1083.     VK_INSERT:
  1084.       if Shift = [] then SendToParent
  1085.       else if (Shift = [ssShift]) and not Grid.CanEditModify then Key := 0;
  1086.     VK_LEFT : if ForwardMovement and (Ctrl or LeftSide ) then SendToParent;
  1087.     VK_RIGHT: if ForwardMovement and (Ctrl or RightSide) then SendToParent;
  1088.     VK_HOME : if ForwardMovement and (Ctrl or LeftSide ) then SendToParent;
  1089.     VK_END  : if ForwardMovement and (Ctrl or RightSide) then SendToParent;
  1090.     VK_F2:
  1091.       begin
  1092.         ParentEvent;
  1093.         if Key = VK_F2 then
  1094.         begin
  1095.           Sender.Deselect;
  1096.           Exit;
  1097.         end;
  1098.       end;
  1099.     VK_TAB:
  1100.       if not (ssAlt in Shift) then
  1101.       begin
  1102.         SendToParent;
  1103.         Key := 0;
  1104.       end;
  1105.   end;
  1106.   if (Key = VK_DELETE) and not Grid.CanEditModify then Key := 0;
  1107.   if Key <> 0 then ParentEvent;
  1108. end;
  1109.  
  1110. { TKnotColumn }
  1111. procedure TKnotColumn.Assign(Source: TPersistent);
  1112. begin
  1113.   if Source is TKnotColumn then
  1114.   begin
  1115.     try
  1116.       RestoreDefaults;
  1117.       Name := TKnotColumn(Source).Name;
  1118.       if cvColor in TKnotColumn(Source).AssignedValues then
  1119.         Color := TKnotColumn(Source).Color;
  1120.       if cvWidth in TKnotColumn(Source).AssignedValues then
  1121.       begin
  1122.         FWidth := TKnotColumn(Source).FWidth;
  1123.         FAssignedValues := FAssignedValues + [cvWidth];
  1124.       end;
  1125.       if cvFont in TKnotColumn(Source).AssignedValues then
  1126.         Font := TKnotColumn(Source).Font;
  1127.       if cvAlignment in TKnotColumn(Source).AssignedValues then
  1128.         Alignment := TKnotColumn(Source).Alignment;
  1129.       Title := TKnotColumn(Source).Title;
  1130.       Options := TKnotColumn(Source).Options;
  1131.       ItemIndex:= TKnotColumn(Source).ItemIndex;
  1132.       DisplayFormat := TKnotColumn(Source).DisplayFormat;
  1133.       FooterPanel.Visible := TKnotColumn(Source).FooterPanel.Visible;
  1134.       FooterPanel.Text := TKnotColumn(Source).FooterPanel.Text;
  1135.     finally
  1136.     end;
  1137.   end
  1138.   else
  1139.     inherited Assign(Source);
  1140. end;
  1141.  
  1142. constructor TKnotColumn.Create(Collection: TCollection);
  1143. var
  1144.   Grid: TDCCustomTreeGrid;
  1145. begin
  1146.   Grid := nil;
  1147.   if Assigned(Collection) and (Collection is TKnotColumns) then
  1148.     Grid := TKnotColumns(Collection).Grid;
  1149.   if Assigned(Grid) then Grid.BeginLayout;
  1150.   try
  1151.     inherited Create(Collection);
  1152.     FWidth := 50;
  1153.     FAlignment := taLeftJustify;
  1154.     FItemIndex := -1;
  1155.     FFont := TFont.Create;
  1156.     FFont.Assign(DefaultFont);
  1157.     FFont.OnChange := FontChanged;
  1158.     FTitle   := TKnotColumnTitle.Create(Self);
  1159.     FOptions := [kcVisible, kcShowEdit, kcSizing];
  1160.     FFooterPanel := TKnotColumnFooterPanel.Create(Grid.ColumnFooter.Panels);
  1161.     FFooterPanel.SetInternalColIndex(Self.Index);
  1162.   finally
  1163.     if Assigned(Grid) then Grid.EndLayout;
  1164.   end;
  1165. end;
  1166.  
  1167. function TKnotColumn.DefaultAlignment: TAlignment;
  1168. begin
  1169.   Result := taLeftJustify;
  1170. end;
  1171.  
  1172. function TKnotColumn.DefaultColor: TColor;
  1173. begin
  1174.   if Assigned(Grid) then
  1175.     Result := Grid.Color
  1176.   else
  1177.     Result := clWindow;
  1178. end;
  1179.  
  1180. function TKnotColumn.DefaultFont: TFont;
  1181. begin
  1182.   if Assigned(Grid) then
  1183.     Result := Grid.Font
  1184.   else
  1185.     Result := FFont;
  1186. end;
  1187.  
  1188. function TKnotColumn.DefaultWidth: Integer;
  1189.  var
  1190.   RestoreCanvas: Boolean;
  1191.   R: TRect;
  1192.   P: TPoint;
  1193.   W: integer;
  1194. begin
  1195.   if Assigned(Grid) then with Grid do
  1196.   begin
  1197.     Result := Grid.DefaultColWidth;
  1198.     RestoreCanvas := not HandleAllocated;
  1199.     if RestoreCanvas then Canvas.Handle := GetDC(0);
  1200.     try
  1201.       if tgTitles in Options then
  1202.       begin
  1203.         Canvas.Font := Title.Font;
  1204.         R := Rect(0, 0, ClientWidth, ClientHeight);
  1205.         P := DrawTitleCell(Canvas, Index, 0, R, dsUp, False, False);
  1206.         W := P.X;
  1207.         if Result < W then  Result := W;
  1208.       end;
  1209.     finally
  1210.       if RestoreCanvas then
  1211.       begin
  1212.         ReleaseDC(0, Canvas.Handle);
  1213.         Canvas.Handle := 0;
  1214.       end;
  1215.     end;
  1216.   end
  1217.   else
  1218.     Result := 64;
  1219. end;
  1220.  
  1221. destructor TKnotColumn.Destroy;
  1222. begin
  1223.   FTitle.Free;
  1224.   FFont.Free;
  1225.   inherited Destroy;
  1226. end;
  1227.  
  1228. procedure TKnotColumn.FontChanged(Sender: TObject);
  1229. begin
  1230.   Include(FAssignedValues, cvFont);
  1231.   Title.RefreshDefaultFont;
  1232.   Changed(False);
  1233. end;
  1234.  
  1235. function TKnotColumn.GetAlignment: TAlignment;
  1236. begin
  1237.   if cvAlignment in FAssignedValues then
  1238.     Result := FAlignment
  1239.   else
  1240.     Result := DefaultAlignment;
  1241. end;
  1242.  
  1243. function TKnotColumn.GetColor: TColor;
  1244. begin
  1245.   if cvColor in FAssignedValues then
  1246.     Result := FColor
  1247.   else
  1248.     Result := DefaultColor;
  1249. end;
  1250.  
  1251. function TKnotColumn.GetDisplayName: string;
  1252. begin
  1253.   Result := FTitle.Caption;
  1254.   if Result = '' then Result := ClassName;
  1255. end;
  1256.  
  1257. function TKnotColumn.GetFont: TFont;
  1258. var
  1259.   Save: TNotifyEvent;
  1260. begin
  1261.   if not (cvFont in FAssignedValues) and (FFont.Handle <> DefaultFont.Handle) then
  1262.   begin
  1263.     Save := FFont.OnChange;
  1264.     FFont.OnChange := nil;
  1265.     FFont.Assign(DefaultFont);
  1266.     FFont.OnChange := Save;
  1267.   end;
  1268.   Result := FFont;
  1269. end;
  1270.  
  1271. function TKnotColumn.GetGrid: TDCCustomTreeGrid;
  1272. begin
  1273.   if Assigned(Collection) and (Collection is TKnotColumns) then
  1274.     Result := TKnotColumns(Collection).Grid
  1275.   else
  1276.     Result := nil;
  1277. end;
  1278.  
  1279. function TKnotColumn.GetWidth: TWidth;
  1280. begin
  1281.   if not( (kcVisible in Options) or
  1282.       ((Grid <> nil) and (csWriting in Grid.ComponentState) )) then
  1283.   begin
  1284.     if (Grid <> nil) and not (tgColLines in Grid.Options) then
  1285.       Result := 0
  1286.     else
  1287.       Result := -1
  1288.   end
  1289.   else if cvWidth in FAssignedValues then
  1290.     Result := FWidth
  1291.   else
  1292.     Result := DefaultWidth;
  1293. end;
  1294.  
  1295. function TKnotColumn.IsAlignmentStored: Boolean;
  1296. begin
  1297.   Result := (cvAlignment in FAssignedValues) and (FAlignment <> DefaultAlignment);
  1298. end;
  1299.  
  1300. function TKnotColumn.IsColorStored: Boolean;
  1301. begin
  1302.   Result := (cvColor in FAssignedValues) and (FColor <> DefaultColor);
  1303. end;
  1304.  
  1305. function TKnotColumn.IsFontStored: Boolean;
  1306. begin
  1307.   Result := (cvFont in FAssignedValues) and (Font <> DefaultFont);
  1308. end;
  1309.  
  1310. function TKnotColumn.IsWidthStored: Boolean;
  1311. begin
  1312.   Result := (cvWidth in FAssignedValues) and (FWidth <> DefaultWidth);
  1313. end;
  1314.  
  1315. procedure TKnotColumn.RefreshDefaultFont;
  1316. var
  1317.   Save: TNotifyEvent;
  1318. begin
  1319.   if cvFont in FAssignedValues then Exit;
  1320.   Save := FFont.OnChange;
  1321.   FFont.OnChange := nil;
  1322.   try
  1323.     FFont.Assign(DefaultFont);
  1324.   finally
  1325.     FFont.OnChange := Save;
  1326.   end;
  1327. end;
  1328.  
  1329. procedure TKnotColumn.RestoreDefaults;
  1330. var
  1331.   FontAssigned: Boolean;
  1332. begin
  1333.   FontAssigned := cvFont in FAssignedValues;
  1334.   FTitle.RestoreDefaults;
  1335.   FAssignedValues := [];
  1336.   RefreshDefaultFont;
  1337.   Changed(FontAssigned);
  1338. end;
  1339.  
  1340. procedure TKnotColumn.SetAlignment(const Value: TAlignment);
  1341. begin
  1342.   if (cvAlignment in FAssignedValues) and (Value = FAlignment) then Exit;
  1343.   FAlignment := Value;
  1344.   Include(FAssignedValues, cvAlignment);
  1345.   Changed(False);
  1346. end;
  1347.  
  1348. procedure TKnotColumn.SetColor(const Value: TColor);
  1349. begin
  1350.   if (cvColor in FAssignedValues) and (Value = FColor) then Exit;
  1351.   FColor := Value;
  1352.   Include(FAssignedValues, cvColor);
  1353.   Changed(False);
  1354. end;
  1355.  
  1356. procedure TKnotColumn.SetName(const Value: string);
  1357. begin
  1358.   FName := Value;
  1359.   Changed(False);
  1360. end;
  1361.  
  1362. procedure TKnotColumn.SetFont(const Value: TFont);
  1363. begin
  1364.   FFont.Assign(Value);
  1365.   Include(FAssignedValues, cvFont);
  1366.   Changed(False);
  1367. end;
  1368.  
  1369. procedure TKnotColumn.SetIndexStyle(const Value: TColumnIndexStyle);
  1370. begin
  1371.   if Value <> FIndexStyle then
  1372.   begin
  1373.     FIndexStyle := Value;
  1374.     Changed(False);
  1375.   end;
  1376. end;
  1377.  
  1378. procedure TKnotColumn.SetItemIndex(const Value: integer);
  1379. begin
  1380.   if Value <> FItemIndex then
  1381.   begin
  1382.     FItemIndex := Value;
  1383.     Changed(False);
  1384.   end;
  1385. end;
  1386.  
  1387. procedure TKnotColumn.SetOptions(const Value: TKnotOptions);
  1388.  var
  1389.   ChangedOptions: TKnotOptions;
  1390. begin
  1391.   ChangedOptions := (FOptions + Value) - (FOptions * Value);
  1392.   if FOptions <> Value then
  1393.   begin
  1394.     FOptions := Value;
  1395.     Changed(True);
  1396.   end;
  1397. end;
  1398.  
  1399. procedure TKnotColumn.SetTitle(const Value: TKnotColumnTitle);
  1400. begin
  1401.   FTitle.Assign(Value);
  1402. end;
  1403.  
  1404. procedure TKnotColumn.SetWidth(const Value: TWidth);
  1405. begin
  1406.   if ((cvWidth in FAssignedValues) or (Value <> DefaultWidth))
  1407.     and (Value <> -1) and (Value <> 0)then
  1408.   begin
  1409.     FWidth := Value;
  1410.     Include(FAssignedValues, cvWidth);
  1411.   end;
  1412.   Changed(True);
  1413. end;
  1414.  
  1415. procedure TKnotColumn.SetComment(const Value: string);
  1416. begin
  1417.   FComment := Value;
  1418.   Include(FAssignedValues, cvComment);
  1419. end;
  1420.  
  1421. function TKnotColumn.IsCommentStored: Boolean;
  1422. begin
  1423.   Result := (cvComment in FAssignedValues);
  1424. end;
  1425.  
  1426. function TKnotColumn.DefaultComment: string;
  1427. begin
  1428.   Result := FName;
  1429. end;
  1430.  
  1431. function TKnotColumn.GetComment: string;
  1432. begin
  1433.   if cvComment in FAssignedValues then
  1434.     Result := FComment
  1435.   else
  1436.     Result := DefaultComment;
  1437. end;
  1438.  
  1439. procedure TKnotColumn.SetDisplayFormat(const Value: string);
  1440. begin
  1441.   if Value <> FDisplayFormat then
  1442.   begin
  1443.     FDisplayFormat := Value;
  1444.     Changed(False);
  1445.   end;
  1446. end;
  1447.  
  1448. procedure TKnotColumn.Changed(AllItems: Boolean);
  1449. begin
  1450.   inherited;
  1451. end;
  1452.  
  1453. function TKnotColumn.GetActualWidth: TWidth;
  1454. begin
  1455.   if cvWidth in FAssignedValues then
  1456.     Result := FWidth
  1457.   else
  1458.     Result := DefaultWidth;
  1459. end;
  1460.  
  1461. procedure TKnotColumn.SetIndex(Value: Integer);
  1462. begin
  1463.   inherited;
  1464. end;
  1465.  
  1466. procedure TKnotColumn.SetFooterPanel(const Value: TKnotColumnFooterPanel);
  1467. begin
  1468.   FFooterPanel.Assign(Value);
  1469. end;
  1470.  
  1471. { TKnotColumns }
  1472.  
  1473. function TKnotColumns.Add: TKnotColumn;
  1474. begin
  1475.   Result := TKnotColumn(inherited Add);
  1476. end;
  1477.  
  1478. constructor TKnotColumns.Create(AGrid: TDCCustomTreeGrid;
  1479.   AKnotColumnClass: TKnotColumnClass);
  1480. begin
  1481.   inherited Create(AKnotColumnClass);
  1482.   FGrid := AGrid;
  1483. end;
  1484.  
  1485. function TKnotColumns.GetItem(Index: Integer): TKnotColumn;
  1486. begin
  1487.   Result := TKnotColumn(inherited GetItem(Index));
  1488. end;
  1489.  
  1490. function TKnotColumns.GetOwner: TPersistent;
  1491. begin
  1492.   Result := TPersistent(FGrid);
  1493. end;
  1494.  
  1495. procedure TKnotColumns.SetItem(Index: Integer; Value: TKnotColumn);
  1496. begin
  1497.   inherited SetItem(Index, Value);
  1498. end;
  1499.  
  1500. procedure TKnotColumns.Update(Item: TCollectionItem);
  1501. var
  1502.   Raw: Integer;
  1503. begin
  1504.   if (Grid = nil) or (csLoading in Grid.ComponentState) then Exit;
  1505.   if Item = nil then
  1506.   begin
  1507.     Grid.LayoutChanged;
  1508.     Grid.UpdateColWidths(-1, True)
  1509.   end
  1510.   else begin
  1511.     Raw := Grid.DataToRawColumn(Item.Index);
  1512.     Grid.InvalidateCol(Raw);
  1513.     if kcSizing in TKnotColumn(Item).Options then
  1514.       Grid.FSizingIndex := Raw
  1515.     else
  1516.       Grid.FSizingIndex := -1;
  1517.     Grid.ColWidths[Raw] := TKnotColumn(Item).Width;
  1518.   end;
  1519.   if Grid.GroupBox.Count > 0 then Grid.GroupBox.Invalidate;
  1520. end;
  1521.  
  1522. { TKnotItem }
  1523.  
  1524. procedure TKnotItem.Clear;
  1525.  var
  1526.   i, iCount: integer;
  1527. begin
  1528.   {╙Σαδ σ∞ Γ±σ⌡ ∩ε≥ε∞ΩεΓ}
  1529.   iCount := ChildCount;
  1530.   for i := iCount-1 downto 0 do TKnotItem(FChildKnots.Items[i]).Free;
  1531. end;
  1532.  
  1533. procedure TKnotItem.Collapse(Recurse: boolean);
  1534.  var
  1535.   i: integer;
  1536. begin
  1537.   if Expanded and HasChildren then
  1538.   begin
  1539.     Owner.BeginUpdate;
  1540.     Expanded := False;
  1541.     if Recurse then
  1542.     begin
  1543.       for i := 0 to ChildCount-1 do
  1544.          TKnotItem(FChildKnots.Items[i]).Collapse(Recurse);
  1545.     end;
  1546.  
  1547.     if Grid <> nil then Grid.DoCollapse(Self);
  1548.     Owner.EndUpdate;
  1549.   end;
  1550. end;
  1551.  
  1552. constructor TKnotItem.Create(AOwner: TKnotItems; AParent: TKnotItem; AName: string);
  1553. begin
  1554.   inherited Create;
  1555.   FOwner  := AOwner;
  1556.   FParent := AParent;
  1557.   FName   := AName;
  1558.  
  1559.   FNormalImage := -1;
  1560.   FSelectImage := -1;
  1561.   FState       := ksCreate;
  1562.  
  1563.   {
  1564.   Expanded     := False;
  1565.   Visible      := True;
  1566.   Enabled      := True;
  1567.   HasChildren  := False;
  1568.   LockItems    := False;
  1569.   Changed      := False;
  1570.   }
  1571.   FFlag := 6;
  1572. end;
  1573.  
  1574. destructor TKnotItem.Destroy;
  1575.  var
  1576.   Apply: boolean;
  1577.   AIndex: integer;
  1578. begin
  1579.   if (Grid <> nil) and (KnotID <> 0) and (FState <> ksCreate)
  1580.   then begin
  1581.     Apply := True;
  1582.     Grid.DoDelete(Self, Apply, [csDestroying]);
  1583.     if Grid.SelectedRows.Find(KnotID, AIndex) then
  1584.       Grid.SelectedRows.FList.Delete(AIndex)
  1585.   end;
  1586.   Data := nil;
  1587.   {╙Σαδ σ∞ ∩ε≥ε∞ΩεΓ}
  1588.   Clear;
  1589.  
  1590.   if (FState <> ksCreate) and Assigned(FParent) then Owner.DeleteChildKnot(FParent, FIndex);
  1591.  
  1592.   if FChildKnots <> nil then FChildKnots.Free;
  1593.   FChildKnots := nil;
  1594.   inherited Destroy;
  1595. end;
  1596.  
  1597. procedure TKnotItem.Expand(Recurse: boolean);
  1598.  var
  1599.   i: integer;
  1600. begin
  1601.   if not Expanded and HasChildren then
  1602.   begin
  1603.     Owner.BeginUpdate;
  1604.     Expanded := True;
  1605.     if Recurse then
  1606.       for i := 0 to ChildCount-1 do
  1607.          TKnotItem(FChildKnots.Items[i]).Expand(Recurse);
  1608.  
  1609.     if Grid <> nil then Grid.DoExpand(Self);
  1610.     Owner.EndUpdate;
  1611.   end;
  1612. end;
  1613.  
  1614. function TKnotItem.GetChild(Index: integer): TKnotItem;
  1615. begin
  1616.   Result := TKnotItem(FChildKnots.Items[Index])
  1617. end;
  1618.  
  1619. function TKnotItem.GetChildCount: integer;
  1620. begin
  1621.   if FChildKnots <> nil then
  1622.     Result := FChildKnots.Count
  1623.   else
  1624.     Result := 0;
  1625. end;
  1626.  
  1627. procedure TKnotItem.SetChild(Index: integer; const Value: TKnotItem);
  1628. begin
  1629.   if Index < ChildCount then FChildKnots.Items[Index] := Value;
  1630. end;
  1631.  
  1632. procedure TKnotItem.SetData(const Value: Pointer);
  1633. begin
  1634.   FData := Value;
  1635. end;
  1636.  
  1637. function TKnotItem.GetNext: TKnotItem;
  1638.  var
  1639.   ParentKnot: TKnotItem;
  1640. begin
  1641.   if (ChildCount > 0) then
  1642.     Result := Childs[0]
  1643.   else begin
  1644.     Result := GetNextSibling;
  1645.     if Result = nil then
  1646.     begin
  1647.       ParentKnot := Parent;
  1648.       Result     := ParentKnot.GetNextSibling;
  1649.       while (Result = nil) and (ParentKnot.Level > 0) do
  1650.       begin
  1651.         ParentKnot := ParentKnot.Parent;
  1652.         Result     := ParentKnot.GetNextSibling
  1653.       end;
  1654.     end;
  1655.   end;
  1656. end;
  1657.  
  1658. function TKnotItem.GetNextVisible: TKnotItem;
  1659.  var
  1660.   i: integer;
  1661.   ParentKnot: TKnotItem;
  1662. begin
  1663.   if Expanded and (ChildCount > 0) then
  1664.   begin
  1665.     i := 0;
  1666.     repeat
  1667.       Result := Childs[i];
  1668.       inc(i);
  1669.     until (i = ChildCount) or Result.Visible;
  1670.     if Result.Visible then Exit;
  1671.   end;
  1672.  
  1673.   Result := Self;
  1674.   repeat
  1675.     ParentKnot := Result.Parent;
  1676.     repeat
  1677.       if Result = nil then
  1678.       begin
  1679.         Result := ParentKnot;
  1680.         ParentKnot := Result.Parent;
  1681.       end;
  1682.       if Result = Owner.Root then
  1683.       begin
  1684.         Result := nil;
  1685.         Exit;
  1686.       end;
  1687.       Result := Result.GetNextSiblingVisible;
  1688.     until (Result <> nil) and Result.Visible;
  1689.  
  1690.   until Result.Visible;
  1691. end;
  1692.  
  1693. function TKnotItem.GetNextSibling: TKnotItem;
  1694. begin
  1695.   if (FIndex >= 0) and (Parent <> nil) and (FIndex < (Parent.ChildCount-1)) then
  1696.     Result := Parent.Childs[FIndex+1]
  1697.   else
  1698.     Result := nil;
  1699. end;
  1700.  
  1701. function TKnotItem.GetPrev: TKnotItem;
  1702. begin
  1703.   Result := GetPrevSibling;
  1704.   if Result = nil then
  1705.     Result  := Parent
  1706.   else begin
  1707.     if Result <> nil then
  1708.       while Result.ChildCount > 0 do
  1709.         Result := Result.Childs[Result.ChildCount-1]
  1710.   end;
  1711. end;
  1712.  
  1713. function TKnotItem.GetPrevSibling: TKnotItem;
  1714. begin
  1715.   if (FIndex > 0) and (FIndex < Parent.ChildCount) then
  1716.     Result := Parent.Childs[FIndex-1]
  1717.   else
  1718.     Result := nil
  1719. end;
  1720.  
  1721. function TKnotItem.GetPrevVisible: TKnotItem;
  1722.  var
  1723.   ParentKnot: TKnotItem;
  1724. begin
  1725.   Result := Self;
  1726.  
  1727.   repeat
  1728.     ParentKnot := Result.Parent;
  1729.     Result := Result.GetPrevSiblingVisible;
  1730.  
  1731.     if Result = nil then
  1732.       Result := ParentKnot
  1733.     else
  1734.       while Result.Expanded and (Result.ChildCount > 0) do
  1735.         Result := Result.Childs[Result.ChildCount-1];
  1736.  
  1737.     if Result = Owner.Root then
  1738.     begin
  1739.       Result := nil;
  1740.       Exit;
  1741.     end;
  1742.  
  1743.   until Result.Visible;
  1744. end;
  1745.  
  1746. procedure TKnotItem.SetName(const Value: string);
  1747. begin
  1748.   if FName <> Value then
  1749.   begin
  1750.     FName := Value;
  1751.     FOwner.UpdateTreeGrid;
  1752.   end;
  1753. end;
  1754.  
  1755. function TKnotItem.GetGrid: TDCCustomTreeGrid;
  1756. begin
  1757.   Result := FOwner.Grid;
  1758. end;
  1759.  
  1760. procedure TKnotItem.SetState(const Value: TKnotState);
  1761. begin
  1762.   FState := Value;
  1763. end;
  1764.  
  1765. function TKnotItem.GetFlagValue(const Index: Integer): boolean; assembler;
  1766. asm
  1767.   mov eax, dword([eax].FFlag)
  1768.   bt  eax, Index
  1769.   sbb eax, eax
  1770.   and eax, 1
  1771. end;
  1772.  
  1773. procedure TKnotItem.SetFlagValue(const Index: Integer; const Value: boolean); assembler;
  1774. asm
  1775.   or  Value, Value
  1776.   jz  @@1
  1777.   bts [eax].FFlag, Index
  1778.   ret
  1779. @@1:
  1780.   btr [eax].FFlag, Index
  1781. end;
  1782.  
  1783. procedure TKnotItem.SetValueEx(const Index: Integer;
  1784.   const Value: boolean);
  1785. begin
  1786.   if GetFlagvalue(Index) <> Value then
  1787.   begin
  1788.     SetFlagValue(Index, Value);
  1789.     Owner.UpdateTreeGrid;
  1790.   end;
  1791. end;
  1792.  
  1793. function TKnotItem.GetVisibleChildCount: integer;
  1794.  var
  1795.   i, iCount: integer;
  1796. begin
  1797.   Result := 0;
  1798.   iCount := ChildCount;
  1799.   for i := 0 to iCount-1 do if Childs[i].Visible then Inc(Result);
  1800. end;
  1801.  
  1802. function TKnotItem.GetVisibleKnotCount: integer;
  1803.  var
  1804.   i, iCount: integer;
  1805. begin
  1806.   Result := 0;
  1807.   if Visible then
  1808.   begin
  1809.     Result := 1;
  1810.     if Expanded then
  1811.     begin
  1812.       iCount := ChildCount;
  1813.       for i := 0 to iCount-1 do Result := Result + Childs[i].GetVisibleKnotCount;
  1814.     end
  1815.   end;
  1816. end;
  1817.  
  1818. procedure TKnotItem.SetNormalImage(const Value: shortint);
  1819. begin
  1820.   if FNormalImage <> Value then
  1821.   begin
  1822.     FNormalImage := Value;
  1823.     FOwner.UpdateTreeGrid;
  1824.   end;
  1825. end;
  1826.  
  1827. procedure TKnotItem.SetSelectImage(const Value: shortint);
  1828. begin
  1829.   if FSelectImage <> Value then
  1830.   begin
  1831.     FSelectImage := Value;
  1832.     FOwner.UpdateTreeGrid;
  1833.   end;
  1834. end;
  1835.  
  1836. function TKnotItem.GetLevel: integer;
  1837.  var
  1838.   KnotItem: TKnotItem;
  1839. begin
  1840.   Result   := -1;
  1841.   KnotItem := Self;
  1842.   if Owner <> nil then
  1843.   begin
  1844.     while (KnotItem <> Owner.Root) and (KnotItem <> nil) do
  1845.     begin
  1846.       KnotItem  := KnotItem.Parent;
  1847.       Inc(Result);
  1848.     end;
  1849.   end;
  1850. end;
  1851.  
  1852. procedure TKnotItem.SetVisible(const Value: boolean);
  1853.  var
  1854.   lHasChildren: boolean;
  1855. begin
  1856.   if GetFlagvalue(1) <> Value then
  1857.   begin
  1858.     SetFlagValue(1, Value);
  1859.     lHasChildren := (Parent.VisibleChilds <> 0);
  1860.  
  1861.     if lHasChildren <> Parent.HasChildren then
  1862.       Parent.HasChildren := lHasChildren
  1863.     else
  1864.       Owner.UpdateTreeGrid;
  1865.   end;
  1866. end;
  1867.  
  1868. function TKnotItem.GetVisible: boolean;
  1869. begin
  1870.   Result := GetFlagValue(1);
  1871. end;
  1872.  
  1873. function TKnotItem.DisplayRect(TextOnly: boolean): TRect;
  1874.  var
  1875.   KnotItem1, KnotItem2: TKnotItem;
  1876.   ItemVisible: boolean;
  1877.   Grid: TDCCustomTreeGrid;
  1878.   i: integer;
  1879. begin
  1880.   {Chack Item Visible}
  1881.   SetRectEmpty(Result);
  1882.   Grid := GetGrid;
  1883.   if Grid <> nil then
  1884.   begin
  1885.     {Check Item Visible}
  1886.     KnotItem1 := Self;
  1887.     ItemVisible := KnotItem1.Visible;
  1888.     while ItemVisible and (KnotItem1 <> Owner.Root)  do
  1889.     begin
  1890.       KnotItem1 := KnotItem1.Parent;
  1891.       ItemVisible := KnotItem1.Visible and KnotItem1.Enabled;
  1892.     end;
  1893.  
  1894.     KnotItem1 := Self;
  1895.     KnotItem2 := Grid.FFirstVisible;
  1896.     with Grid do Result := CellRect(FIndicatorOffset - 1, TopRow + FTitleOffset);
  1897.     i := Owner.ComparePos(KnotItem1, KnotItem2);
  1898.     if i > 0 then
  1899.     begin
  1900.       while KnotItem1 <> KnotItem2 do
  1901.       begin
  1902.         KnotItem1 := KnotItem1.GetNextVisible;
  1903.         OffsetRect(Result, 0, -Grid.DefaultRowHeight)
  1904.       end;
  1905.     end
  1906.     else begin
  1907.       while KnotItem1 <> KnotItem2 do
  1908.       begin
  1909.         KnotItem1 := KnotItem1.GetPrevVisible;
  1910.         OffsetRect(Result, 0, Grid.DefaultRowHeight)
  1911.       end;
  1912.     end;
  1913.     if TextOnly then Result.Left := Result.Left + Grid.GetTreeLableOffset(Self)
  1914.   end;
  1915. end;
  1916.  
  1917. procedure TKnotItem.EditText;
  1918. begin
  1919.   {}
  1920. end;
  1921.  
  1922. procedure TKnotItem.EndEdit(Cancel: boolean);
  1923. begin
  1924.   {}
  1925. end;
  1926.  
  1927. function TKnotItem.GetNextSiblingVisible: TKnotItem;
  1928. begin
  1929.   Result := Self;
  1930.   repeat
  1931.     Result := Result.GetNextSibling;
  1932.   until (Result = nil) or Result.Visible;
  1933. end;
  1934.  
  1935. function TKnotItem.GetPrevSiblingVisible: TKnotItem;
  1936. begin
  1937.   Result := Self;
  1938.   repeat
  1939.     Result := Result.GetPrevSibling;
  1940.   until (Result = nil) or Result.Visible;
  1941. end;
  1942.  
  1943. function TKnotItem.GetOwner: TKnotItems;
  1944. begin
  1945.   Result := FOwner;
  1946. end;
  1947.  
  1948. function TKnotItem.GetParent: TKnotItem;
  1949. begin
  1950.   Result := FParent;
  1951. end;
  1952.  
  1953. procedure TKnotItem.SetParent(const Value: TKnotItem);
  1954. begin
  1955.   FParent := Value;
  1956. end;
  1957.  
  1958. { TKnotItems }
  1959.  
  1960. function TKnotItems.Add(Name: string; Position: integer = KNOT_END): TKnotItem;
  1961. begin
  1962.   Result := AddChild(FRootKnot, Name, Position)
  1963. end;
  1964.  
  1965. function TKnotItems.AddChild(ParentKnot: TKnotItem; Name: string;
  1966.   Position: integer = KNOT_END): TKnotItem;
  1967.  var
  1968.   KnotItem: TKnotItem;
  1969.   Apply: boolean;
  1970. begin
  1971.   KnotItem := FKnotItemClass.Create(Self, ParentKnot, Name);
  1972.   Inc(FLastKnotID);
  1973.   KnotItem.FKnotID := FLastKnotID;
  1974.  
  1975.   Apply := True;
  1976.   if (Grid <> nil) then Grid.DoInsert(KnotItem, Apply);
  1977.  
  1978.   if Apply then
  1979.   begin
  1980.     BeginUpdate;
  1981.     if ParentKnot.FChildKnots = nil then ParentKnot.FChildKnots := TList.Create;
  1982.     case Position of
  1983.       KNOT_BEGIN:
  1984.         begin
  1985.           ParentKnot.FChildKnots.Insert(0, KnotItem);
  1986.           RebuildIndexes(ParentKnot, 0);
  1987.         end;
  1988.       KNOT_END:
  1989.         KnotItem.FIndex := ParentKnot.FChildKnots.Add(KnotItem);
  1990.       else begin
  1991.         ParentKnot.FChildKnots.Insert(Position, KnotItem);
  1992.         RebuildIndexes(ParentKnot, Position);
  1993.       end;
  1994.     end;
  1995.     Result := KnotItem;
  1996.     KnotItem.State := ksBrowse;
  1997.     ParentKnot.HasChildren := True;
  1998.     EndUpdate;
  1999.   end
  2000.   else begin
  2001.     Result := nil;
  2002.     KnotItem.Free;
  2003.   end;
  2004.  
  2005. end;
  2006.  
  2007. procedure TKnotItems.Clear;
  2008. begin
  2009.   SetState(ksUpdate);
  2010.   FRootKnot.Clear;
  2011.   if FOwner <> nil then with FOwner do
  2012.   begin
  2013.     InitGridPos;
  2014.     TopRow := FTitleOffset;
  2015.     Row    := FTitleOffset;
  2016.   end;
  2017.   SetState(ksBrowse);
  2018.   UpdateTreeGrid;
  2019. end;
  2020.  
  2021. constructor TKnotItems.Create(AOwner: TDCCustomTreeGrid;
  2022.   AKnotItemClass: TKnotItemClass);
  2023. begin
  2024.   inherited Create;
  2025.   FOwner := AOwner;
  2026.  
  2027.   FKnotItemClass := AKnotItemClass;
  2028.   FRootKnot := TKnotItem.Create(Self, nil, NE_ROOT_KNOT);
  2029.   FRootKnot.Expanded := True;
  2030.  
  2031.   FLastKnotID  := 0;
  2032.   FUpdateCount := 0;
  2033.  
  2034.   SetState(ksBrowse);
  2035. end;
  2036.  
  2037. function TKnotItems.Delete(Knot: TKnotItem): boolean;
  2038.  var
  2039.   Apply: boolean;
  2040. begin
  2041.   if Knot <> nil then
  2042.   begin
  2043.     Apply := True;
  2044.     if (Grid <> nil) then Grid.DoDelete(Knot, Apply, []);
  2045.     if Apply then
  2046.     begin
  2047.       if Knot = Owner.FFirstVisible then
  2048.       begin
  2049.         Knot.Free;
  2050.         FOwner.InitGridPos;
  2051.       end
  2052.       else
  2053.         Knot.Free;
  2054.       SetState(ksBrowse);
  2055.       UpdateTreeGrid;
  2056.     end;
  2057.     Result := Apply;
  2058.   end
  2059.   else
  2060.     Result := False;
  2061. end;
  2062.  
  2063. destructor TKnotItems.Destroy;
  2064. begin
  2065.   FState := ksUpdate;
  2066.   FRootKnot.Free;
  2067.   inherited;
  2068. end;
  2069.  
  2070. function TKnotItems.GetCount: integer;
  2071. begin
  2072.   Result := FRootKnot.ChildCount;
  2073. end;
  2074.  
  2075. function TKnotItems.GetItem(Index: integer): TKnotItem;
  2076. begin
  2077.   Result := FRootKnot.Childs[Index];
  2078. end;
  2079.  
  2080. procedure TKnotItems.SetItem(Index: integer; const Value: TKnotItem);
  2081. begin
  2082.   FRootKnot.Childs[Index] := Value;
  2083. end;
  2084.  
  2085. procedure TKnotItems.Move(KnotItem, DestKnot: TKnotItem;
  2086.   Position: integer);
  2087.  var
  2088.   ParentKnot: TKnotItem;
  2089. begin
  2090.   if DestKnot  = nil then DestKnot := FRootKnot;
  2091.   ParentKnot := KnotItem.Parent;
  2092.  
  2093.   if ParentKnot.LockItems then Exit;
  2094.  
  2095.   DeleteChildKnot(ParentKnot, KnotItem.FIndex);
  2096.  
  2097.   if DestKnot.FChildKnots = nil then DestKnot.FChildKnots := TList.Create;
  2098.   case Position of
  2099.     KNOT_BEGIN  :
  2100.      begin
  2101.        DestKnot.FChildKnots.Insert(0, KnotItem);
  2102.        RebuildIndexes(DestKnot, 0);
  2103.      end;
  2104.     KNOT_END    :
  2105.       KnotItem.FIndex := DestKnot.FChildKnots.Add(KnotItem);
  2106.     else begin
  2107.       DestKnot.FChildKnots.Insert(Position, KnotItem);
  2108.       if Position > 0 then
  2109.         RebuildIndexes(DestKnot, Position-1)
  2110.       else
  2111.         RebuildIndexes(DestKnot, 0);
  2112.     end;
  2113.   end;
  2114.   KnotItem.Parent := DestKnot;
  2115.   UpdateTreeGrid;
  2116. end;
  2117.  
  2118. function TKnotItems.GetVisibleKnotCount: integer;
  2119.  var
  2120.   i: integer;
  2121. begin
  2122.   Result := 0;
  2123.   for i := 0 to Count-1 do
  2124.   begin
  2125.     Result := Result + Items[i].VisibleKnotCount;
  2126.   end;
  2127. end;
  2128.  
  2129. procedure TKnotItems.BeginUpdate(LockScreen: boolean = False);
  2130. begin
  2131.   if FUpdateCount = 0 then
  2132.   begin
  2133.     SetUpdateState(True);
  2134.   end;
  2135.   Inc(FUpdateCount);
  2136.   if LockScreen then
  2137.   begin
  2138.     FOwner.FLockScreen := LockScreen;
  2139.     FOwner.Refresh;
  2140.     ShowScrollBar(FOwner.Handle, SB_BOTH, False);
  2141.     ProcessPaintMessages;
  2142.   end;
  2143. end;
  2144.  
  2145. procedure TKnotItems.EndUpdate;
  2146.  var
  2147.   ScrollInfo: TScrollInfo;
  2148. begin
  2149.   if FUpdateCount > 0 then begin
  2150.     Dec(FUpdateCount);
  2151.     if FUpdateCount = 0 then
  2152.     begin
  2153.       SetUpdateState(False);
  2154.       if FOwner.FLockScreen then
  2155.       begin
  2156.         with FOwner do
  2157.         begin
  2158.           FLockScreen := False;
  2159.           with ScrollInfo do
  2160.           begin
  2161.             cbSize := SizeOf(ScrollInfo);
  2162.             fMask  := SIF_ALL;
  2163.             nMin   := 0;
  2164.             nMax   := 0;
  2165.             nPage  := 0;
  2166.             nPos      := 0;
  2167.             nTrackPos := 0;
  2168.           end;
  2169.           SetScrollInfo(Handle, SB_HORZ, ScrollInfo, True);
  2170.           SetScrollInfo(Handle, SB_VERT, ScrollInfo, True);
  2171.           ColWidthsChanged;
  2172.           RowHeightsChanged;
  2173.           Refresh;
  2174.         end;
  2175.         ProcessPaintMessages;
  2176.       end;
  2177.       UpdateTreeGrid;
  2178.     end;
  2179.   end;
  2180. end;
  2181.  
  2182. procedure TKnotItems.UpdateTreeGrid;
  2183. begin
  2184.   if (FUpdateCount = 0) and (FOwner <> nil) then
  2185.     FOwner.Perform(CM_KNOTCHANGED, 0, 0);
  2186. end;
  2187.  
  2188. function TKnotItems.SelectKnot(KnotItem: TKnotItem; Offset: integer): TKnotItem;
  2189.  var
  2190.   AKnotItem: TKnotItem;
  2191.   AIndex: integer;
  2192. begin
  2193.   Result := KnotItem;
  2194.   AIndex := Offset;
  2195.   AKnotItem := GetFirstVisibleNode;
  2196.   if AIndex >= 0 then
  2197.   begin
  2198.     while (Result <> nil) and (AIndex > 0) do
  2199.     begin
  2200.       AKnotItem := Result;
  2201.       Result := Result.GetNextVisible;
  2202.       Dec(AIndex);
  2203.     end;
  2204.   end
  2205.   else begin
  2206.     while (Result <> nil) and (AIndex < 0) do
  2207.     begin
  2208.       AKnotItem := Result;
  2209.       Result := Result.GetPrevVisible;
  2210.       Inc(AIndex);
  2211.     end;
  2212.   end;
  2213.   if Result = nil then Result := AKnotItem;
  2214. end;
  2215.  
  2216. procedure TKnotItems.RebuildIndexes(ParentKnot: TKnotItem; FirstIndex: integer);
  2217.  var
  2218.   i: integer;
  2219. begin
  2220.   with ParentKnot do
  2221.   begin
  2222.     if LockItems then
  2223.     begin
  2224.       Changed := True;
  2225.       FLastIndex := _intMin(FLastIndex, FirstIndex);
  2226.     end
  2227.     else
  2228.       for i := FirstIndex to ChildCount-1 do Childs[i].FIndex := i;
  2229.   end;
  2230. end;
  2231.  
  2232. procedure TKnotItems.SetState(Value: TKnotState);
  2233. begin
  2234.   if Value <> FState then
  2235.   begin
  2236.     FState := Value;
  2237.     with Grid do
  2238.       if tgIndicator in Options then InvalidateCell(0,Row)
  2239.   end;
  2240. end;
  2241.  
  2242. function TKnotItems.GetFirstNode: TKnotItem;
  2243. begin
  2244.   if FRootKnot.ChildCount > 0 then
  2245.     Result := FRootKnot.GetNext
  2246.   else
  2247.     Result := nil;
  2248. end;
  2249.  
  2250. procedure TKnotItems.Exchange(KnotItem1, KnotItem2: TKnotItem);
  2251.  var
  2252.   ParentKnot1, ParentKnot2: TKnotItem;
  2253. begin
  2254.   ParentKnot1 := KnotItem1.Parent;
  2255.   ParentKnot2 := KnotItem2.Parent;
  2256.  
  2257.   if ParentKnot1.LockItems or ParentKnot2.LockItems then Exit;
  2258.  
  2259.   ParentKnot1.Childs[KnotItem1.Index] := KnotItem2;
  2260.   ParentKnot2.Childs[KnotItem2.Index] := KnotItem1;
  2261.  
  2262.   if ParentKnot1 = ParentKnot2 then
  2263.     RebuildIndexes(ParentKnot1, _intMin(KnotItem1.Index, KnotItem2.Index))
  2264.   else begin
  2265.     RebuildIndexes(ParentKnot1, KnotItem1.Index);
  2266.     RebuildIndexes(ParentKnot2, KnotItem2.Index);
  2267.   end;
  2268.  
  2269.   UpdateTreeGrid;
  2270. end;
  2271.  
  2272. function TKnotItems.GetUpdateingState: boolean;
  2273. begin
  2274.   Result := FUpdateCount <> 0;
  2275. end;
  2276.  
  2277. procedure TKnotItems.SetUpdateState(Updating: Boolean);
  2278. begin
  2279.   {}
  2280. end;
  2281.  
  2282. procedure TKnotItems.LockRebuilds(KnotItem: TKnotItem; Lock: boolean);
  2283. begin
  2284.   with KnotItem do
  2285.   begin
  2286.     LockItems := Lock;
  2287.     if Lock then
  2288.     begin
  2289.       Changed := False;
  2290.       FLastIndex := MaxInt;
  2291.     end
  2292.     else begin
  2293.       if Changed then Owner.RebuildIndexes(KnotItem, FLastIndex)
  2294.     end;
  2295.   end;
  2296. end;
  2297.  
  2298. procedure TKnotItems.DeleteChildKnot(KnotItem: TKnotItem; KnotIndex: integer);
  2299. begin
  2300.   {╙ΣαδσφΦσ εΣφεπε Φτ child}
  2301.   with KnotItem do
  2302.   begin
  2303.     if KnotIndex < ChildCount then
  2304.     begin
  2305.       FChildKnots.Delete(KnotIndex);
  2306.       FOwner.RebuildIndexes(KnotItem, KnotIndex);
  2307.       if ChildCount = 0 then HasChildren := False;
  2308.     end;
  2309.   end;
  2310. end;
  2311.  
  2312. function TKnotItems.GetKnot(KnotID: integer; var KnotItem: TKnotItem): boolean;
  2313. begin
  2314.   KnotItem := GetFirstNode;
  2315.   while (KnotItem <> nil) and (KnotItem.KnotID <> KnotID) do
  2316.     KnotItem := KnotItem.GetNext;
  2317.   Result := KnotItem <> nil;
  2318. end;
  2319.  
  2320. function TKnotItems.ComparePos(KnotItem1, KnotItem2: TKnotItem): integer;
  2321.  var
  2322.   KnotItemA, KnotItemB: TKnotItem;
  2323.  
  2324. begin
  2325.   if (KnotItem1 = KnotItem2) or (KnotItem2 = nil) or (KnotItem1 = nil) then
  2326.   begin
  2327.     Result := 0;
  2328.     Exit;
  2329.   end;
  2330.  
  2331.   KnotItemA := KnotItem1;
  2332.   KnotItemB := KnotItem2;
  2333.   while KnotItemA.Level <> KnotItemB.Level do
  2334.   begin
  2335.     if KnotItemA.Level > KnotItemB.Level then
  2336.       KnotItemA := KnotItemA.Parent
  2337.     else
  2338.       KnotItemB := KnotItemB.Parent
  2339.   end;
  2340.   while KnotItemA.Parent <> KnotItemB.Parent do
  2341.   begin
  2342.     KnotItemA := KnotItemA.Parent;
  2343.     KnotItemB := KnotItemB.Parent;
  2344.  end;
  2345.  
  2346.  if (KnotItemA.Index > KnotItemB.Index) or
  2347.     ((KnotItemA.Index = KnotItemB.Index) and (KnotItem1.Level > KnotItem2.Level))then
  2348.    Result := -1
  2349.  else
  2350.    Result := 1
  2351. end;
  2352.  
  2353. function TKnotItems.GetFirstVisibleNode: TKnotItem;
  2354. begin
  2355.   if FRootKnot.ChildCount > 0 then
  2356.     Result := FRootKnot.GetNextVisible
  2357.   else
  2358.     Result := nil;
  2359. end;
  2360.  
  2361. function TKnotItems.GetRootKnot: TKnotItem;
  2362. begin
  2363.   Result := FRootKnot;
  2364. end;
  2365.  
  2366. { TKnotColumnTitle }
  2367.  
  2368. procedure TKnotColumnTitle.Assign(Source: TPersistent);
  2369. begin
  2370.   if Source is TKnotColumnTitle then
  2371.   begin
  2372.     if cvTitleAlignment in TKnotColumnTitle(Source).FColumn.FAssignedValues then
  2373.       Alignment := TKnotColumnTitle(Source).Alignment;
  2374.     if cvTitleColor in TKnotColumnTitle(Source).FColumn.FAssignedValues then
  2375.       Color := TKnotColumnTitle(Source).Color;
  2376.     if cvTitleCaption in TKnotColumnTitle(Source).FColumn.FAssignedValues then
  2377.       Caption := TKnotColumnTitle(Source).Caption;
  2378.     if cvTitleFont in TKnotColumnTitle(Source).FColumn.FAssignedValues then
  2379.       Font := TKnotColumnTitle(Source).Font;
  2380.   end
  2381.   else
  2382.     inherited Assign(Source);
  2383. end;
  2384.  
  2385. constructor TKnotColumnTitle.Create(Column: TKnotColumn);
  2386. begin
  2387.   inherited Create;
  2388.  
  2389.   FColumn  := Column;
  2390.   FCaption := 'DefaultCaption';
  2391.   FFont    := TFont.Create;
  2392.   FFont.Assign(DefaultFont);
  2393.   FFont.OnChange := FontChanged;
  2394. end;
  2395.  
  2396. function TKnotColumnTitle.DefaultAlignment: TAlignment;
  2397. begin
  2398.   Result := taLeftJustify;
  2399. end;
  2400.  
  2401. function TKnotColumnTitle.DefaultCaption: string;
  2402. begin
  2403.   Result  := FColumn.FName;
  2404. end;
  2405.  
  2406. function TKnotColumnTitle.DefaultColor: TColor;
  2407.  var
  2408.   TreeGrid: TDCCustomTreeGrid;
  2409. begin
  2410.   TreeGrid := FColumn.GetGrid;
  2411.   if Assigned(TreeGrid) then
  2412.     Result := TreeGrid.FixedColor
  2413.   else
  2414.     Result := clBtnFace;
  2415. end;
  2416.  
  2417. function TKnotColumnTitle.DefaultFont: TFont;
  2418.  var
  2419.   TreeGrid: TDCCustomTreeGrid;
  2420. begin
  2421.   TreeGrid := FColumn.GetGrid;
  2422.   if Assigned(TreeGrid) then
  2423.     Result := TreeGrid.Font
  2424.   else
  2425.     Result := FColumn.Font;
  2426. end;
  2427.  
  2428. destructor TKnotColumnTitle.Destroy;
  2429. begin
  2430.   FFont.Free;
  2431.   inherited Destroy;
  2432. end;
  2433.  
  2434. procedure TKnotColumnTitle.FontChanged(Sender: TObject);
  2435. begin
  2436.   Include(FColumn.FAssignedValues, cvTitleFont);
  2437.   FColumn.Changed(True);
  2438. end;
  2439.  
  2440. function TKnotColumnTitle.GetAlignment: TAlignment;
  2441. begin
  2442.   if cvTitleAlignment in FColumn.FAssignedValues then
  2443.     Result := FAlignment
  2444.   else
  2445.     Result := DefaultAlignment;
  2446. end;
  2447.  
  2448. function TKnotColumnTitle.GetCaption: string;
  2449. begin
  2450.   if cvTitleCaption in FColumn.FAssignedValues then
  2451.     Result := FCaption
  2452.   else
  2453.     Result := DefaultCaption;
  2454. end;
  2455.  
  2456. function TKnotColumnTitle.GetColor: TColor;
  2457. begin
  2458.   if cvTitleColor in FColumn.FAssignedValues then
  2459.     Result := FColor
  2460.   else
  2461.     Result := DefaultColor;
  2462. end;
  2463.  
  2464. function TKnotColumnTitle.GetFont: TFont;
  2465. var
  2466.   Save: TNotifyEvent;
  2467.   Def: TFont;
  2468. begin
  2469.   if not (cvTitleFont in FColumn.FAssignedValues) then
  2470.   begin
  2471.     Def := DefaultFont;
  2472.     if (FFont.Handle <> Def.Handle) or (FFont.Color <> Def.Color) then
  2473.     begin
  2474.       Save := FFont.OnChange;
  2475.       FFont.OnChange := nil;
  2476.       FFont.Assign(DefaultFont);
  2477.       FFont.OnChange := Save;
  2478.     end;
  2479.   end;
  2480.   Result := FFont;
  2481. end;
  2482.  
  2483. function TKnotColumnTitle.IsAlignmentStored: Boolean;
  2484. begin
  2485.   Result := (cvTitleAlignment in FColumn.FAssignedValues) and
  2486.     (FAlignment <> DefaultAlignment);
  2487. end;
  2488.  
  2489. function TKnotColumnTitle.IsCaptionStored: Boolean;
  2490. begin
  2491.   Result := (cvTitleCaption in FColumn.FAssignedValues) and
  2492.     (FCaption <> DefaultCaption);
  2493. end;
  2494.  
  2495. function TKnotColumnTitle.IsColorStored: Boolean;
  2496. begin
  2497.   Result := (cvTitleColor in FColumn.FAssignedValues) and (FColor <> DefaultColor);
  2498. end;
  2499.  
  2500. function TKnotColumnTitle.IsFontStored: Boolean;
  2501. begin
  2502.   Result := (cvTitleFont in FColumn.FAssignedValues);
  2503. end;
  2504.  
  2505. procedure TKnotColumnTitle.RefreshDefaultFont;
  2506. var
  2507.   Save: TNotifyEvent;
  2508. begin
  2509.   if (cvTitleFont in FColumn.FAssignedValues) then Exit;
  2510.   Save := FFont.OnChange;
  2511.   FFont.OnChange := nil;
  2512.   try
  2513.     FFont.Assign(DefaultFont);
  2514.   finally
  2515.     FFont.OnChange := Save;
  2516.   end;
  2517. end;
  2518.  
  2519. procedure TKnotColumnTitle.RestoreDefaults;
  2520. var
  2521.   FontAssigned: Boolean;
  2522. begin
  2523.   FontAssigned := cvTitleFont in FColumn.FAssignedValues;
  2524.   FColumn.FAssignedValues := FColumn.FAssignedValues - ColumnTitleValues;
  2525.   FCaption := '';
  2526.   RefreshDefaultFont;
  2527.   FColumn.Changed(FontAssigned);
  2528. end;
  2529.  
  2530. procedure TKnotColumnTitle.SetAlignment(Value: TAlignment);
  2531. begin
  2532.   if (cvTitleAlignment in FColumn.FAssignedValues) and (Value = FAlignment) then Exit;
  2533.   FAlignment := Value;
  2534.   Include(FColumn.FAssignedValues, cvTitleAlignment);
  2535.   FColumn.Changed(False);
  2536. end;
  2537.  
  2538. procedure TKnotColumnTitle.SetCaption(const Value: string);
  2539. var
  2540.   Grid: TDCCustomTreeGrid;
  2541. begin
  2542.   if not(cvTitleCaption in FColumn.FAssignedValues) or (Value <> FCaption) then
  2543.   begin
  2544.     Grid := Column.GetGrid;
  2545.     FCaption := Value;
  2546.     Include(Column.FAssignedValues, cvTitleCaption);
  2547.     Column.Changed(False);
  2548.     if Assigned(Grid) then with Grid do
  2549.     begin
  2550.       if LayoutLock = 0 then Grid.InternalLayout;
  2551.       if GroupingEnabled then GroupBox.UpdateItemSize(GroupBox.Find(DataToRawColumn(FColumn.Index)));
  2552.     end;
  2553.   end;
  2554. end;
  2555.  
  2556. procedure TKnotColumnTitle.SetColor(Value: TColor);
  2557. begin
  2558.   if (cvTitleColor in FColumn.FAssignedValues) and (Value = FColor) then Exit;
  2559.   FColor := Value;
  2560.   Include(FColumn.FAssignedValues, cvTitleColor);
  2561.   FColumn.Changed(False);
  2562. end;
  2563.  
  2564. procedure TKnotColumnTitle.SetFont(Value: TFont);
  2565. begin
  2566.   FFont.Assign(Value);
  2567.   Include(FColumn.FAssignedValues, cvTitleFont);
  2568.   FColumn.Changed(False);
  2569. end;
  2570.  
  2571. { TDCCustomTreeGrid }
  2572.  
  2573. function TDCCustomTreeGrid.AcquireFocus: Boolean;
  2574. begin
  2575.   Result := True;
  2576.   if CanFocus and not (csDesigning in ComponentState) then
  2577.   begin
  2578.     SetFocus;
  2579.     Result := Focused;
  2580.   end;
  2581. end;
  2582.  
  2583. function TDCCustomTreeGrid.AcquireLayoutLock: Boolean;
  2584. begin
  2585.   Result := (FUpdateLock = 0) and (FLayoutLock = 0);
  2586.   if Result then BeginLayout;
  2587. end;
  2588.  
  2589. procedure TDCCustomTreeGrid.BeginLayout;
  2590. begin
  2591.   BeginUpdate;
  2592.   if FLayoutLock = 0 then Columns.BeginUpdate;
  2593.   Inc(FLayoutLock);
  2594. end;
  2595.  
  2596. procedure TDCCustomTreeGrid.BeginUpdate;
  2597. begin
  2598.   Inc(FUpdateLock);
  2599. end;
  2600.  
  2601. procedure TDCCustomTreeGrid.CellClick(Column: TKnotColumn);
  2602. begin
  2603.   if Assigned(FOnCellClick) then FOnCellClick(Column);
  2604. end;
  2605.  
  2606. procedure TDCCustomTreeGrid.CellDblClick(Column: TKnotColumn);
  2607. begin
  2608.   if Assigned(FOnCellDblClick) then FOnCellDblClick(Column);
  2609. end;
  2610.  
  2611. procedure TDCCustomTreeGrid.ClipClick(ACellType: TFixedCell);
  2612.  var
  2613.   CellType: TFixedCell;
  2614. begin
  2615.   CellType := TKnotClipPopup(FClipPopup).CellType;
  2616.   HideClipPopup;
  2617.   if CellType <> ACellType then ShowClipPopup(ACellType, FClipPopup);
  2618. end;
  2619.  
  2620. procedure TDCCustomTreeGrid.CMCancelMode(var Message: TCMCancelMode);
  2621. begin
  2622.   inherited;
  2623.   with Message do
  2624.     if (Sender <> Self) and (Sender <> FClipPopup) then HideClipPopup;
  2625. end;
  2626.  
  2627. procedure TDCCustomTreeGrid.CMExit(var Message: TMessage);
  2628. begin
  2629.   try
  2630.     if (tgCancelOnExit in Options) then
  2631.     begin
  2632.       with FKnots do
  2633.       begin
  2634.         if (State = ksInsert) and not Modified then Delete(FSelectedKnot);
  2635.         if not HideEditor then
  2636.         begin
  2637.           SetFocus;
  2638.           Exit;
  2639.         end;
  2640.         SetState(ksBrowse);
  2641.       end;
  2642.     end;
  2643.     HideClipPopup;
  2644.     HideHintWindow;
  2645.     DoColumnComment(MODE_HIDEWINDOW, nil);
  2646.   except
  2647.     SetFocus;
  2648.     raise;
  2649.   end;
  2650.   inherited;
  2651. end;
  2652.  
  2653. procedure TDCCustomTreeGrid.CMKnotChanged(var Message: TMessage);
  2654. begin
  2655.   DataChanged;
  2656. end;
  2657.  
  2658. procedure TDCCustomTreeGrid.CMParentFontChanged(var Message: TMessage);
  2659. begin
  2660.   inherited;
  2661.   if ParentFont then
  2662.   begin
  2663.     FSelfChangingTitleFont := True;
  2664.     try
  2665.       TitleFont := Font;
  2666.     finally
  2667.       FSelfChangingTitleFont := False;
  2668.     end;
  2669.     LayoutChanged;
  2670.   end;
  2671. end;
  2672.  
  2673. procedure TDCCustomTreeGrid.ColumnMoved(FromIndex, ToIndex: Integer);
  2674. begin
  2675.   inherited;
  2676.   FromIndex := RawToDataColumn(FromIndex);
  2677.   ToIndex   := RawToDataColumn(ToIndex);
  2678.   Columns[FromIndex].Index := ToIndex;
  2679.   if Assigned(FOnColumnMoved) then FOnColumnMoved(Self, FromIndex, ToIndex);
  2680. end;
  2681.  
  2682. procedure TDCCustomTreeGrid.ColWidthsChanged;
  2683. var
  2684.   I: Integer;
  2685. begin
  2686.   if UpdateLocked then Exit;
  2687.   if AcquireLayoutLock then
  2688.   try
  2689.     inherited ColWidthsChanged;
  2690.     if FColumns.Count  > 0 then
  2691.       for I := FIndicatorOffset to ColCount - 1 do
  2692.         FColumns[I - FIndicatorOffset].Width := ColWidths[I];
  2693.     if FEditorMode then
  2694.       InplaceUpdateLoc(FInplaceEdit, CellRect(FInplaceCol, FInplaceRow), Canvas);
  2695.   finally
  2696.     EndLayout;
  2697.   end;
  2698. end;
  2699.  
  2700. constructor TDCCustomTreeGrid.Create(AOwner: TComponent);
  2701. var
  2702.   Bmp: TBitmap;
  2703. begin
  2704.   inherited Create(AOwner);
  2705.   inherited DefaultDrawing := False;
  2706.   Bmp := TBitmap.Create;
  2707.   try
  2708.     Bmp.LoadFromResourceName(HInstance, bmExpand);
  2709.     FTreeImages := TImageList.CreateSize(Bmp.Width, Bmp.Height);
  2710.     FTreeImages.AddMasked(Bmp, Bmp.Canvas.Pixels[0,0]);
  2711.     Bmp.LoadFromResourceName(HInstance, bmCollapse);
  2712.     FTreeImages.AddMasked(Bmp, Bmp.Canvas.Pixels[0,0]);
  2713.     Bmp.LoadFromResourceName(HInstance, bmExpandR);
  2714.     FTreeImages.AddMasked(Bmp, Bmp.Canvas.Pixels[0,0]);
  2715.     Bmp.LoadFromResourceName(HInstance, bmCollapseR);
  2716.     FTreeImages.AddMasked(Bmp, Bmp.Canvas.Pixels[0,0]);
  2717.  
  2718.     FTreeImages.DrawingStyle := dsTransparent;
  2719.   finally
  2720.     Bmp.Free;
  2721.   end;
  2722.  
  2723.   FDefaultDrawing := True;
  2724.   FTitleOffset := 1;
  2725.   FIndicatorOffset := 1;
  2726.   FOptions := [tgEditing, tgTitles, tgIndicator, tgColumnResize,
  2727.     tgColLines, tgRowLines, tgTabs, tgConfirmDelete, tgCancelOnExit,
  2728.     tgTreePathResize, tgFixedLines, tgColMoving];
  2729.  
  2730.   FOptionsEx := [tgeInsertSelect, tgeMarkerMenu, tgeShadowSelection, tgeShowButtons];
  2731.  
  2732.   DesignOptionsBoost := [goColSizing];
  2733.   VirtualView := True;
  2734.   UsesBitmap;
  2735.  
  2736.   inherited Options := [goFixedHorzLine, goFixedVertLine, goHorzLine,
  2737.     goVertLine, goColSizing, goTabs];
  2738.  
  2739.   FKnots   := CreateKnots;
  2740.   FColumns := CreateColumns;
  2741.  
  2742.   inherited RowCount := 2;
  2743.   inherited ColCount := 2;
  2744.  
  2745.   Color := clWindow;
  2746.   ParentColor := False;
  2747.   FTitleFont := TFont.Create;
  2748.   FTitleFont.OnChange := TitleFontChanged;
  2749.   FSaveCellExtents := False;
  2750.  
  2751.   FBookmarks := TKnotBookmarkList.Create(Self);
  2752.  
  2753.   FCurrentCol := -1;
  2754.   FMousePoint := Point(-1,-1);
  2755.   FClipDown   := False;
  2756.   FFirstGridCell := 0;
  2757.   FTreepathWidth := 0;
  2758.  
  2759.   InitGridPos;
  2760.  
  2761.   FInplaceEdit   := nil;
  2762.   FEditorMode    := False;
  2763.   FInplaceCol    := -1;
  2764.   FInplaceRow    := -1;
  2765.   FIsESCKey      := False;
  2766.   FIsModified    := False;
  2767.   FRowUpdated    := False;
  2768.  
  2769.   FHintRow       := -1;
  2770.  
  2771.   FImageChangeLink :=  TChangeLink.Create;
  2772.   FImageChangeLink.OnChange := ImageListChange;
  2773.   FBookmarkSize  := 20;
  2774.   FMouseDownRow  := -1;
  2775.   FEditTimerID   := -1;
  2776.   FColumnCell    := -1;
  2777.   FLockScroll    := False;
  2778.   FLockWindow    := False;
  2779.  
  2780.   FSizingIndex   := -1;
  2781.   FIndent        := FTreeImages.Width + 2;
  2782.   FColumnFooter  := TKnotColumnFooter.Create(Footers);
  2783.   FTreePath      := TTreePath.Create(Self); 
  2784. end;
  2785.  
  2786. procedure TDCCustomTreeGrid.CreateWnd;
  2787. begin
  2788.   BeginUpdate;   { prevent updates in WMSize message that follows WMCreate }
  2789.   try
  2790.     inherited CreateWnd;
  2791.   finally
  2792.     EndUpdate;
  2793.   end;
  2794.   UpdateRowCount;
  2795.  
  2796.   FClipPopup := TKnotClipPopup.Create(Self);
  2797.   TKnotClipPopup(FClipPopup).CellType := fcNone;
  2798. end;
  2799.  
  2800. procedure TDCCustomTreeGrid.DataChanged;
  2801. begin
  2802.   if not HandleAllocated then Exit;
  2803.   UpdateRowCount;
  2804. end;
  2805.  
  2806. function TDCCustomTreeGrid.DataToRawColumn(ACol: Integer): Integer;
  2807. begin
  2808.   Result := ACol + FIndicatorOffset;
  2809. end;
  2810.  
  2811. procedure TDCCustomTreeGrid.DblClick;
  2812.  var
  2813.   Cell: TGridCoord;
  2814.   P: TPoint;
  2815.   R: TRect;
  2816.   ARow: integer;
  2817. begin
  2818.   if not AcquireFocus or FKnots.Updating then Exit;
  2819.  
  2820.   GetCursorPos(P);
  2821.   P := ScreenToClient(P);
  2822.   Cell := MouseCoord(P.X, P.Y);
  2823.   R := CellRect(Cell.X, Cell.Y);
  2824.  
  2825.   if (FKnots.Count > 0) and (Cell.Y >= FTitleOffset) then
  2826.     with Cell do
  2827.     begin
  2828.       BeginUpdate;
  2829.       try
  2830.         if (Y >= FTitleOffset) and (Y - Row <> 0) then
  2831.         begin
  2832.           ARow := Row;
  2833.           Row  := Cell.Y;
  2834.           if (ARow<>Cell.Y) and (Row<>Cell.Y) and (ARow=Row) then Exit;
  2835.         end;
  2836.         if Cell.X < FIndicatorOffset then
  2837.           with FSelectedKnot do
  2838.           begin
  2839.             case GetFixedCellType(Cell.X, 0) of
  2840.               fcTreePath:
  2841.                 if tgEditing in Options then
  2842.                 begin
  2843.                   case GetHitTestInfoAt(FSelectedKnot, P.X-R.Left, P.Y-R.Top) of
  2844.                     htOnButton,
  2845.                     htOnIcon  ,
  2846.                     htOnLabel :
  2847.                       if HasChildren then
  2848.                       begin
  2849.                         if Expanded then
  2850.                           Collapse(False)
  2851.                         else
  2852.                           Expand(False);
  2853.                       end;
  2854.                   end
  2855.                 end
  2856.                 else
  2857.                   if HasChildren then
  2858.                   begin
  2859.                     if Expanded then
  2860.                       Collapse(False)
  2861.                     else
  2862.                       Expand(False);
  2863.                   end;
  2864.             end
  2865.           end
  2866.         else begin
  2867.           if tgTreePathCompletion in Options then with FSelectedKnot do
  2868.           begin
  2869.             if HasChildren then
  2870.             begin
  2871.                if Expanded then
  2872.                  Collapse(False)
  2873.                else
  2874.                  Expand(False);
  2875.             end;
  2876.           end;
  2877.           ShowEditor;
  2878.         end;
  2879.       finally
  2880.         EndUpdate;
  2881.       end;
  2882.     end
  2883.     else
  2884.       if (Cell.X >= FIndicatorOffset) and (FKnots.Count = 0) and
  2885.          (Cell.Y >= FTitleOffset)
  2886.       then begin
  2887.          ShowEditor;
  2888.       end;
  2889.  
  2890.   inherited;
  2891. end;
  2892.  
  2893. destructor TDCCustomTreeGrid.Destroy;
  2894. begin
  2895.  
  2896.   if Assigned(FCurrentPos[1]) then FreeMem(FCurrentPos[1]);
  2897.   if Assigned(FCurrentPos[2]) then FreeMem(FCurrentPos[2]);
  2898.  
  2899.   if Assigned(FClipPopup) then TKnotClipPopup(FClipPopup).Free;
  2900.  
  2901.   FColumns.Free;
  2902.   FTreeImages.Free;
  2903.   FTitleFont.Free;
  2904.   FKnots.Free;
  2905.   FBookmarks.Free;
  2906.   ReleaseBitmap;
  2907.   FImageChangeLink.Free;
  2908.   FTreePath.Free;
  2909.   inherited;
  2910. end;
  2911.  
  2912. function TDCCustomTreeGrid.DrawTitleCell(ACanvas: TCanvas; ACol,
  2913.   ARow: Integer; ARect: TRect; BorderState: TDrawBorerState; AFillRect, ADraw: boolean): TPoint;
  2914. const
  2915.   ColumnIndexStyle : array [TColumnIndexStyle] of Integer =
  2916.    (nbmIndexNone,nbmIndexAsc,nbmIndexDesc);
  2917.   AlignFlags : array [TAlignment] of Integer =
  2918.     ( DT_LEFT   or DT_NOPREFIX or DT_END_ELLIPSIS,
  2919.       DT_RIGHT  or DT_NOPREFIX or DT_END_ELLIPSIS,
  2920.       DT_CENTER or DT_NOPREFIX or DT_END_ELLIPSIS);
  2921.  
  2922.  var
  2923.   TitleRect, TextRect, DrawRect: TRect;
  2924.   Column: TKnotColumn;
  2925.   Indicators: TImageList;
  2926.  
  2927.   function DoPaint(Canvas: TCanvas; DrawRect: TRect): TPoint;
  2928.    var
  2929.     P: TPoint;
  2930.     W: integer;
  2931.   begin
  2932.     TextRect := DrawRect;
  2933.  
  2934.     Canvas.Font := Column.Title.Font;
  2935.     Canvas.Brush.Color := Column.Title.Color;
  2936.  
  2937.     if AFillRect then FillRect(Canvas.Handle, TextRect, Canvas.Brush.Handle);
  2938.  
  2939.     W := 0;
  2940.     if BorderState = dsDown then
  2941.     begin
  2942.       TextRect.Top    := TextRect.Top  + 1;
  2943.       OffsetRect(TextRect, 3, 0);
  2944.     end
  2945.     else
  2946.       TextRect.Left := TextRect.Left + 2;
  2947.  
  2948.     if (Column.Grid.Images <> nil) and (Column.ItemIndex <> -1) and
  2949.        ((TextRect.Right - TextRect.Left) > 0)
  2950.     then begin
  2951.       if ADraw then Column.Grid.Images.Draw(Canvas, TextRect.Left, TextRect.Top, Column.ItemIndex);
  2952.       TextRect.Left := TextRect.Left + Column.Grid.Images.Width + 2;
  2953.       W := Column.Grid.Images.Height - 1;
  2954.     end;
  2955.  
  2956.     if TextRect.Left < TextRect.Right then
  2957.     begin
  2958.       SetTextColor(Canvas.Handle, Canvas.Font.Color);
  2959.       case Column.Title.Alignment of
  2960.         taLeftJustify:
  2961.           if ADraw then
  2962.             P := DrawHighLightText(Canvas, PChar(Column.Title.Caption),
  2963.               TextRect, 1, DT_NOPREFIX)
  2964.           else
  2965.             P := DrawHighLightText(Canvas, PChar(Column.Title.Caption),
  2966.               TextRect, 0, DT_NOPREFIX);
  2967.         taCenter, taRightJustify:
  2968.           begin
  2969.             if (kcIndexed in Column.Options) and (Column.IndexStyle <> idxNone) then
  2970.               Dec(TextRect.Right, IndexTitleWidth + 2);
  2971.             P := DrawTitleRect(Canvas, TextRect, Column.Title.Caption,
  2972.               Column.Title.Alignment, ADraw)
  2973.           end;
  2974.       end;
  2975.       Result.Y := _intMax(P.Y, W);
  2976.       Result.X := P.X + 2;
  2977.       if (kcIndexed in Column.Options) and ((Column.IndexStyle <> idxNone) and
  2978.         ((IndexTitleWidth + 4) <= (TextRect.Right - TextRect.Left)) or not ADraw)
  2979.       then begin
  2980.         if ADraw then
  2981.         begin
  2982.           if Column.Title.Alignment = taCenter then
  2983.             P.X := (TextRect.Right + TextRect.Left - P.X) div 2 + P.X - 1;
  2984.           Indicators.Draw(Canvas, P.X + 2, TextRect.Top, ColumnIndexStyle[Column.IndexStyle]);
  2985.         end;
  2986.         Inc(Result.X, IndexTitleWidth + 4);
  2987.       end
  2988.       else
  2989.         Inc(Result.X, 2);
  2990.     end;
  2991.  
  2992.   end;
  2993.  
  2994. begin
  2995.   if ACol < 0 then Exit;
  2996.  
  2997.   Column     := Columns[ACol];
  2998.   TitleRect  := ARect;
  2999.   Indicators := GDGetImages;
  3000.  
  3001.   with TitleRect do if Right - Left <= 0 then Exit;
  3002.  
  3003.   if AFillRect then
  3004.   begin
  3005.     DrawBitmap.Width  := TitleRect.Right  - TitleRect.Left;
  3006.     DrawBitmap.Height := TitleRect.Bottom - TitleRect.Top;
  3007.  
  3008.     with DrawBitmap do
  3009.     begin
  3010.       DrawRect := Rect(0,0, Width, Height);
  3011.       Result := DoPaint(Canvas, DrawRect);
  3012.     end;
  3013.     if ADraw then ACanvas.Draw(ARect.Left, ARect.Top, DrawBitmap);
  3014.   end
  3015.   else
  3016.     Result := DoPaint(ACanvas, ARect);
  3017. end;
  3018.  
  3019. procedure TDCCustomTreeGrid.DrawCell(ACol, ARow: Integer; ARect: TRect;
  3020.   AState: TGridDrawState);
  3021. var
  3022.   FrameOffs: Byte;
  3023.   BorderState: TDrawBorerState;
  3024.   BorderStyle: TEdgeBorderStyle;
  3025.   DrawKnot: TKnotItem;
  3026.   DrawColumn: TKnotColumn;
  3027.   Highlight, KnotFound, CellBorder: boolean;
  3028.   ALeft, ATop, KnotIndex, Indicator, LineColor: integer;
  3029.   CellType: TFixedCell;
  3030.   DrawRect: TRect;
  3031.   Indicators: TImageList;
  3032.  
  3033.   procedure GetDrawState(Canvas: TCanvas; AColumn: TKnotColumn);
  3034.   begin
  3035.     Highlight := HighlightCell(ACol, ARow, AState, DrawKnot);
  3036.     with Canvas do
  3037.     begin
  3038.       if (gdFixed in AState) and CellBorder then
  3039.       begin
  3040.          if AColumn <> nil then
  3041.          begin
  3042.            Font := AColumn.Title.Font;
  3043.            Brush.Color := AColumn.Title.Color;
  3044.          end
  3045.          else begin
  3046.            Font := TreePath.Font;
  3047.            Brush.Color := TreePath.Color;
  3048.          end;
  3049.       end
  3050.       else begin
  3051.         if AColumn <> nil then
  3052.         begin
  3053.           Font := AColumn.Font;
  3054.           Brush.Color := AColumn.Color;
  3055.         end
  3056.         else begin
  3057.           Font := Self.Font;
  3058.           if CellBorder then
  3059.             Brush.Color := FixedColor
  3060.           else
  3061.             Brush.Color := Self.Color
  3062.         end;
  3063.       end;
  3064.  
  3065.       if (tgHighlightRow in Options) and (AlwaysShowSelection or
  3066.         Focused or (Row = FInplaceRow)) then
  3067.       begin
  3068.         if ARow = Row - FTitleOffset then
  3069.         begin
  3070.           if not Focused and (tgeShadowSelection in OptionsEx) then
  3071.             Brush.Color := clShadowed
  3072.           else begin
  3073.             if Highlight or not (tgMultiSelect in Options) then
  3074.             begin
  3075.               Brush.Color := clHighlight;
  3076.               Font.Color := clHighlightText;
  3077.             end;
  3078.           end;
  3079.           AState := AState + [gdFocused];
  3080.         end;
  3081.         if Highlight then
  3082.         begin
  3083.           if not Focused and (tgeShadowSelection in OptionsEx) then
  3084.             Brush.Color := clShadowed
  3085.           else begin
  3086.             if not (tgMultiSelect in Options) then
  3087.             begin
  3088.               Brush.Color := clRowHighlight;
  3089.               Font.Color  := clTextHighlight;
  3090.             end
  3091.             else begin
  3092.               Brush.Color := clHighlight;
  3093.               Font.Color := clHighlightText;
  3094.             end;
  3095.           end;
  3096.           AState := AState + [gdSelected];
  3097.         end;
  3098.       end
  3099.       else
  3100.       if Highlight or (not (tgMultiSelect in Options) or (Knots.Count = 0)) and
  3101.          ((tgTitles in Options) and
  3102.             (ARow = (Row-FTitleOffset)) or ([tgTitles]*Options=[]) and (ARow=Row)) and
  3103.          ((tgRowSelect in Options) or
  3104.             (tgTreePathCompletion in Options) and (DrawKnot <> nil) and DrawKnot.HasChildren)
  3105.       then begin
  3106.         if AlwaysShowSelection or Focused then
  3107.         begin
  3108.           if not Focused and (tgeShadowSelection in OptionsEx) then
  3109.             Brush.Color := clShadowed
  3110.           else begin
  3111.             Brush.Color := clHighlight;
  3112.             Font.Color  := clHighlightText;
  3113.           end;
  3114.         end;
  3115.         AState := AState + [gdFocused];
  3116.       end;
  3117.     end;
  3118.   end;
  3119.  
  3120.   procedure DrawTreePathCell(ARect, PieRect: TRect; var AState: TGridDrawState;
  3121.     KnotFound: boolean; DrawKnot: TKnotItem);
  3122.    var
  3123.     DrawRect, TextRect: TRect;
  3124.     ATop, ITop, nVisible: integer;
  3125.     Text: string;
  3126.     P: TPoint;
  3127.     PrevKnot, NextKnot: TKnotItem;
  3128.  
  3129.     {╞σδα≥σδⁿφε Γ√φσ±≥Φ Γ protected Φ ΣεßαΓΦ≥ⁿ Event CustomDrawItem}
  3130.     procedure DoDraw(Canvas: TCanvas);
  3131.      var
  3132.       j, ButtonSize, cx, cy, wx, hy: integer;
  3133.       FastDraw: boolean;
  3134.       LineColor: TColor;
  3135.       LRect: TRect;
  3136.       KnotItem: TKnotItem;
  3137.  
  3138.       procedure DrawLineX(Canvas: TCanvas; AColor: TColor; APos: TPoint;
  3139.         ALength: integer);
  3140.        var
  3141.         i: integer;
  3142.       begin
  3143.         for i := 0 to ALength do
  3144.           if i mod 2 = 1 then Canvas.Pixels[APos.X + i, APos.Y] := AColor;
  3145.       end;
  3146.       procedure DrawLineY(Canvas: TCanvas; AColor: TColor; APos: TPoint;
  3147.         ALength: integer);
  3148.        var
  3149.         i: integer;
  3150.       begin
  3151.         for i := 0 to ALength do
  3152.           if i mod 2 = 1 then Canvas.Pixels[APos.X, APos.Y + i] := AColor;
  3153.       end;
  3154.  
  3155.     begin
  3156.       if not((tgTreePathCompletion in Options) and
  3157.           (AState*[gdSelected, gdFocused] <> []) and KnotFound and DrawKnot.HasChildren) then
  3158.       begin
  3159.         if CellBorder then
  3160.           Canvas.Brush.Color := TreePath.Color
  3161.         else
  3162.           Canvas.Brush.Color := Self.Color;
  3163.         Canvas.Font := TreePath.Font;
  3164.       end;
  3165.       if tgeTreeSelect in OptionsEx then GetDrawState(Canvas, nil);
  3166.  
  3167.       LineColor := clBtnFace;
  3168.  
  3169.       if [tgColLines, tgRowLines] * Options = [tgRowLines] then
  3170.       begin
  3171.         if tgTreePathCompletion in Options then InflateRect(TextRect, 0, -1)
  3172.       end;
  3173.  
  3174.       FillRect(Canvas.Handle, TextRect, Canvas.Brush.Handle);
  3175.       ATop := (DrawRect.Top + DrawRect.Bottom - FTreeImages.Height) shr 1;
  3176.  
  3177.       if BorderState = dsDown then
  3178.       begin
  3179.         TextRect.Left   := TextRect.Left + 3;
  3180.         TextRect.Top    := TextRect.Top  + 1;
  3181.         Inc(ATop);
  3182.       end
  3183.       else
  3184.         TextRect.Left := TextRect.Left + 2;
  3185.  
  3186.       {╨Φ±σ≤∞ δΦφφΦΦ}
  3187.  
  3188.       if tgTreePathCompletion in Options then
  3189.       begin
  3190.         if (tgFlatButtons in Options) and (tgRowLines in Options) then
  3191.         begin
  3192.           if KnotFound and (DrawKnot.Level > 0) then
  3193.           begin
  3194.             for j := 1 to DrawKnot.Level do
  3195.             begin
  3196.               Inc(TextRect.Left, Indent);
  3197.               Canvas.Pen.Color := LineColor;
  3198.               Canvas.PenPos := Point(TextRect.Left - 4, TextRect.Top - 1);
  3199.               Canvas.LineTo(TextRect.Left - 4, TextRect.Bottom + 1);
  3200.  
  3201.               Canvas.Pen.Color := Self.Color;
  3202.               Canvas.PenPos := Point(TextRect.Left - 3, TextRect.Top);
  3203.               Canvas.LineTo(TextRect.Left - 3, TextRect.Bottom + 1);
  3204.             end;
  3205.           end
  3206.           else;
  3207.           Canvas.Pen.Color := Self.Color;
  3208.           Canvas.PenPos := Point(TextRect.Left-3, TextRect.Top);
  3209.           Canvas.LineTo(TextRect.Right, TextRect.Top);
  3210.  
  3211.           Canvas.Pen.Color := LineColor;
  3212.           if tgColLines in Options then
  3213.           begin
  3214.             Canvas.PenPos := Point(TextRect.Left - 2, TextRect.Top - 1);
  3215.             Canvas.LineTo(TextRect.Right, TextRect.Top - 1);
  3216.           end;
  3217.           if tgDrawFixedLine in Options then
  3218.           begin
  3219.             Canvas.PenPos := Point(TextRect.Left - 2, TextRect.Bottom);
  3220.             Canvas.LineTo(TextRect.Right, TextRect.Bottom);
  3221.             Canvas.PenPos := Point(TextRect.Right, TextRect.Top);
  3222.             Canvas.LineTo(TextRect.Right, TextRect.Bottom + 1);
  3223.           end;
  3224.           InflateRect(TextRect, 0, -1);
  3225.         end
  3226.         else begin
  3227.           Canvas.Pen.Color := LineColor;
  3228.           Canvas.PenPos := Point(TextRect.Left - 2, TextRect.Bottom);
  3229.           Canvas.LineTo(TextRect.Right, TextRect.Bottom);
  3230.           if tgDrawFixedLine in Options then
  3231.           begin
  3232.             Canvas.PenPos := Point(TextRect.Right, TextRect.Top);
  3233.             Canvas.LineTo(TextRect.Right, TextRect.Bottom + 1);
  3234.           end;
  3235.           if KnotFound then Inc(TextRect.Left, DrawKnot.Level*Indent);
  3236.         end;
  3237.       end
  3238.       else
  3239.         if KnotFound then Inc(TextRect.Left, DrawKnot.Level*Indent);
  3240.  
  3241.       if not KnotFound then Exit;
  3242.  
  3243.       with DrawKnot do
  3244.       begin
  3245.         nVisible := VisibleChilds;
  3246.         if ((nVisible > 0) or HasChildren) and (tgeShowButtons in OptionsEx) then
  3247.         begin
  3248.           if DrawKnot.Expanded then
  3249.           begin
  3250.             if tgTreePathCompletion in Options then
  3251.               FTreeImages.Draw(Canvas, TextRect.Left, ATop + 1, nbmExpandR)
  3252.             else
  3253.               FTreeImages.Draw(Canvas, TextRect.Left, ATop + 1, nbmExpand)
  3254.           end
  3255.           else
  3256.           begin
  3257.             if tgTreePathCompletion in Options then
  3258.               FTreeImages.Draw(Canvas, TextRect.Left, ATop + 1, nbmCollapseR)
  3259.             else
  3260.               FTreeImages.Draw(Canvas, TextRect.Left, ATop + 1, nbmCollapse);
  3261.           end;
  3262.         end;
  3263.         
  3264.         if [tgeShowLines, tgeShowButtons] * OptionsEx <> [] then
  3265.           TextRect.Left := TextRect.Left + Indent + 1
  3266.         else
  3267.           Inc(TextRect.Left, 1);
  3268.  
  3269.         if (tgeShowLines in OptionsEx) and
  3270.            not(tgTreePathCompletion in Options) then
  3271.         begin
  3272.           ButtonSize := 5;
  3273.           LRect := TextRect;
  3274.           InflateRect(LRect, 0, 2);
  3275.           wx := LRect.Left - 2;
  3276.           hy := LRect.Bottom;
  3277.           cx := LRect.Left - Indent - 1 + ButtonSize;
  3278.           cy := LRect.Top + (LRect.Bottom - LRect.Top) div 2;
  3279.           if cy mod 2 = 0 then dec(cy);
  3280.  
  3281.           PrevKnot := DrawKnot.GetPrevVisible;
  3282.           NextKnot := DrawKnot.GetNextSiblingVisible;
  3283.  
  3284.           Canvas.Pen.Style := psSolid;
  3285.  
  3286.           if DrawKnot.HasChildren and (tgeShowButtons in OptionsEx) then
  3287.             DrawLineX(Canvas, clAppWorkSpace,
  3288.               Point(cx + ButtonSize, cy), wx - (cx + ButtonSize) + 1)
  3289.           else
  3290.             DrawLineX(Canvas, clAppWorkSpace, Point(cx - 1, cy), wx - cx + 1);
  3291.  
  3292.           if tgeShowButtons in OptionsEx then
  3293.           begin
  3294.             if PrevKnot <> nil then
  3295.               DrawLineY(Canvas, clAppWorkSpace, Point(cx, LRect.Top), hy - cy - ButtonSize);
  3296.  
  3297.             if NextKnot <> nil then
  3298.               DrawLineY(Canvas, clAppWorkSpace, Point(cx, cy + ButtonSize), hy - cy - ButtonSize);
  3299.  
  3300.             if (nVisible = 0) or not HasChildren then
  3301.             begin
  3302.               if PrevKnot <> nil then
  3303.                 DrawLineY(Canvas, clAppWorkSpace, Point(cx, cy - ButtonSize), (ButtonSize + 2) div 2);
  3304.               if NextKnot <> nil then
  3305.                 DrawLineY(Canvas, clAppWorkSpace, Point(cx, cy + 1), (ButtonSize + 2) div 2)
  3306.             end;
  3307.           end
  3308.           else begin
  3309.             if PrevKnot <> nil then
  3310.               DrawLineY(Canvas, clAppWorkSpace, Point(cx, LRect.Top), hy - cy);
  3311.  
  3312.             if NextKnot <> nil then
  3313.               DrawLineY(Canvas, clAppWorkSpace, Point(cx, cy - 1), hy - cy);
  3314.           end;
  3315.  
  3316.           KnotItem := DrawKnot.Parent;
  3317.           while KnotItem.Level <> -1 do
  3318.           begin
  3319.             cx := cx - Indent;
  3320.             if KnotItem.GetNextSiblingVisible <> nil then
  3321.               DrawLineY(Canvas, clAppWorkSpace, Point(cx, LRect.Top), hy - LRect.Top);
  3322.             KnotItem := KnotItem.Parent;
  3323.           end;
  3324.         end;
  3325.  
  3326.         if (Images <> nil) then
  3327.         begin
  3328.           if FImages.Height < TextRect.Bottom - TextRect.Top then
  3329.             ITop := (TextRect.Top + TextRect.Bottom - FImages.Height) shr 1
  3330.           else
  3331.             ITop := TextRect.Top;
  3332.           if (ARow = (Row-FTitleOffset)) then
  3333.           begin
  3334.              if(SelectImage <> -1) then
  3335.              begin
  3336.                FImages.Draw(Canvas, TextRect.Left, ITop, SelectImage);
  3337.                TextRect.Left := TextRect.Left + FImages.Width + 5
  3338.              end
  3339.           end
  3340.           else begin
  3341.              if(NormalImage <> -1) then
  3342.              begin
  3343.                FImages.Draw(Canvas, TextRect.Left, ITop, NormalImage);
  3344.                TextRect.Left := TextRect.Left + FImages.Width + 5
  3345.              end;
  3346.           end;
  3347.         end;
  3348.         FastDraw := GetTreePathCaption(DrawKnot, Text);
  3349.  
  3350.         if not(tgTreePathCompletion in Options) and not FastDraw then
  3351.         begin
  3352.           P := DrawHighLightText(Canvas, PChar(Text), TextRect, 0, 0, FImages);
  3353.           if P.Y < TextRect.Bottom - TextRect.Top then
  3354.             TextRect.Top  := (TextRect.Top + TextRect.Bottom - P.Y) shr 1;
  3355.           DrawHighLightText(Canvas, PChar(Text), TextRect, 1, 0, FImages);
  3356.         end
  3357.         else
  3358.           DrawText(Canvas.Handle, PChar(Text), Length(Text), TextRect, DT_LEFT or DT_VCENTER or DT_SINGLELINE);
  3359.       end;
  3360.     end;
  3361.  
  3362.   begin
  3363.     if KnotFound then
  3364.     begin
  3365.       if not(DoubleBuffered or DefaultDrawing) then with DrawBitmap do
  3366.       begin
  3367.         Width  := ARect.Right  - ARect.Left;
  3368.         Height := ARect.Bottom - ARect.Top;
  3369.         DrawRect := Rect(0,0, Width, Height);
  3370.       end
  3371.       else
  3372.         DrawRect := ARect;
  3373.       TextRect := DrawRect;
  3374.  
  3375.       if not(DoubleBuffered or DefaultDrawing)  then
  3376.       begin
  3377.         DoDraw(DrawBitmap.Canvas);
  3378.         with PieRect do
  3379.           BitBlt(Self.Canvas.Handle, Left, Top, Right- Left, Bottom - Top,
  3380.             DrawBitmap.Canvas.Handle, Left - ARect.Left, Top - ARect.Top, SRCCOPY);
  3381.       end
  3382.       else
  3383.         DoDraw(Canvas);
  3384.     end
  3385.     else begin
  3386.       if tgeTreeSelect in OptionsEx then GetDrawState(Canvas, nil);
  3387.       Canvas.FillRect(PieRect);
  3388.     end;
  3389.   end;
  3390.  
  3391.   function GetTreePathRect(ARow: integer; ARect: TRect): TRect;
  3392.    var
  3393.     R1, R2: TRect;
  3394.     TreeCol: integer;
  3395.  
  3396.   begin
  3397.     TreeCol := 0;
  3398.  
  3399.     if tgIndicator in Options then Inc(TreeCol);
  3400.     if tgMarker    in Options then Inc(TreeCol);
  3401.  
  3402.     Inc(ARow, FTitleOffset);
  3403.     R1 := CellRect(TreeCol, ARow);
  3404.     R2 := CellRect(LeftCol + VisibleColCount, ARow);
  3405.     Result := Rect(R1.Left, ARect.Top, R2.Right, ARect.Bottom);
  3406.   end;
  3407.  
  3408.   procedure PaintLine(Canvas: TCanvas; ARect: TRect);
  3409.   begin
  3410.     Canvas.Pen.Color := Self.Color;
  3411.     Canvas.PenPos := Point(ARect.Left, ARect.Top);
  3412.     Canvas.LineTo(ARect.Right, ARect.Top);
  3413.   end;
  3414.  
  3415.   function DoDrawCell(Canvas: TCanvas): boolean;
  3416.   begin
  3417.     Result := False;
  3418.     with Canvas do
  3419.     begin
  3420.       GetDrawState(Canvas, DrawColumn);
  3421.       if not Enabled or
  3422.         ((DrawKnot <> nil) and not DrawKnot.Enabled) then Font.Color := clGrayText;
  3423.  
  3424.       if not (tgTreePathCompletion in Options) then
  3425.       begin
  3426.         FillRect(DrawRect);
  3427.         if KnotFound then
  3428.           DoDrawColumnCell(Canvas, DrawRect, ACol, DrawColumn, DrawKnot, AState);
  3429.       end
  3430.       else begin
  3431.         if KnotFound {and (DrawKnot.Data <> nil)} then
  3432.         begin
  3433.           if DrawKnot.HasChildren and not(kcDrawTreeCell in DrawColumn.Options) then
  3434.           begin
  3435.             if not(DoubleBuffered or DefaultDrawing)  then
  3436.               DrawTreePathCell(GetTreePathRect(ARow, ARect), ARect, AState, KnotFound, DrawKnot)
  3437.             else begin
  3438.               if TreePathWidth = 0 then
  3439.               begin
  3440.                 FillRect(DrawRect);
  3441.                 DoDrawColumnCell(Canvas, DrawRect, ACol, DrawColumn, DrawKnot, AState);
  3442.                 PaintLine(Canvas, DrawRect);
  3443.               end;
  3444.             end;
  3445.             Exit;
  3446.           end
  3447.           else begin
  3448.             FillRect(DrawRect);
  3449.             DoDrawColumnCell(Canvas, DrawRect, ACol, DrawColumn, DrawKnot, AState);
  3450.             PaintLine(Canvas, DrawRect);
  3451.           end;
  3452.         end
  3453.         else begin
  3454.           FillRect(DrawRect);
  3455.           PaintLine(Canvas, DrawRect);
  3456.         end;
  3457.       end
  3458.     end;
  3459.     Result := True;
  3460.   end;
  3461.  
  3462.   procedure DrawFixedBorder(ARect: TRect; Frame: boolean);
  3463.   begin
  3464.     if Frame then FrameRect(Canvas.Handle, ARect, Canvas.Brush.Handle);
  3465.     if tgDrawFixedLine in Options then
  3466.     begin
  3467.       LineColor := clSilver;
  3468.       if ColorToRGB(Color) = clSilver then LineColor := clGray;
  3469.       with Canvas do
  3470.       begin
  3471.         Pen.Color := Pen.Color -1;
  3472.         Pen.Color := LineColor;
  3473.         PenPos := Point(ARect.Right, ARect.Top);
  3474.         LineTo(ARect.Right, ARect.Bottom);
  3475.  
  3476.         PenPos := Point(ARect.Left, ARect.Bottom);
  3477.         LineTo(ARect.Right + 1, ARect.Bottom);
  3478.       end;
  3479.     end;
  3480.   end;
  3481.  
  3482.   procedure DrawBorderEx(ARect: TRect; ABorderState: TDrawBorerState);
  3483.   begin
  3484.     if (tgRowLines in Options) or (BorderStyle <> ebsNone) then
  3485.     begin
  3486.       if (BorderStyle = ebsNone) then
  3487.       begin
  3488.         if [tgColLines, tgRowLines, tgTreePathCompletion] * Options <> [tgRowLines] then
  3489.           InflateRect(ARect, 1, 1);
  3490.         DrawFixedBorder(ARect, True)
  3491.       end
  3492.       else begin
  3493.         InflateRect(ARect, 1, 1);
  3494.         DrawGridFrameBorder(Canvas, ARect, BorderStyle, ABorderState, FixedColor);
  3495.       end;
  3496.     end
  3497.     else
  3498.       if (BorderStyle = ebsNone) and (tgDrawFixedLine in Options) then
  3499.          DrawFixedBorder(ARect, False)
  3500.   end;
  3501.  
  3502.   procedure DrawFixedCellFrame(ACellType: TFixedCell; ImageIndex: integer);
  3503.   begin
  3504.     if FClipDown and (TKnotClipPopup(FClipPopup).CellType = ACellType) then
  3505.     begin
  3506.       if tgFixedLines in Options then
  3507.         Indicators.Draw(Canvas, ALeft, ATop+1, ImageIndex)
  3508.       else
  3509.         Indicators.Draw(Canvas, ALeft-1, ATop, ImageIndex);
  3510.       DrawBorderEx(ARect, dsDown);
  3511.     end
  3512.     else begin
  3513.       Indicators.Draw(Canvas, ALeft-1, ATop, ImageIndex);
  3514.       DrawBorderEx(ARect, dsUp);
  3515.     end;  
  3516.   end;
  3517.  
  3518. begin
  3519.   if (csLoading in ComponentState) then
  3520.   begin
  3521.     Canvas.Brush.Color := Color;
  3522.     Canvas.FillRect(ARect);
  3523.     Exit;
  3524.   end;
  3525.   BorderStyle := GetBorderStyle;
  3526.   Indicators  := GDGetImages;
  3527.  
  3528.   if (ClickedCol <> -1) and (ACol= ClickedCol) then
  3529.     BorderState := dsDown
  3530.   else
  3531.     BorderState := dsUp;
  3532.  
  3533.   Dec(ARow, FTitleOffset);
  3534.   Dec(ACol, FIndicatorOffset);
  3535.  
  3536.   if (GetFixedCellType(ACol, FIndicatorOffset) = fcTreePath) and
  3537.      (tgeTreeSelect in OptionsEx) and not(tgTreePathCompletion in Options) and
  3538.      (ARow >= 0) then
  3539.     CellBorder := False
  3540.   else
  3541.     CellBorder := True;
  3542.  
  3543.   if CellBorder and (gdFixed in AState) and
  3544.      ([tgRowLines, tgColLines] * Options = [tgRowLines, tgColLines])
  3545.   then begin
  3546.     InflateRect(ARect, -1, -1);
  3547.     FrameOffs := 1;
  3548.   end
  3549.   else
  3550.     FrameOffs := 2;
  3551.  
  3552.   DrawKnot := FActiveKnot;
  3553.   if ARow >= 0 then
  3554.   begin
  3555.     KnotIndex := FFirstIndex;
  3556.     DrawKnot  := FFirstVisible;
  3557.  
  3558.     while (KnotIndex <> ARow) and (DrawKnot <> nil) do
  3559.     begin
  3560.       DrawKnot := DrawKnot.GetNextVisible;
  3561.       Inc(KnotIndex);
  3562.     end;
  3563.     FActiveKnot := DrawKnot;
  3564.  
  3565.     if (DrawKnot <> nil) and (DrawKnot <> FKnots.Root) then
  3566.       KnotFound   := True
  3567.     else
  3568.       KnotFound := False;
  3569.   end
  3570.   else
  3571.     KnotFound := False;
  3572.  
  3573.   if (gdFixed in AState) and (ACol < 0)
  3574.   then begin
  3575.     CellType := GetFixedCellType(ACol, FIndicatorOffset);
  3576.     if CellBorder then
  3577.       Canvas.Brush.Color := FixedColor
  3578.     else
  3579.       Canvas.Brush.Color := Self.Color;
  3580.     if (CellType <> fcTreePath) or (ARow<0) or not KnotFound then Canvas.FillRect(ARect);
  3581.     case CellType of
  3582.       fcIndicator:
  3583.         begin
  3584.           ALeft := (ARect.Right + ARect.Left - Indicators.Width - FrameOffs) shr 1 + 1;
  3585.           ATop  := (ARect.Top + ARect.Bottom - Indicators.Height) shr 1;
  3586.           if ARow = (Row-FTitleOffset) then
  3587.           begin
  3588.             case FKnots.State of
  3589.               ksInsert: Indicator := nbmInsert;
  3590.               ksEdit  : Indicator := nbmEdit;
  3591.               ksBrowse: Indicator := nbmArrow;
  3592.               else
  3593.                 Indicator := nbmArrow;
  3594.             end;
  3595.             Indicators.Draw(Canvas, ALeft, ATop, Indicator, True);
  3596.           end;
  3597.           if ARow < 0 then
  3598.           begin
  3599.             if (tgeMarkerMenu in OptionsEx) then
  3600.               DrawFixedCellFrame(fcIndicator, nbmMain)
  3601.             else begin
  3602.               if not( not(tgRowLines in Options) and (BorderStyle = ebsNone) ) then
  3603.               begin
  3604.                 InflateRect(ARect, 1, 1);
  3605.                 if BorderStyle <> ebsNone then
  3606.                   DrawGridFrameBorder(Canvas, ARect, BorderStyle, dsUp, FixedColor)
  3607.                 else
  3608.                   DrawFixedBorder(ARect, True);
  3609.               end;
  3610.             end;
  3611.             Exit;
  3612.           end;
  3613.         end;
  3614.       fcMarker:
  3615.         begin
  3616.           ALeft := (ARect.Right + ARect.Left - Indicators.Width - FrameOffs) shr 1 + 1;
  3617.           ATop  := (ARect.Top + ARect.Bottom - Indicators.Height) shr 1 - 1;
  3618.           if (ARow >= 0) and KnotFound and
  3619.             FBookmarks.KnotSelected(DrawKnot.KnotID)
  3620.           then begin
  3621.             Inc(ALeft, 2);
  3622.             Indicators.Draw(Canvas, ALeft-1, ATop, nbmCheck);
  3623.           end;
  3624.           if ARow < 0 then
  3625.           begin
  3626.             DrawFixedCellFrame(fcMarker, nbmCheckHrd);
  3627.             Exit;
  3628.           end;
  3629.         end;
  3630.       fcTreePath :
  3631.         if ARow >= 0 then
  3632.         begin
  3633.           if tgTreePathCompletion in Options then
  3634.           begin
  3635.             if (tgRowLines in Options) then InflateRect(ARect, 0, 1);
  3636.             if (tgColLines in Options) then InflateRect(ARect, 1, 0);
  3637.             if (DrawKnot <> nil) and DrawKnot.HasChildren then
  3638.             begin
  3639.               GetDrawState(Canvas, nil);
  3640.               DrawTreePathCell(GetTreePathRect(ARow, ARect), ARect, AState, KnotFound, DrawKnot);
  3641.             end
  3642.             else begin
  3643.               DrawTreePathCell(ARect, ARect, AState, KnotFound, DrawKnot);
  3644.             end;
  3645.             Exit;
  3646.           end
  3647.           else
  3648.             DrawTreePathCell(ARect, ARect, AState, KnotFound, DrawKnot);
  3649.         end;
  3650.     end;
  3651.   end
  3652.   else with Canvas do
  3653.   begin
  3654.     if FColumns.Count > ACol then
  3655.     begin
  3656.       DrawColumn := Columns[ACol];
  3657.       if (ARow < 0) then
  3658.       begin
  3659.         if not(kcVisible in DrawColumn.Options) then Exit;
  3660.         DrawTitleCell(Canvas, ACol, ARow, ARect, BorderState, True, True);
  3661.       end
  3662.       else begin
  3663.         if not(kcVisible in DrawColumn.Options) or
  3664.            ((ARow=(FInplaceRow-FTitleOffset))   and
  3665.             (ACol=(FInplaceCol-FIndicatorOffset)))
  3666.         then Exit;
  3667.  
  3668.         if not(DoubleBuffered or DefaultDrawing) then
  3669.         begin
  3670.           DrawBitmap.Width  := ARect.Right  - ARect.Left;
  3671.           DrawBitmap.Height := ARect.Bottom - ARect.Top;
  3672.           with DrawBitmap, DrawBitmap.Canvas do
  3673.           begin
  3674.             DrawRect := Rect(0,0, Width, Height);
  3675.             if DoDrawCell(Canvas) then
  3676.               Self.Canvas.Draw(ARect.Left, ARect.Top, DrawBitmap);
  3677.           end;
  3678.         end
  3679.         else begin
  3680.           DrawRect := ARect;
  3681.           DoDrawCell(Canvas);
  3682.         end;
  3683.       end;
  3684.     end
  3685.     else begin
  3686.       if not (gdFixed in AState) then
  3687.         Brush.Color := Color
  3688.       else
  3689.         Brush.Color := FixedColor;
  3690.       Canvas.FillRect(ARect);
  3691.     end;
  3692.   end;
  3693.   if CellBorder and (gdFixed in AState) then DrawBorderEx(ARect, BorderState)
  3694. end;
  3695.  
  3696. procedure TDCCustomTreeGrid.EndLayout;
  3697. begin
  3698.   if FLayoutLock > 0 then
  3699.   begin
  3700.     try
  3701.       try
  3702.         if FLayoutLock = 1 then
  3703.         begin
  3704.           InternalLayout;
  3705.         end;
  3706.       finally
  3707.         if FLayoutLock = 1 then
  3708.           FColumns.EndUpdate;
  3709.       end;
  3710.     finally
  3711.       Dec(FLayoutLock);
  3712.       EndUpdate;
  3713.     end;
  3714.   end;
  3715. end;
  3716.  
  3717. procedure TDCCustomTreeGrid.EndUpdate;
  3718. begin
  3719.   if FUpdateLock > 0 then
  3720.     Dec(FUpdateLock);
  3721. end;
  3722.  
  3723. function TDCCustomTreeGrid.GetFixedCellType(ACol, AOffset: integer): TFixedCell;
  3724.  var
  3725.   i: integer;
  3726. begin
  3727.   Result := fcColumn;
  3728.   ACol := ACol + AOffset;
  3729.   i := 0;
  3730.   if tgIndicator in Options then Inc(i,4);
  3731.   if tgMarker    in Options then Inc(i,2);
  3732.   if tgTreePath  in Options then Inc(i,1);
  3733.  
  3734.   if (ACol = 0) and ( (i=7) or (i=6) or (i=5) or (i=4) ) then
  3735.     Result := fcIndicator
  3736.   else
  3737.   if (ACol = 0) and ((i=2) or (i=3)) or
  3738.      (ACol = 1) and ((i=7) or (i=6)) then
  3739.     Result := fcMarker
  3740.   else
  3741.   if (ACol = 0) and (i=1) or
  3742.      (ACol = 1) and ((i=3) or (i=5)) or
  3743.      (ACol = 2) and (i=7) then
  3744.     Result := fcTreePath
  3745. end;
  3746.  
  3747. function TDCCustomTreeGrid.GetHitTestInfoAt(KnotItem: TKnotItem;
  3748.   X, Y: integer): TTreeGridHitTest;
  3749.  var
  3750.   BP: TPoint;
  3751.   ALevel: integer;
  3752. begin
  3753.   Result := htNowere;
  3754.  
  3755.   with KnotItem do
  3756.   begin
  3757.     if [tgeShowLines, tgeShowButtons] * OptionsEx <> [] then
  3758.       ALevel := Level
  3759.     else
  3760.       ALevel := Level - 1;
  3761.  
  3762.     if HasChildren then
  3763.     begin
  3764.       BP.X := ALevel * Indent;
  3765.       BP.Y := (ALevel+1) * Indent + 1;
  3766.  
  3767.       if (X >= BP.X) and (X <= BP.Y) and (tgeShowButtons in OptionsEx) then
  3768.       begin
  3769.         Result := htOnButton;
  3770.         Exit;
  3771.       end;
  3772.  
  3773.     end
  3774.     else begin
  3775.       BP.X := (ALevel+1) * Indent;
  3776.       BP.Y := BP.X;
  3777.     end;
  3778.  
  3779.     if (X < BP.X) then
  3780.        Exit;
  3781.  
  3782.     if (Images<>nil) and
  3783.        ((KnotItem.KnotID =  SelectedKnot.KnotID) and (SelectImage>-1) or
  3784.        (KnotItem.KnotID <> SelectedKnot.KnotID) and (NormalImage>-1))
  3785.     then begin
  3786.       BP.X := BP.Y + 1;
  3787.       BP.Y := BP.Y + Images.Width + 5;
  3788.  
  3789.       if (X >= BP.X) and (X <= BP.Y) then begin
  3790.         Result := htOnIcon;
  3791.         Exit;
  3792.       end;
  3793.  
  3794.     end;
  3795.  
  3796.     Result := htOnLabel;
  3797.   end;
  3798. end;
  3799.  
  3800. function TDCCustomTreeGrid.GetSelectedIndex: Integer;
  3801. begin
  3802.   Result := RawToDataColumn(Col);
  3803. end;
  3804.  
  3805. function TDCCustomTreeGrid.GetTreePathWidth: integer;
  3806. begin
  3807.   if not(tgTreePath in Options) then
  3808.     Result := 0
  3809.   else begin
  3810.     if GroupingEnabled and (GroupBox.Count > 0) then
  3811.     begin
  3812.       if tgTreePathCompletion in Options then
  3813.         Result := GroupBox.Count * Indent - 1
  3814.       else
  3815.         Result := GroupBox.Count * Indent + 3
  3816.     end
  3817.     else
  3818.       if FTreePathWidth <> 0
  3819.       then
  3820.         Result := FTreePathWidth
  3821.       else
  3822.         Result := TreeIconWidth;
  3823.   end;
  3824. end;
  3825.  
  3826. procedure TDCCustomTreeGrid.HideClipPopup;
  3827. begin
  3828.   if FClipDown then
  3829.   begin
  3830.     TDCClipPopup(FClipPopup).Hide;
  3831.     ClickedCol := -1;
  3832.     SetClipDown(False);
  3833.     TKnotClipPopup(FClipPopup).CellType := fcNone;
  3834.   end;
  3835. end;
  3836.  
  3837. function TDCCustomTreeGrid.HighlightCell(DataCol, DataRow: Integer;
  3838.   AState: TGridDrawState; KnotItem: TKnotItem): Boolean;
  3839. begin
  3840.   Result := False;
  3841.   if (tgMultiSelect in Options) and (FKnots.Count>0) then
  3842.     Result := FBookmarks.KnotSelected(KnotItem.KnotID);
  3843.   if Options * [tgMultiSelect, tgRowSelect] <> [tgMultiSelect, tgRowSelect] then
  3844.   begin
  3845.     if not Result then
  3846.       Result := (gdSelected in AState)
  3847.         and ((tgAlwaysShowSelection in Options) or Focused)
  3848.         and ((UpdateLock = 0) or (tgRowSelect in Options));
  3849.   end;
  3850. end;
  3851.  
  3852. procedure TDCCustomTreeGrid.InternalLayout;
  3853.  var
  3854.   AColCount, I, ATitleOffset: integer;
  3855.  
  3856.   procedure MeasureTitleHeights;
  3857.   var
  3858.     K: Integer;
  3859.     RestoreCanvas: Boolean;
  3860.   begin
  3861.     RestoreCanvas := not HandleAllocated;
  3862.     if RestoreCanvas then Canvas.Handle := GetDC(0);
  3863.     try
  3864.       Canvas.Font := Font;
  3865.       K := Canvas.TextHeight('Wg') + 3;
  3866.       if tgRowLines in Options then
  3867.         Inc(K, GridLineWidth);
  3868.       if not(tgUserRowHeight in Options) then
  3869.         DefaultRowHeight := K;
  3870.       SetTitleHeight;
  3871.     finally
  3872.       if RestoreCanvas then
  3873.       begin
  3874.         ReleaseDC(0, Canvas.Handle);
  3875.         Canvas.Handle := 0;
  3876.       end;
  3877.     end;
  3878.   end;
  3879.  
  3880. begin
  3881.   FIndicatorOffset := 0;
  3882.   if tgIndicator in Options then Inc(FIndicatorOffset);
  3883.   if tgMarker    in Options then Inc(FIndicatorOffset);
  3884.   if tgTreePath  in Options then Inc(FIndicatorOffset);
  3885.   if (csLoading in ComponentState) then Exit;
  3886.  
  3887.   if HandleAllocated then KillMessage(Handle, CM_DEFERLAYOUT);
  3888.  
  3889.   DoubleBuffered := [tgTreePathCompletion, tgDrawFixedLine, tgDoubleBuffered]*Options <>[];
  3890.  
  3891.   if GroupingEnabled then GroupBox.FixedCols := FIndicatorOffset;
  3892.  
  3893.   AColCount := FIndicatorOffset;
  3894.   if FColumns.Count = 0 then Inc(AColCount) else Inc(AColCount, FColumns.Count);
  3895.   ColCount := AColCount;
  3896.  
  3897.   if inherited FixedCols <> FIndicatorOffset then
  3898.   begin
  3899.     inherited FixedCols := FIndicatorOffset;
  3900.     InitGridPos;
  3901.   end;
  3902.  
  3903.   ATitleOffset := FTitleOffset;
  3904.   if tgTitles in Options then
  3905.     FTitleOffset := 1
  3906.   else
  3907.     FTitleOffset := 0;
  3908.  
  3909.   MeasureTitleHeights;
  3910.   SetColumnAttributes;
  3911.   if ATitleOffset <> FTitleOffset then UpdateRowCount;
  3912.  
  3913.   Invalidate;
  3914.  
  3915.   if tgAutoSize in Options then
  3916.   begin
  3917.     if (FSizingIndex > -1) or FTreePathSizing then
  3918.     begin
  3919.       if FTreePathSizing then FSizingIndex := FIndicatorOffset - 1;
  3920.       I := FSizingIndex;
  3921.       FSizingIndex := -1;
  3922.       UpdateColWidths(I, i <> ColCount - 1);
  3923.     end
  3924.     else
  3925.       UpdateColWidths(-1, True);
  3926.  
  3927.     if FColumns.Count  > 0 then
  3928.       for I := FIndicatorOffset to ColCount - 1 do
  3929.         FColumns[I - FIndicatorOffset].Width := ColWidths[I];
  3930.   end;
  3931. end;
  3932.  
  3933. procedure TDCCustomTreeGrid.InvalidateTitles;
  3934. var
  3935.   R, R1: TRect;
  3936.   DrawInfo: TGridDrawInfo;
  3937. begin
  3938.   if HandleAllocated and (tgTitles in Options) then
  3939.   begin
  3940.     CalcDrawInfo(DrawInfo);
  3941.     with DrawInfo.Horz do
  3942.     begin
  3943.       R1 := CellRect(LeftCol + VisibleColCount, 0);
  3944.       if not IsRectEmpty(R1) and (FFirstGridCell > FirstGridCell) then
  3945.       begin
  3946.         R  := Rect(R1.Left, 0, R1.Right, DrawInfo.Vert.FixedBoundary);
  3947.         InvalidateRect(Handle, @R, False);
  3948.       end;
  3949.       FFirstGridCell := FirstGridCell;
  3950.     end;
  3951.   end;
  3952. end;
  3953.  
  3954. procedure TDCCustomTreeGrid.KeyDown(var Key: Word; Shift: TShiftState);
  3955.  var
  3956.   KeyDownEvent: TKeyEvent;
  3957.   DrawInfo: TGridDrawInfo;
  3958.   PageWidth, PageHeight: Integer;
  3959.  
  3960.   procedure CalcPageExtents;
  3961.   begin
  3962.     CalcDrawInfo(DrawInfo);
  3963.     PageWidth := DrawInfo.Horz.LastFullVisibleCell - LeftCol;
  3964.     if PageWidth < 1 then PageWidth := 1;
  3965.     PageHeight := DrawInfo.Vert.LastFullVisibleCell - TopRow;
  3966.     if PageHeight < 1 then PageHeight := 1;
  3967.   end;
  3968.  
  3969.   procedure Tab(GoForward: Boolean);
  3970.   var
  3971.     ACol, Original: Integer;
  3972.   begin
  3973.     ACol     := Col;
  3974.     Original := ACol;
  3975.     BeginUpdate;
  3976.     try
  3977.       while True do
  3978.       begin
  3979.         if GoForward then
  3980.           Inc(ACol) else
  3981.           Dec(ACol);
  3982.         if ACol >= ColCount then
  3983.         begin
  3984.           NextRow(False, True, Shift);
  3985.           ACol := FIndicatorOffset;
  3986.         end
  3987.         else if ACol < FIndicatorOffset then
  3988.         begin
  3989.           PrevRow(False, Shift);
  3990.           ACol := ColCount - FIndicatorOffset;
  3991.         end;
  3992.         if (ACol = Original) or
  3993.            (Assigned(FInplaceEdit) and TDCCustomEdit(FInplaceEdit).ShowError) then Exit;
  3994.         if TabStops[ACol] then
  3995.         begin
  3996.           MoveCol(ACol, 0);
  3997.           Exit;
  3998.         end;
  3999.       end;
  4000.     finally
  4001.       EndUpdate;
  4002.     end;
  4003.   end;
  4004.  
  4005.  const
  4006.   RowMovementKeys = [VK_UP, VK_PRIOR, VK_DOWN, VK_NEXT, VK_HOME, VK_END];
  4007. begin
  4008.   if not DataVisible then Exit;
  4009.   if (DragState <> dsNone) then
  4010.   begin
  4011.     inherited;
  4012.     Exit;
  4013.   end;
  4014.  
  4015.   if FClipDown then
  4016.   begin
  4017.     if Key = VK_ESCAPE then
  4018.       HideClipPopup
  4019.     else
  4020.       TKnotClipPopup(FClipPopup).KeyDown(Key, Shift);
  4021.     Key := 0;
  4022.     Exit;
  4023.   end;
  4024.  
  4025.   KeyDownEvent := OnKeyDown;
  4026.   if Assigned(KeyDownEvent) then KeyDownEvent(Self, Key, Shift);
  4027.   if not CanGridAcceptKey(Key, Shift) or FKnots.Updating then Exit;
  4028.  
  4029.   with FKnots do
  4030.     if ssCtrl in Shift then
  4031.     begin
  4032.       if (Key in RowMovementKeys) then ClearSelection;
  4033.       case Key of
  4034.         VK_DELETE:
  4035.           DeleteRecords(not(tgConfirmDelete in Options) or False);
  4036.         VK_INSERT:
  4037.           begin
  4038.             if tgEditing in Options then
  4039.             begin
  4040.               ClearSelection;
  4041.               InsertKnot(FSelectedKnot, True, Shift);
  4042.             end;
  4043.           end;
  4044.         VK_LEFT: MoveCol(FIndicatorOffset, 1);
  4045.         VK_RIGHT: MoveCol(ColCount - 1, -1);
  4046.         VK_HOME:
  4047.           begin
  4048.             Row := FTitleOffset;
  4049.             MoveCol(FIndicatorOffset, 1);
  4050.             ClearSelection;
  4051.           end;
  4052.         VK_END:
  4053.           begin
  4054.             ClearSelection;
  4055.             Row := RowCount-1;
  4056.             MoveCol(ColCount - 1, -1);
  4057.           end;
  4058.         VK_NEXT, VK_PRIOR:
  4059.           begin
  4060.             ClearSelection;
  4061.             inherited;
  4062.           end;
  4063.         VK_UP, VK_DOWN: inherited;
  4064.         65:{A} SelectItems(smSelect);
  4065.       end
  4066.     end
  4067.     else
  4068.     if not(ssAlt in Shift) then
  4069.     begin
  4070.       case Key of
  4071.         VK_DOWN:
  4072.           begin
  4073.             if (ssShift in Shift) and not (tgMultiSelect in Options) then
  4074.             begin
  4075.               MarkKnot;
  4076.               NextRow(False, False, Shift);
  4077.             end
  4078.             else
  4079.               NextRow(True, True, Shift);
  4080.             Key := 0;
  4081.           end;
  4082.         VK_UP:
  4083.           begin
  4084.             PrevRow(True, Shift);
  4085.             if ssShift in Shift then MarkKnot;
  4086.             Key := 0;
  4087.           end;
  4088.         VK_LEFT:
  4089.           begin
  4090.             if tgRowSelect in Options then
  4091.               PrevRow(False, Shift)
  4092.             else
  4093.               MoveCol(Col - 1, -1);
  4094.           end;
  4095.         VK_RIGHT:
  4096.           begin
  4097.             if tgRowSelect in Options then
  4098.               NextRow(False, False, Shift)
  4099.             else
  4100.               MoveCol(Col + 1, 1);
  4101.           end;
  4102.         VK_INSERT:
  4103.           begin
  4104.             if (tgeInsertSelect in OptionsEx) then
  4105.             begin
  4106.               ClearSelection;
  4107.               MarkKnot;
  4108.               NextRow(True, True, Shift);
  4109.             end
  4110.             else
  4111.               if tgEditing in Options then
  4112.               begin
  4113.                 ClearSelection;
  4114.                 InsertKnot(FSelectedKnot, False, Shift)
  4115.               end;
  4116.           end;
  4117.         VK_TAB:
  4118.           begin
  4119.             if not (ssAlt in Shift) then Tab(not (ssShift in Shift));
  4120.             Key := 0;
  4121.           end;
  4122.         VK_ESCAPE:
  4123.           begin
  4124.             inherited;
  4125.             if Key = VK_ESCAPE then
  4126.             begin
  4127.               FIsESCKey := True;
  4128.               ClearSelection;
  4129.               if not (tgAlwaysShowEditor in Options) and FEditorMode then
  4130.               begin
  4131.                 FIsModified := False;
  4132.                 HideEditor;
  4133.               end
  4134.               else
  4135.                 if (State = ksInsert) then
  4136.                 begin
  4137.                   FRowUpdated := False;
  4138.                   PrevRow(True, Shift);
  4139.                 end;
  4140.             end;
  4141.           end;
  4142.         VK_HOME:
  4143.           if (ColCount = FIndicatorOffset+1) or (tgRowSelect in Options) then
  4144.           begin
  4145.             Row := FTitleOffset;
  4146.             MoveCol(FIndicatorOffset, 1);
  4147.           end
  4148.           else
  4149.             MoveCol(FIndicatorOffset, 1);
  4150.         VK_END:
  4151.           if (ColCount = FIndicatorOffset+1) or (tgRowSelect in Options) then
  4152.           begin
  4153.             Row := RowCount-1;
  4154.             MoveCol(ColCount - 1, -1);
  4155.           end
  4156.           else
  4157.             MoveCol(ColCount - 1, -1);
  4158.         VK_NEXT:
  4159.           begin
  4160.             CalcPageExtents;
  4161.             NextRow(False, False, Shift, PageHeight);
  4162.           end;
  4163.         VK_PRIOR:
  4164.           begin
  4165.             CalcPageExtents;
  4166.             PrevRow(False, Shift, PageHeight);
  4167.           end;
  4168.         VK_F2: ShowEditor;
  4169.         VK_DELETE:
  4170.           DeleteRecords(True);
  4171.       end;
  4172.     end;
  4173. end;
  4174.  
  4175. procedure TDCCustomTreeGrid.KeyPress(var Key: Char);
  4176.  var
  4177.    KeyPressEvent: TKeyPressEvent;
  4178. begin
  4179.   if not DataVisible then Exit;
  4180.   KeyPressEvent := OnKeyPress;
  4181.   FIsESCKey := False;
  4182.   if (FKnots.Count > 0) and not(FEditorMode or FKnots.Updating) and (DragState = dsNone) then
  4183.     with FSelectedKnot do
  4184.     begin
  4185.       if HasChildren then
  4186.       begin
  4187.         case Key of
  4188.           '-':
  4189.             begin
  4190.               Collapse(False);
  4191.               Key := #0;
  4192.             end;
  4193.           '+':
  4194.             begin
  4195.               Expand(False);
  4196.               Key := #0;
  4197.             end;
  4198.           '*':
  4199.             begin
  4200.               Expand(True);
  4201.               Key := #0;
  4202.             end;
  4203.         end;
  4204.       end;
  4205.     end;
  4206.   if not (tgAlwaysShowEditor in Options) and (Key = Chr(VK_RETURN)) then
  4207.   begin
  4208.     if FEditorMode then
  4209.     begin
  4210.       if not FInplaceEdit.DropDownVisible then
  4211.       begin
  4212.         HideEditor;
  4213.         Key := #0;
  4214.       end
  4215.     end
  4216.     else begin
  4217.       ShowEditor;
  4218.       Key := #0;
  4219.     end;
  4220.   end;
  4221.   if Key = Chr(VK_TAB) then Key := #0;
  4222.  
  4223.   if Assigned(KeyPressEvent) then KeyPressEvent(Self, Key);
  4224. end;
  4225.  
  4226. procedure TDCCustomTreeGrid.LayoutChanged;
  4227. begin
  4228.   if AcquireLayoutLock then
  4229.     EndLayout;
  4230. end;
  4231.  
  4232. procedure TDCCustomTreeGrid.Loaded;
  4233. begin
  4234.   inherited Loaded;
  4235.   if FColumns.Count > 0 then
  4236.     ColCount := FColumns.Count;
  4237.   GroupBoxChanged;
  4238.   LayoutChanged;
  4239. end;
  4240.  
  4241. procedure TDCCustomTreeGrid.MouseDown(Button: TMouseButton;
  4242.   Shift: TShiftState; X, Y: Integer);
  4243.  var
  4244.   Cell, ACell: TGridCoord;
  4245.   GridOptions: TGridOptions;
  4246.   R: TRect;
  4247.   ARow: integer;
  4248.   CellType: TFixedCell;
  4249.   Selected: boolean;
  4250. begin
  4251.   FMouseDownRow := -1;
  4252.   FreeEditTimer;
  4253.   if not AcquireFocus or FKnots.Updating or not DataVisible then Exit;
  4254.  
  4255.   if Y > 0 then
  4256.   begin
  4257.     Cell := MouseCoord(X, Y);
  4258.     R := CellRect(Cell.X, Cell.Y);
  4259.     CellType := GetFixedCellType(Cell.X, 0);
  4260.     if IsRectEmpty(R) then Exit;
  4261.  
  4262.     if (ssDouble in Shift) and (Button = mbLeft) then
  4263.     begin
  4264.       if (Cell.Y  >=  FTitleOffset) and
  4265.          ((Cell.X >= FIndicatorOffset) or (CellType = fcTreePath))
  4266.       then begin
  4267.         DblClick;
  4268.         if Cell.Y >= FTitleOffset then CellDblClick(Columns[SelectedIndex]);
  4269.         Exit;
  4270.       end;
  4271.       Shift := Shift - [ssDouble];
  4272.     end;
  4273.  
  4274.     FMousePoint := Point(X,Y);
  4275.  
  4276.     if (Button = mbLeft) and (Cell.Y = 0) then
  4277.     begin
  4278.       if (CellType = fcIndicator) and (tgeMarkerMenu in OptionsEx) or (CellType = fcMarker) then
  4279.         ClipClick(CellType)
  4280.       else
  4281.         HideClipPopup;
  4282.     end
  4283.     else
  4284.       HideClipPopup;
  4285.  
  4286.     if (tgTitleClicked in Options) and (tgTitles in Options) and
  4287.        (Button = mbLeft) and not Sizing(X, Y) and (Cell.Y=0) and (CellType = fcColumn)
  4288.     then begin
  4289.       ClickedCol := Cell.X;
  4290.       if not(tgColMoving in Options) then InvalidateCell(Cell.X, 0);
  4291.     end;
  4292.  
  4293.     if CellType = fcTreePath then
  4294.     begin
  4295.       FMouseDownRow := Row;
  4296.     end;
  4297.  
  4298.     if Sizing(X, Y) then
  4299.     begin
  4300.       HideEditor;
  4301.       if not FEditorMode then
  4302.         inherited MouseDown(Button, Shift, X, Y);
  4303.       Exit;
  4304.     end
  4305.     else
  4306.       FSizingIndex := -1;
  4307.  
  4308.     if (DragKind = dkDock) and (Cell.X < FIndicatorOffset) and
  4309.       (Cell.Y < FTitleOffset) and (not (csDesigning in ComponentState)) then
  4310.     begin
  4311.       BeginDrag(false);
  4312.       Exit;
  4313.     end;
  4314.  
  4315.     if ((csDesigning in ComponentState) or (tgColumnResize in Options)) and
  4316.       (Cell.Y < FTitleOffset) then
  4317.     begin
  4318.       if (tgTitleClicked in Options) and (Button = mbLeft) and (CellType = fcColumn) then
  4319.       begin
  4320.         HideEditor;
  4321.         if tgColMoving in Options then
  4322.         begin
  4323.           GridOptions := inherited Options;
  4324.           inherited Options := inherited Options - [goColMoving];
  4325.           inherited MouseDown(Button, Shift, X, Y);
  4326.           inherited Options := GridOptions;
  4327.         end
  4328.         else
  4329.          inherited MouseDown(Button, Shift, X, Y);
  4330.       end
  4331.       else inherited MouseDown(Button, Shift, X, Y);
  4332.       Exit;
  4333.     end;
  4334.  
  4335.     with Cell do
  4336.     begin
  4337.       BeginUpdate;
  4338.       try
  4339.         ARow := 0; ACell.X := 0; ACell.Y := 0;
  4340.         if (Y >= FTitleOffset) and (Y - Row <> 0) then
  4341.         begin
  4342.           ARow := Row;
  4343.           with FKnots do
  4344.             if (State = ksInsert) and not Modified then Delete(FSelectedKnot);
  4345.           ACell.Y := Y;
  4346.         end;
  4347.         if (X >= FixedCols) then ACell.X := X;
  4348.  
  4349.         if (ACell.X <> 0) and (ACell.Y <> 0) then
  4350.           MoveColRow(ACell.X, ACell.Y, True, True)
  4351.         else begin
  4352.           if (ACell.Y <> 0) or not (tgTitles in Options) then Row := Y;
  4353.           if ACell.X <> 0 then MoveCol(X, 0);
  4354.         end;
  4355.  
  4356.         if (ACell.Y <> 0) and (ARow <> Y) and (Row <> Y) and (ARow=Row) then Exit;
  4357.  
  4358.         if FKnots.Count > 0 then with FSelectedKnot do
  4359.         begin
  4360.           if FEditorMode then HideEditor;
  4361.           if not FEditorMode then
  4362.           begin
  4363.             if tgMultiSelect in Options then
  4364.               with FBookmarks do
  4365.               begin
  4366.                 FSelecting := False;
  4367.                 Selected := KnotSelected(KnotID);
  4368.                 if Selected then
  4369.                 begin
  4370.                   {Check Drag&Drop !!}
  4371.                   if ssCtrl in Shift then
  4372.                     Select(FSelectedKnot, not Selected)
  4373.                   else
  4374.                   begin
  4375.                     Clear;
  4376.                     Select(FSelectedKnot, True);
  4377.                   end;
  4378.                 end
  4379.                 else begin
  4380.                   if ssCtrl in Shift then
  4381.                     Select(FSelectedKnot, not Selected)
  4382.                   else
  4383.                   begin
  4384.                     Clear;
  4385.                     Select(FSelectedKnot, True);
  4386.                   end;
  4387.                 end;
  4388.               end;
  4389.             case CellType of
  4390.               fcMarker:
  4391.                 with FBookmarks do
  4392.                 begin
  4393.                   Select(FSelectedKnot, not KnotSelected(KnotID));
  4394.                   InvalidateCell(Cell.X, Cell.Y);
  4395.                 end;
  4396.               fcTreePath:
  4397.                 if HasChildren and
  4398.                    (GetHitTestInfoAt(FSelectedKnot,
  4399.                       FMousePoint.X-R.Left, FMousePoint.Y-R.Top) = htOnButton) then
  4400.                 begin
  4401.                    if Expanded then
  4402.                      Collapse(False)
  4403.                    else
  4404.                      Expand(False);
  4405.                 end
  4406.             end;
  4407.           end;
  4408.         end;
  4409.       finally
  4410.         EndUpdate;
  4411.       end;
  4412.     end;
  4413.   end
  4414.   else inherited;
  4415. end;
  4416.  
  4417. procedure TDCCustomTreeGrid.MouseMove(Shift: TShiftState; X, Y: Integer);
  4418. var
  4419.   Cell: TGridCoord;
  4420.   OldCurrentCol, LabelOffset: integer;
  4421.   R: TRect;
  4422.   KnotItem: TKnotItem;
  4423.   P: TPoint;
  4424.   Text: string;
  4425.   CellX, CellY: integer;
  4426. begin
  4427.   if FKnots.Updating or not DataVisible then Exit;
  4428.   Cell := MouseCoord(X,Y);
  4429.   OldCurrentCol := FCurrentCol;
  4430.   if Cell.Y = 0
  4431.     then FCurrentCol := Cell.X
  4432.     else FCurrentCol := -1;
  4433.  
  4434.   if (DragState = dsNone) and
  4435.      (Cell.X >= FixedCols) and (ClickedCol=FCurrentCol) and (ClickedCol <> -1) and
  4436.      (FGridState <> gsColMoving) and (tgColMoving in Options) and
  4437.      ((Abs(FMousePoint.X - X) > 5) or (Abs(FMousePoint.Y - Y) > 5) ) then
  4438.   begin
  4439.      FGridState := gsColMoving;
  4440.      inherited MouseDown(mbLeft, Shift, FMousePoint.X, FMousePoint.Y);
  4441.      if (FGridState = gsColMoving) or (DragState = dsColMoving) then Exit;
  4442.   end;
  4443.  
  4444.   inherited MouseMove(Shift, X, Y);
  4445.  
  4446.   if (ClickedCol <> -1) and (FCurrentCol <> OldCurrentCol) and
  4447.      (FGridState <> gsColMoving) and (DragState = dsNone)and
  4448.      (GetFixedCellType(ClickedCol, 0) = fcColumn)
  4449.   then begin
  4450.     InvalidateCell(ClickedCol, 0);
  4451.   end;
  4452.  
  4453.   if not FKnots.Updating then
  4454.   begin
  4455.     if (GetFixedCellType(Cell.X, 0) = fcTreePath) and (Cell.Y >= FTitleOffset)
  4456.     then begin
  4457.       R := CellRect(Cell.X, Cell.Y);
  4458.       KnotItem := FKnots.SelectKnot(FFirstVisible, Cell.Y-FTitleOffset-FFirstIndex);
  4459.       if Assigned(KnotItem) and (KnotItem.Level > -1) then
  4460.         case GetHitTestInfoAt(KnotItem, X-R.Left, Y-R.Top) of
  4461.           htOnIcon ,
  4462.           htOnLabel :
  4463.             if not(tgTreePathCompletion in Options) then
  4464.             begin
  4465.               LabelOffset := GetHintTreeOffset(KnotItem, htOnLabel);
  4466.               GetTreePathCaption(KnotItem, Text);
  4467.               P := DrawHighLightText(Canvas, PChar(Text), Rect(0, 0, 0, 0), 0);
  4468.               Canvas.Font := Self.Font;
  4469.               if ((R.Left + LabelOffset + P.X + 2) > R.Right) and (X < R.Right)
  4470.               then begin
  4471.                 if (FHintRow <> -1) and (FHintRow = Cell.Y) then Exit;
  4472.                 CellX := Cell.X;
  4473.                 CellY := Cell.Y;
  4474.                 if (tgeTreeSelect in OptionsEx) and
  4475.                    (tgRowLines in Options) then R.Left := R.Left - 1;
  4476.                 ShowHintWindow(CellX, CellY, R.Left - 1, R.Top + 1, LabelOffset, Text);
  4477.               end
  4478.               else
  4479.                 HideHintWindow;
  4480.             end;
  4481.           else
  4482.             HideHintWindow;
  4483.         end;
  4484.     end
  4485.     else begin
  4486.       HideHintWindow;
  4487.       if (Cell.Y < FTitleOffset) and (RawToDataColumn(Cell.X)>=0) and (Columns.Count > 0) then
  4488.       begin
  4489.         if RawToDataColumn(Cell.X) <> FColumnCell then
  4490.         begin
  4491.           FColumnCell := RawToDataColumn(Cell.X);
  4492.           DoColumnComment(MODE_SHOWWINDOW, Columns[FColumnCell]);
  4493.         end;
  4494.       end
  4495.       else begin
  4496.         DoColumnComment(MODE_HIDEWINDOW, nil);
  4497.         {Γ±≥αΓΦ≥ⁿ ∩≡εΓσ≡Ω≤ φα ∩εΣ±Γσ≥Ω≤ hinta σ±δΦ ≥σΩ±≥ φσ ∩ε∞σ∙ασ≥±  Γ  ≈σΘΩσ}
  4498.       end;
  4499.     end;
  4500.   end;
  4501.  
  4502. end;
  4503.  
  4504. procedure TDCCustomTreeGrid.MouseUp(Button: TMouseButton;
  4505.   Shift: TShiftState; X, Y: Integer);
  4506. var
  4507.   Cell: TGridCoord;
  4508.   SaveState: TGridState;
  4509.   SaveDragState: TDragGridState;
  4510.   MouseClick: boolean;
  4511.   OldClickedCol: integer;
  4512.   R: TRect;
  4513. begin
  4514.   SaveState := FGridState;
  4515.   SaveDragState := DragState;
  4516.  
  4517.   MouseClick := (ClickedCol <> -1) and (ClickedCol=FCurrentCol);
  4518.  
  4519.   inherited MouseUp(Button, Shift, X, Y);
  4520.   Cell := MouseCoord(X,Y);
  4521.  
  4522.   if FTreePathSizing and (SaveState = gsColSizing) then
  4523.   begin
  4524.     R := CellRect(FIndicatorOffset-1, Cell.Y);
  4525.     if (X-R.Left + FSizingOff) < TreeIconWidth then
  4526.       TreePathWidth := TreeIconWidth
  4527.     else
  4528.       TreePathWidth := X-R.Left+FSizingOff;
  4529.   end;
  4530.  
  4531.   if (Button = mbLeft) and (ClickedCol <> -1) then
  4532.   begin
  4533.     OldClickedCol := ClickedCol;
  4534.     ClickedCol := -1;
  4535.     InvalidateCell(OldClickedCol, 0);
  4536.   end;
  4537.  
  4538.   if (SaveState = gsRowSizing) or (SaveState = gsColSizing) or
  4539.     ((InplaceEditor <> nil) and (InplaceEditor.Visible) and
  4540.      (PtInRect(InplaceEditor.BoundsRect, Point(X,Y))))
  4541.   then
  4542.     Exit;
  4543.  
  4544.   if (Button = mbLeft) and (Cell.X >= FIndicatorOffset) and(Cell.Y >= 0) and
  4545.      (SaveState <> gsColMoving) and (RawToDataColumn(Cell.X) < Columns.Count) and
  4546.      (SaveDragState <> dsColMoving) and (SaveDragState <>dsHeaderMoving)
  4547.   then begin
  4548.     if (Cell.Y <  FTitleOffset) and MouseClick then
  4549.       DoColumnClick(Shift, Cell.X)
  4550.     else
  4551.       CellClick(Columns[SelectedIndex]);
  4552.   end;
  4553.  
  4554.   if (GetFixedCellType(Cell.X, 0) = fcTreePath) and (FKnots.Count > 0) and
  4555.      (FMouseDownRow <> -1) and (FMouseDownRow = Cell.Y)
  4556.   then begin
  4557.     R := CellRect(Cell.X, Cell.Y);
  4558.     if GetHitTestInfoAt(FSelectedKnot, X-R.Left, Y-R.Top) = htOnLabel then
  4559.     begin
  4560.       if FEditTimerID = -1 then
  4561.         FEditTimerID := SetTimer(Handle, 101, GetDoubleClickTime, nil);
  4562.     end;
  4563.     FMouseDownRow := 1;
  4564.   end;
  4565. end;
  4566.  
  4567. procedure TDCCustomTreeGrid.MoveCol(RawCol, Direction: Integer);
  4568. var
  4569.   OldCol: Integer;
  4570. begin
  4571.   if RawCol >= ColCount then
  4572.     RawCol := ColCount - 1;
  4573.   if RawCol < FixedCols then RawCol := FixedCols;
  4574.   if Direction <> 0 then
  4575.   begin
  4576.     while (RawCol < ColCount) and (RawCol >= FIndicatorOffset) and
  4577.       (ColWidths[RawCol] <= 0) do
  4578.       Inc(RawCol, Direction);
  4579.     if (RawCol >= ColCount) or (RawCol < FIndicatorOffset) then Exit;
  4580.   end;
  4581.   OldCol := Col;
  4582.   if RawCol <> OldCol then
  4583.   begin
  4584.     FLockWindow := True;
  4585.     try
  4586.       Col := RawCol;
  4587.     finally
  4588.       FLockWindow := False;
  4589.       FLockScroll := False;
  4590.     end;
  4591.   end;
  4592. end;
  4593.  
  4594. function TDCCustomTreeGrid.RawToDataColumn(ACol: Integer): Integer;
  4595. begin
  4596.   Result := ACol - FIndicatorOffset;
  4597. end;
  4598.  
  4599. procedure TDCCustomTreeGrid.RowHeightsChanged;
  4600. var
  4601.   i,ThisHasChanged,Def : Integer;
  4602. begin
  4603.   ThisHasChanged:=-1;
  4604.   Def:=DefaultRowHeight;
  4605.   for i:=Ord(tgTitles in Options) to RowCount do
  4606.     if RowHeights[i] <> Def then begin
  4607.       ThisHasChanged:=i;
  4608.       Break;
  4609.     end;
  4610.   if ThisHasChanged<>-1 then begin
  4611.     DefaultRowHeight:=RowHeights[i];
  4612.     if FLayoutLock = 0 then InternalLayout;
  4613.   end;
  4614.   inherited;
  4615.   SetTitleHeight;
  4616. end;
  4617.  
  4618. function TDCCustomTreeGrid.SelectCell(ACol, ARow: Integer): Boolean;
  4619.  var
  4620.   OldRect, NewRect: TRect;
  4621.   DrawInfo: TGridDrawInfo;
  4622. begin
  4623.   Result := inherited SelectCell(ACol, ARow);
  4624.   DoSelectCell(Self, ACol, ARow, Result);
  4625.   if FEditorMode and Result  then
  4626.   begin
  4627.     SendMessage(FInplaceEdit.Handle, CM_EXIT, 0, 0);
  4628.     if FInplaceEdit.ShowError then Result := False;
  4629.   end;
  4630.  
  4631.   if Result and ((ARow<>Row)or(ACol<>Col)) then
  4632.     if not (tgAlwaysShowEditor in Options) and FEditorMode then HideEditor;
  4633.  
  4634.   if Result and (ARow <> Row) then
  4635.   begin
  4636.     CalcDrawInfo(DrawInfo);
  4637.     FRowUpdated := False;
  4638.     SetSelectedKnot(FKnots.SelectKnot(FSelectedKnot, ARow - Row));
  4639.     OldRect := BoxRectEx(0 , Row , ColCount-1, Row );
  4640.     if ARow <= DrawInfo.Vert.LastFullVisibleCell then
  4641.       NewRect := BoxRectEx(0 , ARow, ColCount-1, ARow)
  4642.     else begin
  4643.       with DrawInfo.Vert do
  4644.         NewRect := BoxRectEx(0 , LastFullVisibleCell+1, ColCount-1, LastFullVisibleCell+1);
  4645.     end;
  4646.     ValidateRect(Handle, @OldRect);
  4647.     InvalidateRect(Handle, @OldRect, False);
  4648.     InvalidateRect(Handle, @NewRect, False);
  4649.     FKnots.SetState(ksBrowse);
  4650.   end;
  4651. end;
  4652.  
  4653. procedure TDCCustomTreeGrid.SetClipDown(const Value: boolean);
  4654. begin
  4655.   if FClipDown <> Value then
  4656.   begin
  4657.     FClipDown := Value;
  4658.     if (tgIndicator in Options) then
  4659.       InvalidateCell(GetCellByType(TKnotClipPopup(FClipPopup).CellType), 0);
  4660.   end;
  4661. end;
  4662.  
  4663. procedure TDCCustomTreeGrid.SetColumnAttributes;
  4664. var
  4665.   I, J: Integer;
  4666.  
  4667. begin
  4668.   for I := 0 to FColumns.Count-1 do
  4669.   with FColumns[I] do
  4670.   begin
  4671.     TabStops[I + FIndicatorOffset]  := ([kcVisible,kcReadOnly]*Options=[kcVisible]);
  4672.     ColWidths[I + FIndicatorOffset] := Width;
  4673.   end;
  4674.  
  4675.   J := 0;
  4676.   if (tgIndicator in Options) then
  4677.   begin
  4678.     ColWidths[J] := IndicatorWidth;
  4679.     Inc(J);
  4680.   end;
  4681.   if (tgMarker in Options) then
  4682.   begin
  4683.     ColWidths[J] := MarkerWidth;
  4684.     Inc(J);
  4685.   end;
  4686.   if (tgTreePath  in Options) then
  4687.     ColWidths[J] := TreePathWidth;
  4688.  
  4689.   if FColumns.Count = 0 then ColWidths[FIndicatorOffset] := DefaultColWidth;
  4690. end;
  4691.  
  4692. procedure TDCCustomTreeGrid.SetColumns(const Value: TKnotColumns);
  4693. begin
  4694.   Columns.Assign(Value);
  4695. end;
  4696.  
  4697. procedure TDCCustomTreeGrid.SetKnots(const Value: TKnotItems);
  4698. begin
  4699.   FKnots.Assign(Value);
  4700.   DataChanged;
  4701. end;
  4702.  
  4703. procedure TDCCustomTreeGrid.SetOptions(Value: TTreeGridOptions);
  4704. const
  4705.   LayoutOptions = [tgEditing, tgAlwaysShowEditor, tgTitles, tgIndicator,
  4706.     tgColLines, tgRowLines, tgRowSelect, tgAlwaysShowSelection, tgMarker,
  4707.     tgTitleClicked, tgHighlightRow, tgTreePath, tgCompleteLines,
  4708.     tgTreePathCompletion, tgDrawFixedLine, tgFixedLines, tgDoubleBuffered];
  4709. var
  4710.   NewGridOptions: TGridOptions;
  4711.   ChangedOptions: TTreeGridOptions;
  4712. begin
  4713.   if FOptions <> Value then
  4714.   begin
  4715.     NewGridOptions := [];
  4716.     if tgColLines in Value then
  4717.       NewGridOptions := NewGridOptions + [goFixedVertLine, goVertLine];
  4718.     if tgRowLines in Value then
  4719.       NewGridOptions := NewGridOptions + [goFixedHorzLine, goHorzLine];
  4720.     if tgColumnResize in Value then
  4721.       NewGridOptions := NewGridOptions + [goColSizing];
  4722.     if tgColMoving in Value then
  4723.       NewGridOptions := NewGridOptions + [goColMoving];
  4724.     if tgRowMoving in Value then
  4725.       NewGridOptions := NewGridOptions + [goRowMoving];
  4726.     if tgTabs in Value then Include(NewGridOptions, goTabs);
  4727.     if tgRowSelect in Value then
  4728.     begin
  4729.       Include(NewGridOptions, goRowSelect);
  4730.       Exclude(Value, tgAlwaysShowEditor);
  4731.       Exclude(Value, tgEditing);
  4732.     end;
  4733.  
  4734.     if tgHighlightRow in Value then
  4735.     begin
  4736.       Exclude(Value, tgRowSelect);
  4737.     end;
  4738.  
  4739.     if tgMultiSelect in (FOptions - Value) then ;
  4740.  
  4741.     if tgMultiSelect in Value then Value := Value - [tgMarker];
  4742.  
  4743.     if tgRowSizing in Value  then
  4744.     begin
  4745.        NewGridOptions := NewGridOptions + [goRowSizing];
  4746.        Value := Value +[tgUserRowHeight];
  4747.     end;
  4748.  
  4749.     if tgFlatButtons in Value then
  4750.       NewGridOptions := NewGridOptions - [goFixedHorzLine, goFixedVertLine];
  4751.  
  4752.     inherited Options := NewGridOptions;
  4753.  
  4754.     ChangedOptions := (FOptions + Value) - (FOptions * Value);
  4755.     FOptions := Value;
  4756.  
  4757.     GridOptions := [];
  4758.     if tgAutoSize in Value then GridOptions := GridOptions + [goAutoSize];
  4759.  
  4760.     if ChangedOptions * LayoutOptions <> [] then LayoutChanged;
  4761.     if [tgFlatButtons, tgAutoSize] * ChangedOptions  <> [] then
  4762.     begin
  4763.       LockUpdate;
  4764.       if tgAutoSize in ChangedOptions then ScrollBars := ScrollBars;
  4765.       RecreateWnd;
  4766.       UnlockUpdate;
  4767.       if tgAutoSize in ChangedOptions then LayoutChanged;
  4768.     end;
  4769.   end;
  4770. end;
  4771.  
  4772. procedure TDCCustomTreeGrid.SetSelectedIndex(Value: Integer);
  4773. begin
  4774.   MoveCol(DataToRawColumn(Value), 0);
  4775. end;
  4776.  
  4777. procedure TDCCustomTreeGrid.SetTitleFont(const Value: TFont);
  4778. begin
  4779.   FTitleFont.Assign(Value);
  4780.   if tgTitles in Options then LayoutChanged;
  4781. end;
  4782.  
  4783. procedure TDCCustomTreeGrid.SetTitleHeight;
  4784. var
  4785.   I: Integer;
  4786.   Heights: array of Integer;
  4787.   P: TPoint;
  4788. begin
  4789.   Canvas.Font := Font;
  4790.   if tgTitles in Options then
  4791.   begin
  4792.     SetLength(Heights, FTitleOffset);
  4793.     for I := 0 to FColumns.Count-1 do
  4794.     begin
  4795.       Canvas.Font := FColumns[I].Title.Font;
  4796.       P := DrawHighLightText(Canvas, PChar(FColumns[I].Title.Caption), Rect(0,0,0,0), 0);
  4797.       if P.Y > 0 then Inc(P.Y, 4);
  4798.       if (Images <> nil) and (FColumns[I].ItemIndex <> -1) then
  4799.          if P.Y < (Images.Height + 3) then P.Y := Images.Height+3;
  4800.       Heights[0] := _intMax(P.Y, Heights[0]);
  4801.     end;
  4802.     if Heights[0] = 0 then
  4803.     begin
  4804.       Canvas.Font := FTitleFont;
  4805.       Heights[0] := Canvas.TextHeight('Wg') + 4;
  4806.     end;
  4807.     RowHeights[0] := Heights[0];
  4808.   end;
  4809. end;
  4810.  
  4811. procedure TDCCustomTreeGrid.SetTreePathWidth(const Value: integer);
  4812.  var
  4813.   J: integer;
  4814. begin
  4815.   if Value > 0 then
  4816.   begin
  4817.     FTreePathWidth := Value;
  4818.     J := 0;
  4819.     if (tgIndicator in Options) then Inc(J);
  4820.     if (tgMarker    in Options) then Inc(J);
  4821.     if (tgTreePath  in Options) and (J < ColCount) then
  4822.     begin
  4823.       FSizingIndex := J;
  4824.       ColWidths[J] := TreePathWidth;
  4825.     end;
  4826.     if csDesigning in ComponentState then UpdateDesigner;
  4827.   end;
  4828. end;
  4829.  
  4830. procedure TDCCustomTreeGrid.ShowClipPopup(ACellType: TFixedCell; AClipPopup: TObject);
  4831.  var
  4832.   lShow: boolean;
  4833.   R: TRect;
  4834.  
  4835. begin
  4836.   if not HideEditor then Exit;
  4837.   lShow := True;
  4838.   R := CellRect(GetCellByType(ACellType), 0);
  4839.   with TDCClipPopup(AClipPopup), TKnotClipPopup(AClipPopup) do
  4840.   begin
  4841.     Hide;
  4842.     CellType := ACellType;
  4843.     AddButtons;
  4844.     SetBoundsEx(R.Left, R.Bottom,  Width, Height);
  4845.  
  4846.     if Assigned(FOnClipClick) then  FOnClipClick(AClipPopup, Left, Top, lShow);
  4847.  
  4848.     if lShow then
  4849.     begin
  4850.       ClipDown := not ClipDown;
  4851.       OnButtonClick := ClipButtonClick;
  4852.       Show;
  4853.     end
  4854.     else
  4855.       HideClipPopup;
  4856.   end;
  4857. end;
  4858.  
  4859. procedure TDCCustomTreeGrid.TitleClick(Column: TKnotColumn);
  4860. begin
  4861.   if Assigned(FOnTitleClick) then FOnTitleClick(Column);
  4862. end;
  4863.  
  4864. procedure TDCCustomTreeGrid.TitleFontChanged(Sender: TObject);
  4865. begin
  4866.   if (not FSelfChangingTitleFont) and not (csLoading in ComponentState) then
  4867.     ParentFont := False;
  4868.   if tgTitles in Options then LayoutChanged;
  4869. end;
  4870.  
  4871. procedure TDCCustomTreeGrid.TopLeftChanged;
  4872. begin
  4873.   if tgTreePathCompletion in Options then InvalidateRect(Handle, nil, False);
  4874.   if not FKnots.Updating then
  4875.   begin
  4876.     FFirstVisible := FKnots.SelectKnot(FFirstVisible, TopRow - FFirstIndex - FTitleOffset);
  4877.     FFirstIndex   := TopRow - FTitleOffset;
  4878.     if FEditorMode and (FInplaceEdit <> nil) then
  4879.       InplaceUpdateLoc(FInplaceEdit, CellRect(FInplaceCol, FInplaceRow), Canvas);
  4880.   end;
  4881.   HideHintWindow;
  4882.   inherited;
  4883.   if Assigned(FOnTopLeftChanged) then FOnTopLeftChanged(Self);
  4884. end;
  4885.  
  4886. procedure TDCCustomTreeGrid.UpdateActive;
  4887. begin
  4888.   if FKnots.Count > 0 then
  4889.   begin
  4890.     FFirstVisible := FKnots.SelectKnot(FKnots.GetFirstVisibleNode, FFirstIndex);
  4891.     if FFirstIndex <> TopRow - FTitleOffset then
  4892.     begin
  4893.       FFirstVisible := FKnots.SelectKnot(FFirstVisible, TopRow - FFirstIndex - FTitleOffset);
  4894.       FFirstIndex   := TopRow - FTitleOffset;
  4895.     end;
  4896.     SetSelectedKnot(FKnots.SelectKnot(FFirstVisible, Row - TopRow));
  4897.   end
  4898.   else
  4899.     InitGridPos;
  4900. end;
  4901.  
  4902. procedure TDCCustomTreeGrid.UpdateRowCount;
  4903. var
  4904.   NewFixedRows: integer;
  4905. begin
  4906.   NewFixedRows := FTitleOffset;
  4907.  
  4908.   if RowCount <= NewFixedRows then RowCount := NewFixedRows + 1;
  4909.  
  4910.   if FixedRows <> NewFixedRows then
  4911.   begin
  4912.     FixedRows := NewFixedRows;
  4913.     InitGridPos;
  4914.  end;
  4915.   FKnotCount := FKnots.VisibleKnotCount;
  4916.   if FKnotCount = 0 then
  4917.     RowCount := 1 + NewFixedRows
  4918.   else
  4919.     RowCount := FKnotCount + NewFixedRows;
  4920.   UpdateActive;
  4921.   Invalidate;
  4922. end;
  4923.  
  4924. procedure TDCCustomTreeGrid.WMKillFocus(var Message: TMessage);
  4925. begin
  4926.   inherited;
  4927.   HideClipPopup;
  4928.   InvalidateSelected;
  4929. end;
  4930.  
  4931. procedure TDCCustomTreeGrid.WMSetFocus(var Message: TWMSetFocus);
  4932. begin
  4933.   inherited;
  4934.   HideClipPopup;
  4935.   MoveCol(Col, 1);
  4936.   InvalidateSelected;
  4937. end;
  4938.  
  4939. procedure TDCCustomTreeGrid.WMSize(var Message: TWMSize);
  4940. begin
  4941.   UpdateColWidths(-1, True);
  4942.   inherited;
  4943.   InvalidateTitles;
  4944.   if FLockScreen or not DataVisible or (Footers.Height > 0) then Invalidate;
  4945. end;
  4946.  
  4947. function TDCCustomTreeGrid.HideEditor: boolean;
  4948.  var
  4949.   UpdateRect: TRect;
  4950. begin
  4951.   if Assigned(FInplaceEdit) and FEditorMode then
  4952.   begin
  4953.     if FIsModified then
  4954.     begin
  4955.       Result := FInplaceEdit.ValueCorrect;
  4956.       if not Result then
  4957.       begin
  4958.          FInplaceEdit.ShowErrorMessage;
  4959.          Exit;
  4960.        end;
  4961.       if FInplaceEdit.ErrorCode = ERR_EDIT_NONE then UpdateEditData;
  4962.     end;
  4963.     if GetFocus = FInplaceEdit.Handle then Windows.SetFocus(Handle);
  4964.  
  4965.     FEditorMode  := False;
  4966.     FInplaceEdit.Free;
  4967.     FInplaceEdit := nil;
  4968.  
  4969.     UpdateRect := BoxRectEx(0, FInplaceRow , ColCount - 1, FInplaceRow );
  4970.     ValidateRect(Handle, @UpdateRect);
  4971.     InvalidateRect(Handle, @UpdateRect, False);
  4972.     FInplaceCol  := -1;
  4973.     FInplaceRow  := -1;
  4974.     FIsESCKey    := False;
  4975.     FRowUpdated  := FRowUpdated or FIsModified;
  4976.  
  4977.     DoDestroyCellEdit;
  4978.     FSelectedKnot.State := ksBrowse;
  4979.  
  4980.   end
  4981.   else begin
  4982.     if Assigned(FInplaceEdit) then Windows.SetFocus(Handle);
  4983.   end;
  4984.  
  4985.   FIsModified := False;
  4986.   Result      := True;
  4987. end;
  4988.  
  4989. procedure TDCCustomTreeGrid.ShowEditor;
  4990.  
  4991.   procedure UpdateEditor;
  4992.   begin
  4993.     FInplaceCol := Col;
  4994.     FInplaceRow := Row;
  4995.     FInplaceEdit.SelectAll;
  4996.   end;
  4997.  
  4998. var
  4999.   Column: TKnotColumn;
  5000.   Key: Word;
  5001.   CanCreate: boolean;
  5002.   AState: TKnotState;
  5003. begin
  5004.   if not(tgEditing in Options) or (Columns.Count=0) then Exit;
  5005.   Column := Columns[Col-FIndicatorOffset];
  5006.  
  5007.   if not(kcShowEdit in Column.Options) or
  5008.     (FSelectedKnot <> nil) and not FSelectedKnot.Enabled or
  5009.     (tgTreePathCompletion in Options) and (FSelectedKnot <> nil) and FSelectedKnot.HasChildren then Exit;
  5010.  
  5011.   with FKnots do
  5012.     if Count = 0 then begin
  5013.       Key := VK_DOWN;
  5014.       KeyDown(Key, []);
  5015.       if FSelectedKnot = nil then Exit;
  5016.     end;
  5017.  
  5018.   if FEditorMode then HideEditor;
  5019.  
  5020.   if Assigned(FSelectedKnot) then
  5021.   begin
  5022.     AState := FSelectedKnot.State;
  5023.     FSelectedKnot.State := ksEdit;
  5024.   end
  5025.   else
  5026.     AState := ksBrowse;
  5027.  
  5028.   DoCreateCellEdit(Column, FInplaceEdit, CanCreate);
  5029.  
  5030.   if Assigned(FInplaceEdit) then
  5031.   begin
  5032.     FEditorMode  := True;
  5033.     FIsModified  := False;
  5034.     with FInplaceEdit do
  5035.     begin
  5036.       Visible   := False;
  5037.       ReadOnly  := kcReadOnly in Column.Options ;
  5038.       if Options * [tgColLines, tgRowLines] = [tgColLines, tgRowLines] then
  5039.         DrawStyle := fsNone
  5040.       else
  5041.         DrawStyle := fsSingle;
  5042.     end;
  5043.     UpdateEditor;
  5044.     InplaceUpdateLoc(FInplaceEdit, CellRect(Col, Row), Canvas);
  5045.   end
  5046.   else
  5047.     if Assigned(FSelectedKnot) then FSelectedKnot.State := AState;
  5048. end;
  5049.  
  5050. procedure TDCCustomTreeGrid.DoCreateCellEdit(Column: TKnotColumn;
  5051.   var Edit: TDCCustomChoiceEdit; var CanCreate: boolean);
  5052. begin
  5053.   CanCreate := True;
  5054.   if Assigned(FOnCreateCellEdit) then
  5055.     FOnCreateCellEdit(SelectedKnot, Edit, Column, CanCreate)
  5056.   else
  5057.     Edit := nil;
  5058. end;
  5059.  
  5060. procedure TDCCustomTreeGrid.CMInvalidValue(var Message: TMessage);
  5061. begin
  5062.   if FIsESCKey then
  5063.     Message.Result := Integer(True)
  5064.   else
  5065.     Message.Result := Integer(False);
  5066. end;
  5067.  
  5068. function TDCCustomTreeGrid.Modified: boolean;
  5069. begin
  5070.   Result := FIsModified or FRowUpdated;
  5071. end;
  5072.  
  5073. procedure TDCCustomTreeGrid.SetModified(Value: boolean);
  5074. begin
  5075.   if FIsModified <> Value then
  5076.   begin
  5077.     FIsModified := Value;
  5078.     if FKnots.State <> ksInsert then
  5079.       FKnots.SetState(ksEdit);
  5080.   end;
  5081. end;
  5082.  
  5083. procedure TDCCustomTreeGrid.UpdateEditData;
  5084. begin
  5085.   if SelectedKnot <> nil then
  5086.   begin
  5087.     if (FInplaceCol >= FIndicatorOffset) then
  5088.       DoUpdate(SelectedKnot, FInplaceEdit, FColumns[FInplaceCol-FIndicatorOffset])
  5089.     else
  5090.       DoUpdate(SelectedKnot, FInplaceEdit, nil);
  5091.   end;
  5092. end;
  5093.  
  5094. procedure TDCCustomTreeGrid.WMChar(var Msg: TWMChar);
  5095. begin
  5096.   if not DataVisible then Exit;
  5097.   if (tgEditing in Options) and (Char(Msg.CharCode) in [^H, #32..#255]) then
  5098.     if not FEditorMode and (Char(Msg.CharCode) in ['+', '-', '*']) then
  5099.       inherited
  5100.     else begin
  5101.       if not ShowEditorChar(Char(Msg.CharCode)) then inherited
  5102.     end
  5103.   else
  5104.     inherited;
  5105. end;
  5106.  
  5107. function TDCCustomTreeGrid.ShowEditorChar(Ch: Char): boolean;
  5108. begin
  5109.   Result := True;
  5110.   if not FEditorMode then
  5111.   begin
  5112.     ShowEditor;
  5113.     if FInplaceEdit <> nil then
  5114.       PostMessage(FInplaceEdit.Handle, WM_CHAR, Word(Ch), 0)
  5115.     else
  5116.       Result := False;
  5117.   end;
  5118. end;
  5119.  
  5120. procedure TDCCustomTreeGrid.CalcSizingState(X, Y: Integer;
  5121.   var State: TGridState; var Index, SizingPos, SizingOfs: Integer;
  5122.   var FixedInfo: TGridDrawInfo);
  5123. var
  5124.   EffectiveOptions: TGridOptions;
  5125.   ACol, AWidth: integer;
  5126.  
  5127.   procedure CalcAxisState(const AxisInfo: TGridAxisDrawInfo; Pos: Integer;
  5128.     NewState: TGridState);
  5129.   var
  5130.     I, Line, Back, Range, J: Integer;
  5131.   begin
  5132.     if UseRightToLeftAlignment then
  5133.       Pos := ClientWidth - Pos;
  5134.     with AxisInfo do
  5135.     begin
  5136.       Range := EffectiveLineWidth;
  5137.       Back := 0;
  5138.       if Range < 7 then
  5139.       begin
  5140.         Range := 7;
  5141.         Back := (Range - EffectiveLineWidth) shr 1;
  5142.       end;
  5143.  
  5144.       if tgTreePath in Options then
  5145.       begin
  5146.         Line := FixedBoundary;
  5147.         if not(Line > GridBoundary) and
  5148.           (Pos >= Line - Back) and (Pos <= Line - Back + Range) then
  5149.         begin
  5150.           State := NewState;
  5151.           SizingPos := Line;
  5152.           SizingOfs := Line - Pos;
  5153.           Index := -1;
  5154.           Exit;
  5155.         end;
  5156.       end;
  5157.  
  5158.       Line := FixedBoundary;
  5159.       J := FirstGridCell;
  5160.       for I := J to GridCellCount - 1 do
  5161.       begin
  5162.         Inc(Line, GetExtent(I));
  5163.         if Line > GridBoundary then Break;
  5164.         if (Pos >= Line - Back) and (Pos <= Line - Back + Range) then
  5165.         begin
  5166.           State := NewState;
  5167.           SizingPos := Line;
  5168.           SizingOfs := Line - Pos;
  5169.           Index := I;
  5170.           Exit;
  5171.         end;
  5172.         Inc(Line, EffectiveLineWidth);
  5173.       end;
  5174.       if (GridBoundary = GridExtent) and (Pos >= GridExtent - Back)
  5175.         and (Pos <= GridExtent) then
  5176.       begin
  5177.         State := NewState;
  5178.         SizingPos := GridExtent;
  5179.         SizingOfs := GridExtent - Pos;
  5180.         Index := I;
  5181. //        Index := LastFullVisibleCell + 1;
  5182.       end;
  5183.     end;
  5184.   end;
  5185.  
  5186.   function XOutsideHorzFixedBoundary: Boolean;
  5187.   begin
  5188.     with FixedInfo do
  5189.       if not UseRightToLeftAlignment then
  5190.         Result := X > (Horz.FixedBoundary-AWidth)
  5191.       else
  5192.         Result := X < ClientWidth - (Horz.FixedBoundary-AWidth);
  5193.   end;
  5194.  
  5195.   function XOutsideOrEqualHorzFixedBoundary: Boolean;
  5196.   begin
  5197.     with FixedInfo do
  5198.       if not UseRightToLeftAlignment then
  5199.         Result := X >= (Horz.FixedBoundary-AWidth)
  5200.       else
  5201.         Result := X <= ClientWidth - (Horz.FixedBoundary-AWidth);
  5202.   end;
  5203.  
  5204. begin
  5205.   if not(tgTitles in Options) and not(tgColumnSizing in Options)then Y := -1;
  5206.  
  5207.   ACol := 0; AWidth := 0;
  5208.  
  5209.   FTreePathSizing := False;
  5210.   if tgTreePath in Options then
  5211.   begin
  5212.     AWidth := TreePathWidth;
  5213.     with FixedInfo do
  5214.     begin
  5215.       if not(tgTreePathResize in Options) or GroupingEnabled then
  5216.         FTreePathSizing := False
  5217.       else
  5218.         if not UseRightToLeftAlignment then
  5219.           FTreePathSizing := (X > (Horz.FixedBoundary-AWidth)) and
  5220.                              (X < Horz.FixedBoundary)
  5221.         else
  5222.           FTreePathSizing := (X < ClientWidth - (Horz.FixedBoundary-AWidth)) and
  5223.                              (X < ClientWidth - Horz.FixedBoundary);
  5224.       if (tgAutoSize in Options) and (Horz.FixedBoundary = Horz.GridBoundary) then
  5225.         FTreePathSizing := False;
  5226.     end;
  5227.   end;
  5228.  
  5229.   State := gsNormal;
  5230.   Index := -1;
  5231.   EffectiveOptions := inherited Options;
  5232.   if csDesigning in ComponentState then
  5233.     EffectiveOptions := EffectiveOptions + DesignOptionsBoost;
  5234.   if [goColSizing, goRowSizing] * EffectiveOptions <> [] then
  5235.     with FixedInfo do
  5236.     begin
  5237.       Vert.GridExtent := ClientHeight;
  5238.       Horz.GridExtent := ClientWidth;
  5239.       if (Y > 0) and (XOutsideHorzFixedBoundary) and (goColSizing in EffectiveOptions) then
  5240.       begin
  5241.         if (Y >= Vert.FixedBoundary) and not(tgColumnSizing in Options) then Exit;
  5242.         CalcAxisState(Horz, X, gsColSizing);
  5243.       end
  5244.       else if (Y > Vert.FixedBoundary) and (goRowSizing in EffectiveOptions) then
  5245.       begin
  5246.         if XOutsideOrEqualHorzFixedBoundary then Exit;
  5247.         CalcAxisState(Vert, Y, gsRowSizing);
  5248.       end;
  5249.     end;
  5250.  
  5251.   if (State = gsColSizing)then
  5252.   begin
  5253.     ACol := RawToDataColumn(Index);
  5254.     if (ACol >= 0) and (ACol < Columns.Count) and
  5255.      not( (Columns[ACol].Options * [kcSizing, kcVisible] = [kcSizing, kcVisible]) or
  5256.           (csDesigning in ComponentState) ) or
  5257.      (ACol < 0) and not FTreePathSizing
  5258.    then
  5259.       State := gsNormal
  5260.    else
  5261.       FSizingIndex := Index;
  5262.   end;
  5263.  
  5264.   if (tgTreePath in Options) and (State = gsColSizing) and FTreePathSizing
  5265.   then
  5266.     if SizingPos < FixedInfo.Horz.FixedBoundary then
  5267.       FTreePathSizing := GetFixedCellType(ACol, FIndicatorOffset-1) = fcTreePath
  5268.     else
  5269.       FTreePathSizing := ((ACol+FIndicatorOffset)= -1);
  5270.   FSizingOff := SizingOfs;
  5271. end;
  5272.  
  5273. procedure TDCCustomTreeGrid.SetImages(const Value: TImageList);
  5274. begin
  5275.   if Images <> nil then
  5276.     Images.UnRegisterChanges(FImageChangeLink);
  5277.   FImages := Value;
  5278.   if Images <> nil then
  5279.   begin
  5280.     Images.RegisterChanges(FImageChangeLink);
  5281.     Images.FreeNotification(Self);
  5282.   end;
  5283.   LayoutChanged;
  5284. end;
  5285.  
  5286. function TDCCustomTreeGrid.GetHintTreeOffset(KnotItem: TKnotItem;
  5287.   Hint: TTreeGridHitTest): integer;
  5288.  var
  5289.   ALevel: integer;
  5290. begin
  5291.   with KnotItem do
  5292.     case Hint of
  5293.       htNowere  :
  5294.         Result := 1;
  5295.       htOnButton:
  5296.         begin
  5297.           if [tgeShowLines, tgeShowButtons] * OptionsEx <> [] then
  5298.             ALevel := Level
  5299.           else
  5300.             ALevel := Level - 1;
  5301.           Result := GetHintTreeOffset(KnotItem, htNowere);
  5302.           Result := Result + ALevel* Indent + 1;
  5303.         end;
  5304.       htOnIcon  :
  5305.         begin
  5306.           Result := GetHintTreeOffset(KnotItem, htOnButton);
  5307.           Result := Result + Indent;
  5308.         end;
  5309.       htOnLabel :
  5310.         begin
  5311.           Result := GetHintTreeOffset(KnotItem, htOnIcon);
  5312.           if (Images<>nil) and
  5313.              ((KnotID =  SelectedKnot.KnotID)and(SelectImage>-1) or
  5314.               (KnotID <> SelectedKnot.KnotID)and(NormalImage>-1))
  5315.           then
  5316.             Result := Result+Images.Width + 5;
  5317.         end;
  5318.       else
  5319.         Result := 0;
  5320.     end;
  5321. end;
  5322.  
  5323. procedure TDCCustomTreeGrid.HideHintWindow;
  5324.  var
  5325.   pHintWindow: PHintWindowParam_tag;
  5326. begin
  5327.   if (FHintRow <> -1) and HandleAllocated then
  5328.   begin
  5329.     GetMem(pHintWindow, SizeOf(THintWindowParam));
  5330.     with pHintWindow^ do
  5331.     begin
  5332.       HMode := 0;
  5333.       PHint := nil;
  5334.     end;
  5335.     SendMessage(Handle, CM_POPUPHINTINFO, Integer(pHintWindow), 0);
  5336.   end;
  5337. end;
  5338.  
  5339. procedure TDCCustomTreeGrid.CMMouseLeave(var Message: TMessage);
  5340. begin
  5341.   inherited;
  5342.   DoColumnComment(MODE_HIDEWINDOW, nil);
  5343.   HideHintWindow;
  5344. end;
  5345.  
  5346. procedure TDCCustomTreeGrid.ShowHintWindow(X, Y, ALeft, ATop, AOff: integer;
  5347.   Text: string);
  5348.  var
  5349.   pHintWindow: PHintWindowParam_tag;
  5350. begin
  5351.   if not ShowHint and (DragState = dsNone) then
  5352.   begin
  5353.  
  5354.     if [goHorzLine, goVertLine] * inherited Options <> [goHorzLine, goVertLine] then
  5355.       ALeft := ALeft - GridLineWidth;
  5356.  
  5357.     GetMem(pHintWindow, SizeOf(THintWindowParam));
  5358.     with pHintWindow^ do
  5359.     begin
  5360.       HMode := 1;
  5361.       HLeft := ALeft;
  5362.       HTop  := ATop;
  5363.       HOff  := AOff;
  5364.       HPosX := X;
  5365.       HPosY := Y;
  5366.       GetMem(PHint, (Length(Text)+1)*SizeOf(Char));
  5367.       StrPCopy(PHint, Text);
  5368.     end;
  5369.     SendMessage(Handle, CM_POPUPHINTINFO, Integer(pHintWindow), 1);
  5370.   end;
  5371. end;
  5372.  
  5373. procedure TDCCustomTreeGrid.InvalidateSelected;
  5374.  var
  5375.   Rect: TRect;
  5376. begin
  5377.   if not HandleAllocated then Exit;
  5378.   if (tgMultiSelect in Options) and (FBookmarks.Count > 0) then
  5379.     InvalidateRect(Handle, nil, False)
  5380.   else begin
  5381.     Rect := BoxRectEx(0, Row , ColCount-1, Row );
  5382.     InvalidateRect(Handle, @Rect, False);
  5383.   end;  
  5384. end;
  5385.  
  5386. function TDCCustomTreeGrid.GetTreePathCaption(KnotItem: TKnotItem;
  5387.   var Text: string): boolean;
  5388. begin
  5389.   Result := True;
  5390.   Text   := KnotItem.Name;
  5391.   if Assigned(FOnTreeCellText) then FOnTreeCellText(Self, KnotItem, Text, Result);
  5392. end;
  5393.  
  5394. procedure TDCCustomTreeGrid.RowMoved(FromIndex, ToIndex: Integer);
  5395. begin
  5396.   inherited;
  5397.   if Assigned(FOnRowMoved) then FOnRowMoved(Self, FromIndex, ToIndex);
  5398. end;
  5399.  
  5400. procedure TDCCustomTreeGrid.ShowTreePathEditor;
  5401.  var
  5402.   R: TRect;
  5403.   CanCreate: boolean;
  5404.  
  5405.   procedure UpdateEditor;
  5406.   begin
  5407.     FInplaceCol := FIndicatorOffset-1;
  5408.     FInplaceRow := Row;
  5409.     FInplaceEdit.SelectAll;
  5410.   end;
  5411.  
  5412. begin
  5413.   if not(tgEditing in Options) or (Columns.Count=0) or
  5414.      (FKnots.Count=0) then Exit;
  5415.  
  5416.   if FEditorMode then HideEditor;
  5417.  
  5418.   DoCreateCellEdit(nil, FInplaceEdit, CanCreate);
  5419.  
  5420.   if Assigned(FInplaceEdit) then
  5421.   begin
  5422.     FEditorMode  := True;
  5423.     FIsModified  := False;
  5424.     with FInplaceEdit do
  5425.     begin
  5426.       Text      := FSelectedKnot.Name;
  5427.       Visible   := False;
  5428.       Parent    := Self;
  5429.       DrawStyle := fsSingle;
  5430.     end;
  5431.  
  5432.     UpdateEditor;
  5433.  
  5434.     R := CellRect(FIndicatorOffset-1, Row);
  5435.     R.Left := R.Left + GetTreeLableOffset(FSelectedKnot);
  5436.     InplaceUpdateLoc(FInplaceEdit, R, Canvas);
  5437.   end;
  5438. end;
  5439.  
  5440. procedure TDCCustomTreeGrid.ClipButtonClick(Sender: TObject);
  5441.  var
  5442.   ACellType: TFixedCell;
  5443. begin
  5444.   ACellType := TKnotClipPopup(FClipPopup).CellType;
  5445.   HideClipPopup;
  5446.   if Assigned(FOnClipButtonClick) then FOnClipButtonClick(Sender);
  5447.   if ACellType = fcMarker then
  5448.   begin
  5449.     case TDCAssistButton(Sender).Pos of
  5450.       pmSelectAll: SelectItems(smSelect);
  5451.       pmDeselectAll: SelectItems(smDeselect);
  5452.     end;
  5453.   end;
  5454. end;
  5455.  
  5456. procedure TDCCustomTreeGrid.WMNCLButtonDown(var Message: TWMNCLButtonDown);
  5457. begin
  5458.   inherited;
  5459.   HideClipPopup;
  5460. end;
  5461.  
  5462. procedure TDCCustomTreeGrid.WMHScroll(var Message: TWMHScroll);
  5463.  var
  5464.   NewLeft: integer;
  5465. begin
  5466.   if  (DragState = dsColMoving) or
  5467.       (not(FEditorMode or FKnots.Updating or FLockScreen) and DataVisible) then
  5468.   begin
  5469.     if CanModifyHScrollBar(SB_HORZ, Message.ScrollCode, Message.Pos, True, NewLeft) then
  5470.     begin
  5471.       FLockScroll := True;
  5472.       try
  5473.         if NewLeft <> -1 then
  5474.           LeftCol := NewLeft
  5475.         else
  5476.           inherited;
  5477.       finally
  5478.         FLockScroll := False;
  5479.       end;
  5480.     end;
  5481.   end;
  5482. end;
  5483.  
  5484. procedure TDCCustomTreeGrid.WMVScroll(var Message: TWMVScroll);
  5485. begin
  5486.   if (DragState = dsColMoving) or
  5487.      (not(FEditorMode or FKnots.Updating or FLockScreen) and DataVisible) then
  5488.   begin
  5489.     inherited;
  5490.   end;
  5491. end;
  5492.  
  5493. procedure TDCCustomTreeGrid.SetPopupTitle(const Value: TPopupMenu);
  5494. begin
  5495.   FPopupTitle := Value;
  5496. end;
  5497.  
  5498. function TDCCustomTreeGrid.GetPopupMenu: TPopupMenu;
  5499.  var
  5500.   P: TPoint;
  5501.   Cell: TGridCoord;
  5502. begin
  5503.   GetCursorPos(P);
  5504.   P := ScreenToClient(P);
  5505.   Cell := MouseCoord(P.X, P.Y);
  5506.   with Cell do
  5507.     if (Y < FTitleOffset) and (X > 0) and (X >= FIndicatorOffset) and
  5508.        Assigned(FPopupTitle)
  5509.     then
  5510.       Result := FPopupTitle
  5511.     else
  5512.       Result := inherited GetPopupMenu;
  5513. end;
  5514.  
  5515. procedure TDCCustomTreeGrid.DoDelete(KnotItem: TKnotItem; var Apply: boolean;
  5516.   ComponentState: TComponentState);
  5517. begin
  5518.   if KnotItem.Owner.State <> ksInsert then
  5519.   begin
  5520.     if Assigned(FOnDelete) then FOnDelete(KnotItem, Apply, ComponentState);
  5521.   end
  5522.   else
  5523.     Apply := True;  
  5524. end;
  5525.  
  5526. procedure TDCCustomTreeGrid.DoInsert(KnotItem: TKnotItem; var Apply: boolean);
  5527. begin
  5528.   if Assigned(FOnInsert) then FOnInsert(KnotItem, Apply);
  5529. end;
  5530.  
  5531. procedure TDCCustomTreeGrid.DoUpdate(KnotItem: TKnotItem; var Edit: TDCCustomChoiceEdit;
  5532.   Column: TKnotColumn);
  5533. begin
  5534.   if Assigned(FOnUpdate) then FOnUpdate(KnotItem, Edit, Column);
  5535. end;
  5536.  
  5537. function TDCCustomTreeGrid.DeletePrompt: boolean;
  5538.  var
  5539.   Msg: string;
  5540.   nCount: integer;
  5541. begin
  5542.   nCount := FBookmarks.Count;
  5543.   if (nCount > 1) then
  5544.     Msg := Format(LoadStr(RES_GRID_STR_MSEL),[nCount, RecordCount2Str(nCount)])
  5545.   else
  5546.     Msg := LoadStr(RES_GRID_STR_SSEL);
  5547.   Result := (MessageDlg(Msg, mtConfirmation, mbOKCancel, 0) <> idCancel);
  5548. end;
  5549.  
  5550. procedure TDCCustomTreeGrid.DeleteRecords(AtOnce: boolean);
  5551. begin
  5552.   if (tgEditing in FOptions) and (AtOnce or DeletePrompt) and
  5553.      Assigned(FSelectedKnot)
  5554.   then begin
  5555.     if FBookmarks.Count = 0 then SelectedRows.Select(FSelectedKnot, True);
  5556.     SavePosition;
  5557.     BeginUpdate;
  5558.     try
  5559.       FBookmarks.Delete;
  5560.       if FCurrentPos[1] = nil
  5561.       then
  5562.         SelectedKnot := FKnots.GetFirstVisibleNode
  5563.       else
  5564.         GotoBookmark(FCurrentPos[1])
  5565.     finally
  5566.       EndUpdate;
  5567.     end;
  5568.   end;
  5569. end;
  5570.  
  5571. procedure TDCCustomTreeGrid.DoSelectCell(Sender: TObject; ACol,
  5572.   ARow: Integer; var CanSelect: Boolean);
  5573. begin
  5574.   if Assigned(FOnSelectCell) then FOnSelectCell(Sender, ACol, ARow+1, CanSelect);
  5575. end;
  5576.  
  5577. procedure TDCCustomTreeGrid.DoDrawColumnCell(Canvas: TCanvas; ARect: TRect;
  5578.   ACol: integer; AColumn: TKnotColumn; AKnot: TKnotItem; AState: TGridDrawState);
  5579. begin
  5580.   if Assigned(FOnDrawColumnCell) then
  5581.     FOnDrawColumnCell(Self, ARect, Canvas, ACol, AColumn, AKnot, AState);
  5582. end;
  5583.  
  5584. procedure TDCCustomTreeGrid.DoDestroyCellEdit;
  5585. begin
  5586.   if Assigned(FOnDestroyCellEdit) then FOnDestroyCellEdit(Self);
  5587. end;
  5588.  
  5589. procedure TDCCustomTreeGrid.DoColumnComment(Mode: integer; Column: TKnotColumn);
  5590. begin
  5591.   if (FColumnCell <> -1) and (Mode = MODE_HIDEWINDOW) then
  5592.   begin
  5593.     if Assigned(FOnColumnComment) then FOnColumnComment(Self, Mode, Column);
  5594.     FColumnCell := -1;
  5595.   end
  5596.   else
  5597.     if Assigned(FOnColumnComment) then FOnColumnComment(Self, Mode, Column);
  5598. end;
  5599.  
  5600. procedure TDCCustomTreeGrid.CMPopupHintInfo(var Message: TMessage);
  5601.  var
  5602.   pHintWindow: PHintWindowParam_tag;
  5603. begin
  5604.   pHintWindow := PHintWindowParam_tag(Message.WParam);
  5605.   with pHintWindow^ do
  5606.   begin
  5607.     case HMode of
  5608.       0:
  5609.        if (FHintRow <> - 1) and (FHintWindow <> nil) then
  5610.        begin
  5611.          FHintRow := -1;
  5612.          FHintWindow.Free;
  5613.          FHintWindow := nil;
  5614.        end;
  5615.       1:
  5616.        begin
  5617.          if not Assigned(FHintWindow) then
  5618.          begin
  5619.            FHintWindow := TDCMessageWindow.Create(Self);
  5620.            with FHintWindow do
  5621.            begin
  5622.              Parent := Self;
  5623.              DialogStyle := dsSimple;
  5624.              PopupAlignment := wpOffset;
  5625.              Centered := True;
  5626.            end;
  5627.          end
  5628.          else
  5629.            FHintWindow.Hide;
  5630.  
  5631.          with FHintWindow do
  5632.          begin
  5633.            FHintRow := HPosY;
  5634.            Font   := Self.Font;
  5635.            Caption := Format('/oh{-1}/ow{-2}%s',[PHint]);
  5636.            Left   := HLeft + HOff + 1;
  5637.            Top := HTop - 2;
  5638.            Height := RowHeights[HPosY] + 2;
  5639.            Show;
  5640.          end;
  5641.        end;
  5642.     end;
  5643.   end;
  5644.   if Assigned(pHintWindow^.PHint) then FreeMem(pHintWindow^.PHint);
  5645.   FreeMem(pHintWindow);
  5646. end;
  5647.  
  5648. function TDCCustomTreeGrid.DoMouseWheelDown(Shift: TShiftState;
  5649.   MousePos: TPoint): Boolean;
  5650.  var
  5651.   MouseWheelDownEvent: TMouseWheelUpDownEvent;
  5652. begin
  5653.   Result := False;
  5654.   MouseWheelDownEvent := OnMouseWheelDown;
  5655.   if Assigned(MouseWheelDownEvent) then
  5656.     MouseWheelDownEvent(Self, Shift, MousePos, Result);
  5657.  
  5658.   if not Result and (DragState = dsNone) and
  5659.     PtInRect(ClientRect, ScreenToClient(MousePos)) and not FKnots.Updating then
  5660.   begin
  5661.     if ssShift in Shift then
  5662.       NextRow(True, False, Shift)
  5663.     else begin
  5664.       if TopRow < RowCount - VisibleRowCount then  TopRow := TopRow + 1;
  5665.     end;
  5666.     Result := True;
  5667.   end;
  5668. end;
  5669.  
  5670. function TDCCustomTreeGrid.DoMouseWheelUp(Shift: TShiftState;
  5671.   MousePos: TPoint): Boolean;
  5672.  var
  5673.   MouseWheelUpEvent: TMouseWheelUpDownEvent;
  5674.  
  5675. begin
  5676.   Result := False;
  5677.   MouseWheelUpEvent := OnMouseWheelDown;
  5678.   if Assigned(MouseWheelUpEvent) then
  5679.     MouseWheelUpEvent(Self, Shift, MousePos, Result);
  5680.  
  5681.   if not Result and (DragState =dsNone) and
  5682.     PtInRect(ClientRect, ScreenToClient(MousePos)) and not FKnots.Updating then
  5683.   begin
  5684.     if ssShift in Shift then
  5685.       PrevRow(True, Shift)
  5686.     else
  5687.       if (TopRow > FixedRows) and (RowCount > VisibleRowCount) then TopRow := TopRow - 1;
  5688.     Result := True;
  5689.   end;
  5690. end;
  5691.  
  5692. procedure TDCCustomTreeGrid.InsertKnot(ParentKnot: TKnotItem;
  5693.   lChild: boolean; Shift: TShiftState);
  5694.  var
  5695.   NewKnot, NextKnot: TKnotItem;
  5696.   Delta: integer;
  5697.   CanSelect: boolean;
  5698. begin
  5699.   with FKnots do
  5700.   begin
  5701.     if State = ksInsert then begin
  5702.       CanSelect := True and Modified;
  5703.       DoSelectCell(Self, Col, Row+1, CanSelect);
  5704.       if CanSelect then
  5705.         SetState(ksBrowse)
  5706.       else
  5707.         Exit;
  5708.     end;
  5709.     BeginUpdate;
  5710.     if ParentKnot = nil then
  5711.     begin
  5712.       NewKnot := FKnots.Add(NE_EMPTY_KNOT);
  5713.       if NewKnot <> nil then SetSelectedKnot(NewKnot);
  5714.     end
  5715.     else begin
  5716.       if lChild then
  5717.       begin
  5718.         NewKnot := FKnots.AddChild(ParentKnot, NE_EMPTY_KNOT);
  5719.         ParentKnot.Expand(False);
  5720.       end
  5721.       else
  5722.         if ssShift in Shift then
  5723.         begin
  5724.           NewKnot := FKnots.AddChild(ParentKnot.Parent, NE_EMPTY_KNOT,
  5725.             ParentKnot.FIndex);
  5726.           if NewKnot <> nil then SetSelectedKnot(NewKnot);
  5727.         end
  5728.         else
  5729.           NewKnot := FKnots.AddChild(ParentKnot.Parent, NE_EMPTY_KNOT,
  5730.             ParentKnot.FIndex+1)
  5731.     end;
  5732.     EndUpdate;
  5733.     if NewKnot = nil then Exit;
  5734.     Delta := 0;
  5735.     NextKnot := FSelectedKnot;
  5736.     while (NewKnot.KnotID<>NextKnot.KnotID) and (NextKnot<>nil) do
  5737.     begin
  5738.       Inc(Delta);
  5739.       NextKnot := NextKnot.GetNextVisible;
  5740.     end;
  5741.     if not Eof  then Row := Row + Delta;
  5742.     FKnots.SetState(ksInsert);
  5743.   end;
  5744. end;
  5745.  
  5746. procedure TDCCustomTreeGrid.MarkKnot;
  5747. begin
  5748.   if (tgMarker in Options) and (FKnots.Count>0) then
  5749.   begin
  5750.     try
  5751.       BeginUpdate;
  5752.       with FSelectedKnot, FBookmarks do
  5753.         Select(FSelectedKnot, not KnotSelected(KnotID));
  5754.     finally
  5755.       EndUpdate;
  5756.     end;
  5757.   end;
  5758. end;
  5759.  
  5760. procedure TDCCustomTreeGrid.NextRow(Select, Insert: boolean; Shift: TShiftState;
  5761.    AOffset: integer = 1);
  5762. begin
  5763.   LockUpdate;
  5764.   try
  5765.     with FKnots do
  5766.     begin
  5767.       if (State = ksInsert) then
  5768.       begin
  5769.         if not Modified then
  5770.         begin
  5771.           if not Eof then
  5772.           begin
  5773.             if FEditorMode then HideEditor;
  5774.             if FInplaceEdit = nil then
  5775.             begin
  5776.               Delete(FSelectedKnot);
  5777.               SetState(ksBrowse);
  5778.             end;
  5779.           end;
  5780.           Exit;
  5781.         end
  5782.       end;
  5783.       if FEditorMode then HideEditor;
  5784.       if not Assigned(FInplaceEdit) then
  5785.       begin
  5786.         if Eof then
  5787.         begin
  5788.           if Focused and Insert and (tgEditing in Options) then
  5789.             InsertKnot(FSelectedKnot, False, Shift);
  5790.         end
  5791.         else begin
  5792.           DoSelection(Select, Shift, 1);
  5793.           if (Row + AOffset) < RowCount then
  5794.             Row := Row + AOffset
  5795.           else
  5796.             Row := RowCount - 1;
  5797.         end;
  5798.       end;
  5799.     end;
  5800.   finally
  5801.     UnlockUpdate;
  5802.   end;
  5803. end;
  5804.  
  5805. procedure TDCCustomTreeGrid.PrevRow(Select: Boolean; Shift: TShiftState;
  5806.   AOffset: integer = 1);
  5807.  var
  5808.   AEof: boolean;
  5809. begin
  5810.   LockUpdate;
  5811.   try
  5812.     AEof := False;
  5813.     with FKnots do
  5814.     begin
  5815.       if FEditorMode then HideEditor;
  5816.       if (State = ksInsert) then
  5817.       begin
  5818.         AEof := Eof and not Modified;
  5819.         if (FInplaceEdit = nil) and not Modified then
  5820.         begin
  5821.           Delete(FSelectedKnot);
  5822.           SetState(ksBrowse);
  5823.         end;
  5824.       end;
  5825.       if (FInplaceEdit = nil) and (Row > FTitleOffset) and not(AEof) then
  5826.       begin
  5827.         DoSelection(Select, Shift, -1);
  5828.         if Row - AOffset < 0 then
  5829.           Row := FTitleOffset
  5830.         else
  5831.           Row := Row - AOffset;
  5832.       end;    
  5833.     end;
  5834.   finally
  5835.     UnlockUpdate;
  5836.   end
  5837. end;
  5838.  
  5839. procedure TDCCustomTreeGrid.ClearSelection;
  5840. begin
  5841.   if (tgMultiSelect in Options) then
  5842.   begin
  5843.     FBookmarks.Clear;
  5844.     FSelecting := False;
  5845.   end;
  5846. end;
  5847.  
  5848. function TDCCustomTreeGrid.Eof: boolean;
  5849. begin
  5850.   Result := Row = (RowCount-1);
  5851. end;
  5852.  
  5853. function TDCCustomTreeGrid.BoxRectEx(ALeft, ATop, ARight,
  5854.   ABottom: Integer): TRect;
  5855. begin
  5856.   Result := BoxRect(ALeft, ATop, ARight, ABottom);
  5857.   if tgCompleteLines in Options then Result.Right := Width;
  5858. end;
  5859.  
  5860. procedure TDCCustomTreeGrid.Paint;
  5861.  var
  5862.   DrawInfo: TGridDrawInfo;
  5863.   CurRow: integer;
  5864.   ARect, BRect: TRect;
  5865.   BorderStyle: TEdgeBorderStyle;
  5866.   LineColor: TColor;
  5867.   UpdateRect, FooterRect : TRect;
  5868.   SaveIndex: integer;
  5869. begin
  5870.   if (tgCompleteLines in Options) and not(tgAutoSize in Options) then
  5871.   begin
  5872.     CalcDrawInfo(DrawInfo);
  5873.  
  5874.     SaveIndex := SaveDC(Canvas.Handle);
  5875.     UpdateRect := Canvas.ClipRect;
  5876.     FooterRect := Footers.BoundsRect;
  5877.     with UpdateRect do
  5878.     begin
  5879.       Bottom := FooterRect.Top;
  5880.       Left  := DrawInfo.Horz.GridBoundary;
  5881.       Right := DrawInfo.Horz.GridExtent;
  5882.       ExcludeClipRect(Canvas.Handle, Left, Top, Right, Bottom);
  5883. {
  5884.       ExcludeClipRect(Canvas.Handle, 0,
  5885.         DrawInfo.Vert.GridBoundary, DrawInfo.Horz.GridBoundary, DrawInfo.Vert.GridExtent);
  5886. }
  5887.     end;
  5888.     inherited;
  5889.     RestoreDC(Canvas.Handle, SaveIndex);
  5890.  
  5891.     if not IsRectEmpty(FooterRect) then
  5892.       with FooterRect do
  5893.         ExcludeClipRect(Canvas.Handle, Left, Top, Right, Bottom);
  5894.  
  5895.     with DrawInfo do
  5896.     begin
  5897.       if Horz.GridBoundary < Horz.GridExtent then
  5898.       begin
  5899.         CurRow := 0;
  5900.  
  5901.         if ColorToRGB(Color) = clSilver then
  5902.           LineColor := clGray
  5903.         else
  5904.           LineColor := clSilver;
  5905.  
  5906.         BorderStyle := GetBorderStyle;
  5907.         if not(BorderStyle = ebsShadowFlat) and
  5908.           (ColorToRGB(Color) = ColorToRGB(FixedColor)) then BorderStyle := ebsNone;
  5909.  
  5910.         ARect := Rect(Horz.GridBoundary, 0, Horz.GridExtent, 0);
  5911.         if FTitleOffset > 0 then
  5912.         begin
  5913.           Canvas.Brush.Color := FixedColor;
  5914.           while CurRow < FTitleOffset do
  5915.           begin
  5916.             ARect.Bottom := ARect.Bottom + RowHeights[CurRow];
  5917.             BRect := ARect;
  5918.             InflateRect(BRect, 1, 1);
  5919.             if RectVisible(Canvas.Handle, BRect) then
  5920.             begin
  5921.               if RectVisible(Canvas.Handle, ARect) then
  5922.               begin
  5923.                 Canvas.FillRect(ARect);
  5924.                 if (tgFixedLines in Options) then
  5925.                 begin
  5926.                   if BorderStyle <> ebsNone then
  5927.                   begin
  5928.                     if BorderStyle = ebsShadowFlat then
  5929.                     begin
  5930.                       InflateRect(ARect, 1, 1);
  5931.                       ARect.Right := ARect.Right + 1;
  5932.                       ARect.Right := ARect.Right - 1;
  5933.                       DrawGridFrameBorder(Canvas, ARect, BorderStyle, dsUp, FixedColor);
  5934.                       InflateRect(ARect, -1, -1);
  5935.                     end
  5936.                     else begin
  5937.                       ARect.Right := ARect.Right + 1;
  5938.                       DrawGridFrameBorder(Canvas, ARect, BorderStyle, dsUp, FixedColor);
  5939.                     end;
  5940.                   end;
  5941.                 end;
  5942.               end;
  5943.               Canvas.Pen.Color := Canvas.Pen.Color - 1;
  5944.               if (tgRowLines in FOptions) then
  5945.               begin
  5946.                 case BorderStyle of
  5947.                   ebsNone, ebsFlat:
  5948.                     Canvas.Pen.Color := LineColor;
  5949.                   else
  5950.                     if not (tgColLines in FOptions) then
  5951.                       Canvas.Pen.Color := FixedColor
  5952.                     else
  5953.                       Canvas.Pen.Color := clBlack;
  5954.                 end;
  5955.                 Canvas.MoveTo(ARect.Left, ARect.Bottom);
  5956.                 Canvas.LineTo(ARect.Right, ARect.Bottom);
  5957.               end
  5958.             end;
  5959.             Inc(CurRow);
  5960.             ARect.Top := ARect.Bottom;
  5961.           end;
  5962.  
  5963.         end
  5964.         else begin
  5965.           if tgRowLines in FOptions then
  5966.           begin
  5967.             ARect.Top    := ARect.Top - 1;
  5968.             ARect.Bottom := ARect.Bottom - 1;
  5969.           end;
  5970.         end;
  5971.  
  5972.         while (CurRow < Vert.GridCellCount) and
  5973.               (ARect.Top < UpdateRect.Bottom) do
  5974.         begin
  5975.           if tgRowLines in FOptions then
  5976.           begin
  5977.             ARect.Bottom := ARect.Bottom + RowHeights[CurRow] + 1;
  5978.             ARect.Top    := ARect.Top    + 1;
  5979.           end
  5980.           else begin
  5981.             ARect.Bottom := ARect.Bottom + RowHeights[CurRow];
  5982.             ARect.Top    := ARect.Top;
  5983.           end;
  5984.  
  5985.           if RectVisible(Canvas.Handle, ARect) and
  5986.              ((tgRowSelect in Options) or (tgHighlightRow in Options)) and
  5987.              (AlwaysShowSelection or Focused)
  5988.           then begin
  5989.             if Row = (CurRow + Vert.FirstGridCell - FTitleOffset) then
  5990.             begin
  5991.               if FColumns.Count = 0 then
  5992.                  Canvas.Brush.Color := Self.Color
  5993.               else begin
  5994.                 if Focused or not (tgeShadowSelection in OptionsEx) then
  5995.                   Canvas.Brush.Color := clHighlight
  5996.                 else
  5997.                   if AlwaysShowSelection then
  5998.                     Canvas.Brush.Color := clShadowed;
  5999.                end;
  6000.             end
  6001.             else
  6002.               Canvas.Brush.Color := Self.Color;
  6003.           end
  6004.           else
  6005.             Canvas.Brush.Color := Self.Color;
  6006.  
  6007.           if tgTreePathCompletion in Options then
  6008.           begin
  6009.             Canvas.Pen.Color := Self.Color - 1;
  6010.             Canvas.Pen.Color := Self.Color;
  6011.             Canvas.PenPos := Point(ARect.Left, ARect.Top);
  6012.             Canvas.LineTo(ARect.Right, ARect.Top);
  6013.             Canvas.FillRect(Rect(ARect.Left, ARect.Top+1, ARect.Right, ARect.Bottom))
  6014.           end
  6015.           else
  6016.             Canvas.FillRect(ARect);
  6017.  
  6018.           ARect.Top    := ARect.Top - 1;
  6019.           ARect.Bottom := ARect.Bottom;
  6020.  
  6021.           if (tgRowLines in FOptions) and RectVisible(Canvas.Handle, ARect) then
  6022.           begin
  6023.             Canvas.Pen.Color := 0;
  6024.             Canvas.Pen.Color := LineColor;
  6025.             Canvas.MoveTo(ARect.Left, ARect.Bottom);
  6026.             Canvas.LineTo(ARect.Right, ARect.Bottom);
  6027.           end;
  6028.  
  6029.           Inc(CurRow);
  6030.           ARect.Top := ARect.Bottom;
  6031.         end;
  6032.         if ARect.Top < UpdateRect.Bottom then
  6033.         begin
  6034.           BRect := ClientRect;
  6035.           if Vert.GridBoundary < Vert.GridExtent   then
  6036.           begin
  6037.             ARect.Top    := Vert.GridBoundary;
  6038.             ARect.Bottom := Vert.GridExtent;
  6039.             Canvas.Brush.Color := Self.Color;
  6040.             Canvas.FillRect(ARect);
  6041.           end;
  6042.         end;
  6043.       end;
  6044.     end;
  6045.   end
  6046.   else
  6047.     inherited;
  6048. end;
  6049.  
  6050. procedure TDCCustomTreeGrid.WMEraseBkgnd(var Message: TWmEraseBkgnd);
  6051. begin
  6052. {  inherited;  }
  6053. end;
  6054.  
  6055. procedure TDCCustomTreeGrid.ImageListChange(Sender: TObject);
  6056. begin
  6057.   LayoutChanged;
  6058. end;
  6059.  
  6060. procedure TDCCustomTreeGrid.Notification(AComponent: TComponent;
  6061.   Operation: TOperation);
  6062. begin
  6063.   inherited Notification(AComponent, Operation);
  6064.   if (Operation = opRemove) then
  6065.   begin
  6066.     if (AComponent = FImages) then
  6067.     begin
  6068.       FImages := nil;
  6069.       LayoutChanged;
  6070.       Exit;
  6071.     end;
  6072.   end;
  6073. end;
  6074.  
  6075. procedure TDCCustomTreeGrid.CMFontChanged(var Message: TMessage);
  6076. begin
  6077.   inherited;
  6078.   LayoutChanged;
  6079. end;
  6080.  
  6081. procedure TDCCustomTreeGrid.SetSelectedKnot(KnotItem: TKnotItem);
  6082. begin
  6083.   if FSelectedKnot <> KnotItem then
  6084.   begin
  6085.     FSelectedKnot := KnotItem;
  6086.     if Assigned(FOnSelectKnot) then FOnSelectKnot(Self, FSelectedKnot);
  6087.   end;  
  6088. end;
  6089.  
  6090. procedure TDCCustomTreeGrid.SetSelected(const Value: TKnotItem);
  6091.  var
  6092.   KnotItem1, KnotItem2: TKnotItem;
  6093.   i, ARow: integer;
  6094. begin
  6095.   if Value = nil then
  6096.   begin
  6097.     Row := FTitleOffset;
  6098.     Exit;
  6099.   end;
  6100.   KnotItem1 := Value;
  6101.   {check Visible}
  6102.   BeginUpdate;
  6103.   if not KnotItem1.Visible then KnotItem1.Visible := True;
  6104.   while KnotItem1 <> Knots.Root  do
  6105.   begin
  6106.     KnotItem1 := KnotItem1.Parent;
  6107.     if not KnotItem1.Visible  then KnotItem1.Visible := True;
  6108.     if not KnotItem1.Expanded then KnotItem1.Expand(False);
  6109.   end;
  6110.   EndUpdate;
  6111.   KnotItem1 := Value;
  6112.   KnotItem2 := FFirstVisible;
  6113.   ARow := _intMax(FFirstIndex + FTitleOffset, FTitleOffset);
  6114.   if KnotItem2 <> nil then
  6115.   begin
  6116.     i := Knots.ComparePos(KnotItem1, KnotItem2);
  6117.     while (KnotItem1 <> nil) and (KnotItem1 <> KnotItem2) do
  6118.     begin
  6119.       if i > 0 then
  6120.         KnotItem1 := KnotItem1.GetNextVisible
  6121.       else
  6122.         KnotItem1 := KnotItem1.GetPrevVisible;
  6123.       Inc(ARow, -i);
  6124.     end;
  6125.   end
  6126.   else begin
  6127.     KnotItem2 := Knots.GetFirstVisibleNode;
  6128.     while (KnotItem2 <> nil) and (KnotItem2 <> KnotItem1) do
  6129.     begin
  6130.       KnotItem2 := KnotItem2.GetNextVisible;
  6131.       Inc(ARow);
  6132.     end;
  6133.   end;
  6134.  
  6135.   if Row = ARow then
  6136.   begin
  6137.     if Row < TopRow then
  6138.       TopRow := Row
  6139.     else if Row > (TopRow + VisibleRowCount) then
  6140.       TopRow := Row - VisibleRowCount + 1;
  6141.   end
  6142.   else
  6143.     if (KnotItem1 <> nil) and (ARow <= RowCount) then Row := ARow;
  6144. end;
  6145.  
  6146. function TDCCustomTreeGrid.GetPosition: TBookMark;
  6147. begin
  6148.   Result := FCurrentPos[2];
  6149. end;
  6150.  
  6151. procedure TDCCustomTreeGrid.RestPosition;
  6152. begin
  6153.   if FCurrentPos[2] = nil
  6154.   then begin
  6155.     if Assigned(FCurrentPos[1])  then
  6156.        GotoBookmark(FCurrentPos[1])
  6157.     else
  6158.        SelectedKnot := FKnots.GetFirstVisibleNode;
  6159.   end
  6160.   else GotoBookmark(FCurrentPos[2])
  6161. end;
  6162.  
  6163. procedure TDCCustomTreeGrid.SavePosition;
  6164.  var
  6165.   KnotItem: TKnotItem;
  6166.  
  6167.   function KnotSelected(KnotItem: TKnotItem): boolean;
  6168.   begin
  6169.     if (KnotItem = nil) or (KnotItem.Level = -1) then
  6170.     begin
  6171.       Result := False;
  6172.       Exit;
  6173.     end;
  6174.  
  6175.     Result := SelectedRows.KnotSelected(KnotItem.KnotID);
  6176.  
  6177.     if not Result and (KnotItem.Parent.Level > -1) then
  6178.       Result := Result or KnotSelected(KnotItem.Parent)
  6179.   end;
  6180.  
  6181. begin
  6182.   if FKnots.Count > 0 then
  6183.   begin
  6184.     with FKnots do
  6185.     begin
  6186.  
  6187.       if Assigned(FCurrentPos[1]) then FreeMem(FCurrentPos[1]);
  6188.       if Assigned(FCurrentPos[2]) then FreeMem(FCurrentPos[2]);
  6189.  
  6190.       KnotItem := SelectedKnot;
  6191.  
  6192.       if KnotItem <> nil then
  6193.         FCurrentPos[2] := GetBookmark(KnotItem)
  6194.       else begin
  6195.         FCurrentPos[2] := nil;
  6196.         FCurrentPos[1] := nil;
  6197.         Exit;
  6198.       end;
  6199.  
  6200.       while KnotSelected(KnotItem) do KnotItem := KnotItem.GetPrevVisible;
  6201.  
  6202.       if (KnotItem <> nil) and (KnotItem <> FKnots.Root) then
  6203.         FCurrentPos[1] := GetBookmark(KnotItem)
  6204.       else
  6205.         FCurrentPos[1] := nil;
  6206.  
  6207.     end;
  6208.   end;
  6209. end;
  6210.  
  6211. procedure TDCCustomTreeGrid.SetPosition(const Value: TBookMark);
  6212. begin
  6213.   FCurrentPos[2] := Value;
  6214. end;
  6215.  
  6216. function TDCCustomTreeGrid.GetBookmark(KnotItem: TKnotItem): TBookmark;
  6217. begin
  6218.   GetMem(Result, FBookMarkSize);
  6219.   GetBookmarkData(KnotItem, Result)
  6220. end;
  6221.  
  6222. procedure TDCCustomTreeGrid.GetBookmarkData(KnotItem: TKnotItem;
  6223.   Data: Pointer);
  6224. begin
  6225.   StrPLCopy(PChar(Data), IntToStr(KnotItem.KnotID), FBookMarkSize-1);
  6226. end;
  6227.  
  6228. procedure TDCCustomTreeGrid.GotoBookMark(Bookmark: TBookmark);
  6229.  var
  6230.   KnotItem: TKnotItem;
  6231.   Bookmark1: Pointer;
  6232.   FindEqual: boolean;
  6233. begin
  6234.   KnotItem  := FKnots.GetFirstVisibleNode;
  6235.   FindEqual := False;
  6236.   while (KnotItem <> nil) and not FindEqual  do
  6237.   begin
  6238.     Bookmark1 := GetBookmark(KnotItem);
  6239.     try
  6240.       FindEqual := BookmarksEqual(Bookmark1, Bookmark);
  6241.     finally
  6242.       FreeMem(Bookmark1);
  6243.     end;
  6244.     if not FindEqual then
  6245.     begin
  6246.       KnotItem := KnotItem.GetNext;
  6247.     end;
  6248.   end;
  6249.   SelectedKnot := KnotItem
  6250. end;
  6251.  
  6252. function TDCCustomTreeGrid.BookmarksEqual(Bookmark1,
  6253.   Bookmark2: TBookmark): boolean;
  6254. begin
  6255.   Result := StrComp(PChar(Bookmark1), PChar(Bookmark2)) = 0;
  6256. end;
  6257.  
  6258. function TDCCustomTreeGrid.DataVisible: boolean;
  6259. begin
  6260.   Result := (csDesigning in ComponentState) or (((FColumns.Count <> 0) or
  6261.     (TreePathWidth > 0)) {and (Knots.First <> nil)});
  6262. end;
  6263.  
  6264. procedure TDCCustomTreeGrid.WMSetCursor(var Msg: TWMSetCursor);
  6265. begin
  6266.   if not DataVisible then
  6267.     Windows.SetCursor(LoadCursor(0, IDC_ARROW))
  6268.   else
  6269.     inherited;
  6270. end;
  6271.  
  6272. procedure TDCCustomTreeGrid.WMPaint(var Message: TWMPaint);
  6273.  var
  6274.   PS: TPaintStruct;
  6275.   UpdateMessage: string;
  6276.   R, R1: TRect;
  6277.   MessageType: TTreeGridMessageType;
  6278.   Flags: integer;
  6279.   MBitmap, OBitmap: HBITMAP;
  6280.   MDC, DC: HDC;
  6281. begin
  6282.   if FLockScreen or not DataVisible then
  6283.   begin
  6284.     ShowScrollBar(Handle, SB_HORZ, False);
  6285.     ShowScrollBar(Handle, SB_VERT, False);
  6286.     GetWindowRect(Handle, R);  OffsetRect(R, -R.Left, -R.Top); R1 := R;
  6287.     DC := GetDC(0);
  6288.     MBitmap := CreateCompatibleBitmap(DC, R.Right, R.Bottom);
  6289.     ReleaseDC(0, DC);
  6290.     MDC := CreateCompatibleDC(0);
  6291.     OBitmap := SelectObject(MDC, MBitmap);
  6292.  
  6293.     try
  6294.       DC := BeginPaint(Handle, PS);
  6295.       Canvas.Handle := MDC;
  6296.       Canvas.Brush.Color := Self.Color;
  6297.       Canvas.Font := Self.Font;
  6298.  
  6299.       UpdateMessage := '';
  6300.       Flags         := DT_END_ELLIPSIS or DT_CENTER;
  6301.       MessageType   := mtEmptyColumns;
  6302.  
  6303.       if FLockScreen then
  6304.       begin
  6305.         UpdateMessage := LoadStr(RES_STRN_MSG_ONLOAD);
  6306.         MessageType   := mtLoadData;
  6307.       end
  6308.       else begin
  6309.         if not DataVisible then
  6310.         begin
  6311.           UpdateMessage := LoadStr(RES_STRN_MSG_DBGCEM);
  6312.           MessageType   := mtEmptyColumns;
  6313.         end;
  6314.       end;
  6315.  
  6316.       if Assigned(FOnPaintMessage) then
  6317.         FOnPaintMessage(Self, Canvas, R, MessageType, UpdateMessage)
  6318.       else begin
  6319.         Canvas.Lock;
  6320.         Canvas.FillRect(R);
  6321.         InflateRect(R, -5, -5);
  6322.         DrawHighLightText(Canvas, PChar(UpdateMessage), R, 1, Flags or DT_WORDBREAK);
  6323.         Canvas.UnLock;
  6324.         BitBlt(DC, 0, 0, R1.Right, R1.Bottom, MDC, 0, 0, SRCCOPY);
  6325.       end;
  6326.       EndPaint(Handle, PS);
  6327.     finally
  6328.       SelectObject(MDC, OBitmap);
  6329.       DeleteDC(MDC);
  6330.       DeleteObject(MBitmap);
  6331.       Canvas.Handle := 0;
  6332.     end;
  6333.   end
  6334.   else
  6335.    inherited;
  6336. end;
  6337.  
  6338. function TDCCustomTreeGrid.CanEditModify: Boolean;
  6339. begin
  6340.   Result := True;
  6341. end;
  6342.  
  6343. function TDCCustomTreeGrid.GetTreeLableOffset(
  6344.   KnotItem: TKnotItem): integer;
  6345.  var
  6346.   X: integer;
  6347. begin
  6348.   with KnotItem do
  6349.   begin
  6350.     if Indent > 0 then
  6351.       X := (Level+1)*Indent + 4
  6352.     else
  6353.       X := 0;
  6354.  
  6355.     if (Images<>nil) and
  6356.        ((KnotID =  SelectedKnot.KnotID)and(SelectImage>-1) or
  6357.        (KnotID <> SelectedKnot.KnotID)and(NormalImage>-1))
  6358.     then
  6359.       X := X + Images.Width+2;
  6360.  
  6361.     Result := X;
  6362.  
  6363.   end;
  6364. end;
  6365.  
  6366. procedure TDCCustomTreeGrid.WMTimer(var Msg: TWMTimer);
  6367. begin
  6368.   inherited;
  6369.   if (Msg.TimerId = FEditTimerID) then
  6370.   begin
  6371.     FreeEditTimer;
  6372.     if not FEditorMode then ShowTreePathEditor;
  6373.   end
  6374. end;
  6375.  
  6376. procedure TDCCustomTreeGrid.FreeEditTimer;
  6377. begin
  6378.   if FEditTimerID <> -1 then
  6379.   begin
  6380.     KillTimer(Handle, 101);
  6381.     FEditTimerID := -1;
  6382.   end;
  6383. end;
  6384.  
  6385. procedure TDCCustomTreeGrid.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  6386. begin
  6387.   inherited;
  6388.   if (tgEditing in Options) and (Msg.CharCode = VK_RETURN) then Msg.Result := 1;
  6389. end;
  6390.  
  6391. procedure TDCCustomTreeGrid.WMNCCalcSize(var Message: TWMNCCalcSize);
  6392. begin
  6393.   inherited;
  6394.   if (BorderStyle = bsSingle) and (tgFlatButtons in Options) then
  6395.    InflateRect(Message.CalcSize_Params^.rgrc[0], -1, -1);
  6396. end;
  6397.  
  6398. procedure TDCCustomTreeGrid.WMNCPaint(var Message: TMessage);
  6399.  var
  6400.   R, R1: TRect;
  6401.   DC: HDC;
  6402.   ScrollW, ScrollH: integer;
  6403.   Brush: HBRUSH;
  6404.   ScrollInfo: TScrollInfo;
  6405.   IScroll, VScroll, HScroll: boolean;
  6406. begin
  6407.   inherited;
  6408.   if (BorderStyle = bsSingle) and (tgFlatButtons in Options) then
  6409.   begin
  6410.     DC := GetWindowDC(Handle);
  6411.     Brush := CreateSolidBrush(ColorToRGB(clBtnFace));
  6412.     try
  6413.       GetWindowRect(Handle, R);  OffsetRect(R, -R.Left, -R.Top);
  6414.  
  6415.       ScrollInfo.cbSize := SizeOf(ScrollInfo);
  6416.       ScrollInfo.fMask := SIF_ALL;
  6417.       IScroll := GetScrollInfo(Self.Handle, SB_HORZ, ScrollInfo);
  6418.       HScroll := IScroll and (ScrollInfo.nMin <> ScrollInfo.nMax);
  6419.       IScroll := GetScrollInfo(Self.Handle, SB_VERT, ScrollInfo);
  6420.       VScroll := IScroll and (ScrollInfo.nMin <> ScrollInfo.nMax);
  6421.  
  6422.       if DataVisible and HScroll and VScroll then
  6423.       begin
  6424.         ScrollW := GetSystemMetrics(SM_CXVSCROLL);
  6425.         ScrollH := GetSystemMetrics(SM_CYVSCROLL);
  6426.         R1 := Rect(R.Right - ScrollW-1, R.Bottom - ScrollH-1, R.Right-1, R.Bottom-1);
  6427.         FrameRect(DC, R1, Brush);
  6428.       end;
  6429.  
  6430.       DrawEdge(DC, R, BDR_SUNKENOUTER, BF_TOPLEFT);
  6431.       DrawEdge(DC, R, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
  6432.     finally
  6433.       DeleteObject(Brush);
  6434.       ReleaseDC(Handle, DC);
  6435.     end;
  6436.   end;
  6437. end;
  6438.  
  6439. procedure TDCCustomTreeGrid.CreateParams(var Params: TCreateParams);
  6440. begin
  6441.   inherited;
  6442.   if (BorderStyle = bsSingle) and (tgFlatButtons in Options) then
  6443.   with Params do
  6444.   begin
  6445.     if NewStyleControls and Ctl3D then
  6446.       ExStyle := ExStyle and not WS_EX_CLIENTEDGE
  6447.     else
  6448.       Style := Style and not WS_BORDER;
  6449.   end;
  6450. end;
  6451.  
  6452. procedure TDCCustomTreeGrid.DoCollapse(KnotItem: TKnotItem);
  6453. begin
  6454.   if Assigned(FOnCollapsed) then FOnCollapsed(Self, KnotItem);
  6455. end;
  6456.  
  6457. procedure TDCCustomTreeGrid.DoExpand(KnotItem: TKnotItem);
  6458. begin
  6459.   if Assigned(FOnExpanded) then FOnExpanded(Self, KnotItem);
  6460. end;
  6461.  
  6462. function TDCCustomTreeGrid.GetBorderStyle: TEdgeBorderStyle;
  6463. begin
  6464.   if not((tgColLines in Options) and (tgRowLines in Options)) or
  6465.      not(tgFixedLines in Options) then
  6466.     if (tgFlatButtons in Options) and (tgFixedLines in Options) then
  6467.       Result := ebsShadowFlat
  6468.     else
  6469.       Result := ebsNone
  6470.   else begin
  6471.     if (ColorToRGB(Color) = ColorToRGB(FixedColor)) then
  6472.       Result := ebsNone
  6473.     else
  6474.     begin
  6475.       if tgFlatButtons in Options then
  6476.         Result := ebsFlat
  6477.       else
  6478.         Result := ebsNormal;
  6479.     end;
  6480.   end;
  6481. end;
  6482.  
  6483. function TDCCustomTreeGrid.FlatButtons: boolean;
  6484. begin
  6485.   Result := tgFlatButtons in Options;
  6486. end;
  6487.  
  6488. procedure TDCCustomTreeGrid.Update;
  6489. begin
  6490.   if not UpdateLocked then inherited;
  6491.   if FLockWindow then FLockScroll := True;
  6492. end;
  6493.  
  6494. procedure TDCCustomTreeGrid.DoColumnClick(Shift: TShiftState;
  6495.   ColIndex: integer);
  6496.  var
  6497.   i: integer;
  6498. begin
  6499.   inherited;
  6500.   if (RawToDataColumn(ColIndex) < Columns.Count) then
  6501.   begin
  6502.     if (kcIndexed in Columns[RawToDataColumn(ColIndex)].Options) then
  6503.     for i := 0 to Columns.Count-1 do
  6504.     begin
  6505.       if i = RawToDataColumn(ColIndex) then
  6506.       begin
  6507.         if Columns[i].IndexStyle < High(TColumnIndexStyle)
  6508.           then Columns[i].IndexStyle := Succ(Columns[i].IndexStyle)
  6509.           else Columns[i].IndexStyle := Pred(Columns[i].IndexStyle);
  6510.         InvalidateCell(DataToRawColumn(i),0);
  6511.       end
  6512.       else
  6513.         if not(ssShift in Shift) then
  6514.         begin
  6515.           if (kcIndexed in Columns[i].Options) and
  6516.              (Columns[i].IndexStyle <> Low(TColumnIndexStyle))
  6517.           then begin
  6518.             Columns[i].IndexStyle := Low(TColumnIndexStyle);
  6519.             InvalidateCell(DataToRawColumn(i),0);
  6520.           end;
  6521.         end;
  6522.     end;
  6523.     TitleClick(Columns[RawToDataColumn(ColIndex)])
  6524.   end;
  6525. end;
  6526.  
  6527. function TDCCustomTreeGrid.GroupingEnabled: boolean;
  6528. begin
  6529.   Result := tgGrouping in Options; 
  6530. end;
  6531.  
  6532. function TDCCustomTreeGrid.GetClientRect: TRect;
  6533. begin
  6534.   if FLockScroll then
  6535.   begin
  6536.     if not DoubleBuffered and ((tgTreePathCompletion) in Options) then
  6537.       SetRectEmpty(Result)
  6538.     else
  6539.       Result := GetGridBounds;
  6540.   end
  6541.   else
  6542.     Result := inherited GetClientRect;
  6543. end;
  6544.  
  6545. procedure TDCCustomTreeGrid.GroupBoxChanged;
  6546. begin
  6547.   inherited;
  6548.   if GroupingEnabled then
  6549.   begin
  6550.     if GroupBox.Count = 0 then
  6551.       Options := Options - [tgTreePath]
  6552.     else begin
  6553.       Options := Options + [tgTreePath];
  6554.       TreePathWidth := 1;
  6555.     end;
  6556.   end;
  6557. end;
  6558.  
  6559. function TDCCustomTreeGrid.GetRealColWidth(ColIndex: integer): integer;
  6560. begin
  6561.   Result := Columns[RawToDataColumn(ColIndex)].ActualWidth;
  6562. end;
  6563.  
  6564. function TDCCustomTreeGrid.CalcMaxTopLeft(const Coord: TGridCoord;
  6565.   const DrawInfo: TGridDrawInfo): TGridCoord;
  6566.  
  6567.   function CalcMaxCell(const Axis: TGridAxisDrawInfo; Start: Integer): Integer;
  6568.   var
  6569.     Line: Integer;
  6570.     I, Extent: Longint;
  6571.   begin
  6572.     Result := Start;
  6573.     with Axis do
  6574.     begin
  6575.       Line := GridExtent + EffectiveLineWidth;
  6576.       for I := Start downto FixedCellCount do
  6577.       begin
  6578.         Extent := GetExtent(I);
  6579.         if Extent > 0 then
  6580.         begin
  6581.           Dec(Line, Extent);
  6582.           Dec(Line, EffectiveLineWidth);
  6583.           if Line < FixedBoundary then
  6584.           begin
  6585.             if (Result = Start) and (GetExtent(Start) <= 0) then
  6586.               Result := I;
  6587.             Break;
  6588.           end;
  6589.           Result := I;
  6590.         end;
  6591.       end;
  6592.     end;
  6593.   end;
  6594.  
  6595. begin
  6596.   Result.X := CalcMaxCell(DrawInfo.Horz, Coord.X);
  6597.   Result.Y := CalcMaxCell(DrawInfo.Vert, Coord.Y);
  6598. end;
  6599.  
  6600. function TDCCustomTreeGrid.CanModifyHScrollBar(ScrollBar, ScrollCode,
  6601.   Pos: Cardinal; UseRightToLeft: Boolean; var NewLeft: integer): boolean;
  6602. var
  6603.   NewTopLeft, MaxTopLeft: TGridCoord;
  6604.   DrawInfo: TGridDrawInfo;
  6605.   RTLFactor: Integer;
  6606.  
  6607.   function Min: Longint;
  6608.   begin
  6609.     if ScrollBar = SB_HORZ then Result := FixedCols
  6610.     else Result := FixedRows;
  6611.   end;
  6612.  
  6613.   function Max: Longint;
  6614.   begin
  6615.     if ScrollBar = SB_HORZ then Result := MaxTopLeft.X
  6616.     else Result := MaxTopLeft.Y;
  6617.   end;
  6618.  
  6619.   function PageUp: Longint;
  6620.   var
  6621.     MaxTopLeft: TGridCoord;
  6622.   begin
  6623.     MaxTopLeft := CalcMaxTopLeft(GetTopLeft, DrawInfo);
  6624.     if ScrollBar = SB_HORZ then
  6625.       Result := LeftCol - MaxTopLeft.X else
  6626.       Result := TopRow - MaxTopLeft.Y;
  6627.     if Result < 1 then Result := 1;
  6628.   end;
  6629.  
  6630.   function PageDown: Longint;
  6631.   var
  6632.     DrawInfo: TGridDrawInfo;
  6633.   begin
  6634.     CalcDrawInfo(DrawInfo);
  6635.     with DrawInfo do
  6636.       if ScrollBar = SB_HORZ then
  6637.         Result := Horz.LastFullVisibleCell - LeftCol else
  6638.         Result := Vert.LastFullVisibleCell - TopRow;
  6639.     if Result < 1 then Result := 1;
  6640.   end;
  6641.  
  6642.   function CalcScrollBar(Value, ARTLFactor: Longint): Longint;
  6643.   begin
  6644.     Result := Value;
  6645.     case ScrollCode of
  6646.       SB_LINEUP:
  6647.         Dec(Result, ARTLFactor);
  6648.       SB_LINEDOWN:
  6649.         Inc(Result, ARTLFactor);
  6650.       SB_PAGEUP:
  6651.         Dec(Result, PageUp * ARTLFactor);
  6652.       SB_PAGEDOWN:
  6653.         Inc(Result, PageDown * ARTLFactor);
  6654.       SB_THUMBPOSITION, SB_THUMBTRACK:
  6655.         if (goThumbTracking in  inherited Options) or (ScrollCode = SB_THUMBPOSITION) then
  6656.         begin
  6657.           if (not UseRightToLeftAlignment) or (ARTLFactor = 1) then
  6658.             Result := Min + LongMulDiv(Pos, Max - Min, MaxShortInt)
  6659.           else
  6660.             Result := Max - LongMulDiv(Pos, Max - Min, MaxShortInt);
  6661.         end;
  6662.       SB_BOTTOM:
  6663.         Result := Max;
  6664.       SB_TOP:
  6665.         Result := Min;
  6666.     end;
  6667.   end;
  6668.  
  6669. var
  6670.   Temp: Longint;
  6671. begin
  6672.   Result := False;
  6673.   if (not UseRightToLeftAlignment) or (not UseRightToLeft) then
  6674.     RTLFactor := 1
  6675.   else
  6676.     RTLFactor := -1;
  6677.  
  6678.   CalcDrawInfo(DrawInfo);
  6679.   if ColCount = 1 then
  6680.   begin
  6681.     Result  := True;
  6682.     NewLeft := -1;
  6683.     Exit;
  6684.   end;
  6685.  
  6686.   MaxTopLeft.X := ColCount - 1;
  6687.   MaxTopLeft.Y := RowCount - 1;
  6688.   MaxTopLeft := CalcMaxTopLeft(MaxTopLeft, DrawInfo);
  6689.   NewTopLeft := GetTopLeft;
  6690.  
  6691.   repeat
  6692.     Temp := NewTopLeft.X;
  6693.     NewTopLeft.X := CalcScrollBar(NewTopLeft.X, RTLFactor);
  6694.   until (NewTopLeft.X <= FixedCols) or (NewTopLeft.X >= MaxTopLeft.X)
  6695.      or (ColWidths[NewTopLeft.X] > 0) or (Temp = NewTopLeft.X);
  6696.  
  6697.   NewTopLeft.X := _intMax(FixedCols, _intMin(MaxTopLeft.X, NewTopLeft.X));
  6698.   NewTopLeft.Y := _intMax(FixedRows, _intMin(MaxTopLeft.Y, NewTopLeft.Y));
  6699.  
  6700.   if (NewTopLeft.X <> LeftCol) or (NewTopLeft.Y <> TopRow) then
  6701.   begin
  6702.     Result  := True;
  6703.     NewLeft := NewTopLeft.X;
  6704.   end;
  6705.  
  6706. end;
  6707.  
  6708. function TDCCustomTreeGrid.GetTopLeft: TGridCoord;
  6709. begin
  6710.   Result.X := LeftCol;
  6711.   Result.Y := TopRow;
  6712. end;
  6713.  
  6714. procedure SortKnots(Sender: TObject; Knots: TKnotItems; KnotItem: TKnotItem; L, R: Integer;
  6715.   SortCompare: TGridSortCompare; Data: integer);
  6716. var
  6717.   I, J, K: Integer;
  6718.   P: Pointer;
  6719.   AKnotItem: TKnotItem;
  6720. begin
  6721.   repeat
  6722.     I := L;
  6723.     J := R;
  6724.     K := (L + R) shr 1;
  6725.     P := KnotItem.Childs[K];
  6726.     repeat
  6727.       while SortCompare(Sender, KnotItem.Childs[I], P, Data) < 0 do Inc(I);
  6728.       while SortCompare(Sender, KnotItem.Childs[J], P, Data) > 0 do Dec(J);
  6729.       if I <= J then
  6730.       begin
  6731.         if (I <> J) and
  6732.            (SortCompare(Sender, KnotItem.Childs[I], KnotItem.Childs[J], Data) <> 0) then
  6733.         begin
  6734.           AKnotItem := KnotItem.Childs[I];
  6735.           KnotItem.Childs[I] := KnotItem.Childs[J];
  6736.           KnotItem.Childs[J] := AKnotItem;
  6737.           Knots.RebuildIndexes(KnotItem, i);
  6738.         end;
  6739.         Inc(I);
  6740.         Dec(J);
  6741.       end;
  6742.     until I > J;
  6743.     if L < J then SortKnots(Sender, Knots, KnotItem, L, J, SortCompare, Data);
  6744.     L := I;
  6745.   until I >= R;
  6746. end;
  6747.  
  6748. procedure TDCCustomTreeGrid.Sort(Level: integer; Compare: TGridSortCompare; Data: integer);
  6749.  var
  6750.   KnotItem: TKnotItem;
  6751.  
  6752.   procedure SortLevel(Parent: TKnotItem; Level: integer; Compare: TGridSortCompare);
  6753.    var
  6754.     KnotItem: TKnotItem;
  6755.     iCount: integer;
  6756.   begin
  6757.     if (Parent = nil) or (Parent.ChildCount = 0) then Exit;
  6758.     if Parent.Level = Level -1 then
  6759.     begin
  6760.       iCount := Parent.ChildCount - 1;
  6761.       if iCount > 0 then with Knots do
  6762.       begin
  6763.         LockRebuilds(Parent, True);
  6764.         SortKnots(Self, Knots, Parent, 0, iCount, Compare, Data);
  6765.         LockRebuilds(Parent, False);
  6766.       end;
  6767.     end
  6768.     else begin
  6769.       KnotItem := Parent.Childs[0];
  6770.       iCount   := Parent.ChildCount;
  6771.       while KnotItem <> nil do
  6772.       begin
  6773.         SortLevel(KnotItem, Level, Compare);
  6774.         if KnotItem.Index < iCount - 1 then
  6775.           KnotItem := Parent.Childs[KnotItem.Index + 1]
  6776.         else
  6777.           KnotItem := nil;
  6778.       end;
  6779.     end;
  6780.   end;
  6781.  
  6782. begin
  6783.   if (Knots <> nil) then
  6784.   begin
  6785.     KnotItem := SelectedKnot;
  6786.     Knots.BeginUpdate;
  6787.     SortLevel(Knots.Root, Level, Compare);
  6788.     InitGridPos;
  6789.     Knots.EndUpdate;
  6790.     SelectedKnot := KnotItem;
  6791.   end;
  6792. end;
  6793.  
  6794. function TDCCustomTreeGrid.CanColResize(ACol: integer): boolean;
  6795.  var
  6796.   i: integer;
  6797.   CellType: TFixedCell;
  6798. begin
  6799.   CellType := GetFixedCellType(ACol, 0);
  6800.   case CellType of
  6801.     fcColumn:
  6802.       begin
  6803.         i := RawToDataColumn(ACol);
  6804.         if (i < Columns.Count) and (i > -1) then
  6805.           Result := (kcVisible in Columns[i].Options) and
  6806.             ((csDesigning in ComponentState) or (kcSizing in Columns[i].Options))
  6807.         else
  6808.           Result := True;
  6809.       end;
  6810.     fcTreePath:
  6811.       Result := ([tgTreePath, tgTreePathResize] * Options = [tgTreePath, tgTreePathResize]) and
  6812.         not(GroupingEnabled and (GroupBox.Count > 0));
  6813.     else
  6814.       Result := inherited CanColResize(ACol);     
  6815.   end;
  6816. end;
  6817.  
  6818. procedure TDCCustomTreeGrid.ResizeColWidth(ACol, AWidth: integer);
  6819.  var
  6820.   CellType: TFixedCell;
  6821. begin
  6822.   CellType := GetFixedCellType(ACol, 0);
  6823.   case CellType of
  6824.     fcColumn:
  6825.       inherited;
  6826.     fcTreePath:
  6827.       TreepathWidth := AWidth;
  6828.   end;
  6829. end;
  6830.  
  6831. procedure TDCCustomTreeGrid.SelectItems(Mode: TSelectMode);
  6832. begin
  6833.   Knots.BeginUpdate;
  6834.   case Mode of
  6835.     smSelect: FBookmarks.SelectAll;
  6836.     smDeselect: FBookmarks.Clear;
  6837.   end;
  6838.   Knots.EndUpdate;
  6839. end;
  6840.  
  6841. procedure TDCCustomTreeGrid.SetOptionsEx(const Value: TTreeGridOptionsEx);
  6842.  var
  6843.   ChangedOptions: TTreeGridOptionsEx;
  6844. begin
  6845.   if FOptionsEx <> Value then
  6846.   begin
  6847.     ChangedOptions := (FOptionsEx + Value) - (FOptionsEx * Value);
  6848.     FOptionsEx := Value;
  6849.     if [tgeMarkerMenu, tgeShadowSelection, tgeShowLines, tgeShowButtons,
  6850.         tgeTreeSelect] *  ChangedOptions  <> [] then
  6851.     begin
  6852.       invalidate;
  6853.     end;
  6854.  
  6855.   end;
  6856. end;
  6857.  
  6858. procedure TDCCustomTreeGrid.SetIndent(const Value: integer);
  6859. begin
  6860.   if FIndent <> Value then
  6861.   begin
  6862.     FIndent := _intMax(FTreeImages.Width + 2, Value);
  6863.     invalidate;
  6864.   end;
  6865. end;
  6866.  
  6867. function TDCCustomTreeGrid.CreateColumns: TKnotColumns;
  6868. begin
  6869.   Result := TKnotColumns.Create(Self, TKnotColumn);
  6870. end;
  6871.  
  6872. procedure TDCCustomTreeGrid.InitGridPos;
  6873. begin
  6874.   FFirstIndex   := 0;
  6875.   FFirstVisible := Knots.GetFirstVisibleNode;
  6876.   FSelectedKnot := FFirstVisible;
  6877. end;
  6878.  
  6879. procedure TDCCustomTreeGrid.SetColumnFooter(
  6880.   const Value: TKnotColumnFooter);
  6881. begin
  6882.   FColumnFooter.Assign(Value);
  6883. end;
  6884.  
  6885. function TDCCustomTreeGrid.GetCellByType(ACellType: TFixedCell): integer;
  6886.  type
  6887.    AFixedCells = fcIndicator..fcTreePath;
  6888.  const
  6889.   ATypes: array[AFixedCells] of TTreeGridOption = (tgIndicator, tgMarker, tgTreePath);
  6890.  var
  6891.   j: TFixedCell;
  6892. begin
  6893.   Result := -1;
  6894.   for j := Low(ATypes) to High(ATypes) do
  6895.   begin
  6896.     if ATypes[j] in Options then Inc(Result);
  6897.     if ACellType = j then Break;
  6898.   end;
  6899. end;
  6900.  
  6901. procedure TDCCustomTreeGrid.DoSelection(Select: Boolean; Shift: TShiftState;
  6902.   Direction: Integer);
  6903. var
  6904.   AddAfter: Boolean;
  6905. begin
  6906.   AddAfter := False;
  6907.   BeginUpdate;
  6908.   try
  6909.     if (tgMultiSelect in Options) and (FKnots.Count > 0) then
  6910.       if Select and (ssShift in Shift) then
  6911.       begin
  6912.         if not FSelecting then
  6913.         begin
  6914.           FSelectionKnot := FSelectedKnot;
  6915.           FBookmarks.Select(FSelectedKnot, True);
  6916.           FSelecting := True;
  6917.           AddAfter := True;
  6918.         end
  6919.         else
  6920.         with FBookmarks do
  6921.         begin
  6922.           AddAfter := Compare(FSelectedKnot.KnotID, FSelectionKnot.KnotID) <> -Direction;
  6923.           if not AddAfter then Select(FSelectedKnot, False);
  6924.         end
  6925.       end
  6926.       else
  6927.         ClearSelection;
  6928.     if AddAfter then FBookmarks.Select(FSelectedKnot, True);
  6929.   finally
  6930.     EndUpdate;
  6931.   end;
  6932. end;
  6933.  
  6934. function TDCCustomTreeGrid.AlwaysShowSelection: boolean;
  6935. begin
  6936.   Result := (tgAlwaysShowSelection in Options) or
  6937.     ((tgMultiSelect in Options) and (FBookmarks.Count > 0));
  6938. end;
  6939.  
  6940. function TDCCustomTreeGrid.CreateKnots: TKnotItems;
  6941. begin
  6942.   Result := TKnotItems.Create(Self, TKnotItem);
  6943. end;
  6944.  
  6945. function TDCCustomTreeGrid.GetKnots: TKnotItems;
  6946. begin
  6947.   Result := FKnots;
  6948. end;
  6949.  
  6950. procedure TDCCustomTreeGrid.SetTreePath(const Value: TTreePath);
  6951. begin
  6952.   FTreePath.Assign(Value);
  6953. end;
  6954.  
  6955. { TKnotBookmarkList }
  6956.  
  6957. procedure TKnotBookmarkList.Clear;
  6958. begin
  6959.   if FList.Count = 0 then Exit;
  6960.   FList.Clear;
  6961.   FGrid.Invalidate;
  6962. end;
  6963.  
  6964. function TKnotBookmarkList.Compare(const KnotID1,
  6965.   KnotID2: integer): Integer;
  6966. begin
  6967.   if KnotID1 = KnotID2 then Result := 0
  6968.   else
  6969.    if KnotID1 > KnotID2 then Result := 1
  6970.    else
  6971.      Result := -1;
  6972. end;
  6973.  
  6974. constructor TKnotBookmarkList.Create(AGrid: TDCCustomTreeGrid);
  6975. begin
  6976.   inherited Create;
  6977.   FList := TList.Create;
  6978.   FGrid := AGrid;
  6979.   FSortItems := True;
  6980.   ListChanged;
  6981. end;
  6982.  
  6983. procedure TKnotBookmarkList.Delete;
  6984. var
  6985.   I: Integer;
  6986. begin
  6987.   with FGrid.FKnots do
  6988.   begin
  6989.     BeginUpdate;
  6990.     try
  6991.       I := FList.Count - 1;
  6992.       while (I >= 0) and (FList.Count > 0) do
  6993.       begin
  6994.         Delete(TKnotItem(FList.Items[I]));
  6995.         Dec(I);
  6996.       end;
  6997.     finally
  6998.       EndUpdate;
  6999.     end;
  7000.   end;
  7001. end;
  7002.  
  7003. destructor TKnotBookmarkList.Destroy;
  7004. begin
  7005.   Clear;
  7006.   FList.Free;
  7007.   inherited Destroy;
  7008. end;
  7009.  
  7010. function TKnotBookmarkList.Find(const KnotID: integer;
  7011.   var Index: Integer): Boolean;
  7012. var
  7013.   L, H, I, C: Integer;
  7014. begin
  7015.   if (KnotID = FCache) and (FCacheIndex >= 0) then
  7016.   begin
  7017.     Index  := FCacheIndex;
  7018.     Result := FCacheFind;
  7019.     Exit;
  7020.   end;
  7021.   Result := False;
  7022.   L := 0;
  7023.   H := FList.Count - 1;
  7024.   while L <= H do
  7025.   begin
  7026.     I := (L + H) shr 1;
  7027.     C := Compare(TKnotItem(FList[I]).KnotID, KnotID);
  7028.     if C < 0 then L := I + 1 else
  7029.     begin
  7030.       H := I - 1;
  7031.       if C = 0 then
  7032.       begin
  7033.         Result := True;
  7034.         L := I;
  7035.       end;
  7036.     end;
  7037.   end;
  7038.   Index       := L;
  7039.   FCache      := KnotID;
  7040.   FCacheIndex := Index;
  7041.   FCacheFind  := Result;
  7042. end;
  7043.  
  7044. function TKnotBookmarkList.GetCount: integer;
  7045. begin
  7046.   Result := FList.Count;
  7047. end;
  7048.  
  7049. function TKnotBookmarkList.GetItem(Index: Integer): integer;
  7050. begin
  7051.   Result := Integer(FList[Index]^);
  7052. end;
  7053.  
  7054. function TKnotBookmarkList.IndexOf(const KnotID: integer): Integer;
  7055. begin
  7056.   if not Find(KnotID, Result) then Result := -1;
  7057. end;
  7058.  
  7059. function TKnotBookmarkList.KnotSelected(const KnotID: integer): Boolean;
  7060.  var
  7061.   Index: integer;
  7062. begin
  7063.   Result := Find(KnotID, Index);
  7064. end;
  7065.  
  7066. procedure TKnotBookmarkList.ListChanged;
  7067. begin
  7068.   FCache      := -1;
  7069.   FCacheIndex := -1;
  7070. end;
  7071.  
  7072. function CompareKnotID(Item1, Item2: Pointer): Integer;
  7073. begin
  7074.   if TknotItem(Item1).KnotID = TknotItem(Item2).KnotID then Result := 0
  7075.   else
  7076.    if TknotItem(Item1).KnotID > TknotItem(Item2).KnotID then Result := 1
  7077.    else
  7078.      Result := -1;
  7079. end;
  7080.  
  7081. procedure TKnotBookmarkList.Select(KnotItem: TKnotItem; Value: boolean);
  7082.  var
  7083.   Index: integer;
  7084. begin
  7085.   if (Find(KnotItem.KnotID, Index) = Value) or (FGrid.FKnots.State = ksInsert) then Exit;
  7086.   if Value then
  7087.   begin
  7088.     FList.Add(KnotItem);
  7089.     if FSortItems then Sort;
  7090.   end
  7091.   else begin
  7092.     FList.Delete(Index);
  7093.   end;
  7094.   ListChanged;
  7095.   if not FGrid.Knots.Updating then FGrid.InvalidateRow(FGrid.Row);
  7096. end;
  7097.  
  7098. { TDCInplaceEdit }
  7099.  
  7100. procedure TDCInplaceChoiceEdit.ChoiceClick(Sender: TObject);
  7101. begin
  7102.   Grid.SetModified(True);
  7103.   inherited;
  7104. end;
  7105.  
  7106. procedure TDCInplaceChoiceEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  7107. begin
  7108.   inherited;
  7109.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7110. end;
  7111.  
  7112. function TDCInplaceChoiceEdit.DoMouseWheel(Shift: TShiftState;
  7113.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7114. begin
  7115.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7116. end;
  7117.  
  7118. procedure TDCInplaceChoiceEdit.KeyDown(var Key: Word; Shift: TShiftState);
  7119. begin
  7120.   if Key > $20 then HideErrorMessage;
  7121.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7122.   if Key <> 0 then
  7123.   begin
  7124.     if not ReadOnly then Grid.SetModified(True);
  7125.     inherited KeyDown(Key, Shift);
  7126.   end;
  7127. end;
  7128.  
  7129. procedure TDCInplaceChoiceEdit.KeyPress(var Key: Char);
  7130. begin
  7131.   if not DropDownVisible then Grid.KeyPress(Key);
  7132.   if Key <> #0 then
  7133.   begin
  7134.     if not(Key in [#27, #8, #0]) then
  7135.       if not ReadOnly then Grid.SetModified(True);
  7136.     inherited KeyPress(Key);
  7137.   end;
  7138. end;
  7139.  
  7140. procedure TDCInplaceChoiceEdit.KeyUp(var Key: Word; Shift: TShiftState);
  7141. begin
  7142.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7143.   if Key <> 0 then
  7144.     inherited KeyUp(Key, Shift);
  7145. end;
  7146.  
  7147. procedure TDCInplaceChoiceEdit.SetGrid(Value: TDCCustomTreeGrid);
  7148. begin
  7149.   FGrid := Value;
  7150. end;
  7151.  
  7152. procedure TDCInplaceChoiceEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  7153. begin
  7154.   inherited;
  7155.   if tgTabs in Grid.Options then
  7156.     Message.Result := Message.Result or DLGC_WANTTAB;
  7157. end;
  7158.  
  7159. procedure TKnotBookmarkList.SelectAll;
  7160.  var
  7161.   KnotItem: TKnotItem;
  7162. begin
  7163.   try
  7164.     FList.Clear;
  7165.     KnotItem := FGrid.Knots.GetFirstVisibleNode;
  7166.     while KnotItem <> nil do
  7167.     begin
  7168.       FList.Add(KnotItem);
  7169.       KnotItem := KnotItem.GetNextVisible;
  7170.     end;
  7171.     Sort;
  7172.   finally
  7173.     InvalidateRect(FGrid.Handle, nil, False);
  7174.   end;
  7175. end;
  7176.  
  7177. procedure TKnotBookmarkList.Sort;
  7178. begin
  7179.   FList.Sort(CompareKnotID);
  7180. end;
  7181.  
  7182. { TDCInplaceDateEdit }
  7183.  
  7184. procedure TDCInplaceDateEdit.ChoiceClick(Sender: TObject);
  7185. begin
  7186.   Grid.SetModified(True);
  7187.   inherited;
  7188. end;
  7189.  
  7190. procedure TDCInplaceDateEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  7191. begin
  7192.   inherited;
  7193.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7194. end;
  7195.  
  7196. function TDCInplaceDateEdit.DoMouseWheel(Shift: TShiftState;
  7197.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7198. begin
  7199.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7200. end;
  7201.  
  7202. procedure TDCInplaceDateEdit.KeyDown(var Key: Word; Shift: TShiftState);
  7203. begin
  7204.   if Key > $20 then HideErrorMessage;
  7205.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7206.   if Key <> 0 then
  7207.   begin
  7208.     if not ReadOnly then Grid.SetModified(True);
  7209.     inherited KeyDown(Key, Shift);
  7210.   end;
  7211. end;
  7212.  
  7213. procedure TDCInplaceDateEdit.KeyPress(var Key: Char);
  7214. begin
  7215.   if not DropDownVisible or (PerformCloseUp and (Key = Char(VK_RETURN))) then Grid.KeyPress(Key);
  7216.   if Key <> #0 then
  7217.   begin
  7218.     if not(Key in [#27, #8, #0]) then
  7219.       if not ReadOnly then Grid.SetModified(True);
  7220.     inherited KeyPress(Key);
  7221.   end;
  7222. end;
  7223.  
  7224. procedure TDCInplaceDateEdit.KeyUp(var Key: Word; Shift: TShiftState);
  7225. begin
  7226.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7227.   if Key <> 0 then
  7228.     inherited KeyUp(Key, Shift);
  7229. end;
  7230.  
  7231. procedure TDCInplaceDateEdit.SetGrid(Value: TDCCustomTreeGrid);
  7232. begin
  7233.   FGrid := Value;
  7234. end;
  7235.  
  7236. procedure TDCInplaceDateEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  7237. begin
  7238.   inherited;
  7239.   if tgTabs in Grid.Options then
  7240.     Message.Result := Message.Result or DLGC_WANTTAB;
  7241. end;
  7242.  
  7243. { TDCInplaceGridEdit }
  7244.  
  7245. procedure TDCInplaceGridEdit.ChoiceClick(Sender: TObject);
  7246. begin
  7247.   Grid.SetModified(True);
  7248.   inherited;
  7249. end;
  7250.  
  7251. procedure TDCInplaceGridEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  7252. begin
  7253.   inherited;
  7254.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7255. end;
  7256.  
  7257. function TDCInplaceGridEdit.DoMouseWheel(Shift: TShiftState;
  7258.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7259. begin
  7260.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7261. end;
  7262.  
  7263. procedure TDCInplaceGridEdit.KeyDown(var Key: Word; Shift: TShiftState);
  7264. begin
  7265.   if Key > $20 then HideErrorMessage;
  7266.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7267.   if Key <> 0 then
  7268.   begin
  7269.     if not ReadOnly then Grid.SetModified(True);
  7270.     inherited KeyDown(Key, Shift);
  7271.   end;
  7272. end;
  7273.  
  7274. procedure TDCInplaceGridEdit.KeyPress(var Key: Char);
  7275. begin
  7276.   if not DropDownVisible or (PerformCloseUp and (Key = Char(VK_RETURN))) then Grid.KeyPress(Key);
  7277.   if Key <> #0 then
  7278.   begin
  7279.     if not(Key in [#27, #8, #0]) then
  7280.       if not ReadOnly then Grid.SetModified(True);
  7281.     inherited KeyPress(Key);
  7282.   end;
  7283. end;
  7284.  
  7285. procedure TDCInplaceGridEdit.KeyUp(var Key: Word; Shift: TShiftState);
  7286. begin
  7287.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7288.   if Key <> 0 then
  7289.     inherited KeyUp(Key, Shift);
  7290. end;
  7291.  
  7292. procedure TDCInplaceGridEdit.SetGrid(Value: TDCCustomTreeGrid);
  7293. begin
  7294.   FGrid := Value;
  7295. end;
  7296.  
  7297. procedure TDCInplaceGridEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  7298. begin
  7299.   inherited;
  7300.   if tgTabs in Grid.Options then
  7301.     Message.Result := Message.Result or DLGC_WANTTAB;
  7302. end;
  7303.  
  7304. { TDCInplaceTreeEdit }
  7305.  
  7306. procedure TDCInplaceTreeEdit.ChoiceClick(Sender: TObject);
  7307. begin
  7308.   Grid.SetModified(True);
  7309.   inherited;
  7310. end;
  7311.  
  7312. procedure TDCInplaceTreeEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  7313. begin
  7314.   inherited;
  7315.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7316. end;
  7317.  
  7318. function TDCInplaceTreeEdit.DoMouseWheel(Shift: TShiftState;
  7319.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7320. begin
  7321.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7322. end;
  7323.  
  7324. procedure TDCInplaceTreeEdit.KeyDown(var Key: Word; Shift: TShiftState);
  7325. begin
  7326.   if Key > $20 then HideErrorMessage;
  7327.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7328.   if Key <> 0 then
  7329.   begin
  7330.     if not ReadOnly then Grid.SetModified(True);
  7331.     inherited KeyDown(Key, Shift);
  7332.   end;
  7333. end;
  7334.  
  7335. procedure TDCInplaceTreeEdit.KeyPress(var Key: Char);
  7336. begin
  7337.   if not DropDownVisible or (PerformCloseUp and (Key = Char(VK_RETURN))) then Grid.KeyPress(Key);
  7338.   if Key <> #0 then
  7339.   begin
  7340.     if not(Key in [#27, #8, #0]) then
  7341.       if not ReadOnly then Grid.SetModified(True);
  7342.     inherited KeyPress(Key);
  7343.   end;
  7344. end;
  7345.  
  7346. procedure TDCInplaceTreeEdit.KeyUp(var Key: Word; Shift: TShiftState);
  7347. begin
  7348.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7349.   if Key <> 0 then
  7350.     inherited KeyUp(Key, Shift);
  7351. end;
  7352.  
  7353. procedure TDCInplaceTreeEdit.SetGrid(Value: TDCCustomTreeGrid);
  7354. begin
  7355.   FGrid := Value;
  7356. end;
  7357.  
  7358. procedure TDCInplaceTreeEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  7359. begin
  7360.   inherited;
  7361.   if tgTabs in Grid.Options then
  7362.     Message.Result := Message.Result or DLGC_WANTTAB;
  7363. end;
  7364.  
  7365. { TDCInplaceComboBox }
  7366.  
  7367. procedure TDCInplaceComboBox.ChoiceClick(Sender: TObject);
  7368. begin
  7369.   Grid.SetModified(True);
  7370.   inherited;
  7371. end;
  7372.  
  7373. procedure TDCInplaceComboBox.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  7374. begin
  7375.   inherited;
  7376.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7377. end;
  7378.  
  7379. function TDCInplaceComboBox.DoMouseWheel(Shift: TShiftState;
  7380.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7381. begin
  7382.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7383. end;
  7384.  
  7385. procedure TDCInplaceComboBox.KeyDown(var Key: Word; Shift: TShiftState);
  7386. begin
  7387.   if Key > $20 then HideErrorMessage;
  7388.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7389.   if Key <> 0 then
  7390.   begin
  7391.     if not ReadOnly then Grid.SetModified(True);
  7392.     inherited KeyDown(Key, Shift);
  7393.   end;
  7394. end;
  7395.  
  7396. procedure TDCInplaceComboBox.KeyPress(var Key: Char);
  7397. begin
  7398.   if not DropDownVisible or (PerformCloseUp and (Key = Char(VK_RETURN))) then Grid.KeyPress(Key);
  7399.   if Key <> #0 then
  7400.   begin
  7401.     if not(Key in [#27, #8, #0]) then
  7402.       if not ReadOnly then Grid.SetModified(True);
  7403.     inherited KeyPress(Key);
  7404.   end;
  7405. end;
  7406.  
  7407. procedure TDCInplaceComboBox.KeyUp(var Key: Word; Shift: TShiftState);
  7408. begin
  7409.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7410.   if Key <> 0 then
  7411.     inherited KeyUp(Key, Shift);
  7412. end;
  7413.  
  7414. procedure TDCInplaceComboBox.SetGrid(Value: TDCCustomTreeGrid);
  7415. begin
  7416.   FGrid := Value;
  7417. end;
  7418.  
  7419. procedure TDCInplaceComboBox.WMGetDlgCode(var Message: TWMGetDlgCode);
  7420. begin
  7421.   inherited;
  7422.   if tgTabs in Grid.Options then
  7423.     Message.Result := Message.Result or DLGC_WANTTAB;
  7424. end;
  7425.  
  7426. { TDCInplaceFloatEdit }
  7427.  
  7428. procedure TDCInplaceFloatEdit.ChoiceClick(Sender: TObject);
  7429. begin
  7430.   Grid.SetModified(True);
  7431.   inherited;
  7432. end;
  7433.  
  7434. procedure TDCInplaceFloatEdit.CMWantSpecialKey(var Msg: TCMWantSpecialKey);
  7435. begin
  7436.   inherited;
  7437.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7438. end;
  7439.  
  7440. function TDCInplaceFloatEdit.DoMouseWheel(Shift: TShiftState;
  7441.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7442. begin
  7443.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7444. end;
  7445.  
  7446. procedure TDCInplaceFloatEdit.KeyDown(var Key: Word; Shift: TShiftState);
  7447. begin
  7448.   if Key > $20 then HideErrorMessage;
  7449.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7450.   if Key <> 0 then
  7451.   begin
  7452.     if not ReadOnly then Grid.SetModified(True);
  7453.     inherited KeyDown(Key, Shift);
  7454.   end;
  7455. end;
  7456.  
  7457. procedure TDCInplaceFloatEdit.KeyPress(var Key: Char);
  7458. begin
  7459.   if not DropDownVisible or (PerformCloseUp and (Key = Char(VK_RETURN))) then Grid.KeyPress(Key);
  7460.   if Key <> #0 then
  7461.   begin
  7462.     if not(Key in [#27, #8, #0]) then
  7463.       if not ReadOnly then Grid.SetModified(True);
  7464.     inherited KeyPress(Key);
  7465.   end;
  7466. end;
  7467.  
  7468. procedure TDCInplaceFloatEdit.KeyUp(var Key: Word; Shift: TShiftState);
  7469. begin
  7470.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7471.   if Key <> 0 then
  7472.     inherited KeyUp(Key, Shift);
  7473. end;
  7474.  
  7475. procedure TDCInplaceFloatEdit.SetGrid(Value: TDCCustomTreeGrid);
  7476. begin
  7477.   FGrid := Value;
  7478. end;
  7479.  
  7480. procedure TDCInplaceFloatEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  7481. begin
  7482.   inherited;
  7483.   if tgTabs in Grid.Options then
  7484.     Message.Result := Message.Result or DLGC_WANTTAB;
  7485. end;
  7486.  
  7487. { TDCInplaceADOGridEdit }
  7488.  
  7489. {$IFDEF DELPHI_V5UP}
  7490.  
  7491. procedure TDCInplaceADOGridEdit.ChoiceClick(Sender: TObject);
  7492. begin
  7493.   Grid.SetModified(True);
  7494.   inherited;
  7495. end;
  7496.  
  7497. procedure TDCInplaceADOGridEdit.CMWantSpecialKey(
  7498.   var Msg: TCMWantSpecialKey);
  7499. begin
  7500.   inherited;
  7501.   if Msg.CharCode = VK_RETURN then Msg.Result := 1;
  7502. end;
  7503.  
  7504. function TDCInplaceADOGridEdit.DoMouseWheel(Shift: TShiftState;
  7505.   WheelDelta: Integer; MousePos: TPoint): Boolean;
  7506. begin
  7507.   Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
  7508. end;
  7509.  
  7510. procedure TDCInplaceADOGridEdit.KeyDown(var Key: Word; Shift: TShiftState);
  7511. begin
  7512.   if Key > $20 then HideErrorMessage;
  7513.   if not DropDownVisible then InplaceKeyDown(Self, Grid, Key, Shift);
  7514.   if Key <> 0 then
  7515.   begin
  7516.     if not ReadOnly then Grid.SetModified(True);
  7517.     inherited KeyDown(Key, Shift);
  7518.   end;
  7519. end;
  7520.  
  7521. procedure TDCInplaceADOGridEdit.KeyPress(var Key: Char);
  7522. begin
  7523.   if not DropDownVisible or (PerformCloseUp and (Key = Char(VK_RETURN))) then Grid.KeyPress(Key);
  7524.   if Key <> #0 then
  7525.   begin
  7526.     if not(Key in [#27, #8, #0]) then
  7527.       if not ReadOnly then Grid.SetModified(True);
  7528.     inherited KeyPress(Key);
  7529.   end;
  7530. end;
  7531.  
  7532. procedure TDCInplaceADOGridEdit.KeyUp(var Key: Word; Shift: TShiftState);
  7533. begin
  7534.   if not DropDownVisible then Grid.KeyUp(Key, Shift);
  7535.   if Key <> 0 then
  7536.     inherited KeyUp(Key, Shift);
  7537. end;
  7538.  
  7539. procedure TDCInplaceADOGridEdit.SetGrid(Value: TDCCustomTreeGrid);
  7540. begin
  7541.   FGrid := Value;
  7542. end;
  7543.  
  7544. procedure TDCInplaceADOGridEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  7545. begin
  7546.   inherited;
  7547.   if tgTabs in Grid.Options then
  7548.     Message.Result := Message.Result or DLGC_WANTTAB;
  7549. end;
  7550.  
  7551. {$ENDIF}
  7552.  
  7553. { TKnotColumnFooterPanel }
  7554.  
  7555. function TKnotColumnFooterPanel.GetColIndex: integer;
  7556. begin
  7557.   Result := inherited GetColIndex;
  7558.   if Result >= 0 then Inc(Result, TDCCustomTreeGrid(Footer.Grid).FIndicatorOffset);
  7559. end;
  7560.  
  7561. procedure TKnotColumnFooterPanel.SetColIndex(const Value: integer);
  7562. begin
  7563.   inherited SetColIndex(Value  -TDCCustomTreeGrid(Footer.Grid).FIndicatorOffset);
  7564. end;
  7565.  
  7566. { TKnotClipPopup }
  7567.  
  7568. procedure TKnotClipPopup.AddButtons;
  7569. begin
  7570.   BeginUpdate;
  7571.   Clear;
  7572.   case CellType of
  7573.     fcIndicator:
  7574.       begin
  7575.         PopupStyle := cpPopupMenu;
  7576.         AddButton('#Property', 'DC_DBPROPERTY', LoadStr(RES_STRN_VAL_PROP) , 0, 0);
  7577.         AddButton('#Find'    , 'DC_DBFIND'    , LoadStr(RES_STRN_VAL_FIND) , 0, 1);
  7578.         AddButton('#Print'   , 'DC_PRINT'     , LoadStr(RES_STRN_VAL_PRINT), 0, 2);
  7579.         if (Parent is TDCCustomGrid) and TDCCustomGrid(Parent).GroupingEnabled then
  7580.           AddButton('#GroupBox'   , 'DC_GROUPBOX', LoadStr(RES_STRN_VAL_GRPBOX), 0, 3)
  7581.       end;
  7582.     fcMarker:
  7583.       begin
  7584.         PopupStyle := cpPopupMenu;
  7585.         AddButton('#SelectAll', 'DC_PM_SELALL', LoadStr(RES_STRN_HNT_SELALL) ,
  7586.           0, pmSelectAll);
  7587.         AddButton('#DeselectAll', 'DC_PM_DESALL', LoadStr(RES_STRN_HNT_DESALL) ,
  7588.           0, pmDeselectAll);
  7589.       end;
  7590.   end;
  7591.   EndUpdate;
  7592. end;
  7593.  
  7594. procedure TKnotClipPopup.ButtonClick(Sender: TObject);
  7595. begin
  7596.   inherited;
  7597.   if (Sender <> nil) and (Parent is TDCCustomGrid) then
  7598.     if TDCEditButton(Sender).Name = '#GroupBox' then
  7599.        TDCCustomGrid(Parent).Grouping := not TDCCustomGrid(Parent).Grouping;
  7600. end;
  7601.  
  7602. { TTreePath }
  7603.  
  7604. procedure TTreePath.Assign(Source: TPersistent);
  7605. begin
  7606.   if Source is TTreePath then
  7607.   begin
  7608.     FColor := TTreePath(Source).Color;
  7609.     Include(FAssignedValues, tpColor);
  7610.   end
  7611.   else
  7612.     inherited Assign(Source);
  7613. end;
  7614.  
  7615. constructor TTreePath.Create(AGrid: TDCCustomTreeGrid);
  7616. begin
  7617.   inherited Create;
  7618.   FGrid := AGrid;
  7619.   FFont := TFont.Create;
  7620.   FFont.Assign(DefaultFont);
  7621.   FFont.OnChange := FontChanged;
  7622. end;
  7623.  
  7624. function TTreePath.DefaultFont: TFont;
  7625. begin
  7626.   Result := FGrid.Font
  7627. end;
  7628.  
  7629. function TTreePath.DefaultColor: TColor;
  7630. begin
  7631.   Result := FGrid.FixedColor
  7632. end;
  7633.  
  7634. procedure TTreePath.FontChanged(Sender: TObject);
  7635. begin
  7636.   Include(FAssignedValues, tpFont);
  7637.   FGrid.Invalidate;
  7638. end;
  7639.  
  7640. function TTreePath.GetColor: TColor;
  7641. begin
  7642.   if tpColor in FAssignedValues then
  7643.     Result := FColor
  7644.   else
  7645.     Result := DefaultColor;
  7646. end;
  7647.  
  7648. function TTreePath.GetFont: TFont;
  7649. var
  7650.   Save: TNotifyEvent;
  7651. begin
  7652.   if not (tpFont in FAssignedValues) and (FFont.Handle <> DefaultFont.Handle) then
  7653.   begin
  7654.     Save := FFont.OnChange;
  7655.     FFont.OnChange := nil;
  7656.     FFont.Assign(DefaultFont);
  7657.     FFont.OnChange := Save;
  7658.   end;
  7659.   Result := FFont;
  7660. end;
  7661.  
  7662. function TTreePath.IsColorStored: Boolean;
  7663. begin
  7664.   Result := (tpColor in FAssignedValues) and (FColor <> DefaultColor);
  7665. end;
  7666.  
  7667. function TTreePath.IsFontStored: Boolean;
  7668. begin
  7669.   Result := (tpFont in FAssignedValues) and (Font <> DefaultFont);
  7670. end;
  7671.  
  7672. procedure TTreePath.SetColor(const Value: TColor);
  7673. begin
  7674.   if FColor <> Value then
  7675.   begin
  7676.     FColor := Value;
  7677.     FGrid.Invalidate;
  7678.     Include(FAssignedValues, tpColor);
  7679.   end;
  7680. end;
  7681.  
  7682. procedure TTreePath.SetFont(const Value: TFont);
  7683. begin
  7684.  
  7685. end;
  7686.  
  7687. end.
  7688.