git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@63 05c56307-c608-d34a-929d-697000501d7a
19734 lines
597 KiB
ObjectPascal
19734 lines
597 KiB
ObjectPascal
|
|
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressQuantumTreeList }
|
|
{ }
|
|
{ Copyright (c) 1998-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSQUANTUMTREELIST AND ALL }
|
|
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit cxTL;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Variants,
|
|
{$ENDIF}
|
|
Classes, SysUtils, Clipbrd, Windows, Messages,
|
|
ExtCtrls, Controls, Forms, StdCtrls, Graphics, ImgList, ComCtrls, Math,
|
|
dxCore, cxControls, cxGraphics, cxClasses, cxGeometry, cxStorage,
|
|
cxCustomData, cxData, cxDataUtils, cxVariants, cxEdit, cxStyles,
|
|
cxListBox, cxNavigator, cxInplaceContainer, cxLookAndFeels, cxLookAndFeelPainters,
|
|
cxTLIntf, cxTLStrs, cxLibraryConsts;
|
|
|
|
const
|
|
cxTLMajorVersion = '4';
|
|
// default size values for treelist items
|
|
cxTreeListDefWidth = 100;
|
|
cxTreeListDefMinWidth = 20;
|
|
// default values for treelist options view
|
|
|
|
cxTreeListDefBandHeaderLineCount = 1;
|
|
cxTreeListDefBands = False;
|
|
cxTreeListDefFooter = False;
|
|
cxTreeListDefColumnHeaders = True;
|
|
cxTreeListDefColumnAutoWidth = False;
|
|
cxTreeListDefIndicatorWidth = 15;
|
|
cxTreeListDefSeparatorWidth = 2;
|
|
cxTreeListDefDropArrowColor = $00FF00;
|
|
|
|
cxTreeListDefWaitExpandTime = 500;
|
|
|
|
// preview
|
|
cxTreeListDefPreviewIndent = 5;
|
|
cxTreeListDefPreviewMaxLineCount = 3;
|
|
|
|
// treelist styles predefined indexes
|
|
|
|
tlcs_Header = ecs_EditContainerStylesMaxIndex + 1;
|
|
tlcs_Footer = ecs_EditContainerStylesMaxIndex + 2;
|
|
|
|
// for band styles
|
|
tlbs_Content = 0;
|
|
tlbs_Footer = 1;
|
|
tlbs_Header = 2;
|
|
tlbs_HeaderBackground = 3;
|
|
|
|
// for control styles
|
|
tlsv_Content = ecs_Content;
|
|
tlsv_BandBackground = ecs_EditingStylesMaxIndex + 1;
|
|
tlsv_BandContent = ecs_EditingStylesMaxIndex + 2;
|
|
tlsv_BandHeader = ecs_EditingStylesMaxIndex + 3;
|
|
tlsv_ColumnFooter = ecs_EditingStylesMaxIndex + 4;
|
|
tlsv_ColumnHeader = ecs_EditingStylesMaxIndex + 5;
|
|
tlsv_ContentEven = ecs_EditingStylesMaxIndex + 6;
|
|
tlsv_ContentOdd = ecs_EditingStylesMaxIndex + 7;
|
|
tlsv_Footer = ecs_EditingStylesMaxIndex + 8;
|
|
tlsv_HotTrack = ecs_EditingStylesMaxIndex + 12;
|
|
tlsv_IncSearch = ecs_EditingStylesMaxIndex + 9;
|
|
tlsv_Indicator = ecs_EditingStylesMaxIndex + 10;
|
|
tlsv_Preview = ecs_EditingStylesMaxIndex + 11;
|
|
|
|
// base constants for descendants
|
|
|
|
cxtlMaxControlStyleIndex = tlsv_Preview;
|
|
cxtlMaxColumnStyleIndex = tlcs_Footer;
|
|
cxtlMaxBandStyleIndex = tlbs_HeaderBackground;
|
|
|
|
// base index for hitcodes bits
|
|
|
|
tlhc_Base = 4;
|
|
tlhc_HitAtBand = tlhc_Base;
|
|
tlhc_HitAtBandContainer = tlhc_Base + 1;
|
|
tlhc_HitAtBandHeader = tlhc_Base + 2;
|
|
tlhc_HitAtButton = tlhc_Base + 3;
|
|
tlhc_HitAtColumn = tlhc_Base + 4;
|
|
tlhc_HitAtColumnHeader = tlhc_Base + 5;
|
|
tlhc_HitAtFooter = tlhc_Base + 6;
|
|
tlhc_HitAtFooterItem = tlhc_Base + 7;
|
|
tlhc_HitAtIndent = tlhc_Base + 17;
|
|
tlhc_HitAtIndicator = tlhc_Base + 8;
|
|
tlhc_HitAtNode = tlhc_Base + 9;
|
|
tlhc_HitAtNodePreview = tlhc_Base + 16;
|
|
tlhc_HitAtSeparator = tlhc_Base + 11;
|
|
tlhc_HitAtSizingHorz = tlhc_Base + 12;
|
|
tlhc_HitAtSizingVert = tlhc_Base + 13;
|
|
tlhc_HitAtImage = tlhc_Base + 14;
|
|
tlhc_HitAtStateImage = tlhc_Base + 15;
|
|
tlhc_MaxIndex = tlhc_HitAtSizingVert;
|
|
|
|
// node state flags
|
|
tlnsFocused = $0001;
|
|
tlnsDeleting = $0002;
|
|
tlnsHasChildren = $0004;
|
|
tlnsHasData = $0008;
|
|
tlnsCollapsed = $0010;
|
|
tlnsInternalCreating = $0080;
|
|
tlnsIndexesInvalid = $1000;
|
|
tlnsRecreateList = $2000;
|
|
|
|
// events state
|
|
tlesNone = $0000;
|
|
tlesChanged = $0001;
|
|
tlesSelection = $0002;
|
|
|
|
// hit test and sizing constants
|
|
cxtlHitDelta = 3;
|
|
cxtlScrollDelta = 10;
|
|
cxtlSizingMarkWidth = 1;
|
|
|
|
// overs
|
|
cxColumnTextSeparator = #9;
|
|
cxLineSeparator = #13#10;
|
|
cxTreeListScrollWidthDragInterval = 50;
|
|
cxTreeListIndentOffsetSize = 6;
|
|
cxTreeListEditCellContentOffset: TRect = (Left: 1; Top: 1; Right: 1; Bottom: 1);
|
|
cxTreeListEditCellHeightOffset = 2;
|
|
cxTreeListDragDropTextAreaOffset: TPoint = (X: 20; Y:0);
|
|
|
|
type
|
|
EcxTreeList = class(EdxException);
|
|
|
|
TcxTreeListColumn = class;
|
|
TcxTreeListColumnViewInfo = class;
|
|
TcxTreeListColumnViewInfoClass = class of TcxTreeListColumnViewInfo;
|
|
|
|
TcxTreeListBand = class;
|
|
TcxTreeListBands = class;
|
|
TcxTreeListBandRow = class;
|
|
TcxTreeListBandRows = class;
|
|
|
|
TcxTreeListOptionsBehavior = class;
|
|
|
|
TcxTreeListOptionsCustomizing = class;
|
|
TcxTreeListOptionsCustomizingClass = class of TcxTreeListOptionsCustomizing;
|
|
|
|
TcxTreeListHitTest = class;
|
|
|
|
TcxTreeListHeaderViewInfo = class;
|
|
|
|
TcxTreeListBandViewInfo = class;
|
|
TcxTreeListViewInfo = class;
|
|
TcxTreeListViewInfoItem = class;
|
|
TcxTreeListNodesViewInfo = class;
|
|
TcxTreeListNodeViewInfo = class;
|
|
TcxTreeListCellsGroupViewInfo = class;
|
|
TcxTreeListEditCellViewInfo = class;
|
|
TcxCustomViewInfoItemClass = class of TcxCustomViewInfoItem;
|
|
TcxTreeListNodeViewInfoClass = class of TcxTreeListNodeViewInfo;
|
|
TcxTreeListNodesViewInfoClass = class of TcxTreeListNodesViewInfo;
|
|
TcxTreeListViewInfoItemClass = class of TcxTreeListViewInfoItem;
|
|
TcxTreeListIndentViewInfoClass = class of TcxTreeListIndentViewInfo;
|
|
TcxTreeListEditCellViewInfoClass = class of TcxTreeListEditCellViewInfo;
|
|
TcxTreeListCellsGroupViewInfoClass = class of TcxTreeListCellsGroupViewInfo;
|
|
|
|
TcxTreeListOptionsView = class;
|
|
|
|
TcxTreeListControlPainter = class;
|
|
|
|
TcxTreeListNode = class;
|
|
TcxTreeListNodes = class;
|
|
TcxTreeListNodesClass = class of TcxTreeListNodes;
|
|
|
|
TcxTreeListPreview = class;
|
|
TcxTreeListPreviewClass = class of TcxTreeListPreview;
|
|
TcxCustomTreeListControl = class;
|
|
TcxTreeListCustomizing = class;
|
|
|
|
TcxTreeListStyles = class;
|
|
|
|
// overriding types
|
|
PIntArray = ^TIntArray;
|
|
PPointerList = Classes.PPointerList;
|
|
|
|
TIntArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer;
|
|
|
|
TcxTreeListBandFixedKind = (tlbfNone, tlbfLeft, tlbfRight);
|
|
|
|
TcxTreeListGridLines = (tlglNone, tlglHorz, tlglVert, tlglBoth);
|
|
|
|
TcxTreeListImageIndexType = (tlitImageIndex, tlitSelectedIndex, tlitStateIndex);
|
|
TcxTreeListImageIndexes = set of TcxTreeListImageIndexType;
|
|
|
|
TcxTreeListNodeAttachMode = (tlamAdd, tlamAddFirst, tlamAddChild, tlamAddChildFirst, tlamInsert);
|
|
TcxTreeListNodeAddMode = (tlnaAdd, tlnaAddFirst, tlnaInsert);
|
|
TcxTreeListNodeImageIndexes = array[TcxTreeListImageIndexType] of TImageIndex;
|
|
|
|
TcxTreeListCompareFunc = function(AItem1, AItem2: TcxTreeListNode): Integer;
|
|
|
|
TcxCachedContentParams = array[Boolean] of TcxViewParams;
|
|
|
|
TcxTreeListFindFunc = function(ANode: TcxTreeListNode; AData: Pointer): Boolean;
|
|
|
|
{ TcxTreeListNodes}
|
|
|
|
TcxTreeListNodes = class(TPersistent)
|
|
private
|
|
FFoundItem: TcxTreeListNode;
|
|
FFocusedIndex: Integer;
|
|
FMaxLevel: Integer;
|
|
FOwner: TcxCustomTreeListControl;
|
|
FRoot: TcxTreeListNode;
|
|
FState: Integer;
|
|
FVisibleCount: Integer;
|
|
function GetAbsoluteItem(AFindIndex: Integer): TcxTreeListNode;
|
|
function GetCount: Integer;
|
|
function GetDataController: TcxControlDataController;
|
|
function GetItem(AIndex: Integer): TcxTreeListNode;
|
|
function GetMaxLevel: Integer;
|
|
function GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
function GetState(Index: Integer): Boolean;
|
|
function GetTopVisibleNode: TcxTreeListNode;
|
|
function GetVisibleCount: Integer;
|
|
procedure SetAbsoluteItem(Index: Integer; Value: TcxTreeListNode);
|
|
procedure SetItem(AIndex: Integer; Value: TcxTreeListNode);
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
protected
|
|
TopIndex: Integer;
|
|
TopNode: TcxTreeListNode;
|
|
procedure CalculateInfo(IsLocked: Boolean); virtual;
|
|
procedure Changed; virtual;
|
|
procedure DoNodeChanged(ANode: TcxTreeListNode); virtual;
|
|
class function FindBetween(AFirst, ALast: TcxTreeListNode; ACount, AIndex: Integer): TcxTreeListNode;
|
|
function GetOwner: TPersistent; override;
|
|
function GetVisibleNode(var AIndex: Integer): TcxTreeListNode; virtual;
|
|
function InternalAddNode(ANode, ARelative: TcxTreeListNode; AddMethod: TcxTreeListNodeAttachMode): TcxTreeListNode;
|
|
procedure SetNodeParent(ANewNode, ANewParent: TcxTreeListNode; AMode: TcxTreeListNodeAddMode);
|
|
procedure SetTopVisibleIndex(AIndex: Integer);
|
|
property DataController: TcxControlDataController read GetDataController;
|
|
property FocusedIndex: Integer read FFocusedIndex write FFocusedIndex;
|
|
property NodesViewInfo: TcxTreeListNodesViewInfo read GetNodesViewInfo;
|
|
property State: Integer read FState write FState;
|
|
property IsInvalidState: Boolean index tlnsIndexesInvalid read GetState write SetState;
|
|
property IsInternalCreating: Boolean index tlnsInternalCreating read GetState write SetState;
|
|
public
|
|
constructor Create(AOwner: TcxCustomTreeListControl); virtual;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure Clear;
|
|
property Root: TcxTreeListNode read FRoot;
|
|
property Count: Integer read GetCount;
|
|
property AbsoluteItems[AbsoluteIndex: Integer]: TcxTreeListNode read GetAbsoluteItem write SetAbsoluteItem;
|
|
property Items[Index: Integer]: TcxTreeListNode read GetItem write SetItem; default;
|
|
property TopVisibleNode: TcxTreeListNode read GetTopVisibleNode;
|
|
property TreeList: TcxCustomTreeListControl read FOwner;
|
|
property VisibleCount: Integer read GetVisibleCount;
|
|
property MaxLevel: Integer read GetMaxLevel;
|
|
end;
|
|
|
|
{ TcxTreeListNode }
|
|
|
|
TcxTreeListNode = class(TPersistent, IUnknown, IcxDragSizing)
|
|
private
|
|
FCount: Integer;
|
|
FData: Pointer;
|
|
FFirst: TcxTreeListNode;
|
|
FIndex: Integer;
|
|
FLast: TcxTreeListNode;
|
|
FNext: TcxTreeListNode;
|
|
FOwner: TcxTreeListNodes;
|
|
FParent: TcxTreeListNode;
|
|
FPrev: TcxTreeListNode;
|
|
FRecordIndex: Integer;
|
|
FState: Integer;
|
|
function GetAbsoluteIndex: Integer;
|
|
function GetDataController: TcxControlDataController;
|
|
function GetExpanded: Boolean;
|
|
function GetFocused: Boolean;
|
|
function GetHasChildren: Boolean;
|
|
function GetHotTrack: Boolean;
|
|
function GetIsDeleting: Boolean;
|
|
function GetIsFirst: Boolean;
|
|
function GetIsGroupNode: Boolean;
|
|
function GetIsLast: Boolean;
|
|
function GetIsVisible: Boolean;
|
|
function GetItem(AIndex: Integer): TcxTreeListNode;
|
|
function GetLevel: Integer;
|
|
function GetSelected: Boolean;
|
|
function GetNodeImageIndex(AIndex: Integer): TImageIndex;
|
|
function GetText(Index: Integer): string;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetValue(AIndex: Integer): Variant;
|
|
function GetValueCount: Integer;
|
|
function GetVisibleIndex: Integer;
|
|
procedure AdjustIndexes(ANode: TcxTreeListNode; AIndex: Integer);
|
|
procedure InternalInsert(Value: TcxTreeListNode);
|
|
procedure InternalRemove(Value: TcxTreeListNode);
|
|
procedure SetExpanded(Value: Boolean);
|
|
procedure SetFirst(Value: TcxTreeListNode);
|
|
procedure SetFocused(Value: Boolean);
|
|
procedure SetHasChildren(Value: Boolean);
|
|
procedure SetItem(AIndex: Integer; Value: TcxTreeListNode);
|
|
procedure SetLast(Value: TcxTreeListNode);
|
|
procedure SetNodeImageIndex(AIndex: Integer; Value: TImageIndex);
|
|
procedure SetParentFor(Value: TcxTreeListNode);
|
|
procedure SetText(AIndex: Integer; const AValue: string);
|
|
procedure SetSelected(Value: Boolean);
|
|
procedure SetValue(AIndex: Integer; const AValue: Variant);
|
|
protected
|
|
FImageIndexes: TcxTreeListNodeImageIndexes;
|
|
FVisibleIndex: Integer;
|
|
function AddDataControllerRecord: Integer; virtual;
|
|
procedure DoReadNodeData(AReader: TcxReader); virtual;
|
|
procedure DoWriteNodeData(AWriter: TcxWriter); virtual;
|
|
function GetIsFirstVisible: Boolean; virtual;
|
|
function GetIsLastVisible: Boolean; virtual;
|
|
function GetNextVisibleEx(IsPrev: Boolean): TcxTreeListNode;
|
|
function GetNextSiblingEx(ANode: TcxTreeListNode; AForward: Boolean): TcxTreeListNode;
|
|
function GetOwner: TPersistent; override;
|
|
function GetRootParent: TcxTreeListNode;
|
|
procedure ReadData(AStream: TStream); virtual;
|
|
procedure WriteData(AStream: TStream); virtual;
|
|
// IcxDragSizing
|
|
function CanSizing(ADirection: TcxDragSizingDirection): Boolean;
|
|
function GetSizingBoundsRect(ADirection: TcxDragSizingDirection): TRect;
|
|
function GetSizingIncrement(ADirection: TcxDragSizingDirection): Integer;
|
|
function IsDynamicUpdate: Boolean;
|
|
procedure SetSizeDelta(ADirection: TcxDragSizingDirection; ADelta: Integer);
|
|
// IUnknown
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
property DataController: TcxControlDataController read GetDataController;
|
|
property State: Integer read FState write FState;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListNodes); virtual;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure AssignValues(const AValues:{$IFDEF DELPHI5} array of {$ENDIF} Variant);
|
|
function AddChild: TcxTreeListNode; virtual;
|
|
function AddChildFirst: TcxTreeListNode; virtual;
|
|
procedure AlphaSort(ARecurse: Boolean = False);
|
|
function CanCollapse: Boolean;
|
|
function CanExpand: Boolean;
|
|
function CanMove(ADest: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode): Boolean;
|
|
procedure Collapse(Recurse: Boolean);
|
|
procedure CustomSort(ASortProc: TcxTreeListCompareFunc; ARecurse: Boolean = False);
|
|
procedure Delete;
|
|
procedure DeleteChildren;
|
|
function DisplayRect(AEntryOnly: Boolean): TRect;
|
|
procedure EndEdit(Cancel: Boolean);
|
|
procedure Expand(Recurse: Boolean);
|
|
function GetNext: TcxTreeListNode;
|
|
function GetNextChild(Value: TcxTreeListNode): TcxTreeListNode;
|
|
function getNextSibling: TcxTreeListNode; {GetNextSibling conflicts with C++ macro}
|
|
function GetNextVisible: TcxTreeListNode;
|
|
function GetPrev: TcxTreeListNode;
|
|
function GetPrevChild(Value: TcxTreeListNode): TcxTreeListNode;
|
|
function getPrevSibling: TcxTreeListNode; {GetPrevSibling conflicts with a C++ macro}
|
|
function GetPrevVisible: TcxTreeListNode;
|
|
function getFirstChild: TcxTreeListNode; {GetFirstChild conflicts with C++ macro}
|
|
function GetLastChild: TcxTreeListNode;
|
|
//
|
|
function HasAsParent(Value: TcxTreeListNode): Boolean;
|
|
function IndexOf(Value: TcxTreeListNode): Integer;
|
|
function InsertChild(ABeforeNode: TcxTreeListNode): TcxTreeListNode; virtual;
|
|
procedure MakeVisible;
|
|
procedure MoveTo(ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode); virtual;
|
|
procedure Repaint(ARecalculate: Boolean); virtual;
|
|
property AbsoluteIndex: Integer read GetAbsoluteIndex;
|
|
property Count: Integer read FCount;
|
|
property Data: Pointer read FData write FData;
|
|
property Deleting: Boolean read GetIsDeleting;
|
|
property Expanded: Boolean read GetExpanded write SetExpanded;
|
|
property Focused: Boolean read GetFocused write SetFocused;
|
|
property HasChildren: Boolean read GetHasChildren write SetHasChildren;
|
|
property HotTrack: Boolean read GetHotTrack;
|
|
property ImageIndex: TImageIndex index 0 read GetNodeImageIndex write SetNodeImageIndex;
|
|
property Index: Integer read FIndex;
|
|
property IsFirst: Boolean read GetIsFirst;
|
|
property IsFirstVisible: Boolean read GetIsFirstVisible;
|
|
property IsGroupNode: Boolean read GetIsGroupNode;
|
|
property IsLast: Boolean read GetIsLast;
|
|
property IsLastVisible: Boolean read GetIsLastVisible;
|
|
property IsVisible: Boolean read GetIsVisible;
|
|
property Items[Index: Integer]: TcxTreeListNode read GetItem write SetItem; default;
|
|
property Level: Integer read GetLevel;
|
|
property Owner: TcxTreeListNodes read FOwner;
|
|
property Parent: TcxTreeListNode read FParent;
|
|
property RecordIndex: Integer read FRecordIndex write FRecordIndex;
|
|
property Selected: Boolean read GetSelected write SetSelected;
|
|
property SelectedIndex: TImageIndex index 1 read GetNodeImageIndex write SetNodeImageIndex;
|
|
property StateIndex: TImageIndex index 2 read GetNodeImageIndex write SetNodeImageIndex;
|
|
property Texts[Index: Integer]: string read GetText write SetText;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property ValueCount: Integer read GetValueCount;
|
|
property Values[Index: Integer]: Variant read GetValue write SetValue;
|
|
property VisibleIndex: Integer read GetVisibleIndex;
|
|
end;
|
|
|
|
{ TcxTreeListRootNode }
|
|
|
|
TcxTreeListRootNode = class(TcxTreeListNode)
|
|
protected
|
|
function AddDataControllerRecord: Integer; override;
|
|
end;
|
|
|
|
{ TcxUnboundTreeListNode }
|
|
|
|
TcxUnboundTreeListNode = class(TcxTreeListNode)
|
|
protected
|
|
procedure ReadData(AStream: TStream); override;
|
|
procedure WriteData(AStream: TStream); override;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListNodes); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
end;
|
|
|
|
{ TcxTreeListColumnStyles }
|
|
|
|
TcxTreeListColumnStyles = class(TcxEditContainerStyles)
|
|
private
|
|
function GetBand: TcxTreeListBand;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
ContentParams: TcxCachedContentParams;
|
|
procedure CachedContentStyleChanged;
|
|
property Band: TcxTreeListBand read GetBand;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property Header: TcxStyle index tlcs_Header read GetValue write SetValue;
|
|
property Footer: TcxStyle index tlcs_Footer read GetValue write SetValue;
|
|
property Content;
|
|
end;
|
|
|
|
{ TcxTreeListColumnPosition }
|
|
|
|
TcxTreeListColumnPosition = class(TcxOwnedPersistent)
|
|
private
|
|
FBandIndex: Integer;
|
|
FColIndex: Integer;
|
|
FLineCount: Integer;
|
|
FRowIndex: Integer;
|
|
function GetBandIndex: Integer;
|
|
function GetColumn: TcxTreeListColumn;
|
|
function GetOwnerBandVisibleIndex: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
procedure SetBandIndex(Index: Integer);
|
|
procedure SetColIndex(Value: Integer);
|
|
procedure SetLineCount(Value: Integer);
|
|
procedure SetRowIndex(Value: Integer);
|
|
protected
|
|
procedure Changed; virtual;
|
|
function GetBandFromIndex(AIndex: Integer): TcxTreeListBand;
|
|
procedure Save; virtual;
|
|
procedure Load; virtual;
|
|
property Column: TcxTreeListColumn read GetColumn;
|
|
property OwnerBandVisibleIndex: Integer read GetOwnerBandVisibleIndex;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure SetPosition(AColIndex, ARowIndex: Integer; IsInsertRow: Boolean = False);
|
|
procedure SetPositionEx(ABandIndex, AColIndex, ARowIndex: Integer; IsInsertRow: Boolean = False);
|
|
published
|
|
property ColIndex: Integer read FColIndex write SetColIndex;
|
|
property LineCount: Integer read FLineCount write SetLineCount default 1;
|
|
property RowIndex: Integer read FRowIndex write SetRowIndex;
|
|
property BandIndex: Integer read GetBandIndex write SetBandIndex;
|
|
end;
|
|
|
|
TcxTreeListColumnPositionClass = class of TcxTreeListColumnPosition;
|
|
|
|
{ TcxTreeListCaption }
|
|
|
|
TcxTreeListCaption = class(TcxOwnedPersistent)
|
|
private
|
|
FAlignHorz: TAlignment;
|
|
FAlignVert: TcxAlignmentVert;
|
|
FGlyph: TBitmap;
|
|
FGlyphAlignHorz: TAlignment;
|
|
FGlyphAlignVert: TcxAlignmentVert;
|
|
FText: string;
|
|
FTreeList: TcxCustomTreeListControl;
|
|
FState: Integer;
|
|
FViewInfo: TcxTreeListViewInfoItem;
|
|
procedure SetAlignHorz(Value: TAlignment);
|
|
procedure SetAlignVert(Value: TcxAlignmentVert);
|
|
procedure SetGlyph(Value: TBitmap);
|
|
procedure SetGlyphAlignHorz(Value: TAlignment);
|
|
procedure SetGlyphAlignVert(Value: TcxAlignmentVert);
|
|
procedure SetText(const Value: string);
|
|
protected
|
|
procedure Changed; virtual;
|
|
function GetState(Index: Integer): Boolean;
|
|
function GetText: string; virtual;
|
|
function IsTextStored: Boolean; virtual;
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
property TreeList: TcxCustomTreeListControl read FTreeList;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
constructor CreateEx(ATreeList: TcxCustomTreeListControl;
|
|
AOwner: TPersistent; AViewInfo: TcxTreeListViewInfoItem); virtual;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property AlignHorz: TAlignment read FAlignHorz write SetAlignHorz default taLeftJustify;
|
|
property AlignVert: TcxAlignmentVert read FAlignVert write SetAlignVert default vaTop;
|
|
property Glyph: TBitmap read FGlyph write SetGlyph;
|
|
property GlyphAlignHorz: TAlignment read FGlyphAlignHorz write SetGlyphAlignHorz default taLeftJustify;
|
|
property GlyphAlignVert: TcxAlignmentVert read FGlyphAlignVert write SetGlyphAlignVert default vaTop;
|
|
property MultiLine: Boolean index 2 read GetState write SetState default False;
|
|
property ShowEndEllipsis: Boolean index 1 read GetState write SetState default True;
|
|
property Text: string read GetText write SetText stored IsTextStored;
|
|
end;
|
|
|
|
{ TcxTreeListColumnOptions }
|
|
|
|
TcxTreeListColumnOptions = class(TcxCustomEditContainerItemOptions)
|
|
private
|
|
FState: Integer;
|
|
FHidden: Boolean;
|
|
protected
|
|
procedure Changed; override;
|
|
function GetValue(Index: Integer): Boolean;
|
|
procedure SetValue(Index: Integer; const Value: Boolean);
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure RestoreDefaults; virtual;
|
|
published
|
|
property CellEndEllipsis: Boolean index 1 read GetValue write SetValue default True;
|
|
property Sizing: Boolean index 2 read GetValue write SetValue default True;
|
|
property Footer: Boolean index 3 read GetValue write SetValue default False;
|
|
property Hidden: Boolean read FHidden write FHidden default False;
|
|
property Customizing;
|
|
property Editing;
|
|
property Focusing;
|
|
property IncSearch;
|
|
property Moving;
|
|
property ShowEditButtons;
|
|
property Sorting;
|
|
property TabStop;
|
|
end;
|
|
|
|
{ TcxTreeListColumnSummaryFooter }
|
|
|
|
TcxTreeListColumnSummaryFooter = class(TcxOwnedInterfacedPersistent)
|
|
private
|
|
FAlignHorz: TAlignment;
|
|
FAlignVert: TcxAlignmentVert;
|
|
FFormat: string;
|
|
FMultiLine: Boolean;
|
|
function GetColumn: TcxTreeListColumn;
|
|
function GetDataController: TcxCustomDataController;
|
|
function GetFormat: string;
|
|
function GetSummaryItem: TcxDataSummaryItem;
|
|
function GetSummaryKind: TcxSummaryKind;
|
|
function GetSummaryText: string;
|
|
function GetSummaryValue: Variant;
|
|
procedure SetAlignHorz(Value: TAlignment);
|
|
procedure SetAlignVert(Value: TcxAlignmentVert);
|
|
procedure SetFormat(const Value: string);
|
|
procedure SetMultiLine(Value: Boolean);
|
|
procedure SetSummaryText(const Value: string);
|
|
procedure SetSummaryValue(const Value: Variant);
|
|
procedure SetSummaryKind(Value: TcxSummaryKind);
|
|
protected
|
|
ItemIndex: Integer;
|
|
function IsFormatStored: Boolean;
|
|
function IsSummaryItemValid: Boolean;
|
|
function Summary: TcxDataSummary;
|
|
procedure SummaryItemChanged; virtual;
|
|
function SummaryItemIndex: Integer;
|
|
function SummaryItems: TcxDataFooterSummaryItems;
|
|
property DataController: TcxCustomDataController read GetDataController;
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
property Column: TcxTreeListColumn read GetColumn;
|
|
property SummaryItem: TcxDataSummaryItem read GetSummaryItem;
|
|
property SummaryText: string read GetSummaryText write SetSummaryText;
|
|
property SummaryValue: Variant read GetSummaryValue write SetSummaryValue;
|
|
published
|
|
property Format: string read GetFormat write SetFormat stored IsFormatStored;
|
|
property Kind: TcxSummaryKind read GetSummaryKind write SetSummaryKind default skNone;
|
|
property AlignHorz: TAlignment read FAlignHorz write SetAlignHorz default taLeftJustify;
|
|
property AlignVert: TcxAlignmentVert read FAlignVert write SetAlignVert default vaTop;
|
|
property MultiLine: Boolean read FMultiLine write SetMultiLine default False;
|
|
end;
|
|
|
|
TcxTreeListColumnSummaryFooterClass = class of TcxTreeListColumnSummaryFooter;
|
|
|
|
{ TcxTreeListColumn }
|
|
|
|
TcxTreeListOnGetDisplayTextEvent = procedure(Sender: TcxTreeListColumn;
|
|
ANode: TcxTreeListNode; var Value: string) of object;
|
|
TcxTreeListGetEditPropertiesEvent = procedure(Sender: TcxTreeListColumn;
|
|
ANode: TcxTreeListNode; var EditProperties: TcxCustomEditProperties) of object;
|
|
|
|
TcxTreeListColumn = class(TcxCustomInplaceEditContainer, IUnknown, IcxDragSizing, IcxTreeListIndexedItem, IcxStoredObject)
|
|
private
|
|
FCaption: TcxTreeListCaption;
|
|
FCalculatedWidth: Integer;
|
|
FData: Integer;
|
|
FIsWidthAssigned: Boolean;
|
|
FMinWidth: Integer;
|
|
FOnChangeName: TNotifyEvent;
|
|
FOwnerBand: TcxTreeListBand;
|
|
FPosition: TcxTreeListColumnPosition;
|
|
FSortOrder: TcxDataSortOrder;
|
|
FState: Integer;
|
|
FSummaryFooter: TcxTreeListColumnSummaryFooter;
|
|
FViewInfo: TcxTreeListColumnViewInfo;
|
|
FVisibleIndexAtBand: Integer;
|
|
FWidth: Integer;
|
|
FOnGetDisplayText: TcxTreeListOnGetDisplayTextEvent;
|
|
function GetDataBinding: TcxItemDataBinding;
|
|
function GetDisplayText(Index: Integer): string;
|
|
function GetDisplayWidth: Integer;
|
|
function GetEditingProperties: TcxTreeListGetEditPropertiesEvent;
|
|
function GetEditProperties: TcxTreeListGetEditPropertiesEvent;
|
|
function GetIndentWidth: Integer;
|
|
function GetIsFixed: Boolean;
|
|
function GetIsHidden: Boolean;
|
|
function GetIsLeft: Boolean;
|
|
function GetIsLeftMost: Boolean;
|
|
function GetIsRightMost: Boolean;
|
|
function GetIsPreview: Boolean;
|
|
function GetIsRight: Boolean;
|
|
function GetIsWidthStored: Boolean;
|
|
function GetOptions: TcxTreeListColumnOptions;
|
|
function GetOwnerBandRow: TcxTreeListBandRow;
|
|
function GetRealMinWidth: Integer;
|
|
function GetRealWidth: Integer;
|
|
function GetStyles: TcxTreeListColumnStyles;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetVisible: Boolean;
|
|
function GetVisibility: Boolean;
|
|
function GetWidth: Integer;
|
|
procedure SetCaption(Value: TcxTreeListCaption);
|
|
procedure SetDataBinding(Value: TcxItemDataBinding);
|
|
procedure SetEditingProperties(Value: TcxTreeListGetEditPropertiesEvent);
|
|
procedure SetEditProperties(Value: TcxTreeListGetEditPropertiesEvent);
|
|
procedure SetIsPreview(Value: Boolean);
|
|
procedure SetMinWidth(Value: Integer);
|
|
procedure SetOptions(Value: TcxTreeListColumnOptions);
|
|
procedure SetOwnerBand(Value: TcxTreeListBand);
|
|
procedure SetPosition(Value: TcxTreeListColumnPosition);
|
|
procedure SetSorted(Value: TcxDataSortOrder);
|
|
procedure SetStyles(Value: TcxTreeListColumnStyles);
|
|
procedure SetSummaryFooter(Value: TcxTreeListColumnSummaryFooter);
|
|
procedure SetVisible(Value: Boolean);
|
|
procedure SetWidth(Value: Integer);
|
|
protected
|
|
// container metods
|
|
procedure DoSizeChanged; virtual;
|
|
function CanInitEditing: Boolean; override;
|
|
function CanMoving: Boolean; virtual;
|
|
function CanFocus: Boolean; override;
|
|
function CanSorted: Boolean; virtual;
|
|
function GetHeaderFooterBestfitSize: Integer; virtual;
|
|
function GetOptionsClass: TcxCustomEditContainerItemOptionsClass; override;
|
|
function GetRealSortOrder: TcxDataSortOrder; virtual;
|
|
function GetState(Index: Integer): Boolean;
|
|
function GetStylesClass: TcxEditContainerStylesClass; override;
|
|
function GetSummaryFooterClass: TcxTreeListColumnSummaryFooterClass; virtual;
|
|
procedure SetEditingControl(Value: TcxEditingControl); override;
|
|
procedure SetName(const Value: TComponentName); override;
|
|
procedure SetParentComponent(Value: TComponent); override;
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
// IcxTreeListDragSizing implementation
|
|
function CanSizing(ADirection: TcxDragSizingDirection): Boolean; virtual;
|
|
function GetAvailableMaxWidth: Integer; virtual;
|
|
function GetRealMinSize: Integer;
|
|
function GetSizingBoundsRect(ADirection: TcxDragSizingDirection): TRect; virtual;
|
|
function GetSizingIncrement(ADirection: TcxDragSizingDirection): Integer; virtual;
|
|
function IsDynamicUpdate: Boolean; virtual;
|
|
procedure SetSizeDelta(ADirection: TcxDragSizingDirection; ADelta: Integer); virtual;
|
|
// IcxTreeListIndexedItem
|
|
function GetItemIndex: Integer;
|
|
function GetVisibleIndex: Integer;
|
|
procedure SetItemIndex(Value: Integer);
|
|
procedure SetVisibleIndex(Value: Integer);
|
|
// IcxStoredObject
|
|
function GetObjectName: string;
|
|
function GetProperties(AProperties: TStrings): Boolean; virtual;
|
|
function GetPropertyIndex(const AName: string): Integer;
|
|
procedure GetPropertyValue(const AName: string; var AValue: Variant); virtual;
|
|
procedure SetPropertyValue(const AName: string; const AValue: Variant); virtual;
|
|
// column metods
|
|
procedure DoGetDisplayText(ARecordIndex: Integer; var AText: string); override;
|
|
function DoGetNodeDisplayText(ANode: TcxTreeListNode; const AValue: Variant): Variant; virtual;
|
|
function DoOnGetDisplayText(ANode: TcxTreeListNode; AsText: Boolean = False;
|
|
AValueOnly: Boolean = False): Variant; virtual;
|
|
procedure DoVisibilityChanged; virtual;
|
|
function GetCellHeight(ANode: TcxTreeListNode; AWidth, ALines: Integer;
|
|
AFont: TFont; const AValue: Variant): Integer;
|
|
function GetPositionClass: TcxTreeListColumnPositionClass; virtual;
|
|
function GetViewInfoClass: TcxTreeListColumnViewInfoClass; virtual;
|
|
function HasDataTextHandler: Boolean; override;
|
|
procedure InitAutoWidthItem(AItem: TcxAutoWidthItem); virtual;
|
|
procedure InternalSetBandOwner(ABand: TcxTreeListBand; RemoveFromOwner: Boolean); virtual;
|
|
function IsBandAssigned: Boolean;
|
|
procedure PositionChanged;
|
|
procedure UpdateIndexesBeforeRemove;
|
|
|
|
property Data: Integer read FData write FData;
|
|
property IsFixed: Boolean read GetIsFixed;
|
|
property ViewInfo: TcxTreeListColumnViewInfo read FViewInfo;
|
|
property Controller;
|
|
property EditingControl;
|
|
property EditViewData;
|
|
property OnChangeName: TNotifyEvent read FOnChangeName write FOnChangeName;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure ApplyBestFit;
|
|
function GetParentComponent: TComponent; override;
|
|
function HasParent: Boolean; override;
|
|
procedure MakeVisible;
|
|
procedure RestoreDefaults; virtual;
|
|
procedure RestoreWidths; virtual;
|
|
property DisplayTexts[Index: Integer]: string read GetDisplayText;
|
|
property DisplayWidth: Integer read GetDisplayWidth;
|
|
property IndentWidth: Integer read GetIndentWidth;
|
|
property IsHidden: Boolean read GetIsHidden;
|
|
property IsLeft: Boolean read GetIsLeft;
|
|
property IsLeftMost: Boolean read GetIsLeftMost;
|
|
property IsRightMost: Boolean read GetIsRightMost;
|
|
property IsPreview: Boolean read GetIsPreview write SetIsPreview;
|
|
property IsRight: Boolean read GetIsRight;
|
|
property OwnerBand: TcxTreeListBand read FOwnerBand write SetOwnerBand;
|
|
property OwnerBandRow: TcxTreeListBandRow read GetOwnerBandRow;
|
|
property PropertiesValue;
|
|
property RealMinWidth: Integer read GetRealMinWidth;
|
|
property RealWidth: Integer read GetRealWidth;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property Visibility: Boolean read GetVisibility;
|
|
property VisibleIndex: Integer read GetVisibleIndex;
|
|
property VisibleIndexAtBand: Integer read FVisibleIndexAtBand;
|
|
property Editing;
|
|
property EditValue;
|
|
property Focused;
|
|
property ItemIndex read GetItemIndex write SetItemIndex;
|
|
property Value;
|
|
property ValueCount;
|
|
property Values;
|
|
published
|
|
property Visible: Boolean read GetVisible write SetVisible default True;
|
|
property Caption: TcxTreeListCaption read FCaption write SetCaption;
|
|
property DataBinding: TcxItemDataBinding read GetDataBinding write SetDataBinding;
|
|
property MinWidth: Integer read FMinWidth write SetMinWidth default cxTreeListDefMinWidth;
|
|
property Options: TcxTreeListColumnOptions read GetOptions write SetOptions;
|
|
property Width: Integer read GetWidth write SetWidth stored GetIsWidthStored;
|
|
property Position: TcxTreeListColumnPosition read FPosition write SetPosition;
|
|
property SortOrder: TcxDataSortOrder read FSortOrder write SetSorted default soNone;
|
|
property Styles: TcxTreeListColumnStyles read GetStyles write SetStyles;
|
|
property SummaryFooter: TcxTreeListColumnSummaryFooter read FSummaryFooter write SetSummaryFooter;
|
|
property OnGetDisplayText: TcxTreeListOnGetDisplayTextEvent read FOnGetDisplayText write FOnGetDisplayText;
|
|
property OnGetEditingProperties: TcxTreeListGetEditPropertiesEvent read GetEditingProperties write SetEditingProperties;
|
|
property OnGetEditProperties: TcxTreeListGetEditPropertiesEvent read GetEditProperties write SetEditProperties;
|
|
property PropertiesClassName;
|
|
property Properties;
|
|
property PropertiesEvents;
|
|
property RepositoryItem;
|
|
end;
|
|
|
|
TcxTreeListColumnClass = class of TcxTreeListColumn;
|
|
|
|
{ TcxTreeListDragAndDropObject }
|
|
|
|
TcxTreeListDragDropInfo = class
|
|
public
|
|
DropPos: TPoint;
|
|
Accepted: Boolean;
|
|
end;
|
|
|
|
TcxTreeListDragDropInfoClass = class of TcxTreeListDragDropInfo;
|
|
|
|
TcxTreeListHeaderDragDropInfo = class(TcxTreeListDragDropInfo)
|
|
public
|
|
DropBand: TcxTreeListBand;
|
|
DropViewInfo: TcxTreeListHeaderViewInfo;
|
|
IsInsertRow: Boolean;
|
|
ColIndex: Integer;
|
|
RowIndex: Integer;
|
|
end;
|
|
|
|
TcxTreeListDragAndDropObject = class(TcxCustomControlDragAndDropObject)
|
|
private
|
|
function CanDropHeaderObject: Boolean;
|
|
function GetDragBand: TcxTreeListBand;
|
|
function GetDragColumn: TcxTreeListColumn;
|
|
function GetDragItem: TObject;
|
|
function GetHitTest: TcxTreeListHitTest;
|
|
function GetPainter: TcxTreeListControlPainter;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
procedure InitDropBandInfo;
|
|
procedure InitDropColumnInfo;
|
|
protected
|
|
ScreenArrows: TcxPlaceArrows;
|
|
DragDropInfo: TcxTreeListDragDropInfo;
|
|
PrevColIndex: Integer;
|
|
ArrowBaseLine: TRect;
|
|
procedure BeginDragAndDrop; override;
|
|
function GetDisplayRect: TRect; override;
|
|
function GetDragAndDropCursor(Accepted: Boolean): TCursor; override;
|
|
procedure ChangeArrowPos(const ABaseLine: TRect; AllowHide: Boolean);
|
|
function CheckCustomizingBox(const APos: TPoint): Boolean;
|
|
function CheckDropPos(ADragIndex, ADropIndex, DragX, DropX: Integer;
|
|
var APos: Integer; var ASide: TcxBorder; ACheckIndex: Boolean = True): Boolean;
|
|
procedure DoDrawHeaderItem(AItem: TcxTreeListHeaderViewInfo);
|
|
procedure DoDrawArrows;
|
|
procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override;
|
|
procedure DropHeaderItem; virtual;
|
|
procedure DropNodes; virtual;
|
|
procedure EndDragAndDrop(Accepted: Boolean); override;
|
|
function GetAcceptedRect: TRect; override;
|
|
function GetArrowBaseLine(const ARect: TRect; ASide: TcxBorder): TRect;
|
|
procedure GetArrowRects(out R1, R2: TRect);
|
|
function GetDragDropInfoClass: TcxTreeListDragDropInfoClass; virtual;
|
|
procedure InitDropHeaderInfo; virtual;
|
|
procedure InitDropInfo(const P: TPoint); virtual;
|
|
function IsValidForDrop(AIndex, ADropIndex: Integer; PosIsGreater: Boolean): Boolean;
|
|
procedure Paint; override;
|
|
procedure RestoreArrows;
|
|
procedure RestorePosition;
|
|
procedure StorePosition;
|
|
property DragItem: TObject read GetDragItem;
|
|
property Painter: TcxTreeListControlPainter read GetPainter;
|
|
public
|
|
destructor Destroy; override;
|
|
function IsDragBand: Boolean;
|
|
function IsDragColumn: Boolean;
|
|
property DragBand: TcxTreeListBand read GetDragBand;
|
|
property DragColumn: TcxTreeListColumn read GetDragColumn;
|
|
property HitTest: TcxTreeListHitTest read GetHitTest;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
end;
|
|
|
|
{ TcxTreeListCellNavigator }
|
|
|
|
TcxTreeListCellNavigator = class(TcxCustomCellNavigator)
|
|
private
|
|
function GetCellIndex(AColumn: TcxTreeListColumn; ABandRow: TcxTreeListBandRow): Integer;
|
|
function GetFocusedNode: TcxTreeListNode;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GoToNextCellInBand(AForward: Boolean; AColumn: TcxTreeListColumn; var ACellIndex: Integer): Boolean;
|
|
function GoToNextNodeCell(AForward: Boolean; ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var ACellIndex: Integer): Boolean;
|
|
protected
|
|
procedure AppendRecord(var ARowIndex, ACellIndex: Integer);
|
|
procedure CalcNextRow(AForward: Boolean; var ARowIndex, ACellIndex: Integer); override;
|
|
function GetCount(ARecordIndex: Integer): Integer; override;
|
|
function GetCellContainer(ARowIndex, ACellIndex: Integer): TcxCustomInplaceEditContainer; override;
|
|
procedure Init(var ARowIndex, ACellIndex, ARowCount: Integer); override;
|
|
function IsGroupRow(ARowIndex: Integer): Boolean;
|
|
function SelectCell(AForward, ANextRow: Boolean;
|
|
var ARowIndex, ACellIndex: Integer): TcxCustomInplaceEditContainer; override;
|
|
procedure SetFocusCell(ARowIndex, ACellIndex: Integer; AShift: TShiftState); override;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property FocusedNode: TcxTreeListNode read GetFocusedNode;
|
|
public
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure Refresh; override;
|
|
end;
|
|
|
|
{ TcxTreeListController }
|
|
|
|
TcxTreeListController = class(TcxCustomControlController)
|
|
private
|
|
function GetDataController: TcxControlDataController;
|
|
function GetFocusedNode: TcxTreeListNode;
|
|
function GetHitTest: TcxTreeListHitTest;
|
|
function GetIsControllerEvent: Boolean;
|
|
function GetOptionsBehavior: TcxTreeListOptionsBehavior;
|
|
function GetSelection: TList;
|
|
function GetSelectionAnchor: TcxTreeListNode;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
procedure SetIsControllerEvent(Value: Boolean);
|
|
procedure SetFocusedNode(ANode: TcxTreeListNode);
|
|
protected
|
|
BlockFocusChanged: Boolean;
|
|
DragNodesList: TList;
|
|
DragColumn: TcxTreeListColumn;
|
|
DragNode: TcxTreeListNode;
|
|
ForceFocusedRecord: Integer;
|
|
ForceWidthItem: TObject;
|
|
PrevTopVisibleIndex: Integer;
|
|
PrevHotShift, CurrentShiftState: TShiftState;
|
|
IncSearchText: string;
|
|
IncSearchNode: TcxTreeListNode;
|
|
IsControllerEventRefCount: Integer;
|
|
IsDragDropProcess: Boolean;
|
|
IsInIncSearchChanging: Boolean;
|
|
IsShiftPressed: Boolean;
|
|
PrevCursor: TCursor;
|
|
ResizeDirection: TcxDragSizingDirection;
|
|
SelectionAnchorNode: TcxTreeListNode;
|
|
ShowEditOnMouseUp: Boolean;
|
|
HotTrackNode: TcxTreeListNode;
|
|
// DragDrop fields
|
|
ExpandingNode: TcxTreeListNode;
|
|
ExpandTimer: TTimer;
|
|
ScrollControllers: array[TcxBorder] of TcxAutoScrollingObject;
|
|
procedure BeforeShowEdit; override;
|
|
procedure CheckEdit; override;
|
|
function CheckAutoScrolling(const APoint: TPoint): Boolean; virtual;
|
|
procedure CheckHitItemOnMouseDown(X, Y: Integer; Shift: TShiftState); virtual;
|
|
procedure SetFocusedRecordIndex(Value: Integer); override;
|
|
// Drag drop
|
|
procedure BeforeStartDrag; override;
|
|
procedure CheckButtonTimer; virtual;
|
|
procedure DragDrop(Source: TObject; X, Y: Integer); override;
|
|
procedure DragEnter; virtual;
|
|
procedure DragLeave; virtual;
|
|
procedure DragMove(Source: TObject; const P: TPoint; var Accepted: Boolean); virtual;
|
|
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
|
|
var Accept: Boolean); override;
|
|
procedure DropTo(ANode: TcxTreeListNode; AsChildren: Boolean); virtual;
|
|
procedure EndDrag(Target: TObject; X, Y: Integer); override;
|
|
procedure OnExpandTimer(Sender: TObject); virtual;
|
|
procedure ResetButtonTimer;
|
|
//
|
|
|
|
procedure DoChangeColumnSortOrder(AColumn: TcxTreeListColumn;
|
|
ASortOrder: TcxDataSortOrder; AShift: TShiftState); virtual;
|
|
procedure DoNextNode(AForward: Boolean);
|
|
procedure DoNextPage(AForward: Boolean; Shift: TShiftState); override;
|
|
procedure DoShowNextPageEx(AGoForward, ASetCursor: Boolean;
|
|
AShift: TShiftState); virtual;
|
|
procedure FocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex: Integer); override;
|
|
procedure FocusedItemChanged(APrevFocusedItem: TcxCustomInplaceEditContainer); override;
|
|
function IsDragMode: Boolean;
|
|
function IsKeyForController(AKey: Word; AShift: TShiftState): Boolean; override;
|
|
function IsNodeKeyHandle(ANode: TcxTreeListNode;
|
|
var AKey: Word; Shift: TShiftState): Boolean; virtual;
|
|
function GetCellFromViewInfo(AColumn: TcxTreeListColumn; ANodeViewInfo: TcxTreeListNodeViewInfo): TcxTreeListEditCellViewInfo; virtual;
|
|
function GetCellFromViewInfoEx(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode): TcxTreeListEditCellViewInfo; virtual;
|
|
function GetFocusedCellViewInfo(AEditContainer: TcxCustomInplaceEditContainer): TcxEditCellViewInfo; override;
|
|
function GetNavigatorClass: TcxCustomCellNavigatorClass; override;
|
|
function GetNode(ARecordIndex: Integer): TcxTreeListNode;
|
|
function GetResizeDirection: TcxDragSizingDirection; override;
|
|
procedure MouseLeave; override;
|
|
procedure DoCancelMode; override;
|
|
function ValidateShift(Shift: TShiftState): TShiftState;
|
|
procedure UpdateRecord(ARecordIndex: Integer); override;
|
|
// incsearch
|
|
procedure CancelIncSearching; override;
|
|
function DoSearch(AFromNode: TcxTreeListNode; AItemIndex: Integer;
|
|
const AText: string; AGoForward: Boolean): Boolean; virtual;
|
|
function GetIncSearchingItem: TcxCustomInplaceEditContainer; override;
|
|
function GetIncSearchingText: string; override;
|
|
function GetIsIncSearching: Boolean; override;
|
|
function GetNextIncSearchNode(ANode: TcxTreeListNode; AGoForward: Boolean): TcxTreeListNode;
|
|
procedure SearchCheck(AItemFound: Boolean);
|
|
procedure SearchLocate(AItem: TcxCustomInplaceEditContainer; const Value: string); override;
|
|
procedure SearchLocateNext(AItem: TcxCustomInplaceEditContainer; AForward: Boolean); override;
|
|
procedure UpdateNodeIncSearchingCell(ANode: TcxTreeListNode);
|
|
// design selection
|
|
procedure SelectionTimerHandler(ASender: TObject);
|
|
function CanCreateSelectionHelper: Boolean;
|
|
function IsObjectSelected(AObject: TPersistent): Boolean; virtual;
|
|
procedure SelectObject(AObject: TPersistent; AShift: TShiftState); virtual;
|
|
procedure UnselectObject(AObject: TPersistent); virtual;
|
|
// selection
|
|
procedure CancelSelection(KeepPrimary: Boolean = True);
|
|
procedure Select(ANode: TcxTreeListNode; Shift: TShiftState); virtual;
|
|
property IsControllerEvent: Boolean read GetIsControllerEvent write SetIsControllerEvent;
|
|
property SelectionAnchor: TcxTreeListNode read GetSelectionAnchor;
|
|
property Selection: TList read GetSelection;
|
|
property DataController: TcxControlDataController read GetDataController;
|
|
public
|
|
procedure AfterPaint; override;
|
|
procedure BeforePaint; override;
|
|
procedure BeforeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure BeginDragAndDrop; override;
|
|
function CanDrag(X, Y: Integer): Boolean; override;
|
|
function CanDeleteSelection: Boolean;
|
|
function CanInsertNode: Boolean;
|
|
procedure ControlFocusChanged; override;
|
|
procedure DblClick; override;
|
|
function DeleteConfirmation: Boolean;
|
|
procedure DoMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure DoMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure EndDragAndDrop(Accepted: Boolean); override;
|
|
function HitAtNodeEx: Boolean;
|
|
function GetCursor(X, Y: Integer): TCursor; override;
|
|
function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override;
|
|
function GetImmediateEditor: Boolean; override;
|
|
function IsDragCopy: Boolean; virtual;
|
|
function IsDestroying: Boolean; virtual;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure MakeFocusedItemVisible; override;
|
|
procedure MakeFocusedRecordVisible; override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode;
|
|
var AScrollPos: Integer); override;
|
|
procedure SetFocusedRecordItem(ARecordIndex: Integer;
|
|
AItem: TcxCustomInplaceEditContainer); override;
|
|
procedure SetHotTrackCursor(ACursor: TCursor);
|
|
procedure SetHotTrackNode(ANode: TcxTreeListNode; AShift: TShiftState);
|
|
function StartDragAndDrop(const P: TPoint): Boolean; override;
|
|
procedure UpdateHotTrackNode(AShift: TShiftState); overload;
|
|
procedure UpdateHotTrackNode(X, Y: Integer; AShift: TShiftState); overload;
|
|
property HitTest: TcxTreeListHitTest read GetHitTest;
|
|
property FocusedNode: TcxTreeListNode read GetFocusedNode write SetFocusedNode;
|
|
property OptionsBehavior: TcxTreeListOptionsBehavior read GetOptionsBehavior;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
end;
|
|
|
|
{ TcxTreeListHitTest }
|
|
|
|
TcxTreeListHitTest = class(TcxCustomHitTestController)
|
|
private
|
|
FHitBand: TcxTreeListBand;
|
|
FHitColumn: TcxTreeListColumn;
|
|
FHitNode: TcxTreeListNode;
|
|
FPressedHeader: TcxTreeListHeaderViewInfo;
|
|
FSizingHitNode: TcxTreeListNode;
|
|
function CheckHitInBand(AViewInfo: TcxTreeListBandViewInfo): Boolean;
|
|
function CheckHitInColumn(AViewInfo: TcxTreeListColumnViewInfo): Boolean;
|
|
function CheckHitInNode(AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
function HitInGroup(AViewInfo: TcxTreeListCellsGroupViewInfo): Boolean;
|
|
function HitInGroups(AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
function HitInIndent(AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
function HitInItem(AItem: TcxCustomViewInfoItem; AState: Integer; ADelta: Integer = 0): Boolean;
|
|
function GetHitAtImages: Boolean;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetViewInfo: TcxTreeListViewInfo;
|
|
protected
|
|
FLockUpdate: Boolean;
|
|
FNewHitTestItem: TObject;
|
|
function AllowDesignMouseEvents(X, Y: Integer; AShift: TShiftState): Boolean; override;
|
|
procedure DoCalculate; override;
|
|
function Check(const ARect: TRect): Boolean;
|
|
function CheckHitInBands: Boolean; virtual;
|
|
function CheckHitInNodes: Boolean;
|
|
function GetCurrentCursor: TCursor; override;
|
|
function GetHitTestItem: TObject; virtual;
|
|
function GetState(Index: Integer): Boolean;
|
|
procedure HitTestItemChanged(APrevHitTestItem: TObject); override;
|
|
procedure SetHitState(Index: Integer; Value: Boolean);
|
|
procedure Update; virtual;
|
|
property PressedHeader: TcxTreeListHeaderViewInfo read FPressedHeader;
|
|
property SizingHitNode: TcxTreeListNode read FSizingHitNode;
|
|
property ViewInfo: TcxTreeListViewInfo read GetViewInfo;
|
|
public
|
|
function CanMoving: Boolean; virtual;
|
|
function CanSizing: Boolean; overload;
|
|
function CanSizing(var ASizeDirection: TcxDragSizingDirection): Boolean; overload; virtual;
|
|
property CurrentCursor: TCursor read GetCurrentCursor;
|
|
property HitAtBand: Boolean index tlhc_HitAtBand read GetState;
|
|
property HitAtBandContainer: Boolean index tlhc_HitAtBandContainer read GetState;
|
|
property HitAtBandHeader: Boolean index tlhc_HitAtBandHeader read GetState;
|
|
property HitAtButton: Boolean index tlhc_HitAtButton read GetState;
|
|
property HitAtColumn: Boolean index tlhc_HitAtColumn read GetState;
|
|
property HitAtColumnHeader: Boolean index tlhc_HitAtColumnHeader read GetState;
|
|
property HitAtFooter: Boolean index tlhc_HitAtFooter read GetState;
|
|
property HitAtFooterItem: Boolean index tlhc_HitAtFooterItem read GetState;
|
|
property HitAtImage: Boolean index tlhc_HitAtImage read GetState;
|
|
property HitAtImages: Boolean read GetHitAtImages;
|
|
property HitAtIndent: Boolean index tlhc_HitAtIndent read GetState;
|
|
property HitAtIndicator: Boolean index tlhc_HitAtIndicator read GetState;
|
|
property HitAtStateImage: Boolean index tlhc_HitAtStateImage read GetState;
|
|
property HitAtNode: Boolean index tlhc_HitAtNode read GetState;
|
|
property HitAtNodePreview: Boolean index tlhc_HitAtNodePreview read GetState;
|
|
property HitAtSeparator: Boolean index tlhc_HitAtSeparator read GetState;
|
|
property HitAtSizingHorz: Boolean index tlhc_HitAtSizingHorz read GetState;
|
|
property HitAtSizingVert: Boolean index tlhc_HitAtSizingVert read GetState;
|
|
property HitBand: TcxTreeListBand read FHitBand;
|
|
property HitColumn: TcxTreeListColumn read FHitColumn;
|
|
property HitNode: TcxTreeListNode read FHitNode;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
end;
|
|
|
|
{ TcxTreeListViewInfoItem }
|
|
|
|
TcxTreeListSeparators = array[0..1] of TRect;
|
|
|
|
TcxTreeListViewInfoItem = class(TcxCustomViewInfoItem, IUnknown)
|
|
private
|
|
FBrush: TBrush;
|
|
function GetBrushManager: TcxBrushCache;
|
|
function GetControlViewInfo: TcxTreeListViewInfo;
|
|
function GetHitTestProp: TcxTreeListHitTest;
|
|
function GetOptionsView: TcxTreeListOptionsView;
|
|
function GetPainterClass: TcxCustomLookAndFeelPainterClass;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
procedure Calculate(const ADisplayRect, AVisibleRect: TRect); virtual;
|
|
procedure DoCalculate; override;
|
|
procedure DoHorzOffset(AShift: Integer); override;
|
|
procedure DoVertOffset(AShift: Integer); override;
|
|
function ShiftItem(const AVisibleRect: TRect; DX, DY: Integer): Boolean;
|
|
// IUnknown
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
property Brush: TBrush read FBrush;
|
|
property BrushManager: TcxBrushCache read GetBrushManager;
|
|
property OptionsView: TcxTreeListOptionsView read GetOptionsView;
|
|
property ControlViewInfo: TcxTreeListViewInfo read GetControlViewInfo;
|
|
public
|
|
constructor Create(AOwner: TObject); override;
|
|
destructor Destroy; override;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property HitTest: TcxTreeListHitTest read GetHitTestProp;
|
|
property LookAndFeelPainter: TcxCustomLookAndFeelPainterClass read GetPainterClass;
|
|
end;
|
|
|
|
{ TcxTreeListIndicatorViewInfo }
|
|
|
|
TcxTreeListIndicatorViewInfo = class(TcxTreeListViewInfoItem)
|
|
private
|
|
FKind: TcxIndicatorKind;
|
|
FNode: TcxTreeListNode;
|
|
protected
|
|
procedure Calculate(const ADisplayRect, AVisibleRect: TRect); override;
|
|
procedure DoCalculate; override;
|
|
procedure DoVertOffset(AShift: Integer); override;
|
|
function GetControl: TcxEditingControl; override;
|
|
procedure UpdateKind(AKind: TcxIndicatorKind);
|
|
public
|
|
property Node: TcxTreeListNode read FNode;
|
|
property Kind: TcxIndicatorKind read FKind;
|
|
property TreeList;
|
|
end;
|
|
|
|
TcxTreeListIndicatorViewInfoClass = class of TcxTreeListIndicatorViewInfo;
|
|
|
|
{ TcxTreeListFooterItemViewInfo }
|
|
|
|
TcxTreeListFooterItemViewInfo = class(TcxTreeListViewInfoItem)
|
|
private
|
|
function GetAlignHorz: TAlignment;
|
|
function GetAlignVert: TcxAlignmentVert;
|
|
function GetBandViewInfo: TcxTreeListBandViewInfo;
|
|
function GetColumn: TcxTreeListColumnViewInfo;
|
|
function GetFooterSummary: TcxTreeListColumnSummaryFooter;
|
|
function GetMultiLine: Boolean;
|
|
function GetText: string;
|
|
function GetVisible: Boolean;
|
|
protected
|
|
procedure DoHorzOffset(DX: Integer); override;
|
|
function GetControl: TcxEditingControl; override;
|
|
property FooterSummary: TcxTreeListColumnSummaryFooter read GetFooterSummary;
|
|
public
|
|
property Column: TcxTreeListColumnViewInfo read GetColumn;
|
|
property AlignHorz: TAlignment read GetAlignHorz;
|
|
property AlignVert: TcxAlignmentVert read GetAlignVert;
|
|
property BandViewInfo: TcxTreeListBandViewInfo read GetBandViewInfo;
|
|
property MultiLine: Boolean read GetMultiLine;
|
|
property Text: string read GetText;
|
|
property Visible: Boolean read GetVisible;
|
|
property TreeList;
|
|
end;
|
|
|
|
{ TcxTreeListHeaderViewInfo }
|
|
|
|
TcxTreeListHeaderViewInfo = class(TcxTreeListViewInfoItem, IcxDragSizing, IcxHotTrackElement)
|
|
private
|
|
FBorders: TcxBorders;
|
|
FGlyphPos: TPoint;
|
|
FNeighbors: TcxNeighbors;
|
|
FPressed: Boolean;
|
|
FState: TcxButtonState;
|
|
procedure CustomDrawEvent(var AEvent: TcxCustomDrawViewInfoItemEvent); virtual;
|
|
function GetAlignHorz: TAlignment;
|
|
function GetAlignVert: TcxAlignmentVert;
|
|
function GetBand: TcxTreeListBand;
|
|
function GetBandViewInfo: TcxTreeListBandViewInfo; virtual;
|
|
function GetButtonState: TcxButtonState;
|
|
function GetCaption: TcxTreeListCaption; virtual;
|
|
function GetGlyph: TBitmap;
|
|
function GetGlyphAlignHorz: TAlignment;
|
|
function GetGlyphAlignVert: TcxAlignmentVert;
|
|
function GetHotTrack: Boolean;
|
|
function GetState(Index: Integer): Boolean;
|
|
function GetText: string;
|
|
procedure SetPressed(Value: Boolean);
|
|
protected
|
|
FCallHintNeeded: Integer;
|
|
FSortMarkBounds: TRect;
|
|
FTextBounds: TRect;
|
|
NeedGlyphClipping: Boolean;
|
|
procedure ButtonStateChanged(APrevIsPressed, IsPressed: Boolean); virtual;
|
|
function CanDropAt(const P: TPoint): Boolean; virtual;
|
|
procedure DoCalculate; override;
|
|
procedure DoCalculateGlyphPosition;
|
|
procedure DoHorzOffset(DX: Integer); override;
|
|
function GetDisplayRect: TRect; virtual;
|
|
function GetDragSizing: IcxDragSizing; virtual;
|
|
function GetDroppingRect: TRect; virtual;
|
|
function GetControl: TcxEditingControl; override;
|
|
function GetSelected: Boolean; virtual;
|
|
function GetSortOrder: TcxDataSortOrder; virtual;
|
|
procedure InitViewParams; virtual;
|
|
procedure UpdateState;
|
|
// IcxHotTrackElement
|
|
function GetOrigin: TPoint; virtual;
|
|
function IsNeedHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption;
|
|
out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; virtual;
|
|
procedure UpdateHotTrackState(const APoint: TPoint); virtual;
|
|
property BandViewInfo: TcxTreeListBandViewInfo read GetBandViewInfo;
|
|
property Caption: TcxTreeListCaption read GetCaption;
|
|
property DragSizing: IcxDragSizing read GetDragSizing implements IcxDragSizing;
|
|
property Pressed: Boolean read FPressed write SetPressed;
|
|
property SortMarkBounds: TRect read FSortMarkBounds;
|
|
property SortOrder: TcxDataSortOrder read GetSortOrder;
|
|
public
|
|
destructor Destroy; override;
|
|
property AlignHorz: TAlignment read GetAlignHorz;
|
|
property AlignVert: TcxAlignmentVert read GetAlignVert;
|
|
property Band: TcxTreeListBand read GetBand;
|
|
property Borders: TcxBorders read FBorders;
|
|
property Glyph: TBitmap read GetGlyph;
|
|
property GlyphAlignHorz: TAlignment read GetGlyphAlignHorz;
|
|
property GlyphAlignVert: TcxAlignmentVert read GetGlyphAlignVert;
|
|
property GlyphPos: TPoint read FGlyphPos;
|
|
property ShowEndEllipsis: Boolean index 1 read GetState;
|
|
property HotTrack: Boolean read GetHotTrack;
|
|
property MultiLine: Boolean index 2 read GetState;
|
|
property Neighbors: TcxNeighbors read FNeighbors;
|
|
property Selected: Boolean read GetSelected;
|
|
property State: TcxButtonState read FState;
|
|
property Text: string read GetText;
|
|
property TextBounds: TRect read FTextBounds;
|
|
property TreeList;
|
|
end;
|
|
|
|
{ TcxTreeListColumnHeaderViewInfo }
|
|
|
|
TcxTreeListColumnHeaderViewInfo = class(TcxTreeListHeaderViewInfo)
|
|
private
|
|
FIsUltraFlat: Boolean;
|
|
procedure CustomDrawEvent(var AEvent: TcxCustomDrawViewInfoItemEvent); override;
|
|
function GetBandViewInfo: TcxTreeListBandViewInfo; override;
|
|
function GetCaption: TcxTreeListCaption; override;
|
|
function GetColumn: TcxTreeListColumn;
|
|
protected
|
|
procedure ButtonStateChanged(APrevIsPressed, IsPressed: Boolean); override;
|
|
function CanDropAt(const P: TPoint): Boolean; override;
|
|
procedure DoCalculate; override;
|
|
function GetControl: TcxEditingControl; override;
|
|
function GetDisplayRect: TRect; override;
|
|
function GetDragSizing: IcxDragSizing; override;
|
|
function GetDroppingRect: TRect; override;
|
|
function GetSortOrder: TcxDataSortOrder; override;
|
|
procedure InitViewParams; override;
|
|
function GetSelected: Boolean; override;
|
|
property DragSizing;
|
|
public
|
|
property Column: TcxTreeListColumn read GetColumn;
|
|
property SortMarkBounds;
|
|
property SortOrder;
|
|
end;
|
|
|
|
{ TcxTreeListColumnHeaderViewInfo }
|
|
|
|
TcxTreeListColumnViewInfo = class
|
|
private
|
|
FColumn: TcxTreeListColumn;
|
|
FColumnHeader: TcxTreeListColumnHeaderViewInfo;
|
|
FColumnFooter: TcxTreeListFooterItemViewInfo;
|
|
function GetBandViewInfo: TcxTreeListBandViewInfo;
|
|
function GetDisplayWidth: Integer;
|
|
function GetFooterCellsOffset: Integer;
|
|
function GetLineCount: Integer;
|
|
function GetOptionsView: TcxTreeListOptionsView;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
XOfs: Integer;
|
|
YOfs: Integer;
|
|
function CalcHeaderRect: TRect;
|
|
function CalcFooterRect: TRect;
|
|
procedure DoCalculate; virtual;
|
|
procedure DoHorzOffset(DX: Integer); virtual;
|
|
property DisplayWidth: Integer read GetDisplayWidth;
|
|
property FooterCellsOffset: Integer read GetFooterCellsOffset;
|
|
property LineCount: Integer read GetLineCount;
|
|
property OptionsView: TcxTreeListOptionsView read GetOptionsView;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListColumn); virtual;
|
|
destructor Destroy; override;
|
|
property BandViewInfo: TcxTreeListBandViewInfo read GetBandViewInfo;
|
|
property Column: TcxTreeListColumn read FColumn;
|
|
property ColumnFooter: TcxTreeListFooterItemViewInfo read FColumnFooter;
|
|
property ColumnHeader: TcxTreeListColumnHeaderViewInfo read FColumnHeader;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
end;
|
|
|
|
{ TcxTreeListBandViewInfo }
|
|
|
|
TcxTreeListBandViewInfo = class(TcxTreeListViewInfoItem)
|
|
private
|
|
FBandHeader: TcxTreeListHeaderViewInfo;
|
|
FCapacity: Integer;
|
|
FColumns: PPointerList;
|
|
FContainerViewParams: TcxViewParams;
|
|
FCount: Integer;
|
|
FFooterRect: TRect;
|
|
FFooterViewParams: TcxViewParams;
|
|
function GetBand: TcxTreeListBand;
|
|
function GetColumn(AIndex: Integer): TcxTreeListColumnViewInfo;
|
|
function GetDisplayWidth: Integer;
|
|
function GetFixed: TcxTreeListBandFixedKind;
|
|
protected
|
|
ContainerBrush: TBrush;
|
|
FooterBrush: TBrush;
|
|
IsOpaque: Boolean;
|
|
procedure CalcFooterRect;
|
|
procedure CheckOpaque; virtual;
|
|
procedure DoCalculate; override;
|
|
procedure DoCalculateColumns;
|
|
procedure DoHorzOffset(DX: Integer); override;
|
|
function GetControl: TcxEditingControl; override;
|
|
procedure SetCapacity(ACapacity: Integer);
|
|
property DisplayWidth: Integer read GetDisplayWidth;
|
|
public
|
|
constructor Create(AOwner: TObject); override;
|
|
destructor Destroy; override;
|
|
property Band: TcxTreeListBand read GetBand;
|
|
property BandHeader: TcxTreeListHeaderViewInfo read FBandHeader;
|
|
property ColumnCount: Integer read FCount;
|
|
property Columns[AIndex: Integer]: TcxTreeListColumnViewInfo read GetColumn;
|
|
property ContainerViewParams: TcxViewParams read FContainerViewParams;
|
|
property FooterViewParams: TcxViewParams read FFooterViewParams;
|
|
property Fixed: TcxTreeListBandFixedKind read GetFixed;
|
|
property FooterRect: TRect read FFooterRect;
|
|
property Opaque: Boolean read IsOpaque;
|
|
end;
|
|
|
|
{ TcxTreeListEditCellViewInfo }
|
|
|
|
TcxTreeListEditCellViewInfo = class(TcxEditCellViewInfo)
|
|
private
|
|
function GetBand: TcxTreeListBand;
|
|
function GetControlViewInfo: TcxTreeListViewInfo;
|
|
function GetEditRect: TRect;
|
|
function GetGroup: TcxTreeListCellsGroupViewInfo;
|
|
function GetNode: TcxTreeListNode; virtual;
|
|
function GetNodesViewInfo: TcxTreeListNodesViewInfo; virtual;
|
|
function GetNodeViewInfo: TcxTreeListNodeViewInfo; virtual;
|
|
function GetTreeList: TcxCustomTreeListControl; virtual;
|
|
protected
|
|
GroupIndex: Integer;
|
|
FColumnViewInfo: TcxTreeListColumnViewInfo;
|
|
function ContentOffset: TRect; override;
|
|
function ChangedHeight(APrevHeight, ANewHeight: Integer): Boolean; override;
|
|
procedure CustomDrawEvent(var AEvent: TcxCustomDrawViewInfoItemEvent); virtual;
|
|
procedure DoHorzOffset(AShift: Integer); override;
|
|
procedure DoVertOffset(AShift: Integer); override;
|
|
function GetButtonTransparency: TcxEditButtonTransparency; override;
|
|
function GetColumn: TcxTreeListColumn; virtual;
|
|
function GetDisplayValue: Variant; override;
|
|
function GetEditContainer: TcxCustomInplaceEditContainer; override;
|
|
function GetEditViewParams: TcxViewParams; override;
|
|
function GetFocused: Boolean; override;
|
|
function GetHotTrack: Boolean; virtual;
|
|
function GetLineCount: Integer; virtual;
|
|
function GetLineOffset: Integer; virtual;
|
|
function GetRecordIndex: Integer; override;
|
|
function GetSelected: Boolean; virtual;
|
|
function GetSelectedTextColor: Integer; override;
|
|
function GetSelectedBKColor: Integer; override;
|
|
procedure GetTreeListEditCellParams(var AParams: TcxViewParams); virtual;
|
|
function GetViewInfoData: Pointer; override;
|
|
function IncSearchParams: TcxViewParams;
|
|
function IsAutoHeight: Boolean; override;
|
|
function IsEndEllipsis: Boolean; override;
|
|
function IsTransparent: Boolean; override;
|
|
procedure SetPosition(ATop, AHeight: Integer; const AClipRect: TRect);
|
|
procedure ShiftItem(DX, DY: Integer); virtual;
|
|
procedure UpdateViewInfoPosition;
|
|
property ControlViewInfo: TcxTreeListViewInfo read GetControlViewInfo;
|
|
property LineCount: Integer read GetLineCount;
|
|
property LineOffset: Integer read GetLineOffset;
|
|
property NodesViewInfo: TcxTreeListNodesViewInfo read GetNodesViewInfo;
|
|
property NodeViewInfo: TcxTreeListNodeViewInfo read GetNodeViewInfo;
|
|
public
|
|
procedure Assign(Source: TcxCustomViewInfoItem); override;
|
|
property Column: TcxTreeListColumn read GetColumn;
|
|
property EditRect: TRect read GetEditRect;
|
|
property Group: TcxTreeListCellsGroupViewInfo read GetGroup;
|
|
property Band: TcxTreeListBand read GetBand;
|
|
property Node: TcxTreeListNode read GetNode;
|
|
property Selected: Boolean read GetSelected;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property HotTrack: Boolean read GetHotTrack;
|
|
end;
|
|
|
|
{ TcxTreeListGroupNodeEditViewInfo }
|
|
|
|
TcxTreeListGroupNodeEditViewInfo = class(TcxTreeListEditCellViewInfo)
|
|
private
|
|
function GetCellRect: TRect;
|
|
protected
|
|
function ChangedHeight(APrevHeight, ANewHeight: Integer): Boolean; override;
|
|
procedure DoCalculate; override;
|
|
function GetColumn: TcxTreeListColumn; override;
|
|
procedure ShiftItem(DX, DY: Integer); override;
|
|
procedure Update; virtual;
|
|
end;
|
|
|
|
{ TcxTreeListNodePreviewViewInfo }
|
|
|
|
TcxTreeListNodePreviewViewInfo = class(TcxTreeListEditCellViewInfo)
|
|
private
|
|
function GetPreviewRect: TRect;
|
|
protected
|
|
Preview: TcxTreeListPreview;
|
|
PreviewHeight: Integer;
|
|
function ChangedHeight(APrevHeight, ANewHeight: Integer): Boolean; override;
|
|
function CheckPreviewHeight(DH: Integer): Integer;
|
|
function ContentOffset: TRect; override;
|
|
procedure CustomDrawEvent(var AEvent: TcxCustomDrawViewInfoItemEvent); override;
|
|
procedure DoCalculate; override;
|
|
procedure DoInitPreviewSettings(APreviewOffset: Integer); virtual;
|
|
function GetButtonTransparency: TcxEditButtonTransparency; override;
|
|
function GetColumn: TcxTreeListColumn; override;
|
|
function GetHotTrack: Boolean; override;
|
|
function GetLineCount: Integer; override;
|
|
function GetLineOffset: Integer; override;
|
|
function GetMaxLineCount: Integer; override;
|
|
procedure GetTreeListEditCellParams(var AParams: TcxViewParams); override;
|
|
function IsAutoHeight: Boolean; override;
|
|
procedure ShiftItem(DX, DY: Integer); override;
|
|
procedure Update; virtual;
|
|
public
|
|
constructor Create(AOwner: TObject); override;
|
|
property Height: Integer read PreviewHeight;
|
|
end;
|
|
|
|
TcxTreeListNodePreviewViewInfoClass = class of TcxTreeListNodePreviewViewInfo;
|
|
|
|
{ TcxTreeListCellsGroupViewInfo }
|
|
|
|
TcxTreeListCellsGroupViewInfo = class(TcxTreeListViewInfoItem)
|
|
private
|
|
function GetBand: TcxTreeListBand;
|
|
function GetCell(Index: Integer): TcxTreeListEditCellViewInfo;
|
|
function GetCellsHeight: Integer;
|
|
function GetCount: Integer;
|
|
function GetCurrentBrush: TBrush;
|
|
function GetFixed: Boolean;
|
|
function GetNode: TcxTreeListNode;
|
|
function GetNodeViewInfo: TcxTreeListNodeViewInfo;
|
|
function GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
procedure CalculateEditCellRect(ACell: TcxTreeListEditCellViewInfo; AMostLeftPos: Integer);
|
|
protected
|
|
IsOpaque: Boolean;
|
|
BandViewInfo: TcxTreeListBandViewInfo;
|
|
Borders: TcxBorders;
|
|
Indent: Integer;
|
|
FirstIndex, LastIndex: Integer;
|
|
procedure DoCalculate; override;
|
|
procedure DoCalculateCellsLayout; virtual;
|
|
procedure DoHorzOffset(AShift: Integer); override;
|
|
procedure DoVertOffset(AShift: Integer); override;
|
|
function GetControl: TcxEditingControl; override;
|
|
function GetHotTrack: Boolean; virtual;
|
|
function GetSelected: Boolean; virtual;
|
|
function GetGroupBitmap: TBitmap; virtual;
|
|
procedure SetSize(ATop, AHeight: Integer); virtual;
|
|
procedure ShiftGroup(DX, DY: Integer); virtual;
|
|
property CellsHeight: Integer read GetCellsHeight;
|
|
property CurrentBrush: TBrush read GetCurrentBrush;
|
|
property NodesViewInfo: TcxTreeListNodesViewInfo read GetNodesViewInfo;
|
|
property NodeViewInfo: TcxTreeListNodeViewInfo read GetNodeViewInfo;
|
|
property Fixed: Boolean read GetFixed;
|
|
public
|
|
procedure Assign(Source: TcxCustomViewInfoItem); override;
|
|
property Band: TcxTreeListBand read GetBand;
|
|
property CellCount: Integer read GetCount;
|
|
property Cells[Index: Integer]: TcxTreeListEditCellViewInfo read GetCell;
|
|
property Node: TcxTreeListNode read GetNode;
|
|
property Opaque: Boolean read IsOpaque;
|
|
property Selected: Boolean read GetSelected;
|
|
property HotTrack: Boolean read GetHotTrack;
|
|
end;
|
|
|
|
{ TcxTreeListIndentViewInfo }
|
|
|
|
TcxTreeListLevelTreeLine = (tltVertUp, tltVertDown, tltHorz);
|
|
TcxTreeListLevelTreeLines = set of TcxTreeListLevelTreeLine;
|
|
|
|
TcxTreeListIndentViewInfo = class(TcxTreeListViewInfoItem)
|
|
private
|
|
function GetButtonRect: TRect;
|
|
function GetIsExpanded: Boolean;
|
|
function GetNextVisible: TcxTreeListNodeViewInfo;
|
|
function GetNode: TcxTreeListNode;
|
|
function GetNodeViewInfo: TcxTreeListNodeViewInfo;
|
|
function GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
function GetPrevVisible: TcxTreeListNodeViewInfo;
|
|
protected
|
|
IndentBorders: TcxBorders;
|
|
IndentHasImage: Boolean;
|
|
IndentHasExpandButton: Boolean;
|
|
IndentHorzTreeLine: TRect;
|
|
IndentImageIndex: Integer;
|
|
IndentStateImage: Boolean;
|
|
IndentImageList: TCustomImageList;
|
|
IndentIsLevel: Boolean;
|
|
IndentLevel: Integer;
|
|
IndentLevelNode: TcxTreeListNode;
|
|
IndentTreeLines: TcxTreeListLevelTreeLines;
|
|
IndentVertTreeLine: TRect;
|
|
procedure DoCalculate; override;
|
|
procedure DoHorzOffset(AShift: Integer); override;
|
|
procedure DoVertOffset(AShift: Integer); override;
|
|
function GetControl: TcxEditingControl; override;
|
|
procedure ShiftIndent(DX, DY: Integer); virtual;
|
|
procedure UpdateImageIndex;
|
|
property NextVisible: TcxTreeListNodeViewInfo read GetNextVisible;
|
|
property NodesViewInfo: TcxTreeListNodesViewInfo read GetNodesViewInfo;
|
|
property NodeViewInfo: TcxTreeListNodeViewInfo read GetNodeViewInfo;
|
|
property PrevVisible: TcxTreeListNodeViewInfo read GetPrevVisible;
|
|
property Brush;
|
|
public
|
|
property Borders: TcxBorders read IndentBorders;
|
|
property ButtonRect: TRect read GetButtonRect;
|
|
property HasButton: Boolean read IndentHasExpandButton;
|
|
property HasImage: Boolean read IndentHasImage;
|
|
property HorzTreeLine: TRect read IndentHorzTreeLine;
|
|
property IsExpanded: Boolean read GetIsExpanded;
|
|
property IsLevel: Boolean read IndentIsLevel;
|
|
property Level: Integer read IndentLevel;
|
|
property LevelNode: TcxTreeListNode read IndentLevelNode;
|
|
property Node: TcxTreeListNode read GetNode;
|
|
property TreeLines: TcxTreeListLevelTreeLines read IndentTreeLines;
|
|
property VertTreeLine: TRect read IndentVertTreeLine;
|
|
property ImageIndex: Integer read IndentImageIndex;
|
|
property ImageList: TCustomImageList read IndentImageList;
|
|
property ViewParams;
|
|
property TreeList;
|
|
end;
|
|
|
|
{ TcxTreeListNodeViewInfo }
|
|
|
|
TcxTreeListNodeViewInfo = class
|
|
private
|
|
// subitems lists
|
|
FGroups: TList;
|
|
FCells: TList;
|
|
FIndents: TList;
|
|
// sub items
|
|
FIndicator: TcxTreeListIndicatorViewInfo;
|
|
FPreview: TcxTreeListNodePreviewViewInfo;
|
|
// other
|
|
FOwner: TcxTreeListNodesViewInfo;
|
|
function GetCell(Index: Integer): TcxTreeListEditCellViewInfo;
|
|
function GetCellCount: Integer;
|
|
function GetControlViewInfo: TcxTreeListViewInfo;
|
|
function GetFocusRect: TRect;
|
|
function GetGroup(Index: Integer): TcxTreeListCellsGroupViewInfo;
|
|
function GetGroupCount: Integer;
|
|
function GetHotTrack: Boolean;
|
|
function GetIndent(Index: Integer): TcxTreeListIndentViewInfo;
|
|
function GetIndentCount: Integer;
|
|
function GetIndentWidth: Integer;
|
|
function GetOptionsView: TcxTreeListOptionsView;
|
|
function GetRealHeight: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetVisibleIndex: Integer;
|
|
function GetVisibleRect(AFixed: Boolean): TRect;
|
|
function AddGroup(AInfo: TcxTreeListBandViewInfo; var AIndex, AOfs: Integer): TcxTreeListCellsGroupViewInfo;
|
|
procedure AddCell(AInfo: TcxTreeListColumnViewInfo; var AGroupIndex, AIndex: Integer);
|
|
procedure CalculateIndentInfo(AIndent: TcxTreeListIndentViewInfo;
|
|
var ANode: TcxTreeListNode; ALevel: Integer; var ALeft: Integer);
|
|
procedure UpdateContentRects;
|
|
procedure UpdateLinks;
|
|
protected
|
|
ViewInfoNode: TcxTreeListNode;
|
|
NodeCellsCalculated: Boolean;
|
|
NodeFocused: Boolean;
|
|
NodeHasButton: Boolean;
|
|
NodeHasPreview: Boolean;
|
|
NodeSelected: Boolean;
|
|
NodeVisible: Boolean;
|
|
NodeIsGroup: Boolean;
|
|
NodeIsExpanded: Boolean;
|
|
NodeBorders: TcxBorders;
|
|
NodeLevel: Integer;
|
|
NodeGroupEditViewInfo: TcxTreeListGroupNodeEditViewInfo;
|
|
NodeFocusedCell: TcxTreeListEditCellViewInfo;
|
|
NodeNextVisible: TcxTreeListNodeViewInfo;
|
|
NodePrevVisible: TcxTreeListNodeViewInfo;
|
|
// size and position variables
|
|
NodeIndentLeft: Integer;
|
|
NodeCellsRect: TRect; // cells only
|
|
NodeClipRect: TRect; // visible content only
|
|
NodeContentRect: TRect; // cells + preview + indicator
|
|
NodeCellsOffset: Integer;
|
|
NodePreviewOffset: Integer;
|
|
// FCellHeight: Integer;
|
|
CellsMaxHeight: Integer;
|
|
CellMaxHeightRefCount: Integer;
|
|
// fixed bands viewinfo variables
|
|
LeftFixedGroup: TcxTreeListCellsGroupViewInfo;
|
|
RightFixedGroup: TcxTreeListCellsGroupViewInfo;
|
|
Separators: TcxTreeListSeparators;
|
|
// position and misc. variables
|
|
Index: Integer;
|
|
Top, Left: Integer;
|
|
UnusedArea: TRect;
|
|
procedure DoCalculate; virtual;
|
|
procedure DoCalculateAutoHeights; virtual;
|
|
procedure DoCalculateCellsViewInfo; virtual;
|
|
procedure DoCalculateImageIndents(var ALeft: Integer); virtual;
|
|
function DoCalculateIndentsLayout: Integer; virtual;
|
|
procedure DoCalculateIndentsViewInfo; virtual;
|
|
procedure DoCalculateLayout; virtual;
|
|
procedure DoHorzOffset(AShift: Integer); virtual;
|
|
procedure DoVertOffset(AShift: Integer); virtual;
|
|
function GetNodeIndicatorKind: TcxIndicatorKind; virtual;
|
|
procedure Update(ARecalculate: Boolean = False); virtual;
|
|
procedure UpdateClipping; virtual;
|
|
procedure UpdateImageIndexes; virtual;
|
|
procedure UpdatePostCalculate(ATop, AIndex: Integer); virtual;
|
|
// node view info routines
|
|
procedure ReallocateData; overload;
|
|
property ControlViewInfo: TcxTreeListViewInfo read GetControlViewInfo;
|
|
property IndentWidth: Integer read GetIndentWidth;
|
|
property Owner: TcxTreeListNodesViewInfo read FOwner;
|
|
property OptionsView: TcxTreeListOptionsView read GetOptionsView;
|
|
property RealHeight: Integer read GetRealHeight;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListNodesViewInfo); virtual;
|
|
destructor Destroy; override;
|
|
procedure AssignLayoutTo(ADest: TcxTreeListNodeViewInfo); virtual;
|
|
procedure Clear;
|
|
property CellCount: Integer read GetCellCount;
|
|
property Cells[Index: Integer]: TcxTreeListEditCellViewInfo read GetCell;
|
|
property ClipRect: TRect read NodeClipRect;
|
|
property ContentRect: TRect read NodeContentRect;
|
|
property Focused: Boolean read NodeFocused;
|
|
property FocusRect: TRect read GetFocusRect;
|
|
property GroupCount: Integer read GetGroupCount;
|
|
property Groups[Index: Integer]: TcxTreeListCellsGroupViewInfo read GetGroup;
|
|
property HasButton: Boolean read NodeHasButton;
|
|
property HasPreview: Boolean read NodeHasPreview;
|
|
property HotTrack: Boolean read GetHotTrack;
|
|
property IndentCount: Integer read GetIndentCount;
|
|
property Indents[Index: Integer]: TcxTreeListIndentViewInfo read GetIndent;
|
|
property Indicator: TcxTreeListIndicatorViewInfo read FIndicator;
|
|
property IsGroupNode: Boolean read NodeIsGroup;
|
|
property IsExpanded: Boolean read NodeIsExpanded;
|
|
property Level: Integer read NodeLevel;
|
|
property NextVisible: TcxTreeListNodeViewInfo read NodeNextVisible;
|
|
property Node: TcxTreeListNode read ViewInfoNode;
|
|
property Preview: TcxTreeListNodePreviewViewInfo read FPreview;
|
|
property PreviewOffset: Integer read NodePreviewOffset;
|
|
property PrevVisible: TcxTreeListNodeViewInfo read NodePrevVisible;
|
|
property Selected: Boolean read NodeSelected;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property Visible: Boolean read NodeVisible;
|
|
property VisibleIndex: Integer read GetVisibleIndex;
|
|
end;
|
|
|
|
{ TcxTreeListNodesViewInfo }
|
|
|
|
TcxTreeListNodesViewInfo = class
|
|
private
|
|
FCapacity: Integer;
|
|
FNeedSynchronize: Boolean;
|
|
FNeedUpdatePos: Boolean;
|
|
FNodesCount: Integer;
|
|
FNodes: PPointerList;
|
|
FOwner: TcxTreeListViewInfo;
|
|
FUpdatePost: Boolean;
|
|
function GetMaxVisibleIndex: Integer;
|
|
function GetNextNodeForProcess: TcxTreeListNode;
|
|
function GetNextNodeFromViewInfo(Index: Integer): TcxTreeListNode;
|
|
function GetNodeViewInfo(Index: Integer): TcxTreeListNodeViewInfo;
|
|
function GetOptionsView: TcxTreeListOptionsView;
|
|
function GetScrollWindow: Boolean;
|
|
function GetTopVisibleIndex: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function ProcessAddNode(var ANode: TcxTreeListNode; var IsBreak: Boolean): Integer;
|
|
protected
|
|
CheckSelectionMode: Boolean;
|
|
ClipRect: TRect;
|
|
Count: Integer;
|
|
IndentWidth: Integer;
|
|
IsAddFirst: Boolean;
|
|
IsRowAutoHeight: Boolean;
|
|
NodesBottom: Integer;
|
|
ScrollRect: TRect;
|
|
SpaceArea: TRect;
|
|
Template: TcxTreeListNodeViewInfo;
|
|
TopNode: TcxTreeListNode;
|
|
VisibleCount: Integer;
|
|
procedure Add(ANode: TcxTreeListNode; var AHeight: Integer); virtual;
|
|
function AddNode(ANode: TcxTreeListNode): TcxTreeListNodeViewInfo;
|
|
procedure BeforeShowEdit; virtual;
|
|
procedure CalculatePreviewHeight; virtual;
|
|
procedure CancelUpdatePost;
|
|
procedure ChangeDirection;
|
|
procedure ClearState;
|
|
procedure DoCalculate(AFullRecalculate: Boolean = True); virtual;
|
|
procedure DoCalculateNextPage(AGoForward: Boolean); virtual;
|
|
procedure DoCalculateShiftUp(ALineCount: Integer); virtual;
|
|
procedure DoCalculateShiftDown(ALineCount: Integer); virtual;
|
|
procedure DoHorzOffset(AShift: Integer); virtual;
|
|
procedure DoVertOffset(AShift: Integer); virtual;
|
|
function FindNodeViewInfo(ANode: TcxTreeListNode;
|
|
var AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
procedure FocusedRecordChanged(APrevNode, ANewNode: TcxTreeListNode); virtual;
|
|
procedure MakeNodeVisible(ANode: TcxTreeListNode); virtual;
|
|
function MoveFirstToLatest(ACheckedOne: Boolean = True): Integer;
|
|
procedure NeedUpdatePost;
|
|
procedure NeedViewInfoUpdatePost;
|
|
function PostViewInfoUpdate: Boolean;
|
|
procedure PostUpdate;
|
|
procedure ProcessNodes(ATopNode: TcxTreeListNode; ANeedLastVisible: Boolean); virtual;
|
|
procedure SetLastVisibleNode(ANode: TcxTreeListNode); virtual;
|
|
procedure SynchronizeTopNode; virtual;
|
|
procedure UpdateSelectedNodes; virtual;
|
|
procedure UpdatePostCalculate; virtual;
|
|
procedure UpdateData; virtual;
|
|
function GetGroupViewInfoItemClass: TcxTreeListCellsGroupViewInfoClass; virtual;
|
|
function GetEditCellViewInfoItemClass: TcxTreeListEditCellViewInfoClass; virtual;
|
|
function GetIndentViewInfoItemClass: TcxTreeListIndentViewInfoClass; virtual;
|
|
function GetNodePreviewViewInfoClass: TcxTreeListNodePreviewViewInfoClass; virtual;
|
|
function GetNodeViewInfoClass: TcxTreeListNodeViewInfoClass; virtual;
|
|
property ScrollWindow: Boolean read GetScrollWindow;
|
|
property MaxVisibleIndex: Integer read GetMaxVisibleIndex;
|
|
property Owner: TcxTreeListViewInfo read FOwner;
|
|
property OptionsView: TcxTreeListOptionsView read GetOptionsView;
|
|
property TopVisibleIndex: Integer read GetTopVisibleIndex;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property Nodes[Index: Integer]: TcxTreeListNodeViewInfo read GetNodeViewInfo;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListViewInfo); virtual;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
end;
|
|
|
|
{ TcxTreeListViewInfo }
|
|
|
|
TcxTreeListViewInfo = class(TcxCustomControlViewInfo)
|
|
private
|
|
FBandCapacity: Integer;
|
|
FBandCount: Integer;
|
|
FBands: PPointerList;
|
|
FDefaultRowHeight: Integer;
|
|
FFixedBands: array[0..1] of TcxTreeListBandViewInfo;
|
|
FNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
FScrollingArea: TRect;
|
|
FScrollingAreaVisible: Boolean;
|
|
FSeparators: TcxTreeListSeparators;
|
|
function GetBand(AIndex: Integer): TcxTreeListBandViewInfo;
|
|
function GetBorderSize: Integer;
|
|
function GetBrushManager: TcxBrushCache;
|
|
function GetCellsHeight: Integer;
|
|
function GetCellsOffset: Integer;
|
|
function GetContentOffset: Integer;
|
|
function GetDefaultHeight: Integer;
|
|
function GetFooterOffset: Integer;
|
|
function GetHeaderOffset: Integer;
|
|
function GetLeftFixedBand: TcxTreeListBandViewInfo;
|
|
function GetOptionsView: TcxTreeListOptionsView;
|
|
function GetRightFixedBand: TcxTreeListBandViewInfo;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetVisibleBand(Index: Integer): TcxTreeListBandViewInfo;
|
|
function GetVisibleBandCount: Integer;
|
|
procedure SetBandCount(ACount: Integer);
|
|
procedure SetBandViewParams(ABand: TcxTreeListBand; Index: Integer);
|
|
procedure SetColumnViewParams(AColumn: TcxTreeListColumn);
|
|
// helpers function
|
|
function CalcBandRect(var ARect: TRect;
|
|
AWidth, AOfs: Integer; Fixed: TcxTreeListBandFixedKind): Integer;
|
|
procedure CalculateCellRects;
|
|
function SetHeaderSizeValue(const ViewParams: TcxViewParams;
|
|
var ASize: Integer; CheckSize: Boolean; Delta: Integer = 0): TcxViewParams;
|
|
protected
|
|
BackgroundBitmap: TBitmap;
|
|
BandLineHeight: Integer;
|
|
CellsRect: TRect;
|
|
ContentRect: TRect;
|
|
ExpandButtonSize: Integer;
|
|
FooterBitmap: TBitmap;
|
|
FooterBrush: TBrush;
|
|
FooterColor: TColor;
|
|
FooterIndicator: TcxTreeListIndicatorViewInfo;
|
|
FooterLineHeight: Integer;
|
|
FooterRect : TRect;
|
|
FooterSeparators: TcxTreeListSeparators;
|
|
GridLinesBrush: TBrush;
|
|
HeaderRect: TRect;
|
|
HeaderIndicator: TcxTreeListIndicatorViewInfo;
|
|
HeaderLineHeight: Integer;
|
|
HeaderSeparators: TcxTreeListSeparators;
|
|
IndicatorViewParams: TcxViewParams;
|
|
PreviewHeight: Integer;
|
|
PrevClientRect: TRect;
|
|
SeparatorBrush: TBrush;
|
|
TreeLineColor: TColor;
|
|
// scrolling variables
|
|
PrevHorzScrollSize: Integer;
|
|
HorzScrollInc: Integer;
|
|
HorzScrollPage: Integer;
|
|
HorzScrollPos: Integer;
|
|
HorzScrollSize: Integer;
|
|
SizingViewInfo: TcxTreeListEditCellViewInfo;
|
|
procedure CalculateDefaultHeights; override;
|
|
function CalculateDefaultEditHeight: Integer; override;
|
|
procedure CalculateDefaultViewParams; virtual;
|
|
procedure CalculateHeaderFooterViewInfo; virtual;
|
|
procedure CheckScrolling; virtual;
|
|
procedure DoCalculate; override;
|
|
procedure DoScrollHorizontal(APos: Integer); virtual;
|
|
procedure DoScrollVertical(APos: Integer); virtual;
|
|
function GetIndicatorViewInfoClass: TcxTreeListIndicatorViewInfoClass; virtual;
|
|
function GetNodesViewInfoClass: TcxTreeListNodesViewInfoClass; virtual;
|
|
procedure InvalidateRect(const ARect: TRect);
|
|
procedure UpdateSelection; override;
|
|
procedure UpdateFootersViewInfo; virtual;
|
|
property BorderSize: Integer read GetBorderSize;
|
|
property BrushManager: TcxBrushCache read GetBrushManager;
|
|
property CellsHeight: Integer read GetCellsHeight;
|
|
property CellsOffset: Integer read GetCellsOffset;
|
|
property ContentOffset: Integer read GetContentOffset;
|
|
property FooterOffset: Integer read GetFooterOffset;
|
|
property HeaderOffset: Integer read GetHeaderOffset;
|
|
property OptionsView: TcxTreeListOptionsView read GetOptionsView;
|
|
property VisibleBandCount: Integer read GetVisibleBandCount;
|
|
property VisibleBands[Index: Integer]: TcxTreeListBandViewInfo read GetVisibleBand;
|
|
public
|
|
constructor Create(AOwner: TcxEditingControl); override;
|
|
destructor Destroy; override;
|
|
procedure InvalidateScrollRect(ADirection: TcxDragSizingDirection); virtual;
|
|
property BandCount: Integer read FBandCount;
|
|
property Bands[Index: Integer]: TcxTreeListBandViewInfo read GetBand;
|
|
property DefaultHeight: Integer read GetDefaultHeight;
|
|
property DefaultRowHeight: Integer read FDefaultRowHeight;
|
|
property LeftFixedBand: TcxTreeListBandViewInfo read GetLeftFixedBand;
|
|
property NodesViewInfo: TcxTreeListNodesViewInfo read FNodesViewInfo;
|
|
property RightFixedBand: TcxTreeListBandViewInfo read GetRightFixedBand;
|
|
property ScrollingArea: TRect read FScrollingArea;
|
|
property ScrollingAreaVisible: Boolean read FScrollingAreaVisible;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
end;
|
|
|
|
{ TcxTreeListControlPainter }
|
|
|
|
TcxTreeListControlPainter = class(TcxCustomControlPainter)
|
|
private
|
|
function GetBackgroundBrush: TBrush;
|
|
function GetGridLinesBrush: TBrush;
|
|
function GetIsFooterVisible: Boolean;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetTreeLineColor: TColor;
|
|
function GetViewInfo: TcxTreeListViewInfo;
|
|
protected
|
|
ContentClipRegion: TcxRegion;
|
|
CurrentBitmap: TBitmap;
|
|
procedure AfterCustomDraw(AViewInfo: TcxCustomViewInfoItem); override;
|
|
procedure AfterCustomDraw(AViewInfo: TcxTreeListEditCellViewInfo); overload;
|
|
procedure BeforeCustomDraw(AViewInfo: TcxCustomViewInfoItem); override;
|
|
procedure BeforeCustomDraw(AViewInfo: TcxTreeListEditCellViewInfo); overload;
|
|
function DoCustomDrawEx(AViewInfoItem: TcxCustomViewInfoItem;
|
|
AEvent: TcxCustomDrawViewInfoItemEvent; AExclude: Boolean): Boolean;
|
|
procedure DoPaint; override;
|
|
function DoPaintBackground(ACanvas: TcxCanvas; const ABounds: TRect): Boolean;
|
|
procedure DrawBackgroundRect(const R: TRect); virtual;
|
|
procedure DrawBandItem(AViewInfo: TcxTreeListBandViewInfo); virtual;
|
|
procedure DrawBandFooter(AViewInfo: TcxTreeListBandViewInfo); virtual;
|
|
procedure DrawCellsGroup(AViewInfo: TcxTreeListCellsGroupViewInfo); virtual;
|
|
procedure DrawEditCell(AViewInfo: TcxTreeListEditCellViewInfo; IsOpaque: Boolean); virtual;
|
|
procedure DrawExpandButton(const ARect: TRect; AExpanded: Boolean; ABitmap: TBitmap); virtual;
|
|
procedure DrawFocusRect(AViewInfo: TcxTreeListNodeViewInfo); virtual;
|
|
procedure DrawFooter; virtual;
|
|
procedure DrawFooterItem(AViewInfo: TcxTreeListFooterItemViewInfo);
|
|
procedure DrawFooterRect(const R: TRect; AViewInfo: TcxTreeListBandViewInfo); virtual;
|
|
procedure DrawHeader; virtual;
|
|
procedure DrawHeaderItem(AViewInfo: TcxTreeListHeaderViewInfo; IsOpaque: Boolean); virtual;
|
|
procedure DrawHeaderRect(const R: TRect; AViewInfo: TcxTreeListBandViewInfo); virtual;
|
|
procedure DrawImage(AViewInfo: TcxTreeListIndentViewInfo); virtual;
|
|
procedure DrawIndicator(AViewInfo: TcxTreeListIndicatorViewInfo); virtual;
|
|
procedure DrawNode(AViewInfo: TcxTreeListNodeViewInfo); virtual;
|
|
procedure DrawNodeCells(AViewInfo: TcxTreeListNodeViewInfo;
|
|
AFromIndex, AToIndex: Integer); virtual;
|
|
procedure DrawNodeIndent(AViewInfo: TcxTreeListIndentViewInfo); virtual;
|
|
procedure DrawNodePreview(AViewInfo: TcxTreeListNodePreviewViewInfo); virtual;
|
|
procedure DrawNodes; virtual;
|
|
procedure DrawRect(AViewInfo: TcxTreeListViewInfoItem); overload;
|
|
procedure DrawRect(const ARect: TRect; ABrush: TBrush; ABitmap: TBitmap = nil); overload; virtual;
|
|
procedure DrawRectWithBorders(const ARect: TRect; ABrush: TBrush;
|
|
IsOpaque: Boolean; ABorders: TcxBorders = []; ABitmap: TBitmap = nil); overload;
|
|
procedure DrawRectWithBorders(AViewInfo: TcxTreeListViewInfoItem;
|
|
IsOpaque: Boolean; ABorders: TcxBorders = []); overload;
|
|
procedure DrawSeparators(const ASeparators: TcxTreeListSeparators); virtual;
|
|
procedure DrawTreeLines(AViewInfo: TcxTreeListIndentViewInfo); virtual;
|
|
procedure ExtDrawHeader(ACanvas: TcxCanvas;
|
|
const ABounds, ATextAreaBounds: TRect; ANeighbors: TcxNeighbors; ABorders: TcxBorders;
|
|
AState: TcxButtonState; AAlignmentHorz: TAlignment; AAlignmentVert: TcxAlignmentVert;
|
|
AMultiLine, AShowEndEllipsis: Boolean; const AText: string; AFont: TFont;
|
|
ATextColor, ABkColor: TColor; AOnDrawBackground: TcxDrawBackgroundEvent = nil);
|
|
function GetViewState(AIndex: Integer): Boolean;
|
|
procedure RestoreClipping;
|
|
property NodesClipping: TcxRegion read ContentClipRegion;
|
|
property Bands: Boolean index 0 read GetViewState;
|
|
property BackgroundBrush: TBrush read GetBackgroundBrush;
|
|
property Footer: Boolean index 2 read GetViewState;
|
|
property Headers: Boolean index 3 read GetViewState;
|
|
property Indicator: Boolean index 4 read GetViewState;
|
|
property IsFooterVisible: Boolean read GetIsFooterVisible;
|
|
property ShowRoot: Boolean index 5 read GetViewState;
|
|
property GridLinesBrush: TBrush read GetGridLinesBrush;
|
|
property TreeLineColor: TColor read GetTreeLineColor;
|
|
public
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property ViewInfo: TcxTreeListViewInfo read GetViewInfo;
|
|
end;
|
|
|
|
{ TcxTreeListBandOptions }
|
|
|
|
TcxTreeListBandOptions = class(TcxOwnedPersistent)
|
|
private
|
|
FState: Integer;
|
|
FHidden: Boolean;
|
|
function GetState(AIndex: Integer): Boolean;
|
|
procedure SetState(AIndex: Integer; Value: Boolean);
|
|
protected
|
|
procedure Changed; virtual;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure RestoreDefaults; virtual;
|
|
published
|
|
property Customizing: Boolean index 0 read GetState write SetState default True;
|
|
property Hidden: Boolean read FHidden write FHidden default False;
|
|
property Moving: Boolean index 1 read GetState write SetState default True;
|
|
property OnlyOwnColumns: Boolean index 2 read GetState write SetState default False;
|
|
property Sizing: Boolean index 3 read GetState write SetState default True;
|
|
end;
|
|
|
|
TcxTreeListBandOptionsClass = class of TcxTreeListBandOptions;
|
|
|
|
{ TcxTreeListBandStyles }
|
|
|
|
TcxTreeListBandStyles = class(TcxStyles)
|
|
private
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
ContentParams: TcxCachedContentParams;
|
|
procedure CachedContentStyleChanged;
|
|
procedure Changed(AIndex: Integer); override;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property Content: TcxStyle index tlbs_Content read GetValue write SetValue;
|
|
property Footer: TcxStyle index tlbs_Footer read GetValue write SetValue;
|
|
property Header: TcxStyle index tlbs_Header read GetValue write SetValue;
|
|
property HeaderBackground: TcxStyle index tlbs_HeaderBackground read GetValue write SetValue;
|
|
end;
|
|
|
|
{ TcxTreeListBand }
|
|
|
|
TcxTreeListBand = class(TcxInterfacedCollectionItem, IUnknown, IcxTreeListIndexedItem, IcxDragSizing, IcxStoredObject)
|
|
private
|
|
FBandRows: TcxTreeListBandRows;
|
|
FBandViewInfo: TcxTreeListBandViewInfo;
|
|
FCaption: TcxTreeListCaption;
|
|
FCalculatedWidth: Integer;
|
|
FColumns: TList;
|
|
FMinWidth: Integer;
|
|
FOptions: TcxTreeListBandOptions;
|
|
FState: Integer;
|
|
FStyles: TcxTreeListBandStyles;
|
|
FVisibleColumns: TList;
|
|
FWidth: Integer;
|
|
function GetBands: TcxTreeListBands;
|
|
function GetColumn(Index: Integer): TcxTreeListColumn;
|
|
function GetColumnCount: Integer;
|
|
function GetDisplayWidth: Integer;
|
|
function GetFixedKind: TcxTreeListBandFixedKind;
|
|
function GetIndentWidth: Integer;
|
|
function GetIsLeftMost: Boolean;
|
|
function GetIsRightMost: Boolean;
|
|
function GetItemIndex: Integer;
|
|
function GetRealWidth: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetVisible: Boolean;
|
|
function GetVisibleIndex: Integer;
|
|
function GetVisibleColumn(Index: Integer): TcxTreeListColumn;
|
|
function GetVisibleColumnCount: Integer;
|
|
procedure SetBandVisiblePos(APos: Integer);
|
|
procedure SetCaption(Value: TcxTreeListCaption);
|
|
procedure SetColumn(Index: Integer; Value: TcxTreeListColumn);
|
|
procedure SetFixedKind(Value: TcxTreeListBandFixedKind);
|
|
procedure SetItemIndex(Value: Integer);
|
|
procedure SetMinWidth(Value: Integer);
|
|
procedure SetOptions(Value: TcxTreeListBandOptions);
|
|
procedure SetStyles(Value: TcxTreeListBandStyles);
|
|
procedure SetVisible(Value: Boolean);
|
|
procedure SetVisibleColumn(Index: Integer; Value: TcxTreeListColumn);
|
|
procedure SetVisibleIndex(Value: Integer);
|
|
procedure SetWidth(Value: Integer);
|
|
protected
|
|
procedure AssignColumnWidths;
|
|
procedure InitAutoWidthItem(AItem: TcxAutoWidthItem);
|
|
function IsFixed: Boolean;
|
|
function IsOnlyOwnColumns: Boolean;
|
|
function CanDropColumnAt(const APoint: TPoint; out ARowIndex, AColIndex: Integer): Boolean; virtual;
|
|
function GetMaxDeltaWidth: Integer;
|
|
function CanMoving: Boolean; virtual;
|
|
function GetState(Index: Integer): Boolean;
|
|
function GetOptionsClass: TcxTreeListBandOptionsClass; virtual;
|
|
procedure AddColumn(AColumn: TcxTreeListColumn);
|
|
procedure RealignColumns;
|
|
procedure RemoveColumn(AColumn: TcxTreeListColumn);
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
procedure VisibleChanged; virtual;
|
|
// IcxTreeListDragSizing implementation
|
|
function CanSizing(ADirection: TcxDragSizingDirection): Boolean;
|
|
function GetSizingBoundsRect(ADirection: TcxDragSizingDirection): TRect; virtual;
|
|
function GetSizingIncrement(ADirection: TcxDragSizingDirection): Integer; virtual;
|
|
function IsDynamicUpdate: Boolean; virtual;
|
|
procedure SetSizeDelta(ADirection: TcxDragSizingDirection; ADelta: Integer); virtual;
|
|
// IcxStoredObject
|
|
function GetObjectName: string;
|
|
function GetProperties(AProperties: TStrings): Boolean; virtual;
|
|
function GetPropertyIndex(const AName: string): Integer;
|
|
procedure GetPropertyValue(const AName: string; var AValue: Variant); virtual;
|
|
procedure SetPropertyValue(const AName: string; const AValue: Variant); virtual;
|
|
property Bands: TcxTreeListBands read GetBands;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
property ViewInfo: TcxTreeListBandViewInfo read FBandViewInfo;
|
|
property IndentWidth: Integer read GetIndentWidth;
|
|
public
|
|
constructor Create(Collection: TCollection); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure ApplyBestFit;
|
|
procedure RestoreDefaults; virtual;
|
|
procedure RestoreWidths;
|
|
property BandRows: TcxTreeListBandRows read FBandRows;
|
|
property ColumnCount: Integer read GetColumnCount;
|
|
property Columns[Index: Integer]: TcxTreeListColumn read GetColumn write SetColumn;
|
|
property DisplayWidth: Integer read GetDisplayWidth;
|
|
property IsLeftMost: Boolean read GetIsLeftMost;
|
|
property IsRightMost: Boolean read GetIsRightMost;
|
|
property RealWidth: Integer read GetRealWidth;
|
|
property VisibleColumnCount: Integer read GetVisibleColumnCount;
|
|
property VisibleColumns[Index: Integer]: TcxTreeListColumn read GetVisibleColumn write SetVisibleColumn;
|
|
property Index;
|
|
published
|
|
property Caption: TcxTreeListCaption read FCaption write SetCaption;
|
|
property FixedKind: TcxTreeListBandFixedKind read GetFixedKind write SetFixedKind default tlbfNone;
|
|
property MinWidth: Integer read FMinWidth write SetMinWidth default cxTreeListDefMinWidth;
|
|
property Options: TcxTreeListBandOptions read FOptions write SetOptions;
|
|
property Styles: TcxTreeListBandStyles read FStyles write SetStyles;
|
|
property Visible: Boolean read GetVisible write SetVisible default True;
|
|
property Width: Integer read FWidth write SetWidth default 0;
|
|
property VisibleIndex: Integer read GetVisibleIndex write SetVisibleIndex stored False;
|
|
end;
|
|
|
|
TcxTreeListBandClass = class of TcxTreeListBand;
|
|
|
|
{ TcxTreeListBands }
|
|
|
|
TcxTreeListBands = class(TCollection, {$IFNDEF DELPHI6} IUnknown, {$ENDIF} IcxStoredObject, IcxStoredParent)
|
|
private
|
|
FTreeList: TcxCustomTreeListControl;
|
|
function GetItem(AIndex: Integer): TcxTreeListBand;
|
|
function GetVisibleItemEx(AIndex: Integer): TcxTreeListBand;
|
|
procedure SetItem(AIndex: Integer; Value: TcxTreeListBand);
|
|
protected
|
|
function GetOwner: TPersistent; override;
|
|
procedure RealignColumns;
|
|
procedure RefreshBandStates; virtual;
|
|
procedure Update(Item: TCollectionItem); override;
|
|
//
|
|
{$IFDEF DELPHI6}
|
|
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override;
|
|
{$ENDIF}
|
|
|
|
// IInterface
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
// IcxStoredObject }
|
|
function GetObjectName: string;
|
|
function GetProperties(AProperties: TStrings): Boolean; virtual;
|
|
procedure GetPropertyValue(const AName: string; var AValue: Variant); virtual;
|
|
procedure SetPropertyValue(const AName: string; const AValue: Variant); virtual;
|
|
// IcxStoredParent
|
|
function CreateChild(const AObjectName, AClassName: string): TObject; virtual;
|
|
procedure DeleteChild(const AObjectName: string; AObject: TObject); virtual;
|
|
procedure GetChildren(AChildren: TStringList); virtual;
|
|
public
|
|
constructor Create(AOwner: TcxCustomTreeListControl); virtual;
|
|
function Add: TcxTreeListBand;
|
|
function GetAbsoluteIndex(VisibleIndex: Integer): Integer;
|
|
function GetVisibleIndex(AbsoluteIndex: Integer): Integer;
|
|
procedure RestoreDefaults; virtual;
|
|
procedure RestoreWidths; virtual;
|
|
property FirstVisible: TcxTreeListBand index 0 read GetVisibleItemEx;
|
|
property Items[AIndex: Integer]: TcxTreeListBand read GetItem write SetItem; default;
|
|
property LastVisible: TcxTreeListBand index 1 read GetVisibleItemEx;
|
|
property TreeList: TcxCustomTreeListControl read FTreeList;
|
|
end;
|
|
|
|
{ TcxTreeListBandRow }
|
|
|
|
TcxTreeListBandRow = class
|
|
private
|
|
FBandRows: TcxTreeListBandRows;
|
|
FItems: TList;
|
|
FLineCount: Integer;
|
|
FLineOffset: Integer;
|
|
function GetBand: TcxTreeListBand;
|
|
function GetCount: Integer;
|
|
function GetFirst: TcxTreeListColumn;
|
|
function GetIndex: Integer;
|
|
function GetIsFirst: Boolean;
|
|
function GetIsLast: Boolean;
|
|
function GetItem(Index: Integer): TcxTreeListColumn;
|
|
function GetItemEx(Index: Integer): TcxTreeListColumn;
|
|
function GetLast: TcxTreeListColumn;
|
|
function GetLineCount: Integer;
|
|
function GetMinWidth: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
function GetWidth: Integer;
|
|
protected
|
|
procedure AddColumn(AColumn: TcxTreeListColumn);
|
|
procedure DoCalculateColumnsAutoWidth;
|
|
function GetRowMinWidth: Integer;
|
|
function GetMaxColumnWidth(AColumn: TcxTreeListColumn): Integer;
|
|
procedure UpdateInformation;
|
|
property Band: TcxTreeListBand read GetBand;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListBandRows); virtual;
|
|
destructor Destroy; override;
|
|
function IndexOf(AColumn: TcxTreeListColumn): Integer;
|
|
property BandRows: TcxTreeListBandRows read FBandRows;
|
|
property Count: Integer read GetCount;
|
|
property First: TcxTreeListColumn read GetFirst;
|
|
property Index: Integer read GetIndex;
|
|
property IsFirst: Boolean read GetIsLast;
|
|
property IsLast: Boolean read GetIsFirst;
|
|
property Items[Index: Integer]: TcxTreeListColumn read GetItem; default;
|
|
property Last: TcxTreeListColumn read GetLast;
|
|
property LineCount: Integer read GetLineCount;
|
|
property LineOffset: Integer read FLineOffset;
|
|
property MinWidth: Integer read GetMinWidth;
|
|
property Width: Integer read GetWidth;
|
|
end;
|
|
|
|
{ TcxTreeListBandRows }
|
|
|
|
TcxTreeListBandRows = class
|
|
private
|
|
FBand: TcxTreeListBand;
|
|
FColumnsMaxWidth: Integer;
|
|
FColumnsMinWidth: Integer;
|
|
FItems: TList;
|
|
FLineCount: Integer;
|
|
function GetCount: Integer;
|
|
function GetFirst: TcxTreeListBandRow;
|
|
function GetItem(Index: Integer): TcxTreeListBandRow;
|
|
function GetItemEx(Index: Integer): TcxTreeListBandRow;
|
|
function GetLast: TcxTreeListBandRow;
|
|
function GetLeftMostMinWidth: Integer;
|
|
function GetLeftMostWidth: Integer;
|
|
function GetMinWidth: Integer;
|
|
protected
|
|
function Add: TcxTreeListBandRow;
|
|
function CalculateAvaliableMinWidth: Integer;
|
|
procedure Clear;
|
|
procedure Refresh;
|
|
procedure UpdateInformation;
|
|
public
|
|
constructor Create(AOwner: TcxTreeListBand); virtual;
|
|
destructor Destroy; override;
|
|
property Band: TcxTreeListBand read FBand;
|
|
property Count: Integer read GetCount;
|
|
property ColumnsMaxWidth: Integer read FColumnsMaxWidth;
|
|
property ColumnsMinWidth: Integer read FColumnsMinWidth;
|
|
property First: TcxTreeListBandRow read GetFirst;
|
|
property Items[Index: Integer]: TcxTreeListBandRow read GetItem; default;
|
|
property Last: TcxTreeListBandRow read GetLast;
|
|
property LeftMostMinWidth: Integer read GetLeftMostMinWidth;
|
|
property LeftMostWidth: Integer read GetLeftMostWidth;
|
|
property LineCount: Integer read FLineCount;
|
|
property MinWidth: Integer read GetMinWidth;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsView }
|
|
|
|
TcxTreeListTreeLineStyle = (tllsNone, tllsDot, tllsSolid);
|
|
TcxTreeListPaintStyle = (tlpsStandard, tlpsCategorized);
|
|
|
|
TcxTreeListOptionsView = class(TcxControlOptionsView, IUnknown, IcxTreeListSubClass)
|
|
private
|
|
FBandLineCount: Integer;
|
|
FCategorizedColumn: TcxTreeListColumn;
|
|
FDropArrowColor: TColor;
|
|
FFixedSeparatorColor: TColor;
|
|
FFixedSeparatorWidth: Integer;
|
|
FGridLineColor: TColor;
|
|
FGridLines: TcxTreeListGridLines;
|
|
FIndicatorWidth: Integer;
|
|
FPaintStyle: TcxTreeListPaintStyle;
|
|
FState: Integer;
|
|
FTreeLineColor: TColor;
|
|
FTreeLineStyle: TcxTreeListTreeLineStyle;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
procedure SetCategorizedColumn(Value: TcxTreeListColumn);
|
|
procedure SetColumnAutoWidth(Index: Integer; Value: Boolean);
|
|
procedure SetBandLineCount(Value: Integer);
|
|
procedure SetIndicatorWidth(Value: Integer);
|
|
procedure SetFixedSeparatorColor(Value: TColor);
|
|
procedure SetFixedSeparatorWidth(Value: Integer);
|
|
procedure SetGridLineColor(Value: TColor);
|
|
procedure SetGridLines(Value: TcxTreeListGridLines);
|
|
procedure SetHeaderSingleLine(Index: Integer; Value: Boolean);
|
|
procedure SetPaintStyle(Value: TcxTreeListPaintStyle);
|
|
procedure SetTreeLineColor(Value: TColor);
|
|
procedure SetTreeLineStyle(Value: TcxTreeListTreeLineStyle);
|
|
protected
|
|
procedure Changed; override;
|
|
function GetControl: TObject;
|
|
function GetState(AIndex: Integer): Boolean;
|
|
procedure SetState(AIndex: Integer; Value: Boolean);
|
|
// helper functions
|
|
function HasImages(ANode: TcxTreeListNode): Boolean;
|
|
function HasStateImages(ANode: TcxTreeListNode): Boolean;
|
|
function HorzIncrement: Integer;
|
|
function IsCategorizedPaint: Boolean;
|
|
function IsExtPaintStyle: Boolean;
|
|
function IsRowAutoHeight: Boolean;
|
|
function VertIncrement: Integer;
|
|
// IUnknown
|
|
function _AddRef: Integer; stdcall;
|
|
function _Release: Integer; stdcall;
|
|
function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
function GetCategorizedColumn: TcxTreeListColumn;
|
|
procedure RestoreDefaults; virtual;
|
|
published
|
|
property BandLineCount: Integer read FBandLineCount write SetBandLineCount default cxTreeListDefBandHeaderLineCount;
|
|
property Bands: Boolean index 0 read GetState write SetState default cxTreeListDefBands;
|
|
property Buttons: Boolean index 7 read GetState write SetState default True;
|
|
property CategorizedColumn: TcxTreeListColumn read FCategorizedColumn write SetCategorizedColumn;
|
|
property ColumnAutoWidth: Boolean index 1 read GetState write SetColumnAutoWidth default cxTreeListDefColumnAutoWidth;
|
|
property DropArrowColor: TColor read FDropArrowColor write FDropArrowColor default cxTreeListDefDropArrowColor;
|
|
property ExtPaintStyle: Boolean index 12 read GetState write SetState default False;
|
|
property FixedSeparatorColor: TColor read FFixedSeparatorColor write SetFixedSeparatorColor default clDefault;
|
|
property FixedSeparatorWidth: Integer read FFixedSeparatorWidth write SetFixedSeparatorWidth default cxTreeListDefSeparatorWidth;
|
|
property Footer: Boolean index 2 read GetState write SetState default False;
|
|
property GridLineColor: TColor read FGridLineColor write SetGridLineColor default clDefault;
|
|
property GridLines: TcxTreeListGridLines read FGridLines write SetGridLines default tlglNone;
|
|
property Headers: Boolean index 3 read GetState write SetState default cxTreeListDefColumnHeaders;
|
|
property HeaderSingleLine: Boolean index 10 read GetState write SetHeaderSingleLine default False;
|
|
property Indicator: Boolean index 4 read GetState write SetState default False;
|
|
property IndicatorWidth: Integer read FIndicatorWidth write SetIndicatorWidth default cxTreeListDefIndicatorWidth;
|
|
property PaintStyle: TcxTreeListPaintStyle read FPaintStyle write SetPaintStyle default tlpsStandard;
|
|
property ShowRoot: Boolean index 5 read GetState write SetState default True;
|
|
property SimpleCustomizeBox: Boolean index 8 read GetState write SetState default False;
|
|
property TreeLineColor: TColor read FTreeLineColor write SetTreeLineColor default clDefault;
|
|
property TreeLineStyle: TcxTreeListTreeLineStyle read FTreeLineStyle write SetTreeLineStyle default tllsDot;
|
|
property UseImageIndexForSelected: Boolean index 13 read GetState write SetState default True;
|
|
property UseNodeColorForIndent: Boolean index 9 read GetState write SetState default True;
|
|
property CellAutoHeight;
|
|
property CellEndEllipsis;
|
|
property CellTextMaxLineCount;
|
|
property ScrollBars;
|
|
property ShowEditButtons;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsCustomizing }
|
|
|
|
TcxTreeListOptionsCustomizing = class(TcxOwnedPersistent)
|
|
private
|
|
FState: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
function GetState(Index: Integer): Boolean;
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property BandCustomizing: Boolean index 7 read GetState write SetState default True;
|
|
property BandHorzSizing: Boolean index 1 read GetState write SetState default True;
|
|
property BandMoving: Boolean index 2 read GetState write SetState default True;
|
|
property BandVertSizing: Boolean index 3 read GetState write SetState default True;
|
|
property ColumnCustomizing: Boolean index 4 read GetState write SetState default True;
|
|
property ColumnHorzSizing: Boolean index 5 read GetState write SetState default True;
|
|
property ColumnMoving: Boolean index 6 read GetState write SetState default True;
|
|
property ColumnVertSizing: Boolean index 8 read GetState write SetState default True;
|
|
property DynamicSizing: Boolean index 9 read GetState write SetState default False;
|
|
property RowSizing: Boolean index 10 read GetState write SetState default False;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsSelection }
|
|
|
|
TcxTreeListOptionsSelection = class(TcxOwnedPersistent)
|
|
private
|
|
FState: Integer;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
procedure Changed; virtual;
|
|
function GetSelectionState(Index: Integer): Boolean;
|
|
procedure SetSelectionState(Index: Integer; Value: Boolean);
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property CellSelect: Boolean index 0 read GetSelectionState write SetSelectionState default True;
|
|
property HideFocusRect: Boolean index 1 read GetSelectionState write SetSelectionState default True;
|
|
property HideSelection: Boolean index 2 read GetSelectionState write SetSelectionState default False;
|
|
property InvertSelect: Boolean index 3 read GetSelectionState write SetSelectionState default True;
|
|
property MultiSelect: Boolean index 4 read GetSelectionState write SetSelectionState default False;
|
|
end;
|
|
|
|
TcxTreeListOptionsSelectionClass = class of TcxTreeListOptionsSelection;
|
|
|
|
{ TcxTreeListOptionsBehavior }
|
|
|
|
TcxTreeListOptionsBehavior = class(TcxControlOptionsBehavior)
|
|
private
|
|
FState: Integer;
|
|
FWaitExpandingTime: Integer;
|
|
function GetChangeDelay: Integer;
|
|
function GetIncSearchItem: TcxTreeListColumn;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
procedure SetChangeDelay(Value: Integer);
|
|
procedure SetAutomateLeftMostIndent(Index: Integer; Value: Boolean);
|
|
procedure SetIncSearchItem(Value: TcxTreeListColumn);
|
|
protected
|
|
function GetState(Index: Integer): Boolean;
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property AutoDragCopy: Boolean index 4 read GetState write SetState default False;
|
|
property AutomateLeftMostIndent: Boolean index 9 read GetState write SetAutomateLeftMostIndent default True;
|
|
property ChangeDelay: Integer read GetChangeDelay write SetChangeDelay default 0;
|
|
property ConfirmDelete: Boolean index 6 read GetState write SetState default True;
|
|
property DragCollapse: Boolean index 0 read GetState write SetState default True;
|
|
property DragExpand: Boolean index 1 read GetState write SetState default True;
|
|
property DragFocusing: Boolean index 15 read GetState write SetState default False;
|
|
property ExpandOnDblClick: Boolean index 16 read GetState write SetState default True;
|
|
property ExpandOnIncSearch: Boolean index 2 read GetState write SetState default False;
|
|
property HotTrack: Boolean index 10 read GetState write SetState default False;
|
|
property IncSearchItem: TcxTreeListColumn read GetIncSearchItem write SetIncSearchItem default nil;
|
|
property Sorting: Boolean index 8 read GetState write SetState default True;
|
|
property MultiSort: Boolean index 7 read GetState write SetState default True;
|
|
property ShowHourGlass: Boolean index 3 read GetState write SetState default True;
|
|
property WaitForExpandNodeTime: Integer read FWaitExpandingTime write FWaitExpandingTime default cxTreeListDefWaitExpandTime;
|
|
property DragDropText;
|
|
property FocusCellOnCycle;
|
|
property IncSearch;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsData }
|
|
|
|
TcxTreeListOptionsData = class(TcxControlOptionsData)
|
|
private
|
|
FState: Integer;
|
|
function GetAnsiSort: Boolean;
|
|
function GetCaseInsensitive: Boolean;
|
|
function GetSummaryNullIgnore: Boolean;
|
|
procedure SetAnsiSort(Value: Boolean);
|
|
procedure SetCaseInsensitive(Value: Boolean);
|
|
procedure SetSummaryNullIgnore(Value: Boolean);
|
|
protected
|
|
procedure Changed; override;
|
|
function GetState(Index: Integer): Boolean;
|
|
procedure SetState(Index: Integer; Value: Boolean);
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property AnsiSort: Boolean read GetAnsiSort write SetAnsiSort default False;
|
|
property CaseInsensitive: Boolean read GetCaseInsensitive write SetCaseInsensitive default False;
|
|
property Deleting: Boolean index 0 read GetState write SetState default True;
|
|
property Inserting: Boolean index 1 read GetState write SetState default False;
|
|
property SummaryNullIgnore: Boolean read GetSummaryNullIgnore write SetSummaryNullIgnore default False;
|
|
end;
|
|
|
|
{ TcxTreeListPreview }
|
|
|
|
TcxTreeListPreviewPlace = (tlppBottom, tlppTop);
|
|
|
|
TcxTreeListPreview = class(TcxOwnedInterfacedPersistent, IcxTreeListSubClass)
|
|
private
|
|
FAutoHeight: Boolean;
|
|
FColumn: TcxTreeListColumn;
|
|
FLeftIndent: Integer;
|
|
FMaxLineCount: Integer;
|
|
FPlace: TcxTreeListPreviewPlace;
|
|
FRightIndent: Integer;
|
|
FVisible: Boolean;
|
|
function GetActive: Boolean;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
procedure SetAutoHeight(Value: Boolean);
|
|
procedure SetColumn(Value: TcxTreeListColumn);
|
|
procedure SetLeftIndent(Value: Integer);
|
|
procedure SetMaxLineCount(Value: Integer);
|
|
procedure SetPlace(Value: TcxTreeListPreviewPlace);
|
|
procedure SetRightIndent(Value: Integer);
|
|
procedure SetVisible(Value: Boolean);
|
|
protected
|
|
procedure Changed(ACheckActivate: Boolean); virtual;
|
|
function GetControl: TObject;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
property Active: Boolean read GetActive;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
published
|
|
property AutoHeight: Boolean read FAutoHeight write SetAutoHeight default True;
|
|
property Column: TcxTreeListColumn read FColumn write SetColumn;
|
|
property LeftIndent: Integer read FLeftIndent write SetLeftIndent
|
|
default cxTreeListDefPreviewMaxLineCount;
|
|
property MaxLineCount: Integer read FMaxLineCount write SetMaxLineCount
|
|
default cxTreeListDefPreviewMaxLineCount;
|
|
property Place: TcxTreeListPreviewPlace read FPlace write SetPlace default tlppBottom;
|
|
property RightIndent: Integer read FRightIndent write SetRightIndent
|
|
default cxTreeListDefPreviewIndent;
|
|
property Visible: Boolean read FVisible write SetVisible default False;
|
|
end;
|
|
|
|
{ TcxTreeListStyleSheet }
|
|
|
|
TcxTreeListStyleSheet = class(TcxCustomStyleSheet)
|
|
private
|
|
function GetStylesValue: TcxTreeListStyles;
|
|
procedure SetStylesValue(Value: TcxTreeListStyles);
|
|
public
|
|
class function GetStylesClass: TcxCustomStylesClass; override;
|
|
published
|
|
property Styles: TcxTreeListStyles read GetStylesValue write SetStylesValue;
|
|
end;
|
|
|
|
{ TcxTreeListStyles }
|
|
|
|
TcxtlOnGetItemStyleEvent = procedure(Sender: TObject; AItem: TObject; var AStyle: TcxStyle) of object;
|
|
|
|
TcxtlOnGetContentStyleEvent = procedure(Sender: TObject; AItem: TObject;
|
|
ANode: TcxTreeListNode; var AStyle: TcxStyle) of object;
|
|
|
|
TcxtlOnGetNodeIndentStyleEvent = procedure(Sender: TObject;
|
|
ANode: TcxTreeListNode; ALevel: Integer; var AStyle: TcxStyle) of object;
|
|
|
|
TcxTreeListStyles = class(TcxCustomControlStyles)
|
|
private
|
|
FOnGetBandBackgroundStyle: TcxtlOnGetItemStyleEvent;
|
|
FOnGetBandContentStyle: TcxtlOnGetContentStyleEvent;
|
|
FOnGetBandHeaderStyle: TcxtlOnGetItemStyleEvent;
|
|
FOnGetBandFooterStyle: TcxtlOnGetItemStyleEvent;
|
|
FOnGetColumnFooterStyle: TcxtlOnGetItemStyleEvent;
|
|
FOnGetColumnHeaderStyle: TcxtlOnGetItemStyleEvent;
|
|
FOnGetContentStyle: TcxtlOnGetContentStyleEvent;
|
|
FOnGetHotTrackStyle: TcxtlOnGetContentStyleEvent;
|
|
FOnGetNodeIndentStyle: TcxtlOnGetNodeIndentStyleEvent;
|
|
FOnGetPreviewStyle: TcxtlOnGetItemStyleEvent;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
ContentParams: TcxCachedContentParams;
|
|
CachedPreviewStyle: TcxViewParams;
|
|
procedure ContentStyleChanged; virtual;
|
|
procedure DoGetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AParams: TcxViewParams); virtual;
|
|
procedure DoGetBandContentParams(ANode: TcxTreeListNode; ABand: TcxTreeListBand; var AParams: TcxViewParams); virtual;
|
|
function DoGetBandContentStyle(ANode: TcxTreeListNode; ABand: TcxTreeListBand; out AStyle: TcxStyle): Boolean;
|
|
procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override;
|
|
function GetStyleFromEvent(const AEvent: TcxtlOnGetItemStyleEvent; AItem: TObject): TcxStyle;
|
|
function SelectionFontAssigned: Boolean;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
procedure Assign(Source: TPersistent); override;
|
|
function GetBandBackgroundParams(ABand: TcxTreeListBand): TcxViewParams;
|
|
function GetBandContentParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode): TcxViewParams;
|
|
function GetBandFooterParams(ABand: TcxTreeListBand): TcxViewParams;
|
|
function GetBandHeaderParams(ABand: TcxTreeListBand): TcxViewParams;
|
|
function GetColumnContentParams(AColumn: TcxTreeListColumn; IsOdd: Boolean): TcxViewParams;
|
|
function GetColumnHeaderParams(AColumn: TcxTreeListColumn): TcxViewParams;
|
|
function GetColumnFooterParams(AColumn: TcxTreeListColumn): TcxViewParams;
|
|
function GetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxViewParams;
|
|
function GetIncSearchParams: TcxViewParams;
|
|
function GetIndentParams(ANode: TcxTreeListNode; AIndent: Integer): TcxViewParams;
|
|
function GetIndicatorParams: TcxViewParams;
|
|
function GetFooterParams: TcxViewParams;
|
|
function GetPreviewParams(ANode: TcxTreeListNode): TcxViewParams;
|
|
published
|
|
property BandBackground: TcxStyle index tlsv_BandBackground read GetValue write SetValue;
|
|
property BandContent: TcxStyle index tlsv_BandContent read GetValue write SetValue;
|
|
property BandHeader: TcxStyle index tlsv_BandHeader read GetValue write SetValue;
|
|
property ColumnFooter: TcxStyle index tlsv_ColumnFooter read GetValue write SetValue;
|
|
property ColumnHeader: TcxStyle index tlsv_ColumnHeader read GetValue write SetValue;
|
|
property ContentEven: TcxStyle index tlsv_ContentEven read GetValue write SetValue;
|
|
property ContentOdd: TcxStyle index tlsv_ContentOdd read GetValue write SetValue;
|
|
property Footer: TcxStyle index tlsv_Footer read GetValue write SetValue;
|
|
property HotTrack: TcxStyle index tlsv_HotTrack read GetValue write SetValue;
|
|
property IncSearch: TcxStyle index tlsv_IncSearch read GetValue write SetValue;
|
|
property Indicator: TcxStyle index tlsv_Indicator read GetValue write SetValue;
|
|
property Preview: TcxStyle index tlsv_Preview read GetValue write SetValue;
|
|
property OnGetBandBackgroundStyle: TcxtlOnGetItemStyleEvent read FOnGetBandBackgroundStyle write FOnGetBandBackgroundStyle;
|
|
property OnGetBandContentStyle: TcxtlOnGetContentStyleEvent read FOnGetBandContentStyle write FOnGetBandContentStyle;
|
|
property OnGetBandHeaderStyle: TcxtlOnGetItemStyleEvent read FOnGetBandHeaderStyle write FOnGetBandHeaderStyle;
|
|
property OnGetBandFooterStyle: TcxtlOnGetItemStyleEvent read FOnGetBandFooterStyle write FOnGetBandFooterStyle;
|
|
property OnGetColumnFooterStyle: TcxtlOnGetItemStyleEvent read FOnGetColumnFooterStyle write FOnGetColumnFooterStyle;
|
|
property OnGetColumnHeaderStyle: TcxtlOnGetItemStyleEvent read FOnGetColumnHeaderStyle write FOnGetColumnHeaderStyle;
|
|
property OnGetContentStyle: TcxtlOnGetContentStyleEvent read FOnGetContentStyle write FOnGetContentStyle;
|
|
property OnGetNodeIndentStyle: TcxtlOnGetNodeIndentStyleEvent read FOnGetNodeIndentStyle write FOnGetNodeIndentStyle;
|
|
property OnGetHotTrackStyle: TcxtlOnGetContentStyleEvent read FOnGetHotTrackStyle write FOnGetHotTrackStyle;
|
|
property OnGetPreviewStyle: TcxtlOnGetItemStyleEvent read FOnGetPreviewStyle write FOnGetPreviewStyle;
|
|
property Background;
|
|
property Content;
|
|
property Inactive;
|
|
property Selection;
|
|
property StyleSheet;
|
|
end;
|
|
|
|
{ TcxTreeListItemsCustomizeListBox }
|
|
|
|
TcxTreeListItemsCustomizeListBox = class(TcxListBox)
|
|
private
|
|
FAccepted: Boolean;
|
|
FDragAndDropItemIndex: Integer;
|
|
FDragAndDropObject: TcxTreeListDragAndDropObject;
|
|
FIsBandListBox: Boolean;
|
|
FMouseDownPos: TPoint;
|
|
FOrgPoint: TPoint;
|
|
FPrevCursor: TCursor;
|
|
FTreeList: TcxCustomTreeListControl;
|
|
function GetPainter: TcxCustomLookAndFeelPainterClass;
|
|
procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE;
|
|
protected
|
|
procedure BeginDrag; virtual;
|
|
procedure FocusChanged; override;
|
|
procedure DoDrawItem(AControl: TcxListBox; ACanvas: TcxCanvas;
|
|
AIndex: Integer; ARect: TRect; AState: TOwnerDrawState); virtual;
|
|
procedure DoDrawItemEx(Control: TWinControl; Index: Integer;
|
|
Rect: TRect; State: TOwnerDrawState);
|
|
procedure EndDrag(Accepted: Boolean); virtual;
|
|
procedure FinishDrag(Accepted: Boolean); virtual;
|
|
procedure InitDragAndDropObject; virtual;
|
|
function GetItemHeight(AItem: Integer): Integer; virtual;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure MeasureItem(AControl: TcxListBox; Index: Integer; var Height: Integer); virtual;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure RefreshList;
|
|
procedure Resize; override;
|
|
property DragAndDropObject: TcxTreeListDragAndDropObject read FDragAndDropObject;
|
|
property TreeList: TcxCustomTreeListControl read FTreeList;
|
|
property Painter: TcxCustomLookAndFeelPainterClass read GetPainter;
|
|
public
|
|
constructor CreateEx(AOwner: TComponent;
|
|
ATreeList: TcxCustomTreeListControl; IsBandListBox: Boolean);
|
|
end;
|
|
|
|
{ TcxTreeListCustomizationForm }
|
|
|
|
TcxTreeListCustomizationForm = class(TForm)
|
|
private
|
|
FCustomizingListBox: TcxTreeListItemsCustomizeListBox;
|
|
FDeactivationTimer: TTimer;
|
|
FHookTimer: TcxTimer;
|
|
FOwner: TcxTreeListCustomizing;
|
|
function GetTreeList: TcxCustomTreeListControl;
|
|
protected
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure DeactivationTimeHandler(Sender: TObject);
|
|
procedure StartDeactivationTimer(Sender: TcxTreeListItemsCustomizeListBox);
|
|
procedure StopDeactivationTimer;
|
|
procedure HookTimerHandler(Sender: TObject);
|
|
|
|
property HookTimer: TcxTimer read FHookTimer;
|
|
property Customizing: TcxTreeListCustomizing read FOwner;
|
|
property CustomizingListBox: TcxTreeListItemsCustomizeListBox read FCustomizingListBox;
|
|
property TreeList: TcxCustomTreeListControl read GetTreeList;
|
|
public
|
|
constructor CreateEx(AOwner: TcxTreeListCustomizing);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
{ TcxTreeListCustomizing }
|
|
|
|
TcxTreeListCustomizing = class(TcxOwnedInterfacedPersistent, IcxTreeListDesigner)
|
|
private
|
|
FBandListBox: TcxTreeListItemsCustomizeListBox;
|
|
FDragAndDropObject: TcxTreeListDragAndDropObject;
|
|
FForm: TcxTreeListCustomizationForm;
|
|
FHeaderListBox: TcxTreeListItemsCustomizeListBox;
|
|
FLastBandIndex: Integer;
|
|
FLastHeaderIndex: Integer;
|
|
FLastPosition: TPoint;
|
|
FLineHeight: Integer;
|
|
FPageControl: TPageControl;
|
|
FRowCount: Integer;
|
|
FTabSheetBands: TTabSheet;
|
|
FTabSheetHeaders: TTabSheet;
|
|
FTreeList: TcxCustomTreeListControl;
|
|
FVisible: Boolean;
|
|
function GetForm: TForm;
|
|
function GetVisible: Boolean;
|
|
procedure SetRowCount(Value: Integer);
|
|
procedure SetVisible(Value: Boolean);
|
|
protected
|
|
procedure AdjustControls; virtual;
|
|
procedure Activate(Sender: TObject); virtual;
|
|
procedure Close(Sender: TObject; var Action: TCloseAction); virtual;
|
|
procedure CreateControls; virtual;
|
|
procedure CreateCustomizingForm;
|
|
function IsSimpleMode: Boolean;
|
|
procedure LookAndFeelChanged; virtual;
|
|
procedure ReleaseControls;
|
|
procedure SetControlParent(AControl, AParent: TWinControl);
|
|
procedure ShowCustomizingForm;
|
|
function SizeDelta: TSize; virtual;
|
|
procedure ValidateListBox(AListBox: TcxTreeListItemsCustomizeListBox; AIndex: Integer);
|
|
procedure VisibleChanged(Sender: TObject);
|
|
procedure Update; virtual;
|
|
// IcxTreeListDesigner
|
|
procedure ComponentRemoved(Sender: TObject); virtual;
|
|
procedure Modified; virtual;
|
|
property DragAndDropObject: TcxTreeListDragAndDropObject read FDragAndDropObject write FDragAndDropObject;
|
|
property BandListBox: TcxTreeListItemsCustomizeListBox read FBandListBox;
|
|
property CustomizingPos: TPoint read FLastPosition write FLastPosition;
|
|
property HeaderListBox: TcxTreeListItemsCustomizeListBox read FHeaderListBox;
|
|
public
|
|
constructor Create(AOwner: TPersistent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure MakeBandSheetVisible;
|
|
procedure MakeColumnSheetVisible;
|
|
property Form: TForm read GetForm;
|
|
function PtInCustomizingBox(const APoint: TPoint): Boolean;
|
|
property RowCount: Integer read FRowCount write SetRowCount default 10;
|
|
property TreeList: TcxCustomTreeListControl read FTreeList;
|
|
property Visible: Boolean read GetVisible write SetVisible;
|
|
end;
|
|
|
|
TcxTreeListCustomizingClass = class of TcxTreeListCustomizing;
|
|
|
|
{ TcxCustomTreeListControl }
|
|
|
|
TcxTreeListNodeChangedEvent = procedure(Sender: TObject; ANode: TcxTreeListNode) of object;
|
|
|
|
TcxTreeListNodeChangingEvent = procedure(Sender: TObject; ANode: TcxTreeListNode;
|
|
var Allow: Boolean) of object;
|
|
|
|
TcxTreeListMoveToEvent = procedure(Sender: TObject; AttachNode: TcxTreeListNode;
|
|
AttachMode: TcxTreeListNodeAttachMode; Nodes: TList; var IsCopy, Done: Boolean) of object;
|
|
|
|
TcxTreeListNodeCompareEvent = procedure(Sender: TObject;
|
|
ANode1, ANode2: TcxTreeListNode; var ACompare: Integer) of object;
|
|
|
|
TcxTreeListFocusedChangedEvent = procedure(Sender: TObject;
|
|
APrevFocusedNode, AFocusedNode: TcxTreeListNode) of object;
|
|
|
|
TcxTreeListGetNodeImageIndexEvent = procedure(Sender: Tobject;
|
|
ANode: TcxTreeListNode; AIndexType: TcxTreeListImageIndexType; var AIndex: TImageIndex) of object;
|
|
|
|
TcxTreeListGetPreviewTextEvent = procedure(Sender: TObject;
|
|
ANode: TcxTreeListNode; var AText: string) of object;
|
|
|
|
TcxTreeListGetNodePreviewHeightEvent = procedure(Sender: TObject;
|
|
ANode: TcxTreeListNode; const ADisplayValue: Variant; var AHeight: Integer) of object;
|
|
|
|
TcxTreeListIsGroupNodeEvent = procedure(Sender: TObject;
|
|
ANode: TcxTreeListNode; var IsGroup: Boolean) of object;
|
|
|
|
TcxTreeListEditingEvent = procedure(Sender: TObject;
|
|
AColumn: TcxTreeListColumn; var Allow: Boolean) of object;
|
|
|
|
TcxTreeListColumnChangedEvent = procedure(Sender: TObject;
|
|
AColumn: TcxTreeListColumn) of object;
|
|
|
|
TcxTreeListBandChangedEvent = procedure(Sender: TObject;
|
|
ABand: TcxTreeListBand) of object;
|
|
|
|
TcxTreeListFocusedColumnChanged = procedure(Sender: TObject;
|
|
APrevFocusedColumn, AFocusedColumn: TcxTreeListColumn) of object;
|
|
|
|
TcxTreeListOnHotTrackNodeEvent = procedure(Sender: TObject; ANode: TcxTreeListNode;
|
|
AShift: TShiftState; var ACursor: TCursor) of object;
|
|
|
|
TcxTreeListItemChangedEvent = procedure(Sender: TObject; AItem: TObject) of object;
|
|
|
|
TcxTreeListNodeDataChangedEvent = procedure(Sender: TObject;
|
|
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn) of object;
|
|
|
|
TcxCustomDrawBackgroundEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
const R: TRect; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawEditCellViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListEditCellViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawCellsGroupViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListCellsGroupViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawHeaderViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListHeaderViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawIndentViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListIndentViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawIndicatorViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListIndicatorViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawFooterItemViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListFooterItemViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxCustomDrawBandViewInfoEvent = procedure(Sender: TObject; ACanvas: TcxCanvas;
|
|
AViewInfo: TcxTreeListBandViewInfo; var ADone: Boolean) of object;
|
|
|
|
TcxTreeListGetNodeHeight = procedure(Sender: TcxCustomTreeListControl;
|
|
ANode: TcxTreeListNode; var AHeight: Integer) of object;
|
|
|
|
TcxCustomTreeListControl = class(TcxExtEditingControl, IcxNavigator, IcxStoredParent,
|
|
IcxStoredObject, IcxTreeListDesignTimeOperations, IdxSkinSupport)
|
|
private
|
|
FAutoWidthController: TcxAutoWidthObject;
|
|
FBands: TcxTreeListBands;
|
|
FBandsVisibleList: TList;
|
|
FChangeImagesLink: TChangeLink;
|
|
FChangeStateImagesLink: TChangeLink;
|
|
FCheckedList: TList;
|
|
FColumnsVisibleList: TList;
|
|
FContentIndentWidth: Integer;
|
|
FCustomizing: TcxTreeListCustomizing;
|
|
FDelayTimer: TTimer;
|
|
FDefaultLayout: Boolean;
|
|
FDefaultRowHeight: Integer;
|
|
FDeletedNodes: TList;
|
|
FDesigners: TList;
|
|
FDragNode: TcxTreeListNode;
|
|
FFreezeCount: Integer;
|
|
FHeaderLineCount: Integer;
|
|
FImages: TCustomImageList;
|
|
FIsRestore: Boolean;
|
|
FLevelIndentWidth: Integer;
|
|
FLockChanges: Boolean;
|
|
FNavigatorNotifier: TcxNavigatorControlNotifier;
|
|
FNodes: TcxTreeListNodes;
|
|
FNodesList: TList;
|
|
FNeedMakeVisible: Boolean;
|
|
FNeedSortPost: Boolean;
|
|
FNeedUpdateDesigners: Boolean;
|
|
FNeedRestoreSorting: Boolean;
|
|
FNeedFocusedRecordUpdatePost: Boolean;
|
|
FOptionsCustomizing: TcxTreeListOptionsCustomizing;
|
|
FOptionsSelection: TcxTreeListOptionsSelection;
|
|
FPostChanged: Boolean;
|
|
FPreview: TcxTreeListPreview;
|
|
FRealBandLineHeight: Integer;
|
|
FSafeDelete: Boolean;
|
|
FSortedColumns: TList;
|
|
FSortLocking: Integer;
|
|
FSortOrderList: TList;
|
|
FSelection: TList;
|
|
FSelectionUpdateLocked: Integer;
|
|
FStateImages: TCustomImageList;
|
|
FStoredCursor: TCursor;
|
|
FStylesEvents: TNotifyEvent;
|
|
FTopPos: Integer;
|
|
FUseGlassCursor: Integer;
|
|
FOnAfterSorting: TNotifyEvent;
|
|
FOnBandHeaderClick: TcxTreeListBandChangedEvent;
|
|
FOnBandSizeChanged: TcxTreeListItemChangedEvent;
|
|
FOnCanSelectNode: TcxTreeListNodeChangingEvent;
|
|
FOnChange: TNotifyEvent;
|
|
FOnCollapsed: TcxTreeListNodeChangedEvent;
|
|
FOnCollapsing: TcxTreeListNodeChangingEvent;
|
|
FOnColumnHeaderClick: TcxTreeListColumnChangedEvent;
|
|
FOnColumnSizeChanged: TcxTreeListItemChangedEvent;
|
|
FOnCompare: TcxTreeListNodeCompareEvent;
|
|
FOnCustomDrawBackground: TcxCustomDrawBackgroundEvent;
|
|
FOnCustomDrawBandHeader: TcxCustomDrawHeaderViewInfoEvent;
|
|
FOnCustomDrawCell: TcxCustomDrawEditCellViewInfoEvent;
|
|
FOnCustomDrawCellsGroup: TcxCustomDrawCellsGroupViewInfoEvent;
|
|
FOnCustomDrawIndicatorCell: TcxCustomDrawIndicatorViewInfoEvent;
|
|
FOnCustomDrawIndentCell: TcxCustomDrawIndentViewInfoEvent;
|
|
FOnCustomDrawFooter: TcxCustomDrawBandViewInfoEvent;
|
|
FOnCustomDrawFooterCell: TcxCustomDrawFooterItemViewInfoEvent;
|
|
FOnCustomDrawHeader: TcxCustomDrawBandViewInfoEvent;
|
|
FOnCustomDrawHeaderCell: TcxCustomDrawHeaderViewInfoEvent;
|
|
FOnCustomDrawPreview: TcxCustomDrawEditCellViewInfoEvent;
|
|
FOnCustomizationVisibleChanged: TNotifyEvent;
|
|
FOnDataChanged: TNotifyEvent;
|
|
FOnDeletion: TcxTreeListNodeChangedEvent;
|
|
FOnExpanded: TcxTreeListNodeChangedEvent;
|
|
FOnExpanding: TcxTreeListNodeChangingEvent;
|
|
FOnFocusedColumnChanged: TcxTreeListFocusedColumnChanged;
|
|
FOnFocusedNodeChanged: TcxTreeListFocusedChangedEvent;
|
|
FOnGetNodeImageIndex: TcxTreeListGetNodeImageIndexEvent;
|
|
FOnGetNodePreviewHeight: TcxTreeListGetNodePreviewHeightEvent;
|
|
FOnGetNodeHeight: TcxTreeListGetNodeHeight;
|
|
FOnHotTrackNode: TcxTreeListOnHotTrackNodeEvent;
|
|
FOnIsGroupNode: TcxTreeListIsGroupNodeEvent;
|
|
FOnLayoutChanged: TNotifyEvent;
|
|
FOnMoveTo: TcxTreeListMoveToEvent;
|
|
FOnNodeChanged: TcxTreeListNodeDataChangedEvent;
|
|
FOnSelectionChanged: TNotifyEvent;
|
|
FOnSorting: TNotifyEvent;
|
|
FOnTopRecordIndexChanged: TNotifyEvent;
|
|
function GetBands: TcxTreeListBands;
|
|
function GetBandPanelHeight: Integer;
|
|
function GetColumn(AIndex: Integer): TcxTreeListColumn;
|
|
function GetColumnCount: Integer;
|
|
function GetColumnsList: TList;
|
|
function GetController: TcxTreeListController;
|
|
function GetCount: Integer;
|
|
function GetDefaultRowHeight: Integer;
|
|
function GetFixedBandCount: Integer;
|
|
function GetFooterHeight: Integer;
|
|
function GetFocusedColumn: TcxTreeListColumn;
|
|
function GetFocusedNode: TcxTreeListNode;
|
|
function GetHeaderHeight: Integer;
|
|
function GetHeaderPanelHeight: Integer;
|
|
function GetHitTest: TcxTreeListHitTest;
|
|
function GetInplaceEditor: TcxCustomEdit;
|
|
function GetInplaceColumnIndex: Integer;
|
|
function GetIsEditing: Boolean;
|
|
function GetItem(Index: Integer): TcxTreeListNode;
|
|
function GetLastNode: TcxTreeListNode;
|
|
function GetLastVisibleNode: TcxTreeListNode;
|
|
function GetNavigatorIsActive: Boolean;
|
|
function GetOnAfterSummary: TcxAfterSummaryEvent;
|
|
function GetOnEdited: TcxTreeListColumnChangedEvent;
|
|
function GetOnEditing: TcxTreeListEditingEvent;
|
|
function GetOnEditValueChanged: TcxTreeListColumnChangedEvent;
|
|
function GetOnSummary: TcxSummaryEvent;
|
|
function GetOptionsBehavior: TcxTreeListOptionsBehavior;
|
|
function GetOptionsData: TcxTreeListOptionsData;
|
|
function GetOptionsView: TcxTreeListOptionsView;
|
|
function GetSearching: Boolean;
|
|
function GetSearchingText: string;
|
|
function GetSelection(Index: Integer): TcxtreeListNode;
|
|
function GetSelectionCount: Integer;
|
|
function GetSorted: Boolean;
|
|
function GetSortedColumnCount: Integer;
|
|
function GetSortedColumn(Index: Integer): TcxTreeListColumn;
|
|
function GetStyles: TcxTreeListStyles;
|
|
function GetSummary: TcxDataSummary;
|
|
function GetTopNode: TcxTreeListNode;
|
|
function GetTopVisibleIndex: Integer;
|
|
function GetTopVisibleNode: TcxTreeListNode;
|
|
function GetVisibleCount: Integer;
|
|
function GetViewInfo: TcxTreeListViewInfo;
|
|
function GetVisibleBand(AIndex: Integer): TcxTreeListBand;
|
|
function GetVisibleBandCount: Integer;
|
|
function GetVisibleColumn(AIndex: Integer): TcxTreeListColumn;
|
|
function GetVisibleColumnCount: Integer;
|
|
function IsDefaultRowHeightAssigned: Boolean;
|
|
procedure SetBands(Value: TcxTreeListBands);
|
|
procedure SetColumn(AIndex: Integer; Value: TcxTreeListColumn);
|
|
procedure SetDefaultRowHeight(Value: Integer);
|
|
procedure SetDefaultLayout(Value: Boolean);
|
|
procedure SetFocusedColumn(Value: TcxTreeListColumn);
|
|
procedure SetFocusedNodeProp(Value: TcxTreeListNode);
|
|
procedure SetImages(Value: TCustomImageList);
|
|
procedure SetInternalImageList(AList: TCustomImageList; var Value: TCustomImageList; ALink: TChangeLink);
|
|
procedure SetLastVisibleNode(Value: TcxTreeListNode);
|
|
procedure SetNodes(Value: TcxTreeListNodes);
|
|
procedure SetOnAfterSummary(Value: TcxAfterSummaryEvent);
|
|
procedure SetOnEdited(Value: TcxTreeListColumnChangedEvent);
|
|
procedure SetOnEditing(Value: TcxTreeListEditingEvent);
|
|
procedure SetOnEditValueChanged(Value: TcxTreeListColumnChangedEvent);
|
|
procedure SetOnSummary(Value: TcxSummaryEvent);
|
|
procedure SetOptionsBehavior(Value: TcxTreeListOptionsBehavior);
|
|
procedure SetOptionsCustomizing(Value: TcxTreeListOptionsCustomizing);
|
|
procedure SetOptionsData(Value: TcxTreeListOptionsData);
|
|
procedure SetOptionsSelection(Value: TcxTreeListOptionsSelection);
|
|
procedure SetOptionsView(Value: TcxTreeListOptionsView);
|
|
procedure SetPreview(Value: TcxTreeListPreview);
|
|
procedure SetSearchingText(const Value: string);
|
|
procedure SetSorted(Value: Boolean);
|
|
procedure SetStateImages(Value: TCustomImageList);
|
|
procedure SetStyles(Value: TcxTreeListStyles);
|
|
procedure SetTopVisibleIndex(AValue: Integer);
|
|
procedure SetTopVisibleNode(ANode: TcxTreeListNode);
|
|
procedure SetVisibleBand(Index: Integer; AValue: TcxTreeListBand);
|
|
procedure SetVisibleColumn(Index: Integer; AValue: TcxTreeListColumn);
|
|
procedure DoChangedTimer(Sender: TObject);
|
|
procedure UpdateDesignerForms;
|
|
// IcxStoredObject
|
|
function GetObjectName: string;
|
|
function GetProperties(AProperties: TStrings): Boolean;
|
|
procedure GetPropertyValue(const AName: string; var AValue: Variant);
|
|
procedure SetPropertyValue(const AName: string; const AValue: Variant);
|
|
// IcxStoredParent
|
|
function IcxStoredParent.CreateChild = StoredCreateChild;
|
|
procedure IcxStoredParent.DeleteChild = StoredDeleteChild;
|
|
procedure IcxStoredParent.GetChildren = GetStoredChildren;
|
|
// messages
|
|
procedure CMDrag(var Message: TCMDrag); message CM_DRAG;
|
|
protected
|
|
FMaxIndentWidth: Integer;
|
|
procedure AssignColumnWidths;
|
|
procedure AssignLeftMostWidths;
|
|
procedure BoundsChanged; override;
|
|
// TL procedures
|
|
function AddNode(ANode, ARelative: TcxTreeListNode; AData: Pointer;
|
|
AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode; virtual;
|
|
procedure BeforeAddNode(ANewNode, ANewParent: TcxTreeListNode;
|
|
AMode: TcxTreeListNodeAddMode); virtual;
|
|
procedure BeforeCalculate; virtual;
|
|
procedure BeforeShowingEdit;
|
|
procedure CalculateLeftMostIndentWidth;
|
|
function CanAddIndentWidth(const AIndentWidth: Integer): Boolean; virtual;
|
|
function CanColumnVisible(AColumn: TcxTreeListColumn): Boolean; virtual;
|
|
function CanMultiSelect: Boolean; virtual;
|
|
procedure CheckFocusedItem;
|
|
procedure ColumnSortOrderChanged(AColumn: TcxTreeListColumn);
|
|
procedure DoAssignNodes(Source: TcxTreeListNodes); virtual;
|
|
procedure DoBandSizeChanged(ABand: TcxTreeListBand); virtual;
|
|
procedure DoClear; virtual;
|
|
procedure DoColumnSizeChanged(AColumn: TcxTreeListColumn); virtual;
|
|
function DoCreateColumn: TcxTreeListColumn;
|
|
procedure DoDeleteSelection;
|
|
procedure AddToDelitionList(ANode: TcxTreeListNode); virtual;
|
|
procedure DoRemoveNode(ANode: TcxTreeListNode); virtual;
|
|
procedure DoCheckDeletedNode(ANode: TcxTreeListNode); virtual;
|
|
procedure DoDeleteNode(ANode: TcxTreeListNode); virtual;
|
|
procedure DoInplaceEditContainerItemRemoved(AItem: TcxCustomInplaceEditContainer); override;
|
|
procedure DoInternalMoveTo(AttachNode: TcxTreeListNode;
|
|
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean);
|
|
procedure DoMoveTo(AttachNode: TcxTreeListNode;
|
|
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean); virtual;
|
|
// doXXXX metods fire OnXXXX events
|
|
procedure DoOnAfterSorting; virtual;
|
|
procedure DoOnBandSizeChanged(ABand: TcxTreeListBand); virtual;
|
|
procedure DoOnColumnSizeChanged(AColumn: TcxTreeListColumn); virtual;
|
|
procedure DoOnCollapsed(ANode: TcxTreeListNode); virtual;
|
|
procedure DoOnCollapsing(ANode: TcxTreeListNode; var Allow: Boolean); virtual;
|
|
procedure DoOnCompare(ANode1, ANode2: TcxTreeListNode; var ACompare: Integer); virtual;
|
|
procedure DoOnCustomizationVisibleChanged; virtual;
|
|
procedure DoOnDeletion(ANode: TcxTreeListNode); virtual;
|
|
procedure DoOnExpanded(ANode: TcxTreeListNode); virtual;
|
|
procedure DoOnExpanding(ANode: TcxTreeListNode; var Allow: Boolean); virtual;
|
|
procedure DoOnGetNodeHeight(ANode: TcxTreeListNode; var AHeight: Integer); virtual;
|
|
procedure DoOnHotTrackNode(ANode: TcxTreeListNode; AShift: TShiftState; var ACursor: TCursor); virtual;
|
|
procedure DoOnIsGroupNode(ANode: TcxTreeListNode; var IsGroup: Boolean); virtual;
|
|
procedure DoOnMoveTo(AttachNode: TcxTreeListNode; AttachMode: TcxTreeListNodeAttachMode; Nodes: TList; var IsCopy, Done: Boolean); virtual;
|
|
procedure DoOnTopRecordIndexChanged; virtual;
|
|
procedure DoStartDrag(var DragObject: TDragObject); override;
|
|
//
|
|
function DoWriteHeaderToText: string; virtual;
|
|
function DoWriteNodeToText(ANode: TcxTreeListNode): string; virtual;
|
|
procedure DoWriteToClipboard(AOnlySelected: Boolean); virtual;
|
|
function DoWriteToText(AOnlySelected: Boolean; out AText: string): Boolean;
|
|
procedure DoUpdateDesignerForms; virtual;
|
|
procedure DoDeleteRecords; virtual;
|
|
procedure DoValidateDeletedNodes; virtual;
|
|
procedure DeleteSelectionList(AList: TList); virtual;
|
|
function GetCountNodeForBestFit: Integer; virtual;
|
|
function GetImageIndentWidth(AType: TcxTreeListImageIndexType): Integer; virtual;
|
|
function GetIsActive: Boolean; virtual;
|
|
function GetFixedContentSize: Integer; virtual;
|
|
function GetLevelIndentCount(ALevel: Integer; AWithImages: Boolean; ANode: TcxTreeListNode): Integer;
|
|
function GetLevelIndentsWidth(ALevel: Integer; AWithImages: Boolean; ANode: TcxTreeListNode): Integer; virtual;
|
|
function GetMaxBandWidth(ABand: TcxTreeListBand): Integer;
|
|
function GetMouseWheelScrollingKind: TcxMouseWheelScrollingKind; override;
|
|
function GetStartNodeForBestFit: TcxTreeListNode; virtual;
|
|
function HasImages: Boolean;
|
|
function ImagesIndentWidth: Integer; virtual;
|
|
function InsertNode(IsAppend: Boolean): Boolean; virtual;
|
|
procedure InternalMove(ANode, ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode); virtual;
|
|
procedure InternalCopy(ANode, ADestNode: TcxTreeListNode); virtual;
|
|
function IsMultiSelect: Boolean;
|
|
function IsCancelOperation: Boolean; virtual;
|
|
function IsSmartLoad: Boolean; virtual;
|
|
function IsNodeInserted(ANode: TcxTreeListNode): Boolean;
|
|
function IsNodeEdited(ANode: TcxTreeListNode): Boolean;
|
|
procedure MakeNodeVisible(ANode: TcxTreeListNode); virtual;
|
|
procedure OnChangeImages(Sender: TObject); virtual;
|
|
procedure SaveDragPos; virtual;
|
|
procedure RestoreDragPos; virtual;
|
|
function RealBandLineHeight: Integer;
|
|
procedure ReadData(AStream: TStream); virtual;
|
|
procedure RealignBands; virtual;
|
|
procedure RefreshVisibleIndexes;
|
|
procedure RestoreCursor;
|
|
procedure RestoreSorting; virtual;
|
|
function SkipFocusedRecordChanged: Boolean; virtual;
|
|
function SkipCancelOperation: Boolean; virtual;
|
|
procedure SetGlassCursor;
|
|
procedure SortingStateChanged(AColumn: TcxTreeListColumn; AShift: TShiftState);
|
|
procedure WriteData(AStream: TStream); virtual;
|
|
// IcxTreeListDesignTimeOperations implementation
|
|
function SupportsBandColumnEditor: Boolean; virtual;
|
|
function SupportsItemsEditor: Boolean; virtual;
|
|
function SupportsCreateAllItems: Boolean; virtual;
|
|
function GetVersion: string; virtual;
|
|
procedure CreateAllItems; virtual;
|
|
// IcxNavigator
|
|
function IcxNavigator.IsActive = GetNavigatorIsActive;
|
|
function IcxNavigator.IsEditing = GetIsEditing;
|
|
function IcxNavigator.IsBof = IsBof;
|
|
function IcxNavigator.IsEof = IsEof;
|
|
|
|
procedure RefreshNavigatorButtons;
|
|
procedure DoAction(AButtonIndex: Integer);
|
|
function GetNotifier: TcxNavigatorControlNotifier;
|
|
function IsActionSupported(AButtonIndex: Integer): Boolean;
|
|
|
|
function CanAppend: Boolean;
|
|
function CanEdit: Boolean;
|
|
function CanDelete: Boolean;
|
|
function CanInsert: Boolean;
|
|
|
|
procedure ClearBookmark;
|
|
procedure GotoBookmark;
|
|
function HasData: Boolean;
|
|
function IsBookmarkAvailable: Boolean;
|
|
procedure SaveBookmark;
|
|
function UseRowIndexForNewRecord: Boolean; virtual;
|
|
// updates
|
|
procedure Freeze;
|
|
procedure UnFreeze;
|
|
function IsFreeze: Boolean;
|
|
function IsLocked: Boolean; override;
|
|
// nodes
|
|
function CreateNode: TcxTreeListNode; virtual;
|
|
function DoCanNodeCollapse(ANode: TcxTreeListNode): Boolean; virtual;
|
|
function DoCanNodeExpand(ANode: TcxTreeListNode): Boolean; virtual;
|
|
function DoCreateNode: TcxTreeListNode;
|
|
function DoGetNodeImageIndex(ANode: TcxTreeListNode; AIndex: TcxTreeListImageIndexType): TImageIndex; virtual;
|
|
function DoGetNodeValueCount: Integer; virtual;
|
|
procedure DoNodeChanged(ANode: TcxTreeListNode); virtual;
|
|
function DoIsGroupNode(ANode: TcxTreeListNode): Boolean; virtual;
|
|
procedure DoSelectAll; virtual;
|
|
procedure DoSetNodeExpanded(ANode: TcxTreeListNode; AExpanded: Boolean); virtual;
|
|
procedure DoSetNodeImageIndex(ANode: TcxTreeListNode; AIndex: TcxTreeListImageIndexType; Value: TImageIndex); virtual;
|
|
// procedure DoSetNodeSelected(ANode: TcxTreeListNode; Value: Boolean; Shift: TShiftState = []); virtual;
|
|
procedure DoSetNodeFocused(ANode: TcxTreeListNode; Value: Boolean; Shift: TShiftState = []); virtual;
|
|
procedure DoSorting; virtual;
|
|
function GetColumnById(AItemIndex: Integer): TcxTreeListColumn;
|
|
function GetNodeByID(ARecordIndex: Integer): TcxTreeListNode;
|
|
function GetSelectionsEx: TList;
|
|
// sorting
|
|
procedure CancelSortPost;
|
|
procedure DisableSorting;
|
|
procedure DoSortNodes; virtual;
|
|
procedure EnableSorting;
|
|
procedure NeedSortPost;
|
|
function IsNeedSortPost: Boolean;
|
|
procedure RecreateSortOrdersList; virtual;
|
|
|
|
// events generation
|
|
function CheckEvent(AHasHandler: Boolean): Boolean;
|
|
|
|
procedure DoBandHeaderClick(ABand: TcxTreeListBand); virtual;
|
|
procedure DoColumnHeaderClick(AColumn: TcxTreeListColumn); virtual;
|
|
procedure DoChanged(BlockChangedEvent: Boolean = True); virtual;
|
|
function DoCanSelectNode(ANode: TcxTreeListNode): Boolean; virtual;
|
|
procedure DoDataChangedEvent(Sender: TObject); virtual;
|
|
|
|
procedure DoEditChanged(AItem: TcxCustomInplaceEditContainer); override;
|
|
procedure DoEdited(AItem: TcxCustomInplaceEditContainer); override;
|
|
function DoEditing(AItem: TcxCustomInplaceEditContainer): Boolean; override;
|
|
procedure DoEditValueChanged(AItem: TcxCustomInplaceEditContainer); override;
|
|
procedure DoInitEdit(AItem: TcxCustomInplaceEditContainer; AEdit: TcxCustomEdit); override;
|
|
|
|
procedure DoFocusedItemChanged(APrevFocusedItem,
|
|
AFocusedItem: TcxCustomInplaceEditContainer); virtual;
|
|
procedure DoFocusedRecordChanged(APrevIndex, AFocusedIndex: Integer); virtual;
|
|
procedure DoLayoutChangedEvent; virtual;
|
|
procedure DoRecordChanged(Sender: TcxCustomDataController;
|
|
ARecordIndex, AItemIndex: Integer); virtual;
|
|
procedure DoSelectionChanged; virtual;
|
|
// selection
|
|
procedure BeginUpdateSelection;
|
|
procedure CancelUpdateSelection;
|
|
procedure EndUpdateSelection;
|
|
function IsSelectionLocked: Boolean;
|
|
procedure UpdateSelection; virtual;
|
|
procedure CancelFocusedRecordUpdatePost;
|
|
procedure PostUpdateFocusedRecord;
|
|
procedure UpdateFocusedRecordPost;
|
|
// used classes
|
|
function GetBandItemClass: TcxTreeListBandClass; virtual;
|
|
function GetControllerClass: TcxCustomControlControllerClass; override;
|
|
function GetControlStylesClass: TcxCustomControlStylesClass; override;
|
|
function GetHitTestControllerClass: TcxHitTestControllerClass; override;
|
|
function GetNodesClass: TcxTreeListNodesClass; virtual;
|
|
function GetOptionsCustomizingClass: TcxTreeListOptionsCustomizingClass; virtual;
|
|
function GetOptionsBehaviorClass: TcxControlOptionsBehaviorClass; override;
|
|
function GetOptionsDataClass: TcxControlOptionsDataClass; override;
|
|
function GetOptionsSelectionClass: TcxTreeListOptionsSelectionClass; virtual;
|
|
function GetOptionsViewClass: TcxControlOptionsViewClass; override;
|
|
function GetPainterClass: TcxCustomControlPainterClass; override;
|
|
function GetPreviewClass: TcxTreeListPreviewClass; virtual;
|
|
function GetTreeListColumnClass: TcxTreeListColumnClass; virtual;
|
|
function GetTreeListCustomizingClass: TcxTreeListCustomizingClass; virtual;
|
|
function GetViewInfoClass: TcxCustomControlViewInfoClass; override;
|
|
procedure UpdateColumn(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn); virtual;
|
|
procedure UpdateNode(ANode: TcxTreeListNode); virtual;
|
|
// overrided methods
|
|
procedure AfterLayoutChanged; override;
|
|
procedure BeforeUpdate; override;
|
|
procedure CheckCreateDesignSelectionHelper; override;
|
|
procedure ControlUpdateData(AInfo: TcxUpdateControlInfo); override;
|
|
procedure CreateSubClasses; override;
|
|
procedure DataChanged; override;
|
|
procedure DataLayoutChanged; override;
|
|
procedure DestroySubClasses; override;
|
|
procedure DoLayoutChanged; override;
|
|
function DragDropImageDisplayRect: TRect; override;
|
|
procedure DrawDragDropImage(ADragBitmap: TBitmap; ACanvas: TcxCanvas); override;
|
|
function GetDragDropText: string; virtual;
|
|
function GetDragDropViewParams: TcxViewParams; virtual;
|
|
function GetDragObjectClass: TDragControlObjectClass; override;
|
|
function GetImageListHeight(AImageList: TCustomImageList): Integer; virtual;
|
|
procedure InitScrollBarsParameters; override;
|
|
procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override;
|
|
procedure ReadState(Reader: TReader); override;
|
|
procedure Updated; override;
|
|
procedure Updating; override;
|
|
// inherits for loading bug fixing
|
|
procedure AssignColumnsParams; virtual;
|
|
procedure SaveColumnsParams; virtual;
|
|
|
|
// cxStorage implementation
|
|
procedure GetStoredChildren(AChildren: TStringList); virtual;
|
|
function GetStoredObjectName: string; virtual;
|
|
function GetStoredObjectProperties(AProperties: TStrings): Boolean; virtual;
|
|
procedure GetStoredPropertyValue(const AName: string; var AValue: Variant); virtual;
|
|
procedure RestoreTopPos;
|
|
procedure StoreTopPos;
|
|
procedure SetStoredPropertyValue(const AName: string; const AValue: Variant); virtual;
|
|
function StoredCreateChild(const AObjectName, AClassName: string): TObject; virtual;
|
|
procedure StoredDeleteChild(const AObjectName: string; AObject: TObject); virtual;
|
|
// standart control metods
|
|
{$IFNDEF DELPHI12}
|
|
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
|
|
{$ENDIF}
|
|
function IsUpdating: Boolean;
|
|
procedure Loaded; override;
|
|
procedure Modified; override;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure SetName(const NewName: TComponentName); override;
|
|
|
|
property Bands: TcxTreeListBands read GetBands write SetBands;
|
|
property CheckedList: TList read FCheckedList write FCheckedList;
|
|
property ColumnCount: Integer read GetColumnCount;
|
|
property Columns[Index: Integer]: TcxTreeListColumn read GetColumn write SetColumn;
|
|
property ColumnsList: TList read GetColumnsList;
|
|
property Controller: TcxTreeListController read GetController;
|
|
property Customizing: TcxTreeListCustomizing read FCustomizing write FCustomizing;
|
|
property DefaultLayout: Boolean read FDefaultLayout write SetDefaultLayout default False;
|
|
property DeletedNodes: TList read FDeletedNodes write FDeletedNodes;
|
|
property Designers: TList read FDesigners;
|
|
property FixedBandCount: Integer read GetFixedBandCount;
|
|
property FocusedColumn: TcxTreeListColumn read GetFocusedColumn write SetFocusedColumn;
|
|
property HeaderLineCount: Integer read FHeaderLineCount;
|
|
property HitTest: TcxTreeListHitTest read GetHitTest;
|
|
property IsRestore: Boolean read FIsRestore write FIsRestore;
|
|
property Images: TCustomImageList read FImages write SetImages;
|
|
property LastVisibleNode: TcxTreeListNode read GetLastVisibleNode write SetLastVisibleNode;
|
|
property LockChanges: Boolean read FLockChanges write FLockChanges;
|
|
property Nodes: TcxTreeListNodes read FNodes write SetNodes;
|
|
property NodesList: TList read FNodesList write FNodesList;
|
|
property NeedRestoreSorting: Boolean read FNeedRestoreSorting write FNeedRestoreSorting;
|
|
property OptionsBehavior: TcxTreeListOptionsBehavior read GetOptionsBehavior write SetOptionsBehavior;
|
|
property OptionsCustomizing: TcxTreeListOptionsCustomizing read FOptionsCustomizing write SetOptionsCustomizing;
|
|
property OptionsData: TcxTreeListOptionsData read GetOptionsData write SetOptionsData;
|
|
property OptionsSelection: TcxTreeListOptionsSelection read FOptionsSelection write SetOptionsSelection;
|
|
property OptionsView: TcxTreeListOptionsView read GetOptionsView write SetOptionsView;
|
|
property Preview: TcxTreeListPreview read FPreview write SetPreview;
|
|
property SafeDelete: Boolean read FSafeDelete write FSafeDelete;
|
|
property SelectionCount: Integer read GetSelectionCount;
|
|
property Selections[Index: Integer]: TcxTreeListNode read GetSelection;
|
|
property SortedColumnCount: Integer read GetSortedColumnCount;
|
|
property SortedColumns[Index: Integer]: TcxTreeListColumn read GetSortedColumn;
|
|
property SortOrderList: TList read FSortOrderList;
|
|
property StateImages: TCustomImageList read FStateImages write SetStateImages;
|
|
property StoredCursor: TCursor read FStoredCursor;
|
|
property StylesEvents: TNotifyEvent read FStylesEvents write FStylesEvents;
|
|
property TopVisibleIndex: Integer read GetTopVisibleIndex write SetTopVisibleIndex;
|
|
property TopVisibleNode: TcxTreeListNode read GetTopVisibleNode write SetTopVisibleNode;
|
|
property ViewInfo: TcxTreeListViewInfo read GetViewInfo;
|
|
property VisibleBandCount: Integer read GetVisibleBandCount;
|
|
property VisibleBands[Index: Integer]: TcxTreeListBand read GetVisibleBand write SetVisibleBand;
|
|
property VisibleColumnCount: Integer read GetVisibleColumnCount;
|
|
property VisibleColumns[Index: Integer]: TcxTreeListColumn read GetVisibleColumn write SetVisibleColumn;
|
|
property VisibleCount: Integer read GetVisibleCount;
|
|
property OnAfterSorting: TNotifyEvent read FOnAfterSorting write FOnAfterSorting;
|
|
property OnAfterSummary: TcxAfterSummaryEvent read GetOnAfterSummary write SetOnAfterSummary;
|
|
property OnBandHeaderClick: TcxTreeListBandChangedEvent read FOnBandHeaderClick write FOnBandHeaderClick;
|
|
property OnBandSizeChanged: TcxTreeListItemChangedEvent read FOnBandSizeChanged write FOnBandSizeChanged;
|
|
property OnCanSelectNode: TcxTreeListNodeChangingEvent read FOnCanSelectNode write FOnCanSelectNode;
|
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
|
property OnCollapsed: TcxTreeListNodeChangedEvent read FOnCollapsed write FOnCollapsed;
|
|
property OnCollapsing: TcxTreeListNodeChangingEvent read FOnCollapsing write FOnCollapsing;
|
|
property OnColumnHeaderClick: TcxTreeListColumnChangedEvent read FOnColumnHeaderClick write FOnColumnHeaderClick;
|
|
property OnColumnSizeChanged: TcxTreeListItemChangedEvent read FOnColumnSizeChanged write FOnColumnSizeChanged;
|
|
property OnCompare: TcxTreeListNodeCompareEvent read FOnCompare write FOnCompare;
|
|
property OnCustomDrawBackground: TcxCustomDrawBackgroundEvent read FOnCustomDrawBackground write FOnCustomDrawBackground;
|
|
property OnCustomDrawBandHeader: TcxCustomDrawHeaderViewInfoEvent read FOnCustomDrawBandHeader write FOnCustomDrawBandHeader;
|
|
property OnCustomDrawCell: TcxCustomDrawEditCellViewInfoEvent read FOnCustomDrawCell write FOnCustomDrawCell;
|
|
property OnCustomDrawCellsGroup: TcxCustomDrawCellsGroupViewInfoEvent read FOnCustomDrawCellsGroup write FOnCustomDrawCellsGroup;
|
|
property OnCustomDrawFooter: TcxCustomDrawBandViewInfoEvent read FOnCustomDrawFooter write FOnCustomDrawFooter;
|
|
property OnCustomDrawFooterCell: TcxCustomDrawFooterItemViewInfoEvent read FOnCustomDrawFooterCell write FOnCustomDrawFooterCell;
|
|
property OnCustomDrawHeader: TcxCustomDrawBandViewInfoEvent read FOnCustomDrawHeader write FOnCustomDrawHeader;
|
|
property OnCustomDrawHeaderCell: TcxCustomDrawHeaderViewInfoEvent read FOnCustomDrawHeaderCell write FOnCustomDrawHeaderCell;
|
|
property OnCustomDrawIndentCell: TcxCustomDrawIndentViewInfoEvent read FOnCustomDrawIndentCell write FOnCustomDrawIndentCell;
|
|
property OnCustomDrawIndicatorCell: TcxCustomDrawIndicatorViewInfoEvent read FOnCustomDrawIndicatorCell write FOnCustomDrawIndicatorCell;
|
|
property OnCustomDrawPreview: TcxCustomDrawEditCellViewInfoEvent read FOnCustomDrawPreview write FOnCustomDrawPreview;
|
|
property OnCustomizationFormVisibleChanged: TNotifyEvent read FOnCustomizationVisibleChanged write FOnCustomizationVisibleChanged;
|
|
property OnDataChanged: TNotifyEvent read FOnDataChanged write FOnDataChanged;
|
|
property OnDeletion: TcxTreeListNodeChangedEvent read FOnDeletion write FOnDeletion;
|
|
property OnEdited: TcxTreeListColumnChangedEvent read GetOnEdited write SetOnEdited;
|
|
property OnEditing: TcxTreeListEditingEvent read GetOnEditing write SetOnEditing;
|
|
property OnEditValueChanged: TcxTreeListColumnChangedEvent read GetOnEditValueChanged write SetOnEditValueChanged;
|
|
property OnExpanded: TcxTreeListNodeChangedEvent read FOnExpanded write FOnExpanded;
|
|
property OnExpanding: TcxTreeListNodeChangingEvent read FOnExpanding write FOnExpanding;
|
|
property OnFocusedColumnChanged: TcxTreeListFocusedColumnChanged read FOnFocusedColumnChanged write FOnFocusedColumnChanged;
|
|
property OnFocusedNodeChanged: TcxTreeListFocusedChangedEvent read FOnFocusedNodeChanged write FOnFocusedNodeChanged;
|
|
property OnGetNodeHeight: TcxTreeListGetNodeHeight read FOnGetNodeHeight write FOnGetNodeHeight;
|
|
property OnGetNodeImageIndex: TcxTreeListGetNodeImageIndexEvent read FOnGetNodeImageIndex write FOnGetNodeImageIndex;
|
|
property OnGetNodePreviewHeight: TcxTreeListGetNodePreviewHeightEvent read FOnGetNodePreviewHeight write FOnGetNodePreviewHeight;
|
|
property OnHotTrackNode: TcxTreeListOnHotTrackNodeEvent read FOnHotTrackNode write FOnHotTrackNode;
|
|
property OnIsGroupNode: TcxTreeListIsGroupNodeEvent read FOnIsGroupNode write FOnIsGroupNode;
|
|
property OnLayoutChanged: TNotifyEvent read FOnLayoutChanged write FOnLayoutChanged;
|
|
property OnMoveTo: TcxTreeListMoveToEvent read FOnMoveTo write FOnMoveTo;
|
|
property OnNodeChanged: TcxTreeListNodeDataChangedEvent read FOnNodeChanged write FOnNodeChanged;
|
|
property OnSelectionChanged: TNotifyEvent read FOnSelectionChanged write FOnSelectionChanged;
|
|
property OnSorting: TNotifyEvent read FOnSorting write FOnSorting;
|
|
property OnSummary: TcxSummaryEvent read GetOnSummary write SetOnSummary;
|
|
property OnTopRecordIndexChanged: TNotifyEvent read FOnTopRecordIndexChanged write FOnTopRecordIndexChanged;
|
|
//
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure AdjustColumnsWidth;
|
|
procedure ApplyBestFit;
|
|
procedure Clear;
|
|
function CreateColumn(ABand: TcxTreeListBand = nil): TcxTreeListColumn; virtual;
|
|
procedure DeleteAllColumns; virtual;
|
|
procedure DeleteSelection;
|
|
procedure DragDrop(Source: TObject; X, Y: Integer); override;
|
|
{$IFDEF DELPHI12}
|
|
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
|
|
{$ENDIF}
|
|
function GetIndentWidth(IsLeftMost: Boolean): Integer;
|
|
procedure MakeDefaultLayout; virtual;
|
|
procedure FullCollapse;
|
|
procedure FullExpand;
|
|
procedure FullRefresh; virtual;
|
|
function Find(AData: Pointer; AStart: TcxTreeListNode; AExpandedOnly, AForward: Boolean;
|
|
AFilter: TcxTreeListFindFunc): TcxTreeListNode; virtual;
|
|
function FindNodeByText(const AText: string; AColumn: TcxTreeListColumn;
|
|
AStartNode: TcxTreeListNode = nil; AExpandedOnly: Boolean = False; AForward: Boolean = True): TcxTreeListNode;
|
|
procedure SelectAll;
|
|
procedure Select(Node: TcxTreeListNode; ShiftState: TShiftState = []); overload; virtual;
|
|
procedure Select(const ANodes: array of TcxTreeListNode); overload; virtual;
|
|
procedure Select(ANodes: TList); overload; virtual;
|
|
procedure SetFocusedNode(Value: TcxTreeListNode; AShift: TShiftState);
|
|
procedure SetColumnSortOrder(AColumn: TcxTreeListColumn;
|
|
ASortOrder: TcxDataSortOrder; AShift: TShiftState);
|
|
function StartDrag(DragObject: TDragObject): Boolean; override;
|
|
procedure Subselect(Node: TcxTreeListNode); virtual;
|
|
procedure Deselect(Node: TcxTreeListNode); virtual;
|
|
procedure ClearSelection(KeepPrimary: Boolean = False); virtual;
|
|
procedure ClearSorting;
|
|
function ColumnByName(const AName: string): TcxTreeListColumn;
|
|
function GetSelections(AList: TList): TcxTreeListNode;
|
|
// navigation
|
|
procedure GotoBOF;
|
|
procedure GotoEOF;
|
|
procedure GotoNext;
|
|
procedure GotoNextPage;
|
|
procedure GotoPrev;
|
|
procedure GotoPrevPage;
|
|
function IsBOF: Boolean;
|
|
function IsEOF: Boolean;
|
|
// edit control
|
|
procedure CancelEdit;
|
|
procedure HideEdit;
|
|
procedure ShowEdit;
|
|
procedure ShowEditByKey(AKey: Char);
|
|
procedure ShowEditByMouse(X, Y: Integer; AShift: TShiftState);
|
|
// storing layout
|
|
procedure RestoreFromIniFile(const AStorageName: string; AChildrenCreating: Boolean = False;
|
|
AChildrenDeleting: Boolean = False);
|
|
procedure RestoreFromRegistry(const AStorageName: string; AChildrenCreating: Boolean = False;
|
|
AChildrenDeleting: Boolean = False);
|
|
procedure RestoreFromStream(AStream: TStream; AChildrenCreating: Boolean = False;
|
|
AChildrenDeleting: Boolean = False);
|
|
procedure StoreToIniFile(AStorageName: string; AReCreate: Boolean = True);
|
|
procedure StoreToRegistry(AStorageName: string; AReCreate: Boolean = True);
|
|
procedure StoreToStream(AStream: TStream);
|
|
// searching
|
|
function FindNext(AForward: Boolean): Boolean;
|
|
procedure CancelSearching;
|
|
// positions
|
|
function CellRect(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TRect;
|
|
function GetEditRect(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TRect;
|
|
function GetNodeAt(X, Y: Integer): TcxTreeListNode;
|
|
// misc
|
|
procedure CopyAllToClipboard;
|
|
procedure CopySelectedToClipboard;
|
|
procedure RestoreColumnsDefaults;
|
|
procedure RestoreColumnsWidths;
|
|
property BandPanelHeight: Integer read GetBandPanelHeight;
|
|
property BorderSize;
|
|
property Count: Integer read GetCount;
|
|
property DefaultRowHeight: Integer read GetDefaultRowHeight write SetDefaultRowHeight stored IsDefaultRowHeightAssigned;
|
|
property DragNode: TcxTreeListNode read FDragNode;
|
|
property FocusedNode: TcxTreeListNode read GetFocusedNode write SetFocusedNodeProp;
|
|
property FooterPanelHeight: Integer read GetFooterHeight;
|
|
property HeaderHeight: Integer read GetHeaderHeight;
|
|
property HeaderPanelHeight: Integer read GetHeaderPanelHeight;
|
|
property InplaceColumnIndex: Integer read GetInplaceColumnIndex;
|
|
property InplaceEditor: TcxCustomEdit read GetInplaceEditor;
|
|
property IsActive: Boolean read GetIsActive;
|
|
property IsEditing: Boolean read GetIsEditing;
|
|
property Items[Index: Integer]: TcxTreeListNode read GetItem;
|
|
property LastNode: TcxTreeListNode read GetLastNode;
|
|
property LevelIndentWidth: Integer read FLevelIndentWidth write FLevelIndentWidth;
|
|
property Searching: Boolean read GetSearching;
|
|
property SearchingText: string read GetSearchingText write SetSearchingText;
|
|
property Sorted: Boolean read GetSorted write SetSorted;
|
|
property Styles: TcxTreeListStyles read GetStyles write SetStyles;
|
|
property Summary: TcxDataSummary read GetSummary;
|
|
property TopNode: TcxTreeListNode read GetTopNode;
|
|
property Color;
|
|
end;
|
|
|
|
{ TcxTreeList }
|
|
|
|
TcxTreeList = class(TcxCustomTreeListControl)
|
|
private
|
|
FLoadingTemporaryStream: TMemoryStream;
|
|
function ExCreateNode(AParent, APrev: TcxTreeListNode; var AIndex: Integer): TcxTreeListNode;
|
|
protected
|
|
procedure DoAssignNodes(Source: TcxTreeListNodes); override;
|
|
procedure DoSetNodeImageIndex(ANode: TcxTreeListNode;
|
|
AIndex: TcxTreeListImageIndexType; Value: TImageIndex); override;
|
|
procedure DefineProperties(Filer: TFiler); override;
|
|
procedure Loaded; override;
|
|
function SupportsBandColumnEditor: Boolean; override;
|
|
function SupportsItemsEditor: Boolean; override;
|
|
procedure ReadBinaryData(AStream: TStream);
|
|
procedure ReadData(AStream: TStream); override;
|
|
procedure WriteData(AStream: TStream); override;
|
|
public
|
|
destructor Destroy; override;
|
|
function Add: TcxTreeListNode; overload;
|
|
function Add(ASibling: TcxTreeListNode; AData: Pointer = nil): TcxTreeListNode; overload;
|
|
function AddChild(AParent: TcxTreeListNode; AData: Pointer = nil): TcxTreeListNode;
|
|
function AddChildFirst(AParent: TcxTreeListNode; AData: Pointer = nil): TcxTreeListNode;
|
|
function AddFirst: TcxTreeListNode; overload;
|
|
function AddFirst(ASibling: TcxTreeListNode; AData: Pointer = nil): TcxTreeListNode; overload;
|
|
function AddNode(ANode, ARelative: TcxTreeListNode;
|
|
AData: Pointer; AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode; override;
|
|
function Insert(ASibling: TcxTreeListNode; AData: Pointer = nil): TcxTreeListNode;
|
|
function InsertEx(ANode, ASibling: TcxTreeListNode; AData: Pointer = nil): TcxTreeListNode;
|
|
procedure LoadFromFile(const AFileName: string);
|
|
procedure LoadFromStream(AStream: TStream);
|
|
procedure SaveToFile(const AFileName: string);
|
|
procedure SaveToStream(AStream: TStream);
|
|
property ColumnCount;
|
|
property Columns;
|
|
property Customizing;
|
|
property FocusedColumn;
|
|
property FocusedNode;
|
|
property HitTest;
|
|
property IsEditing;
|
|
property LevelIndentWidth;
|
|
property Nodes;
|
|
property SelectionCount;
|
|
property Selections;
|
|
property Sorted;
|
|
property SortedColumnCount;
|
|
property SortedColumns;
|
|
property TopVisibleIndex;
|
|
property TopVisibleNode;
|
|
property VisibleBandCount;
|
|
property VisibleBands;
|
|
property VisibleColumnCount;
|
|
property VisibleColumns;
|
|
property VisibleCount;
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property Bands;
|
|
property BorderStyle;
|
|
property BufferedPaint;
|
|
property Constraints;
|
|
property Cursor;
|
|
property DefaultLayout;
|
|
property DefaultRowHeight;
|
|
property DragCursor;
|
|
property DragKind;
|
|
property DragMode;
|
|
property Enabled;
|
|
property Font;
|
|
{$IFDEF DELPHI6}
|
|
property HelpContext;
|
|
property HelpKeyword;
|
|
property HelpType;
|
|
{$ENDIF}
|
|
property Hint;
|
|
property Images;
|
|
property LookAndFeel;
|
|
property OptionsBehavior;
|
|
property OptionsCustomizing;
|
|
property OptionsData;
|
|
property OptionsSelection;
|
|
property OptionsView;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property PopupMenu;
|
|
property Preview;
|
|
property StateImages;
|
|
property Styles;
|
|
property StylesEvents;
|
|
property TabOrder;
|
|
property TabStop;
|
|
property Visible;
|
|
// TreeList events
|
|
property OnAfterSorting;
|
|
property OnAfterSummary;
|
|
property OnBandHeaderClick;
|
|
property OnBandSizeChanged;
|
|
property OnCanResize;
|
|
property OnCanSelectNode;
|
|
property OnChange;
|
|
property OnClick;
|
|
property OnCollapsed;
|
|
property OnCollapsing;
|
|
property OnColumnHeaderClick;
|
|
property OnColumnSizeChanged;
|
|
property OnCompare;
|
|
property OnConstrainedResize;
|
|
property OnSorting;
|
|
{$IFDEF DELPHI5}
|
|
property OnContextPopup;
|
|
{$ENDIF}
|
|
property OnCustomDrawBackground;
|
|
property OnCustomDrawBandHeader;
|
|
property OnCustomDrawCell;
|
|
property OnCustomDrawCellsGroup;
|
|
property OnCustomDrawFooter;
|
|
property OnCustomDrawFooterCell;
|
|
property OnCustomDrawHeader;
|
|
property OnCustomDrawHeaderCell;
|
|
property OnCustomDrawIndentCell;
|
|
property OnCustomDrawIndicatorCell;
|
|
property OnCustomDrawPreview;
|
|
property OnCustomizationFormVisibleChanged;
|
|
property OnDataChanged;
|
|
property OnDblClick;
|
|
property OnDeletion;
|
|
property OnDockDrop;
|
|
property OnDockOver;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnEdited;
|
|
property OnEditing;
|
|
property OnEditValueChanged;
|
|
property OnEndDock;
|
|
property OnEndDrag;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnExpanded;
|
|
property OnExpanding;
|
|
property OnFocusedColumnChanged;
|
|
property OnFocusedNodeChanged;
|
|
property OnGetNodeImageIndex;
|
|
property OnGetNodePreviewHeight;
|
|
property OnGetSiteInfo;
|
|
property OnHotTrackNode;
|
|
property OnInitEdit;
|
|
property OnIsGroupNode;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
property OnLayoutChanged;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnMouseWheel;
|
|
property OnMouseWheelDown;
|
|
property OnMouseWheelUp;
|
|
property OnMoveTo;
|
|
property OnNodeChanged;
|
|
property OnResize;
|
|
property OnSelectionChanged;
|
|
property OnStartDock;
|
|
property OnStartDrag;
|
|
property OnSummary;
|
|
property OnTopRecordIndexChanged;
|
|
property OnUnDock;
|
|
end;
|
|
|
|
procedure cxTreeListError(const Description: string);
|
|
function cxCompareColumnsPos(AItem1, AItem2: Pointer): Integer;
|
|
function cxCompareColumnsPosEx(AItem1, AItem2: Pointer): Integer;
|
|
|
|
var
|
|
DesignerNavigatorProc: procedure(AListener: TObject; AddListener: Boolean) of object;
|
|
|
|
implementation
|
|
|
|
{$R cxTL.res}
|
|
|
|
const
|
|
cxTreeListVersion = $00040002;
|
|
|
|
cxInvalidIndex = -1;
|
|
cxMinCapacityInc = 32;
|
|
cxMaxCapacityInc = 32768;
|
|
|
|
cxDefaultImageIndexes: TcxTreeListNodeImageIndexes = (0, 0, -1);
|
|
|
|
// internal column state
|
|
|
|
tlcsVisible = $08;
|
|
|
|
// internal band state
|
|
tlbsVisible = $00;
|
|
tlbsFixedLeft = $02;
|
|
tlbsFixedRight = $04;
|
|
tlbsAllFixed = tlbsFixedRight or tlbsFixedLeft;
|
|
|
|
ColumnPropertiesName: array[0..11] of string =
|
|
('Visible', 'Index', 'LineCount', 'ColIndex', 'RowIndex',
|
|
'BandIndex', 'Caption', 'SortOrder', 'SortIndex', 'RealMinWidth', 'IsWidthAssigned', 'RealWidth');
|
|
BandPropertiesName: array[0..4] of string =
|
|
('Caption', 'RealMinWidth', 'RealWidth', 'Visible', 'Index');
|
|
|
|
GridLineBorders: array[TcxTreeListGridLines] of TcxBorders =
|
|
([], [bTop, bBottom], [bLeft, bRight], cxBordersAll);
|
|
|
|
type
|
|
TAllowExpandChangingFunc = function: Boolean of object;
|
|
|
|
TcxDataControllerAccess = class(TcxDataController);
|
|
TcxItemDataBindingAccess = class(TcxItemDataBinding);
|
|
TControlAccess = class(TWinControl);
|
|
TcxEditingControllerAccess = class(TcxEditingController);
|
|
|
|
TcxDefColorFunc = function: TColor of object;
|
|
|
|
TcxTreeListDataSignature = packed record
|
|
Version, Size: Integer;
|
|
end;
|
|
|
|
{ TSortingManager }
|
|
|
|
PNodesList = ^TNodesList;
|
|
TNodesList = array[0..MaxInt div SizeOf(Pointer) - 1] of TcxTreeListNode;
|
|
|
|
PcxSortData = ^TcxSortData;
|
|
TcxSortData = record
|
|
Count: Integer;
|
|
Items: PIntArray;
|
|
end;
|
|
|
|
PcxSortingItem = ^TcxSortingItem;
|
|
TcxSortingItem = packed record
|
|
Capacity: Integer;
|
|
Compare: TcxTreeListCompareFunc;
|
|
IsInternalCompare: Boolean;
|
|
Count: Integer;
|
|
DataController: TcxCustomDataController;
|
|
NodesList: PNodesList;
|
|
Node: TcxTreeListNode;
|
|
NeedUpdate: Boolean;
|
|
TreeList: TcxCustomTreeListControl;
|
|
SortOrderList: TList;
|
|
Recurse: Boolean;
|
|
RefCount: Integer;
|
|
end;
|
|
|
|
TSortingManager = class
|
|
private
|
|
FList: TList;
|
|
protected
|
|
function AddItem(ANode: TcxTreeListNode; ACompare: TcxTreeListCompareFunc;
|
|
ARecurse: Boolean): PcxSortingItem;
|
|
procedure DoneItem(AItem: PcxSortingItem);
|
|
procedure InitItem(AItem: PcxSortingItem);
|
|
procedure InternalSort(AItem: PcxSortingItem);
|
|
procedure InternalSortChildren(AItem: PcxSortingItem);
|
|
procedure UpdateLinks(AItem: PcxSortingItem);
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Sort(ANode: TcxTreeListNode;
|
|
ACompare: TcxTreeListCompareFunc; ARecurse: Boolean = False);
|
|
end;
|
|
|
|
{ TcxTemporaryCellViewInfo }
|
|
|
|
TcxTemporaryCellViewInfo = class(TcxTreeListEditCellViewInfo)
|
|
private
|
|
function GetNode: TcxTreeListNode; override;
|
|
function GetNodesViewInfo: TcxTreeListNodesViewInfo; override;
|
|
function GetNodeViewInfo: TcxTreeListNodeViewInfo; override;
|
|
function GetTreeList: TcxCustomTreeListControl; override;
|
|
protected
|
|
CellColumn: TcxTreeListColumn;
|
|
NodeIsFocused: Boolean;
|
|
CellNode: TcxTreeListNode;
|
|
function ContentOffset: TRect; override;
|
|
function GetButtonTransparency: TcxEditButtonTransparency; override;
|
|
function GetColumn: TcxTreeListColumn; override;
|
|
function GetEditContainer: TcxCustomInplaceEditContainer; override;
|
|
function GetFocused: Boolean; override;
|
|
function GetLineCount: Integer; override;
|
|
function GetRecordIndex: Integer; override;
|
|
function GetSelected: Boolean; override;
|
|
function IsAutoHeight: Boolean; override;
|
|
function IsEndEllipsis: Boolean; override;
|
|
public
|
|
destructor Destroy; override;
|
|
function CalculateWidth(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode;
|
|
AIsFocused: Boolean; AHeight: Integer): Integer;
|
|
property Column;
|
|
property Node;
|
|
property TreeList;
|
|
end;
|
|
|
|
var
|
|
SortingManager: TSortingManager;
|
|
|
|
function cxFind(ATreeList: TcxCustomTreeListControl; AData: Pointer;
|
|
AStart: TcxTreeListNode; AExpandedOnly, AForward: Boolean;
|
|
AFilter: TcxTreeListFindFunc): TcxTreeListNode;
|
|
|
|
function LoadChildren(ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
with ANode do
|
|
begin
|
|
if (FCount = 0) and HasChildren and not Expanded and not AExpandedOnly then
|
|
begin
|
|
ANode.Expanded := True;
|
|
ANode.Expanded := False;
|
|
end;
|
|
Result := (FCount <> 0) and (Expanded or not AExpandedOnly);
|
|
end;
|
|
end;
|
|
|
|
function GetNext(ANode: TcxTreeListNode): TcxTreeListNode;
|
|
begin
|
|
Result := ANode;
|
|
if not LoadChildren(Result) then
|
|
while Result <> nil do
|
|
begin
|
|
if Result.FNext <> nil then
|
|
begin
|
|
Result := Result.FNext;
|
|
Break;
|
|
end;
|
|
while (Result <> nil) and (Result.FNext = nil) do
|
|
Result := Result.Parent;
|
|
end
|
|
else
|
|
Result := Result.FFirst;
|
|
end;
|
|
|
|
function GetPrev(ANode: TcxTreeListNode): TcxTreeListNode;
|
|
begin
|
|
Result := ANode;
|
|
if Result.FPrev <> nil then
|
|
begin
|
|
Result := Result.FPrev;
|
|
while LoadChildren(Result) do Result := Result.FLast;
|
|
end
|
|
else
|
|
begin
|
|
Result := Result.Parent;
|
|
if Result = ATreeList.Nodes.Root then
|
|
Result := nil;;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Result := nil;
|
|
if AStart = nil then
|
|
AStart := ATreeList.FNodes.Root.FFirst;
|
|
ATreeList.BeginUpdate;
|
|
try
|
|
while (AStart <> nil) and (Result = nil) do
|
|
begin
|
|
if AFilter(AStart, AData) then
|
|
Result := AStart
|
|
else
|
|
begin
|
|
if AForward then
|
|
AStart := GetNext(AStart)
|
|
else
|
|
AStart := GetPrev(AStart);
|
|
end;
|
|
end;
|
|
finally
|
|
ATreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function cxGetLatest(
|
|
ANode: TcxTreeListNode; ACheckExpanded: Boolean = True): TcxTreeListNode;
|
|
begin
|
|
Result := ANode;
|
|
if Result <> nil then
|
|
begin
|
|
if ACheckExpanded then
|
|
while (Result.FCount > 0) and (Result.FState and tlnsCollapsed = 0) do
|
|
Result := Result.FLast
|
|
else
|
|
while Result.Count > 0 do Result := Result.FLast;
|
|
end;
|
|
end;
|
|
|
|
function cxGetState(Flags: Integer; Index: Integer): Boolean;
|
|
begin
|
|
Result := (Flags and (1 shl Index)) <> 0;
|
|
end;
|
|
|
|
function cxHitDelta(CanSizing: Boolean): Integer;
|
|
begin
|
|
if CanSizing then
|
|
Result := cxtlHitDelta
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure cxRectScaleH(var ARect: TRect; AHeight: Integer);
|
|
begin
|
|
with ARect do
|
|
begin
|
|
Top := Top * AHeight;
|
|
Bottom := Top + Bottom * AHeight;
|
|
end;
|
|
end;
|
|
|
|
procedure cxRectSetTopEx(var ARect: TRect; ATop, AHeight: Integer); overload;
|
|
begin
|
|
with ARect do
|
|
begin
|
|
Bottom := ATop + AHeight;
|
|
Top := ATop;
|
|
end;
|
|
end;
|
|
|
|
procedure cxRectSetTopEx(var ARect: TRect; const ASrcRect: TRect); overload;
|
|
begin
|
|
ARect.Top := ASrcRect.Top;
|
|
ARect.Bottom := ASrcRect.Bottom;
|
|
end;
|
|
|
|
procedure cxRectSetHeightEx(var ARect: TRect; const AHeight: Integer); overload;
|
|
begin
|
|
ARect.Bottom := ARect.Top + AHeight;
|
|
end;
|
|
|
|
procedure cxRectSetHeightEx(var ARect: TRect; const ASrcRect: TRect); overload;
|
|
begin
|
|
ARect.Bottom := ARect.Top + (ASrcRect.Bottom - ASrcRect.Top);
|
|
end;
|
|
|
|
procedure cxSetMax(var AValue: Integer; ANewValue: Integer);
|
|
begin
|
|
if AValue < ANewValue then AValue := ANewValue;
|
|
end;
|
|
|
|
procedure cxSetMin(var AValue: Integer; ANewValue: Integer);
|
|
begin
|
|
if AValue > ANewValue then AValue := ANewValue;
|
|
end;
|
|
|
|
function cxExcludeBorders(const ARect: TRect; ABorders: TcxBorders): TRect;
|
|
begin
|
|
Result := ARect;
|
|
with Result do
|
|
begin
|
|
Inc(Left, Byte(bLeft in ABorders));
|
|
Inc(Top, Byte(bTop in ABorders));
|
|
Dec(Right, Byte(bRight in ABorders));
|
|
Dec(Bottom, Byte(bBottom in ABorders));
|
|
end;
|
|
end;
|
|
|
|
procedure cxGetIndexes(AList: TList; AItem: TObject;
|
|
var AFromIndex, AToIndex: Integer);
|
|
begin
|
|
AFromIndex := 0;
|
|
AToIndex := AList.Count - 1;
|
|
if AList.Last = AItem then
|
|
AToIndex := AList.IndexOf(AItem) - 1
|
|
else
|
|
AFromIndex := AList.IndexOf(AItem) + 1;
|
|
end;
|
|
|
|
procedure cxCalcSeparators(var ASeparators: TcxTreeListSeparators;
|
|
const AControlSeparators: TcxTreeListSeparators; const ABounds: TRect);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := Low(TcxTreeListSeparators) to High(TcxTreeListSeparators) do
|
|
cxRectIntersect(ASeparators[I], AControlSeparators[I], ABounds);
|
|
end;
|
|
|
|
function cxGetNativeColor(AColor: TColor; ADefColorFunc: TcxDefColorFunc): TColor;
|
|
begin
|
|
if AColor = clDefault then
|
|
Result := ADefColorFunc
|
|
else
|
|
Result := AColor;
|
|
end;
|
|
|
|
function cxSetState(var Flags: Integer; Index: Integer; Value: Boolean): Boolean;
|
|
begin
|
|
Result := (Flags and (1 shl Index) <> 0) <> Value;
|
|
if Result then
|
|
begin
|
|
if Value then
|
|
Flags := Flags or (1 shl Index)
|
|
else
|
|
Flags := Flags xor (1 shl Index);
|
|
end;
|
|
end;
|
|
|
|
procedure cxValidateIntDef(var Value: Integer; AMin: Integer; AMax: Integer = MaxInt);
|
|
begin
|
|
if Value < AMin then
|
|
Value := AMin
|
|
else
|
|
if Value > AMax then
|
|
Value := AMax;
|
|
end;
|
|
|
|
function cxValidateIntDefEx(var Value: Integer; ADefValue: Integer;
|
|
AMin: Integer; AMax: Integer = MaxInt): Boolean;
|
|
begin
|
|
cxValidateIntDef(Value, AMin, AMax);
|
|
Result := Value <> ADefValue;
|
|
end;
|
|
|
|
function cxCheckValue(AValue, AMin, AMax: Integer): Boolean;
|
|
begin
|
|
Result := (AValue >= AMin) and (AValue < AMax);
|
|
end;
|
|
|
|
function cxMin(AValue1, AValue2: Integer): Integer;
|
|
begin
|
|
if AValue1 > AValue2 then
|
|
Result := AValue2
|
|
else
|
|
Result := AValue1;
|
|
end;
|
|
|
|
function cxMax(AValue1, AValue2: Integer): Integer;
|
|
begin
|
|
if AValue1 > AValue2 then
|
|
Result := AValue1
|
|
else
|
|
Result := AValue2;
|
|
end;
|
|
|
|
procedure cxOffsetHorz(var Value: TRect; DX: Integer);
|
|
begin
|
|
Inc(Value.Left, DX);
|
|
Inc(Value.Right, DX);
|
|
end;
|
|
|
|
function cxParamsCombine(AStyle: TcxStyle; HasValues: TcxStyleValues;
|
|
var AParams: TcxViewParams): TcxStyleValues;
|
|
|
|
function SetValue(AValue: TcxStyleValue; var ASetValues: TcxStyleValues): Boolean;
|
|
begin
|
|
Result := not (AValue in HasValues) and (AValue in AStyle.AssignedValues);
|
|
if Result then Include(ASetValues, AValue);
|
|
end;
|
|
|
|
begin
|
|
Result := HasValues;
|
|
if (AStyle = nil) or ([svColor, svFont, svTextColor, svBitmap] = HasValues) or
|
|
(csDestroying in AStyle.ComponentState) then Exit;
|
|
with AParams do
|
|
begin
|
|
if SetValue(svColor, Result) then Color := AStyle.Color;
|
|
if (AStyle.Font <> nil) and SetValue(svFont, Result) then Font := AStyle.Font;
|
|
if SetValue(svTextColor, Result) then TextColor := AStyle.TextColor;
|
|
if SetValue(svBitmap, Result) then Bitmap := AStyle.Bitmap;
|
|
end;
|
|
end;
|
|
|
|
function cxCompareColumnsPos(AItem1, AItem2: Pointer): Integer;
|
|
begin
|
|
with TcxTreeListColumn(AItem1).Position, TcxTreeListColumn(AItem2) do
|
|
begin
|
|
Result := FRowIndex - Position.FRowIndex;
|
|
if Result = 0 then
|
|
Result := FColIndex - Position.FColIndex
|
|
end;
|
|
end;
|
|
|
|
function cxCompareColumnsPosEx(AItem1, AItem2: Pointer): Integer;
|
|
begin
|
|
with TcxTreeListColumn(AItem1).Position, TcxTreeListColumn(AItem2) do
|
|
begin
|
|
Result := FRowIndex - Position.FRowIndex;
|
|
if Result = 0 then
|
|
Result := OwnerBandVisibleIndex - Position.OwnerBandVisibleIndex;
|
|
if Result = 0 then
|
|
Result := FColIndex - Position.FColIndex
|
|
end;
|
|
end;
|
|
|
|
function cxCompareVisibleBands(AItem1, AItem2: Pointer): Integer;
|
|
const
|
|
AWeights: array[TcxTreeListBandFixedKind] of Integer = (0, -1, 1);
|
|
begin
|
|
with TcxTreeListBand(AItem1) do
|
|
begin
|
|
Result := AWeights[FixedKind] - AWeights[TcxTreeListBand(AItem2).FixedKind];
|
|
if Result = 0 then
|
|
Result := Index - TcxTreeListBand(AItem2).Index;
|
|
end;
|
|
end;
|
|
|
|
function cxIntegerListCompare(AItem1, AItem2: Pointer): Integer;
|
|
begin
|
|
Result := Integer(AItem1) - Integer(AItem2);
|
|
end;
|
|
|
|
procedure cxCheckObjectList(AList: TList; ACount: Integer;
|
|
AItemClass: TcxCustomViewInfoItemClass; AOwner: TObject);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with AList do
|
|
begin
|
|
for I := ACount to Count - 1 do FreeAndNil(TObject(List^[I]));
|
|
I := Count;
|
|
Count := ACount;
|
|
while I < Count do
|
|
begin
|
|
List^[I] := AItemClass.Create(AOwner);
|
|
Inc(I);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure cxValidateSingleLine(APos: TcxTreeListColumnPosition);
|
|
begin
|
|
APos.FRowIndex := 0;
|
|
APos.FLineCount := 1;
|
|
end;
|
|
|
|
procedure cxShiftEditViewInfoItem(
|
|
AViewInfo: TcxTreeListEditCellViewInfo; DX, DY: Integer);
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
OffsetRect(CellEditRect, DX, DY);;
|
|
OffsetRect(CellContentRect, DX, DY);
|
|
OffsetRect(DisplayRect, DX, DY);
|
|
if ViewInfo <> nil then
|
|
begin
|
|
ViewInfo.Top := CellContentRect.Top;
|
|
ViewInfo.Left := CellContentRect.Left;
|
|
end;
|
|
ItemVisible := cxRectIntersect(ClipRect, DisplayRect, NodesViewInfo.ClipRect);
|
|
end;
|
|
end;
|
|
|
|
procedure cxTreeListError(const Description: string);
|
|
begin
|
|
raise EcxTreeList.Create(Description);
|
|
end;
|
|
|
|
procedure cxError(Condition: Boolean;
|
|
const Description: string; Args: array of const); overload;
|
|
begin
|
|
if Condition then
|
|
raise EdxException.CreateFmt(Description, Args);
|
|
end;
|
|
|
|
function cxIternalCompare(AItem: PcxSortingItem; ANode1, ANode2: TcxTreeListNode): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
with AItem^, TcxDataControllerAccess(DataController) do
|
|
begin
|
|
for I := 0 to SortOrderList.Count - 1 do
|
|
begin
|
|
Result := CompareRecords(ANode1.FRecordIndex, ANode2.FRecordIndex, PcxDataSortInfo(SortOrderList.List^[I])^);
|
|
if Result <> 0 then Exit;
|
|
end;
|
|
if Result = 0 then
|
|
Result := CompareEqualRecords(ANode1.FRecordIndex, ANode2.RecordIndex);
|
|
end;
|
|
end;
|
|
|
|
function cxDoCustomCompare(AItem: PcxSortingItem; ANode1, ANode2: TcxTreeListNode): Integer;
|
|
begin
|
|
with AItem^ do
|
|
begin
|
|
if Assigned(Compare) then
|
|
Result := Compare(ANode1, ANode2)
|
|
else
|
|
TreeList.DoOnCompare(ANode1, ANode2, Result);
|
|
end;
|
|
end;
|
|
|
|
{ TSortingManager }
|
|
|
|
constructor TSortingManager.Create;
|
|
begin
|
|
FList := TList.Create;
|
|
end;
|
|
|
|
destructor TSortingManager.Destroy;
|
|
begin
|
|
FreeAndNil(FList);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TSortingManager.Sort(ANode: TcxTreeListNode;
|
|
ACompare: TcxTreeListCompareFunc; ARecurse: Boolean = False);
|
|
var
|
|
AItem: PcxSortingItem;
|
|
begin
|
|
if ANode.FCount = 0 then Exit;
|
|
AItem := AddItem(ANode, ACompare, ARecurse);
|
|
InternalSort(AItem);
|
|
end;
|
|
|
|
function TSortingManager.AddItem(ANode: TcxTreeListNode;
|
|
ACompare: TcxTreeListCompareFunc; ARecurse: Boolean): PcxSortingItem;
|
|
begin
|
|
Result := AllocMem(SizeOf(TcxSortingItem));
|
|
FList.Add(Result);
|
|
with Result^ do
|
|
begin
|
|
TreeList := ANode.TreeList;
|
|
IsInternalCompare := not (Assigned(ACompare) or Assigned(TreeList.FOnCompare));
|
|
Compare := ACompare;
|
|
Node := ANode;
|
|
Recurse := ARecurse;
|
|
SortOrderList := TreeList.SortOrderList;
|
|
DataController := TreeList.DataController;
|
|
end;
|
|
end;
|
|
|
|
procedure TSortingManager.DoneItem(AItem: PcxSortingItem);
|
|
begin
|
|
with AItem^ do
|
|
begin
|
|
Dec(RefCount);
|
|
if RefCount = 0 then
|
|
begin
|
|
FreeMem(NodesList);
|
|
FList.Remove(AItem);
|
|
if NeedUpdate then
|
|
try
|
|
with Node.Owner do
|
|
begin
|
|
IsInvalidState := True;
|
|
CalculateInfo(False);
|
|
TreeList.DoLayoutChanged;
|
|
NodesViewInfo.Owner.InvalidateRect(NodesViewInfo.ClipRect);
|
|
// TreeList.MakeNodeVisible(TreeList.FocusedNode);
|
|
TreeList.DoChanged;
|
|
end;
|
|
finally
|
|
FreeMem(AItem);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TSortingManager.InitItem(AItem: PcxSortingItem);
|
|
var
|
|
I: Integer;
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
with AItem^ do
|
|
begin
|
|
Count := Node.FCount;
|
|
if Capacity <= Count then
|
|
begin
|
|
ReallocMem(NodesList, Count * SizeOf(Pointer));
|
|
Capacity := Count;
|
|
end;
|
|
Inc(RefCount);
|
|
if Count = 0 then Exit;
|
|
ANode := Node.FFirst;
|
|
I := 0;
|
|
while I < Count do
|
|
begin
|
|
NodesList^[I] := ANode;
|
|
ANode := ANode.FNext;
|
|
Inc(I);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TSortingManager.InternalSort(AItem: PcxSortingItem);
|
|
|
|
procedure DoSort(L, R: Integer);
|
|
var
|
|
I, J: Integer;
|
|
TMP: TcxTreeListNode;
|
|
Mid: TcxTreeListNode;
|
|
begin
|
|
with AItem^ do
|
|
repeat
|
|
I := L;
|
|
J := R;
|
|
Mid := NodesList^[(L + R) shr 1];
|
|
repeat
|
|
if IsInternalCompare then
|
|
begin
|
|
while cxIternalCompare(AItem, NodesList^[I], Mid) < 0 do Inc(I);
|
|
while cxIternalCompare(AItem, NodesList^[J], Mid) > 0 do Dec(J);
|
|
end
|
|
else
|
|
begin
|
|
while cxDoCustomCompare(AItem, NodesList^[I], Mid) < 0 do Inc(I);
|
|
while cxDoCustomCompare(AItem, NodesList^[J], Mid) > 0 do Dec(J);
|
|
end;
|
|
if I <= J then
|
|
begin
|
|
NeedUpdate := True;
|
|
TMP := NodesList^[I];
|
|
NodesList^[I] := NodesList^[J];
|
|
NodesList^[J] := TMP;
|
|
Inc(I);
|
|
Dec(J);
|
|
end;
|
|
until I > J;
|
|
if L < J then DoSort(L, J);
|
|
L := I;
|
|
until I >= R;
|
|
end;
|
|
|
|
begin
|
|
InitItem(AItem);
|
|
try
|
|
DoSort(0, AItem.Count - 1);
|
|
UpdateLinks(AItem);
|
|
if AItem.Recurse then
|
|
InternalSortChildren(AItem);
|
|
finally
|
|
DoneItem(AItem);
|
|
end;
|
|
end;
|
|
|
|
procedure TSortingManager.InternalSortChildren(AItem: PcxSortingItem);
|
|
var
|
|
ANeedUpdate: Boolean;
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
ANeedUpdate := False;
|
|
with AItem^ do
|
|
try
|
|
ANeedUpdate := NeedUpdate;
|
|
ANode := Node.FFirst;
|
|
while ANode <> nil do
|
|
begin
|
|
NeedUpdate := False;
|
|
AItem^.Node := ANode;
|
|
if ANode.Count > 0 then InternalSort(AItem);
|
|
ANeedUpdate := ANeedUpdate or NeedUpdate;
|
|
ANode := ANode.FNext;
|
|
end;
|
|
finally
|
|
NeedUpdate := ANeedUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TSortingManager.UpdateLinks(AItem: PcxSortingItem);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Dec(AItem^.Count);
|
|
with AItem^ do
|
|
begin
|
|
if (Count = 0) or not NeedUpdate then Exit;
|
|
for I := 0 to Count do
|
|
begin
|
|
with NodesList^[I] do
|
|
begin
|
|
FIndex := I;
|
|
if I > 0 then
|
|
FPrev := NodesList^[I - 1]
|
|
else
|
|
FPrev := nil;
|
|
if I < AItem^.Count then
|
|
FNext := NodesList^[I + 1]
|
|
else
|
|
FNext := nil;
|
|
FIndex := I;
|
|
end;
|
|
end;
|
|
Node.FFirst := NodesList^[0];
|
|
Node.FLast := NodesList^[Count];
|
|
end;
|
|
end;
|
|
|
|
{ TcxTemporaryCellViewInfo }
|
|
|
|
destructor TcxTemporaryCellViewInfo.Destroy;
|
|
begin
|
|
CellColumn := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.CalculateWidth(AColumn: TcxTreeListColumn;
|
|
ANode: TcxTreeListNode; AIsFocused: Boolean; AHeight: Integer): Integer;
|
|
begin
|
|
NodeIsFocused := AIsFocused;
|
|
CellNode := ANode;
|
|
CellColumn := AColumn;
|
|
Column.InitEditViewInfo(Self);
|
|
CellContentRect := cxRect(0, 0, 0, AHeight);
|
|
Result := CellColumn.GetEditWidth(Self) +
|
|
Byte(AColumn.TreeList.OptionsView.GridLines in [tlglBoth, tlglVert]) shl 1 + 2;
|
|
if Result < Column.MinWidth then
|
|
Result := Column.MinWidth;
|
|
if AColumn.IsLeftMost then
|
|
Inc(Result, AColumn.TreeList.ImagesIndentWidth);
|
|
if Result > Column.Data then
|
|
Column.Data := Result;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.ContentOffset: TRect;
|
|
begin
|
|
Result := cxNullRect;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetButtonTransparency: TcxEditButtonTransparency;
|
|
begin
|
|
Result := ebtNone;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := CellColumn;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetEditContainer: TcxCustomInplaceEditContainer;
|
|
begin
|
|
Result := CellColumn;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetFocused: Boolean;
|
|
begin
|
|
Result := NodeIsFocused;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetLineCount: Integer;
|
|
begin
|
|
Result := 1;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetRecordIndex: Integer;
|
|
begin
|
|
Result := CellNode.RecordIndex;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetSelected: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.IsAutoHeight: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.IsEndEllipsis: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetNode: TcxTreeListNode;
|
|
begin
|
|
Result := CellNode;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetNodeViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTemporaryCellViewInfo.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Column.TreeList;
|
|
end;
|
|
|
|
{ TcxTreeListNodes}
|
|
|
|
constructor TcxTreeListNodes.Create(AOwner: TcxCustomTreeListControl);
|
|
begin
|
|
FOwner := AOwner;
|
|
FRoot := TcxTreeListRootNode.Create(Self);
|
|
FRoot.FState := 0;
|
|
end;
|
|
|
|
destructor TcxTreeListNodes.Destroy;
|
|
begin
|
|
FState := FState or tlnsDeleting;
|
|
TreeList.BeginUpdate;
|
|
try
|
|
FreeAndNil(FRoot);
|
|
finally
|
|
TreeList.CancelUpdate;
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListNodes then
|
|
TreeList.DoAssignNodes(Source as TcxTreeListNodes)
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.Clear;
|
|
begin
|
|
if TreeList.NodesList.Count = 0 then Exit;
|
|
if not TreeList.SafeDelete and not TreeList.IsDestroying then
|
|
TreeList.UpdateFocusedRecordPost;
|
|
TreeList.BeginUpdate;
|
|
try
|
|
NodesViewInfo.Clear;
|
|
Root.DeleteChildren;
|
|
finally
|
|
TopIndex := 0;
|
|
TopNode := nil;
|
|
FState := tlnsIndexesInvalid;
|
|
TreeList.DoValidateDeletedNodes;
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.Changed;
|
|
begin
|
|
FFoundItem := nil;
|
|
IsInvalidState := True;
|
|
NodesViewInfo.TopNode := nil;
|
|
TreeList.LayoutChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.CalculateInfo(IsLocked: Boolean);
|
|
|
|
procedure DoCalc(ANode: TcxTreeListNode; ALevel: Integer);
|
|
begin
|
|
while ANode <> nil do
|
|
begin
|
|
if ALevel > FMaxLevel then FMaxLevel := ALevel;
|
|
if TopIndex >= FVisibleCount then TopNode := ANode;
|
|
ANode.FVisibleIndex := FVisibleCount;
|
|
Inc(FVisibleCount);
|
|
with ANode do
|
|
if Expanded then DoCalc(FFirst, ALevel + 1);
|
|
ANode := ANode.FNext;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if not IsInvalidState and (TopNode <> nil) then Exit;
|
|
if not IsLocked then
|
|
begin
|
|
FMaxLevel := -1;
|
|
FVisibleCount := 0;
|
|
if TopIndex < 0 then TopIndex := 0;
|
|
DoCalc(FRoot.FFirst, 0);
|
|
if TopIndex > FVisibleCount then TopIndex := FVisibleCount - 1;
|
|
IsInvalidState := False
|
|
end
|
|
else
|
|
begin
|
|
FMaxLevel := 0;
|
|
FVisibleCount := -1;
|
|
TopIndex := 0;
|
|
TopNode := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.DoNodeChanged(ANode: TcxTreeListNode);
|
|
begin
|
|
if ANode = nil then
|
|
Changed
|
|
else
|
|
TreeList.DoNodeChanged(ANode);
|
|
end;
|
|
|
|
class function TcxTreeListNodes.FindBetween(
|
|
AFirst, ALast: TcxTreeListNode; ACount, AIndex: Integer): TcxTreeListNode;
|
|
begin
|
|
cxError((AIndex < 0) or (AIndex >= ACount) or (AFirst.Index > AIndex) or
|
|
(ALast.FIndex < AIndex), scxStr(@scxIndexOutOfBounds), [AIndex]);
|
|
if (ALast.Index shr 1) <= AIndex then
|
|
begin
|
|
Result := ALast;
|
|
while Result.FIndex <> AIndex do Result := Result.FPrev;
|
|
end
|
|
else
|
|
begin
|
|
Result := AFirst;
|
|
while Result.FIndex <> AIndex do Result := Result.FNext;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetOwner: TPersistent;
|
|
begin
|
|
Result := FOwner;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetVisibleNode(var AIndex: Integer): TcxTreeListNode;
|
|
|
|
procedure DoSearch(AStartNode, AEndNode: TcxTreeListNode;
|
|
AFromEnd: Boolean; var ANode: TcxTreeListNode);
|
|
begin
|
|
if AFromEnd then
|
|
begin
|
|
ANode := AEndNode;
|
|
while (ANode <> nil) and (ANode.FVisibleIndex > AIndex) do
|
|
ANode := ANode.GetPrevVisible;
|
|
end
|
|
else
|
|
begin
|
|
Result := AStartNode;
|
|
while (ANode <> nil) and (ANode.FVisibleIndex < AIndex) do
|
|
Result := ANode.GetNextVisible;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
CalculateInfo(False);
|
|
cxValidateIntDefEx(AIndex, -1, 0, VisibleCount - 1);
|
|
if TopNode = nil then
|
|
begin
|
|
TopNode := Root.FFirst;
|
|
TopIndex := 0;
|
|
end
|
|
else
|
|
if TopNode.VisibleIndex <> TopIndex then
|
|
TopIndex := TopNode.VisibleIndex;
|
|
if AIndex >= TopIndex then
|
|
DoSearch(TopNode, cxGetLatest(Root.FLast),
|
|
AIndex > ((VisibleCount + TopIndex) shr 1), Result)
|
|
else
|
|
DoSearch(Root.FFirst, TopNode, AIndex > (TopIndex shr 1), Result);
|
|
if Result = nil then
|
|
AIndex := 0
|
|
else
|
|
AIndex := Result.FVisibleIndex;
|
|
end;
|
|
|
|
function TcxTreeListNodes.InternalAddNode(ANode, ARelative: TcxTreeListNode;
|
|
AddMethod: TcxTreeListNodeAttachMode): TcxTreeListNode;
|
|
const
|
|
IsAddChild: array[TcxTreeListNodeAttachMode] of Boolean =
|
|
(False, False, True, True, False);
|
|
AddMode: array[TcxTreeListNodeAttachMode] of TcxTreeListNodeAddMode =
|
|
(tlnaAdd, tlnaAddFirst, tlnaAdd, tlnaAddFirst, tlnaInsert);
|
|
begin
|
|
if ANode = nil then
|
|
Result := TreeList.DoCreateNode
|
|
else
|
|
Result := ANode;
|
|
if (ARelative = nil) and (AddMethod = tlamInsert) then
|
|
AddMethod := tlamAdd;
|
|
if ARelative <> nil then
|
|
SetNodeParent(Result, ARelative, AddMode[AddMethod])
|
|
else
|
|
SetNodeParent(Result, FRoot, AddMode[AddMethod]);
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.SetNodeParent(ANewNode, ANewParent: TcxTreeListNode;
|
|
AMode: TcxTreeListNodeAddMode);
|
|
begin
|
|
TreeList.BeforeAddNode(ANewNode, ANewParent, AMode);
|
|
case AMode of
|
|
tlnaAdd:
|
|
ANewParent.SetLast(ANewNode);
|
|
tlnaAddFirst:
|
|
ANewParent.SetFirst(ANewNode);
|
|
tlnaInsert:
|
|
ANewNode.InternalInsert(ANewParent);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.SetTopVisibleIndex(AIndex: Integer);
|
|
begin
|
|
TopNode := GetVisibleNode(AIndex);
|
|
TopIndex := AIndex;
|
|
NodesViewInfo.TopNode := nil;
|
|
if AIndex >= 0 then
|
|
NodesViewInfo.SynchronizeTopNode;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetAbsoluteItem(AFindIndex: Integer): TcxTreeListNode;
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
Result := nil;
|
|
if cxInRange(AFindIndex, 0, Count - 1) then
|
|
begin
|
|
AIndex := 0;
|
|
Result := Root.FFirst;
|
|
while AFindIndex <> AIndex do
|
|
begin
|
|
Inc(AIndex);
|
|
if Result.Count > 0 then
|
|
Result := Result.FFirst
|
|
else
|
|
begin
|
|
while Result.FNext = nil do Result := Result.Parent;
|
|
Result := Result.FNext;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetCount: Integer;
|
|
begin
|
|
Result := TreeList.NodesList.Count;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetDataController: TcxControlDataController;
|
|
begin
|
|
Result := TcxControlDataController(TreeList.DataController);
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetItem(AIndex: Integer): TcxTreeListNode;
|
|
begin
|
|
Result := TcxTreeListNode(TreeList.NodesList[AIndex]);
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetMaxLevel: Integer;
|
|
begin
|
|
CalculateInfo(TreeList.IsLocked);
|
|
Result := FMaxLevel;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := FState and Index <> 0;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetVisibleCount: Integer;
|
|
begin
|
|
CalculateInfo(TreeList.IsLocked);
|
|
Result := FVisibleCount;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
if Value then
|
|
FState := FState or Index
|
|
else
|
|
FState := FState and not Index;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
begin
|
|
Result := TreeList.ViewInfo.NodesViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListNodes.GetTopVisibleNode: TcxTreeListNode;
|
|
begin
|
|
CalculateInfo(TreeList.IsLocked);
|
|
Result := TopNode;
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.SetAbsoluteItem(
|
|
Index: Integer; Value: TcxTreeListNode);
|
|
begin
|
|
AbsoluteItems[Index].Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListNodes.SetItem(
|
|
AIndex: Integer; Value: TcxTreeListNode);
|
|
begin
|
|
GetItem(AIndex).Assign(Value);
|
|
end;
|
|
|
|
{ TcxTreeListNode }
|
|
|
|
constructor TcxTreeListNode.Create(AOwner: TcxTreeListNodes);
|
|
begin
|
|
FOwner := AOwner;
|
|
FState := FState or tlnsCollapsed;
|
|
FillChar(FImageIndexes, SizeOf(FImageIndexes), -1);
|
|
if Owner.State and tlnsInternalCreating = 0 then
|
|
FRecordIndex := AddDataControllerRecord
|
|
else
|
|
FRecordIndex := -1;
|
|
end;
|
|
|
|
destructor TcxTreeListNode.Destroy;
|
|
var
|
|
NeedAdjustIndexes: Boolean;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
if not TreeList.SafeDelete and TreeList.DataController.IsEditing then
|
|
TreeList.DataController.Post;
|
|
TreeList.DoOnDeletion(Self);
|
|
if HasChildren and (Count > 0) then
|
|
DeleteChildren;
|
|
TreeList.DoCheckDeletedNode(Self);
|
|
TreeList.DoDeleteNode(Self);
|
|
Owner.IsInvalidState := True;
|
|
NeedAdjustIndexes := FState and tlnsDeleting = 0;
|
|
FState := FState or tlnsDeleting;
|
|
if Owner.NodesViewInfo.TopNode = Self then
|
|
begin
|
|
Owner.TopNode := nil;
|
|
Owner.NodesViewInfo.TopNode := nil;
|
|
end;
|
|
if NeedAdjustIndexes then
|
|
FState := FState xor tlnsDeleting;
|
|
InternalRemove(Self);
|
|
finally
|
|
TreeList.EndUpdate;
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.Assign(Source: TPersistent);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
I: Integer;
|
|
begin
|
|
if Source is TcxTreeListNode then
|
|
begin
|
|
ANode := TcxTreeListNode(Source);
|
|
FData := ANode.Data;
|
|
Focused := ANode.Focused;
|
|
HasChildren := ANode.HasChildren;
|
|
for I := 0 to ANode.ValueCount - 1 do
|
|
Values[I] := ANode.Values[I];
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.AssignValues(
|
|
const AValues:{$IFDEF DELPHI5} array of {$ENDIF} Variant);
|
|
var
|
|
I, K: Integer;
|
|
begin
|
|
K := 0;
|
|
{$IFNDEF DELPHI5}
|
|
if VarType(AValues) <> varArray then Exit;
|
|
for I := 0 to Length(AValues) do
|
|
{$ELSE}
|
|
for I := Low(AValues) to High(AValues) do
|
|
{$ENDIF}
|
|
begin
|
|
if K >= ValueCount then Break;
|
|
Values[I] := AValues[I];
|
|
Inc(K);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.AddChild: TcxTreeListNode;
|
|
begin
|
|
Result := TreeList.AddNode(nil, Self, nil, tlamAddChild);
|
|
end;
|
|
|
|
function TcxTreeListNode.AddChildFirst: TcxTreeListNode;
|
|
begin
|
|
Result := TreeList.AddNode(nil, Self, nil, tlamAddChildFirst);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.AlphaSort(ARecurse: Boolean = False);
|
|
begin
|
|
CustomSort(nil, ARecurse);
|
|
end;
|
|
|
|
function TcxTreeListNode.CanCollapse: Boolean;
|
|
begin
|
|
Result := TreeList.DoCanNodeCollapse(Self);
|
|
end;
|
|
|
|
function TcxTreeListNode.CanExpand: Boolean;
|
|
begin
|
|
Result := TreeList.DoCanNodeExpand(Self);
|
|
end;
|
|
|
|
function TcxTreeListNode.CanMove(
|
|
ADest: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode): Boolean;
|
|
begin
|
|
if (ADest = nil) or ((ADest = Self) and (AMode in [tlamAddChild, tlamAddChildFirst, tlamInsert])) or
|
|
ADest.HasAsParent(Self) then
|
|
Result := False
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.Collapse(Recurse: Boolean);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if not HasChildren then Exit;
|
|
TreeList.BeginUpdate;
|
|
try
|
|
Expanded := False;
|
|
if Recurse then
|
|
begin
|
|
ANode := FFirst;
|
|
while ANode <> nil do
|
|
begin
|
|
ANode.Collapse(True);
|
|
ANode := ANode.FNext;
|
|
end;
|
|
end;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.CustomSort(
|
|
ASortProc: TcxTreeListCompareFunc; ARecurse: Boolean = False);
|
|
begin
|
|
SortingManager.Sort(Self, ASortProc, ARecurse);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.Delete;
|
|
begin
|
|
if not Deleting then Free;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.DeleteChildren;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
while FFirst <> nil do
|
|
begin
|
|
FFirst.FState := FFirst.FState or tlnsDeleting;
|
|
ANode := FFirst;
|
|
FFirst := FFirst.FNext;
|
|
FreeAndNil(ANode);
|
|
end;
|
|
finally
|
|
FCount := 0;
|
|
HasChildren := False;
|
|
FFirst := nil;
|
|
FLast := nil;
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.DisplayRect(AEntryOnly: Boolean): TRect;
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
if Owner.NodesViewInfo.FindNodeViewInfo(Self, AViewInfo) then
|
|
begin
|
|
if AEntryOnly then
|
|
Result := AViewInfo.NodeCellsRect
|
|
else
|
|
Result := AViewInfo.NodeContentRect;
|
|
end
|
|
else
|
|
Result := cxNullRect;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.EndEdit(Cancel: Boolean);
|
|
begin
|
|
TreeList.Controller.EditingController.HideEdit(not Cancel);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.Expand(Recurse: Boolean);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if not HasChildren then Exit;
|
|
if not TreeList.IsSmartLoad then
|
|
TreeList.BeginUpdate;
|
|
try
|
|
Expanded := True;
|
|
if Recurse then
|
|
begin
|
|
ANode := FFirst;
|
|
while ANode <> nil do
|
|
begin
|
|
ANode.Expand(True);
|
|
ANode := ANode.FNext;
|
|
end;
|
|
end;
|
|
finally
|
|
if not TreeList.IsSmartLoad then
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNextChild(Value: TcxTreeListNode): TcxTreeListNode;
|
|
begin
|
|
if Value <> nil then
|
|
Result := TcxTreeListNode(Value.FNext)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetFirstChild: TcxTreeListNode;
|
|
begin
|
|
Result := FFirst
|
|
end;
|
|
|
|
function TcxTreeListNode.GetLastChild: TcxTreeListNode;
|
|
begin
|
|
Result := FLast
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNext: TcxTreeListNode;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
Result := FFirst;
|
|
if FCount = 0 then
|
|
begin
|
|
ANode := Self;
|
|
while ANode <> nil do
|
|
begin
|
|
if ANode.FNext <> nil then
|
|
begin
|
|
Result := ANode.FNext;
|
|
Break;
|
|
end;
|
|
while (ANode <> nil) and (ANode.FNext = nil) do ANode := ANode.Parent;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNextSibling: TcxTreeListNode;
|
|
begin
|
|
Result := FNext;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetPrev: TcxTreeListNode;
|
|
begin
|
|
Result := FPrev;
|
|
if Result <> nil then
|
|
Result := cxGetLatest(Result, False)
|
|
else
|
|
Result := Parent;
|
|
if Result = Owner.Root then Result := nil;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetPrevSibling: TcxTreeListNode;
|
|
begin
|
|
Result := FPrev;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetPrevChild(Value: TcxTreeListNode): TcxTreeListNode;
|
|
begin
|
|
if Value <> nil then
|
|
Result := TcxTreeListNode(Value.FPrev)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTreeListNode.HasAsParent(Value: TcxTreeListNode): Boolean;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
Result := False;
|
|
ANode := Parent;
|
|
while (ANode <> nil) and not Result do
|
|
begin
|
|
Result := ANode = Value;
|
|
ANode := ANode.FParent;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.IndexOf(Value: TcxTreeListNode): Integer;
|
|
begin
|
|
if Value.Parent = Self then
|
|
Result := Value.FIndex
|
|
else
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListNode.InsertChild(
|
|
ABeforeNode: TcxTreeListNode): TcxTreeListNode;
|
|
begin
|
|
Result := TreeList.AddNode(nil, ABeforeNode, nil, tlamInsert);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.MakeVisible;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if not TreeList.FNeedMakeVisible then Exit;
|
|
if not IsVisible then
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
ANode := FParent;
|
|
while ANode <> nil do
|
|
begin
|
|
ANode.Expanded := True;
|
|
if not ANode.Expanded then Break;
|
|
ANode := ANode.FParent;
|
|
end;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
if IsVisible then
|
|
TreeList.MakeNodeVisible(Self);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.MoveTo(
|
|
ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode);
|
|
begin
|
|
if (ADestNode = nil) or (ADestNode = Self) then Exit;
|
|
if AMode in [tlamAdd, tlamAddFirst] then
|
|
ADestNode := ADestNode.Parent;
|
|
if not ADestNode.HasAsParent(Self) then
|
|
TreeList.InternalMove(Self, ADestNode, AMode);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.Repaint(ARecalculate: Boolean);
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
with TreeList.ViewInfo do
|
|
begin
|
|
if NodesViewInfo.FindNodeViewInfo(Self, AViewInfo) then
|
|
begin
|
|
AViewInfo.Update(ARecalculate);
|
|
InvalidateRect(AViewInfo.NodeContentRect);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.AddDataControllerRecord: Integer;
|
|
begin
|
|
Result := DataController.AppendRecord;
|
|
FRecordIndex := Result;
|
|
TreeList.NodesList.Add(Self);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.DoReadNodeData(AReader: TcxReader);
|
|
begin
|
|
FState := AReader.ReadInteger;
|
|
FCount := AReader.ReadInteger;
|
|
FRecordIndex := AReader.ReadInteger;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.DoWriteNodeData(AWriter: TcxWriter);
|
|
begin
|
|
AWriter.WriteInteger(FState);
|
|
AWriter.WriteInteger(FCount);
|
|
AWriter.WriteInteger(FRecordIndex);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNextSiblingEx(
|
|
ANode: TcxTreeListNode; AForward: Boolean): TcxTreeListNode;
|
|
begin
|
|
if AForward then
|
|
Result := ANode.FNext
|
|
else
|
|
Result := ANode.FPrev;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsFirstVisible: Boolean;
|
|
begin
|
|
Result := IsVisible and (Owner.Root.FFirst = Self);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsLastVisible: Boolean;
|
|
begin
|
|
Result := IsVisible and (GetNextVisible = nil);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNextVisibleEx(IsPrev: Boolean): TcxTreeListNode;
|
|
begin
|
|
if IsPrev then
|
|
Result := GetPrevVisible
|
|
else
|
|
Result := GetNextVisible;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetOwner: TPersistent;
|
|
begin
|
|
Result := FOwner;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.ReadData(AStream: TStream);
|
|
begin
|
|
AStream.ReadBuffer(FRecordIndex, SizeOf(Integer));
|
|
AStream.ReadBuffer(FState, SizeOf(Integer));
|
|
FCount := 0;
|
|
if FState and tlnsHasChildren <> 0 then
|
|
AStream.ReadBuffer(FCount, SizeOf(Integer));
|
|
end;
|
|
|
|
procedure TcxTreeListNode.WriteData(AStream: TStream);
|
|
begin
|
|
AStream.WriteBuffer(FRecordIndex, SizeOf(Integer));
|
|
if FCount > 0 then FState := FState or tlnsHasChildren;
|
|
AStream.WriteBuffer(FState, SizeOf(Integer));
|
|
if (FCount > 0) or (FState and tlnsHasChildren <> 0) then
|
|
AStream.WriteBuffer(FCount, SizeOf(Integer));
|
|
end;
|
|
|
|
function TcxTreeListNode.CanSizing(
|
|
ADirection: TcxDragSizingDirection): Boolean;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
Result := OptionsCustomizing.RowSizing and (ADirection = dsdVert);
|
|
Result := Result and not OptionsView.CellAutoHeight
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetSizingBoundsRect(
|
|
ADirection: TcxDragSizingDirection): TRect;
|
|
begin
|
|
Result := TreeList.ClientBounds;
|
|
with DisplayRect(False) do
|
|
begin
|
|
Result.Top := Top + TreeList.ViewInfo.DefaultEditHeight;
|
|
Result.Bottom := Result.Top + cxRectHeight(TreeList.ClientBounds);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetSizingIncrement(
|
|
ADirection: TcxDragSizingDirection): Integer;
|
|
begin
|
|
Result := 1;
|
|
end;
|
|
|
|
function TcxTreeListNode.IsDynamicUpdate: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetSizeDelta(
|
|
ADirection: TcxDragSizingDirection; ADelta: Integer);
|
|
begin
|
|
with TreeList do
|
|
DefaultRowHeight := DefaultRowHeight + ADelta;
|
|
end;
|
|
|
|
function TcxTreeListNode.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
Result := 0
|
|
else
|
|
Result := cxE_NOINTERFACE;
|
|
end;
|
|
|
|
function TcxTreeListNode._AddRef: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListNode._Release: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetRootParent: TcxTreeListNode;
|
|
begin
|
|
Result := Self;
|
|
while (Result.FParent <> nil) and (Result.FParent <> Owner.Root) do
|
|
Result := Result.FParent;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetAbsoluteIndex: Integer;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if Self.Parent = nil then
|
|
Result := -1
|
|
else
|
|
begin
|
|
Result := 0;
|
|
ANode := Owner.Root.FFirst;
|
|
while ANode <> Self do
|
|
begin
|
|
Inc(Result);
|
|
if ANode.Count > 0 then
|
|
ANode := ANode.FFirst
|
|
else
|
|
begin
|
|
while ANode.FNext = nil do ANode := ANode.Parent;
|
|
ANode := ANode.FNext;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetDataController: TcxControlDataController;
|
|
begin
|
|
Result := Owner.DataController;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetExpanded: Boolean;
|
|
begin
|
|
Result := (Count > 0) and ((FState and tlnsCollapsed) = 0);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetFocused: Boolean;
|
|
begin
|
|
Result := DataController.FocusedRecordIndex = RecordIndex;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetHasChildren: Boolean;
|
|
begin
|
|
Result := (FState and tlnsHasChildren <> 0) or (FCount > 0)
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsDeleting: Boolean;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
Result := False;
|
|
ANode := Self;
|
|
while not Result and (ANode <> nil) do
|
|
begin
|
|
Result := ANode.FState and tlnsDeleting <> 0;
|
|
ANode := ANode.Parent;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetHotTrack: Boolean;
|
|
begin
|
|
Result := TreeList.Controller.HotTrackNode = Self;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsFirst: Boolean;
|
|
begin
|
|
Result := (FParent = nil) or (FParent.FFirst = Self);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsGroupNode: Boolean;
|
|
begin
|
|
Result := TreeList.DoIsGroupNode(Self);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsLast: Boolean;
|
|
begin
|
|
Result := (FParent = nil) or (FParent.FLast = Self);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetIsVisible: Boolean;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
Result := FParent <> nil;
|
|
ANode := Self;
|
|
while Result and (ANode.FParent <> nil) and (ANode.FParent <> FOwner.Root) do
|
|
begin
|
|
Result := ANode.FParent.FState and tlnsCollapsed = 0;
|
|
ANode := ANode.FParent;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetItem(AIndex: Integer): TcxTreeListNode;
|
|
begin
|
|
Result := Owner.FindBetween(FFirst, FLast, FCount, AIndex);
|
|
end;
|
|
|
|
function TcxTreeListNode.GetLevel: Integer;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
ANode := FParent;
|
|
Result := -1;
|
|
while ANode <> nil do
|
|
begin
|
|
Inc(Result);
|
|
ANode := ANode.FParent;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetSelected: Boolean;
|
|
begin
|
|
if TreeList.IsMultiSelect then
|
|
Result := TreeList.FSelection.IndexOf(Self) <> cxInvalidIndex
|
|
else
|
|
Result := Focused;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNextVisible: TcxTreeListNode;
|
|
begin
|
|
if (FCount > 0) and (FState and tlnsCollapsed = 0) then
|
|
Result := FFirst
|
|
else
|
|
begin
|
|
Result := Self;
|
|
while Result <> nil do
|
|
begin
|
|
if Result.FNext <> nil then
|
|
begin
|
|
Result := Result.FNext;
|
|
Break;
|
|
end;
|
|
Result := Result.FParent;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetNodeImageIndex(AIndex: Integer): TImageIndex;
|
|
begin
|
|
Result := TreeList.DoGetNodeImageIndex(Self, TcxTreeListImageIndexType(AIndex));
|
|
end;
|
|
|
|
function TcxTreeListNode.GetPrevVisible: TcxTreeListNode;
|
|
begin
|
|
Result := cxGetLatest(FPrev);
|
|
if (Result = nil) and (FParent <> FOwner.Root) then
|
|
Result := FParent;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetText(Index: Integer): string;
|
|
begin
|
|
Result := TreeList.Columns[Index].DisplayTexts[RecordIndex];
|
|
end;
|
|
|
|
function TcxTreeListNode.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Owner.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetValue(AIndex: Integer): Variant;
|
|
begin
|
|
Result := DataController.Values[FRecordIndex, AIndex]
|
|
end;
|
|
|
|
function TcxTreeListNode.GetValueCount: Integer;
|
|
begin
|
|
Result := TreeList.DoGetNodeValueCount;
|
|
end;
|
|
|
|
function TcxTreeListNode.GetVisibleIndex: Integer;
|
|
begin
|
|
if IsVisible then
|
|
Result := FVisibleIndex
|
|
else
|
|
Result := -1;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.AdjustIndexes(ANode: TcxTreeListNode; AIndex: Integer);
|
|
begin
|
|
while ANode <> nil do
|
|
begin
|
|
ANode.FIndex := AIndex;
|
|
ANode := ANode.FNext;
|
|
Inc(AIndex);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.InternalInsert(Value: TcxTreeListNode);
|
|
begin
|
|
if FParent <> nil then
|
|
InternalRemove(Self);
|
|
FPrev := Value.FPrev;
|
|
if FPrev <> nil then
|
|
FPrev.FNext := Self
|
|
else
|
|
Value.FParent.FFirst := Self;
|
|
FNext := Value;
|
|
if FNext <> nil then
|
|
FNext.FPrev := Self
|
|
else
|
|
Value.FParent.FLast := Self;
|
|
Value.FParent.SetParentFor(Self);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.InternalRemove(Value: TcxTreeListNode);
|
|
begin
|
|
if Deleting then Exit;
|
|
AdjustIndexes(Value.FNext, Value.Index);
|
|
if Value.FParent <> nil then
|
|
begin
|
|
Dec(Value.FParent.FCount);
|
|
if Value.FParent.FFirst = Value then
|
|
Value.FParent.FFirst := Value.FNext;
|
|
if Value.FParent.FLast = Value then
|
|
Value.FParent.FLast := Value.FPrev;
|
|
if Value.FParent.FCount = 0 then
|
|
Value.FParent.FState := (Value.FParent.FState and not tlnsHasChildren) or tlnsCollapsed ;
|
|
end;
|
|
if Value.FNext <> nil then
|
|
Value.FNext.FPrev := Value.FPrev;
|
|
if Value.FPrev <> nil then
|
|
Value.FPrev.FNext := Value.FNext;
|
|
Value.FPrev := nil;
|
|
Value.FNext := nil;
|
|
Value.FParent := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetExpanded(Value: Boolean);
|
|
begin
|
|
if Value <> Expanded then
|
|
begin
|
|
Owner.IsInvalidState := True;
|
|
TreeList.DoSetNodeExpanded(Self, Value);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetFirst(Value: TcxTreeListNode);
|
|
begin
|
|
InternalRemove(Value);
|
|
if FFirst <> nil then
|
|
begin
|
|
Value.FNext := FFirst;
|
|
FFirst.FPrev := Value;
|
|
end
|
|
else
|
|
FLast := Value;
|
|
FFirst := Value;
|
|
SetParentFor(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetFocused(Value: Boolean);
|
|
begin
|
|
if Value <> Focused then
|
|
begin
|
|
if Value then
|
|
TreeList.Controller.FocusedRecordIndex := RecordIndex
|
|
else
|
|
DataController.FocusedRecordIndex := -1;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetHasChildren(Value: Boolean);
|
|
begin
|
|
if HasChildren <> Value then
|
|
begin
|
|
if Value then
|
|
FState := FState or tlnsHasChildren
|
|
else
|
|
if FCount = 0 then
|
|
FState := FState and not tlnsHasChildren;
|
|
Owner.DoNodeChanged(Self);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetItem(AIndex: Integer; Value: TcxTreeListNode);
|
|
begin
|
|
GetItem(AIndex).Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetLast(Value: TcxTreeListNode);
|
|
begin
|
|
InternalRemove(Value);
|
|
if FLast <> nil then
|
|
begin
|
|
Value.FPrev := FLast;
|
|
FLast.FNext := Value;
|
|
end
|
|
else
|
|
FFirst := Value;
|
|
FLast := Value;
|
|
SetParentFor(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetNodeImageIndex(AIndex: Integer; Value: TImageIndex);
|
|
begin
|
|
TreeList.DoSetNodeImageIndex(Self, TcxTreeListImageIndexType(AIndex), Value);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetParentFor(Value: TcxTreeListNode);
|
|
begin
|
|
Value.FParent := Self;
|
|
Inc(FCount);
|
|
if Value.FPrev = nil then
|
|
AdjustIndexes(Value, 0)
|
|
else
|
|
AdjustIndexes(Value.FPrev, Value.FPrev.Index);
|
|
Owner.DoNodeChanged(nil);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetText(AIndex: Integer; const AValue: string);
|
|
begin
|
|
SetValue(AIndex, AValue);
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetSelected(Value: Boolean);
|
|
begin
|
|
if (Selected <> Value) and TreeList.IsMultiSelect then
|
|
try
|
|
if not Value then
|
|
TreeList.FSelection.Remove(Self)
|
|
else
|
|
begin
|
|
if not TreeList.DoCanSelectNode(Self) then
|
|
Exit
|
|
else
|
|
TreeList.FSelection.Add(Self);
|
|
end;
|
|
TreeList.DoSelectionChanged;
|
|
finally
|
|
Repaint(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNode.SetValue(AIndex: Integer; const AValue: Variant);
|
|
begin
|
|
with DataController do
|
|
begin
|
|
if (dceEdit in EditState) and (FocusedRecordIndex = RecordIndex) then
|
|
SetEditValue(AIndex, AValue, evsValue)
|
|
else
|
|
Values[RecordIndex, AIndex] := AValue;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListRootNode }
|
|
|
|
function TcxTreeListRootNode.AddDataControllerRecord: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
{ TcxUnboundTreeListNode }
|
|
|
|
constructor TcxUnboundTreeListNode.Create(AOwner: TcxTreeListNodes);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FImageIndexes := cxDefaultImageIndexes;
|
|
end;
|
|
|
|
procedure TcxUnboundTreeListNode.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxUnboundTreeListNode then
|
|
FImageIndexes := TcxUnboundTreeListNode(Source).FImageIndexes;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxUnboundTreeListNode.ReadData(AStream: TStream);
|
|
begin
|
|
inherited ReadData(AStream);
|
|
AStream.ReadBuffer(FImageIndexes, SizeOf(FImageIndexes))
|
|
end;
|
|
|
|
procedure TcxUnboundTreeListNode.WriteData(AStream: TStream);
|
|
begin
|
|
inherited WriteData(AStream);
|
|
AStream.WriteBuffer(FImageIndexes, SizeOf(FImageIndexes))
|
|
end;
|
|
|
|
{ TcxTreeListColumnStyles }
|
|
|
|
procedure TcxTreeListColumnStyles.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListColumnStyles then
|
|
begin
|
|
Header := TcxTreeListColumnStyles(Source).Header;
|
|
Footer := TcxTreeListColumnStyles(Source).Footer;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnStyles.CachedContentStyleChanged;
|
|
var
|
|
B: Boolean;
|
|
begin
|
|
if Band <> nil then
|
|
ContentParams := Band.Styles.ContentParams
|
|
else
|
|
ContentParams := TreeList.Styles.ContentParams;
|
|
for B := False to True do
|
|
cxParamsCombine(Content, [], ContentParams[B]);
|
|
end;
|
|
|
|
function TcxTreeListColumnStyles.GetBand: TcxTreeListBand;
|
|
begin
|
|
Result := TcxTreeListColumn(GetOwner).OwnerBand;
|
|
end;
|
|
|
|
function TcxTreeListColumnStyles.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(Control);
|
|
end;
|
|
|
|
{ TcxTreeListColumnPosition }
|
|
|
|
constructor TcxTreeListColumnPosition.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FColIndex := 0;
|
|
FLineCount := 1;
|
|
FRowIndex := 0;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListColumnPosition then
|
|
begin
|
|
FLineCount := TcxTreeListColumnPosition(Source).FLineCount;
|
|
with TcxTreeListColumnPosition(Source) do
|
|
Self.SetPositionEx(BandIndex, FColIndex, FRowIndex);
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.SetPosition(
|
|
AColIndex, ARowIndex: Integer; IsInsertRow: Boolean = False);
|
|
begin
|
|
SetPositionEx(BandIndex, AColIndex, ARowIndex);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.SetPositionEx(
|
|
ABandIndex, AColIndex, ARowIndex: Integer; IsInsertRow: Boolean = False);
|
|
|
|
procedure CheckColumnPos(AColumn: TcxTreeListColumn);
|
|
begin
|
|
with AColumn.Position do
|
|
begin
|
|
if IsInsertRow and (FRowIndex >= ARowIndex) then Inc(FRowIndex);
|
|
if (FRowIndex = ARowIndex) and (FColIndex >= AColIndex) then
|
|
Inc(FColIndex);
|
|
end;
|
|
end;
|
|
|
|
procedure SetOwnerBand(ABand: TcxTreeListBand);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Column.OwnerBand := ABand;
|
|
if ABand <> nil then
|
|
begin
|
|
for I := 0 to ABand.VisibleColumnCount - 1 do
|
|
CheckColumnPos(ABand.VisibleColumns[I]);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
SetOwnerBand(GetBandFromIndex(ABandIndex));
|
|
FColIndex := AColIndex;
|
|
FRowIndex := ARowIndex;
|
|
cxValidateIntDef(FColIndex, 0);
|
|
cxValidateIntDef(FRowIndex, 0);
|
|
finally
|
|
TreeList.CancelUpdate;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.Changed;
|
|
begin
|
|
if TreeList.OptionsView.HeaderSingleLine then
|
|
cxValidateSingleLine(Self);
|
|
TreeList.LayoutChanged;
|
|
end;
|
|
|
|
function TcxTreeListColumnPosition.GetBandFromIndex(
|
|
AIndex: Integer): TcxTreeListBand;
|
|
begin
|
|
Result := nil;
|
|
with TreeList.Bands do
|
|
begin
|
|
if not cxValidateIntDefEx(AIndex, BandIndex, -1, Count - 1) then
|
|
Result := Column.OwnerBand
|
|
else
|
|
if AIndex <> cxInvalidIndex then
|
|
Result := Column.TreeList.Bands[AIndex];
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.Save;
|
|
begin
|
|
FBandIndex := BandIndex;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.Load;
|
|
begin
|
|
BandIndex := FBandIndex;
|
|
end;
|
|
|
|
function TcxTreeListColumnPosition.GetBandIndex: Integer;
|
|
begin
|
|
if Column.OwnerBand <> nil then
|
|
Result := Column.OwnerBand.Index
|
|
else
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListColumnPosition.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(GetOwner);
|
|
end;
|
|
|
|
function TcxTreeListColumnPosition.GetOwnerBandVisibleIndex: Integer;
|
|
begin
|
|
Result := BandIndex;
|
|
if BandIndex <> cxInvalidIndex then
|
|
Result := Column.OwnerBand.VisibleIndex;
|
|
end;
|
|
|
|
function TcxTreeListColumnPosition.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Column.TreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.SetBandIndex(Index: Integer);
|
|
begin
|
|
if BandIndex <> Index then
|
|
Column.OwnerBand := GetBandFromIndex(Index);
|
|
if [csReading, csUpdating] * Column.ComponentState <> [] then
|
|
FBandIndex := Index;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.SetColIndex(Value: Integer);
|
|
begin
|
|
if TreeList.IsRestore then
|
|
FColIndex := Value
|
|
else
|
|
if cxValidateIntDefEx(Value, FColIndex, 0) then
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
if Value > FColIndex then Inc(Value);
|
|
SetPositionEx(BandIndex, Value, RowIndex, False);
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.SetLineCount(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FLineCount, 1) then
|
|
begin
|
|
FLineCount := Value;
|
|
Column.PositionChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnPosition.SetRowIndex(Value: Integer);
|
|
begin
|
|
if TreeList.IsRestore then
|
|
FRowIndex := Value
|
|
else
|
|
if cxValidateIntDefEx(Value, FRowIndex, 0) then
|
|
begin
|
|
FRowIndex := Value;
|
|
Column.PositionChanged;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListCaption }
|
|
|
|
constructor TcxTreeListCaption.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FGlyph := TBitmap.Create;
|
|
end;
|
|
|
|
constructor TcxTreeListCaption.CreateEx(ATreeList: TcxCustomTreeListControl;
|
|
AOwner: TPersistent; AViewInfo: TcxTreeListViewInfoItem);
|
|
begin
|
|
Create(AOwner);
|
|
FTreeList := ATreeList;
|
|
FViewInfo := AViewInfo;
|
|
ShowEndEllipsis := True;
|
|
end;
|
|
|
|
destructor TcxTreeListCaption.Destroy;
|
|
begin
|
|
FreeAndNil(FGlyph);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListCaption then
|
|
begin
|
|
FState := TcxTreeListCaption(Source).FState;
|
|
FAlignHorz := TcxTreeListCaption(Source).FAlignHorz;
|
|
FAlignVert := TcxTreeListCaption(Source).FAlignVert;
|
|
FText := TcxTreeListCaption(Source).Text;
|
|
FGlyphAlignHorz := TcxTreeListCaption(Source).FGlyphAlignHorz;
|
|
FGlyphAlignVert := TcxTreeListCaption(Source).FGlyphAlignVert;
|
|
Glyph := TcxTreeListCaption(Source).Glyph;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.Changed;
|
|
begin
|
|
if (FViewInfo = nil) or (TreeList = nil) or TreeList.IsLocked then Exit;
|
|
FViewInfo.DoCalculate;
|
|
FViewInfo.Invalidate;
|
|
end;
|
|
|
|
function TcxTreeListCaption.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
function TcxTreeListCaption.GetText: string;
|
|
begin
|
|
Result := FText;
|
|
if (Result = '') and (GetOwner is TcxTreeListColumn) then
|
|
Result := TcxItemDataBindingAccess(
|
|
TcxTreeListColumn(GetOwner).DataBinding).GetDefaultCaption;
|
|
end;
|
|
|
|
function TcxTreeListCaption.IsTextStored: Boolean;
|
|
begin
|
|
Result := FText <> '';
|
|
if Result and (GetOwner is TcxTreeListColumn) then
|
|
begin
|
|
Result := FText <> TcxItemDataBindingAccess(
|
|
TcxTreeListColumn(GetOwner).DataBinding).GetDefaultCaption;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
if cxSetState(FState, Index, Value) then
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetAlignHorz(Value: TAlignment);
|
|
begin
|
|
if Value <> FAlignHorz then
|
|
begin
|
|
FAlignHorz := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetAlignVert(Value: TcxAlignmentVert);
|
|
begin
|
|
if Value <> FAlignVert then
|
|
begin
|
|
FAlignVert := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetGlyph(Value: TBitmap);
|
|
begin
|
|
FGlyph.Assign(Value);
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetGlyphAlignHorz(Value: TAlignment);
|
|
begin
|
|
if FGlyphAlignHorz <> Value then
|
|
begin
|
|
FGlyphAlignHorz := Value;
|
|
if not FGlyph.Empty then Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetGlyphAlignVert(Value: TcxAlignmentVert);
|
|
begin
|
|
if FGlyphAlignVert <> Value then
|
|
begin
|
|
FGlyphAlignVert := Value;
|
|
if not FGlyph.Empty then Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCaption.SetText(const Value: string);
|
|
begin
|
|
if FText <> Value then
|
|
begin
|
|
FText := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListColumnOptions }
|
|
|
|
constructor TcxTreeListColumnOptions.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Sizing := True;
|
|
CellEndEllipsis := True;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnOptions.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListColumnOptions then
|
|
FState := TcxTreeListColumnOptions(Source).FState;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnOptions.RestoreDefaults;
|
|
begin
|
|
Sorting := True;
|
|
Sizing := True;
|
|
Customizing := True;
|
|
Editing := True;
|
|
TabStop := True;
|
|
Focusing := True;
|
|
Moving := True;
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnOptions.Changed;
|
|
begin
|
|
with TcxTreeListColumn(GetOwner) do
|
|
if TreeList <> nil then TreeList.UpdateViewStyles;
|
|
end;
|
|
|
|
function TcxTreeListColumnOptions.GetValue(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnOptions.SetValue(Index: Integer; const Value: Boolean);
|
|
begin
|
|
if cxSetState(FState, Index, Value) then Changed;
|
|
end;
|
|
|
|
{ TcxTreeListColumnSummaryFooter }
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.Assign(Source: TPersistent);
|
|
var
|
|
AProp: TcxTreeListColumnSummaryFooter;
|
|
begin
|
|
if Source is TcxTreeListColumnSummaryFooter then
|
|
begin
|
|
AProp := TcxTreeListColumnSummaryFooter(Source);
|
|
Kind := AProp.Kind;
|
|
Format := AProp.Format;
|
|
AlignHorz := AProp.AlignHorz;
|
|
AlignVert := AProp.AlignVert;
|
|
MultiLine := AProp.MultiLine;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.IsFormatStored: Boolean;
|
|
begin
|
|
Result := Format <> '';
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.IsSummaryItemValid: Boolean;
|
|
begin
|
|
ItemIndex := SummaryItemIndex;
|
|
Result := ItemIndex <> -1;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.Summary: TcxDataSummary;
|
|
begin
|
|
Result := DataController.Summary;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SummaryItemChanged;
|
|
begin
|
|
with Column.TreeList do
|
|
begin
|
|
if IsLocked then Exit;
|
|
Column.ViewInfo.FColumnFooter.DoCalculate;
|
|
if OptionsView.Footer then
|
|
ViewInfo.InvalidateRect(ViewInfo.FooterRect);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.SummaryItemIndex: Integer;
|
|
begin
|
|
Result := SummaryItems.IndexOfItemLink(Column);
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.SummaryItems: TcxDataFooterSummaryItems;
|
|
begin
|
|
Result := Summary.FooterSummaryItems;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(GetOwner);
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetDataController: TcxCustomDataController;
|
|
begin
|
|
Result := Column.DataController;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetFormat: string;
|
|
begin
|
|
if IsSummaryItemValid then
|
|
FFormat := SummaryItem.Format;
|
|
Result := FFormat;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetSummaryItem: TcxDataSummaryItem;
|
|
begin
|
|
if IsSummaryItemValid then
|
|
Result := SummaryItems[ItemIndex]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetSummaryKind: TcxSummaryKind;
|
|
begin
|
|
if SummaryItem <> nil then
|
|
Result := SummaryItem.Kind
|
|
else
|
|
Result := skNone;
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetSummaryText: string;
|
|
begin
|
|
if IsSummaryItemValid then
|
|
Result := Summary.FooterSummaryTexts[ItemIndex]
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
function TcxTreeListColumnSummaryFooter.GetSummaryValue: Variant;
|
|
begin
|
|
if IsSummaryItemValid then
|
|
Result := Summary.FooterSummaryValues[ItemIndex]
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetAlignHorz(Value: TAlignment);
|
|
begin
|
|
if FAlignHorz <> Value then
|
|
begin
|
|
FAlignHorz := Value;
|
|
SummaryItemChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetAlignVert(Value: TcxAlignmentVert);
|
|
begin
|
|
if FAlignVert <> Value then
|
|
begin
|
|
FAlignVert := Value;
|
|
SummaryItemChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetFormat(const Value: string);
|
|
begin
|
|
FFormat := Value;
|
|
if IsSummaryItemValid then
|
|
SummaryItem.Format := Value;
|
|
SummaryItemChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetMultiLine(Value: Boolean);
|
|
begin
|
|
if Value <> FMultiLine then
|
|
begin
|
|
FMultiLine := Value;
|
|
SummaryItemChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetSummaryText(const Value: string);
|
|
begin
|
|
SummaryValue := Value;
|
|
if IsSummaryItemValid then
|
|
Summary.FooterSummaryValues[ItemIndex] := Value;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetSummaryValue(const Value: Variant);
|
|
begin
|
|
if IsSummaryItemValid then
|
|
Summary.FooterSummaryValues[ItemIndex] := Value;
|
|
SummaryItemChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnSummaryFooter.SetSummaryKind(Value: TcxSummaryKind);
|
|
begin
|
|
{ if Kind <> Value then
|
|
begin
|
|
if Value = skNone then
|
|
SummaryItem.Free
|
|
else }
|
|
begin
|
|
if not IsSummaryItemValid then
|
|
SummaryItems.Add.ItemLink := Column;
|
|
with SummaryItem do
|
|
begin
|
|
Kind := Value;
|
|
Format := FFormat;
|
|
end;
|
|
SummaryItemChanged;
|
|
end;
|
|
// end;
|
|
end;
|
|
|
|
{ TcxTreeListColumn }
|
|
|
|
constructor TcxTreeListColumn.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FViewInfo := GetViewInfoClass.Create(Self);
|
|
FSummaryFooter := GetSummaryFooterClass.Create(Self);
|
|
FCaption := TcxTreeListCaption.CreateEx(nil, Self, FViewInfo.FColumnHeader);
|
|
FPosition := GetPositionClass.Create(Self);
|
|
FMinWidth := cxTreeListDefMinWidth;
|
|
SetState(tlcsVisible, True);
|
|
end;
|
|
|
|
destructor TcxTreeListColumn.Destroy;
|
|
begin
|
|
SortOrder := soNone;
|
|
if Visible then
|
|
TreeList.ViewInfo.NodesViewInfo.Clear;
|
|
if (TreeList <> nil) and not TreeList.IsDestroying then
|
|
begin
|
|
if TreeList <> nil then
|
|
TreeList.ColumnsList.Remove(Self);
|
|
if Controller.FocusedItem = Self then
|
|
Controller.FocusedItem := nil;
|
|
UpdateIndexesBeforeRemove;
|
|
OwnerBand := nil;
|
|
TreeList.DoUpdateDesignerForms;
|
|
if TreeList.Preview.Column = Self then
|
|
TreeList.Preview.Column := nil;
|
|
if TreeList.OptionsView.CategorizedColumn = Self then
|
|
TreeList.OptionsView.CategorizedColumn := nil;
|
|
end;
|
|
FreeAndNil(FCaption);
|
|
FreeAndNil(FViewInfo);
|
|
FreeAndNil(FPosition);
|
|
FreeAndNil(FSummaryFooter);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.Assign(Source: TPersistent);
|
|
var
|
|
AColumn: TcxTreeListColumn;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
inherited Assign(Source);
|
|
if Source is TcxTreeListColumn then
|
|
begin
|
|
AColumn := TcxTreeListColumn(Source);
|
|
FCalculatedWidth := AColumn.FCalculatedWidth;
|
|
FMinWidth := AColumn.FMinWidth;
|
|
FWidth := AColumn.FWidth;
|
|
Position := TcxTreeListColumn(Source).Position;
|
|
Caption := AColumn.Caption;
|
|
SortOrder := AColumn.FSortOrder;
|
|
Visible := AColumn.Visible;
|
|
end;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.ApplyBestFit;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
AIndentSize, AWidth: Integer;
|
|
AHeight, AOffset, ACount: Integer;
|
|
AIsLeftMost: Boolean;
|
|
AInfo: TcxTemporaryCellViewInfo;
|
|
begin
|
|
if (TreeList = nil) or not CanSizing(dsdHorz) then Exit;
|
|
if TreeList.FLevelIndentWidth = 0 then
|
|
TreeList.DoLayoutChanged;
|
|
if IsLeftMost then
|
|
TreeList.FContentIndentWidth := 0;
|
|
TreeList.HandleNeeded;
|
|
AHeight := TreeList.ViewInfo.DefaultHeight;
|
|
ANode := TreeList.GetStartNodeForBestFit;
|
|
ACount := TreeList.GetCountNodeForBestFit;
|
|
AInfo := TcxTemporaryCellViewInfo(TreeList.ViewInfo.SizingViewInfo);
|
|
AIsLeftMost := IsLeftMost;
|
|
AIndentSize := TreeList.FLevelIndentWidth;
|
|
try
|
|
TreeList.HideEdit;
|
|
while (ACount <> 0) and (ANode <> nil) do
|
|
begin
|
|
if AIsLeftMost then
|
|
AOffset := (ANode.Level + Byte(TreeList.OptionsView.ShowRoot)) * AIndentSize
|
|
else
|
|
AOffset := 0;
|
|
AWidth := AInfo.CalculateWidth(Self, ANode, True, AHeight);
|
|
if (AWidth + AOffset) > Data then
|
|
FData := AWidth + AOffset;
|
|
ANode := ANode.GetNextVisible;
|
|
Dec(ACount);
|
|
end;
|
|
AWidth := GetHeaderFooterBestfitSize;
|
|
if AWidth > Data then Data := AWidth;
|
|
SetSizeDelta(dsdHorz, Data - DisplayWidth);
|
|
finally
|
|
Data := 0;
|
|
TreeList.LayoutChanged;
|
|
TreeList.Controller.CheckEdit;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetDisplayText(Index: Integer): string;
|
|
begin
|
|
Result := VarToStr(DoOnGetDisplayText(TreeList.Controller.GetNode(Index), True));
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetParentComponent: TComponent;
|
|
begin
|
|
Result := EditingControl;
|
|
end;
|
|
|
|
function TcxTreeListColumn.HasParent: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.MakeVisible;
|
|
var
|
|
AShift: Integer;
|
|
R: TRect;
|
|
begin
|
|
if Visibility and (OwnerBand.FixedKind = tlbfNone) then
|
|
begin
|
|
AShift := 0;
|
|
R := TreeList.ViewInfo.ScrollingArea;
|
|
if TreeList.OptionsView.Indicator and (TreeList.FixedBandCount = 0) then
|
|
Inc(R.Left, TreeList.OptionsView.IndicatorWidth);
|
|
with ViewInfo do
|
|
begin
|
|
if IsLeftMost then
|
|
begin
|
|
if (DisplayWidth > cxRectWidth(R)) and (XOfs <= R.Left) and
|
|
((XOfs + DisplayWidth) > R.Left) then
|
|
Exit
|
|
else
|
|
AShift := 0;
|
|
end
|
|
else
|
|
if (XOfs + DisplayWidth) >= R.Right then
|
|
AShift := (XOfs + DisplayWidth) - R.Right
|
|
else
|
|
if XOfs <= R.Left then
|
|
AShift := XOfs - R.Left - OptionsView.HorzIncrement;
|
|
if (XOfs >= R.Left) and ((XOfs + DisplayWidth) <= R.Right) and not IsLeftMost then Exit;
|
|
end;
|
|
if AShift <> 0 then
|
|
begin
|
|
Inc(AShift, TreeList.ViewInfo.HorzScrollPos);
|
|
TreeList.Scroll(sbHorizontal, scPosition, AShift);
|
|
end
|
|
else
|
|
if IsLeftMost then
|
|
TreeList.Scroll(sbHorizontal, scPosition, AShift);
|
|
end;
|
|
TreeList.LayoutChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.RestoreDefaults;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
Options.RestoreDefaults;
|
|
SortOrder := soNone;
|
|
Caption.FAlignVert := vaTop;
|
|
Caption.FAlignHorz := taLeftJustify;
|
|
RestoreWidths;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.RestoreWidths;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
FMinWidth := cxTreeListDefMinWidth;
|
|
SetWidth(cxTreeListDefWidth);
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.DoSizeChanged;
|
|
begin
|
|
if Visibility or TreeList.IsLocked then
|
|
TreeList.LayoutChanged;
|
|
if not TreeList.IsLocked then
|
|
TreeList.DoColumnSizeChanged(Self);
|
|
end;
|
|
|
|
function TcxTreeListColumn.CanInitEditing: Boolean;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
Result := inherited CanInitEditing and ((DragAndDropState = ddsNone) or
|
|
((DragMode <> dmAutomatic) or not HitTest.HitAtNode));
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.CanMoving: Boolean;
|
|
begin
|
|
Result := TreeList.OptionsCustomizing.ColumnMoving and
|
|
Options.Moving{ and (TreeList.VisibleColumnCount > 1)};
|
|
end;
|
|
|
|
function TcxTreeListColumn.CanSorted: Boolean;
|
|
begin
|
|
Result := not Assigned(OnGetEditProperties) and
|
|
(esoSorting in PropertiesValue.GetSupportedOperations);
|
|
if not Result then
|
|
Result := Assigned(TreeList.FOnCompare);
|
|
end;
|
|
|
|
function TcxTreeListColumn.CanFocus: Boolean;
|
|
begin
|
|
Result := inherited CanFocus and TreeList.OptionsSelection.CellSelect;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetRealSortOrder: TcxDataSortOrder;
|
|
begin
|
|
Result := soNone;
|
|
if CanSorted then
|
|
Result := FSortOrder;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetHeaderFooterBestfitSize: Integer;
|
|
|
|
function CalcSize(AViewParams: TcxViewParams; const AText: string): Integer;
|
|
begin
|
|
Result := cxTextWidth(AViewParams.Font, AText) + cxTextOffset shl 2;
|
|
end;
|
|
|
|
var
|
|
ASize: Integer;
|
|
begin
|
|
Result := FMinWidth;
|
|
with TreeList.Styles do
|
|
begin
|
|
if TreeList.OptionsView.Headers then
|
|
begin
|
|
with Caption do
|
|
begin
|
|
ASize := CalcSize(GetColumnHeaderParams(Self), Text);
|
|
if not Glyph.Empty and (Byte(GlyphAlignHorz) < 2) then
|
|
Inc(ASize, Glyph.Width);
|
|
if ASize > Result then Result := ASize;
|
|
if SortOrder <> soNone then
|
|
Inc(Result, TreeList.LookAndFeelPainter.SortingMarkAreaSize.X);
|
|
end;
|
|
end;
|
|
if TreeList.OptionsView.Footer and Options.Footer then
|
|
begin
|
|
ASize := CalcSize(GetColumnFooterParams(Self), SummaryFooter.SummaryText);
|
|
with TreeList.LookAndFeelPainter do
|
|
Inc(ASize, (FooterCellBorderSize + FooterCellOffset) shl 1);
|
|
if ASize > Result then Result := ASize;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetOptionsClass: TcxCustomEditContainerItemOptionsClass;
|
|
begin
|
|
Result := TcxTreeListColumnOptions;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetStylesClass: TcxEditContainerStylesClass;
|
|
begin
|
|
Result := TcxTreeListColumnStyles;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetSummaryFooterClass: TcxTreeListColumnSummaryFooterClass;
|
|
begin
|
|
Result := TcxTreeListColumnSummaryFooter;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetEditingControl(Value: TcxEditingControl);
|
|
begin
|
|
if TreeList <> nil then
|
|
TreeList.ColumnsList.Remove(Self);
|
|
if not (csDestroying in ComponentState) and (Value <> nil) then
|
|
FCaption.FTreeList := TcxCustomTreeListControl(Value);
|
|
inherited SetEditingControl(Value);
|
|
if TreeList <> nil then TreeList.DoUpdateDesignerForms;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetName(const Value: TComponentName);
|
|
begin
|
|
inherited SetName(Value);
|
|
if Assigned(FOnChangeName) then FOnChangeName(Self);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetParentComponent(Value: TComponent);
|
|
begin
|
|
if Value is TcxEditingControl then
|
|
EditingControl := Value as TcxEditingControl
|
|
else
|
|
EditingControl := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
cxSetState(FState, Index, Value)
|
|
end;
|
|
|
|
function TcxTreeListColumn.HasDataTextHandler: Boolean;
|
|
begin
|
|
Result := Assigned(FOnGetDisplayText);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.InitAutoWidthItem(AItem: TcxAutoWidthItem);
|
|
begin
|
|
AItem.Width := Width;
|
|
AItem.MinWidth := FMinWidth;
|
|
AItem.Fixed := not Options.Sizing or IsFixed;
|
|
AItem.AutoWidth := -1;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.InternalSetBandOwner(
|
|
ABand: TcxTreeListBand; RemoveFromOwner: Boolean);
|
|
begin
|
|
try
|
|
if ABand = OwnerBand then Exit;
|
|
if IsBandAssigned and RemoveFromOwner then
|
|
FOwnerBand.RemoveColumn(Self);
|
|
if ABand <> nil then
|
|
ABand.AddColumn(Self);
|
|
finally
|
|
FOwnerBand := ABand;
|
|
DoVisibilityChanged;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.IsBandAssigned: Boolean;
|
|
begin
|
|
Result := FOwnerBand <> nil;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.PositionChanged;
|
|
begin
|
|
if IsBandAssigned then
|
|
OwnerBand.Changed(True);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.UpdateIndexesBeforeRemove;
|
|
var
|
|
I: Integer;
|
|
APos: TcxtreeListColumnPosition;
|
|
begin
|
|
if OwnerBand = nil then Exit;
|
|
for I := 0 to OwnerBand.ColumnCount - 1 do
|
|
begin
|
|
APos := OwnerBand.Columns[I].Position;
|
|
if (APos.RowIndex = Position.RowIndex) and (APos.FColIndex > Position.ColIndex) then
|
|
Dec(APos.FColIndex);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.CanSizing(ADirection: TcxDragSizingDirection): Boolean;
|
|
begin
|
|
if ADirection = dsdVert then
|
|
Result := TreeList.OptionsCustomizing.ColumnVertSizing and
|
|
not TreeList.OptionsView.HeaderSingleLine
|
|
else
|
|
Result := Options.Sizing and TreeList.OptionsCustomizing.ColumnHorzSizing;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetAvailableMaxWidth: Integer;
|
|
var
|
|
AFromIndex, AToIndex: Integer;
|
|
begin
|
|
Result := FMinWidth;
|
|
if not Visibility then Exit;
|
|
Result := MaxInt shr 2;
|
|
if OwnerBand.Width <> 0 then
|
|
begin
|
|
Result := OwnerBand.DisplayWidth - OwnerBand.IndentWidth;
|
|
cxGetIndexes(OwnerBandRow.FItems, Self, AFromIndex, AToIndex);
|
|
with OwnerBandRow do
|
|
while AFromIndex <= AToIndex do
|
|
begin
|
|
Dec(Result, Items[AFromIndex].GetRealMinSize);
|
|
Inc(AFromIndex);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetRealMinSize: Integer;
|
|
begin
|
|
if Options.Sizing then
|
|
Result := FMinWidth
|
|
else
|
|
Result := FWidth;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetSizingBoundsRect(
|
|
ADirection: TcxDragSizingDirection): TRect;
|
|
begin
|
|
with TreeList.ViewInfo, ViewInfo.FColumnHeader do
|
|
begin
|
|
if ADirection <> dsdVert then
|
|
Result := cxRectSetLeft(ClientRect, DisplayRect.Left + GetRealMinSize, GetAvailableMaxWidth)
|
|
else
|
|
Result := cxRectSetTop(ClientRect, DisplayRect.Top + HeaderLineHeight);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetSizingIncrement(
|
|
ADirection: TcxDragSizingDirection): Integer;
|
|
begin
|
|
if ADirection = dsdHorz then
|
|
Result := 1
|
|
else
|
|
Result := TreeList.ViewInfo.HeaderLineHeight;
|
|
end;
|
|
|
|
function TcxTreeListColumn.IsDynamicUpdate: Boolean;
|
|
var
|
|
ADir: TcxDragSizingDirection;
|
|
begin
|
|
Result := TreeList.OptionsCustomizing.DynamicSizing and
|
|
TreeList.HitTest.CanSizing(ADir) and (ADir = dsdHorz);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetSizeDelta(
|
|
ADirection: TcxDragSizingDirection; ADelta: Integer);
|
|
begin
|
|
if ADelta = 0 then Exit;
|
|
TreeList.Controller.ForceWidthItem := Self;
|
|
if ADirection = dsdHorz then
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
TreeList.AssignColumnWidths;
|
|
Width := DisplayWidth + ADelta;
|
|
// calculate new realwidth for band
|
|
OwnerBand.BandRows.Refresh;
|
|
OwnerBand.FCalculatedWidth := OwnerBand.BandRows.ColumnsMaxWidth;
|
|
// refresh columns in band
|
|
OwnerBand.RealignColumns;
|
|
// refresh bands (may be depends on column widths)
|
|
TreeList.RealignBands;
|
|
// refresh columns in band, band width can changed after refresh bands
|
|
OwnerBand.RealignColumns;
|
|
// apply new widths
|
|
TreeList.AssignColumnWidths;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
Position.FLineCount := Position.LineCount + ADelta;
|
|
TreeList.Controller.ForceWidthItem := nil;
|
|
TreeList.LayoutChanged;
|
|
TreeList.Modified;
|
|
DoSizeChanged;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetItemIndex: Integer;
|
|
begin
|
|
Result := inherited ItemIndex;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetVisibleIndex: Integer;
|
|
begin
|
|
Result := TreeList.FColumnsVisibleList.IndexOf(Self)
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetItemIndex(Value: Integer);
|
|
|
|
function IsIndexValid(AIndex: Integer): Boolean;
|
|
begin
|
|
Result := (AIndex >= 0) and (AIndex < TreeList.ContainerList.Count)
|
|
end;
|
|
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
if IsIndexValid(ItemIndex) and IsIndexValid(Value) then
|
|
ContainerList.Exchange(ItemIndex, Value);
|
|
Position.ColIndex := Value;
|
|
DataController.UpdateItemIndexes;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetVisibleIndex(Value: Integer);
|
|
begin
|
|
// todo: do nothing
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetObjectName: string;
|
|
begin
|
|
Result := Name;
|
|
if Result = '' then
|
|
Result := ClassName + IntToStr(ItemIndex);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetProperties(AProperties: TStrings): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to High(ColumnPropertiesName) do
|
|
AProperties.Add(ColumnPropertiesName[I]);
|
|
Result := True;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetPropertyIndex(const AName: string): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := -1;
|
|
for I := 0 to High(ColumnPropertiesName) do
|
|
begin
|
|
if AnsiCompareText(ColumnPropertiesName[I], AName) = 0 then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.GetPropertyValue(
|
|
const AName: string; var AValue: Variant);
|
|
begin
|
|
case GetPropertyIndex(AName) of
|
|
0: AValue := Visible;
|
|
1: AValue := ItemIndex;
|
|
2: AValue := Position.FLineCount;
|
|
3: AValue := Position.FColIndex;
|
|
4: AValue := Position.FRowIndex;
|
|
5: AValue := Position.BandIndex;
|
|
6: AValue := Caption.Text;
|
|
7: AValue := SortOrder;
|
|
9: AValue := FMinWidth;
|
|
10: AValue := FIsWidthAssigned;
|
|
11: AValue := FWidth;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetPropertyValue(
|
|
const AName: string; const AValue: Variant);
|
|
begin
|
|
case GetPropertyIndex(AName) of
|
|
0: Visible := AValue;
|
|
1: ItemIndex := AValue;
|
|
2: Position.FLineCount := AValue;
|
|
3: Position.FColIndex := AValue;
|
|
4: Position.FRowIndex := AValue;
|
|
5: Position.BandIndex := AValue;
|
|
6:
|
|
if Caption.Text = '' then
|
|
Caption.Text := AValue;
|
|
7: FSortOrder := AValue;
|
|
9: FMinWidth := AValue;
|
|
10: FIsWidthAssigned := AValue;
|
|
11: FWidth := AValue;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.DoGetDisplayText(
|
|
ARecordIndex: Integer; var AText: string);
|
|
begin
|
|
if (ARecordIndex >= 0) and (ARecordIndex < TreeList.FNodesList.Count) and
|
|
(ARecordIndex < DataController.RecordCount) then
|
|
begin
|
|
AText := DoGetNodeDisplayText(
|
|
TcxTreeListNode(TreeList.FNodesList[ARecordIndex]), AText);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.DoGetNodeDisplayText(
|
|
ANode: TcxTreeListNode; const AValue: Variant): Variant;
|
|
var
|
|
AText: string;
|
|
begin
|
|
Result := AValue;
|
|
if Assigned(OnGetDisplayText) then
|
|
begin
|
|
AText := VarToStr(Result);
|
|
OnGetDisplayText(Self, ANode, AText);
|
|
Result := AText;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.DoOnGetDisplayText(
|
|
ANode: TcxTreeListNode; AsText: Boolean = False; AValueOnly: Boolean = False): Variant;
|
|
var
|
|
AProperties: TcxCustomEditProperties;
|
|
AText: string;
|
|
begin
|
|
AProperties := DoGetEditProperties(ANode);
|
|
Result := GetDisplayValue(AProperties, ANode.RecordIndex);
|
|
if AValueOnly then Exit;
|
|
if Assigned(OnGetDisplayText) or AsText then
|
|
begin
|
|
if AProperties.GetEditValueSource(False) = evsValue then
|
|
begin
|
|
if AsText then
|
|
AText := AProperties.GetDisplayText(Values[ANode.RecordIndex], True)
|
|
else
|
|
AText := '';
|
|
AText := DoGetNodeDisplayText(ANode, AText);
|
|
if (AText = '') and not AsText then
|
|
Result := Values[ANode.RecordIndex]
|
|
else
|
|
Result := AText;
|
|
end
|
|
else
|
|
Result := DoGetNodeDisplayText(ANode, Result);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.DoVisibilityChanged;
|
|
begin
|
|
if (FOwnerBand <> nil) and (TreeList <> nil) and not TreeList.IsDestroying then
|
|
begin
|
|
FOwnerBand.Changed(True);
|
|
TreeList.DoUpdateDesignerForms;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetCellHeight(ANode: TcxTreeListNode;
|
|
AWidth, ALines: Integer; AFont: TFont; const AValue: Variant): Integer;
|
|
var
|
|
ASizeProp: TcxEditSizeProperties;
|
|
AEditProp: TcxCustomEditProperties;
|
|
AViewData: TcxCustomEditViewData;
|
|
begin
|
|
ASizeProp := cxDefaultEditSizeProp;
|
|
AEditProp := DoGetEditProperties(ANode);
|
|
AViewData := nil;
|
|
try
|
|
if AEditProp = PropertiesValue then
|
|
AViewData := EditViewData
|
|
else
|
|
AViewData := AEditProp.CreateViewData(TreeList.EditStyle, True);
|
|
AViewData.Style.Font := AFont;
|
|
ASizeProp.Width := AWidth;
|
|
ASizeProp.MaxLineCount := ALines;
|
|
Result := AViewData.GetEditSize(GetControlCanvas, AValue, ASizeProp).cy;
|
|
finally
|
|
if AViewData <> EditViewData then FreeAndNil(AViewData);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetPositionClass: TcxTreeListColumnPositionClass;
|
|
begin
|
|
Result := TcxTreeListColumnPosition;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetViewInfoClass: TcxTreeListColumnViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListColumnViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetEditingProperties: TcxTreeListGetEditPropertiesEvent;
|
|
begin
|
|
Result := TcxTreeListGetEditPropertiesEvent(inherited OnGetEditingProperties);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetEditProperties: TcxTreeListGetEditPropertiesEvent;
|
|
begin
|
|
Result := TcxTreeListGetEditPropertiesEvent(inherited OnGetEditProperties);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIndentWidth: Integer;
|
|
begin
|
|
Result := TreeList.GetIndentWidth(IsLeftMost);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetDataBinding: TcxItemDataBinding;
|
|
begin
|
|
Result := TcxItemDataBinding(inherited DataBinding);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetDisplayWidth: Integer;
|
|
begin
|
|
if Visibility then
|
|
Result := RealWidth + IndentWidth
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsFixed: Boolean;
|
|
var
|
|
AForceWidthItem: TcxTreeListColumn;
|
|
begin
|
|
if (TreeList.Controller.ForceWidthItem is TcxTreeListColumn) then
|
|
begin
|
|
AForceWidthItem := TreeList.Controller.ForceWidthItem as TcxTreeListColumn;
|
|
Result := (AForceWidthItem.OwnerBand = OwnerBand) and ((AForceWidthItem = Self) or
|
|
(not AForceWidthItem.IsRight and (VisibleIndex < AForceWidthItem.VisibleIndex)));
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsHidden: Boolean;
|
|
begin
|
|
Result := not Visibility or IsPreview;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsLeft: Boolean;
|
|
begin
|
|
Result := Visibility and (OwnerBandRow <> nil) and (OwnerBandRow.First = Self);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsLeftMost: Boolean;
|
|
begin
|
|
Result := IsLeft and (OwnerBand.VisibleIndex = 0);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsRightMost: Boolean;
|
|
begin
|
|
Result := IsRight and (OwnerBand.VisibleIndex = TreeList.VisibleBandCount - 1);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsPreview: Boolean;
|
|
begin
|
|
Result := (TreeList <> nil) and (TreeList.Preview.Column = Self);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsRight: Boolean;
|
|
begin
|
|
Result := Visibility and (OwnerBandRow.Last = Self);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetIsWidthStored: Boolean;
|
|
begin
|
|
Result := FIsWidthAssigned;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetStyles: TcxTreeListColumnStyles;
|
|
begin
|
|
Result := TcxTreeListColumnStyles(inherited Styles);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetOptions: TcxTreeListColumnOptions;
|
|
begin
|
|
Result := TcxTreeListColumnOptions(inherited Options);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetOwnerBandRow: TcxTreeListBandRow;
|
|
begin
|
|
if (OwnerBand <> nil) and (OwnerBand.BandRows.Count > 0) then
|
|
Result := OwnerBand.BandRows[Position.RowIndex]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetRealMinWidth: Integer;
|
|
begin
|
|
Result := FMinWidth;
|
|
if IsFixed then
|
|
Result := RealWidth;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetRealWidth: Integer;
|
|
begin
|
|
Result := FCalculatedWidth;
|
|
if Result = 0 then
|
|
Result := Width;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(EditingControl);
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetVisible: Boolean;
|
|
begin
|
|
if TreeList.CanColumnVisible(Self) then
|
|
Result := GetState(tlcsVisible)
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetVisibility: Boolean;
|
|
begin
|
|
Result := Visible and (IsBandAssigned and OwnerBand.Visible)
|
|
end;
|
|
|
|
function TcxTreeListColumn.GetWidth: Integer;
|
|
begin
|
|
if FIsWidthAssigned then
|
|
Result := FWidth
|
|
else
|
|
Result := Max(MinWidth, cxTreeListDefWidth);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetCaption(Value: TcxTreeListCaption);
|
|
begin
|
|
FCaption.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetDataBinding(Value: TcxItemDataBinding);
|
|
begin
|
|
DataBinding.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetEditingProperties(
|
|
Value: TcxTreeListGetEditPropertiesEvent);
|
|
begin
|
|
inherited OnGetEditingProperties := TcxGetEditPropertiesEvent(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetEditProperties(
|
|
Value: TcxTreeListGetEditPropertiesEvent);
|
|
begin
|
|
inherited OnGetEditProperties := TcxGetEditPropertiesEvent(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetIsPreview(Value: Boolean);
|
|
begin
|
|
if Value <> IsPreview then
|
|
begin
|
|
if Value then
|
|
TreeList.Preview.Column := Self
|
|
else
|
|
TreeList.Preview.Column := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetMinWidth(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FMinWidth, 0) then
|
|
begin
|
|
FMinWidth := Value;
|
|
if FMinWidth > Width then
|
|
SetWidth(FMinWidth);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetOptions(Value: TcxTreeListColumnOptions);
|
|
begin
|
|
Options.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetOwnerBand(Value: TcxTreeListBand);
|
|
begin
|
|
InternalSetBandOwner(Value, Value <> OwnerBand)
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetPosition(Value: TcxTreeListColumnPosition);
|
|
begin
|
|
FPosition.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetSorted(Value: TcxDataSortOrder);
|
|
begin
|
|
if not Options.Sorting then
|
|
Value := soNone;
|
|
if Value <> FSortOrder then
|
|
begin
|
|
FSortOrder := Value;
|
|
with TreeList do
|
|
begin
|
|
FNeedRestoreSorting := FNeedRestoreSorting or (Value = soNone);
|
|
ColumnSortOrderChanged(Self);
|
|
end;
|
|
if CanSorted and (TreeList <> nil) and not IsDestroying then
|
|
begin
|
|
TreeList.DoSortNodes;
|
|
if not TreeList.IsLocked then
|
|
ViewInfo.ColumnHeader.Invalidate(True);
|
|
end;
|
|
TreeList.Modified;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetStyles(Value: TcxTreeListColumnStyles);
|
|
begin
|
|
Styles.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetSummaryFooter(
|
|
Value: TcxTreeListColumnSummaryFooter);
|
|
begin
|
|
FSummaryFooter.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetVisible(Value: Boolean);
|
|
begin
|
|
if Value <> GetState(tlcsVisible) then
|
|
begin
|
|
SetState(tlcsVisible, Value);
|
|
if FOwnerBand <> nil then
|
|
begin
|
|
{ if not Value then
|
|
OwnerBand.FColumns.Remove(Self)
|
|
else}
|
|
if OwnerBand.FColumns.IndexOf(Self) < 0 then
|
|
OwnerBand.FColumns.Add(Self);
|
|
end;
|
|
if IsBandAssigned and OwnerBand.Visible then DoVisibilityChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumn.SetWidth(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FWidth, FMinWidth) then
|
|
begin
|
|
FWidth := Value;
|
|
FIsWidthAssigned := True;
|
|
DoSizeChanged;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListDragAndDropObject }
|
|
|
|
destructor TcxTreeListDragAndDropObject.Destroy;
|
|
begin
|
|
FreeAndNil(ScreenArrows);
|
|
FreeAndNil(DragDropInfo);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.BeginDragAndDrop;
|
|
begin
|
|
inherited BeginDragAndDrop;
|
|
with TreeList.ViewInfo do
|
|
begin
|
|
if ScrollingAreaVisible then
|
|
with ScrollingArea do
|
|
begin
|
|
AddAutoScrollingObject(Rect(Left, Top, Left + cxtlScrollDelta, Bottom),
|
|
sbHorizontal, scLineUp);
|
|
AddAutoScrollingObject(Rect(Right - cxtlScrollDelta, Top, Right, Bottom),
|
|
sbHorizontal, scLineDown);
|
|
end;
|
|
if IsDragColumn then
|
|
begin
|
|
if not DragColumn.Visibility then StorePosition;
|
|
if TreeList.Customizing.Visible then
|
|
TreeList.Customizing.MakeColumnSheetVisible;
|
|
end
|
|
else
|
|
if IsDragBand and TreeList.Customizing.Visible then
|
|
TreeList.Customizing.MakeBandSheetVisible;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetDisplayRect: TRect;
|
|
begin
|
|
Result := TcxTreeListHeaderViewInfo(DragItem).GetDisplayRect;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetDragAndDropCursor(
|
|
Accepted: Boolean): TCursor;
|
|
begin
|
|
Result := inherited GetDragAndDropCursor(Accepted);
|
|
if not Accepted and TreeList.Customizing.Visible then
|
|
begin
|
|
if not IsDragBand or not TreeList.OptionsView.SimpleCustomizeBox and
|
|
(TreeList.VisibleColumnCount > 1) then
|
|
Result := crcxRemove;
|
|
if IsDragColumn and not DragColumn.Options.Customizing then
|
|
Result := crArrow;
|
|
end
|
|
else
|
|
if Accepted and TreeList.Customizing.Visible and
|
|
IsDragColumn and not DragColumn.Options.Customizing then
|
|
begin
|
|
if CheckCustomizingBox(DragDropInfo.DropPos) then
|
|
Result := inherited GetDragAndDropCursor(False)
|
|
else
|
|
Result := crArrow;
|
|
end;
|
|
if Result = crDefault then Result := crArrow;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.ChangeArrowPos(const ABaseLine: TRect;
|
|
AllowHide: Boolean);
|
|
begin
|
|
if AllowHide then
|
|
begin
|
|
if ScreenArrows <> nil then
|
|
ScreenArrows.Hide;
|
|
end
|
|
else
|
|
begin
|
|
ArrowBaseLine := ABaseLine;
|
|
DoDrawArrows;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.CheckCustomizingBox(
|
|
const APos: TPoint): Boolean;
|
|
begin
|
|
with TreeList do
|
|
Result := Customizing.PtInCustomizingBox(ClientToScreen(APos));
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.CheckDropPos(ADragIndex, ADropIndex,
|
|
DragX, DropX: Integer; var APos: Integer; var ASide: TcxBorder;
|
|
ACheckIndex: Boolean = True): Boolean;
|
|
begin
|
|
if ADragIndex = -1 then Dec(ADragIndex);
|
|
APos := ADropIndex;
|
|
ASide := bRight;
|
|
if ACheckIndex then
|
|
Result := (ADragIndex <> ADropIndex) and
|
|
(ADragIndex <> (ADropIndex + cxIntOffs[DragX > DropX]))
|
|
else
|
|
Result := True;
|
|
if not Result then
|
|
APos := ADragIndex
|
|
else
|
|
if DragX <= DropX then
|
|
ASide := bLeft
|
|
else
|
|
Inc(APos);
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.DoDrawHeaderItem(
|
|
AItem: TcxTreeListHeaderViewInfo);
|
|
var
|
|
AState: TcxButtonState;
|
|
begin
|
|
AState := AItem.FState;
|
|
AItem.FState := cxbsDefault;
|
|
try
|
|
if AItem is TcxTreeListColumnHeaderViewInfo and
|
|
not TcxTreeListColumnHeaderViewInfo(AItem).Column.Visibility then
|
|
begin
|
|
Canvas.Brush.Color := clBtnShadow;
|
|
Canvas.FillRect(TcxTreeListColumnHeaderViewInfo(AItem).GetDisplayRect);
|
|
end
|
|
else
|
|
begin
|
|
Canvas.Brush.Color := AItem.BandViewInfo.FContainerViewParams.Color;
|
|
Canvas.FillRect(AItem.BandViewInfo.DisplayRect);
|
|
end;
|
|
Painter.DrawHeaderItem(AItem, True);
|
|
finally
|
|
AItem.FState := AState;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.DoDrawArrows;
|
|
var
|
|
APosChanged: Boolean;
|
|
begin
|
|
if ScreenArrows = nil then
|
|
ScreenArrows := TcxPlaceArrows.CreateArrows(TreeList.OptionsView.DropArrowColor, clBtnText);
|
|
if ArrowBaseLine.Left = ArrowBaseLine.Right then
|
|
APosChanged := ScreenArrows.MoveTo(ArrowBaseLine, bLeft)
|
|
else
|
|
APosChanged := ScreenArrows.MoveTo(ArrowBaseLine, bTop);
|
|
if APosChanged and DragImage.Visible then
|
|
begin
|
|
SetWindowPos(ScreenArrows.Handle, DragImage.Handle, 0, 0, 0, 0,
|
|
SWP_NOMOVE + SWP_NOSIZE + SWP_NOACTIVATE);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.DragAndDrop(
|
|
const P: TPoint; var Accepted: Boolean);
|
|
var
|
|
ALine: TRect;
|
|
begin
|
|
TreeList.Controller.IsDragDropProcess := True;
|
|
InitDropInfo(P);
|
|
Accepted := DragDropInfo.Accepted;
|
|
ALine := ArrowBaseLine;
|
|
inherited DragAndDrop(P, Accepted);
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.DropHeaderItem;
|
|
begin
|
|
with TcxTreeListHeaderDragDropInfo(DragDropInfo) do
|
|
begin
|
|
if not Accepted then Exit;
|
|
if IsDragColumn and ((DragColumn.OwnerBand = DropBand) or
|
|
(not DropBand.IsOnlyOwnColumns and ((DragColumn.OwnerBand = nil) or
|
|
not DragColumn.OwnerBand.IsOnlyOwnColumns))) then
|
|
with TcxTreeListColumnHeaderViewInfo(DragItem).Column do
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
Position.SetPositionEx(DropBand.Index, ColIndex, RowIndex, IsInsertRow);
|
|
Visible := True;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
if IsDragBand then
|
|
begin
|
|
with TcxTreeListHeaderViewInfo(DragItem).BandViewInfo.Band do
|
|
begin
|
|
if Index < (ColIndex - 1) then
|
|
Dec(ColIndex);
|
|
cxRange(ColIndex, 0, TreeList.Bands.Count - 1);
|
|
if TreeList.FixedBandCount < TreeList.VisibleBandCount then
|
|
Index := ColIndex;
|
|
Visible := True;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.DropNodes;
|
|
begin
|
|
// todo: do nothing;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.EndDragAndDrop(Accepted: Boolean);
|
|
var
|
|
ACanDrop: Boolean;
|
|
begin
|
|
ACanDrop := True;
|
|
if DragDropInfo <> nil then
|
|
DragDropInfo.Accepted := DragDropInfo.Accepted and not TreeList.Controller.DragCancel;
|
|
if (DragDropInfo <> nil) and not DragDropInfo.Accepted
|
|
and IsDragColumn and not DragColumn.Visibility then RestorePosition;
|
|
if not TreeList.Controller.DragCancel and (DragDropInfo <> nil) and
|
|
(DragDropInfo.Accepted or TreeList.Customizing.Visible) then
|
|
begin
|
|
if not CheckCustomizingBox(DragDropInfo.DropPos) and DragDropInfo.Accepted then
|
|
begin
|
|
DropHeaderItem;
|
|
ACanDrop := True;
|
|
end
|
|
else
|
|
begin
|
|
ACanDrop := False;
|
|
if IsDragColumn then
|
|
begin
|
|
if DragColumn.Options.Customizing and (TreeList.VisibleColumnCount > 1) then
|
|
DragColumn.Visible := False;
|
|
end
|
|
else
|
|
if not TreeList.OptionsView.SimpleCustomizeBox then
|
|
DragBand.Visible := False;
|
|
end;
|
|
end
|
|
else
|
|
TcxTreeListHeaderViewInfo(DragItem).Pressed := False;
|
|
inherited EndDragAndDrop(ACanDrop);
|
|
RestoreArrows;
|
|
TreeList.UpdateViewStyles;
|
|
TreeList.Modified;
|
|
TreeList.Customizing.Modified;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetAcceptedRect: TRect;
|
|
begin
|
|
Result := TcxTreeListHeaderViewInfo(DragItem).GetDroppingRect;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetArrowBaseLine(
|
|
const ARect: TRect; ASide: TcxBorder): TRect;
|
|
begin
|
|
with cxRectOffset(ARect, OrgOffset) do
|
|
begin
|
|
case ASide of
|
|
bLeft:
|
|
Result := cxRect(Left, Top, Left, Bottom - 1);
|
|
bTop:
|
|
Result := cxRect(Left, Top, Right - 1, Top);
|
|
bRight:
|
|
Result := cxRect(Right - 1, Top, Right - 1, Bottom - 1);
|
|
bBottom:
|
|
Result := cxRect(Left, Bottom - 1, Right - 1, Bottom - 1);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.GetArrowRects(out R1, R2: TRect);
|
|
begin
|
|
with ArrowBaseLine do
|
|
begin
|
|
if Top = Bottom then
|
|
begin
|
|
R1 := Rect(Left - 10, Top - 10, Left, Top + 10);
|
|
R2 := Rect(Right, Top - 10, Right + 10, Top + 10);
|
|
end
|
|
else
|
|
begin
|
|
R1 := Rect(Left - 10, Top - 10, Left + 10, Top);
|
|
R2 := Rect(Left - 10, Bottom, Left + 10, Bottom + 10);
|
|
end
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetDragDropInfoClass: TcxTreeListDragDropInfoClass;
|
|
begin
|
|
Result := TcxTreeListHeaderDragDropInfo
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.InitDropHeaderInfo;
|
|
begin
|
|
HitTest.ReCalculate(DragDropInfo.DropPos);
|
|
if IsDragBand then
|
|
InitDropBandInfo
|
|
else
|
|
InitDropColumnInfo;
|
|
with DragDropInfo do
|
|
Accepted := Accepted or CheckCustomizingBox(DropPos);
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.InitDropInfo(const P: TPoint);
|
|
begin
|
|
if DragDropInfo = nil then
|
|
DragDropInfo := GetDragDropInfoClass.Create;
|
|
DragDropInfo.DropPos := P;
|
|
InitDropHeaderInfo;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.IsDragBand: Boolean;
|
|
begin
|
|
Result := (DragItem is TcxTreeListHeaderViewInfo) and
|
|
not (DragItem is TcxTreeListColumnHeaderViewInfo)
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.IsDragColumn: Boolean;
|
|
begin
|
|
Result := DragItem is TcxTreeListColumnHeaderViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.IsValidForDrop(AIndex, ADropIndex: Integer;
|
|
PosIsGreater: Boolean): Boolean;
|
|
begin
|
|
Result := (AIndex <> ADropIndex) and
|
|
(AIndex <> (ADropIndex + cxIntOffs[PosIsGreater]))
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.Paint;
|
|
begin
|
|
DoDrawHeaderItem(TcxTreeListHeaderViewInfo(DragItem));
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.RestoreArrows;
|
|
begin
|
|
if ScreenArrows <> nil then
|
|
ScreenArrows.Hide;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.RestorePosition;
|
|
begin
|
|
if IsDragColumn then
|
|
DragColumn.Position.FColIndex := PrevColIndex;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.StorePosition;
|
|
begin
|
|
if IsDragColumn then
|
|
begin
|
|
PrevColIndex := DragColumn.Position.FColIndex;
|
|
DragColumn.Position.FColIndex := -2;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.CanDropHeaderObject: Boolean;
|
|
begin
|
|
with HitTest do
|
|
Result := HitAtBandHeader or HitAtBandContainer or HitAtColumnHeader
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetDragBand: TcxTreeListBand;
|
|
begin
|
|
Result := TcxTreeListHeaderViewInfo(DragItem).Band;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetDragColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumnHeaderViewInfo(DragItem).Column;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetDragItem: TObject;
|
|
begin
|
|
Result := TreeList.Controller.DragItem;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetHitTest: TcxTreeListHitTest;
|
|
begin
|
|
Result := TreeList.HitTest;
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetPainter: TcxTreeListControlPainter;
|
|
begin
|
|
Result := TcxTreeListControlPainter(TreeList.Painter);
|
|
end;
|
|
|
|
function TcxTreeListDragAndDropObject.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(Control);
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.InitDropBandInfo;
|
|
var
|
|
R: TRect;
|
|
ASide: TcxBorder;
|
|
begin
|
|
with TcxTreeListHeaderDragDropInfo(DragDropInfo) do
|
|
begin
|
|
Accepted := CanDropHeaderObject;
|
|
R := cxInvalidRect;
|
|
if Accepted then
|
|
begin
|
|
DropBand := HitTest.HitBand;
|
|
with DropBand, DropBand.ViewInfo.FBandHeader do
|
|
begin
|
|
if (DropPos.X < 30) and (VisibleIndex = 0) then
|
|
ASide := ASide;
|
|
if Accepted and (DropBand.FixedKind <> tlbfNone) then
|
|
begin
|
|
if DropBand.FixedKind = tlbfRight then
|
|
DropPos.X := DisplayRect.Left
|
|
else
|
|
DropPos.X := DisplayRect.Right
|
|
end;
|
|
if CheckDropPos(DragBand.VisibleIndex, VisibleIndex, DropPos.X,
|
|
cxRectCenter(DisplayRect).X, ColIndex, ASide) then
|
|
R := GetArrowBaseLine(ClipRect, ASide);
|
|
if ASide = bLeft then OffsetRect(R, -1, 0);
|
|
end;
|
|
end
|
|
else
|
|
ColIndex := DragBand.VisibleIndex;
|
|
ChangeArrowPos(R, not Accepted or (ColIndex = DragBand.VisibleIndex));
|
|
if not Accepted then
|
|
begin
|
|
with TreeList do
|
|
Accepted := PtInRect(ClientBounds, DropPos) and (VisibleBandCount = 0);
|
|
if Accepted then
|
|
begin
|
|
DropBand := TreeList.Bands[0];
|
|
ColIndex := 0;
|
|
with TreeList do
|
|
ChangeArrowPos(GetArrowBaseLine(CxRectSetHeight(ClientBounds,
|
|
RealBandLineHeight), bLeft), not Accepted or (ColIndex = DragBand.VisibleIndex));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListDragAndDropObject.InitDropColumnInfo;
|
|
var
|
|
AInfo: TcxTreeListHeaderDragDropInfo;
|
|
ACanDrop: Boolean;
|
|
R: TRect;
|
|
ADisplayRect, AClipRect: TRect;
|
|
|
|
procedure AssignPosition(AColumn: TcxTreeListColumn);
|
|
begin
|
|
AInfo.RowIndex := AColumn.Position.RowIndex;
|
|
AInfo.ColIndex := AColumn.Position.ColIndex;
|
|
end;
|
|
|
|
procedure GetRects(AViewInfo: TcxTreeListViewInfoItem; var DisplayRect, ClipRect: TRect);
|
|
begin
|
|
DisplayRect := AViewInfo.DisplayRect;
|
|
ClipRect := AViewInfo.ClipRect;
|
|
end;
|
|
|
|
function CheckDropAtColumn: Boolean;
|
|
var
|
|
ASide: TcxBorder;
|
|
AIndex: Integer;
|
|
begin
|
|
with HitTest, AInfo do
|
|
begin
|
|
Result := HitAtColumnHeader and ((DragColumn.OwnerBand = DropBand) or
|
|
(not DropBand.IsOnlyOwnColumns and ((DragColumn.OwnerBand = nil) or
|
|
not DragColumn.OwnerBand.IsOnlyOwnColumns)));
|
|
if not Result then Exit;
|
|
AssignPosition(HitColumn);
|
|
GetRects(HitColumn.ViewInfo.FColumnHeader, ADisplayRect, AClipRect);
|
|
AIndex := -2;
|
|
if (DragColumn.OwnerBand = DropBand) and
|
|
(DragColumn.Position.RowIndex = RowIndex) then
|
|
AIndex := DragColumn.Position.ColIndex;
|
|
Result := CheckDropPos(AIndex, ColIndex, DropPos.X,
|
|
cxRectCenter(ADisplayRect).X, ColIndex, ASide);
|
|
if Result then
|
|
R := GetArrowBaseLine(AClipRect, ASide);
|
|
end;
|
|
end;
|
|
|
|
function GetRelativePos(Y: Integer): Integer;
|
|
begin
|
|
Result := Y;
|
|
if TreeList.OptionsView.Bands then
|
|
Dec(Result, AInfo.DropBand.ViewInfo.FBandHeader.DisplayRect.Bottom);
|
|
end;
|
|
|
|
function CheckDropAtContainer: Boolean;
|
|
var
|
|
I, ARowHeight: Integer;
|
|
begin
|
|
with HitTest, AInfo do
|
|
begin
|
|
Result := HitAtBandContainer or ((TreeList.VisibleColumnCount = 0) and HitAtBand);
|
|
Result := Result and ((DragColumn.OwnerBand = DropBand) or (not DropBand.IsOnlyOwnColumns and
|
|
((DragColumn.OwnerBand = nil) or not DragColumn.OwnerBand.IsOnlyOwnColumns)));
|
|
if not Result then Exit;
|
|
IsInsertRow := DropBand.VisibleColumnCount <> 0;
|
|
if IsInsertRow and TreeList.OptionsView.HeaderSingleLine or (DropViewInfo = DragItem) then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
AClipRect := DropBand.FBandViewInfo.ClipRect;
|
|
if DropBand.FBandViewInfo.OptionsView.Bands then
|
|
AClipRect.Top := DropBand.FBandViewInfo.FBandHeader.DisplayRect.Bottom;
|
|
if IsInsertRow then
|
|
begin
|
|
for I := 0 to DropBand.BandRows.Count - 1 do
|
|
begin
|
|
ARowHeight := DropBand.BandRows[I].LineCount * TreeList.ViewInfo.HeaderLineHeight;
|
|
Inc(AClipRect.Top, ARowHeight);
|
|
RowIndex := DropBand.BandRows[I].Index + 1;
|
|
if cxInRange(GetRelativePos(DropPos.Y), AClipRect.Top - ARowHeight, AClipRect.Top) then
|
|
Break;
|
|
end;
|
|
R := GetArrowBaseLine(AClipRect, bTop);
|
|
end
|
|
else
|
|
begin
|
|
cxRectSetHeightEx(AClipRect, DragColumn.ViewInfo.FColumnHeader.DisplayRect);
|
|
R := GetArrowBaseLine(AClipRect, bLeft);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function CheckEmptyContent(): Boolean;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
Result := (VisibleColumnCount = 0) and (VisibleBandCount > 0) and
|
|
PtInRect(ClientBounds, AInfo.DropPos);
|
|
if not Result then Exit;
|
|
R := cxRectSetHeight(GetArrowBaseLine(ClientBounds, bLeft), ViewInfo.HeaderLineHeight);
|
|
AInfo.Accepted := Result;
|
|
AInfo.DropBand := TreeList.VisibleBands[0];
|
|
if OptionsView.Bands then
|
|
begin
|
|
with TreeList.VisibleBands[0].ViewInfo do
|
|
R := cxRectSetTop(R, ClientToScreen(FBandHeader.DisplayRect.BottomRight).Y);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
AInfo := TcxTreeListHeaderDragDropInfo(DragDropInfo);
|
|
with AInfo, HitTest do
|
|
begin
|
|
DropBand := HitBand;
|
|
Accepted := HitAtBandContainer or HitAtColumnHeader or CheckEmptyContent;
|
|
IsInsertRow := False;
|
|
AssignPosition(DragColumn);
|
|
ACanDrop := True;
|
|
ChangeArrowPos(R, not (Accepted and (CheckEmptyContent or
|
|
CheckDropAtColumn or CheckDropAtContainer) and ACanDrop));
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListCellNavigator }
|
|
|
|
function TcxTreeListCellNavigator.GetCount(ARecordIndex: Integer): Integer;
|
|
begin
|
|
if IsGroupRow(ARecordIndex) then
|
|
Result := 1
|
|
else
|
|
Result := TreeList.VisibleColumnCount;
|
|
end;
|
|
|
|
procedure TcxTreeListCellNavigator.CalcNextRow(AForward: Boolean;
|
|
var ARowIndex, ACellIndex: Integer);
|
|
var
|
|
AColumn: TcxTreeListColumn;
|
|
ANewRow: Integer;
|
|
ACellFound: Boolean;
|
|
begin
|
|
ACellFound := False;
|
|
if cxInRange(ACellIndex, 0, Count[ARowIndex] - 1) and not IsGroupRow(ARowIndex) then
|
|
begin
|
|
AColumn := TreeList.VisibleColumns[ACellIndex];
|
|
ACellFound := GoToNextCellInBand(AForward, AColumn, ACellIndex);
|
|
if ACellFound then
|
|
ACellIndex := AColumn.OwnerBand.VisibleColumns[ACellIndex].VisibleIndex;
|
|
end
|
|
else
|
|
AColumn := nil;
|
|
if not ACellFound then
|
|
begin
|
|
ANewRow := ARowIndex + cxIntOffs[AForward];
|
|
if cxInRange(ANewRow, 0, TreeList.Nodes.VisibleCount - 1) then
|
|
begin
|
|
ARowIndex := ANewRow;
|
|
GoToNextNodeCell(AForward, TreeList.Nodes.GetVisibleNode(ARowIndex), AColumn, ACellIndex);
|
|
end
|
|
else
|
|
if AForward then AppendRecord(ARowIndex, ACellIndex);
|
|
end
|
|
end;
|
|
|
|
procedure TcxTreeListCellNavigator.AppendRecord(
|
|
var ARowIndex, ACellIndex: Integer);
|
|
begin
|
|
if [dceEdit, dceChanging] * DataController.EditState <> [] then
|
|
DataController.Post;
|
|
if dceInsert in DataController.EditState then
|
|
begin
|
|
if [dceChanging, dceModified] * DataController.EditState <> [] then
|
|
TreeList.DataController.Post
|
|
else
|
|
Exit;
|
|
end;
|
|
if TcxTreeListController(Controller).CanInsertNode then
|
|
begin
|
|
if TreeList.InsertNode(True) and TreeList.UseRowIndexForNewRecord then
|
|
ARowIndex := TreeList.Nodes.VisibleCount + 1;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.GetCellContainer(
|
|
ARowIndex, ACellIndex: Integer): TcxCustomInplaceEditContainer;
|
|
var
|
|
AMax: Integer;
|
|
begin
|
|
if IsGroupRow(ARowIndex) then
|
|
AMax := 0
|
|
else
|
|
AMax := TreeList.VisibleColumnCount - 1;
|
|
if not cxInRange(ACellIndex, 0, AMax) then
|
|
Result := nil
|
|
else
|
|
Result := TreeList.VisibleColumns[ACellIndex];
|
|
end;
|
|
|
|
procedure TcxTreeListCellNavigator.Init(
|
|
var ARowIndex, ACellIndex, ARowCount: Integer);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
ARowCount := TreeList.Nodes.VisibleCount;
|
|
ANode := TcxTreeListController(Controller).FocusedNode;
|
|
if ANode <> nil then
|
|
ARowIndex := ANode.FVisibleIndex
|
|
else
|
|
ARowIndex := 0;
|
|
if TreeList.FocusedColumn <> nil then
|
|
ACellIndex := TreeList.FocusedColumn.VisibleIndex
|
|
else
|
|
ACellIndex := 0;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.IsGroupRow(ARowIndex: Integer): Boolean;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
ANode := TreeList.Nodes.GetVisibleNode(ARowIndex);
|
|
Result := (ANode <> nil) and ANode.IsGroupNode;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.SelectCell(AForward, ANextRow: Boolean;
|
|
var ARowIndex, ACellIndex: Integer): TcxCustomInplaceEditContainer;
|
|
begin
|
|
if (FocusedNode <> nil) and FocusedNode.IsGroupNode then
|
|
begin
|
|
if ANextRow or TreeList.OptionsBehavior.FocusCellOnCycle then
|
|
begin
|
|
if AForward or ANextRow or (ACellIndex < 0) then
|
|
ACellIndex := Min(0, TreeList.VisibleColumnCount - 1)
|
|
else
|
|
ACellIndex := TreeList.VisibleColumnCount - 1;
|
|
if not ANextRow then
|
|
Inc(ARowIndex, cxIntOffs[AForward]);
|
|
end;
|
|
end;
|
|
Result := inherited SelectCell(AForward, ANextRow, ARowIndex, ACellIndex);
|
|
end;
|
|
|
|
procedure TcxTreeListCellNavigator.SetFocusCell(
|
|
ARowIndex, ACellIndex: Integer; AShift: TShiftState);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
AIndex: Integer;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
ANode := Nodes.GetVisibleNode(ARowIndex);
|
|
if ANode <> nil then
|
|
AIndex := ANode.RecordIndex
|
|
else
|
|
AIndex := cxInvalidIndex;
|
|
if IsGroupRow(ARowIndex) then
|
|
Controller.SetFocusedRecordItem(AIndex, TreeList.OptionsView.GetCategorizedColumn)
|
|
else
|
|
Controller.SetFocusedRecordItem(AIndex, VisibleColumns[ACellIndex]);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCellNavigator.KeyDown(var Key: Word; Shift: TShiftState);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
TcxTreeListController(Controller).IsControllerEvent := True;
|
|
try
|
|
if TreeList.OptionsSelection.CellSelect and ([ssShift, ssCtrl] * Shift = []) then
|
|
inherited KeyDown(Key, Shift)
|
|
else
|
|
case Key of
|
|
VK_LEFT, VK_RIGHT:
|
|
begin
|
|
if TreeList.ViewInfo.HorzScrollSize <> 0 then
|
|
TreeList.ScrollContent(TcxDirection(Byte(Key = VK_RIGHT) + 1));
|
|
Key := 0;
|
|
end;
|
|
VK_UP, VK_DOWN:
|
|
begin
|
|
if TreeList.FocusedNode <> nil then
|
|
begin
|
|
ANode := TreeList.FocusedNode.GetNextVisibleEx(Key = VK_UP);
|
|
if ANode <> nil then
|
|
TreeList.SetFocusedNode(ANode, Shift);
|
|
end;
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
finally
|
|
TcxTreeListController(Controller).IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCellNavigator.Refresh;
|
|
begin
|
|
inherited Refresh;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.GetCellIndex(
|
|
AColumn: TcxTreeListColumn; ABandRow: TcxTreeListBandRow): Integer;
|
|
begin
|
|
with AColumn.Position do
|
|
Result := ABandRow[cxMin(ColIndex, ABandRow.Count - 1)].VisibleIndexAtBand;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.GetFocusedNode: TcxTreeListNode;
|
|
begin
|
|
Result := TreeList.FocusedNode;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(TcxTreeListController(Controller).EditingControl);
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.GoToNextCellInBand(AForward: Boolean;
|
|
AColumn: TcxTreeListColumn; var ACellIndex: Integer): Boolean;
|
|
var
|
|
ARow: Integer;
|
|
begin
|
|
ARow := AColumn.Position.RowIndex;
|
|
Inc(ARow, cxIntOffs[AForward]);
|
|
Result := False;
|
|
with AColumn.OwnerBand do
|
|
begin
|
|
if BandRows.Count > 1 then
|
|
begin
|
|
while not Result and cxInRange(ARow, 0, BandRows.Count - 1) do
|
|
begin
|
|
if BandRows[ARow].Count > 0 then
|
|
begin
|
|
ACellIndex := GetCellIndex(AColumn, BandRows[ARow]);
|
|
Result := True;
|
|
end
|
|
else
|
|
Inc(ARow, cxIntOffs[AForward]);
|
|
end;
|
|
end
|
|
else
|
|
ACellIndex := AColumn.VisibleIndex;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListCellNavigator.GoToNextNodeCell(AForward: Boolean;
|
|
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var ACellIndex: Integer): Boolean;
|
|
var
|
|
ARow: Integer;
|
|
begin
|
|
Result := (ANode <> nil) and (AColumn <> nil);
|
|
if Result then
|
|
begin
|
|
if ANode.IsGroupNode then
|
|
ACellIndex := 0
|
|
else
|
|
with AColumn.OwnerBand do
|
|
begin
|
|
ARow := cxSetValue(AForward, 0, BandRows.Count - 1);
|
|
while BandRows[ARow].Count = 0 do
|
|
Inc(ARow, cxIntOffs[AForward]);
|
|
ACellIndex := AColumn.VisibleIndex;
|
|
if ACellIndex = -1 then
|
|
ACellIndex := GetCellIndex(AColumn, BandRows[ARow]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListController }
|
|
|
|
procedure TcxTreeListController.AfterPaint;
|
|
begin
|
|
if (TreeList.DragAndDropState = ddsInProcess) and
|
|
(TreeList.Customizing.DragAndDropObject <> nil) then
|
|
TreeList.Customizing.DragAndDropObject.OwnerImageChanged
|
|
else
|
|
inherited AfterPaint;
|
|
end;
|
|
|
|
procedure TcxTreeListController.BeforePaint;
|
|
begin
|
|
TreeList.ViewInfo.NodesViewInfo.PostUpdate;
|
|
TreeList.ViewInfo.NodesViewInfo.PostViewInfoUpdate;
|
|
if (TreeList.DragAndDropState = ddsInProcess) and
|
|
(TreeList.Customizing.DragAndDropObject <> nil) then
|
|
TreeList.Customizing.DragAndDropObject.OwnerImageChanging
|
|
else
|
|
inherited BeforePaint;
|
|
if PrevTopVisibleIndex <> TreeList.TopVisibleIndex then
|
|
begin
|
|
PrevTopVisibleIndex := TreeList.TopVisibleIndex;
|
|
TreeList.DoOnTopRecordIndexChanged;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.CheckAutoScrolling(
|
|
const APoint: TPoint): Boolean;
|
|
var
|
|
ASide: TcxBorder;
|
|
begin
|
|
Result := False;
|
|
for ASide := bLeft to bBottom do
|
|
Result := Result or ScrollControllers[ASide].Check(APoint);
|
|
end;
|
|
|
|
procedure TcxTreeListController.CheckHitItemOnMouseDown(
|
|
X, Y: Integer; Shift: TShiftState);
|
|
|
|
function GetNeededItem: TcxCustomInplaceEditContainer;
|
|
begin
|
|
with TreeList.HitTest do
|
|
if HitAtColumn then
|
|
Result := HitColumn
|
|
else
|
|
Result := FocusedItem
|
|
end;
|
|
|
|
begin
|
|
IsControllerEvent := True;
|
|
try
|
|
with TreeList.HitTest do
|
|
begin
|
|
RecalculateOnMouseEvent(X, Y, Shift);
|
|
if HitTestItem is TcxTreeListHeaderViewInfo and not CanSizing() and (ssLeft in Shift) then
|
|
TcxTreeListHeaderViewInfo(HitTestItem).Pressed := not TreeList.IsDesigning
|
|
else
|
|
if HitAtButton and (ssLeft in Shift) then
|
|
begin
|
|
if TreeList.IsCancelOperation then Exit;
|
|
RecalculateOnMouseEvent(X, Y, Shift);
|
|
HitNode.Expanded := not HitNode.Expanded
|
|
end
|
|
else
|
|
if HitAtNode and not (HitAtButton or HitAtIndent) and not CanDrag(X, Y) then
|
|
begin
|
|
if not IsItemEditCell then
|
|
SetFocusedRecordItem(HitNode.RecordIndex, GetNeededItem);
|
|
end;
|
|
end;
|
|
finally
|
|
IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.CheckEdit;
|
|
begin
|
|
inherited CheckEdit;
|
|
TreeList.RefreshNavigatorButtons;
|
|
end;
|
|
|
|
procedure TcxTreeListController.BeforeShowEdit;
|
|
begin
|
|
TreeList.ViewInfo.NodesViewInfo.BeforeShowEdit;
|
|
end;
|
|
|
|
procedure TcxTreeListController.SetFocusedRecordIndex(Value: Integer);
|
|
begin
|
|
if not TreeList.SkipFocusedRecordChanged then
|
|
inherited SetFocusedRecordIndex(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListController.BeforeStartDrag;
|
|
begin
|
|
inherited BeforeStartDrag;
|
|
DragNodesList := TreeList.GetSelectionsEx;
|
|
if HitTest.HitAtColumn and HitTest.HitAtNode then
|
|
begin
|
|
DragColumn := HitTest.HitColumn;
|
|
DragNode := HitTest.HitNode;
|
|
end
|
|
else
|
|
begin
|
|
DragColumn := nil;
|
|
DragNode := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.CheckButtonTimer;
|
|
var
|
|
NeedTimer: Boolean;
|
|
begin
|
|
if (ExpandingNode <> HitTest.HitNode) or not HitTest.HitAtButton then
|
|
ResetButtonTimer;
|
|
if ExpandingNode = nil then
|
|
begin
|
|
NeedTimer := HitTest.HitAtButton and
|
|
(OptionsBehavior.DragExpand and not HitTest.HitNode.Expanded) or
|
|
(OptionsBehavior.DragCollapse and HitTest.HitNode.Expanded);
|
|
if NeedTimer then
|
|
begin
|
|
ExpandTimer.Interval := OptionsBehavior.WaitForExpandNodeTime;
|
|
ExpandTimer.Enabled := True;
|
|
ExpandTimer.OnTimer := OnExpandTimer;
|
|
ExpandingNode := HitTest.HitNode;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DragDrop(Source: TObject; X, Y: Integer);
|
|
begin
|
|
with TreeList, HitTest do
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
if Source is TBaseDragControlObject then
|
|
Source := TBaseDragControlObject(Source).Control;
|
|
if (Source = TreeList) and HitAtNode then
|
|
DropTo(HitNode, HitAtNodePreview or HitAtColumn);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DragEnter;
|
|
|
|
function AddAutoScrollRegion(Kind: TScrollBarKind;
|
|
const ARect: TRect; ACode: TScrollCode): TcxAutoScrollingObject;
|
|
begin
|
|
Result := TcxControllerAutoScrollingObject.Create(Self);
|
|
Result.SetParams(ARect, Kind, ACode, 1);
|
|
end;
|
|
|
|
begin
|
|
if ExpandTimer <> nil then Exit;
|
|
if TreeList.FDragNode = nil then
|
|
TreeList.FDragNode := TreeList.FocusedNode;
|
|
with TreeList.ViewInfo.NodesViewInfo do
|
|
begin
|
|
ScrollControllers[bTop] := AddAutoScrollRegion(sbVertical,
|
|
cxRectSetHeight(ClipRect, cxtlScrollDelta), scLineUp);
|
|
ScrollControllers[bBottom] := AddAutoScrollRegion(sbVertical,
|
|
cxRectSetTop(ClipRect, ClipRect.Bottom - cxtlScrollDelta), scLineDown);
|
|
ScrollControllers[bLeft] := AddAutoScrollRegion(sbHorizontal,
|
|
cxRectSetWidth(ClipRect, cxtlScrollDelta), scLineUp);
|
|
ScrollControllers[bRight] := AddAutoScrollRegion(sbHorizontal,
|
|
cxRectSetWidth(ClipRect, ClipRect.Right - cxtlScrollDelta, cxtlScrollDelta), scLineDown);
|
|
end;
|
|
ExpandTimer := TTimer.Create(TreeList);
|
|
end;
|
|
|
|
procedure TcxTreeListController.DragLeave;
|
|
var
|
|
ASide: TcxBorder;
|
|
begin
|
|
for ASide := bLeft to bBottom do
|
|
FreeAndNil(ScrollControllers[ASide]);
|
|
FreeAndNil(ExpandTimer);
|
|
end;
|
|
|
|
procedure TcxTreeListController.DragMove(
|
|
Source: TObject; const P: TPoint; var Accepted: Boolean);
|
|
|
|
procedure ProcessDragMove;
|
|
begin
|
|
HitTest.Recalculate(P);
|
|
if HitTest.HitAtButton then
|
|
CheckButtonTimer
|
|
else
|
|
ExpandingNode := nil;
|
|
CheckAutoScrolling(P);
|
|
end;
|
|
|
|
begin
|
|
ProcessDragMove;
|
|
HitTest.ReCalculate(P);
|
|
with TreeList.OptionsBehavior do
|
|
begin
|
|
if HitTest.HitAtNode and DragFocusing and not HitTest.HitNode.Focused then
|
|
HitTest.HitNode.Focused := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DragOver(
|
|
Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
begin
|
|
case State of
|
|
dsDragEnter:
|
|
DragEnter;
|
|
dsDragLeave:
|
|
DragLeave;
|
|
dsDragMove:
|
|
DragMove(Source, Point(X, Y), Accept);
|
|
end;
|
|
inherited DragOver(Source, X, Y, State, Accept);
|
|
end;
|
|
|
|
procedure TcxTreeListController.DropTo(
|
|
ANode: TcxTreeListNode; AsChildren: Boolean);
|
|
const
|
|
AModes: array[Boolean] of TcxTreeListNodeAttachMode = (tlamInsert, tlamAddChild);
|
|
begin
|
|
if ANode <> nil then
|
|
begin
|
|
if TreeList.OptionsBehavior.DragFocusing and
|
|
(DragNodesList.IndexOf(TreeList.DragNode) = cxInvalidIndex) then
|
|
DragNodesList.Add(TreeList.DragNode);
|
|
try
|
|
TreeList.SaveDragPos;
|
|
TreeList.DoInternalMoveTo(ANode,
|
|
AModes[AsChildren], DragNodesList, TreeList.Controller.IsDragCopy);
|
|
finally
|
|
FreeAndNil(DragNodesList);
|
|
TreeList.Controller.CancelSelection;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.EndDrag(Target: TObject; X, Y: Integer);
|
|
begin
|
|
HitTestController.ReCalculate(Point(X, Y));
|
|
if (GetAsyncKeyState(VK_SHIFT) >= 0) and not IsCtrlPressed then
|
|
CancelSelection;
|
|
if TreeList.OptionsBehavior.AlwaysShowEditor or TreeList.OptionsBehavior.ImmediateEditor and
|
|
((FocusedItem <> nil) and (FocusedNode <> nil)) then EditingController.ShowEdit();
|
|
FreeAndNil(DragNodesList);
|
|
end;
|
|
|
|
procedure TcxTreeListController.OnExpandTimer(Sender: TObject);
|
|
begin
|
|
with HitTest do
|
|
begin
|
|
ResetButtonTimer;
|
|
if HitAtNode and HitAtButton and (HitNode = ExpandingNode) then
|
|
ExpandingNode.Expanded := not ExpandingNode.Expanded
|
|
else
|
|
ExpandingNode := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.ResetButtonTimer;
|
|
begin
|
|
if ExpandTimer <> nil then
|
|
ExpandTimer.Enabled := False;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoChangeColumnSortOrder(
|
|
AColumn: TcxTreeListColumn; ASortOrder: TcxDataSortOrder; AShift: TShiftState);
|
|
begin
|
|
AShift := ValidateShift(AShift);
|
|
if not TreeList.OptionsBehavior.Sorting or not AColumn.Options.Sorting then Exit;
|
|
TreeList.DisableSorting;
|
|
try
|
|
TreeList.Sorted := ([ssShift, ssCtrl] * AShift <> []) and
|
|
TreeList.OptionsBehavior.MultiSort;
|
|
if ssCtrl in AShift then
|
|
AColumn.SortOrder := soNone
|
|
else
|
|
if TreeList.OptionsBehavior.Sorting then
|
|
AColumn.SortOrder := ASortOrder;
|
|
finally
|
|
TreeList.EnableSorting;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoNextNode(AForward: Boolean);
|
|
begin
|
|
if (FocusedNode <> nil) and (FocusedNode.GetNextVisibleEx(AForward) <> nil) then
|
|
FocusedNode := FocusedNode.GetNextVisibleEx(AForward);
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoNextPage(AForward: Boolean; Shift: TShiftState);
|
|
begin
|
|
DoShowNextPageEx(AForward, True, Shift);
|
|
TreeList.Controller.CheckEdit;
|
|
TreeList.Update;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoShowNextPageEx(
|
|
AGoForward, ASetCursor: Boolean; AShift: TShiftState);
|
|
|
|
function GetNext(ANode: TcxTreeListNode; IsNext: Boolean): TcxTreeListNode;
|
|
begin
|
|
Result := ANode;
|
|
if (ANode <> nil) and (TreeList.VisibleCount = 1) then
|
|
Result := ANode.GetNextVisibleEx(not IsNext);
|
|
end;
|
|
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
if AGoForward then
|
|
begin
|
|
if LastVisibleNode <> nil then
|
|
with LastVisibleNode do
|
|
if IsLastVisible and Focused and ASetCursor then Exit;
|
|
if ASetCursor then
|
|
begin
|
|
TopVisibleNode := GetNext(FocusedNode, True);
|
|
SetFocusedNode(LastVisibleNode, AShift)
|
|
end
|
|
else
|
|
TopVisibleNode := GetNext(LastVisibleNode, True);
|
|
end
|
|
else
|
|
begin
|
|
if TopVisibleNode <> nil then
|
|
with TopVisibleNode do
|
|
if IsFirstVisible and Focused and ASetCursor then Exit;
|
|
if ASetCursor then
|
|
begin
|
|
LastVisibleNode := GetNext(FocusedNode, False);
|
|
SetFocusedNode(TopVisibleNode, AShift)
|
|
end
|
|
else
|
|
LastVisibleNode := GetNext(TopVisibleNode, False);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.FocusedRecordChanged(
|
|
APrevFocusedRecordIndex, AFocusedRecordIndex: Integer);
|
|
var
|
|
APrevFocusedNode, AFocusedNode: TcxTreeListNode;
|
|
begin
|
|
if not IsInIncSearchChanging and IsIncSearching then
|
|
CancelIncSearching;
|
|
TreeList.DoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex);
|
|
if TreeList.FNeedFocusedRecordUpdatePost then Exit;
|
|
with TcxTreeListCellNavigator(Navigator) do
|
|
begin
|
|
Refresh;
|
|
AFocusedNode := GetNode(AFocusedRecordIndex);
|
|
if (AFocusedNode <> nil) and not IsDragMode then
|
|
AFocusedNode.MakeVisible;
|
|
APrevFocusedNode := GetNode(APrevFocusedRecordIndex);
|
|
with TreeList do
|
|
begin
|
|
if DoIsGroupNode(AFocusedNode) and (VisibleColumnCount > 0) then
|
|
FocusedColumn := OptionsView.GetCategorizedColumn;
|
|
end;
|
|
TreeList.ViewInfo.NodesViewInfo.FocusedRecordChanged(APrevFocusedNode, AFocusedNode);
|
|
end;
|
|
if(TreeList.DragAndDropState = ddsNone) and not IsControllerEvent or
|
|
(CurrentShiftState * [ssCtrl, ssShift, ssLeft, ssRight] = []) then
|
|
CancelSelection
|
|
else
|
|
if (SelectionAnchorNode = nil) and (APrevFocusedNode <> nil) then
|
|
SelectionAnchorNode := APrevFocusedNode;
|
|
inherited FocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex);
|
|
AFocusedNode := GetNode(AFocusedRecordIndex);
|
|
if AFocusedNode <> nil then AFocusedNode.Repaint(False);
|
|
end;
|
|
|
|
procedure TcxTreeListController.FocusedItemChanged(
|
|
APrevFocusedItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
inherited FocusedItemChanged(APrevFocusedItem);
|
|
UpdateRecord(DataController.FocusedRecordIndex);
|
|
TreeList.DoFocusedItemChanged(APrevFocusedItem, FocusedItem);
|
|
end;
|
|
|
|
function TcxTreeListController.IsDragMode: Boolean;
|
|
begin
|
|
with TreeList do
|
|
Result := DragAndDropState = ddsInProcess;
|
|
end;
|
|
|
|
function TcxTreeListController.IsKeyForController(
|
|
AKey: Word; AShift: TShiftState): Boolean;
|
|
begin
|
|
Result := (AKey = VK_ADD) or (AKey = VK_SUBTRACT) or (AKey = VK_MULTIPLY) or
|
|
(AKey = VK_HOME) or (AKey = VK_END);
|
|
Result := inherited IsKeyForController(AKey, AShift) or
|
|
((IsEditing and (ssCtrl in AShift) and Result) or (not IsEditing and Result));
|
|
end;
|
|
|
|
function TcxTreeListController.IsNodeKeyHandle(ANode: TcxTreeListNode;
|
|
var AKey: Word; Shift: TShiftState): Boolean;
|
|
var
|
|
ATop: Integer;
|
|
begin
|
|
Result := True;
|
|
case AKey of
|
|
VK_SUBTRACT, VK_ADD:
|
|
if (IncSearchText = '') and (ANode <> nil) and ANode.HasChildren then
|
|
ANode.Expanded := AKey = VK_ADD
|
|
else
|
|
Result := False;
|
|
VK_MULTIPLY:
|
|
if (ANode <> nil) and ANode.HasChildren then
|
|
ANode.Expand(AKey = VK_MULTIPLY);
|
|
VK_HOME:
|
|
with TreeList do
|
|
begin
|
|
if ssCtrl in Shift then
|
|
begin
|
|
TreeList.TopVisibleIndex := 0;
|
|
TreeList.FocusedNode := TreeList.TopVisibleNode;
|
|
end
|
|
else
|
|
if VisibleColumnCount > 0 then
|
|
VisibleColumns[0].Focused := True;
|
|
end;
|
|
VK_END:
|
|
with TreeList do
|
|
begin
|
|
if ssCtrl in Shift then
|
|
begin
|
|
TopVisibleIndex := Nodes.VisibleCount - 1;
|
|
FocusedNode := LastVisibleNode;
|
|
end
|
|
else
|
|
if VisibleColumnCount > 0 then
|
|
VisibleColumns[VisibleColumnCount - 1].Focused := True;
|
|
end;
|
|
VK_DELETE:
|
|
begin
|
|
Result := (ssCtrl in Shift) and CanDeleteSelection and DeleteConfirmation;
|
|
ATop := TreeList.TopVisibleIndex;
|
|
if Result then
|
|
try
|
|
TreeList.DoDeleteSelection;
|
|
TreeList.DataController.Post;
|
|
finally
|
|
TreeList.TopVisibleIndex := ATop;
|
|
if TreeList.FocusedNode <> nil then
|
|
TreeList.FocusedNode.MakeVisible;
|
|
end;
|
|
end;
|
|
VK_INSERT:
|
|
begin
|
|
if (FocusedNode = nil) or (not CanInsertNode) then
|
|
Result := False
|
|
else
|
|
TreeList.InsertNode(ssCtrl in Shift);
|
|
end;
|
|
else
|
|
Result := False
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.CanDrag(X, Y: Integer): Boolean;
|
|
begin
|
|
with TreeList.HitTest do
|
|
begin
|
|
HitPoint := Point(X, Y);
|
|
Result := not CanSizing and not TreeList.IsDesigning and not IsEditing and
|
|
(HitAtNode and HitNode.Selected and not HitAtIndent);
|
|
if Result then
|
|
TreeList.FDragNode := HitNode;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.BeforeMouseDown(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
|
|
function GetNeededItem: TcxCustomInplaceEditContainer;
|
|
begin
|
|
with TreeList.HitTest do
|
|
if HitAtColumn then
|
|
Result := HitColumn
|
|
else
|
|
Result := FocusedItem
|
|
end;
|
|
|
|
begin
|
|
IsControllerEvent := True;
|
|
try
|
|
CurrentShiftState := Shift;
|
|
if not Focused and (FocusedRecordIndex = cxInvalidIndex) then
|
|
begin
|
|
if HitTest.HitAtNode then
|
|
ForceFocusedRecord := HitTest.HitNode.RecordIndex;
|
|
if not HitTest.HitAtButton then
|
|
CheckHitItemOnMouseDown(X, Y, Shift);
|
|
if (FocusedRecordIndex <> cxInvalidIndex) and (TreeList.VisibleColumnCount > 0) then
|
|
TreeList.VisibleColumns[0].Focused := True;
|
|
end;
|
|
if Focused and OptionsBehavior.ImmediateEditor and HitTest.HitAtNode and
|
|
not HitTest.HitAtIndent and not TreeList.IsDesigning then
|
|
begin
|
|
SetFocusedRecordItem(HitTest.HitNode.RecordIndex, GetNeededItem);
|
|
BlockFocusChanged := True;
|
|
end;
|
|
finally
|
|
IsControllerEvent := False;
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxTreeListController.BeginDragAndDrop;
|
|
begin
|
|
inherited BeginDragAndDrop;
|
|
TreeList.Update;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoMouseDown(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if (TreeList.DragAndDropState <> ddsNone) and HitTest.CanSizing then
|
|
begin
|
|
EditingController.HideEdit(True);
|
|
Exit;
|
|
end;
|
|
IsControllerEvent := True;
|
|
try
|
|
inherited DoMouseDown(Button, Shift, X, Y);
|
|
BlockFocusChanged := False;
|
|
if CanDrag(X, Y) and HitTest.HitAtNode and IsEditing then
|
|
TreeList.DragAndDropState := ddsNone;
|
|
HitTest.ReCalculate(Point(X, Y));
|
|
if HitAtNodeEx then
|
|
begin
|
|
if ([ssCtrl, ssShift] * Shift <> []) then
|
|
Select(HitTest.HitNode, Shift)
|
|
else
|
|
if (FocusedNode = nil) or not FocusedNode.Selected then
|
|
CancelSelection;
|
|
end;
|
|
|
|
if TreeList.IsDesigning and (HitTest.HitTestItem is TcxTreeListHeaderViewInfo) and
|
|
not HitTest.CanSizing() and (ssLeft in Shift) then
|
|
begin
|
|
if HitTest.HitAtColumn then
|
|
SelectObject(HitTest.HitColumn, Shift)
|
|
else
|
|
SelectObject(HitTest.HitBand, Shift);
|
|
end;
|
|
if CanDrag(X, Y) and HitTest.HitAtNode and (HitTest.HitAtImages or
|
|
HitTest.HitAtIndicator or (HitTest.HitAtColumn and
|
|
not GetImmediateEditor) or HitTest.HitAtBandContainer) then;
|
|
finally
|
|
ShowEditOnMouseUp := TreeList.OptionsBehavior.ImmediateEditor and HitTest.IsItemEditCell;
|
|
IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.ControlFocusChanged;
|
|
var
|
|
AColumn: TcxTreeListColumn;
|
|
ARecordIndex: Integer;
|
|
begin
|
|
inherited ControlFocusChanged;
|
|
if ForceFocusedRecord >= 0 then Exit;
|
|
ARecordIndex := 0;
|
|
AColumn := TreeList.FocusedColumn;
|
|
with DataController, TreeList do
|
|
if (RecordCount > 0) and (FocusedRecordIndex = cxInvalidIndex) and
|
|
(VisibleColumnCount > 0) then
|
|
begin
|
|
if AColumn = nil then
|
|
AColumn := VisibleColumns[0];
|
|
if SelectionCount > 0 then
|
|
ARecordIndex := Selections[0].RecordIndex;
|
|
SetFocusedRecordItem(ARecordIndex, AColumn);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.CanDeleteSelection: Boolean;
|
|
begin
|
|
Result := TreeList.OptionsData.Deleting and not TreeList.IsEditing;
|
|
end;
|
|
|
|
function TcxTreeListController.CanInsertNode: Boolean;
|
|
begin
|
|
Result := TreeList.OptionsData.Inserting;
|
|
if not Result then Exit;
|
|
Result := False;
|
|
if [dceEdit, dceChanging] * DataController.EditState <> [] then
|
|
DataController.Post;
|
|
if dceInsert in DataController.EditState then
|
|
begin
|
|
if [dceChanging, dceModified] * DataController.EditState <> [] then
|
|
TreeList.DataController.Post
|
|
else
|
|
Exit;
|
|
end;
|
|
Result := ([dceInsert, dceEdit] * DataController.EditState = []);
|
|
end;
|
|
|
|
procedure TcxTreeListController.DblClick;
|
|
var
|
|
ADir: TcxDragSizingDirection;
|
|
begin
|
|
if IsEditing and (FocusedNode <> nil) and FocusedNode.HasChildren then
|
|
EditingController.HideEdit(True);
|
|
if TreeList.IsCancelOperation then Exit;
|
|
EditingController.StopEditShowingTimer;
|
|
inherited DblClick;
|
|
TreeList.ViewInfo.IsDirty := True;
|
|
with HitTest do
|
|
begin
|
|
HitTest.Recalculate;
|
|
if HitAtNode and not HitAtButton and not IsEditing and OptionsBehavior.ExpandOnDblClick then
|
|
HitNode.Expanded := not HitNode.Expanded;
|
|
if (HitAtBandHeader or HitAtColumnHeader) and CanSizing(ADir) and (ADir = dsdHorz) then
|
|
begin
|
|
if HitAtBandHeader then
|
|
HitBand.ApplyBestFit
|
|
else
|
|
HitColumn.ApplyBestFit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.EndDragAndDrop(Accepted: Boolean);
|
|
begin
|
|
inherited EndDragAndDrop(Accepted);
|
|
end;
|
|
|
|
function TcxTreeListController.DeleteConfirmation: Boolean;
|
|
begin
|
|
if TreeList.OptionsBehavior.ConfirmDelete then
|
|
Result := cxConfirmMessageBox(
|
|
scxStr(@scxTreeListDeletingFocusedConfirmationText),
|
|
scxStr(@scxTreeListDeletingConfirmationCaption))
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoMouseUp(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
if [ssShift, ssCtrl] * Shift <> [] then
|
|
with TreeList do
|
|
begin
|
|
if OptionsSelection.MultiSelect and not GetImmediateEditor then
|
|
EditingController.StopEditShowingTimer;
|
|
end;
|
|
if ShowEditOnMouseUp and HitTest.IsItemEditCell then
|
|
begin
|
|
if not TreeList.IsEditing then
|
|
EditingController.ShowEdit();
|
|
ShowEditOnMouseUp := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.GetCursor(X, Y: Integer): TCursor;
|
|
begin
|
|
if not TreeList.IsDesigning then
|
|
begin
|
|
if Int64(Point(X, Y)) <> Int64(HitTestController.HitPoint) then
|
|
TcxTreeListHitTest(HitTestController).RecalculateOnMouseEvent(X, Y, []);
|
|
Result := TcxTreeListHitTest(HitTestController).CurrentCursor;
|
|
if Result = crDefault then
|
|
Result := inherited GetCursor(X, Y);
|
|
end
|
|
else
|
|
Result := inherited GetCursor(X, Y);
|
|
end;
|
|
|
|
function TcxTreeListController.GetDragAndDropObjectClass: TcxDragAndDropObjectClass;
|
|
begin
|
|
DragItem := HitTest.HitTestItem;
|
|
if HitTest.CanSizing(ResizeDirection) then
|
|
begin
|
|
Result := TcxSizingDragAndDropObject;
|
|
if HitTest.HitAtNode then
|
|
DragItem := HitTest.SizingHitNode;
|
|
end
|
|
else
|
|
if HitTest.CanMoving then
|
|
Result := TcxTreeListDragAndDropObject
|
|
else
|
|
if HitTest.HitAtNode then
|
|
Result := nil
|
|
else
|
|
begin
|
|
DragItem := nil;
|
|
Result := inherited GetDragAndDropObjectClass;
|
|
end
|
|
end;
|
|
|
|
function TcxTreeListController.GetImmediateEditor: Boolean;
|
|
begin
|
|
Result := inherited GetImmediateEditor;
|
|
if Result and TreeList.OptionsSelection.MultiSelect then
|
|
Result := [ssShift, ssCtrl] * CurrentShiftState = [];
|
|
end;
|
|
|
|
function TcxTreeListController.HitAtNodeEx: Boolean;
|
|
begin
|
|
with HitTest do
|
|
begin
|
|
Result := TreeList.IsMultiSelect and HitAtNode and
|
|
not (HitAtButton or (HitAtIndent and not HitAtImage));
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.IsDragCopy: Boolean;
|
|
begin
|
|
Result := IsCtrlPressed and
|
|
TreeList.OptionsBehavior.AutoDragCopy;
|
|
end;
|
|
|
|
function TcxTreeListController.IsDestroying: Boolean;
|
|
begin
|
|
Result := TreeList.IsDestroying;
|
|
end;
|
|
|
|
procedure TcxTreeListController.KeyDown(var Key: Word;
|
|
Shift: TShiftState);
|
|
|
|
procedure RevertExpanding;
|
|
begin
|
|
FocusedNode.Expanded := not FocusedNode.Expanded;
|
|
Key := 0;
|
|
end;
|
|
|
|
var
|
|
AKey: Word;
|
|
APrevNode: TcxTreeListNode;
|
|
|
|
begin
|
|
IsControllerEvent := True;
|
|
CurrentShiftState := Shift;
|
|
try
|
|
AKey := Key;
|
|
EatKeyPress := IsNodeKeyHandle(FocusedNode, Key, Shift);
|
|
if (AKey = VK_SPACE) and (FocusedNode <> nil) and
|
|
TreeList.IsMultiSelect and ([ssCtrl, ssShift] * Shift <> []) then
|
|
begin
|
|
if (ssCtrl in Shift) then
|
|
begin
|
|
FocusedNode.Selected := not FocusedNode.Selected;
|
|
if FocusedNode.Selected then
|
|
SelectionAnchorNode := FocusedNode;
|
|
end
|
|
else
|
|
Select(FocusedNode, CurrentShiftState);
|
|
Key := 0;
|
|
end;
|
|
if (TreeList.VisibleColumnCount = 1) and (FocusedNode <> nil) and (FocusedNode.HasChildren) then
|
|
begin
|
|
if ((Key = VK_LEFT) and FocusedNode.Expanded) or
|
|
((Key = VK_RIGHT) and not FocusedNode.Expanded) then RevertExpanding;
|
|
end;
|
|
inherited KeyDown(Key, Shift);
|
|
case AKey of
|
|
VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_NEXT, VK_PRIOR, VK_HOME, VK_END:
|
|
begin
|
|
if Key in [VK_NEXT, VK_PRIOR, VK_HOME, VK_END] then
|
|
begin
|
|
APrevNode := SelectionAnchorNode;
|
|
Selection.Clear;
|
|
if (SelectionAnchorNode <> nil) then
|
|
Selection.Add(SelectionAnchorNode);
|
|
Select(FocusedNode, CurrentShiftState);
|
|
SelectionAnchorNode := APrevNode;
|
|
end
|
|
else
|
|
Select(FocusedNode, CurrentShiftState);
|
|
end;
|
|
VK_MENU, VK_SHIFT, VK_CONTROL:
|
|
SetHotTrackNode(HotTrackNode, CurrentShiftState);
|
|
end;
|
|
finally
|
|
IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
IsControllerEvent := True;
|
|
try
|
|
CurrentShiftState := Shift;
|
|
inherited KeyUp(Key, Shift);
|
|
case Key of
|
|
VK_MENU, VK_SHIFT, VK_CONTROL:
|
|
SetHotTrackNode(HotTrackNode, CurrentShiftState);
|
|
end;
|
|
finally
|
|
IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.MakeFocusedItemVisible;
|
|
var
|
|
AColumn: TcxTreeListColumn;
|
|
begin
|
|
AColumn := TcxTreeListColumn(FocusedItem);
|
|
if AColumn <> nil then
|
|
begin
|
|
AColumn.MakeVisible;
|
|
MakeFocusedRecordVisible;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.MakeFocusedRecordVisible;
|
|
begin
|
|
TreeList.MakeNodeVisible(FocusedNode);
|
|
end;
|
|
|
|
procedure TcxTreeListController.MouseDown(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
CurrentShiftState := Shift;
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
CheckHitItemOnMouseDown(X, Y, Shift);
|
|
SetHotTrackNode(nil, []);
|
|
end;
|
|
|
|
procedure TcxTreeListController.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
IsControllerEvent := True;
|
|
try
|
|
CurrentShiftState := Shift;
|
|
inherited MouseMove(Shift, X, Y);
|
|
UpdateHotTrackNode(X, Y, Shift);
|
|
finally
|
|
IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.MouseUp(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
IsControllerEvent := True;
|
|
try
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
with TreeList do
|
|
begin
|
|
if HitAtNodeEx and (SelectionCount > 1) and ([ssShift, ssCtrl] * Shift = []) and
|
|
(Button = mbLeft) then CancelSelection;
|
|
end;
|
|
CurrentShiftState := Shift;
|
|
with TreeList.HitTest do
|
|
if FPressedHeader <> nil then FPressedHeader.Pressed := False;
|
|
IsDragDropProcess := False;
|
|
finally
|
|
IsControllerEvent := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.Scroll(AScrollBarKind: TScrollBarKind;
|
|
AScrollCode: TScrollCode; var AScrollPos: Integer);
|
|
var
|
|
AScrolled: Boolean;
|
|
|
|
function CheckPos(APos, APage, AInc, AMax : Integer): Boolean;
|
|
begin
|
|
case AScrollCode of
|
|
scLineUp:
|
|
AScrollPos := APos - AInc;
|
|
scLineDown:
|
|
AScrollPos := APos + AInc;
|
|
scPageUp:
|
|
AScrollPos := APos - APage;
|
|
scPageDown:
|
|
AScrollPos := APos + APage;
|
|
scTop:
|
|
AScrollPos := 0;
|
|
scBottom:
|
|
AScrollPos := AMax;
|
|
scTrack:
|
|
AScrollCode := scPosition;
|
|
end;
|
|
if AScrollPos < 0 then
|
|
AScrollPos := 0
|
|
else
|
|
if AScrollPos + APage > AMax then AScrollPos := AMax - APage;
|
|
if AScrollCode = scPosition then cxRange(AScrollPos, 0, AMax);
|
|
Result := AScrollPos <> APos;
|
|
AScrolled := AScrolled or Result;
|
|
end;
|
|
|
|
begin
|
|
if TreeList.IsLocked or (AScrollCode = scEndScroll) then Exit;
|
|
with TreeList.ViewInfo do
|
|
begin
|
|
AScrolled := False;
|
|
if (AScrollBarKind = sbHorizontal) and CheckPos(HorzScrollPos,
|
|
Max(1, HorzScrollPage - TreeList.GetFixedContentSize), HorzScrollInc, HorzScrollSize - TreeList.GetFixedContentSize) then
|
|
begin
|
|
TreeList.HScrollBar.Position := AScrollPos;
|
|
DoScrollHorizontal(AScrollPos);
|
|
end
|
|
else
|
|
if AScrollBarKind = sbVertical then
|
|
begin
|
|
begin
|
|
if (AScrollCode in [scPageUp, scPageDown]) then
|
|
TreeList.Controller.DoShowNextPageEx(AScrollCode = scPageDown, False, [])
|
|
else
|
|
with TreeList.Nodes do
|
|
begin
|
|
if CheckPos(TopIndex, NodesViewInfo.VisibleCount, 1, VisibleCount) then
|
|
DoScrollVertical(AScrollPos - TopIndex);
|
|
end;
|
|
end;
|
|
AScrollPos := TreeList.Nodes.TopIndex;
|
|
end;
|
|
end;
|
|
inherited Scroll(AScrollBarKind, AScrollCode, AScrollPos);
|
|
UpdateHotTrackNode([]);
|
|
TreeList.DoChanged;
|
|
if AScrolled then
|
|
TreeList.Update;
|
|
end;
|
|
|
|
procedure TcxTreeListController.SetFocusedRecordItem(ARecordIndex: Integer;
|
|
AItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
if BlockFocusChanged then Exit;
|
|
if not TreeList.Dragging and not (ssDouble in CurrentShiftState) then
|
|
inherited SetFocusedRecordItem(ARecordIndex, AItem);
|
|
HitTestController.ReCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListController.SetHotTrackCursor(ACursor: TCursor);
|
|
begin
|
|
TreeList.Cursor := ACursor;
|
|
end;
|
|
|
|
procedure TcxTreeListController.SetHotTrackNode(
|
|
ANode: TcxTreeListNode; AShift: TShiftState);
|
|
var
|
|
APrevNode: TcxTreeListNode;
|
|
ACursor: TCursor;
|
|
begin
|
|
if IsDestroying then Exit;
|
|
if not Focused or not TreeList.OptionsBehavior.HotTrack then ANode := nil;
|
|
if ((ANode = HotTrackNode) and (AShift = PrevHotShift)) or
|
|
TreeList.IsDesigning or TreeList.IsDestroying then Exit;
|
|
APrevNode := HotTrackNode;
|
|
HotTrackNode := ANode;
|
|
PrevHotShift := AShift;
|
|
if TreeList.OptionsBehavior.HotTrack then
|
|
begin
|
|
if APrevNode <> nil then
|
|
APrevNode.Repaint(True)
|
|
else
|
|
begin
|
|
if TreeList.FUseGlassCursor > 0 then
|
|
PrevCursor := TreeList.FStoredCursor
|
|
else
|
|
PrevCursor := TreeList.Cursor;
|
|
end;
|
|
if ANode <> nil then
|
|
begin
|
|
ANode.Repaint(True);
|
|
TreeList.DoOnHotTrackNode(ANode, AShift, ACursor);
|
|
SetHotTrackCursor(ACursor);
|
|
end
|
|
else
|
|
SetHotTrackCursor(PrevCursor);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.StartDragAndDrop(const P: TPoint): Boolean;
|
|
begin
|
|
with TreeList.HitTest do
|
|
begin
|
|
HitPoint := P;
|
|
Result := CanSizing or CanMoving and not (HitAtNode and HitNode.Selected and not HitAtIndent);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.UpdateHotTrackNode(AShift: TShiftState);
|
|
begin
|
|
with HitTest.HitPoint do
|
|
UpdateHotTrackNode(X, Y, AShift);
|
|
end;
|
|
|
|
procedure TcxTreeListController.UpdateHotTrackNode(X, Y: Integer; AShift: TShiftState);
|
|
begin
|
|
HitTest.RecalculateOnMouseEvent(X, Y, AShift);
|
|
if HitTest.HitAtNode then
|
|
SetHottrackNode(HitTest.HitNode, AShift)
|
|
else
|
|
SetHottrackNode(nil, AShift);
|
|
end;
|
|
|
|
function TcxTreeListController.GetCellFromViewInfo(AColumn: TcxTreeListColumn;
|
|
ANodeViewInfo: TcxTreeListNodeViewInfo): TcxTreeListEditCellViewInfo;
|
|
|
|
function IsExtraCell(Condition: Boolean; ACheckedInfo: TcxTreeListEditCellViewInfo;
|
|
var AInfo: TcxTreeListEditCellViewInfo): Boolean;
|
|
begin
|
|
Result := Condition and (ACheckedInfo.Column = AColumn);
|
|
if Result then AInfo := ACheckedInfo;
|
|
end;
|
|
|
|
begin
|
|
with ANodeViewInfo, AColumn do
|
|
begin
|
|
Result := nil;
|
|
if Visibility and not IsExtraCell(HasPreview, Preview, Result) and
|
|
not IsExtraCell(IsGroupNode, NodeGroupEditViewInfo, Result) then
|
|
begin
|
|
if VisibleIndexAtBand < Groups[Position.OwnerBandVisibleIndex].CellCount then
|
|
Result := Groups[Position.OwnerBandVisibleIndex].Cells[VisibleIndexAtBand]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.GetCellFromViewInfoEx(
|
|
AColumn: TcxTreeListColumn; ANode: TcxTreeListNode): TcxTreeListEditCellViewInfo;
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
if (AColumn <> nil) and (ANode <> nil) and
|
|
TreeList.ViewInfo.NodesViewInfo.FindNodeViewInfo(ANode, AViewInfo) then
|
|
Result := GetCellFromViewInfo(AColumn, AViewInfo)
|
|
else
|
|
Result := nil
|
|
end;
|
|
|
|
function TcxTreeListController.GetFocusedCellViewInfo(
|
|
AEditContainer: TcxCustomInplaceEditContainer): TcxEditCellViewInfo;
|
|
begin
|
|
Result := nil;
|
|
if (AEditContainer = nil) or TreeList.ViewInfo.IsDirty then Exit;
|
|
with TcxTreeListColumn(AEditContainer) do
|
|
if not Visibility or IsPreview then Exit;
|
|
Result := GetCellFromViewInfoEx(TcxTreeListColumn(AEditContainer), FocusedNode);
|
|
end;
|
|
|
|
function TcxTreeListController.GetNavigatorClass: TcxCustomCellNavigatorClass;
|
|
begin
|
|
Result := TcxTreeListCellNavigator;
|
|
end;
|
|
|
|
function TcxTreeListController.GetNode(ARecordIndex: Integer): TcxTreeListNode;
|
|
begin
|
|
if (ARecordIndex >= 0) and (ARecordIndex < TreeList.NodesList.Count) then
|
|
Result := TcxTreeListNode(TreeList.NodesList[ARecordIndex])
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListController.CancelIncSearching;
|
|
begin
|
|
if IsDestroying then Exit;
|
|
IncSearchText := '';
|
|
inherited CancelIncSearching;
|
|
UpdateNodeIncSearchingCell(IncSearchNode);
|
|
IncSearchNode := nil;
|
|
end;
|
|
|
|
function TcxTreeListController.DoSearch(AFromNode: TcxTreeListNode;
|
|
AItemIndex: Integer; const AText: string; AGoForward: Boolean): Boolean;
|
|
|
|
function DoSearchNode(AForward: Boolean; var ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
ANode := AFromNode;
|
|
Result := False;
|
|
while ANode <> nil do
|
|
begin
|
|
if DataCompareText(ANode.Texts[AItemIndex], AText, True) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
ANode := GetNextIncSearchNode(ANode, AForward);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
APrevFocusedNode: TcxTreeListNode;
|
|
begin
|
|
Result := DoSearchNode(AGoForward, ANode);
|
|
if not Result then
|
|
Result := DoSearchNode(not AGoForward, ANode);
|
|
APrevFocusedNode := TreeList.FocusedNode;
|
|
IsInIncSearchChanging := True;
|
|
if Result then
|
|
begin
|
|
try
|
|
if (ANode <> nil) then
|
|
begin
|
|
ANode.MakeVisible;
|
|
if ANode.IsVisible then
|
|
TreeList.FocusedNode := ANode
|
|
else
|
|
AFromNode.MakeVisible;
|
|
end;
|
|
finally
|
|
IsInIncSearchChanging := False;
|
|
end;
|
|
IncSearchNode := TreeList.FocusedNode;
|
|
UpdateNodeIncSearchingCell(TreeList.FocusedNode);
|
|
if APrevFocusedNode <> TreeList.FocusedNode then
|
|
UpdateNodeIncSearchingCell(APrevFocusedNode);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.GetIncSearchingItem: TcxCustomInplaceEditContainer;
|
|
begin
|
|
Result := TreeList.OptionsBehavior.IncSearchItem;
|
|
if Result = nil then
|
|
Result := TreeList.FocusedColumn;
|
|
end;
|
|
|
|
function TcxTreeListController.GetIncSearchingText: string;
|
|
begin
|
|
Result := IncSearchText;
|
|
end;
|
|
|
|
function TcxTreeListController.GetIsIncSearching: Boolean;
|
|
begin
|
|
Result := IncSearchText <> '';
|
|
end;
|
|
|
|
function TcxTreeListController.GetNextIncSearchNode(
|
|
ANode: TcxTreeListNode; AGoForward: Boolean): TcxTreeListNode;
|
|
begin
|
|
if ANode = nil then
|
|
Result := nil
|
|
else
|
|
if TreeList.OptionsBehavior.ExpandOnIncSearch then
|
|
begin
|
|
if AGoForward then
|
|
Result := ANode.GetNext
|
|
else
|
|
Result := ANode.GetPrev
|
|
end
|
|
else
|
|
Result := ANode.GetNextVisibleEx(not AGoForward);
|
|
end;
|
|
|
|
procedure TcxTreeListController.SearchCheck(AItemFound: Boolean);
|
|
begin
|
|
if not AItemFound and (IncSearchNode = nil) then
|
|
CancelIncSearching
|
|
else
|
|
if not AItemFound then
|
|
IncSearchingText := Copy(IncSearchingText, 1, Length(IncSearchingText) - 1);
|
|
end;
|
|
|
|
procedure TcxTreeListController.SearchLocate(
|
|
AItem: TcxCustomInplaceEditContainer; const Value: string);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if TreeList.FocusedNode <> nil then
|
|
ANode := TreeList.FocusedNode
|
|
else
|
|
ANode := TreeList.Nodes.Root.FFirst;
|
|
IncSearchText := Value;
|
|
if (AItem <> nil) and (ANode <> nil) then
|
|
SearchCheck(DoSearch(ANode, AItem.ItemIndex, IncSearchText, True));
|
|
end;
|
|
|
|
procedure TcxTreeListController.SearchLocateNext(
|
|
AItem: TcxCustomInplaceEditContainer; AForward: Boolean);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if (AItem <> nil) and (TreeList.FocusedNode <> nil) then
|
|
begin
|
|
ANode := GetNextIncSearchNode(TreeList.FocusedNode, AForward);
|
|
if ANode = nil then
|
|
ANode := TreeList.FocusedNode;
|
|
SearchCheck(DoSearch(ANode, AItem.ItemIndex, IncSearchText, AForward));
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.UpdateNodeIncSearchingCell(
|
|
ANode: TcxTreeListNode);
|
|
var
|
|
ANodeViewInfo: TcxTreeListNodeViewInfo;
|
|
ACellViewInfo: TcxTreeListEditCellViewInfo;
|
|
begin
|
|
if ANode <> nil then
|
|
begin
|
|
if TreeList.ViewInfo.NodesViewInfo.FindNodeViewInfo(ANode, ANodeViewInfo) then
|
|
begin
|
|
ACellViewInfo := GetCellFromViewInfo(TcxTreeListColumn(ItemForIncSearching), ANodeViewInfo);
|
|
if ACellViewInfo <> nil then ACellViewInfo.Invalidate(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.SelectionTimerHandler(ASender: TObject);
|
|
begin
|
|
// for I := 0 to
|
|
end;
|
|
|
|
function TcxTreeListController.CanCreateSelectionHelper: Boolean;
|
|
begin
|
|
Result := TreeList.IsDesigning and not TreeList.IsDestroying and not TreeList.IsLoading and
|
|
(cxDesignSelectionHelperClass <> nil) and TreeList.HandleAllocated;
|
|
end;
|
|
|
|
function TcxTreeListController.IsObjectSelected(AObject: TPersistent): Boolean;
|
|
var
|
|
AHelper: TcxCustomDesignSelectionHelper;
|
|
begin
|
|
Result := False;
|
|
if not CanCreateSelectionHelper then Exit;
|
|
AHelper := cxDesignSelectionHelperClass.Create(TreeList);
|
|
try
|
|
Result := AHelper.IsObjectSelected(AObject);
|
|
finally
|
|
AHelper.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.SelectObject(
|
|
AObject: TPersistent; AShift: TShiftState);
|
|
var
|
|
AHelper: TcxCustomDesignSelectionHelper;
|
|
begin
|
|
if not CanCreateSelectionHelper then Exit;
|
|
AHelper := cxDesignSelectionHelperClass.Create(TreeList);
|
|
try
|
|
AHelper.Select(AObject, AShift);
|
|
finally
|
|
AHelper.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.UnselectObject(AObject: TPersistent);
|
|
var
|
|
AHelper: TcxCustomDesignSelectionHelper;
|
|
begin
|
|
if not CanCreateSelectionHelper then Exit;
|
|
AHelper := cxDesignSelectionHelperClass.Create(TreeList);
|
|
try
|
|
AHelper.UnselectObject(AObject);
|
|
finally
|
|
AHelper.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.CancelSelection(KeepPrimary: Boolean = True);
|
|
begin
|
|
if TreeList.IsMultiSelect then
|
|
begin
|
|
TreeList.BeginUpdateSelection;
|
|
try
|
|
SelectionAnchorNode := nil;
|
|
Selection.Clear;
|
|
if (FocusedNode <> nil) and KeepPrimary and
|
|
(FocusedNode.RecordIndex < DataController.RecordCount) then
|
|
FocusedNode.Selected := True
|
|
finally
|
|
TreeList.EndUpdateSelection;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListController.Select(ANode: TcxTreeListNode; Shift: TShiftState);
|
|
|
|
procedure ValidateSelectionList(AIndex1, AIndex2: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AIndex1 > AIndex2 then
|
|
ValidateSelectionList(AIndex2, AIndex1)
|
|
else
|
|
begin
|
|
I := 0;
|
|
while I < Selection.Count do
|
|
begin
|
|
if cxInRange(TcxTreeListNode(Selection.List^[I]).VisibleIndex, AIndex1, AIndex2) then
|
|
Inc(I)
|
|
else
|
|
Selection.Delete(I);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure SelectRange(AToNode: TcxTreeListNode; IsAdd: Boolean);
|
|
var
|
|
AGoToForward: Boolean;
|
|
AIndex1, AIndex2: Integer;
|
|
AFromNode: TcxTreeListNode;
|
|
begin
|
|
AFromNode := SelectionAnchor;
|
|
AIndex1 := AToNode.VisibleIndex;
|
|
AIndex2 := AFromNode.VisibleIndex;
|
|
if not IsAdd then
|
|
ValidateSelectionList(AIndex1, AIndex2);
|
|
AGoToForward := AIndex1 < AIndex2;
|
|
TreeList.BeginUpdateSelection;
|
|
try
|
|
AFromNode.Selected := True;
|
|
while AFromNode <> AToNode do
|
|
begin
|
|
AFromNode := AFromNode.GetNextVisibleEx(AGoToForward);
|
|
AFromNode.Selected := True;
|
|
end;
|
|
finally
|
|
TreeList.EndUpdateSelection;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AShift: TShiftState;
|
|
begin
|
|
if not TreeList.IsMultiSelect then Exit;
|
|
if ANode = nil then
|
|
begin
|
|
TreeList.FocusedNode := nil;
|
|
Exit;
|
|
end;
|
|
if ANode.Selected and not (ssCtrl in Shift) and ((ANode = TreeList.TopVisibleNode) or
|
|
(ANode = TreeList.LastVisibleNode) or (TreeList.SelectionCount = 1)) then Exit;
|
|
if not ANode.IsVisible then Exit;
|
|
TreeList.BeginUpdateSelection;
|
|
try
|
|
AShift := [ssShift, ssCtrl] * Shift;
|
|
if AShift = [] then
|
|
CancelSelection
|
|
else
|
|
begin
|
|
if ssShift in AShift then
|
|
SelectRange(ANode, ssCtrl in Shift)
|
|
else
|
|
if (AShift = [ssCtrl]) and (ssLeft in Shift) then
|
|
ANode.Selected := not ANode.Selected;
|
|
if (ssCtrl in Shift) and ANode.Selected then
|
|
SelectionAnchorNode := ANode;
|
|
end;
|
|
finally
|
|
TreeList.EndUpdateSelection;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListController.GetResizeDirection: TcxDragSizingDirection;
|
|
begin
|
|
Result := ResizeDirection;
|
|
end;
|
|
|
|
procedure TcxTreeListController.MouseLeave;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited MouseLeave;
|
|
SetHotTrackNode(nil, []);
|
|
for I := 0 to TreeList.VisibleColumnCount - 1 do
|
|
TreeList.VisibleColumns[I].ViewInfo.ColumnHeader.UpdateState;
|
|
end;
|
|
|
|
procedure TcxTreeListController.DoCancelMode;
|
|
begin
|
|
inherited DoCancelMode;
|
|
if HitTest.FPressedHeader <> nil then
|
|
HitTest.FPressedHeader.Pressed := False;
|
|
SetHotTrackNode(nil, []);
|
|
end;
|
|
|
|
function TcxTreeListController.ValidateShift(Shift: TShiftState): TShiftState;
|
|
begin
|
|
if IsControllerEvent then
|
|
Result := CurrentShiftState
|
|
else
|
|
Result := Shift;
|
|
end;
|
|
|
|
procedure TcxTreeListController.UpdateRecord(ARecordIndex: Integer);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
ANode := GetNode(ARecordIndex);
|
|
if (ANode <> nil) and ANode.IsVisible and
|
|
TreeList.ViewInfo.NodesViewInfo.FindNodeViewInfo(ANode, AViewInfo) then
|
|
AViewInfo.Update(True);
|
|
end;
|
|
|
|
function TcxTreeListController.GetDataController: TcxControlDataController;
|
|
begin
|
|
Result := TcxControlDataController(TreeList.DataController);
|
|
end;
|
|
|
|
function TcxTreeListController.GetFocusedNode: TcxTreeListNode;
|
|
begin
|
|
Result := GetNode(FocusedRecordIndex);
|
|
end;
|
|
|
|
function TcxTreeListController.GetHitTest: TcxTreeListHitTest;
|
|
begin
|
|
Result := TreeList.HitTest;
|
|
end;
|
|
|
|
function TcxTreeListController.GetIsControllerEvent: Boolean;
|
|
begin
|
|
Result := IsControllerEventRefCount > 0;
|
|
end;
|
|
|
|
function TcxTreeListController.GetOptionsBehavior: TcxTreeListOptionsBehavior;
|
|
begin
|
|
Result := TreeList.OptionsBehavior;
|
|
end;
|
|
|
|
function TcxTreeListController.GetSelection: TList;
|
|
begin
|
|
Result := TreeList.FSelection;
|
|
end;
|
|
|
|
function TcxTreeListController.GetSelectionAnchor: TcxTreeListNode;
|
|
begin
|
|
Result := SelectionAnchorNode;
|
|
if Result = nil then
|
|
Result := FocusedNode;
|
|
while (Result <> nil) and not Result.IsVisible do
|
|
Result := Result.Parent;
|
|
end;
|
|
|
|
function TcxTreeListController.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(EditingControl);
|
|
end;
|
|
|
|
procedure TcxTreeListController.SetIsControllerEvent(Value: Boolean);
|
|
begin
|
|
if Value then
|
|
Inc(IsControllerEventRefCount)
|
|
else
|
|
Dec(IsControllerEventRefCount);
|
|
end;
|
|
|
|
procedure TcxTreeListController.SetFocusedNode(ANode: TcxTreeListNode);
|
|
begin
|
|
if ANode <> nil then
|
|
FocusedRecordIndex := ANode.RecordIndex
|
|
else
|
|
FocusedRecordIndex := cxInvalidIndex;
|
|
end;
|
|
|
|
{ TcxTreeListViewInfoItem }
|
|
|
|
constructor TcxTreeListViewInfoItem.Create(AOwner: TObject);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FBrush := TBrush.Create;
|
|
end;
|
|
|
|
destructor TcxTreeListViewInfoItem.Destroy;
|
|
begin
|
|
FBrush.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfoItem.Calculate(const ADisplayRect, AVisibleRect: TRect);
|
|
begin
|
|
CheckClipping(ADisplayRect, AVisibleRect);
|
|
DoCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfoItem.DoHorzOffset(AShift: Integer);
|
|
begin
|
|
// do nothing
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfoItem.DoCalculate;
|
|
begin
|
|
FBrush.Color := ViewParams.Color;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfoItem.DoVertOffset(AShift: Integer);
|
|
begin
|
|
// do nothing
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.ShiftItem(
|
|
const AVisibleRect: TRect; DX, DY: Integer): Boolean;
|
|
begin
|
|
Result := Visible;
|
|
CheckClipping(cxRectOffset(DisplayRect, DX, DY), AVisibleRect);
|
|
Result := Result = Visible;
|
|
if not Result and Visible then
|
|
DoCalculate;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
Result := 0
|
|
else
|
|
Result := cxE_NOINTERFACE;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem._AddRef: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem._Release: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.GetBrushManager: TcxBrushCache;
|
|
begin
|
|
Result := TreeList.BrushCache;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.GetControlViewInfo: TcxTreeListViewInfo;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetControl).ViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.GetHitTestProp: TcxTreeListHitTest;
|
|
begin
|
|
Result := TreeList.HitTest;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.GetOptionsView: TcxTreeListOptionsView;
|
|
begin
|
|
Result := TreeList.OptionsView;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.GetPainterClass: TcxCustomLookAndFeelPainterClass;
|
|
begin
|
|
Result := TreeList.LookAndFeelPainter;
|
|
end;
|
|
|
|
function TcxTreeListViewInfoItem.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetControl);
|
|
end;
|
|
|
|
{ TcxTreeListIndicatorViewInfo }
|
|
|
|
procedure TcxTreeListIndicatorViewInfo.Calculate(
|
|
const ADisplayRect, AVisibleRect: TRect);
|
|
begin
|
|
if not OptionsView.Indicator then Exit;
|
|
with ADisplayRect, ControlViewInfo do
|
|
begin
|
|
CheckClipping(cxRect(BorderSize, Top,
|
|
BorderSize + OptionsView.IndicatorWidth, Bottom), AVisibleRect);
|
|
end;
|
|
if Visible then DoCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListIndicatorViewInfo.DoCalculate;
|
|
begin
|
|
ItemViewParams := TcxTreeListViewInfo(ControlViewInfo).IndicatorViewParams;
|
|
end;
|
|
|
|
procedure TcxTreeListIndicatorViewInfo.DoVertOffset(AShift: Integer);
|
|
begin
|
|
CheckClipping(cxRectOffset(DisplayRect, 0, AShift),
|
|
ControlViewInfo.NodesViewInfo.ClipRect);
|
|
end;
|
|
|
|
function TcxTreeListIndicatorViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := TcxTreeListViewInfo(Owner).TreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListIndicatorViewInfo.UpdateKind(AKind: TcxIndicatorKind);
|
|
begin
|
|
if AKind <> FKind then
|
|
begin
|
|
FKind := AKind;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListFooterItemViewInfo }
|
|
|
|
procedure TcxTreeListFooterItemViewInfo.DoHorzOffset(DX: Integer);
|
|
begin
|
|
ShiftItem(BandViewInfo.FooterRect, DX, 0);
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := Column.GetTreeList;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetAlignHorz: TAlignment;
|
|
begin
|
|
Result := FooterSummary.FAlignHorz;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetAlignVert: TcxAlignmentVert;
|
|
begin
|
|
Result := FooterSummary.FAlignVert;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetBandViewInfo: TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := Column.BandViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetColumn: TcxTreeListColumnViewInfo;
|
|
begin
|
|
Result := TcxTreeListColumnViewInfo(Owner);
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetFooterSummary: TcxTreeListColumnSummaryFooter;
|
|
begin
|
|
Result := Column.Column.SummaryFooter;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetMultiLine: Boolean;
|
|
begin
|
|
Result := FooterSummary.MultiLine;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetText: string;
|
|
begin
|
|
Result := FooterSummary.SummaryText;
|
|
end;
|
|
|
|
function TcxTreeListFooterItemViewInfo.GetVisible: Boolean;
|
|
begin
|
|
Result := inherited Visible and Column.Column.Options.Footer;
|
|
end;
|
|
|
|
{ TcxTreeListHeaderViewInfo }
|
|
|
|
destructor TcxTreeListHeaderViewInfo.Destroy;
|
|
begin
|
|
if (TreeList <> nil) and (TreeList.HitTest.FPressedHeader = Self) then
|
|
TreeList.HitTest.FPressedHeader := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.ButtonStateChanged(
|
|
APrevIsPressed, IsPressed: Boolean);
|
|
begin
|
|
if APrevIsPressed and not IsPressed then
|
|
TreeList.DoBandHeaderClick(Band);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.CanDropAt(const P: TPoint): Boolean;
|
|
begin
|
|
HitTest.HitPoint := P;
|
|
with HitTest do
|
|
Result := HitAtBand and
|
|
PtInRect(cxRectInflate(HitBand.ViewInfo.ClipRect, 0, 0, 0, cxtlScrollDelta), P);
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.DoCalculate;
|
|
begin
|
|
if not Visible then Exit;
|
|
FTextBounds := DisplayRect;
|
|
FTextBounds := cxRectInflate(DisplayRect,
|
|
-cxHeaderTextOffset, -cxHeaderTextOffset);
|
|
with LookAndFeelPainter do
|
|
begin
|
|
if SortOrder <> soNone then
|
|
begin
|
|
FSortMarkBounds := FTextBounds;
|
|
FSortMarkBounds.Left := FSortMarkBounds.Right - SortingMarkAreaSize.X;
|
|
FTextBounds.Right := FSortMarkBounds.Left - cxHeaderTextOffset;
|
|
end;
|
|
end;
|
|
InflateRect(FTextBounds, -1, 0);
|
|
DoCalculateGlyphPosition;
|
|
FBorders := cxBordersAll;
|
|
FState := GetButtonState;
|
|
inherited DoCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.DoCalculateGlyphPosition;
|
|
var
|
|
AWidth, AHeight: Integer;
|
|
begin
|
|
if Glyph.Empty then Exit;
|
|
AWidth := Glyph.Width;
|
|
AHeight := Glyph.Height;
|
|
case GlyphAlignHorz of
|
|
taLeftJustify:
|
|
begin
|
|
FGlyphPos.X := FTextBounds.Left;
|
|
Inc(FTextBounds.Left, AWidth + cxHeaderTextOffset);
|
|
end;
|
|
taRightJustify:
|
|
begin
|
|
Dec(FTextBounds.Right, AWidth);
|
|
FGlyphPos.X := FTextBounds.Right;
|
|
Dec(FTextBounds.Right, cxHeaderTextOffset);
|
|
end;
|
|
taCenter:
|
|
with FTextBounds do
|
|
FGlyphPos.X := (Left + Right - AWidth) div 2;
|
|
end;
|
|
case GlyphAlignVert of
|
|
vaTop:
|
|
FGlyphPos.Y := FTextBounds.Top;
|
|
vaBottom:
|
|
FGlyphPos.Y := FTextBounds.Bottom - AHeight;
|
|
vaCenter:
|
|
with FTextBounds do
|
|
FGlyphPos.Y := (Bottom + Top - AHeight) div 2;
|
|
end;
|
|
with ClipRect do
|
|
NeedGlyphClipping := not cxInRange(FGlyphPos.X, Left, Right - AWidth) or
|
|
not cxInRange(FGlyphPos.Y, Top, Bottom - AHeight);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetDisplayRect: TRect;
|
|
begin
|
|
Result := DisplayRect;
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.DoHorzOffset(DX: Integer);
|
|
begin
|
|
if ShiftItem(BandViewInfo.ClipRect, DX, 0) then
|
|
begin
|
|
cxOffsetHorz(FSortMarkBounds, DX);
|
|
cxOffsetHorz(FTextBounds, DX);
|
|
Inc(FGlyphPos.X, DX);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetDroppingRect: TRect;
|
|
begin
|
|
with ControlViewInfo, ClientRect do
|
|
Result := Rect(ContentOffset, GetBorderSize, Right, HeaderOffset);
|
|
InflateRect(Result, 0, cxtlScrollDelta);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetDragSizing: IcxDragSizing;
|
|
begin
|
|
Supports(TObject(BandViewInfo.Band), IcxDragSizing, Result);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := BandViewInfo.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetSelected: Boolean;
|
|
begin
|
|
Result := TreeList.Controller.IsObjectSelected(Band);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetSortOrder: TcxDataSortOrder;
|
|
begin
|
|
Result := soNone;
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.InitViewParams;
|
|
begin
|
|
ItemViewParams := TreeList.Styles.GetBandHeaderParams(Band);
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.UpdateState;
|
|
begin
|
|
if GetButtonState <> FState then
|
|
begin
|
|
FState := GetButtonState;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetOrigin: TPoint;
|
|
begin
|
|
Result := DisplayRect.TopLeft;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.IsNeedHint(ACanvas: TcxCanvas;
|
|
const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean;
|
|
out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean;
|
|
var
|
|
R: TRect;
|
|
AFlags: Integer;
|
|
begin
|
|
if FCallHintNeeded >= 1 then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
Inc(FCallHintNeeded);
|
|
AText := Text;
|
|
try
|
|
AFlags := cxAlignTop or cxAlignLeft or cxDontPrint;
|
|
if AIsMultiLine then
|
|
AFlags := AFlags or cxWordBreak;
|
|
ACanvas.Font := ViewParams.Font;
|
|
R := TextBounds;
|
|
ACanvas.TextExtent(Text, R, AFlags);
|
|
AIsMultiLine := MultiLine;
|
|
Result := not HitTest.CanSizing and PtInRect(TextBounds, P) and
|
|
(cxRectWidth(R) > cxRectWidth(TextBounds)) or
|
|
(cxRectHeight(R) > cxRectHeight(TextBounds));
|
|
finally
|
|
Dec(FCallHintNeeded);
|
|
AText := Text;
|
|
ATextRect := R;
|
|
IsNeedOffsetHint := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.UpdateHotTrackState(const APoint: TPoint);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.CustomDrawEvent(
|
|
var AEvent: TcxCustomDrawViewInfoItemEvent);
|
|
begin
|
|
AEvent := TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawBandHeader);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetAlignHorz: TAlignment;
|
|
begin
|
|
Result := Caption.FAlignHorz;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetAlignVert: TcxAlignmentVert;
|
|
begin
|
|
Result := Caption.FAlignVert;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetBand: TcxTreeListBand;
|
|
begin
|
|
Result := BandViewInfo.Band;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetBandViewInfo: TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := TcxTreeListBandViewInfo(Owner);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetCaption: TcxTreeListCaption;
|
|
begin
|
|
Result := BandViewInfo.Band.Caption;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetButtonState: TcxButtonState;
|
|
begin
|
|
Result := cxbsDefault;
|
|
with TreeList do
|
|
begin
|
|
if Pressed then
|
|
Result := cxbsPressed
|
|
else
|
|
if GetHotTrack then Result := cxbsHot;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetGlyph: TBitmap;
|
|
begin
|
|
Result := Caption.Glyph;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetGlyphAlignHorz: TAlignment;
|
|
begin
|
|
Result := Caption.GlyphAlignHorz;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetGlyphAlignVert: TcxAlignmentVert;
|
|
begin
|
|
Result := Caption.GlyphAlignVert;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetHotTrack: Boolean;
|
|
begin
|
|
Result := LookandFeelPainter.IsHeaderHotTrack and
|
|
(TreeList.DragAndDropState <> ddsInProcess) and
|
|
(TreeList.HitTest.HitTestItem = Self);
|
|
if Result then
|
|
begin
|
|
TreeList.HitTest.HitPoint := TreeList.ScreenToClient(GetMouseCursorPos);
|
|
Result := TreeList.HitTest.HitTestItem = Self;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := Caption.GetState(Index);
|
|
end;
|
|
|
|
function TcxTreeListHeaderViewInfo.GetText: string;
|
|
begin
|
|
Result := Caption.Text;
|
|
end;
|
|
|
|
procedure TcxTreeListHeaderViewInfo.SetPressed(Value: Boolean);
|
|
begin
|
|
if (Self = nil) or (TreeList = nil) or
|
|
(TreeList.HitTest = nil) or (Value = FPressed) then Exit;
|
|
with TreeList.HitTest do
|
|
begin
|
|
FPressed := Value;
|
|
if FPressed and (FPressedHeader <> Self) then
|
|
begin
|
|
if FPressedHeader <> nil then FPressedHeader.Pressed := False;
|
|
FPressedHeader := Self;
|
|
end;
|
|
end;
|
|
ButtonStateChanged(not FPressed, Value);
|
|
UpdateState;
|
|
end;
|
|
|
|
{ TcxTreeListColumnHeaderViewInfo }
|
|
|
|
procedure TcxTreeListColumnHeaderViewInfo.ButtonStateChanged(
|
|
APrevIsPressed, IsPressed: Boolean);
|
|
const
|
|
ASortOrders: array[TcxDataSortOrder] of TcxDataSortOrder =
|
|
(soAscending, soDescending, soAscending);
|
|
begin
|
|
with TreeList.Controller do
|
|
begin
|
|
if APrevIsPressed and not IsPressed and not IsDragDropProcess and not IsDblClick then
|
|
DoChangeColumnSortOrder(Column, ASortOrders[Column.SortOrder], []);
|
|
if APrevIsPressed and not IsPressed and not IsDragDropProcess then
|
|
TreeList.DoColumnHeaderClick(Column);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.CanDropAt(const P: TPoint): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnHeaderViewInfo.DoCalculate;
|
|
begin
|
|
inherited DoCalculate;
|
|
FIsUltraFlat := not OptionsView.IsExtPaintStyle and
|
|
(Painter.HeaderBorders([nLeft, nRight]) <> cxBordersAll);
|
|
with Column do
|
|
begin
|
|
if not IsLeft then FNeighbors := [nLeft];
|
|
if not IsRight then FNeighbors := [nRight];
|
|
with GetDisplayRect do
|
|
begin
|
|
if (ClipRect.Left = DisplayRect.Left) and (DisplayRect.Left <> Left) then
|
|
ClipRect.Left := Left;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := Column.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetDisplayRect: TRect;
|
|
begin
|
|
Result := inherited GetDisplayRect;
|
|
if FIsUltraFlat and not Column.IsLeft then Dec(Result.Left);
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetDragSizing: IcxDragSizing;
|
|
begin
|
|
Supports(TObject(Column), IcxDragSizing, Result);
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetDroppingRect: TRect;
|
|
begin
|
|
with ControlViewInfo, ClientRect do
|
|
Result := Rect(ContentOffset, HeaderOffset, Right, CellsOffset);
|
|
InflateRect(Result, 0, cxtlScrollDelta);
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetSortOrder: TcxDataSortOrder;
|
|
begin
|
|
Result := Column.GetRealSortOrder;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnHeaderViewInfo.InitViewParams;
|
|
begin
|
|
ItemViewParams := TreeList.Styles.GetColumnHeaderParams(Column)
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetSelected: Boolean;
|
|
begin
|
|
Result := TreeList.Controller.IsObjectSelected(Column);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnHeaderViewInfo.CustomDrawEvent(
|
|
var AEvent: TcxCustomDrawViewInfoItemEvent);
|
|
begin
|
|
AEvent := TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawHeaderCell);
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetBandViewInfo: TcxTreeListBandViewInfo;
|
|
begin
|
|
if not Column.Visible then
|
|
Result := nil
|
|
else
|
|
Result := TcxTreeListColumnViewInfo(Owner).BandViewInfo
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetCaption: TcxTreeListCaption;
|
|
begin
|
|
Result := Column.Caption;
|
|
end;
|
|
|
|
function TcxTreeListColumnHeaderViewInfo.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumnViewInfo(Owner).Column;
|
|
end;
|
|
|
|
{ TcxTreeListColumnHeaderViewInfo }
|
|
|
|
constructor TcxTreeListColumnViewInfo.Create(AOwner: TcxTreeListColumn);
|
|
begin
|
|
FColumn := AOwner;
|
|
FColumnHeader := TcxTreeListColumnHeaderViewInfo.Create(Self);
|
|
FColumnFooter := TcxTreeListFooterItemViewInfo.Create(Self);
|
|
end;
|
|
|
|
destructor TcxTreeListColumnViewInfo.Destroy;
|
|
begin
|
|
FreeAndNil(FColumnFooter);
|
|
FreeAndNil(FColumnHeader);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.CalcHeaderRect: TRect;
|
|
begin
|
|
with TreeList, ViewInfo, Result do
|
|
begin
|
|
Result.TopLeft := Point(XOfs, HeaderOffset + YOfs * HeaderLineHeight);
|
|
with Column.Position do
|
|
Result := cxRectSetSize(Result, DisplayWidth, LineCount * HeaderLineHeight);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.CalcFooterRect: TRect;
|
|
|
|
function GetWidth: Integer;
|
|
begin
|
|
with Column, TreeList.LookAndFeelPainter do
|
|
Result := DisplayWidth - Byte(IsLeftMost or IsRightMost) * FooterBorderSize;
|
|
end;
|
|
|
|
begin
|
|
with TreeList, ViewInfo, LookAndFeelPainter, Result do
|
|
begin
|
|
TopLeft := Point(XOfs + Byte(Column.IsLeftMost) * FooterBorderSize, FooterCellsOffset);
|
|
Right := Left + GetWidth;
|
|
Bottom := Top + Column.Position.LineCount * FooterLineHeight;
|
|
InflateRect(Result, -FooterCellOffset, -FooterCellOffset);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListColumnViewInfo.DoCalculate;
|
|
begin
|
|
if OptionsView.Headers then
|
|
FColumnHeader.Calculate(CalcHeaderRect, BandViewInfo.ClipRect);
|
|
if OptionsView.Footer then
|
|
FColumnFooter.Calculate(CalcFooterRect, BandViewInfo.FooterRect);
|
|
end;
|
|
|
|
procedure TcxTreeListColumnViewInfo.DoHorzOffset(DX: Integer);
|
|
begin
|
|
if OptionsView.Headers then
|
|
FColumnHeader.DoHorzOffset(DX);
|
|
if OptionsView.Footer and (TreeList.VisibleColumnCount > 0) then
|
|
FColumnFooter.DoHorzOffset(DX);
|
|
Inc(XOfs, DX);
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.GetBandViewInfo: TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := Column.OwnerBand.ViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.GetDisplayWidth: Integer;
|
|
begin
|
|
Result := Column.DisplayWidth;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.GetFooterCellsOffset: Integer;
|
|
begin
|
|
with TreeList, ViewInfo, LookAndFeelPainter do
|
|
Result := FooterOffset + FooterBorderSize + YOfs * FooterLineHeight;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.GetLineCount: Integer;
|
|
begin
|
|
Result := Column.Position.LineCount;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.GetOptionsView: TcxTreeListOptionsView;
|
|
begin
|
|
Result := TreeList.OptionsView;
|
|
end;
|
|
|
|
function TcxTreeListColumnViewInfo.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := FColumn.TreeList;
|
|
end;
|
|
|
|
{ TcxTreeListBandViewInfo }
|
|
|
|
constructor TcxTreeListBandViewInfo.Create(AOwner: TObject);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FBandHeader := TcxTreeListHeaderViewInfo.Create(Self);
|
|
FooterBrush := TBrush.Create;
|
|
ContainerBrush := TBrush.Create;
|
|
end;
|
|
|
|
destructor TcxTreeListBandViewInfo.Destroy;
|
|
begin
|
|
FreeAndNil(FBandHeader);
|
|
FreeMem(FColumns);
|
|
FooterBrush.Free;
|
|
ContainerBrush.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListBandViewInfo.CalcFooterRect;
|
|
begin
|
|
FFooterRect := ControlViewInfo.FooterRect;
|
|
FFooterRect.Left := ClipRect.Left;
|
|
FFooterRect.Right := ClipRect.Right;
|
|
end;
|
|
|
|
procedure TcxTreeListBandViewInfo.CheckOpaque;
|
|
var
|
|
I, ALines: Integer;
|
|
|
|
function CheckRow(ARow: TcxTreeListBandRow): Integer;
|
|
var
|
|
J: Integer;
|
|
begin
|
|
Result := MaxInt div 20;
|
|
for J := 0 to ARow.Count - 1 do
|
|
Result := cxMin(Result, ARow[J].Position.LineCount);
|
|
end;
|
|
|
|
begin
|
|
with Band.BandRows do
|
|
begin
|
|
ALines := 0;
|
|
IsOpaque := ColumnCount > 0;
|
|
if IsOpaque then
|
|
for I := 0 to Count - 1 do Inc(ALines, CheckRow(Items[I]));
|
|
end;
|
|
IsOpaque := IsOpaque and (ALines = TreeList.HeaderLineCount);
|
|
end;
|
|
|
|
procedure TcxTreeListBandViewInfo.DoCalculate;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if Self = nil then Exit;
|
|
ContainerBrush.Color := ContainerViewParams.Color;
|
|
FFooterViewParams := TreeList.Styles.GetBandFooterParams(Band);
|
|
FooterBrush.Color := FFooterViewParams.Color;
|
|
if OptionsView.Bands then
|
|
begin
|
|
BandHeader.ItemViewParams := ItemViewParams;
|
|
R := DisplayRect;
|
|
R.Bottom := ControlViewInfo.HeaderOffset;
|
|
BandHeader.Calculate(R, ClipRect);
|
|
end;
|
|
CalcFooterRect;
|
|
DoCalculateColumns;
|
|
end;
|
|
|
|
procedure TcxTreeListBandViewInfo.DoCalculateColumns;
|
|
var
|
|
I, J, AOfs: Integer;
|
|
|
|
procedure AddColumnViewInfo(AViewInfo: TcxTreeListColumnViewInfo; YOfs: Integer);
|
|
begin
|
|
AViewInfo.XOfs := AOfs;
|
|
AViewInfo.YOfs := YOfs;
|
|
FColumns[FCount] := AViewInfo;
|
|
Inc(FCount);
|
|
Inc(AOfs, AViewInfo.DisplayWidth);
|
|
AViewInfo.DoCalculate;
|
|
end;
|
|
|
|
begin
|
|
SetCapacity(Band.FColumns.Count);
|
|
FCount := 0;
|
|
for I := 0 to Band.BandRows.Count - 1 do
|
|
begin
|
|
with Band.BandRows[I] do
|
|
begin
|
|
AOfs := DisplayRect.Left;
|
|
for J := 0 to Count - 1 do
|
|
AddColumnViewInfo(Items[J].ViewInfo, LineOffset);
|
|
end;
|
|
end;
|
|
IsOpaque := False;
|
|
CheckOpaque;
|
|
end;
|
|
|
|
procedure TcxTreeListBandViewInfo.DoHorzOffset(DX: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if ShiftItem(ControlViewInfo.ScrollingArea, DX, 0) then
|
|
begin
|
|
CalcFooterRect;
|
|
if OptionsView.Bands then
|
|
BandHeader.DoHorzOffset(DX);
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].DoHorzOffset(DX);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListBandViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := Band.GetTreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListBandViewInfo.SetCapacity(ACapacity: Integer);
|
|
begin
|
|
if ACapacity > FCapacity then
|
|
begin
|
|
FCapacity := ACapacity;
|
|
ReallocMem(FColumns, FCapacity * SizeOf(Pointer));
|
|
end;
|
|
FCount := 0;
|
|
end;
|
|
|
|
function TcxTreeListBandViewInfo.GetBand: TcxTreeListBand;
|
|
begin
|
|
Result := TcxTreeListBand(Owner);
|
|
end;
|
|
|
|
function TcxTreeListBandViewInfo.GetColumn(AIndex: Integer): TcxTreeListColumnViewInfo;
|
|
begin
|
|
Result := TcxTreeListColumnViewInfo(FColumns^[AIndex]);
|
|
end;
|
|
|
|
function TcxTreeListBandViewInfo.GetDisplayWidth: Integer;
|
|
begin
|
|
Result := Band.DisplayWidth;
|
|
end;
|
|
|
|
function TcxTreeListBandViewInfo.GetFixed: TcxTreeListBandFixedKind;
|
|
begin
|
|
Result := Band.FixedKind;
|
|
end;
|
|
|
|
{ TcxTreeListEditCellViewInfo }
|
|
|
|
procedure TcxTreeListEditCellViewInfo.Assign(Source: TcxCustomViewInfoItem);
|
|
begin
|
|
if Source is TcxTreeListEditCellViewInfo then
|
|
begin
|
|
GroupIndex := TcxTreeListEditCellViewInfo(Source).GroupIndex;
|
|
FColumnViewInfo := TcxTreeListEditCellViewInfo(Source).FColumnViewInfo;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.ContentOffset: TRect;
|
|
begin
|
|
Result := cxTreeListEditCellContentOffset;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.ChangedHeight(
|
|
APrevHeight, ANewHeight: Integer): Boolean;
|
|
begin
|
|
Result := inherited ChangedHeight(APrevHeight, ANewHeight);
|
|
with NodeViewInfo do
|
|
begin
|
|
if Result and (APrevHeight = CellsMaxHeight) then
|
|
Dec(CellMaxHeightRefCount);
|
|
Result := Result or (ANewHeight > CellsMaxHeight) or (CellMaxHeightRefCount = 0);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.CustomDrawEvent(
|
|
var AEvent: TcxCustomDrawViewInfoItemEvent);
|
|
begin
|
|
AEvent := TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawCell);
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.DoHorzOffset(AShift: Integer);
|
|
begin
|
|
ShiftItem(AShift, 0);
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.DoVertOffset(AShift: Integer);
|
|
begin
|
|
ShiftItem(0, AShift);
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
if FColumnViewInfo = nil then
|
|
Result := nil
|
|
else
|
|
Result := FColumnViewInfo.FColumn;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetButtonTransparency: TcxEditButtonTransparency;
|
|
var
|
|
B1: TcxEditingControlEditShowButtons;
|
|
B2: TcxEditItemShowEditButtons;
|
|
AFocused: Boolean;
|
|
begin
|
|
AFocused := Node = TreeList.FocusedNode;
|
|
B1 := TreeList.OptionsView.ShowEditButtons;
|
|
B2 := Column.Options.ShowEditButtons;
|
|
if (B2 = eisbAlways) or (B2 = eisbDefault) and
|
|
((B1 = ecsbAlways) or (B1 = ecsbFocused) and AFocused) then
|
|
Result := ebtNone
|
|
else
|
|
Result := ebtHideInactive;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetDisplayValue: Variant;
|
|
begin
|
|
Result := Column.DoOnGetDisplayText(Node, False, True);
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetEditContainer: TcxCustomInplaceEditContainer;
|
|
begin
|
|
if TreeList.IsDestroying then
|
|
Result := nil
|
|
else
|
|
Result := Column;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetEditViewParams: TcxViewParams;
|
|
begin
|
|
GetTreeListEditCellParams(Result);
|
|
if Selected then
|
|
with ControlViewInfo.SelectionParams do
|
|
begin
|
|
Result.TextColor := TextColor;
|
|
if TreeList.Styles.SelectionFontAssigned then
|
|
Result.Font := Font;
|
|
Result.Color := Color;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetFocused: Boolean;
|
|
begin
|
|
Result := NodeViewInfo.Selected;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetHotTrack: Boolean;
|
|
begin
|
|
Result := Node.HotTrack;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetLineCount: Integer;
|
|
begin
|
|
Result := FColumnViewInfo.LineCount;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetLineOffset: Integer;
|
|
begin
|
|
Result := FColumnViewInfo.YOfs;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetRecordIndex: Integer;
|
|
begin
|
|
Result := Node.RecordIndex;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetSelected: Boolean;
|
|
begin
|
|
Result := Focused;
|
|
with TreeList, OptionsSelection do
|
|
begin
|
|
if NodeViewInfo.Focused then
|
|
begin
|
|
if Result and CellSelect then
|
|
begin
|
|
Result := Result and ((InvertSelect and not Column.Focused) or
|
|
(not InvertSelect and Column.Focused and not Column.Editing));
|
|
if not InvertSelect and Result then
|
|
NodeViewInfo.NodeFocusedCell := Self;
|
|
if Result and (HideSelection and not IsFocused) then
|
|
Result := False;
|
|
end
|
|
else
|
|
Result := Result and InvertSelect;
|
|
if HideSelection and not IsFocused then
|
|
Result := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetSelectedTextColor: Integer;
|
|
begin
|
|
Result := IncSearchParams.TextColor;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetSelectedBKColor: Integer;
|
|
begin
|
|
Result := IncSearchParams.Color
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.GetTreeListEditCellParams(
|
|
var AParams: TcxViewParams);
|
|
begin
|
|
TreeList.Styles.DoGetContentParams(Node, Column, AParams);
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetViewInfoData: Pointer;
|
|
begin
|
|
Result := Node;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.IncSearchParams: TcxViewParams;
|
|
begin
|
|
Result := TreeList.Styles.GetIncSearchParams;
|
|
if Result.Color = clDefault then
|
|
Result.Color := inherited GetSelectedBKColor;
|
|
if Result.TextColor = clDefault then
|
|
Result.TextColor := inherited GetSelectedTextColor;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.IsAutoHeight: Boolean;
|
|
begin
|
|
Result := NodeViewInfo.Owner.IsRowAutoHeight;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.IsEndEllipsis: Boolean;
|
|
begin
|
|
Result := inherited IsEndEllipsis and Column.Options.CellEndEllipsis;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.IsTransparent: Boolean;
|
|
begin
|
|
Result := inherited IsTransparent and not Selected;
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.SetPosition(
|
|
ATop, AHeight: Integer; const AClipRect: TRect);
|
|
begin
|
|
if not IsAutoHeight then
|
|
begin
|
|
AHeight := cxRectHeight(DisplayRect);
|
|
ATop := ATop - NodeViewInfo.Top + DisplayRect.Top;
|
|
end;
|
|
cxRectSetTopEx(DisplayRect, ATop, AHeight);
|
|
CheckClipping(DisplayRect, AClipRect);
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.ShiftItem(DX, DY: Integer);
|
|
begin
|
|
CheckClipping(cxRectOffset(DisplayRect, DX, DY), Group.ClipRect);
|
|
UpdateViewInfoPosition;
|
|
end;
|
|
|
|
procedure TcxTreeListEditCellViewInfo.UpdateViewInfoPosition;
|
|
begin
|
|
if ViewInfo <> nil then
|
|
begin
|
|
ViewInfo.Top := DisplayRect.Top + Byte(bTop in Borders);
|
|
ViewInfo.Left := DisplayRect.Left + Byte(bLeft in Borders);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetBand: TcxTreeListBand;
|
|
begin
|
|
Result := Column.OwnerBand;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetControlViewInfo: TcxTreeListViewInfo;
|
|
begin
|
|
Result := TreeList.ViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetEditRect: TRect;
|
|
begin
|
|
Result := CellEditRect;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetGroup: TcxTreeListCellsGroupViewInfo;
|
|
begin
|
|
Result := NodeViewInfo.Groups[GroupIndex]
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetNode: TcxTreeListNode;
|
|
begin
|
|
Result := NodeViewInfo.Node;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
begin
|
|
Result := NodeViewInfo.Owner;
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetNodeViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := TcxTreeListNodeViewInfo(Owner);
|
|
end;
|
|
|
|
function TcxTreeListEditCellViewInfo.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := NodeViewInfo.TreeList;
|
|
end;
|
|
|
|
{ TcxTreeListCellsGroupViewInfo }
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.Assign(Source: TcxCustomViewInfoItem);
|
|
begin
|
|
if Source is TcxTreeListViewInfoItem then
|
|
begin
|
|
BandViewInfo := TcxTreeListCellsGroupViewInfo(Source).BandViewInfo;
|
|
Borders := TcxTreeListCellsGroupViewInfo(Source).Borders;
|
|
Indent := TcxTreeListCellsGroupViewInfo(Source).Indent;
|
|
FirstIndex := TcxTreeListCellsGroupViewInfo(Source).FirstIndex;
|
|
LastIndex := TcxTreeListCellsGroupViewInfo(Source).LastIndex;
|
|
IsOpaque := TcxTreeListCellsGroupViewInfo(Source).IsOpaque;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.DoCalculate;
|
|
begin
|
|
if not IsOpaque then inherited DoCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.DoCalculateCellsLayout;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to CellCount - 1 do
|
|
CalculateEditCellRect(Cells[I], BandViewInfo.DisplayRect.Left);
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.DoHorzOffset(AShift: Integer);
|
|
begin
|
|
ShiftGroup(AShift, 0);
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.DoVertOffset(AShift: Integer);
|
|
begin
|
|
ShiftGroup(0, AShift);
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := NodeViewInfo.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetHotTrack: Boolean;
|
|
begin
|
|
Result := NodeViewInfo.Node.HotTrack;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetSelected: Boolean;
|
|
begin
|
|
with TreeList, OptionsSelection do
|
|
begin
|
|
Result := NodeViewInfo.Selected and InvertSelect and
|
|
((HideSelection and Focused) or not HideSelection);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetGroupBitmap: TBitmap;
|
|
begin
|
|
if Selected then
|
|
Result := nil
|
|
else
|
|
Result := ViewParams.Bitmap;
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.SetSize(ATop, AHeight: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CheckClipping(cxRectSetTop(DisplayRect, ATop, AHeight),
|
|
NodeViewInfo.NodeClipRect);
|
|
with TcxTreeListNodeViewInfo(Owner), FCells do
|
|
begin
|
|
for I := FirstIndex to LastIndex - 1 do
|
|
TcxTreeListEditCellViewInfo(List^[I]).SetPosition(
|
|
NodeCellsOffset, CellsMaxHeight, ClipRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.ShiftGroup(DX, DY: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
CheckClipping(cxRectOffset(DisplayRect, DX, DY), NodeViewInfo.GetVisibleRect(Fixed));
|
|
for I := 0 to CellCount - 1 do
|
|
Cells[I].ShiftItem(DX, DY);
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetBand: TcxTreeListBand;
|
|
begin
|
|
Result := BandViewInfo.Band;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetCell(Index: Integer): TcxTreeListEditCellViewInfo;
|
|
begin
|
|
Result :=
|
|
TcxTreeListEditCellViewInfo(TcxTreeListNodeViewInfo(Owner).FCells.List^[FirstIndex + Index]);
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetCellsHeight: Integer;
|
|
begin
|
|
Result := ControlViewInfo.DefaultHeight;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetCount: Integer;
|
|
begin
|
|
Result := LastIndex - FirstIndex;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetCurrentBrush: TBrush;
|
|
begin
|
|
with TreeList.OptionsSelection do
|
|
begin
|
|
if Selected then
|
|
Result := ControlViewInfo.SelectionBrush
|
|
else
|
|
Result := Brush;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetFixed: Boolean;
|
|
begin
|
|
Result := Band.FixedKind <> tlbfNone;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetNodeViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := TcxTreeListNodeViewInfo(Owner);
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
begin
|
|
Result := NodeViewInfo.Owner;
|
|
end;
|
|
|
|
function TcxTreeListCellsGroupViewInfo.GetNode: TcxTreeListNode;
|
|
begin
|
|
Result := NodeViewInfo.Node;
|
|
end;
|
|
|
|
procedure TcxTreeListCellsGroupViewInfo.CalculateEditCellRect(
|
|
ACell: TcxTreeListEditCellViewInfo; AMostLeftPos: Integer);
|
|
var
|
|
AOfs: Integer;
|
|
begin
|
|
with ACell, FColumnViewInfo do
|
|
begin
|
|
CellBorders := Group.Borders;
|
|
if XOfs = AMostLeftPos then
|
|
begin
|
|
AOfs := Self.DisplayRect.Left;
|
|
if CellBorders <> cxBordersAll then Exclude(CellBorders, bLeft);
|
|
end
|
|
else
|
|
AOfs := XOfs - Byte(bRight in CellBorders);
|
|
if True{not IsAutoHeight} then
|
|
begin
|
|
DisplayRect := cxRect(AOfs, YOfs, XOfs + DisplayWidth, LineCount);
|
|
cxRectScaleH(DisplayRect, Self.CellsHeight);
|
|
DisplayRect:= cxRectOffset(DisplayRect, 0, NodeViewInfo.Top);
|
|
end
|
|
else
|
|
DisplayRect := cxRect(AOfs, 0, XOfs + DisplayWidth, 1);
|
|
if YOfs > 0 then
|
|
Dec(DisplayRect.Top, OptionsView.VertIncrement)
|
|
else
|
|
Exclude(CellBorders, bTop);
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListIndentViewInfo }
|
|
|
|
procedure TcxTreeListIndentViewInfo.DoCalculate;
|
|
begin
|
|
if not Visible then Exit;
|
|
if IndentTreeLines <> [] then
|
|
with DisplayRect, cxRectCenter(DisplayRect) do
|
|
begin
|
|
if tltHorz in IndentTreeLines then
|
|
IndentHorzTreeLine := cxRect(X, Y - 1, Right, Y);
|
|
if [tltVertUp, tltVertDown] * IndentTreeLines <> [] then
|
|
begin
|
|
IndentVertTreeLine := cxRect(X, Top, X + 1, Bottom);
|
|
if not (tltVertUp in IndentTreeLines) then
|
|
IndentVertTreeLine.Top := Y - 1;
|
|
if not (tltVertDown in IndentTreeLines) then
|
|
IndentVertTreeLine.Bottom := Y - 1;
|
|
end;
|
|
end;
|
|
inherited DoCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListIndentViewInfo.DoHorzOffset(AShift: Integer);
|
|
begin
|
|
ShiftIndent(AShift, 0);
|
|
end;
|
|
|
|
procedure TcxTreeListIndentViewInfo.DoVertOffset(AShift: Integer);
|
|
begin
|
|
ShiftIndent(0, AShift);
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetControl: TcxEditingControl;
|
|
begin
|
|
Result := Node.TreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListIndentViewInfo.ShiftIndent(DX, DY: Integer);
|
|
begin
|
|
CheckClipping(cxRectOffset(DisplayRect, DX, DY), NodesViewInfo.ClipRect);
|
|
DoCalculate;
|
|
end;
|
|
|
|
procedure TcxTreeListIndentViewInfo.UpdateImageIndex;
|
|
begin
|
|
with NodeViewInfo do
|
|
begin
|
|
if not IndentStateImage then
|
|
IndentImageIndex :=
|
|
TreeList.DoGetNodeImageIndex(Node, TcxTreeListImageIndexType(Selected))
|
|
else
|
|
IndentImageIndex := TreeList.DoGetNodeImageIndex(Node, tlitStateIndex);
|
|
end;
|
|
IndentHasImage := cxInRange(IndentImageIndex, 0, IndentImageList.Count - 1);
|
|
Invalidate;
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetButtonRect: TRect;
|
|
begin
|
|
with ControlViewInfo do
|
|
begin
|
|
if HasButton then
|
|
begin
|
|
Result := cxRectCenter(DisplayRect, ExpandButtonSize, ExpandButtonSize);
|
|
OffsetRect(Result, 0, -1);
|
|
with DisplayRect do
|
|
OffsetRect(Result, Byte(not Odd(Right - Left)), Byte(not Odd(Bottom - Top)));
|
|
end
|
|
else
|
|
Result := cxInvalidRect;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetIsExpanded: Boolean;
|
|
begin
|
|
Result := HasButton and NodeViewInfo.IsExpanded;
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetNextVisible: TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := NodeViewInfo.NextVisible;
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetNode: TcxTreeListNode;
|
|
begin
|
|
Result := NodeViewInfo.Node;
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetNodeViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := TcxTreeListNodeViewInfo(Owner);
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetNodesViewInfo: TcxTreeListNodesViewInfo;
|
|
begin
|
|
Result := NodeViewInfo.Owner;
|
|
end;
|
|
|
|
function TcxTreeListIndentViewInfo.GetPrevVisible: TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := NodeViewInfo.PrevVisible;
|
|
end;
|
|
|
|
{ TcxTreeListGroupNodeEditViewInfo }
|
|
|
|
function TcxTreeListGroupNodeEditViewInfo.ChangedHeight(
|
|
APrevHeight, ANewHeight: Integer): Boolean;
|
|
begin
|
|
if ANewHeight < TreeList.ViewInfo.DefaultHeight then
|
|
ANewHeight := TreeList.ViewInfo.DefaultHeight;
|
|
Result := APrevHeight <> ANewHeight;
|
|
end;
|
|
|
|
procedure TcxTreeListGroupNodeEditViewInfo.DoCalculate;
|
|
begin
|
|
CellBorders := GridLineBorders[TreeList.OptionsView.GridLines] - [bTop];
|
|
// if TreeList.OptionsView.GridLines = tlglVert then Exclude(CellBorders, bLeft);
|
|
with NodeViewInfo do
|
|
CheckClipping(GetCellRect, NodeClipRect);
|
|
inherited DoCalculate;
|
|
end;
|
|
|
|
function TcxTreeListGroupNodeEditViewInfo.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := NodeViewInfo.TreeList.OptionsView.GetCategorizedColumn;
|
|
end;
|
|
|
|
procedure TcxTreeListGroupNodeEditViewInfo.ShiftItem(DX, DY: Integer);
|
|
begin
|
|
cxShiftEditViewInfoItem(Self, DX, DY);
|
|
end;
|
|
|
|
procedure TcxTreeListGroupNodeEditViewInfo.Update;
|
|
begin
|
|
if not NodeViewInfo.NodeIsGroup then Exit;
|
|
Column.InitEditViewInfo(Self);
|
|
DoCalculate;
|
|
end;
|
|
|
|
function TcxTreeListGroupNodeEditViewInfo.GetCellRect: TRect;
|
|
begin
|
|
with NodeViewInfo do
|
|
Result := cxRectSetTop(NodeCellsRect, NodeCellsOffset, CellsMaxHeight);
|
|
end;
|
|
|
|
{ TcxTreeListNodePreviewViewInfo }
|
|
|
|
constructor TcxTreeListNodePreviewViewInfo.Create(AOwner: TObject);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Preview := TreeList.Preview;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.ChangedHeight(
|
|
APrevHeight, ANewHeight: Integer): Boolean;
|
|
begin
|
|
Result := inherited ChangedHeight(APrevHeight, ANewHeight);
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.CheckPreviewHeight(DH: Integer): Integer;
|
|
var
|
|
ALines: Integer;
|
|
begin
|
|
if Preview.MaxLineCount = 0 then
|
|
ALines := Round(PreviewHeight / ControlViewInfo.PreviewHeight)
|
|
else
|
|
ALines := Preview.MaxLineCount;
|
|
Result := (ControlViewInfo.PreviewHeight + DH) * ALines;
|
|
if Result > PreviewHeight then Result := PreviewHeight;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.ContentOffset: TRect;
|
|
begin
|
|
Result := cxTreeListEditCellContentOffset;
|
|
with Preview do
|
|
begin
|
|
Result.Left := FLeftIndent;
|
|
Result.Right := FRightIndent;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodePreviewViewInfo.CustomDrawEvent(
|
|
var AEvent: TcxCustomDrawViewInfoItemEvent);
|
|
begin
|
|
AEvent := TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawPreview);
|
|
end;
|
|
|
|
procedure TcxTreeListNodePreviewViewInfo.DoCalculate;
|
|
begin
|
|
if not NodeViewInfo.HasPreview then Exit;
|
|
with NodeViewInfo do
|
|
CheckClipping(GetPreviewRect, NodeClipRect);
|
|
Refresh(False);
|
|
if Visible then
|
|
Column.CalculateEditViewInfo(CellValue, Self, cxInvalidPoint);
|
|
end;
|
|
|
|
procedure TcxTreeListNodePreviewViewInfo.DoInitPreviewSettings(
|
|
APreviewOffset: Integer);
|
|
var
|
|
DH: Integer;
|
|
begin
|
|
PreviewHeight := 0;
|
|
CellBorders := NodeViewInfo.NodeBorders;
|
|
NodeViewInfo.NodeHasPreview := TreeList.Preview.Active;
|
|
NodeViewInfo.NodePreviewOffset := APreviewOffset;
|
|
if not NodeViewInfo.NodeHasPreview then Exit;
|
|
Column.InitEditViewInfo(Self);
|
|
Include(ViewData.PaintOptions, epoAllowZeroHeight);
|
|
with ContentOffset do
|
|
DH := Byte(bBottom in Borders) + Byte(bTop in Borders) + Top + Bottom;
|
|
PreviewHeight := ControlViewInfo.PreviewHeight + DH;
|
|
if IsAutoHeight then
|
|
begin
|
|
CellContentRect := GetPreviewRect;
|
|
PreviewHeight := Column.GetEditHeight(Self);
|
|
PreviewHeight := CheckPreviewHeight(DH);
|
|
end;
|
|
with NodesViewInfo do
|
|
begin
|
|
if Assigned(TreeList.OnGetNodePreviewHeight) then
|
|
TreeList.OnGetNodePreviewHeight(TreeList, Node, DisplayValue, PreviewHeight);
|
|
if (PreviewHeight - DH) <= 0 then
|
|
begin
|
|
PreviewHeight := 0;
|
|
ItemVisible := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := Preview.Column;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetButtonTransparency: TcxEditButtonTransparency;
|
|
begin
|
|
Result := ebtHideInactive;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetHotTrack: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetLineCount: Integer;
|
|
begin
|
|
Result := Preview.MaxLineCount;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetLineOffset: Integer;
|
|
begin
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetMaxLineCount: Integer;
|
|
begin
|
|
Result := Preview.MaxLineCount;
|
|
end;
|
|
|
|
procedure TcxTreeListNodePreviewViewInfo.GetTreeListEditCellParams(
|
|
var AParams: TcxViewParams);
|
|
begin
|
|
AParams := TreeList.Styles.GetPreviewParams(Node);
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.IsAutoHeight: Boolean;
|
|
begin
|
|
Result := Preview.AutoHeight;
|
|
end;
|
|
|
|
procedure TcxTreeListNodePreviewViewInfo.ShiftItem(DX, DY: Integer);
|
|
begin
|
|
cxShiftEditViewInfoItem(Self, DX, DY);
|
|
end;
|
|
|
|
procedure TcxTreeListNodePreviewViewInfo.Update;
|
|
begin
|
|
if not NodeViewInfo.HasPreview then Exit;
|
|
Column.InitEditViewInfo(Self);
|
|
DoCalculate;
|
|
end;
|
|
|
|
function TcxTreeListNodePreviewViewInfo.GetPreviewRect: TRect;
|
|
begin
|
|
with NodeViewInfo do
|
|
begin
|
|
Result := cxRectSetTop(NodeContentRect, NodePreviewOffset, PreviewHeight);
|
|
if TreeList.ViewInfo.LeftFixedBand = nil then
|
|
Result.Left := NodeCellsRect.Left
|
|
else
|
|
Result.Left := NodeViewInfo.NodeIndentLeft;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListNodeViewInfo }
|
|
|
|
constructor TcxTreeListNodeViewInfo.Create(AOwner: TcxTreeListNodesViewInfo);
|
|
begin
|
|
FOwner := AOwner;
|
|
FGroups := TList.Create;
|
|
FCells := TList.Create;
|
|
FIndents := TList.Create;
|
|
FIndicator := ControlViewInfo.GetIndicatorViewInfoClass.Create(ControlViewInfo);
|
|
FPreview := FOwner.GetNodePreviewViewInfoClass.Create(Self);
|
|
NodeGroupEditViewInfo := TcxTreeListGroupNodeEditViewInfo.Create(Self);
|
|
end;
|
|
|
|
destructor TcxTreeListNodeViewInfo.Destroy;
|
|
begin
|
|
try
|
|
FreeAndNil(NodeGroupEditViewInfo);
|
|
Clear;
|
|
FreeAndNil(FPreview);
|
|
FreeAndNil(FIndicator);
|
|
FreeAndNil(FGroups);
|
|
FreeAndNil(FIndents);
|
|
FreeAndNil(FCells);
|
|
finally
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.AssignLayoutTo(ADest: TcxTreeListNodeViewInfo);
|
|
|
|
procedure AssignObjectLists(ASrc, ADest: PPointerList; ACount: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ACount - 1 do
|
|
TcxCustomViewInfoItem(ADest^[I]).Assign(TcxCustomViewInfoItem(ASrc^[I]));
|
|
end;
|
|
|
|
begin
|
|
ADest.ReallocateData;
|
|
AssignObjectLists(FGroups.List, ADest.FGroups.List, FGroups.Count);
|
|
AssignObjectLists(FCells.List, ADest.FCells.List, FCells.Count);
|
|
ADest.Top := Top;
|
|
ADest.Left := Left;
|
|
ADest.NodeCellsCalculated := False;
|
|
ADest.NodeFocused := False;
|
|
ADest.NodeHasButton := False;
|
|
ADest.NodeHasPreview := False;
|
|
ADest.NodeSelected := False;
|
|
ADest.NodeVisible := False;
|
|
ADest.NodeIsExpanded := False;
|
|
ADest.NodeBorders := NodeBorders;
|
|
ADest.CellsMaxHeight := CellsMaxHeight;
|
|
ADest.NodeContentRect := NodeContentRect;
|
|
ADest.NodeCellsRect := NodeCellsRect;
|
|
ADest.NodeFocusedCell := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.Clear;
|
|
begin
|
|
cxCheckObjectList(FGroups, 0, nil, nil);
|
|
cxCheckObjectList(FIndents, 0, nil, nil);
|
|
cxCheckObjectList(FCells, 0, nil, nil);
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoCalculate;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
NodeHasButton := OptionsView.Buttons and Node.HasChildren;
|
|
NodeIsGroup := TreeList.DoIsGroupNode(Node);
|
|
NodeFocused := Node.Focused;
|
|
NodeSelected := Node.Selected;
|
|
if NodeHasButton then
|
|
NodeIsExpanded := Node.Expanded
|
|
else
|
|
NodeIsExpanded := False;
|
|
NodeLevel := Node.Level;
|
|
NodeIndentLeft := DoCalculateIndentsLayout;
|
|
NodeCellsOffset := Top;
|
|
if Preview.Preview.Place = tlppTop then
|
|
begin
|
|
Preview.DoInitPreviewSettings(Top);
|
|
NodeCellsOffset := Top + Preview.PreviewHeight;
|
|
end;
|
|
if not NodeIsGroup then
|
|
begin
|
|
for I := 0 to GroupCount - 1 do
|
|
with Groups[I] do
|
|
begin
|
|
ItemViewParams := TreeList.Styles.GetBandContentParams(Band, Node);
|
|
DoCalculate;
|
|
end;
|
|
end;
|
|
if Owner.IsRowAutoHeight then DoCalculateAutoHeights;
|
|
if Preview.Preview.Place = tlppBottom then
|
|
Preview.DoInitPreviewSettings(Top + CellsMaxHeight);
|
|
cxRectSetHeightEx(NodeContentRect, RealHeight);
|
|
UpdateContentRects;
|
|
FIndicator.FKind := GetNodeIndicatorKind;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoCalculateAutoHeights;
|
|
var
|
|
I: Integer;
|
|
AIndent: Integer;
|
|
begin
|
|
CellMaxHeightRefCount := 0;
|
|
CellsMaxHeight := ControlViewInfo.DefaultEditHeight;
|
|
if not IsGroupNode then
|
|
begin
|
|
AIndent := TreeList.GetLevelIndentsWidth(Node.Level, True, Node);
|
|
for I := 0 to CellCount - 1 do
|
|
with Cells[I] do
|
|
begin
|
|
CellContentRect := cxExcludeBorders(DisplayRect, Borders);
|
|
if Column.IsLeftMost then
|
|
Inc(CellContentRect.Left, AIndent);
|
|
CellHeight := CalculateEditHeight;
|
|
if CellsMaxHeight < CellHeight then
|
|
begin
|
|
CellMaxHeightRefCount := 1;
|
|
CellsMaxHeight := CellHeight;
|
|
end
|
|
else
|
|
if CellHeight = CellsMaxHeight then Inc(CellMaxHeightRefCount);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
with NodeGroupEditViewInfo do
|
|
CheckClipping(cxRectSetXPos(NodeCellsRect, NodeIndentLeft, NodeCellsRect.Right), NodeClipRect);
|
|
CellsMaxHeight := cxMax(NodeGroupEditViewInfo.CalculateEditHeight, CellsMaxHeight);
|
|
end;
|
|
TreeList.DoOnGetNodeHeight(Node, CellsMaxHeight);
|
|
if CellMaxHeightRefCount = 0 then Inc(CellMaxHeightRefCount);
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoCalculateCellsViewInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not IsGroupNode then
|
|
for I := 0 to CellCount - 1 do Cells[I].DoCalculate
|
|
else
|
|
NodeGroupEditViewInfo.DoCalculate;
|
|
NodeCellsCalculated := True;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoCalculateImageIndents(var ALeft: Integer);
|
|
|
|
procedure AddImageIndent(HasImages: Boolean; var Index: Integer; AType: Integer);
|
|
begin
|
|
if not HasImages then Exit;
|
|
with Indents[Index] do
|
|
begin
|
|
IndentIsLevel := False;
|
|
IndentBorders := [];
|
|
IndentImageIndex := Node.GetNodeImageIndex(AType);
|
|
IndentStateImage := AType = Byte(tlitStateIndex);
|
|
if IndentStateImage then
|
|
IndentImageList := TreeList.StateImages
|
|
else
|
|
IndentImageList := TreeList.Images;
|
|
ItemViewParams := TreeList.Styles.GetIndentParams(Self.Node, Index);
|
|
DisplayRect := Rect(ALeft - TreeList.GetImageIndentWidth(
|
|
TcxTreeListImageIndexType(AType)), Self.Top, ALeft, Self.Top + RealHeight);
|
|
Dec(ALeft, TreeList.FMaxIndentWidth);
|
|
IndentHasImage := cxInRange(IndentImageIndex, 0, IndentImageList.Count - 1);
|
|
end;
|
|
Dec(Index);
|
|
end;
|
|
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
AIndex := IndentCount - 1;
|
|
with OptionsView do
|
|
begin
|
|
AddImageIndent(HasImages(Node), AIndex, Byte(Node.Selected));
|
|
AddImageIndent(HasStateImages(Node), AIndex, Byte(tlitStateIndex));
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.DoCalculateIndentsLayout: Integer;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
I, AIndentCount, ANextIndentCount, ALeft: Integer;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
Result := Groups[0].DisplayRect.Left + GetLevelIndentsWidth(NodeLevel, True, Node);
|
|
AIndentCount := GetLevelIndentCount(NodeLevel, True, Node);
|
|
if AIndentCount = 0 then
|
|
begin
|
|
cxCheckObjectList(FIndents, 0, nil, nil);
|
|
Exit;
|
|
end;
|
|
cxCheckObjectList(FIndents, AIndentCount, Self.Owner.GetIndentViewInfoItemClass, Self);
|
|
Inc(NodeLevel, Byte(OptionsView.ShowRoot));
|
|
ANextIndentCount := -1;
|
|
ANode := Node.GetNextVisible;
|
|
if ANode <> nil then
|
|
ANextIndentCount := GetLevelIndentCount(ANode.Level, True, ANode);
|
|
ANode := Node;
|
|
ALeft := Result;
|
|
DoCalculateImageIndents(ALeft);
|
|
for I := NodeLevel - 1 downto 0 do
|
|
CalculateIndentInfo(Indents[I], ANode, I, ALeft);
|
|
if OptionsView.GridLines in [tlglBoth, tlglHorz] then
|
|
begin
|
|
for I := 0 to AIndentCount - 1 do
|
|
if (I >= ANextIndentCount) then
|
|
Indents[I].IndentBorders := [bBottom]
|
|
else
|
|
Indents[I].IndentBorders := []
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoCalculateIndentsViewInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to IndentCount - 1 do
|
|
Indents[I].DoCalculate;
|
|
end;
|
|
|
|
// main calculate layout cells in nodes used for template viewinfo and
|
|
// that be assigned to another NodeViewInfo
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoCalculateLayout;
|
|
var
|
|
AOfs, I, AIndex, ACellIndex: Integer;
|
|
AMin, AMax: Integer;
|
|
APrev: TcxTreeListBandViewInfo;
|
|
|
|
procedure DoCalculateLayoutCellsInBand(AInfo: TcxTreeListBandViewInfo);
|
|
var
|
|
I: Integer;
|
|
AGroup: TcxTreeListCellsGroupViewInfo;
|
|
AIsLeft: Boolean;
|
|
begin
|
|
if AInfo = nil then Exit;
|
|
AIsLeft := (APrev = nil) or (APrev.Fixed <> tlbfNone) or (AInfo.Fixed <> tlbfNone);
|
|
if AIsLeft then
|
|
begin
|
|
AOfs := AInfo.DisplayRect.Left;
|
|
NodeCellsRect.Left := AOfs;
|
|
end
|
|
else
|
|
Dec(AOfs);
|
|
AGroup := AddGroup(AInfo, AIndex, AOfs);
|
|
with AGroup do
|
|
begin
|
|
Borders := GridLineBorders[Self.OptionsView.GridLines];
|
|
FirstIndex := ACellIndex;
|
|
for I := 0 to AInfo.ColumnCount - 1 do
|
|
AddCell(AInfo.Columns[I], AIndex, ACellIndex);
|
|
LastIndex := ACellIndex;
|
|
cxSetMin(Left, DisplayRect.Left);
|
|
CheckClipping(DisplayRect, GetVisibleRect(Fixed));
|
|
DoCalculateCellsLayout;
|
|
AOfs := DisplayRect.Right;
|
|
NodeCellsRect.Right := AOfs;
|
|
Exclude(Borders, bTop);
|
|
if AInfo.Band.IsLeftMost and not (bBottom in Borders) then Exclude(Borders, bLeft);
|
|
end;
|
|
APrev := AInfo;
|
|
end;
|
|
|
|
begin
|
|
ReallocateData;
|
|
Top := Owner.ClipRect.Top;
|
|
Left := MaxInt;
|
|
NodeContentRect := Owner.ClipRect;
|
|
if OptionsView.Indicator then
|
|
Dec(NodeContentRect.Left, OptionsView.IndicatorWidth);
|
|
with ControlViewInfo do
|
|
begin
|
|
AIndex := 0;
|
|
ACellIndex := 0;
|
|
APrev := nil;
|
|
DoCalculateLayoutCellsInBand(LeftFixedBand);
|
|
for I := 0 to BandCount - 1 do
|
|
DoCalculateLayoutCellsInBand(Bands[I]);
|
|
DoCalculateLayoutCellsInBand(RightFixedBand);
|
|
NodeBorders := Groups[0].Borders;
|
|
if bRight in Groups[GroupCount - 1].Borders then
|
|
Include(NodeBorders, bRight);
|
|
end;
|
|
if not Owner.IsRowAutoHeight then
|
|
begin
|
|
cxRectMinMaxInit(AMin, AMax);
|
|
for I := 0 to CellCount - 1 do
|
|
cxRectMinMaxHeight(Cells[I].DisplayRect, AMax, AMin);
|
|
CellsMaxHeight := AMax - AMin;
|
|
end
|
|
else
|
|
CellsMaxHeight := 0;
|
|
NodeContentRect.Right := cxMin(Owner.ClipRect.Right, NodeCellsRect.Right);
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoHorzOffset(AShift: Integer);
|
|
var
|
|
I: Integer;
|
|
R: TRect;
|
|
begin
|
|
if not IsGroupNode then
|
|
begin
|
|
for I := Byte(LeftFixedGroup <> nil) to GroupCount - Byte(RightFixedGroup <> nil) - 1 do
|
|
Groups[I].DoHorzOffset(AShift);
|
|
end
|
|
else
|
|
R := NodeGroupEditViewInfo.GetCellRect;
|
|
if not Groups[GroupCount - 1].Fixed then
|
|
Inc(NodeCellsRect.Right, AShift);
|
|
if not Groups[0].Fixed then
|
|
begin
|
|
Inc(NodeCellsRect.Left, AShift);
|
|
for I := 0 to IndentCount - 1 do Indents[I].DoHorzOffset(AShift);
|
|
end;
|
|
UpdateClipping;
|
|
Preview.DoCalculate;
|
|
if IsGroupNode then
|
|
begin
|
|
with NodeGroupEditViewInfo do
|
|
begin
|
|
CheckClipping(GetCellRect, NodeContentRect);
|
|
DoCalculate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.DoVertOffset(AShift: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (AShift = 0) and NodeCellsCalculated then Exit;
|
|
Inc(NodePreviewOffset, AShift);
|
|
Inc(NodeCellsOffset, AShift);
|
|
OffsetRect(NodeContentRect, 0, AShift);
|
|
OffsetRect(NodeCellsRect, 0, AShift);
|
|
UpdateClipping;
|
|
if not IsGroupNode then
|
|
for I := 0 to GroupCount - 1 do
|
|
Groups[I].DoVertOffset(AShift);
|
|
for I := 0 to IndentCount - 1 do
|
|
Indents[I].DoVertOffset(AShift);
|
|
DoCalculateIndentsViewInfo;
|
|
if not IsGroupNode then
|
|
cxCalcSeparators(Separators, ControlViewInfo.FSeparators, NodeCellsRect)
|
|
else
|
|
NodeGroupEditViewInfo.ShiftItem(0, AShift);
|
|
FIndicator.Calculate(ContentRect, NodeContentRect);
|
|
Preview.DoCalculate;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetNodeIndicatorKind: TcxIndicatorKind;
|
|
|
|
function IsMultiSelect: Boolean;
|
|
begin
|
|
Result := TreeList.SelectionCount > 1;
|
|
end;
|
|
|
|
begin
|
|
Result := ikNone;
|
|
if Focused then
|
|
begin
|
|
if Selected and IsMultiSelect then
|
|
Result := ikMultiArrow
|
|
else
|
|
Result := ikArrow;
|
|
if TreeList.IsNodeEdited(Node) then
|
|
Result := ikEdit
|
|
else
|
|
if TreeList.IsNodeInserted(Node) then
|
|
Result := ikInsert
|
|
end
|
|
else
|
|
if Selected then Result := ikMultiDot;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.Update(ARecalculate: Boolean = False);
|
|
|
|
function ChangeState(var APrevState: Boolean; AState, ACheckPrev: Boolean): Boolean;
|
|
begin
|
|
Result := (ACheckPrev and APrevState) or (AState <> APrevState);
|
|
APrevState := AState;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
ARecalculateOnFocusChanged, NeedUpdate: Boolean;
|
|
begin
|
|
NeedUpdate := Node.Focused;
|
|
ARecalculateOnFocusChanged := (NodeFocused <> NeedUpdate);
|
|
{$B+}
|
|
NeedUpdate := ChangeState(NodeFocused, NeedUpdate, True) or
|
|
ChangeState(NodeSelected, Node.Selected, not Owner.CheckSelectionMode);
|
|
{$B-}
|
|
ARecalculateOnFocusChanged := ARecalculate or ARecalculateOnFocusChanged;
|
|
if NeedUpdate or NodeFocused or ARecalculate then
|
|
begin
|
|
for I := 0 to IndentCount - 1 do
|
|
with Indents[I] do
|
|
begin
|
|
ItemViewParams := TreeList.Styles.GetIndentParams(Self.Node, I);
|
|
DoCalculate;
|
|
end;
|
|
NeedUpdate := False;
|
|
if not IsGroupNode then
|
|
for I := 0 to CellCount - 1 do
|
|
NeedUpdate := NeedUpdate or Cells[I].Refresh(ARecalculateOnFocusChanged)
|
|
else
|
|
NeedUpdate := NeedUpdate or NodeGroupEditViewInfo.Refresh(ARecalculateOnFocusChanged);
|
|
NeedUpdate := NeedUpdate or (HasPreview and Preview.Refresh(ARecalculateOnFocusChanged));
|
|
if NeedUpdate then
|
|
TreeList.LayoutChanged
|
|
else
|
|
begin
|
|
UpdateImageIndexes;
|
|
Owner.Owner.InvalidateRect(NodeContentRect);
|
|
end;
|
|
end;
|
|
Indicator.FKind := GetNodeIndicatorKind;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.UpdateClipping;
|
|
begin
|
|
NodeClipRect := NodeCellsRect;
|
|
NodeClipRect.Right := cxMin(Owner.ClipRect.Right, NodeClipRect.Right);
|
|
NodeVisible := cxRectIntersect(NodeClipRect, NodeContentRect, Owner.ClipRect);
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.UpdateImageIndexes;
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
AIndex := IndentCount - 1;
|
|
while AIndex >= 0 do
|
|
with Indents[AIndex] do
|
|
begin
|
|
if not IsLevel then
|
|
UpdateImageIndex
|
|
else
|
|
Break;
|
|
Dec(AIndex)
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.UpdatePostCalculate(ATop, AIndex: Integer);
|
|
begin
|
|
Indicator.FNode := Node;
|
|
Index := AIndex;
|
|
UpdateLinks;
|
|
DoVertOffset(ATop - Top);
|
|
if not NodeCellsCalculated then
|
|
DoCalculateCellsViewInfo
|
|
else
|
|
UpdateClipping;
|
|
Top := ATop;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.ReallocateData;
|
|
begin
|
|
with Owner, TreeList do
|
|
begin
|
|
cxCheckObjectList(FGroups, VisibleBandCount, GetGroupViewInfoItemClass, Self);
|
|
cxCheckObjectList(FCells, VisibleColumnCount, GetEditCellViewInfoItemClass, Self);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetCell(Index: Integer): TcxTreeListEditCellViewInfo;
|
|
begin
|
|
Result := TcxTreeListEditCellViewInfo(FCells.List^[Index]);
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetCellCount: Integer;
|
|
begin
|
|
Result := FCells.Count;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetControlViewInfo: TcxTreeListViewInfo;
|
|
begin
|
|
Result := Owner.Owner;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetFocusRect: TRect;
|
|
begin
|
|
if Focused and (GroupCount > 0) then
|
|
begin
|
|
if NodeFocusedCell <> nil then
|
|
Result := NodeFocusedCell.CellContentRect
|
|
else
|
|
begin
|
|
Result := NodeCellsRect;
|
|
cxRectSetTopEx(Result, NodeContentRect);
|
|
Result := cxExcludeBorders(Result, NodeBorders);
|
|
end;
|
|
end
|
|
else
|
|
Result := cxInvalidRect;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetGroup(Index: Integer): TcxTreeListCellsGroupViewInfo;
|
|
begin
|
|
Result := TcxTreeListCellsGroupViewInfo(FGroups.List^[Index]);
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetGroupCount: Integer;
|
|
begin
|
|
Result := FGroups.Count;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetIndent(Index: Integer): TcxTreeListIndentViewInfo;
|
|
begin
|
|
Result := TcxTreeListIndentViewInfo(FIndents.List^[Index]);
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetHotTrack: Boolean;
|
|
begin
|
|
Result := Node.HotTrack;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetIndentCount: Integer;
|
|
begin
|
|
Result := FIndents.Count;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetIndentWidth: Integer;
|
|
begin
|
|
Result := Owner.IndentWidth;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetOptionsView: TcxTreeListOptionsView;
|
|
begin
|
|
Result := TreeList.OptionsView;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetRealHeight: Integer;
|
|
begin
|
|
Result := CellsMaxHeight + Byte(HasPreview) * Preview.PreviewHeight;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Owner.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetVisibleIndex: Integer;
|
|
begin
|
|
Result := Node.FVisibleIndex;
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.AddGroup(AInfo: TcxTreeListBandViewInfo;
|
|
var AIndex, AOfs: Integer): TcxTreeListCellsGroupViewInfo;
|
|
begin
|
|
Result := Groups[AIndex];
|
|
Result.DisplayRect :=
|
|
cxRect(AOfs, Top, AInfo.DisplayRect.Right, NodeContentRect.Bottom);
|
|
Result.BandViewInfo := AInfo;
|
|
Result.IsOpaque := AInfo.IsOpaque;
|
|
Inc(AIndex);
|
|
end;
|
|
|
|
function TcxTreeListNodeViewInfo.GetVisibleRect(AFixed: Boolean): TRect;
|
|
begin
|
|
if AFixed then
|
|
Result := Owner.ClipRect
|
|
else
|
|
Result := Owner.ScrollRect;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.AddCell(
|
|
AInfo: TcxTreeListColumnViewInfo; var AGroupIndex, AIndex: Integer);
|
|
begin
|
|
// if (AIndex < 0) or (AIndex >= CellCount) then Exit;
|
|
with Cells[AIndex] do
|
|
begin
|
|
GroupIndex := AGroupIndex - 1;
|
|
FColumnViewInfo := AInfo;
|
|
end;
|
|
Inc(AIndex);
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.CalculateIndentInfo(AIndent: TcxTreeListIndentViewInfo;
|
|
var ANode: TcxTreeListNode; ALevel: Integer; var ALeft: Integer);
|
|
begin
|
|
with AIndent do
|
|
begin
|
|
IndentLevelNode := ANode;
|
|
IndentIsLevel := True;
|
|
IndentLevel := ALevel;
|
|
IndentTreeLines := [];
|
|
IndentBorders := [];
|
|
IndentHasExpandButton := (ANode = Self.Node) and NodeHasButton;
|
|
IndentTreeLines := [];
|
|
if OptionsView.TreeLineStyle <> tllsNone then
|
|
begin
|
|
IndentTreeLines := [tltVertUp];
|
|
if ANode = Self.Node then
|
|
Include(IndentTreeLines, tltHorz);
|
|
if ANode.FNext <> nil then
|
|
Include(IndentTreeLines, tltVertDown)
|
|
else
|
|
if ((ANode <> Self.Node) and (ANode.Parent <> Self.Node.Parent)) then
|
|
Exclude(IndentTreeLines, tltVertUp);
|
|
if (ANode = ViewInfoNode) and (ANode = ANode.Owner.Root.FFirst) then
|
|
Exclude(IndentTreeLines, tltVertUp);
|
|
end;
|
|
end;
|
|
with TreeList do
|
|
AIndent.ItemViewParams := Styles.GetIndentParams(Self.Node, ALevel);
|
|
AIndent.DisplayRect := Rect(ALeft - IndentWidth, Top, ALeft, Top + RealHeight);
|
|
Dec(ALeft, IndentWidth);
|
|
ANode := ANode.Parent;
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.UpdateContentRects;
|
|
|
|
procedure SetLeftMostIndent(AGroup: TcxTreeListCellsGroupViewInfo);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
AGroup.SetSize(NodeCellsOffset, CellsMaxHeight);
|
|
for I := 0 to AGroup.CellCount - 1 do
|
|
with AGroup.Cells[I] do
|
|
begin
|
|
if DisplayRect.Left = AGroup.DisplayRect.Left then
|
|
DisplayRect.Left := NodeIndentLeft;
|
|
end;
|
|
AGroup.DisplayRect.Left := NodeIndentLeft;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
NodeCellsRect.Left := NodeIndentLeft;
|
|
if not IsGroupNode then
|
|
begin
|
|
SetLeftMostIndent(Groups[0]);
|
|
cxRectSetTopEx(NodeCellsRect, NodeCellsOffset, CellsMaxHeight);
|
|
cxRectSetTopEx(NodeContentRect, Top, RealHeight);
|
|
for I := 1 to GroupCount - 1 do
|
|
Groups[I].SetSize(NodeCellsOffset, CellsMaxHeight);
|
|
end;
|
|
for I := 0 to IndentCount - 1 do
|
|
cxRectSetHeightEx(Indents[I].DisplayRect, RealHeight);
|
|
end;
|
|
|
|
procedure TcxTreeListNodeViewInfo.UpdateLinks;
|
|
|
|
function GetNodeViewInfo(AIndex: Integer): TcxTreeListNodeViewInfo;
|
|
begin
|
|
with Owner do
|
|
if (AIndex = cxInvalidIndex) or (AIndex >= Count) then
|
|
Result := nil
|
|
else
|
|
Result := Nodes[AIndex];
|
|
end;
|
|
|
|
function CheckFixed(AGroup: TcxTreeListCellsGroupViewInfo;
|
|
AKind: TcxTreeListBandFixedKind): TcxTreeListCellsGroupViewInfo;
|
|
begin
|
|
if AGroup.Band.FixedKind = AKind then
|
|
Result := AGroup
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
begin
|
|
NodeNextVisible := GetNodeViewInfo(Index + 1);
|
|
NodePrevVisible := GetNodeViewInfo(Index - 1);
|
|
if (GroupCount > 0) and not IsGroupNode then
|
|
begin
|
|
LeftFixedGroup := CheckFixed(Groups[0], tlbfLeft);
|
|
RightFixedGroup := CheckFixed(Groups[GroupCount - 1], tlbfRight);
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListNodesViewInfo }
|
|
|
|
constructor TcxTreeListNodesViewInfo.Create(AOwner: TcxTreeListViewInfo);
|
|
begin
|
|
FOwner := AOwner;
|
|
end;
|
|
|
|
destructor TcxTreeListNodesViewInfo.Destroy;
|
|
begin
|
|
try
|
|
Clear;
|
|
FreeMem(FNodes);
|
|
finally
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.Add(ANode: TcxTreeListNode; var AHeight: Integer);
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
AViewInfo := AddNode(ANode);
|
|
if IsAddFirst and (Count > 1) then
|
|
begin
|
|
System.Move(FNodes^[0], FNodes^[1], (Count - 1) * SizeOf(Pointer));
|
|
FNodes^[0] := AViewInfo;
|
|
end;
|
|
Template.AssignLayoutTo(AViewInfo);
|
|
with AViewInfo do
|
|
begin
|
|
AViewInfo.DoCalculate;
|
|
AHeight := RealHeight;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.AddNode(
|
|
ANode: TcxTreeListNode): TcxTreeListNodeViewInfo;
|
|
var
|
|
ACapacity: Integer;
|
|
begin
|
|
if FNodesCount > Count then
|
|
Result := TcxTreeListNodeViewInfo(FNodes^[Count])
|
|
else
|
|
begin
|
|
Result := GetNodeViewInfoClass.Create(Self);
|
|
Inc(FNodesCount);
|
|
ACapacity :=
|
|
((FNodesCount + cxMinCapacityInc) div cxMinCapacityInc) * cxMinCapacityInc;
|
|
if ACapacity > FCapacity then
|
|
begin
|
|
FCapacity := ACapacity;
|
|
ReallocMem(FNodes, FCapacity * SizeOf(Pointer));
|
|
end;
|
|
FNodes^[Count] := Result;
|
|
end;
|
|
Result.ViewInfoNode := ANode;
|
|
Inc(Count);
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.BeforeShowEdit;
|
|
begin
|
|
PostViewInfoUpdate;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.CalculatePreviewHeight;
|
|
begin
|
|
with TreeList.Preview do
|
|
begin
|
|
if Active then
|
|
begin
|
|
Self.Owner.PreviewHeight := Column.GetEditDefaultHeight(
|
|
TreeList.Styles.GetPreviewParams(TreeList.Nodes.Root.FFirst).Font);
|
|
Self.Owner.PreviewHeight := Self.Owner.PreviewHeight {* MaxLineCount};
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.CancelUpdatePost;
|
|
begin
|
|
FUpdatePost := False;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.ChangeDirection;
|
|
begin
|
|
IsAddFirst := not IsAddFirst;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
try
|
|
for I := 0 to FNodesCount - 1 do
|
|
FreeAndNil(TObject(FNodes^[I]));
|
|
FreeMem(FNodes);
|
|
finally
|
|
FreeAndNil(Template);
|
|
if not TreeList.IsDestroying then ClearState;
|
|
TopNode := nil;
|
|
VisibleCount := 0;
|
|
Count := 0;
|
|
FNodes := nil;
|
|
FNodesCount := 0;
|
|
FCapacity := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.ClearState;
|
|
begin
|
|
IsAddFirst := False;
|
|
Count := 0;
|
|
VisibleCount := 0;
|
|
IsRowAutoHeight := OptionsView.CellAutoHeight and (TreeList.HeaderLineCount = 1);
|
|
with TreeList.Nodes do
|
|
begin
|
|
Self.TopNode := TopVisibleNode;
|
|
TopIndex := TopIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.DoCalculate(AFullRecalculate: Boolean = True);
|
|
begin
|
|
ClearState;
|
|
IndentWidth := TreeList.FLevelIndentWidth;
|
|
with Owner do
|
|
begin
|
|
ClipRect := ContentRect;
|
|
cxRectIntersect(ScrollRect, ContentRect, ScrollingArea);
|
|
end;
|
|
SpaceArea := Owner.CellsRect;
|
|
SpaceArea.Left := Owner.BorderSize;
|
|
TopNode := TreeList.Nodes.TopNode;
|
|
if (TopNode = nil) or (TreeList.VisibleBandCount = 0) or (TreeList.VisibleColumnCount = 0) then
|
|
begin
|
|
VisibleCount := 0;
|
|
Exit;
|
|
end;
|
|
CalculatePreviewHeight;
|
|
if AFullRecalculate then
|
|
begin
|
|
if Template = nil then Template := GetNodeViewInfoClass.Create(Self);
|
|
Template.DoCalculateLayout;
|
|
end;
|
|
NodesBottom := Owner.CellsRect.Top;
|
|
ProcessNodes(TopNode, True);
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.DoCalculateNextPage(AGoForward: Boolean);
|
|
begin
|
|
TreeList.Controller.DoShowNextPageEx(AGoForward, False, []);
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.DoHorzOffset(AShift: Integer);
|
|
|
|
procedure DoOffsetGroup(AGroup: TcxTreeListCellsGroupViewInfo);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with AGroup do
|
|
begin
|
|
if Band.FixedKind <> tlbfNone then Exit;
|
|
OffsetRect(DisplayRect, AShift, 0);
|
|
for I := 0 to CellCount - 1 do
|
|
OffsetRect(Cells[I].DisplayRect, AShift, 0);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Count = 0 then Exit;
|
|
for I := 0 to Count - 1 do
|
|
Nodes[I].DoHorzOffset(AShift);
|
|
with Template do
|
|
for I := 0 to GroupCount - 1 do DoOffsetGroup(Groups[I]);
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.DoCalculateShiftUp(
|
|
ALineCount: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ALineCount - 1 do
|
|
Dec(NodesBottom, MoveFirstToLatest(False));
|
|
if Count > 0 then
|
|
TopNode := Nodes[0].Node;
|
|
ProcessNodes(GetNextNodeFromViewInfo(Count - 1), True);
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.DoCalculateShiftDown(ALineCount: Integer);
|
|
var
|
|
I: Integer;
|
|
ANode: TcxTreeListNode;
|
|
IsBreak: Boolean;
|
|
begin
|
|
IsAddFirst := True;
|
|
if ALineCount > 0 then
|
|
begin
|
|
NeedViewInfoUpdatePost;
|
|
ANode := GetNextNodeFromViewInfo(0);
|
|
for I := 1 to ALineCount do
|
|
begin
|
|
IsAddFirst := True;
|
|
IsBreak := False;
|
|
if ANode <> nil then
|
|
begin
|
|
NodesBottom := 0;
|
|
ProcessAddNode(ANode, IsBreak);
|
|
end
|
|
else
|
|
Break;
|
|
TopNode := Nodes[0].Node;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.DoVertOffset(AShift: Integer);
|
|
begin
|
|
if AShift = 0 then Exit;
|
|
if TreeList.IsLocked then
|
|
TreeList.Nodes.SetTopVisibleIndex(TopVisibleIndex + AShift)
|
|
else
|
|
begin
|
|
if Abs(AShift) >= Count then
|
|
begin
|
|
TreeList.Nodes.SetTopVisibleIndex(TopVisibleIndex + AShift);
|
|
DoCalculate(False);
|
|
Owner.InvalidateRect(ClipRect);
|
|
end
|
|
else
|
|
begin
|
|
if AShift > 0 then
|
|
begin
|
|
TreeList.Nodes.SetTopVisibleIndex(TopVisibleIndex + AShift);
|
|
DoCalculate(False);
|
|
Owner.InvalidateRect(ClipRect);
|
|
end
|
|
else
|
|
DoCalculateShiftDown(Abs(AShift));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.FindNodeViewInfo(
|
|
ANode: TcxTreeListNode; var AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
Result := ANode <> nil;
|
|
if not Result then Exit;
|
|
with ANode do
|
|
AIndex := VisibleIndex - TopVisibleIndex;
|
|
Result := (AIndex >= 0) and (AIndex < Count);
|
|
if Result then AViewInfo := Nodes[AIndex];
|
|
Result := Result and (ANode = AViewInfo.Node);
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.FocusedRecordChanged(
|
|
APrevNode, ANewNode: TcxTreeListNode);
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
if (APrevNode <> ANewNode) and not TreeList.IsLocked then
|
|
begin
|
|
if FindNodeViewInfo(APrevNode, AViewInfo) then AViewInfo.Update;
|
|
if FindNodeViewInfo(ANewNode, AViewInfo) then AViewInfo.Update;
|
|
FNeedUpdatePos := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.MakeNodeVisible(ANode: TcxTreeListNode);
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
if (ANode = nil) or not ANode.IsVisible or
|
|
(FindNodeViewInfo(ANode, AViewInfo) and (AViewInfo.Index < VisibleCount)) then Exit;
|
|
if ANode.FVisibleIndex <= TopVisibleIndex then
|
|
TreeList.SetTopVisibleNode(ANode)
|
|
else
|
|
if (ANode.FVisibleIndex - TopVisibleIndex) = VisibleCount then
|
|
Owner.DoScrollVertical(1)
|
|
else
|
|
SetLastVisibleNode(ANode);
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.MoveFirstToLatest(
|
|
ACheckedOne: Boolean = True): Integer;
|
|
var
|
|
AItem: Pointer;
|
|
begin
|
|
Result := 0;
|
|
if Count < 1 then Exit;
|
|
if (ACheckedOne and (Count > 1)) or not ACheckedOne then
|
|
begin
|
|
AItem := FNodes^[0];
|
|
Dec(Count);
|
|
if Count > 0 then
|
|
begin
|
|
System.Move(FNodes^[1], FNodes^[0], Count * SizeOf(Pointer));
|
|
FNodes^[Count] := AItem;
|
|
end;
|
|
Result := TcxTreeListNodeViewInfo(AItem).RealHeight;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.NeedUpdatePost;
|
|
begin
|
|
FUpdatePost := True;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.NeedViewInfoUpdatePost;
|
|
begin
|
|
FNeedSynchronize := True;
|
|
FNeedUpdatePos := True;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.PostViewInfoUpdate: Boolean;
|
|
begin
|
|
if FNeedUpdatePos then
|
|
begin
|
|
UpdatePostCalculate;
|
|
FNeedUpdatePos := False;
|
|
TreeList.HitTest.Recalculate;
|
|
Result := True;
|
|
TreeList.DoChanged;
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.PostUpdate;
|
|
begin
|
|
if FUpdatePost then UpdateSelectedNodes;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.ProcessNodes(
|
|
ATopNode: TcxTreeListNode; ANeedLastVisible: Boolean);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
PrevH: Integer;
|
|
IsBreak: Boolean;
|
|
begin
|
|
if (TreeList.VisibleColumnCount = 0) or (TopNode = nil) then
|
|
begin
|
|
VisibleCount := 0;
|
|
Exit;
|
|
end;
|
|
NeedViewInfoUpdatePost;
|
|
TreeList.Controller.EditingController.PostEditUpdate;
|
|
try
|
|
ANode := ATopNode;
|
|
IsBreak := False;
|
|
PrevH := 0;
|
|
repeat
|
|
while (ANode <> nil) and not IsBreak do
|
|
PrevH := ProcessAddNode(ANode, IsBreak);
|
|
if (ANode = nil) and not IsBreak then
|
|
begin
|
|
ChangeDirection;
|
|
ANode := GetNextNodeForProcess
|
|
end;
|
|
if IsBreak and ANeedLastVisible and IsAddFirst then
|
|
begin
|
|
Dec(NodesBottom, PrevH);
|
|
IsBreak := NodesBottom > ClipRect.Bottom;
|
|
MoveFirstToLatest;
|
|
ChangeDirection;
|
|
ANode := GetNextNodeForProcess;
|
|
if IsAddFirst then Break;
|
|
end;
|
|
until (ANode = nil) or IsBreak or (Count = TreeList.Nodes.VisibleCount);
|
|
VisibleCount := Count;
|
|
if IsBreak and (Count > 1) then Dec(VisibleCount);
|
|
if Count > 0 then
|
|
TopNode := Nodes[0].Node;
|
|
|
|
finally
|
|
IsAddFirst := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.SetLastVisibleNode(ANode: TcxTreeListNode);
|
|
begin
|
|
IsAddFirst := True;
|
|
NodesBottom := ClipRect.Top;
|
|
Count := 0;
|
|
VisibleCount := 0;
|
|
ProcessNodes(ANode, True);
|
|
Owner.InvalidateScrollRect(dsdVert);
|
|
UpdatePostCalculate;
|
|
SynchronizeTopNode;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.SynchronizeTopNode;
|
|
begin
|
|
with TreeList.Nodes do
|
|
begin
|
|
TopNode := Self.TopNode;
|
|
if TopNode <> nil then
|
|
TopIndex := TopNode.VisibleIndex;
|
|
TreeList.VScrollBar.Position := TopIndex;
|
|
if Self.VisibleCount < VisibleCount then
|
|
TreeList.VScrollBar.PageSize := Self.VisibleCount;
|
|
FNeedSynchronize := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.UpdatePostCalculate;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
NodesBottom := ClipRect.Top;
|
|
VisibleCount := 0;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
with Nodes[I] do
|
|
begin
|
|
UpdatePostCalculate(NodesBottom, I);
|
|
Inc(NodesBottom, RealHeight);
|
|
SpaceArea.Top := NodesBottom;
|
|
if NodesBottom > Self.ClipRect.Bottom then Break;
|
|
Inc(VisibleCount);
|
|
end;
|
|
end;
|
|
if VisibleCount = 0 then VisibleCount := 1;
|
|
if Count > VisibleCount then Count := VisibleCount + 1;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.UpdateData;
|
|
|
|
procedure CheckNodeIndicator(ANode: TcxTreeListNodeViewInfo);
|
|
begin
|
|
ANode.Indicator.UpdateKind(ANode.GetNodeIndicatorKind);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if OptionsView.Indicator then
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
CheckNodeIndicator(Nodes[I]);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListNodesViewInfo.UpdateSelectedNodes;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not TreeList.IsLocked then
|
|
begin
|
|
CancelUpdatePost;
|
|
for I := 0 to Count - 1 do
|
|
Nodes[I].Update;
|
|
TreeList.DoChanged;
|
|
end
|
|
else
|
|
NeedUpdatePost;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetGroupViewInfoItemClass: TcxTreeListCellsGroupViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListCellsGroupViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetEditCellViewInfoItemClass: TcxTreeListEditCellViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListEditCellViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetIndentViewInfoItemClass: TcxTreeListIndentViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListIndentViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetNodePreviewViewInfoClass: TcxTreeListNodePreviewViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListNodePreviewViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetNodeViewInfoClass: TcxTreeListNodeViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListNodeViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetMaxVisibleIndex: Integer;
|
|
begin
|
|
Result := TreeList.Nodes.VisibleCount - 1;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetNextNodeFromViewInfo(
|
|
Index: Integer): TcxTreeListNode;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if Index < 0 then
|
|
Result := nil
|
|
else
|
|
begin
|
|
Result := Nodes[Index].Node;
|
|
ANode := Result.GetNextVisibleEx(IsAddFirst);
|
|
if ANode = nil then
|
|
begin
|
|
ChangeDirection;
|
|
Result := Nodes[0].Node;
|
|
ANode := Result.GetNextVisibleEx(IsAddFirst);
|
|
end;
|
|
Result := ANode;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetNextNodeForProcess: TcxTreeListNode;
|
|
begin
|
|
if IsAddFirst then
|
|
Result := GetNextNodeFromViewInfo(0)
|
|
else
|
|
Result := GetNextNodeFromViewInfo(Count - 1);
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetNodeViewInfo(
|
|
Index: Integer): TcxTreeListNodeViewInfo;
|
|
begin
|
|
Result := TcxTreeListNodeViewInfo(FNodes^[Index]);
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetOptionsView: TcxTreeListOptionsView;
|
|
begin
|
|
Result := Owner.OptionsView;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetScrollWindow: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetTopVisibleIndex: Integer;
|
|
begin
|
|
if TopNode <> nil then
|
|
Result := TopNode.VisibleIndex
|
|
else
|
|
Result := TreeList.Nodes.TopIndex;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Owner.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListNodesViewInfo.ProcessAddNode(
|
|
var ANode: TcxTreeListNode; var IsBreak: Boolean): Integer;
|
|
begin
|
|
IsBreak := NodesBottom > ClipRect.Bottom;
|
|
Result := 0;
|
|
if IsBreak then Exit;
|
|
Add(ANode, Result);
|
|
Inc(NodesBottom, Result);
|
|
IsBreak := NodesBottom > ClipRect.Bottom;
|
|
ANode := ANode.GetNextVisibleEx(IsAddFirst);
|
|
end;
|
|
|
|
{ TcxTreeListHitTest }
|
|
|
|
function TcxTreeListHitTest.CanMoving: Boolean;
|
|
var
|
|
ADirection: TcxDragSizingDirection;
|
|
begin
|
|
Result := (HitAtBandHeader and HitBand.CanMoving) or
|
|
(HitAtColumnHeader and HitColumn.CanMoving) and not CanSizing(ADirection);
|
|
end;
|
|
|
|
function TcxTreeListHitTest.CanSizing: Boolean;
|
|
var
|
|
ADir: TcxDragSizingDirection;
|
|
begin
|
|
Result := CanSizing(ADir);
|
|
end;
|
|
|
|
type
|
|
TcxHotTrackControllerAccess = class(TcxHotTrackController);
|
|
|
|
function TcxTreeListHitTest.CanSizing(
|
|
var ASizeDirection: TcxDragSizingDirection): Boolean;
|
|
|
|
function SetValue(Condition: Boolean; ADirection: TcxDragSizingDirection): Boolean;
|
|
begin
|
|
Result := Condition;
|
|
if Result then ASizeDirection := ADirection;
|
|
end;
|
|
|
|
var
|
|
AItem: TObject;
|
|
AIntf: IcxDragSizing;
|
|
ARect: TRect;
|
|
begin
|
|
Result := HitAtBandHeader or HitAtColumnHeader or HitAtNode;
|
|
if not Result then Exit;
|
|
if HitAtBandHeader then
|
|
FNewHitTestItem := FHitBand.ViewInfo.FBandHeader
|
|
else
|
|
if HitAtColumnHeader then
|
|
FNewHitTestItem := FHitColumn.ViewInfo.FColumnHeader;
|
|
AItem := FNewHitTestItem;
|
|
if not HitAtNode then
|
|
begin
|
|
ARect := TcxCustomViewInfoItem(FNewHitTestItem).VisibleRect;
|
|
with ARect do
|
|
begin
|
|
Result := SetValue(Abs(Right - HitX) <= cxtlHitDelta, dsdHorz) or
|
|
SetValue(Abs(Bottom - HitY) <= cxtlHitDelta, dsdVert)
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ARect := HitNode.DisplayRect(False);
|
|
FSizingHitNode := HitNode;
|
|
if HitNode <> TreeList.TopVisibleNode then
|
|
begin
|
|
if cxInRange(HitY, ARect.Top - cxtlHitDelta, ARect.Top + cxtlHitDelta) then
|
|
begin
|
|
FSizingHitNode := HitNode.GetPrevVisible;
|
|
ARect := HitNode.DisplayRect(False);
|
|
end;
|
|
end;
|
|
AItem := FSizingHitNode;
|
|
with ARect do
|
|
Result := SetValue(cxInRange(HitY, Bottom - cxtlHitDelta * 2,
|
|
Bottom + cxtlHitDelta), dsdVert);
|
|
end;
|
|
Result := Result and Supports(AItem, IcxDragSizing, AIntf) and
|
|
AIntf.CanSizing(ASizeDirection);
|
|
end;
|
|
|
|
function TcxTreeListHitTest.AllowDesignMouseEvents(
|
|
X, Y: Integer; AShift: TShiftState): Boolean;
|
|
begin
|
|
Result := inherited AllowDesignMouseEvents(X, Y, AShift);
|
|
Result := Result or (TreeList.DragAndDropState <> ddsNone) or HitAtBandContainer or
|
|
HitAtBandHeader or HitAtColumnHeader or CanSizing or HitAtButton;
|
|
end;
|
|
|
|
procedure TcxTreeListHitTest.DoCalculate;
|
|
var
|
|
ADir: TcxDragSizingDirection;
|
|
const
|
|
ASizingFlags: array[TcxDragSizingDirection] of Integer =
|
|
(tlhc_HitAtSizingHorz, tlhc_HitAtSizingVert);
|
|
begin
|
|
FHitBand := nil;
|
|
FHitColumn := nil;
|
|
FHitNode := nil;
|
|
FNewHitTestItem := nil;
|
|
try
|
|
if not cxRectPtIn(TreeList.ClientBounds, HitPoint) then Exit;
|
|
with ViewInfo do
|
|
begin
|
|
NodesViewInfo.PostViewInfoUpdate;
|
|
if cxRectPtIn(FSeparators[0], HitPoint) or
|
|
cxRectPtIn(FSeparators[1], HitPoint) then SetHitState(tlhc_HitAtSeparator, True);
|
|
if not CheckHitInBands then CheckHitInNodes;
|
|
end;
|
|
if not (HitAtNode and HitAtColumn) then
|
|
begin
|
|
FNewHitTestItem := GetHitTestItem;
|
|
if CanSizing(ADir) then SetHitState(ASizingFlags[ADir], True);
|
|
end;
|
|
finally
|
|
HitTestItem := FNewHitTestItem;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.Check(const ARect: TRect): Boolean;
|
|
begin
|
|
Result := cxRectPtIn(ARect, HitPoint);
|
|
end;
|
|
|
|
function TcxTreeListHitTest.CheckHitInBands: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with TreeList.OptionsView do
|
|
begin
|
|
Result := (HitPoint.Y <= ViewInfo.CellsOffset) or
|
|
(Footer and (HitPoint.Y >= ViewInfo.FooterRect.Top));
|
|
end;
|
|
if Result then
|
|
with ViewInfo do
|
|
begin
|
|
Result := CheckHitInBand(LeftFixedBand) or CheckHitInBand(RightFixedBand);
|
|
if not Result then
|
|
for I := 0 to FBandCount - 1 do
|
|
if CheckHitInBand(TcxTreeListBandViewInfo(FBands^[I])) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.CheckHitInNodes: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with ViewInfo.NodesViewInfo do
|
|
begin
|
|
Result := VisibleCount > 0;
|
|
if Result then
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
Result := CheckHitInNode(Nodes[I]);
|
|
if Result then Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.GetCurrentCursor: TCursor;
|
|
var
|
|
ADirection: TcxDragSizingDirection;
|
|
const
|
|
ACursors: array[Boolean, TcxDragSizingDirection] of TCursor =
|
|
((crcxHorzSize, crcxVertSize), (crHSplit, crVSplit));
|
|
begin
|
|
Result := inherited GetCurrentCursor;
|
|
if (TreeList.DragAndDropState = ddsInProcess) and
|
|
not (TreeList.DragAndDropObject is TcxSizingDragAndDropObject) then Exit;
|
|
if (Result = crDefault) and CanSizing(ADirection) then
|
|
Result := ACursors[TreeList.DragAndDropState <> ddsNone, ADirection];
|
|
end;
|
|
|
|
function TcxTreeListHitTest.GetHitTestItem: TObject;
|
|
begin
|
|
Result := nil;
|
|
if HitAtBandHeader and
|
|
cxPtInViewInfoItem(FHitBand.ViewInfo.FBandHeader, HitPoint) then
|
|
Result := FHitBand.ViewInfo.FBandHeader;
|
|
if HitAtColumnHeader and
|
|
cxPtInViewInfoItem(FHitColumn.ViewInfo.FColumnHeader, HitPoint) then
|
|
Result := FHitColumn.ViewInfo.FColumnHeader;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := (HitState and (1 shl Index)) <> 0;
|
|
end;
|
|
|
|
procedure TcxTreeListHitTest.HitTestItemChanged(APrevHitTestItem: TObject);
|
|
|
|
procedure CheckHeader(AViewInfo: TObject);
|
|
begin
|
|
if AViewInfo is TcxTreeListHeaderViewInfo then
|
|
TcxTreeListHeaderViewInfo(AViewInfo).UpdateState;
|
|
end;
|
|
|
|
var
|
|
AHitPoint: TPoint;
|
|
begin
|
|
if FLockUpdate then Exit;
|
|
FLockUpdate := True;
|
|
try
|
|
AHitPoint := HitPoint;
|
|
if TreeList.DragAndDropState = ddsNone then
|
|
begin
|
|
CheckHeader(APrevHitTestItem);
|
|
CheckHeader(HitTestItem);
|
|
end;
|
|
inherited HitTestItemChanged(APrevHitTestItem);
|
|
finally
|
|
HitPoint := AHitPoint;
|
|
FLockUpdate := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListHitTest.SetHitState(Index: Integer; Value: Boolean);
|
|
begin
|
|
if Value then
|
|
FHitState := FHitState or (1 shl Index)
|
|
else
|
|
FHitState := FHitState and not (1 shl Index);
|
|
end;
|
|
|
|
procedure TcxTreeListHitTest.Update;
|
|
var
|
|
P: TPoint;
|
|
begin
|
|
IsMouseEvent := True;
|
|
try
|
|
HitTestItem := nil;
|
|
GetCursorPos(P);
|
|
HitPoint := TreeList.ScreenToClient(P);
|
|
finally
|
|
IsMouseEvent := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.CheckHitInBand(AViewInfo: TcxTreeListBandViewInfo): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
if AViewInfo = nil then Exit;
|
|
with AViewInfo, OptionsView do
|
|
begin
|
|
I := cxHitDelta(Band.CanSizing(dsdHorz));
|
|
with ClipRect do
|
|
Result := cxCheckValue(HitX, Left, Right + I);
|
|
if Result then
|
|
begin
|
|
SetHitState(tlhc_HitAtBand, Result);
|
|
FHitBand := AViewInfo.Band;
|
|
if Bands or Headers or Footer then
|
|
begin
|
|
if Bands and HitInItem(BandHeader, tlhc_HitAtBandHeader, I) then Exit;
|
|
for I := 0 to FCount - 1 do
|
|
if CheckHitInColumn(TcxTreeListColumnViewInfo(FColumns^[I])) then Exit;
|
|
if Headers then
|
|
SetHitState(tlhc_HitAtBandContainer,
|
|
cxCheckValue(HitY, ClipRect.Top, ClipRect.Bottom));
|
|
if Footer then
|
|
SetHitState(tlhc_HitAtFooter,
|
|
cxCheckValue(HitY, ViewInfo.FooterOffset, ViewInfo.ClientRect.Bottom));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.CheckHitInColumn(
|
|
AViewInfo: TcxTreeListColumnViewInfo): Boolean;
|
|
var
|
|
ADelta: Integer;
|
|
begin
|
|
with AViewInfo, OptionsView do
|
|
begin
|
|
with Column do
|
|
ADelta := cxMax(cxHitDelta(CanSizing(dsdVert)), cxHitDelta(CanSizing(dsdHorz)));
|
|
Result := (HitInItem(ColumnFooter, tlhc_HitAtFooterItem)) or
|
|
(Headers and HitInItem(ColumnHeader, tlhc_HitAtColumnHeader, ADelta));
|
|
if Result then
|
|
begin
|
|
FHitColumn := Column;
|
|
SetHitState(tlhc_HitAtColumn, True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.CheckHitInNode(
|
|
AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
begin
|
|
Result := HitInIndent(AViewInfo);
|
|
if AViewInfo.IsGroupNode then
|
|
begin
|
|
if not Result and HitInItem(AViewInfo.NodeGroupEditViewInfo, tlhc_HitAtColumn) then
|
|
begin
|
|
SetHitState(tlhc_HitAtBand, True);
|
|
FHitColumn := AViewInfo.NodeGroupEditViewInfo.Column;
|
|
FNewHitTestItem := AViewInfo.NodeGroupEditViewInfo;
|
|
FHitBand := TreeList.VisibleBands[0];
|
|
Result := True;
|
|
end
|
|
end
|
|
else
|
|
Result := Result or HitInGroups(AViewInfo) or
|
|
(AViewInfo.HasPreview and HitInItem(AViewInfo.Preview, tlhc_HitAtNodePreview));
|
|
Result := Result or (TreeList.OptionsView.Indicator and
|
|
HitInItem(AViewInfo.Indicator, tlhc_HitAtIndicator));
|
|
if Result then
|
|
begin
|
|
SetHitState(tlhc_HitAtNode, True);
|
|
FHitNode := AViewInfo.Node;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.HitInGroup(AViewInfo: TcxTreeListCellsGroupViewInfo): Boolean;
|
|
|
|
function CheckHitCell(ACell: TcxTreeListEditCellViewInfo): Boolean;
|
|
begin
|
|
Result := ACell.Visible and Check(ACell.ClipRect);
|
|
if Result then
|
|
begin
|
|
SetHitState(tlhc_HitAtColumn, True);
|
|
FHitColumn := ACell.Column;
|
|
FNewHitTestItem := ACell;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
Result := Visible and Check(ClipRect);
|
|
if Result then
|
|
begin
|
|
SetHitState(tlhc_HitAtBand, True);
|
|
FHitBand := Band;
|
|
for I := 0 to CellCount - 1 do
|
|
if CheckHitCell(Cells[I]) then Break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.HitInGroups(AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to AViewInfo.GroupCount - 1 do
|
|
if HitInGroup(AViewInfo.Groups[I]) then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.HitInIndent(AViewInfo: TcxTreeListNodeViewInfo): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
with AViewInfo do
|
|
begin
|
|
for I := 0 to IndentCount - 1 do
|
|
with Indents[I] do
|
|
begin
|
|
if Check(Indents[I].ClipRect) then
|
|
begin
|
|
SetHitState(tlhc_HitAtIndent, True);
|
|
if not IsLevel then
|
|
SetHitState(tlhc_HitAtImage + Byte(IndentStateImage), True)
|
|
else
|
|
if HasButton and Check(cxRectInflate(ButtonRect, cxtlHitDelta, cxtlHitDelta)) then
|
|
SetHitState(tlhc_HitAtButton, True);
|
|
if HitAtImage or HitAtStateImage then
|
|
SetHitState(tlhc_HitAtIndent, False);
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.HitInItem(
|
|
AItem: TcxCustomViewInfoItem; AState: Integer; ADelta: Integer = 0): Boolean;
|
|
begin
|
|
Result := (AItem <> nil) and AItem.Visible and
|
|
cxRectPtIn(cxRectInflate(AItem.VisibleRect, 0, 0, ADelta, ADelta), HitPoint);
|
|
if Result then SetHitState(AState, True);
|
|
end;
|
|
|
|
function TcxTreeListHitTest.GetHitAtImages: Boolean;
|
|
begin
|
|
Result := HitAtImage or HitAtStateImage;
|
|
end;
|
|
|
|
function TcxTreeListHitTest.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(Control);
|
|
end;
|
|
|
|
function TcxTreeListHitTest.GetViewInfo: TcxTreeListViewInfo;
|
|
begin
|
|
Result := TcxTreeListViewInfo(inherited ViewInfo);
|
|
end;
|
|
|
|
{ TcxTreeListViewInfo }
|
|
|
|
constructor TcxTreeListViewInfo.Create(AOwner: TcxEditingControl);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FooterBrush := TBrush.Create;
|
|
GridLinesBrush := TBrush.Create;
|
|
SeparatorBrush := TBrush.Create;
|
|
HeaderIndicator := GetIndicatorViewInfoClass.Create(Self);
|
|
FooterIndicator := GetIndicatorViewInfoClass.Create(Self);
|
|
FNodesViewInfo := GetNodesViewInfoClass.Create(Self);
|
|
SizingViewInfo := TcxTemporaryCellViewInfo.Create(Self);
|
|
end;
|
|
|
|
destructor TcxTreeListViewInfo.Destroy;
|
|
begin
|
|
try
|
|
FreeAndNil(SizingViewInfo);
|
|
FreeAndNil(HeaderIndicator);
|
|
FreeAndNil(FooterIndicator);
|
|
FreeMem(FBands);
|
|
FreeAndNil(FNodesViewInfo);
|
|
finally
|
|
FooterBrush.Free;
|
|
GridLinesBrush.Free;
|
|
SeparatorBrush.Free;
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.InvalidateScrollRect(
|
|
ADirection: TcxDragSizingDirection);
|
|
begin
|
|
if (ADirection = dsdHorz) and ScrollingAreaVisible then
|
|
InvalidateRect(ScrollingArea)
|
|
else
|
|
if ADirection = dsdVert then
|
|
with NodesViewInfo.ClipRect do
|
|
InvalidateRect(cxRectSetTop(ClientRect, Top, Bottom - Top));
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.CalculateDefaultHeights;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TreeList.Styles.ContentStyleChanged;
|
|
FooterLineHeight := 0;
|
|
if BandLineHeight <> 0 then
|
|
TreeList.FRealBandLineHeight := BandLineHeight;
|
|
HeaderLineHeight := 0;
|
|
BandLineHeight := 0;
|
|
FillChar(FFixedBands, SizeOf(FFixedBands), 0);
|
|
with TreeList do
|
|
begin
|
|
SetBandCount(VisibleBandCount);
|
|
FBandCount := 0;
|
|
for I := 0 to VisibleBandCount - 1 do SetBandViewParams(VisibleBands[I], I);
|
|
HeaderLineHeight := LookAndFeelPainter.HeaderHeight(cxTextHeight(TreeList.Font));
|
|
if VisibleColumnCount = 0 then
|
|
TreeList.FHeaderLineCount := 0
|
|
else
|
|
for I := 0 to VisibleColumnCount - 1 do SetColumnViewParams(VisibleColumns[I]);
|
|
HorzScrollInc := cxTextWidth(Font, 'W');
|
|
if (VisibleBandCount > 0) then
|
|
cxSetMax(BandLineHeight, LookAndFeelPainter.HeaderHeight(cxTextHeight(TreeList.Font)));
|
|
end;
|
|
if FooterLineHeight = 0 then
|
|
with LookAndFeelPainter do
|
|
FooterLineHeight := HeaderHeight(cxTextHeight(TreeList.Font)) + FooterCellBorderSize;
|
|
inherited CalculateDefaultHeights;
|
|
if BandLineHeight <> 0 then
|
|
TreeList.FRealBandLineHeight := BandLineHeight;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.CalculateDefaultEditHeight: Integer;
|
|
|
|
function GetColumnEditHeight(AColumn: TcxTreeListColumn): Integer;
|
|
begin
|
|
with AColumn, Styles do
|
|
begin
|
|
Result := GetEditDefaultHeight(ContentParams[True].Font);
|
|
cxSetMax(Result, GetEditDefaultHeight(ContentParams[False].Font));
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
|
|
begin
|
|
Result := 0;
|
|
with TreeList do
|
|
begin
|
|
for I := 0 to VisibleColumnCount - 1 do
|
|
Result := cxMax(Result, GetColumnEditHeight(VisibleColumns[I]));
|
|
Inc(Result, OptionsView.VertIncrement + cxTreeListEditCellHeightOffset);
|
|
Self.FDefaultRowHeight := Result + cxTextOffset;
|
|
if Images <> nil then
|
|
cxSetMax(Result, GetImageListHeight(Images));
|
|
if StateImages <> nil then
|
|
cxSetMax(Result, GetImageListHeight(StateImages));
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.CalculateDefaultViewParams;
|
|
|
|
function GetBitmap(AStyle: TcxStyle): TBitmap;
|
|
begin
|
|
if AStyle <> nil then
|
|
Result := AStyle.Bitmap
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
begin
|
|
IndicatorViewParams := TreeList.Styles.GetIndicatorParams;
|
|
with BrushManager, OptionsView, LookAndFeelPainter do
|
|
begin
|
|
Self.TreeLineColor := cxGetNativeColor(TreeLineColor, DefaultGridLineColor);
|
|
GridLinesBrush.Color := cxGetNativeColor(GridLineColor, DefaultGridLineColor);
|
|
if TreeLineColor <> clDefault then
|
|
Self.TreeLineColor := ColorToRGB(TreeLineColor);
|
|
SeparatorBrush.Color :=
|
|
cxGetNativeColor(FixedSeparatorColor, DefaultFixedSeparatorColor);
|
|
BackgroundBitmap := GetBitmap(TreeList.Styles.Background);
|
|
FooterBitmap := GetBitmap(TreeList.Styles.Footer);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.CalculateHeaderFooterViewInfo;
|
|
var
|
|
I: Integer;
|
|
AOfs: Integer;
|
|
R: TRect;
|
|
begin
|
|
FScrollingArea := ClientRect;
|
|
AOfs := cxRectWidth(ClientRect) - cxRectWidth(PrevClientRect);
|
|
if (PrevHorzScrollSize - HorzScrollPos - HorzScrollPage) < AOfs then
|
|
begin
|
|
Dec(HorzScrollPos, AOfs);
|
|
cxValidateIntDef(HorzScrollPos, 0, PrevHorzScrollSize);
|
|
end;
|
|
R := Rect(0, BorderSize, 0, BorderSize + BandLineHeight * OptionsView.BandLineCount +
|
|
HeaderLineHeight * TreeList.HeaderLineCount);//CellsOffset);
|
|
AOfs := ContentOffset;
|
|
if LeftFixedBand = nil then Dec(AOfs, HorzScrollPos);
|
|
if OptionsView.Footer and (TreeList.VisibleColumnCount > 0) then
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
FooterColor := Styles.GetFooterParams.Color;
|
|
FooterBrush.Color := FooterColor;
|
|
end;
|
|
with ClientRect, LookAndFeelPainter do
|
|
FooterRect := cxRectInflate(cxRect(ContentOffset, FooterOffset, Right, Bottom),
|
|
-FooterBorderSize, -FooterBorderSize);
|
|
end;
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
with VisibleBands[I] do
|
|
begin
|
|
AOfs := CalcBandRect(R, DisplayWidth, AOfs, Fixed);
|
|
Calculate(R, ClientRect);
|
|
end;
|
|
with OptionsView do
|
|
begin
|
|
if Indicator then Inc(HorzScrollSize, IndicatorWidth);
|
|
if (TreeList.VisibleColumnCount = 0) and not Bands then HorzScrollSize := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.CheckScrolling;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
HorzScrollPage := cxRectWidth(ClientRect);
|
|
if HorzScrollSize < (HorzScrollPage + HorzScrollPos) then
|
|
HorzScrollPos := HorzScrollSize - HorzScrollPage;
|
|
if HorzScrollSize <= HorzScrollPage then
|
|
begin
|
|
HorzScrollPos := 0;
|
|
HorzScrollSize := 0;
|
|
end
|
|
else
|
|
cxValidateIntDef(HorzScrollPos, 0, HorzScrollSize - HorzScrollPage + 1);
|
|
FScrollingAreaVisible := cxRectIntersect(R, ClientRect, FScrollingArea) or
|
|
(ContentRect.Right >= ClientRect.Right);
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.DoCalculate;
|
|
begin
|
|
inherited DoCalculate;
|
|
IsDirty := False;
|
|
if TreeList.VisibleBandCount <> BandCount then
|
|
begin
|
|
SetBandCount(TreeList.VisibleBandCount);
|
|
CalculateDefaultHeights;
|
|
end;
|
|
ExpandButtonSize := LookAndFeelPainter.SmallExpandButtonSize;
|
|
HorzScrollSize := 0;
|
|
FillChar(FSeparators, SizeOf(FSeparators), 0);
|
|
CalculateHeaderFooterViewInfo;
|
|
CalculateCellRects;
|
|
CheckScrolling;
|
|
PrevHorzScrollSize := HorzScrollSize;
|
|
NodesViewInfo.DoCalculate;
|
|
HeaderRect := ClientRect;
|
|
HeaderRect.Bottom := CellsOffset;
|
|
cxCalcSeparators(HeaderSeparators, FSeparators, cxRectSetHeight(ClientRect, CellsOffset));
|
|
cxCalcSeparators(FooterSeparators, FSeparators,
|
|
cxRectInflate(cxRectSetTop(ClientRect, FooterOffset), 0, -LookAndFeelPainter.FooterBorderSize));
|
|
HeaderIndicator.Calculate(HeaderRect, HeaderRect);
|
|
HeaderIndicator.ItemViewParams.Color := TreeList.Styles.GetIndicatorParams().Color;
|
|
FooterRect.Right := ContentRect.Right;
|
|
FooterIndicator.Calculate(
|
|
cxRectInflate(FooterRect, 0, LookAndFeelPainter.FooterBorderSize), ClientRect);
|
|
FooterIndicator.ItemViewParams := TreeList.Styles.GetIndicatorParams;
|
|
CalculateDefaultViewParams;
|
|
PrevClientRect := ClientRect;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.DoScrollHorizontal(APos: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
try
|
|
for I := 0 to BandCount - 1 do
|
|
Bands[I].DoHorzOffset(HorzScrollPos - APos);
|
|
NodesViewInfo.DoHorzOffset(HorzScrollPos - APos);
|
|
finally
|
|
HorzScrollPos := APos;
|
|
InvalidateScrollRect(dsdHorz);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.DoScrollVertical(APos: Integer);
|
|
begin
|
|
TreeList.Nodes.CalculateInfo(False);
|
|
NodesViewInfo.DoVertOffset(APos);
|
|
NodesViewInfo.NeedViewInfoUpdatePost;
|
|
InvalidateScrollRect(dsdVert);
|
|
NodesViewInfo.SynchronizeTopNode;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetIndicatorViewInfoClass: TcxTreeListIndicatorViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListIndicatorViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetNodesViewInfoClass: TcxTreeListNodesViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListNodesViewInfo;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.InvalidateRect(const ARect: TRect);
|
|
begin
|
|
with TreeList do
|
|
if not IsLocked then InvalidateRect(ARect, False);
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.UpdateSelection;
|
|
begin
|
|
inherited UpdateSelection;
|
|
NodesViewInfo.UpdateSelectedNodes;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.UpdateFootersViewInfo;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].ViewInfo.FColumnFooter.Invalidate(False);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetBand(AIndex: Integer): TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := TcxTreeListBandViewInfo(FBands^[AIndex]);
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetBorderSize: Integer;
|
|
begin
|
|
Result := TreeList.BorderSize;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetBrushManager: TcxBrushCache;
|
|
begin
|
|
Result := TreeList.BrushCache;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetCellsHeight: Integer;
|
|
begin
|
|
Result := FooterOffset - CellsOffset;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetCellsOffset: Integer;
|
|
begin
|
|
with TreeList, OptionsView do
|
|
Result := HeaderOffset + Byte(Headers) * HeaderLineHeight * HeaderLineCount;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetContentOffset: Integer;
|
|
begin
|
|
with OptionsView do
|
|
Result := BorderSize + Byte(Indicator) * IndicatorWidth;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetDefaultHeight: Integer;
|
|
begin
|
|
Result := DefaultEditHeight;
|
|
if TreeList.FDefaultRowHeight <> 0 then
|
|
Result := TreeList.FDefaultRowHeight;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetFooterOffset: Integer;
|
|
begin
|
|
with TreeList, LookAndFeelPainter do
|
|
Result := Self.ClientRect.Bottom -
|
|
Byte(OptionsView.Footer) * Byte(TreeList.VisibleColumnCount > 0) *
|
|
(HeaderLineCount * FooterLineHeight + FooterBorderSize shl 1);
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetHeaderOffset: Integer;
|
|
begin
|
|
with OptionsView do
|
|
Result := BorderSize + Byte(Bands) * BandLineHeight * BandLineCount;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetLeftFixedBand: TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := FFixedBands[0];
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetOptionsView: TcxTreeListOptionsView;
|
|
begin
|
|
Result := TreeList.OptionsView;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetRightFixedBand: TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := FFixedBands[1];
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(Control)
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetVisibleBand(Index: Integer): TcxTreeListBandViewInfo;
|
|
begin
|
|
Result := TreeList.VisibleBands[Index].ViewInfo;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.GetVisibleBandCount: Integer;
|
|
begin
|
|
Result := TreeList.VisibleBandCount;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.SetBandCount(ACount: Integer);
|
|
begin
|
|
if ACount > FBandCapacity then
|
|
ReallocMem(FBands, ACount * SizeOf(Pointer));
|
|
FBandCount := ACount;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.SetBandViewParams(
|
|
ABand: TcxTreeListBand; Index: Integer);
|
|
begin
|
|
if ABand.FixedKind = tlbfNone then
|
|
begin
|
|
FBands^[FBandCount] := ABand.ViewInfo;
|
|
Inc(FBandCount);
|
|
end
|
|
else
|
|
FFixedBands[Byte(ABand.FixedKind) - 1] := ABand.ViewInfo;
|
|
with ABand.ViewInfo, TreeList.Styles do
|
|
begin
|
|
ItemViewParams := SetHeaderSizeValue(GetBandHeaderParams(ABand),
|
|
BandLineHeight, OptionsView.Bands);
|
|
FContainerViewParams := GetBandBackgroundParams(ABand);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.SetColumnViewParams(AColumn: TcxTreeListColumn);
|
|
begin
|
|
with AColumn.ViewInfo, TreeList.Styles, OptionsView do
|
|
begin
|
|
FColumnHeader.ItemViewParams :=
|
|
SetHeaderSizeValue(GetColumnHeaderParams(AColumn), Self.HeaderLineHeight, Headers);
|
|
with Painter.Painter do
|
|
FColumnFooter.ItemViewParams := SetHeaderSizeValue(GetColumnFooterParams(AColumn),
|
|
Self.FooterLineHeight, Footer, FooterCellBorderSize shl 1);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.CalcBandRect(var ARect: TRect;
|
|
AWidth, AOfs: Integer; Fixed: TcxTreeListBandFixedKind): Integer;
|
|
begin
|
|
with OptionsView do
|
|
begin
|
|
Inc(HorzScrollSize, AWidth);
|
|
if Fixed = tlbfRight then
|
|
begin
|
|
Inc(AOfs, FFixedSeparatorWidth);
|
|
if AOfs > (ClientRect.Right - AWidth) then
|
|
AOfs := ClientRect.Right - AWidth;
|
|
if (LeftFixedBand <> nil) and (AOfs < FSeparators[0].Right) then
|
|
AOfs := FSeparators[0].Right;
|
|
FSeparators[1] := cxRectSetWidth(ClientRect,
|
|
AOfs - FixedSeparatorWidth, FixedSeparatorWidth);
|
|
FScrollingArea.Right := FSeparators[1].Left;
|
|
Inc(HorzScrollSize, FixedSeparatorWidth);
|
|
end;
|
|
Result := AOfs + AWidth;
|
|
ARect.Left := AOfs;
|
|
ARect.Right := Result;
|
|
if Fixed = tlbfLeft then
|
|
begin
|
|
FSeparators[0] := cxRectSetWidth(ClientRect,
|
|
Result, FixedSeparatorWidth);
|
|
Result := FSeparators[0].Right - HorzScrollPos;
|
|
FScrollingArea.Left := FSeparators[0].Right;
|
|
Inc(HorzScrollSize, FixedSeparatorWidth);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListViewInfo.CalculateCellRects;
|
|
|
|
procedure CheckBounds(ADefInfo: TcxTreeListBandViewInfo;
|
|
AIndex: Integer; var ALeft, ARight: Integer);
|
|
var
|
|
AInfo: TcxTreeListBandViewInfo;
|
|
begin
|
|
AInfo := nil;
|
|
if ADefInfo <> nil then
|
|
AInfo := ADefInfo
|
|
else
|
|
if (AIndex < FBandCount) and (AIndex <> cxInvalidIndex) then
|
|
AInfo := TcxTreeListBandViewInfo(FBands^[AIndex]);
|
|
if (AInfo <> nil) and ((ALeft > AInfo.DisplayRect.Left) or (ALeft = -1)) then
|
|
ALeft := AInfo.DisplayRect.Left;
|
|
if (AInfo <> nil) and (ARight < AInfo.DisplayRect.Right) then
|
|
ARight := AInfo.DisplayRect.Right;
|
|
end;
|
|
|
|
begin
|
|
CellsRect := cxInvalidRect;
|
|
CheckBounds(LeftFixedBand, 0, CellsRect.Left, CellsRect.Right);
|
|
CheckBounds(RightFixedBand, FBandCount - 1, CellsRect.Left, CellsRect.Right);
|
|
CellsRect.Top := CellsOffset;
|
|
CellsRect.Bottom := FooterOffset;
|
|
ContentRect := CellsRect;
|
|
if ContentRect.Right > ClientRect.Right then
|
|
ContentRect.Right := ClientRect.Right;
|
|
FooterRect.Right := ClientRect.Right;
|
|
PreviewHeight := 0;
|
|
end;
|
|
|
|
function TcxTreeListViewInfo.SetHeaderSizeValue(const ViewParams: TcxViewParams;
|
|
var ASize: Integer; CheckSize: Boolean; Delta: Integer = 0): TcxViewParams;
|
|
begin
|
|
Result := ViewParams;
|
|
if CheckSize then
|
|
begin
|
|
with ViewParams do
|
|
Delta := Delta shl 1 + LookAndFeelPainter.HeaderHeight(cxTextHeight(Font));
|
|
if Delta > ASize then ASize := Delta;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListControlPainter }
|
|
|
|
procedure TcxTreeListControlPainter.AfterCustomDraw(
|
|
AViewInfo: TcxCustomViewInfoItem);
|
|
begin
|
|
if AViewInfo is TcxTreeListEditCellViewInfo then
|
|
AfterCustomDraw(TcxTreeListEditCellViewInfo(AViewInfo))
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.AfterCustomDraw(
|
|
AViewInfo: TcxTreeListEditCellViewInfo);
|
|
begin
|
|
with AViewInfo.EditViewInfo do
|
|
begin
|
|
BackgroundColor := Canvas.Brush.Color;
|
|
TextColor := Canvas.Font.Color;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.BeforeCustomDraw(
|
|
AViewInfo: TcxCustomViewInfoItem);
|
|
begin
|
|
if AViewInfo is TcxTreeListEditCellViewInfo then
|
|
BeforeCustomDraw(TcxTreeListEditCellViewInfo(AViewInfo))
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.BeforeCustomDraw(
|
|
AViewInfo: TcxTreeListEditCellViewInfo);
|
|
begin
|
|
with AViewInfo.EditViewInfo do
|
|
begin
|
|
if AViewInfo.ViewParams.Font <> nil then
|
|
begin
|
|
Canvas.Brush.Color := AViewInfo.ViewParams.Color;
|
|
if AViewInfo.EditViewInfo.Font <> nil then
|
|
Canvas.Font := AViewInfo.EditViewInfo.Font;
|
|
Canvas.Font.Color := TextColor;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.DoCustomDrawEx(AViewInfoItem: TcxCustomViewInfoItem;
|
|
AEvent: TcxCustomDrawViewInfoItemEvent; AExclude: Boolean): Boolean;
|
|
begin
|
|
Result := DoCustomDraw(AViewInfoItem, AEvent);
|
|
if Result and AExclude then
|
|
Canvas.ExcludeClipRect(AViewInfoItem.VisibleRect);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DoPaint;
|
|
begin
|
|
if TreeList.IsLocked then
|
|
inherited DoPaint
|
|
else
|
|
begin
|
|
with ViewInfo, ContentRect do
|
|
begin
|
|
if Right < ClientRect.Right then
|
|
DrawBackgroundRect(cxRectSetLeft(ClientRect, Right, ClientRect.Right - Right));
|
|
end;
|
|
if Bands or Headers then DrawHeader;
|
|
if IsFooterVisible then DrawFooter;
|
|
ContentClipRegion := Canvas.GetClipRegion;
|
|
try
|
|
DrawNodes;
|
|
finally
|
|
FreeAndNil(ContentClipRegion);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.DoPaintBackground(
|
|
ACanvas: TcxCanvas; const ABounds: TRect): Boolean;
|
|
begin
|
|
Result := CurrentBitmap <> nil;
|
|
if Result then
|
|
ACanvas.FillRect(ABounds, CurrentBitmap);
|
|
CurrentBitmap := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawBackgroundRect(const R: TRect);
|
|
var
|
|
ADone: Boolean;
|
|
begin
|
|
if cxRectIsEmpty(R) or not Canvas.RectVisible(R) then Exit;
|
|
ADone := False;
|
|
if Assigned(TreeList.FOnCustomDrawBackground) then
|
|
TreeList.FOnCustomDrawBackground(TreeList, Canvas, R, ADone);
|
|
if not ADone then
|
|
DrawRect(R, BackgroundBrush, ViewInfo.BackgroundBitmap);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawBandItem(AViewInfo: TcxTreeListBandViewInfo);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not DoCustomDraw(AViewInfo, nil) then
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
if Buffered then
|
|
DrawHeaderRect(VisibleRect, AViewInfo);
|
|
if Bands then
|
|
DrawHeaderItem(AViewInfo.BandHeader, Opaque);
|
|
if Headers then
|
|
for I := 0 to AViewInfo.ColumnCount - 1 do
|
|
DrawHeaderItem(AViewInfo.Columns[I].ColumnHeader, Opaque);
|
|
if not Buffered and not Opaque then
|
|
DrawHeaderRect(VisibleRect, AViewInfo);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawBandFooter(
|
|
AViewInfo: TcxTreeListBandViewInfo);
|
|
|
|
procedure DoDrawBandFooterItem;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to AViewInfo.ColumnCount - 1 do
|
|
DrawFooterItem(AViewInfo.Columns[I].ColumnFooter);
|
|
end;
|
|
|
|
begin
|
|
if (AViewInfo = nil) or not AViewInfo.Visible then Exit;
|
|
if Buffered then
|
|
begin
|
|
DrawFooterRect(AViewInfo.FooterRect, AViewInfo);
|
|
DoDrawBandFooterItem;
|
|
end
|
|
else
|
|
begin
|
|
DoDrawBandFooterItem;
|
|
DrawFooterRect(AViewInfo.FooterRect, AViewInfo);
|
|
end
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawCellsGroup(
|
|
AViewInfo: TcxTreeListCellsGroupViewInfo);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
if not Visible or not Self.Canvas.RectVisible(ClipRect) then Exit;
|
|
if Buffered and not IsOpaque and not DoCustomDraw(AViewInfo,
|
|
TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawCellsGroup)) then
|
|
DrawRectWithBorders(DisplayRect, CurrentBrush, Opaque, Borders, GetGroupBitmap);
|
|
for I := 0 to AViewInfo.CellCount - 1 do
|
|
DrawEditCell(Cells[I], Opaque);
|
|
if not Buffered and not IsOpaque and not DoCustomDraw(AViewInfo,
|
|
TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawCellsGroup)) then
|
|
DrawRectWithBorders(DisplayRect, CurrentBrush, Opaque, Borders, GetGroupBitmap);
|
|
DrawRectWithBorders(DisplayRect, CurrentBrush, True, Borders, GetGroupBitmap);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawEditCell(
|
|
AViewInfo: TcxTreeListEditCellViewInfo; IsOpaque: Boolean);
|
|
var
|
|
AEvent: TcxCustomDrawViewInfoItemEvent;
|
|
AFont: TFont;
|
|
ADone: Boolean;
|
|
begin
|
|
if Canvas.RectVisible(AViewInfo.DisplayRect) then
|
|
begin
|
|
ADone := False;
|
|
DrawRectWithBorders(AViewInfo.DisplayRect, nil, True, AViewInfo.Borders);
|
|
BeforeCustomDraw(AViewInfo);
|
|
if Assigned(TreeList.FOnCustomDrawCell) then
|
|
TreeList.FOnCustomDrawCell(TreeList, Canvas, AViewInfo, ADone);
|
|
AfterCustomDraw(AViewInfo);
|
|
if not ADone then
|
|
begin
|
|
if (AViewInfo.ViewParams.Bitmap <> nil) and not AViewInfo.Selected then
|
|
Canvas.FillRect(AViewInfo.ContentRect, AViewInfo.ViewParams.Bitmap);
|
|
AFont := AViewInfo.EditViewInfo.Font;
|
|
AViewInfo.EditViewInfo.Font := Canvas.Font;
|
|
AViewInfo.CustomDrawEvent(AEvent);
|
|
if not DoCustomDraw(AViewInfo, AEvent) then
|
|
AViewInfo.ViewInfo.PaintEx(Canvas);
|
|
AViewInfo.EditViewInfo.Font := AFont;
|
|
end;
|
|
if not Buffered and not IsOpaque then
|
|
Canvas.ExcludeClipRect(AViewInfo.ClipRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawExpandButton(
|
|
const ARect: TRect; AExpanded: Boolean; ABitmap: TBitmap);
|
|
begin
|
|
if ABitmap <> nil then
|
|
Canvas.FillRect(ARect, ABitmap)
|
|
else
|
|
Canvas.FillRect(ARect);
|
|
Canvas.Brush.Color := TreeLineColor;
|
|
Painter.DrawSmallExpandButton(Canvas, ARect, AExpanded, TreeLineColor);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawFocusRect(
|
|
AViewInfo: TcxTreeListNodeViewInfo);
|
|
var
|
|
R, R1: TRect;
|
|
begin
|
|
R := AViewInfo.FocusRect;
|
|
if AViewInfo.NodeFocusedCell <> nil then
|
|
begin
|
|
if TreeList.Controller.IsEditing then Exit;
|
|
R1 := AViewInfo.NodeFocusedCell.ClipRect
|
|
end
|
|
else
|
|
R1 := AViewInfo.ContentRect;
|
|
if cxRectIntersect(R1, R, R1) then
|
|
begin
|
|
RestoreClipping;
|
|
Canvas.IntersectClipRect(R1);
|
|
try
|
|
if TreeList.IsFocused then
|
|
Self.Canvas.DrawFocusRect(R)
|
|
else
|
|
if not TreeList.OptionsSelection.HideFocusRect then
|
|
Self.Canvas.InvertFrame(R, 1);
|
|
finally
|
|
RestoreClipping;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawFooter;
|
|
var
|
|
R: TRect;
|
|
I: Integer;
|
|
ARegion: TcxRegion;
|
|
begin
|
|
ARegion := Canvas.GetClipRegion;
|
|
if Indicator then
|
|
DrawIndicator(ViewInfo.FooterIndicator);
|
|
with ViewInfo do
|
|
try
|
|
DrawSeparators(FooterSeparators);
|
|
DrawBandFooter(LeftFixedBand);
|
|
DrawBandFooter(RightFixedBand);
|
|
if (BandCount > 0) and ScrollingAreaVisible then
|
|
Canvas.IntersectClipRect(ScrollingArea);
|
|
for I := 0 to BandCount - 1 do DrawBandFooter(Bands[I]);
|
|
finally
|
|
Canvas.SetClipRegion(ARegion, roSet);
|
|
with Self.Painter do
|
|
R := cxRectInflate(ViewInfo.FooterRect, FooterBorderSize,
|
|
FooterBorderSize, 0, FooterBorderSize);
|
|
Self.Painter.DrawFooterSeparator(Canvas,
|
|
cxRectSetHeight(R, Self.Painter.FooterBorderSize));
|
|
Self.Painter.DrawFooterBorder(Canvas, R);
|
|
R.Left := ViewInfo.ClientRect.Left;
|
|
Canvas.ExcludeClipRect(R);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawFooterItem(
|
|
AViewInfo: TcxTreeListFooterItemViewInfo);
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
if Visible and Canvas.RectVisible(AViewInfo.VisibleRect) then
|
|
begin
|
|
if not Buffered and not Painter.FooterDrawCellsFirst then
|
|
DrawFooterRect(ClipRect, AViewInfo.BandViewInfo);
|
|
if not DoCustomDraw(AViewInfo,
|
|
TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawFooterCell)) then
|
|
begin
|
|
CurrentBitmap := ViewParams.Bitmap;
|
|
with ViewParams do
|
|
Painter.DrawFooterCell(Canvas, DisplayRect, AlignHorz, AlignVert,
|
|
MultiLine, Text, Font, TextColor, Color, DoPaintBackground);
|
|
end;
|
|
if not Buffered then Canvas.ExcludeClipRect(ClipRect);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawFooterRect(
|
|
const R: TRect; AViewInfo: TcxTreeListBandViewInfo);
|
|
var
|
|
ADone: Boolean;
|
|
R1, R2: TRect;
|
|
begin
|
|
if not (AViewInfo.Visible and Canvas.RectVisible(R)) then Exit;
|
|
ADone := False;
|
|
if Assigned(TreeList.FOnCustomDrawFooter) then
|
|
begin
|
|
R1 := AViewInfo.DisplayRect;
|
|
R2 := AViewInfo.VisibleRect;
|
|
AViewInfo.DisplayRect := cxRectSetTop(R1, R.Top);
|
|
AViewInfo.ClipRect := R;
|
|
try
|
|
TreeList.FOnCustomDrawFooter(Control, Canvas, AViewInfo, ADone);
|
|
finally
|
|
AViewInfo.DisplayRect := R1;
|
|
AViewInfo.ClipRect := R2;
|
|
end;
|
|
end;
|
|
if not ADone then
|
|
begin
|
|
Canvas.SaveClipRegion;
|
|
try
|
|
Canvas.SetClipRegion(TcxRegion.Create(R), roIntersect);
|
|
Painter.DrawFooterContent(Canvas, R, AViewInfo.FFooterViewParams);
|
|
finally
|
|
Canvas.RestoreClipRegion;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawHeader;
|
|
var
|
|
I: Integer;
|
|
ARegion: TcxRegion;
|
|
|
|
procedure DrawEdgeBorder(AItem: TcxTreeListBandViewInfo);
|
|
begin
|
|
if not AItem.Opaque then
|
|
Canvas.FrameRect(AItem.DisplayRect, clBtnShadow, 1, [bRight]);
|
|
end;
|
|
|
|
begin
|
|
ARegion := Canvas.GetClipRegion;
|
|
with ViewInfo do
|
|
try
|
|
if Indicator and (Self.Bands or Self.Headers) then
|
|
DrawIndicator(HeaderIndicator);
|
|
DrawSeparators(HeaderSeparators);
|
|
DrawBandItem(LeftFixedBand);
|
|
DrawBandItem(RightFixedBand);
|
|
if (BandCount > 0) and ScrollingAreaVisible then
|
|
Canvas.IntersectClipRect(ScrollingArea);
|
|
for I := 0 to BandCount - 1 do
|
|
DrawBandItem(Bands[I]);
|
|
if RightFixedBand <> nil then
|
|
DrawEdgeBorder(RightFixedBand)
|
|
else
|
|
if BandCount > 0 then
|
|
DrawEdgeBorder(Bands[BandCount - 1])
|
|
finally
|
|
Canvas.SetClipRegion(ARegion, roSet);
|
|
Canvas.ExcludeClipRect(HeaderRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawHeaderItem(
|
|
AViewInfo: TcxTreeListHeaderViewInfo; IsOpaque: Boolean);
|
|
var
|
|
AEvent: TcxCustomDrawViewInfoItemEvent;
|
|
AClipRgn: TcxRegion;
|
|
begin
|
|
if (AViewInfo = nil) or not Canvas.RectVisible(AViewInfo.ClipRect) then Exit;
|
|
with AViewInfo, LookAndFeelPainter, Self do
|
|
begin
|
|
if not Buffered and not LookAndFeelPainter.HeaderDrawCellsFirst and
|
|
(BandViewInfo <> nil) and (BandViewInfo.ContainerBrush <> nil) then
|
|
DrawHeaderRect(ClipRect, BandViewInfo);
|
|
AViewInfo.CustomDrawEvent(AEvent);
|
|
if not DoCustomDrawEx(AViewInfo, AEvent, False) then
|
|
begin
|
|
CurrentBitmap := ViewParams.Bitmap;
|
|
with ViewParams do
|
|
ExtDrawHeader(Self.Canvas, GetDisplayRect, TextBounds, Neighbors, Borders, State, AlignHorz,
|
|
AlignVert, MultiLine, ShowEndEllipsis, Text, Font, TextColor, Color, DoPaintBackground);
|
|
if not Glyph.Empty then
|
|
begin
|
|
AClipRgn := nil;
|
|
if NeedGlyphClipping then
|
|
begin
|
|
AClipRgn := Self.Canvas.GetClipRegion;
|
|
Self.Canvas.IntersectClipRect(ClipRect);
|
|
end;
|
|
Self.Canvas.DrawGlyph(GlyphPos.X, GlyphPos.Y, Glyph);
|
|
if NeedGlyphClipping then Self.Canvas.SetClipRegion(AClipRgn, roSet);
|
|
end;
|
|
if SortOrder <> soNone then
|
|
DrawSortingMark(Self.Canvas, FSortMarkBounds, SortOrder = soAscending);
|
|
if State = cxbsPressed then
|
|
DrawHeaderPressed(Self.Canvas, DisplayRect);
|
|
end;
|
|
if Selected then
|
|
begin
|
|
Self.Canvas.DrawFocusRect(cxRectInflate(GetDisplayRect, -1, -1));
|
|
Self.Canvas.DrawFocusRect(cxRectInflate(GetDisplayRect, -2, -2));
|
|
end;
|
|
if not Buffered and not IsOpaque then Self.Canvas.ExcludeClipRect(ClipRect);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawHeaderRect(const R: TRect;
|
|
AViewInfo: TcxTreeListBandViewInfo);
|
|
begin
|
|
if not DoCustomDraw(AViewInfo,
|
|
TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawHeader)) then
|
|
begin
|
|
DrawRect(R, AViewInfo.ContainerBrush, AViewInfo.ContainerViewParams.Bitmap);
|
|
Canvas.FrameRect(R, clBtnShadow, 1, [bBottom]);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawImage(
|
|
AViewInfo: TcxTreeListIndentViewInfo);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
R := DisplayRect;
|
|
Dec(R.Right, cxTreeListIndentOffsetSize div 2);
|
|
R := cxRectCenter(R, ImageList.Width, ImageList.Height);
|
|
if not IsRectEmpty(R) then
|
|
begin
|
|
ImageList.DrawingStyle := dsTransparent;
|
|
ImageList.Draw(Self.Canvas.Canvas, R.Left, R.Top, ImageIndex);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawIndicator(
|
|
AViewInfo: TcxTreeListIndicatorViewInfo);
|
|
var
|
|
APainter: TcxCustomLookAndFeelPainterClass;
|
|
begin
|
|
if not AViewInfo.Visible then Exit;
|
|
if not DoCustomDraw(AViewInfo,
|
|
TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawIndicatorCell)) then
|
|
begin
|
|
APainter := Painter;
|
|
CurrentBitmap := AViewInfo.ViewParams.Bitmap;
|
|
if (AViewInfo = ViewInfo.HeaderIndicator) or (AViewInfo = ViewInfo.FooterIndicator) then
|
|
with AViewInfo do
|
|
ExtDrawHeader(Self.Canvas, DisplayRect, DisplayRect, [], cxBordersAll, cxbsDefault,
|
|
taLeftJustify, vaTop, False, False, '', nil, clDefault, ViewParams.Color,
|
|
DoPaintBackground)
|
|
else
|
|
with AViewInfo do
|
|
begin
|
|
if TreeList.OptionsView.IsExtPaintStyle then
|
|
APainter.DrawIndicatorItemEx(Self.Canvas, DisplayRect, Kind, ViewParams.Color, DoPaintBackground)
|
|
else
|
|
APainter.DrawIndicatorItem(Self.Canvas, DisplayRect, Kind, ViewParams.Color, DoPaintBackground);
|
|
end;
|
|
end;
|
|
Canvas.ExcludeClipRect(AViewInfo.ClipRect);
|
|
if ContentClipRegion <> nil then
|
|
ContentClipRegion.Combine(TcxRegion.Create(AViewInfo.ClipRect), roSubtract);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawNode(AViewInfo: TcxTreeListNodeViewInfo);
|
|
|
|
function DoDrawFixedGroup(AGroup: TcxTreeListCellsGroupViewInfo): Boolean;
|
|
begin
|
|
Result := AGroup <> nil;
|
|
if Result then DrawCellsGroup(AGroup);
|
|
end;
|
|
|
|
var
|
|
I, AFromIndex, AToIndex: Integer;
|
|
begin
|
|
if Indicator then DrawIndicator(AViewInfo.Indicator);
|
|
if not Canvas.RectVisible(AViewInfo.ContentRect) then Exit;
|
|
for I := AViewInfo.IndentCount - 1 downto 0 do
|
|
DrawNodeIndent(AViewInfo.Indents[I]);
|
|
AFromIndex := 0;
|
|
if not AViewInfo.IsGroupNode then
|
|
begin
|
|
AToIndex := AViewInfo.GroupCount - 1;
|
|
DrawSeparators(AViewInfo.Separators);
|
|
Inc(AFromIndex, Byte(DoDrawFixedGroup(AViewInfo.LeftFixedGroup)));
|
|
Dec(AToIndex, Byte(DoDrawFixedGroup(AViewInfo.RightFixedGroup)));
|
|
end
|
|
else
|
|
AToIndex := -1;
|
|
if AViewInfo.HasPreview then
|
|
DrawNodePreview(AViewInfo.Preview);
|
|
try
|
|
DrawNodeCells(AViewInfo, AFromIndex, AToIndex);
|
|
finally
|
|
RestoreClipping;
|
|
if AViewInfo.Focused then DrawFocusRect(AViewInfo);
|
|
DrawBackgroundRect(AViewInfo.UnusedArea);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawNodeCells(
|
|
AViewInfo: TcxTreeListNodeViewInfo; AFromIndex, AToIndex: Integer);
|
|
begin
|
|
if not AViewInfo.IsGroupNode then
|
|
begin
|
|
if Self.ViewInfo.ScrollingAreaVisible then
|
|
Canvas.IntersectClipRect(Self.ViewInfo.ScrollingArea);
|
|
while AFromIndex <= AToIndex do
|
|
begin
|
|
DrawCellsGroup(AViewInfo.Groups[AFromIndex]);
|
|
Inc(AFromIndex);
|
|
end;
|
|
end
|
|
else
|
|
DrawEditCell(AViewInfo.NodeGroupEditViewInfo, True);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawNodeIndent(
|
|
AViewInfo: TcxTreeListIndentViewInfo);
|
|
begin
|
|
if DoCustomDraw(AViewInfo,
|
|
TcxCustomDrawViewInfoItemEvent(TreeList.FOnCustomDrawIndentCell)) then Exit;
|
|
with AViewInfo do
|
|
begin
|
|
DrawRectWithBorders(DisplayRect, Brush, False, Borders, ViewParams.Bitmap);
|
|
if IsLevel then
|
|
begin
|
|
DrawTreeLines(AViewInfo);
|
|
if HasButton then
|
|
DrawExpandButton(ButtonRect, IsExpanded, ViewParams.Bitmap);
|
|
end
|
|
else
|
|
if HasImage then DrawImage(AViewInfo);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawNodePreview(
|
|
AViewInfo: TcxTreeListNodePreviewViewInfo);
|
|
begin
|
|
DrawEditCell(AViewInfo, False)
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawNodes;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with ViewInfo.NodesViewInfo do
|
|
begin
|
|
for I := 0 to Count - 1 do DrawNode(Nodes[I]);
|
|
DrawBackgroundRect(SpaceArea);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawRect(AViewInfo: TcxTreeListViewInfoItem);
|
|
begin
|
|
with AViewInfo do DrawRect(ClipRect, Brush, ViewParams.Bitmap);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawRect(
|
|
const ARect: TRect; ABrush: TBrush; ABitmap: TBitmap = nil);
|
|
begin
|
|
if cxRectIsEmpty(ARect) then Exit;
|
|
if (ABitmap <> nil) and not ABitmap.Empty then
|
|
Canvas.FillRect(ARect, ABitmap)
|
|
else
|
|
begin
|
|
Canvas.Brush := ABrush;
|
|
Canvas.FillRect(ARect);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawRectWithBorders(const ARect: TRect;
|
|
ABrush: TBrush; IsOpaque: Boolean; ABorders: TcxBorders = []; ABitmap: TBitmap = nil);
|
|
begin
|
|
with ARect do
|
|
begin
|
|
if bLeft in ABorders then
|
|
DrawRect(cxRect(Left, Top, Left + 1, Bottom), GridLinesBrush);
|
|
if bRight in ABorders then
|
|
DrawRect(cxRect(Right - 1, Top, Right, Bottom), GridLinesBrush);
|
|
if bTop in ABorders then
|
|
DrawRect(cxRect(Left, Top, Right, Top + 1), GridLinesBrush);
|
|
if bBottom in ABorders then
|
|
DrawRect(cxRect(Left, Bottom - 1, Right, Bottom), GridLinesBrush);
|
|
end;
|
|
if not IsOpaque then
|
|
DrawRect(cxExcludeBorders(ARect, ABorders), ABrush, ABitmap);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawRectWithBorders(
|
|
AViewInfo: TcxTreeListViewInfoItem; IsOpaque: Boolean; ABorders: TcxBorders = []);
|
|
begin
|
|
with AViewInfo do
|
|
begin
|
|
if (ABorders = []) and not IsOpaque then
|
|
DrawRect(ClipRect, Brush, ViewParams.Bitmap)
|
|
else
|
|
DrawRectWithBorders(DisplayRect, Brush, IsOpaque, ABorders, ViewParams.Bitmap);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawSeparators(const ASeparators: TcxTreeListSeparators);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Canvas.Brush.Assign(ViewInfo.SeparatorBrush);
|
|
for I := Low(TcxTreeListSeparators) to High(TcxTreeListSeparators) do
|
|
if not cxRectIsEmpty(ASeparators[I]) then
|
|
begin
|
|
Canvas.FillRect(ASeparators[I]);
|
|
Canvas.ExcludeClipRect(ASeparators[I]);
|
|
if ContentClipRegion <> nil then
|
|
ContentClipRegion.Combine(TcxRegion.Create(ASeparators[I]), roSubtract);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.DrawTreeLines(
|
|
AViewInfo: TcxTreeListIndentViewInfo);
|
|
|
|
procedure DrawTreeLine(const ARect: TRect; AColor: TColor);
|
|
begin
|
|
if TreeList.OptionsView.TreeLineStyle = tllsDot then
|
|
cxFillHalfToneRect(Canvas.Canvas, ARect, AColor, TreeLineColor)
|
|
else
|
|
begin
|
|
Canvas.Brush.Color := TreeLineColor;
|
|
Canvas.FillRect(ARect);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
with AViewInfo, ViewParams do
|
|
begin
|
|
if [tltVertUp, tltVertDown] * TreeLines <> [] then
|
|
DrawTreeLine(IndentVertTreeLine, Color);
|
|
if tltHorz in TreeLines then
|
|
DrawTreeLine(IndentHorzTreeLine, Color);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.ExtDrawHeader(ACanvas: TcxCanvas;
|
|
const ABounds, ATextAreaBounds: TRect; ANeighbors: TcxNeighbors; ABorders: TcxBorders;
|
|
AState: TcxButtonState; AAlignmentHorz: TAlignment; AAlignmentVert: TcxAlignmentVert;
|
|
AMultiLine, AShowEndEllipsis: Boolean; const AText: string; AFont: TFont;
|
|
ATextColor, ABkColor: TColor; AOnDrawBackground: TcxDrawBackgroundEvent = nil);
|
|
begin
|
|
if TreeList.OptionsView.IsExtPaintStyle then
|
|
Painter.DrawHeaderEx(ACanvas, ABounds, ATextAreaBounds, ANeighbors, ABorders,
|
|
AState, AAlignmentHorz, AAlignmentVert, AMultiLine, AShowEndEllipsis, AText,
|
|
AFont, ATextColor, ABkColor, AOnDrawBackground)
|
|
else
|
|
Painter.DrawHeader(ACanvas, ABounds, ATextAreaBounds, ANeighbors, ABorders,
|
|
AState, AAlignmentHorz, AAlignmentVert, AMultiLine, AShowEndEllipsis, AText,
|
|
AFont, ATextColor, ABkColor, AOnDrawBackground);
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetViewState(AIndex: Integer): Boolean;
|
|
begin
|
|
Result := TcxTreeListOptionsView(TreeList.OptionsView).GetState(AIndex);
|
|
end;
|
|
|
|
procedure TcxTreeListControlPainter.RestoreClipping;
|
|
begin
|
|
Canvas.SetClipRegion(ContentClipRegion, roSet, False);
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetBackgroundBrush: TBrush;
|
|
begin
|
|
Result := ViewInfo.Brush;
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetGridLinesBrush: TBrush;
|
|
begin
|
|
Result := ViewInfo.GridLinesBrush;
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(Control);
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetIsFooterVisible: Boolean;
|
|
begin
|
|
Result := Footer and (TreeList.VisibleColumnCount > 0);
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetTreeLineColor: TColor;
|
|
begin
|
|
Result := ViewInfo.TreeLineColor;
|
|
end;
|
|
|
|
function TcxTreeListControlPainter.GetViewInfo: TcxTreeListViewInfo;
|
|
begin
|
|
Result := TcxTreeListViewInfo(inherited ViewInfo);
|
|
end;
|
|
|
|
{ TcxTreeListBandOptions }
|
|
|
|
constructor TcxTreeListBandOptions.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FState := Integer($FFFFFFFF);
|
|
OnlyOwnColumns := False;
|
|
end;
|
|
|
|
procedure TcxTreeListBandOptions.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListBandOptions then
|
|
begin
|
|
if FState <> TcxTreeListBandOptions(Source).FState then
|
|
begin
|
|
FState := TcxTreeListBandOptions(Source).FState;
|
|
Changed;
|
|
end;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListBandOptions.RestoreDefaults;
|
|
begin
|
|
FState := 0;
|
|
Sizing := True;
|
|
Customizing := True;
|
|
Moving := True;
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListBandOptions.Changed;
|
|
begin
|
|
TcxTreeListBand(GetOwner).Changed(False);
|
|
end;
|
|
|
|
function TcxTreeListBandOptions.GetState(AIndex: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, AIndex);
|
|
end;
|
|
|
|
procedure TcxTreeListBandOptions.SetState(AIndex: Integer; Value: Boolean);
|
|
begin
|
|
if cxSetState(FState, AIndex, Value) then
|
|
Changed;
|
|
end;
|
|
|
|
{ TcxTreeListBandStyles }
|
|
|
|
procedure TcxTreeListBandStyles.Assign(Source: TPersistent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Source is TcxTreeListBandStyles then
|
|
begin
|
|
for I := tlbs_Content to tlbs_HeaderBackground do
|
|
SetValue(I, TcxTreeListBandStyles(Source).GetValue(I));
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListBandStyles.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxTreeListBand(GetOwner).TreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListBandStyles.CachedContentStyleChanged;
|
|
var
|
|
B: Boolean;
|
|
begin
|
|
ContentParams := TreeList.Styles.ContentParams;
|
|
for B := False to True do
|
|
cxParamsCombine(Content, [], ContentParams[B]);
|
|
end;
|
|
|
|
procedure TcxTreeListBandStyles.Changed(AIndex: Integer);
|
|
begin
|
|
inherited Changed(AIndex);
|
|
TreeList.UpdateViewStyles;
|
|
end;
|
|
|
|
{ TcxTreeListBand }
|
|
|
|
constructor TcxTreeListBand.Create(Collection: TCollection);
|
|
begin
|
|
TcxTreeListBands(Collection).TreeList.BeginUpdate;
|
|
inherited Create(Collection);
|
|
FVisibleColumns := TList.Create;
|
|
FBandRows := TcxTreeListBandRows.Create(Self);
|
|
FColumns := TList.Create;
|
|
FOptions := GetOptionsClass.Create(Self);
|
|
FBandViewInfo := TcxTreeListBandViewInfo.Create(Self);
|
|
FCaption := TcxTreeListCaption.CreateEx(TreeList, Self, FBandViewInfo);
|
|
FStyles := TcxTreeListBandStyles.Create(Self);
|
|
Visible := True;
|
|
RestoreWidths;
|
|
if TreeList <> nil then TreeList.DoUpdateDesignerForms;
|
|
TreeList.EndUpdate;
|
|
end;
|
|
|
|
destructor TcxTreeListBand.Destroy;
|
|
var
|
|
I: Integer;
|
|
ATreeList: TcxCustomTreeListControl;
|
|
begin
|
|
ATreeList := TreeList;
|
|
ATreeList.BeginUpdate;
|
|
try
|
|
FreeAndNil(FCaption);
|
|
if not (TreeList.IsDestroying or TreeList.IsLoading) then
|
|
begin
|
|
if TreeList.HitTest.FPressedHeader = ViewInfo.BandHeader then
|
|
TreeList.HitTest.FPressedHeader := nil;
|
|
TreeList.ViewInfo.IsDirty := True;
|
|
Visible := False;
|
|
TreeList.Controller.UnselectObject(Self);
|
|
if Visible then
|
|
TreeList.FBandsVisibleList.Remove(Self);
|
|
for I := 0 to FColumns.Count - 1 do
|
|
TcxTreeListColumn(FColumns[I]).InternalSetBandOwner(nil, False);
|
|
end;
|
|
FreeAndNil(FBandViewInfo);
|
|
FreeAndNil(FColumns);
|
|
FreeAndNil(FOptions);
|
|
FreeAndNil(FStyles);
|
|
FreeAndNil(FBandRows);
|
|
FreeAndNil(FVisibleColumns);
|
|
TreeList.UpdateViewStyles;
|
|
finally
|
|
inherited Destroy;
|
|
ATreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.Assign(Source: TPersistent);
|
|
var
|
|
ABand: TcxTreeListBand;
|
|
begin
|
|
if Source is TcxTreeListBand then
|
|
begin
|
|
ABand := TcxTreeListBand(Source);
|
|
FCalculatedWidth := ABand.FCalculatedWidth;
|
|
FMinWidth := ABand.MinWidth;
|
|
FWidth := ABand.FWidth;
|
|
Visible := ABand.Visible;
|
|
Options := ABand.Options;
|
|
Styles := ABand.Styles;
|
|
Caption := ABand.Caption;
|
|
FixedKind := ABand.FixedKind;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.ApplyBestFit;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TreeList.HandleNeeded;
|
|
if IsLeftMost then
|
|
TreeList.FContentIndentWidth := 0;
|
|
if not CanSizing(dsdHorz) then Exit;
|
|
TreeList.BeginUpdate;
|
|
try
|
|
FWidth := 0;
|
|
TreeList.HideEdit;
|
|
I := 0;
|
|
while I < VisibleColumnCount do
|
|
begin
|
|
VisibleColumns[I].ApplyBestFit;
|
|
Inc(I);
|
|
end;
|
|
BandRows.Refresh;
|
|
FCalculatedWidth := BandRows.ColumnsMaxWidth;
|
|
if FWidth <> 0 then
|
|
FCalculatedWidth := FWidth;
|
|
TreeList.Controller.ForceWidthItem := Self;
|
|
AssignColumnWidths;
|
|
TreeList.RealignBands;
|
|
finally
|
|
TreeList.Controller.ForceWidthItem := nil;
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.RestoreDefaults;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
Options.RestoreDefaults;
|
|
RestoreWidths;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.RestoreWidths;
|
|
begin
|
|
FMinWidth := cxTreeListDefMinWidth;
|
|
SetWidth(0);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.AssignColumnWidths;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
for I := 0 to VisibleColumnCount - 1 do
|
|
VisibleColumns[I].Width := VisibleColumns[I].RealWidth;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.InitAutoWidthItem(AItem: TcxAutoWidthItem);
|
|
begin
|
|
AItem.Width := Width;
|
|
if AItem.Width = 0 then
|
|
AItem.Width := BandRows.ColumnsMaxWidth;
|
|
AItem.MinWidth := cxMax(FMinWidth, BandRows.ColumnsMinWidth);
|
|
AItem.AutoWidth := -1;
|
|
AItem.Fixed := (TreeList.Controller.ForceWidthItem = Self) or not Options.Sizing;
|
|
end;
|
|
|
|
function TcxTreeListBand.IsFixed: Boolean;
|
|
begin
|
|
Result := FixedKind <> tlbfNone;
|
|
end;
|
|
|
|
function TcxTreeListBand.IsOnlyOwnColumns: Boolean;
|
|
begin
|
|
Result := Options.OnlyOwnColumns;
|
|
end;
|
|
|
|
function TcxTreeListBand.CanDropColumnAt(
|
|
const APoint: TPoint; out ARowIndex, AColIndex: Integer): Boolean;
|
|
begin
|
|
Result := True;
|
|
ARowIndex := 0;
|
|
AColIndex := 0;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetMaxDeltaWidth: Integer;
|
|
begin
|
|
Result := TreeList.GetMaxBandWidth(Self) - DisplayWidth;
|
|
end;
|
|
|
|
function TcxTreeListBand.CanMoving: Boolean;
|
|
begin
|
|
Result := (FixedKind = tlbfNone) and (TreeList.VisibleBandCount > 1) and
|
|
Options.Moving and TreeList.OptionsCustomizing.BandMoving;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetOptionsClass: TcxTreeListBandOptionsClass;
|
|
begin
|
|
Result := TcxTreeListBandOptions;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.AddColumn(AColumn: TcxTreeListColumn);
|
|
begin
|
|
if FColumns.IndexOf(AColumn) = cxInvalidIndex then
|
|
begin
|
|
// if not (TreeList.IsLocked or TreeList.IsUpdating) then
|
|
// AColumn.Position.FColIndex := FColumns.Count;
|
|
FColumns.Add(AColumn);
|
|
end;
|
|
AColumn.FOwnerBand := Self;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.RealignColumns;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not Visible then Exit;
|
|
BandRows.Refresh;
|
|
if not TreeList.OptionsView.ColumnAutoWidth then
|
|
FCalculatedWidth := BandRows.ColumnsMaxWidth;
|
|
try
|
|
for I := 0 to BandRows.Count - 1 do
|
|
BandRows[I].DoCalculateColumnsAutoWidth;
|
|
finally
|
|
BandRows.UpdateInformation;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.RemoveColumn(AColumn: TcxTreeListColumn);
|
|
begin
|
|
if (FColumns <> nil) and (FColumns.Remove(AColumn) <> cxInvalidIndex) then
|
|
begin
|
|
Changed(True);
|
|
AColumn.FOwnerBand := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
cxSetState(FState, Index, Value);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.VisibleChanged;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
FixedKind := tlbfNone;
|
|
if not Self.Visible then
|
|
FBandsVisibleList.Remove(Self)
|
|
else
|
|
FBandsVisibleList.Add(Self);
|
|
finally
|
|
Self.Changed(True);
|
|
DoUpdateDesignerForms;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListBand.CanSizing(ADirection: TcxDragSizingDirection): Boolean;
|
|
begin
|
|
with TreeList.OptionsCustomizing do
|
|
begin
|
|
if ADirection = dsdVert then
|
|
Result := BandVertSizing
|
|
else
|
|
Result := BandHorzSizing and Options.Sizing;
|
|
end
|
|
end;
|
|
|
|
function TcxTreeListBand.GetSizingBoundsRect(
|
|
ADirection: TcxDragSizingDirection): TRect;
|
|
begin
|
|
Result := TreeList.ViewInfo.ClientRect;
|
|
InflateRect(Result, TreeList.Width, 0);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetSizingIncrement(
|
|
ADirection: TcxDragSizingDirection): Integer;
|
|
begin
|
|
if ADirection = dsdHorz then
|
|
Result := 1
|
|
else
|
|
Result := TreeList.ViewInfo.BandLineHeight;
|
|
end;
|
|
|
|
function TcxTreeListBand.IsDynamicUpdate: Boolean;
|
|
var
|
|
ADir: TcxDragSizingDirection;
|
|
begin
|
|
Result := TreeList.OptionsCustomizing.DynamicSizing and
|
|
TreeList.HitTest.CanSizing(ADir) and (ADir = dsdHorz);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetSizeDelta(
|
|
ADirection: TcxDragSizingDirection; ADelta: Integer);
|
|
begin
|
|
TreeList.Controller.ForceWidthItem := Self;
|
|
if ADirection = dsdHorz then
|
|
Width := DisplayWidth + ADelta
|
|
else
|
|
with TreeList.OptionsView do
|
|
BandLineCount := BandLineCount + ADelta;
|
|
TreeList.LayoutChanged;
|
|
TreeList.Controller.ForceWidthItem := nil;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetObjectName: string;
|
|
begin
|
|
Result := 'Band' + IntToStr(Index);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetProperties(
|
|
AProperties: TStrings): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to High(BandPropertiesName) do
|
|
AProperties.Add(BandPropertiesName[I]);
|
|
Result := True;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetPropertyIndex(const AName: string): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := -1;
|
|
for I := 0 to High(BandPropertiesName) do
|
|
if BandPropertiesName[I] = AName then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.GetPropertyValue(
|
|
const AName: string; var AValue: Variant);
|
|
begin
|
|
case GetPropertyIndex(AName) of
|
|
0: AValue := Caption.Text;
|
|
1: AValue := FMinWidth;
|
|
2: AValue := FWidth;
|
|
3: AValue := Visible;
|
|
4: AValue := Index;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetPropertyValue(
|
|
const AName: string; const AValue: Variant);
|
|
begin
|
|
case GetPropertyIndex(AName) of
|
|
0:
|
|
if Caption.Text = '' then
|
|
Caption.Text := AValue;
|
|
1:
|
|
FMinWidth := AValue;
|
|
2:
|
|
FWidth := AValue;
|
|
3:
|
|
Visible := AValue;
|
|
4:
|
|
Index := AValue;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetRealWidth: Integer;
|
|
begin
|
|
Result := FCalculatedWidth;
|
|
if Result = 0 then
|
|
Result := FWidth;
|
|
if Result = 0 then
|
|
Result := BandRows.ColumnsMaxWidth;
|
|
Result := Max(Result, BandRows.ColumnsMinWidth);
|
|
if Result = 0 then
|
|
Result := cxTreeListDefWidth;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Bands.TreeList;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetBands: TcxTreeListBands;
|
|
begin
|
|
Result := TcxTreeListBands(Collection);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetColumn(Index: Integer): TcxTreeListColumn;
|
|
var
|
|
I, AIndex: Integer;
|
|
begin
|
|
Result := nil;
|
|
AIndex := 0;
|
|
for I := 0 to TreeList.ColumnCount - 1 do
|
|
begin
|
|
Result := TreeList.Columns[I];
|
|
if Result.OwnerBand = Self then
|
|
begin
|
|
if Index = AIndex then Break;
|
|
Inc(AIndex);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetColumnCount: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to TreeList.ColumnCount - 1 do
|
|
if TreeList.Columns[I].OwnerBand = Self then
|
|
Inc(Result);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetDisplayWidth: Integer;
|
|
begin
|
|
Result := FCalculatedWidth + IndentWidth;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetFixedKind: TcxTreeListBandFixedKind;
|
|
begin
|
|
Result := TcxTreeListBandFixedKind(FState shr 1 and 3);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetIndentWidth: Integer;
|
|
begin
|
|
Result := TreeList.GetIndentWidth(Bands.FirstVisible = Self);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetIsLeftMost: Boolean;
|
|
begin
|
|
Result := Visible and (Bands.FirstVisible = Self);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetIsRightMost: Boolean;
|
|
begin
|
|
Result := Visible and (Bands.LastVisible = Self);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetItemIndex: Integer;
|
|
begin
|
|
Result := Index;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetVisible: Boolean;
|
|
begin
|
|
Result := GetState(tlbsVisible);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetVisibleColumn(Index: Integer): TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(FVisibleColumns[Index]);
|
|
end;
|
|
|
|
function TcxTreeListBand.GetVisibleColumnCount: Integer;
|
|
begin
|
|
Result := FVisibleColumns.Count;
|
|
end;
|
|
|
|
function TcxTreeListBand.GetVisibleIndex: Integer;
|
|
begin
|
|
Result := TreeList.FBandsVisibleList.IndexOf(Self);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetBandVisiblePos(APos: Integer);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with TreeList.FBandsVisibleList do
|
|
begin
|
|
I := IndexOf(Self);
|
|
if I <> APos then
|
|
begin
|
|
Remove(Self);
|
|
if APos >= Count then
|
|
Add(Self)
|
|
else
|
|
Insert(APos, Self);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetCaption(Value: TcxTreeListCaption);
|
|
begin
|
|
FCaption.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetColumn(Index: Integer; Value: TcxTreeListColumn);
|
|
begin
|
|
Columns[Index].Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetFixedKind(Value: TcxTreeListBandFixedKind);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (Value <> FixedKind) and Visible then
|
|
begin
|
|
if Value <> tlbfNone then
|
|
begin
|
|
for I := 0 to Bands.Count - 1 do
|
|
if Bands[I].FixedKind = Value then
|
|
Bands[I].FixedKind := tlbfNone;
|
|
end;
|
|
FState := FState and not tlbsAllFixed;
|
|
if Value <> tlbfNone then
|
|
FState := FState or Integer(Value) shl 1;
|
|
with TreeList.FBandsVisibleList do
|
|
begin
|
|
if Value = tlbfLeft then
|
|
SetBandVisiblePos(0)
|
|
else
|
|
if Value = tlbfRight then
|
|
SetBandVisiblePos(Count - 1);
|
|
Changed(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetItemIndex(Value: Integer);
|
|
begin
|
|
if cxInRange(Value, 0, Bands.Count - 1) then
|
|
Index := Value;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetMinWidth(Value: Integer);
|
|
begin
|
|
if Value <> FMinWidth then
|
|
begin
|
|
FMinWidth := Value;
|
|
Changed(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetOptions(Value: TcxTreeListBandOptions);
|
|
begin
|
|
FOptions.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetStyles(Value: TcxTreeListBandStyles);
|
|
begin
|
|
FStyles.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetVisibleColumn(
|
|
Index: Integer; Value: TcxTreeListColumn);
|
|
begin
|
|
VisibleColumns[Index].Assign(Value);
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetVisible(Value: Boolean);
|
|
begin
|
|
if Value <> Visible then
|
|
begin
|
|
SetState(tlbsVisible, Value);
|
|
VisibleChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetVisibleIndex(Value: Integer);
|
|
const
|
|
ACorrectValue: array[TcxTreeListBandFixedKind] of Integer = (0, 1, -1);
|
|
|
|
procedure ModifyList;
|
|
begin
|
|
with TreeList.FBandsVisibleList do
|
|
begin
|
|
if cxValidateIntDefEx(Value, -1, 0, Count) then
|
|
begin
|
|
Inc(Value, ACorrectValue[TcxTreeListBand(List^[Value]).FixedKind]);
|
|
if Value >= Count then
|
|
Add(Self)
|
|
else
|
|
Insert(Value, Self);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Inc(Value);
|
|
if Value <> VisibleIndex then
|
|
begin
|
|
if Value < 0 then
|
|
Visible := False
|
|
else
|
|
if FixedKind = tlbfNone then
|
|
begin
|
|
I := TreeList.FBandsVisibleList.Remove(Self);
|
|
if (I >= 0) and (I < Value) then Dec(Value);
|
|
ModifyList;
|
|
SetState(tlbsVisible, VisibleIndex >= 0);
|
|
Changed(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBand.SetWidth(Value: Integer);
|
|
begin
|
|
if (Value = 0) or (cxValidateIntDefEx(Value, FWidth, FMinWidth)) then
|
|
begin
|
|
FWidth := Value;
|
|
if TreeList.IsLocked or not Visible then Exit;
|
|
TreeList.LayoutChanged;
|
|
TreeList.DoOnBandSizeChanged(Self);
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListBands }
|
|
|
|
constructor TcxTreeListBands.Create(AOwner: TcxCustomTreeListControl);
|
|
begin
|
|
inherited Create(AOwner.GetBandItemClass);
|
|
FTreeList := AOwner;
|
|
end;
|
|
|
|
function TcxTreeListBands.Add: TcxTreeListBand;
|
|
begin
|
|
Result := TcxTreeListBand(inherited Add);
|
|
Update(nil);
|
|
end;
|
|
|
|
function TcxTreeListBands.GetAbsoluteIndex(VisibleIndex: Integer): Integer;
|
|
begin
|
|
if (VisibleIndex >= 0) and (VisibleIndex < TreeList.FBandsVisibleList.Count) then
|
|
Result := TcxTreeListBand(TreeList.FBandsVisibleList.List[VisibleIndex]).Index
|
|
else
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListBands.GetVisibleIndex(AbsoluteIndex: Integer): Integer;
|
|
begin
|
|
Result := TreeList.FBandsVisibleList.IndexOf(inherited GetItem(AbsoluteIndex));
|
|
end;
|
|
|
|
procedure TcxTreeListBands.RestoreDefaults;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
for I := 0 to Count - 1 do
|
|
Items[I].RestoreDefaults;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.RestoreWidths;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
for I := 0 to Count - 1 do
|
|
Items[I].RestoreWidths;
|
|
finally
|
|
TreeList.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.RealignColumns;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TreeList.FHeaderLineCount := 0;
|
|
for I := 0 to TreeList.VisibleBandCount - 1 do
|
|
TreeList.VisibleBands[I].RealignColumns;
|
|
end;
|
|
|
|
function TcxTreeListBands.GetOwner: TPersistent;
|
|
begin
|
|
Result := FTreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.RefreshBandStates;
|
|
var
|
|
I: Integer;
|
|
ALastVisible, AFirstVisible: TcxTreeListBand;
|
|
|
|
procedure CheckFixed(ABand: TcxTreeListBand);
|
|
begin
|
|
if (ABand = AFirstVisible) or (ABand = ALastVisible) then Exit;
|
|
ABand.FixedKind := tlbfNone;
|
|
end;
|
|
|
|
begin
|
|
TreeList.FBandsVisibleList.Sort(cxCompareVisibleBands);
|
|
AFirstVisible := FirstVisible;
|
|
ALastVisible := LastVisible;
|
|
for I := 0 to Count - 1 do
|
|
CheckFixed(TcxTreeListBand(inherited GetItem(I)));
|
|
end;
|
|
|
|
procedure TcxTreeListBands.Update(Item: TCollectionItem);
|
|
begin
|
|
if FTreeList = nil then Exit;
|
|
if FTreeList.Bands.Count <> 1 then
|
|
FTreeList.FDefaultLayout := False;
|
|
with FTreeList do
|
|
begin
|
|
if IsLoading or IsDestroying then Exit;
|
|
if not IsLocked then RefreshBandStates;
|
|
end;
|
|
TreeList.DoUpdateDesignerForms;
|
|
TreeList.UpdateViewStyles;
|
|
end;
|
|
|
|
{$IFDEF DELPHI6}
|
|
|
|
procedure TcxTreeListBands.Notify(Item: TCollectionItem; Action: TCollectionNotification);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if (Action = cnExtracting) and (TreeList <> nil) and not TreeList.IsDestroying then
|
|
begin
|
|
TreeList.FBandsVisibleList.Remove(Item);
|
|
for I := 0 to TreeList.ColumnCount - 1 do
|
|
if TreeList.Columns[I].FOwnerBand = Item then
|
|
TreeList.Columns[I].FOwnerBand := nil;
|
|
end;
|
|
inherited Notify(Item, Action);
|
|
end;
|
|
|
|
{$ENDIF}
|
|
|
|
// IInterface
|
|
function TcxTreeListBands.QueryInterface(const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
Result := 0
|
|
else
|
|
Result := cxE_NOINTERFACE;
|
|
end;
|
|
|
|
function TcxTreeListBands._AddRef: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListBands._Release: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
// IcxStoredObject }
|
|
function TcxTreeListBands.GetObjectName: string;
|
|
begin
|
|
Result := 'Bands';
|
|
end;
|
|
|
|
function TcxTreeListBands.GetProperties(AProperties: TStrings): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.GetPropertyValue(
|
|
const AName: string; var AValue: Variant);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxTreeListBands.SetPropertyValue(
|
|
const AName: string; const AValue: Variant);
|
|
begin
|
|
end;
|
|
|
|
// IcxStoredParent
|
|
function TcxTreeListBands.CreateChild(
|
|
const AObjectName, AClassName: string): TObject;
|
|
begin
|
|
if AClassName = 'TcxTreeListBand' then
|
|
Result := Add
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.DeleteChild(const AObjectName: string; AObject: TObject);
|
|
begin
|
|
AObject.Free;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.GetChildren(AChildren: TStringList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
AChildren.AddObject('', Items[I]);
|
|
end;
|
|
|
|
function TcxTreeListBands.GetItem(AIndex: Integer): TcxTreeListBand;
|
|
begin
|
|
Result := TcxTreeListBand(inherited GetItem(AIndex));
|
|
end;
|
|
|
|
function TcxTreeListBands.GetVisibleItemEx(AIndex: Integer): TcxTreeListBand;
|
|
begin
|
|
with TreeList.FBandsVisibleList do
|
|
begin
|
|
if Count = 0 then
|
|
Result := nil
|
|
else
|
|
if AIndex = 0 then
|
|
Result := TcxTreeListBand(List^[0])
|
|
else
|
|
Result := TcxTreeListBand(List^[Count - 1]);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBands.SetItem(AIndex: Integer; Value: TcxTreeListBand);
|
|
begin
|
|
inherited GetItem(AIndex).Assign(Value);
|
|
end;
|
|
|
|
{ TcxTreeListBandRow }
|
|
|
|
constructor TcxTreeListBandRow.Create(AOwner: TcxTreeListBandRows);
|
|
begin
|
|
FBandRows := AOwner;
|
|
FItems := TList.Create;
|
|
end;
|
|
|
|
destructor TcxTreeListBandRow.Destroy;
|
|
begin
|
|
FreeAndNil(FItems);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.IndexOf(AColumn: TcxTreeListColumn): Integer;
|
|
begin
|
|
Result := FItems.IndexOf(AColumn);
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetRowMinWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Count - 1 do
|
|
Inc(Result, Items[I].GetRealMinWidth);
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetMaxColumnWidth(
|
|
AColumn: TcxTreeListColumn): Integer;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
Result := Band.DisplayWidth;
|
|
J := FItems.IndexOf(AColumn);
|
|
if J = Count - 1 then
|
|
for I := Count - 2 downto 0 do
|
|
Dec(Result, Items[I].GetRealMinWidth)
|
|
else
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
if I < J then
|
|
Dec(Result, Items[I].DisplayWidth)
|
|
else
|
|
if I > J then
|
|
Dec(Result, Items[I].GetRealMinWidth);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBandRow.UpdateInformation;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FLineOffset := 0;
|
|
FLineCount := 0;
|
|
with FItems do
|
|
for I := 0 to Count - 1 do
|
|
FLineCount := cxMax(FLineCount, TcxTreeListColumn(List^[I]).Position.LineCount);
|
|
end;
|
|
|
|
procedure TcxTreeListBandRow.AddColumn(AColumn: TcxTreeListColumn);
|
|
begin
|
|
if not AColumn.IsHidden then
|
|
begin
|
|
Band.FVisibleColumns.Add(AColumn);
|
|
FItems.Add(AColumn);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListBandRow.DoCalculateColumnsAutoWidth;
|
|
var
|
|
I: Integer;
|
|
AAutoWidth: TcxAutoWidthObject;
|
|
begin
|
|
if Count = 0 then Exit;
|
|
AAutoWidth := TcxAutoWidthObject.Create(Count);
|
|
try
|
|
AAutoWidth.AvailableWidth := Band.RealWidth;
|
|
for I := 0 to Count - 1 do
|
|
Items[I].InitAutoWidthItem(AAutoWidth.AddItem);
|
|
AAutoWidth.Calculate;
|
|
for I := 0 to Count - 1 do
|
|
Items[I].FCalculatedWidth := AAutoWidth.Items[I].AutoWidth;
|
|
finally
|
|
AAutoWidth.Free;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetBand: TcxTreeListBand;
|
|
begin
|
|
Result := FBandRows.FBand;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetCount: Integer;
|
|
begin
|
|
Result := FItems.Count
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetIsFirst: Boolean;
|
|
begin
|
|
Result := BandRows.First = Self;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetFirst: TcxTreeListColumn;
|
|
begin
|
|
Result := GetItemEx(0);
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetIndex: Integer;
|
|
begin
|
|
Result := BandRows.FItems.IndexOf(Self);
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetIsLast: Boolean;
|
|
begin
|
|
Result := BandRows.Last = Self;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetItem(Index: Integer): TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(FItems[Index])
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetItemEx(Index: Integer): TcxTreeListColumn;
|
|
begin
|
|
if (Index >= 0) and (Index < FItems.Count) then
|
|
Result := TcxTreeListColumn(FItems.List^[Index])
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetLast: TcxTreeListColumn;
|
|
begin
|
|
Result := GetItemEx(FItems.Count - 1);
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetLineCount: Integer;
|
|
begin
|
|
if FLineCount = 0 then
|
|
begin
|
|
Result := LineOffset;
|
|
UpdateInformation;
|
|
FLineOffset := Result;
|
|
end;
|
|
Result := FLineCount;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetMinWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Count - 1 do
|
|
cxSetMax(Result, Items[I].GetRealMinSize);
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := FBandRows.FBand.GetTreeList;
|
|
end;
|
|
|
|
function TcxTreeListBandRow.GetWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Count - 1 do
|
|
Inc(Result, Items[I].DisplayWidth);
|
|
if Result = 0 then
|
|
Result := Band.DisplayWidth;
|
|
end;
|
|
|
|
{ TcxTreeListBandRows }
|
|
|
|
constructor TcxTreeListBandRows.Create(AOwner: TcxTreeListBand);
|
|
begin
|
|
FBand := AOwner;
|
|
FItems := TList.Create;
|
|
end;
|
|
|
|
destructor TcxTreeListBandRows.Destroy;
|
|
begin
|
|
Clear;
|
|
FreeAndNil(FItems);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxTreeListBandRows.Add: TcxTreeListBandRow;
|
|
begin
|
|
Result := TcxTreeListBandRow.Create(Self);
|
|
FItems.Add(Result);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.CalculateAvaliableMinWidth: Integer;
|
|
|
|
function GetRowMinWidth(ARow: TcxTreeListBandRow): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to ARow.Count - 1 do
|
|
Inc(Result, ARow[I].FMinWidth);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to Count - 1 do
|
|
Result := cxMax(Result, GetRowMinWidth(Items[I]));
|
|
end;
|
|
|
|
procedure TcxTreeListBandRows.Clear;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to FItems.Count - 1 do
|
|
FreeAndNil(TcxTreeListBandRow(FItems.List^[I]));
|
|
FItems.Clear;
|
|
end;
|
|
|
|
procedure TcxTreeListBandRows.Refresh;
|
|
|
|
procedure CheckColumns(AList: TList);
|
|
var
|
|
I, ARow, ACurRow: Integer;
|
|
begin
|
|
ARow := cxInvalidIndex;
|
|
ACurRow := 0;
|
|
for I := 0 to AList.Count - 1 do
|
|
with TcxTreeListColumn(AList.List^[I]) do
|
|
begin
|
|
if not Visible then Continue;
|
|
if ARow <> Position.FRowIndex then
|
|
begin
|
|
if ARow <> cxInvalidIndex then
|
|
Inc(ACurRow);
|
|
ARow := Position.FRowIndex
|
|
end;
|
|
Position.FRowIndex := ACurRow;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ABandRow: TcxTreeListBandRow;
|
|
AColumn: TcxTreeListColumn;
|
|
I, ARow, ACol, AMaxRowWidth, AMinRowWidth, AVisibleIndex: Integer;
|
|
begin
|
|
Clear;
|
|
Band.FVisibleColumns.Clear;
|
|
ABandRow := nil;
|
|
Band.FColumns.Sort(cxCompareColumnsPos);
|
|
CheckColumns(Band.FColumns);
|
|
ARow := -1;
|
|
ACol := -1;
|
|
FColumnsMaxWidth := Band.Width;
|
|
FColumnsMinWidth := Band.FMinWidth;
|
|
AMaxRowWidth := 0;
|
|
AMinRowWidth := 0;
|
|
AVisibleIndex := 0;
|
|
for I := 0 to Band.FColumns.Count - 1 do
|
|
begin
|
|
AColumn := TcxTreeListColumn(Band.FColumns.List^[I]);
|
|
Inc(ACol);
|
|
if AColumn.Position.FRowIndex <> ARow then
|
|
begin
|
|
Inc(ARow);
|
|
AMaxRowWidth := 0;
|
|
AMinRowWidth := 0;
|
|
ACol := 0;
|
|
ABandRow := Add;
|
|
end;
|
|
if AColumn.Visible and not AColumn.IsPreview then
|
|
begin
|
|
Inc(AMaxRowWidth, AColumn.Width);
|
|
Inc(AMinRowWidth, AColumn.MinWidth);
|
|
FColumnsMinWidth := Max(FColumnsMinWidth, AMinRowWidth);
|
|
FColumnsMaxWidth := Max(FColumnsMaxWidth, AMaxRowWidth);
|
|
AColumn.FVisibleIndexAtBand := AVisibleIndex;
|
|
Inc(AVisibleIndex);
|
|
end;
|
|
if not Band.TreeList.IsUpdating then
|
|
begin
|
|
AColumn.Position.FColIndex := ACol; //todo: fixed B20392
|
|
AColumn.Position.FRowIndex := ARow;
|
|
end;
|
|
if ABandRow <> nil then
|
|
ABandRow.AddColumn(AColumn);
|
|
end;
|
|
if FColumnsMaxWidth = 0 then
|
|
FColumnsMaxWidth := cxTreeListDefWidth;
|
|
if Band.Width <> 0 then
|
|
FColumnsMaxWidth := Max(FColumnsMinWidth, Band.Width);
|
|
UpdateInformation;
|
|
end;
|
|
|
|
procedure TcxTreeListBandRows.UpdateInformation;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FLineCount := 0;
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
with Items[I] do
|
|
begin
|
|
UpdateInformation;
|
|
FLineOffset := Self.FLineCount;
|
|
Inc(Self.FLineCount, LineCount);
|
|
end;
|
|
end;
|
|
with Band.TreeList do
|
|
FHeaderLineCount := cxMax(FHeaderLineCount, LineCount);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetCount: Integer;
|
|
begin
|
|
Result := FItems.Count;
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetFirst: TcxTreeListBandRow;
|
|
begin
|
|
Result := GetItemEx(0);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetItem(Index: Integer): TcxTreeListBandRow;
|
|
begin
|
|
Result := TcxTreeListBandRow(FItems[Index]);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetItemEx(Index: Integer): TcxTreeListBandRow;
|
|
begin
|
|
if (Index < 0) or (Index >= Count) then
|
|
Result := nil
|
|
else
|
|
Result := Items[Index];
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetLast: TcxTreeListBandRow;
|
|
begin
|
|
Result := GetItemEx(FItems.Count - 1);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetMinWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := Band.FMinWidth;
|
|
for I := 0 to Count - 1 do
|
|
cxSetMax(Result, Items[I].MinWidth);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetLeftMostMinWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := Band.FMinWidth;
|
|
for I := 0 to Count - 1 do
|
|
if Items[I].Count > 0 then
|
|
cxSetMin(Result, Items[I][0].MinWidth);
|
|
end;
|
|
|
|
function TcxTreeListBandRows.GetLeftMostWidth: Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := MaxInt;
|
|
for I := 0 to Count - 1 do
|
|
if Items[I].Count > 0 then
|
|
cxSetMin(Result, Items[I][0].RealWidth);
|
|
if Result = MaxInt then
|
|
Result := Band.RealWidth;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsView }
|
|
|
|
constructor TcxTreeListOptionsView.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FIndicatorWidth := cxTreeListDefIndicatorWidth;
|
|
FBandLineCount := cxTreeListDefBandHeaderLineCount;
|
|
FFixedSeparatorColor := clDefault;
|
|
FFixedSeparatorWidth := cxTreeListDefSeparatorWidth;
|
|
FDropArrowColor := cxTreeListDefDropArrowColor;
|
|
Bands := cxTreeListDefBands;
|
|
Buttons := True;
|
|
Headers := cxTreeListDefColumnHeaders;
|
|
Footer := cxTreeListDefFooter;
|
|
FFixedSeparatorColor := clDefault;
|
|
ColumnAutoWidth := cxTreeListDefColumnAutoWidth;
|
|
FGridLineColor := clDefault;
|
|
FTreeLineColor := clDefault;
|
|
FTreeLineStyle := tllsDot;
|
|
UseNodeColorForIndent := True;
|
|
UseImageIndexForSelected := True;
|
|
ShowRoot := True;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.Assign(Source: TPersistent);
|
|
var
|
|
ASource: TcxTreeListOptionsView;
|
|
begin
|
|
if Source is TcxTreeListOptionsView then
|
|
begin
|
|
ASource := TcxTreeListOptionsView(Source);
|
|
HeaderSingleLine := ASource.HeaderSingleLine;
|
|
FState := ASource.FState;
|
|
if ASource.FCategorizedColumn <> nil then
|
|
FCategorizedColumn := TreeList.Columns[ASource.FCategorizedColumn.ItemIndex]
|
|
else
|
|
FCategorizedColumn := nil;
|
|
FBandLineCount := ASource.FBandLineCount;
|
|
FIndicatorWidth := ASource.FIndicatorWidth;
|
|
FFixedSeparatorColor := ASource.FFixedSeparatorColor;
|
|
FFixedSeparatorWidth := ASource.FixedSeparatorWidth;
|
|
FGridLines := ASource.FGridLines;
|
|
FGridLineColor := ASource.GridLineColor;
|
|
FDropArrowColor := ASource.FDropArrowColor;
|
|
FPaintStyle := ASource.FPaintStyle;
|
|
FTreeLineColor := ASource.FTreeLineColor;
|
|
FTreeLineStyle := ASource.FTreeLineStyle;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.GetCategorizedColumn: TcxTreeListColumn;
|
|
begin
|
|
if FCategorizedColumn <> nil then
|
|
Result := FCategorizedColumn
|
|
else
|
|
if TreeList.VisibleColumnCount > 0 then
|
|
Result := TreeList.VisibleColumns[0]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.RestoreDefaults;
|
|
begin
|
|
FState := 0;
|
|
FIndicatorWidth := cxTreeListDefIndicatorWidth;
|
|
Headers := True;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.Changed;
|
|
begin
|
|
TreeList.UpdateViewStyles;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.GetControl: TObject;
|
|
begin
|
|
Result := TreeList;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.GetState(AIndex: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, AIndex);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetState(AIndex: Integer; Value: Boolean);
|
|
begin
|
|
if cxSetState(FState, AIndex, Value) then Changed;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.HasImages(ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := TreeList.Images <> nil;
|
|
if Result and (ANode <> nil) and (TreeList.DoGetNodeImageIndex(ANode, tlitImageIndex) < 0) then
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.HasStateImages(ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := TreeList.StateImages <> nil;
|
|
if Result and (ANode <> nil) and (TreeList.DoGetNodeImageIndex(ANode, tlitStateIndex) < 0) then
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.HorzIncrement: Integer;
|
|
begin
|
|
Result := Byte(GridLines in [tlglVert, tlglBoth])
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.IsCategorizedPaint: Boolean;
|
|
begin
|
|
Result := PaintStyle = tlpsCategorized;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.IsExtPaintStyle: Boolean;
|
|
begin
|
|
Result := ExtPaintStyle and (GetTreeList.LookAndFeel.SkinPainter = nil);
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.IsRowAutoHeight: Boolean;
|
|
begin
|
|
Result := (TreeList.HeaderLineCount = 1) and
|
|
(CellAutoHeight or Assigned(TreeList.FOnGetNodeHeight));
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.VertIncrement: Integer;
|
|
begin
|
|
Result := Byte(GridLines in [tlglHorz, tlglBoth])
|
|
end;
|
|
|
|
function TcxTreeListOptionsView._AddRef: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView._Release: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.QueryInterface(
|
|
const IID: TGUID; out Obj): HResult;
|
|
begin
|
|
if GetInterface(IID, Obj) then
|
|
Result := 0
|
|
else
|
|
Result := cxE_NOINTERFACE;
|
|
end;
|
|
|
|
function TcxTreeListOptionsView.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(EditingControl);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetCategorizedColumn(Value: TcxTreeListColumn);
|
|
begin
|
|
FCategorizedColumn := Value;
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetColumnAutoWidth(Index: Integer; Value: Boolean);
|
|
begin
|
|
if cxSetState(FState, Index, Value) then
|
|
Changed;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetBandLineCount(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FBandLineCount, 1) then
|
|
begin
|
|
FBandLineCount := Value;
|
|
if Bands then Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetIndicatorWidth(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FIndicatorWidth, 0) then
|
|
begin
|
|
FIndicatorWidth := Value;
|
|
if Indicator then Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetFixedSeparatorColor(Value: TColor);
|
|
begin
|
|
if Value <> FFixedSeparatorColor then
|
|
begin
|
|
FFixedSeparatorColor := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetFixedSeparatorWidth(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FFixedSeparatorWidth, 0) then
|
|
begin
|
|
FFixedSeparatorWidth := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetGridLineColor(Value: TColor);
|
|
begin
|
|
if Value <> FGridLineColor then
|
|
begin
|
|
FGridLineColor := Value;
|
|
if GridLines <> tlglNone then Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetGridLines(Value: TcxTreeListGridLines);
|
|
begin
|
|
if Value <> FGridLines then
|
|
begin
|
|
FGridLines := Value;
|
|
TreeList.UpdateViewStyles;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetHeaderSingleLine(
|
|
Index: Integer; Value: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Value <> HeaderSingleLine then
|
|
begin
|
|
if Value then
|
|
for I := 0 to TreeList.ColumnCount - 1 do
|
|
cxValidateSingleLine(TreeList.Columns[I].Position);
|
|
SetState(Index, Value);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetPaintStyle(Value: TcxTreeListPaintStyle);
|
|
begin
|
|
if FPaintStyle <> Value then
|
|
begin
|
|
FPaintStyle := Value;
|
|
TreeList.UpdateViewStyles;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetTreeLineColor(Value: TColor);
|
|
begin
|
|
if Value <> FTreeLineColor then
|
|
begin
|
|
FTreeLineColor := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsView.SetTreeLineStyle(Value: TcxTreeListTreeLineStyle);
|
|
begin
|
|
if Value <> FTreeLineStyle then
|
|
begin
|
|
FTreeLineStyle := Value;
|
|
Changed;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsCustomizing }
|
|
|
|
constructor TcxTreeListOptionsCustomizing.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FState := Integer($FFFFFFFF);
|
|
DynamicSizing := False;
|
|
RowSizing := False;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsCustomizing.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListOptionsCustomizing then
|
|
FState := TcxTreeListOptionsCustomizing(Source).FState
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListOptionsCustomizing.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsCustomizing.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
cxSetState(FState, Index, Value);
|
|
end;
|
|
|
|
function TcxTreeListOptionsCustomizing.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetOwner);
|
|
end;
|
|
|
|
{ TcxTreeListOptionsSelection }
|
|
|
|
constructor TcxTreeListOptionsSelection.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
CellSelect := True;
|
|
HideFocusRect := True;
|
|
HideSelection := False;
|
|
InvertSelect := True;
|
|
MultiSelect := False;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsSelection.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListOptionsSelection then
|
|
FState := TcxTreeListOptionsSelection(Source).FState
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsSelection.Changed;
|
|
begin
|
|
TreeList.LayoutChanged;
|
|
end;
|
|
|
|
function TcxTreeListOptionsSelection.GetSelectionState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsSelection.SetSelectionState(Index: Integer; Value: Boolean);
|
|
begin
|
|
if cxSetState(FState, Index, Value) then Changed;
|
|
end;
|
|
|
|
function TcxTreeListOptionsSelection.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetOwner);
|
|
end;
|
|
|
|
{ TcxTreeListOptionsBehavior }
|
|
|
|
constructor TcxTreeListOptionsBehavior.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
ConfirmDelete := True;
|
|
DragCollapse := True;
|
|
DragExpand := True;
|
|
ExpandOnIncSearch := False;
|
|
ShowHourGlass := True;
|
|
Sorting := True;
|
|
MultiSort := True;
|
|
AutomateLeftMostIndent := True;
|
|
FWaitExpandingTime := cxTreeListDefWaitExpandTime;
|
|
ExpandOnDblClick := True;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsBehavior.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListOptionsBehavior then
|
|
begin
|
|
FState := TcxTreeListOptionsBehavior(Source).FState;
|
|
FWaitExpandingTime := TcxTreeListOptionsBehavior(Source).FWaitExpandingTime;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListOptionsBehavior.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsBehavior.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
cxSetState(FState, Index, Value);
|
|
end;
|
|
|
|
function TcxTreeListOptionsBehavior.GetChangeDelay: Integer;
|
|
begin
|
|
Result := TreeList.FDelayTimer.Interval;
|
|
end;
|
|
|
|
function TcxTreeListOptionsBehavior.GetIncSearchItem: TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(inherited IncSearchItem);
|
|
end;
|
|
|
|
function TcxTreeListOptionsBehavior.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetOwner);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsBehavior.SetAutomateLeftMostIndent(
|
|
Index: Integer; Value: Boolean);
|
|
begin
|
|
SetState(Index, Value);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsBehavior.SetChangeDelay(Value: Integer);
|
|
begin
|
|
if Value < 0 then Value := 0;
|
|
TreeList.FDelayTimer.Enabled := Value > 0;
|
|
TreeList.FDelayTimer.Interval := Value;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsBehavior.SetIncSearchItem(Value: TcxTreeListColumn);
|
|
begin
|
|
inherited IncSearchItem := Value;
|
|
end;
|
|
|
|
{ TcxTreeListOptionsData }
|
|
|
|
constructor TcxTreeListOptionsData.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Deleting := True;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsData.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListOptionsData then
|
|
begin
|
|
FState := TcxTreeListOptionsData(Source).FState;
|
|
SummaryNullIgnore := TcxTreeListOptionsData(Source).SummaryNullIgnore;
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsData.Changed;
|
|
begin
|
|
inherited Changed;
|
|
TcxCustomTreeListControl(GetOwner).RefreshNavigatorButtons;
|
|
end;
|
|
|
|
function TcxTreeListOptionsData.GetState(Index: Integer): Boolean;
|
|
begin
|
|
Result := cxGetState(FState, Index);
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsData.SetState(Index: Integer; Value: Boolean);
|
|
begin
|
|
cxSetState(FState, Index, Value);
|
|
Changed;
|
|
end;
|
|
|
|
function TcxTreeListOptionsData.GetAnsiSort: Boolean;
|
|
begin
|
|
Result := dcoAnsiSort in
|
|
TcxCustomTreeListControl(GetOwner).DataController.Options;
|
|
end;
|
|
|
|
function TcxTreeListOptionsData.GetCaseInsensitive: Boolean;
|
|
begin
|
|
Result := dcoCaseInsensitive in
|
|
TcxCustomTreeListControl(GetOwner).DataController.Options;
|
|
end;
|
|
|
|
function TcxTreeListOptionsData.GetSummaryNullIgnore: Boolean;
|
|
begin
|
|
Result := soNullIgnore in
|
|
TcxCustomTreeListControl(GetOwner).DataController.Summary.Options;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsData.SetAnsiSort(Value: Boolean);
|
|
begin
|
|
with TcxCustomTreeListControl(GetOwner).DataController do
|
|
begin
|
|
if Value then
|
|
Options := Options + [dcoAnsiSort]
|
|
else
|
|
Options := Options - [dcoAnsiSort]
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsData.SetCaseInsensitive(Value: Boolean);
|
|
begin
|
|
with TcxCustomTreeListControl(GetOwner).DataController do
|
|
begin
|
|
if Value then
|
|
Options := Options + [dcoCaseInsensitive]
|
|
else
|
|
Options := Options - [dcoCaseInsensitive]
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListOptionsData.SetSummaryNullIgnore(Value: Boolean);
|
|
begin
|
|
if Value then
|
|
TcxCustomTreeListControl(GetOwner).DataController.Summary.Options := [soNullIgnore]
|
|
else
|
|
TcxCustomTreeListControl(GetOwner).DataController.Summary.Options := [];
|
|
end;
|
|
|
|
{ TcxTreeListPreview }
|
|
|
|
constructor TcxTreeListPreview.Create(AOwner: TPersistent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FAutoHeight := True;
|
|
FLeftIndent := cxTreeListDefPreviewMaxLineCount;
|
|
FMaxLineCount := cxTreeListDefPreviewMaxLineCount;
|
|
FRightIndent := cxTreeListDefPreviewIndent;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.Assign(Source: TPersistent);
|
|
var
|
|
APreview: TcxTreeListPreview;
|
|
begin
|
|
if Source is TcxTreeListPreview then
|
|
begin
|
|
APreview := TcxTreeListPreview(Source);
|
|
AutoHeight := APreview.AutoHeight;
|
|
if APreview.Column <> nil then
|
|
Column := TreeList.Columns[APreview.Column.ItemIndex];
|
|
LeftIndent := APreview.LeftIndent;
|
|
MaxLineCount := APreview.MaxLineCount;
|
|
Place := APreview.Place;
|
|
RightIndent := APreview.RightIndent;
|
|
Visible := APreview.Visible;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.Changed(ACheckActivate: Boolean);
|
|
begin
|
|
if not ACheckActivate or (ACheckActivate and Active) then
|
|
TreeList.UpdateViewStyles;
|
|
end;
|
|
|
|
function TcxTreeListPreview.GetControl: TObject;
|
|
begin
|
|
Result := TreeList;
|
|
end;
|
|
|
|
function TcxTreeListPreview.GetActive: Boolean;
|
|
begin
|
|
Result := Visible and (FColumn <> nil);
|
|
end;
|
|
|
|
function TcxTreeListPreview.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetOwner);
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetAutoHeight(Value: Boolean);
|
|
begin
|
|
if Value <> FAutoHeight then
|
|
begin
|
|
FAutoHeight := Value;
|
|
Changed(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetColumn(Value: TcxTreeListColumn);
|
|
begin
|
|
if Value <> FColumn then
|
|
begin
|
|
FColumn := Value;
|
|
Changed(False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetLeftIndent(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FLeftIndent, 0) then
|
|
begin
|
|
FLeftIndent := Value;
|
|
Changed(True)
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetMaxLineCount(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FMaxLineCount, 0) then
|
|
begin
|
|
FMaxLineCount := Value;
|
|
Changed(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetPlace(Value: TcxTreeListPreviewPlace);
|
|
begin
|
|
if Value <> FPlace then
|
|
begin
|
|
FPlace := Value;
|
|
Changed(True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetRightIndent(Value: Integer);
|
|
begin
|
|
if cxValidateIntDefEx(Value, FRightIndent, 0) then
|
|
begin
|
|
FRightIndent := Value;
|
|
Changed(True)
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListPreview.SetVisible(Value: Boolean);
|
|
begin
|
|
if Value <> FVisible then
|
|
begin
|
|
FVisible := Value;
|
|
Changed(False);
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListStyleSheet }
|
|
|
|
function TcxTreeListStyleSheet.GetStylesValue: TcxTreeListStyles;
|
|
begin
|
|
Result := TcxTreeListStyles(GetStyles)
|
|
end;
|
|
|
|
procedure TcxTreeListStyleSheet.SetStylesValue(Value: TcxTreeListStyles);
|
|
begin
|
|
SetStyles(Value);
|
|
end;
|
|
|
|
class function TcxTreeListStyleSheet.GetStylesClass: TcxCustomStylesClass;
|
|
begin
|
|
Result := TcxTreeListStyles;
|
|
end;
|
|
|
|
{ TcxTreeListStyles }
|
|
|
|
procedure TcxTreeListStyles.Assign(Source: TPersistent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if Source is TcxTreeListStyles then
|
|
begin
|
|
for I := tlsv_BandBackground to tlsv_Preview do
|
|
SetValue(I, TcxTreeListStyles(Source).GetValue(I));
|
|
end;
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetBandBackgroundParams(
|
|
ABand: TcxTreeListBand): TcxViewParams;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_BandBackground, nil,
|
|
[GetStyleFromEvent(FOnGetBandBackgroundStyle, ABand),
|
|
ABand.Styles.HeaderBackground, BandBackground], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetBandContentParams(ABand: TcxTreeListBand;
|
|
ANode: TcxTreeListNode): TcxViewParams;
|
|
begin
|
|
DoGetBandContentParams(ANode, ABand, Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetBandHeaderParams(
|
|
ABand: TcxTreeListBand): TcxViewParams;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_BandHeader, nil,
|
|
[GetStyleFromEvent(FOnGetBandHeaderStyle, ABand),
|
|
ABand.Styles.Header, BandHeader], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetBandFooterParams(
|
|
ABand: TcxTreeListBand): TcxViewParams;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_Footer, nil,
|
|
[GetStyleFromEvent(FOnGetBandFooterStyle, ABand),
|
|
ABand.Styles.Footer, Footer], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetColumnContentParams(
|
|
AColumn: TcxTreeListColumn; IsOdd: Boolean): TcxViewParams;
|
|
begin
|
|
Result := AColumn.Styles.ContentParams[IsOdd];
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetColumnHeaderParams(
|
|
AColumn: TcxTreeListColumn): TcxViewParams;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_ColumnHeader, nil,
|
|
[GetStyleFromEvent(FOnGetColumnHeaderStyle, AColumn),
|
|
AColumn.Styles.Header, ColumnHeader], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetColumnFooterParams(
|
|
AColumn: TcxTreeListColumn): TcxViewParams;
|
|
begin
|
|
if AColumn.OwnerBand <> nil then
|
|
begin
|
|
Result := GetBandFooterParams(AColumn.OwnerBand);
|
|
cxParamsCombine(ColumnFooter,
|
|
cxParamsCombine(AColumn.Styles.Footer, [], Result), Result) ;
|
|
end
|
|
else
|
|
cxStylesToViewParams(Self, tlsv_ColumnFooter, nil,
|
|
[GetStyleFromEvent(FOnGetColumnFooterStyle, AColumn),
|
|
AColumn.Styles.Footer, ColumnFooter, Footer], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetContentParams(ANode: TcxTreeListNode;
|
|
AColumn: TcxTreeListColumn): TcxViewParams;
|
|
begin
|
|
if not ANode.IsVisible then ANode.FVisibleIndex := -1;
|
|
DoGetContentParams(ANode, AColumn, Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetFooterParams: TcxViewParams;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_Footer, nil, [Footer], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetIncSearchParams: TcxViewParams;
|
|
begin
|
|
GetViewParams(tlsv_IncSearch, nil, IncSearch, Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetIndentParams(
|
|
ANode: TcxTreeListNode; AIndent: Integer): TcxViewParams;
|
|
|
|
function GetIndentParams: TcxViewParams;
|
|
var
|
|
AStyle: TcxStyle;
|
|
begin
|
|
with TreeList.OptionsView do
|
|
begin
|
|
AIndent := ANode.Level - AIndent + Byte(ShowRoot);
|
|
if IsCategorizedPaint then
|
|
while AIndent > 0 do
|
|
begin
|
|
ANode := ANode.Parent;
|
|
Dec(AIndent);
|
|
end;
|
|
AStyle := nil;
|
|
if Assigned(FOnGetContentStyle) and (ANode <> ANode.Owner.Root) then
|
|
FOnGetContentStyle(Control, nil, ANode, AStyle);
|
|
if (UseNodeColorForIndent or (AIndent < 0)) then
|
|
begin
|
|
Result := ContentParams[Odd(ANode.FVisibleIndex)];
|
|
cxParamsCombine(AStyle, [], Result);
|
|
end
|
|
else
|
|
cxStylesToViewParams(Self, tlsv_Content, nil, [AStyle, Content], Result);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
AStyle: TcxStyle;
|
|
begin
|
|
AStyle := nil;
|
|
Result.Bitmap := nil;
|
|
if Assigned(FOnGetNodeIndentStyle) then
|
|
FOnGetNodeIndentStyle(Control, ANode, AIndent, AStyle);
|
|
Result := GetIndentParams;
|
|
cxParamsCombine(AStyle, [], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetIndicatorParams: TcxViewParams;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_Indicator, nil, [Indicator], Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetPreviewParams(ANode: TcxTreeListNode): TcxViewParams;
|
|
var
|
|
AStyle: TcxStyle;
|
|
begin
|
|
DoGetContentParams(ANode, TreeList.Preview.Column, Result);
|
|
AStyle := GetStyleFromEvent(FOnGetPreviewStyle, ANode);
|
|
cxParamsCombine(Preview, cxParamsCombine(AStyle, [], Result), Result);
|
|
end;
|
|
|
|
procedure TcxTreeListStyles.ContentStyleChanged;
|
|
var
|
|
I: Integer;
|
|
B: Boolean;
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_Preview, nil, [Preview], CachedPreviewStyle);
|
|
for B := False to True do
|
|
begin
|
|
cxStylesToViewParams(Self, tlsv_Content, nil,
|
|
[GetValue(tlsv_ContentEven + Byte(B)), Content], ContentParams[B]);
|
|
end;
|
|
with TreeList do
|
|
begin
|
|
for I := 0 to Bands.Count - 1 do
|
|
Bands[I].Styles.CachedContentStyleChanged;
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].Styles.CachedContentStyleChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListStyles.DoGetContentParams(
|
|
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AParams: TcxViewParams);
|
|
var
|
|
AStyle: TcxStyle;
|
|
AValues: TcxStyleValues;
|
|
begin
|
|
if AColumn <> TreeList.Preview.Column then
|
|
begin
|
|
AParams := AColumn.Styles.ContentParams[Odd(ANode.FVisibleIndex)];
|
|
if DoGetBandContentStyle(ANode, AColumn.OwnerBand, AStyle) then
|
|
cxParamsCombine(AStyle, [], AParams);
|
|
AStyle := nil;
|
|
end
|
|
else
|
|
begin
|
|
AStyle := nil;
|
|
AParams := ContentParams[Odd(ANode.FVisibleIndex)];
|
|
end;
|
|
if Assigned(FOnGetContentStyle) then
|
|
FOnGetContentStyle(Control, AColumn, ANode, AStyle);
|
|
cxParamsCombine(AStyle, [], AParams);
|
|
if ANode.HotTrack and (not TreeList.IsEditing or (TreeList.FocusedNode <> ANode)) then
|
|
begin
|
|
AStyle := nil;
|
|
if Assigned(FOnGetHotTrackStyle) then
|
|
FOnGetHotTrackStyle(Control, AColumn, ANode, AStyle);
|
|
AValues := cxParamsCombine(HotTrack, cxParamsCombine(AStyle, [], AParams), AParams);
|
|
if not (svTextColor in AValues) then
|
|
AParams.TextColor := clHighLightText;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListStyles.DoGetBandContentParams(
|
|
ANode: TcxTreeListNode; ABand: TcxTreeListBand; var AParams: TcxViewParams);
|
|
var
|
|
AStyle: TcxStyle;
|
|
begin
|
|
AParams := ABand.Styles.ContentParams[Odd(ANode.FVisibleIndex)];
|
|
DoGetBandContentStyle(ANode, ABand, AStyle);
|
|
cxParamsCombine(BandContent, cxParamsCombine(AStyle, [], AParams), AParams);
|
|
end;
|
|
|
|
function TcxTreeListStyles.DoGetBandContentStyle(
|
|
ANode: TcxTreeListNode; ABand: TcxTreeListBand; out AStyle: TcxStyle): Boolean;
|
|
begin
|
|
AStyle := nil;
|
|
if Assigned(FOnGetBandContentStyle) then
|
|
FOnGetBandContentStyle(TreeList, ABand, ANode, AStyle);
|
|
Result := AStyle <> nil;
|
|
end;
|
|
|
|
procedure TcxTreeListStyles.GetDefaultViewParams(
|
|
Index: Integer; AData: TObject; out AParams: TcxViewParams);
|
|
begin
|
|
with TcxCustomTreeListControl(Control).LookAndFeelPainter, AParams do
|
|
begin
|
|
Bitmap := nil;
|
|
Font := TcxCustomTreeListControl(Control).Font;
|
|
case Index of
|
|
tlsv_Preview, tlsv_ContentOdd, tlsv_ContentEven, tlsv_Content:
|
|
begin
|
|
Color := DefaultContentColor;
|
|
TextColor := DefaultContentTextColor;
|
|
end;
|
|
tlsv_BandHeader, tlsv_Indicator, tlsv_ColumnHeader:
|
|
begin
|
|
Color := DefaultHeaderColor;
|
|
TextColor := DefaultHeaderTextColor;
|
|
end;
|
|
tlsv_Footer, tlsv_ColumnFooter:
|
|
begin
|
|
Color := DefaultFooterColor;
|
|
TextColor := DefaultFooterTextColor;
|
|
end;
|
|
tlsv_BandBackground:
|
|
begin
|
|
Color := DefaultHeaderBackgroundColor;
|
|
TextColor := DefaultHeaderBackgroundTextColor;
|
|
end;
|
|
tlsv_IncSearch:
|
|
begin
|
|
Color := DefaultSelectionColor;
|
|
TextColor := DefaultSelectionTextColor;
|
|
end;
|
|
else
|
|
inherited GetDefaultViewParams(Index, AData, AParams);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetStyleFromEvent(
|
|
const AEvent: TcxtlOnGetItemStyleEvent; AItem: TObject): TcxStyle;
|
|
begin
|
|
Result := nil;
|
|
if Assigned(AEvent) then AEvent(Control, AItem, Result);
|
|
end;
|
|
|
|
function TcxTreeListStyles.SelectionFontAssigned: Boolean;
|
|
begin
|
|
if TreeList.Controller.Focused or Control.Focused then
|
|
Result := (Selection <> nil) and (cxStyles.svFont in Selection.AssignedValues)
|
|
else
|
|
Result := (Inactive <> nil) and (cxStyles.svFont in Inactive.AssignedValues);
|
|
end;
|
|
|
|
function TcxTreeListStyles.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := TcxCustomTreeListControl(GetOwner);
|
|
end;
|
|
|
|
{ TcxTreeListItemsCustomizeListBox }
|
|
|
|
constructor TcxTreeListItemsCustomizeListBox.CreateEx(AOwner: TComponent;
|
|
ATreeList: TcxCustomTreeListControl; IsBandListBox: Boolean);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Style.HotTrack := False;
|
|
FDragAndDropItemIndex := -1;
|
|
OnMeasureItem := MeasureItem;
|
|
InnerListBox.OnDrawItem := DoDrawItemEx;
|
|
OnDrawItem := DoDrawItem;
|
|
FTreeList := ATreeList;
|
|
FIsBandListBox := IsBandListBox;
|
|
ListStyle := lbOwnerDrawVariable;
|
|
Style.LookAndFeel.MasterLookAndFeel := ATreeList.LookAndFeel;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.BeginDrag;
|
|
begin
|
|
SetCaptureControl(TreeList);
|
|
FPrevCursor := Screen.Cursor;
|
|
if FDragAndDropObject <> nil then Exit;
|
|
FDragAndDropObject := TcxTreeListDragAndDropObject.Create(TreeList);
|
|
InitDragAndDropObject;
|
|
TreeList.DragAndDropState := ddsStarting;
|
|
TreeList.Customizing.FDragAndDropObject := FDragAndDropObject;
|
|
FDragAndDropObject.BeginDragAndDrop;
|
|
SetCaptureControl(Self);
|
|
TreeList.Customizing.FForm.StartDeactivationTimer(Self);
|
|
FAccepted := True;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.FocusChanged;
|
|
begin
|
|
if not IsFocused then
|
|
FinishDrag(False);
|
|
inherited FocusChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.DoDrawItem(AControl: TcxListBox;
|
|
ACanvas: TcxCanvas; AIndex: Integer; ARect: TRect; AState: TOwnerDrawState);
|
|
var
|
|
R: TRect;
|
|
ABitmap: TBitmap;
|
|
ABmpCanvas: TcxCanvas;
|
|
begin
|
|
ABitmap := cxCreateBitmap(cxRectSize(ARect));
|
|
ABmpCanvas := TcxCanvas.Create(ABitmap.Canvas);
|
|
try
|
|
R := cxRectOffset(ARect, cxPointInvert(ARect.TopLeft));
|
|
with TcxTreeListHeaderViewInfo(Items.Objects[AIndex]) do
|
|
begin
|
|
InitViewParams;
|
|
if Painter.HeaderDrawCellsFirst then
|
|
begin
|
|
ABmpCanvas.Brush.Color := Color;
|
|
ABmpCanvas.FillRect(R);
|
|
end;
|
|
with TcxTreeListControlPainter(TreeList.Painter) do
|
|
begin
|
|
ExtDrawHeader(ABmpCanvas, R, cxRectInflate(R, -2, -2), [],
|
|
cxBordersAll, cxbsNormal, AlignHorz, AlignVert, False, True, Text,
|
|
ViewParams.Font, ViewParams.TextColor, ViewParams.Color, nil);
|
|
end;
|
|
end;
|
|
ACanvas.Draw(ARect.Left, ARect.Top, ABitmap);
|
|
finally
|
|
ABmpCanvas.Free;
|
|
ABitmap.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.DoDrawItemEx(Control: TWinControl;
|
|
Index: Integer; Rect: TRect; State: TOwnerDrawState);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.EndDrag(Accepted: Boolean);
|
|
begin
|
|
if FDragAndDropObject <> nil then
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
try
|
|
if not Accepted then FAccepted := False;
|
|
FDragAndDropObject.EndDragAndDrop(FAccepted);
|
|
finally
|
|
FreeAndNil(FDragAndDropObject);
|
|
TreeList.Customizing.FDragAndDropObject := nil;
|
|
Screen.Cursor := FPrevCursor;
|
|
end;
|
|
finally
|
|
TreeList.DragAndDropState := ddsNone;
|
|
if not FAccepted then
|
|
TreeList.CancelUpdate
|
|
else
|
|
TreeList.EndUpdate;
|
|
end;
|
|
TreeList.Controller.EndDragAndDrop(Accepted);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.FinishDrag(Accepted: Boolean);
|
|
|
|
begin
|
|
if FDragAndDropObject <> nil then
|
|
begin
|
|
TreeList.BeginUpdate;
|
|
try
|
|
try
|
|
if not Accepted then FAccepted := False;
|
|
with FDragAndDropObject do
|
|
DragDropInfo.Accepted := DragDropInfo.Accepted and FAccepted;
|
|
FDragAndDropObject.EndDragAndDrop(FAccepted);
|
|
finally
|
|
FreeAndNil(FDragAndDropObject);
|
|
TreeList.Customizing.FDragAndDropObject := nil;
|
|
Screen.Cursor := FPrevCursor;
|
|
end;
|
|
finally
|
|
TreeList.DragAndDropState := ddsNone;
|
|
if not FAccepted then
|
|
TreeList.CancelUpdate
|
|
else
|
|
TreeList.EndUpdate;
|
|
end;
|
|
TreeList.Controller.EndDragAndDrop(Accepted);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.InitDragAndDropObject;
|
|
var
|
|
AInfo: TcxTreeListHeaderViewInfo;
|
|
begin
|
|
FOrgPoint := Point(0, 0);
|
|
MapWindowPoint(Handle, TreeList.Handle, FOrgPoint);
|
|
AInfo := TcxTreeListHeaderViewInfo(Items.Objects[ItemIndex]);
|
|
AInfo.InitViewParams;
|
|
TreeList.Controller.DragItem := AInfo;
|
|
AInfo.DisplayRect := cxRectOffset(ItemRect(ItemIndex),
|
|
[cxPointInvert(ScreenToClient(Mouse.CursorPos)),
|
|
cxPointInvert(TreeList.ClientToScreen(Point(0, 0)))]);
|
|
AInfo.FTextBounds := cxRectInflate(AInfo.DisplayRect, -2, -2);
|
|
AInfo.ClipRect := AInfo.DisplayRect;
|
|
AInfo.ItemVisible := True;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.MouseDown(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
if (Button = mbLeft) and (ItemAtPos(Point(X, Y), True) <> -1) then
|
|
begin
|
|
FDragAndDropItemIndex := ItemIndex;
|
|
FMouseDownPos := Point(X, Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.MouseMove(
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if (FDragAndDropItemIndex <> -1) and
|
|
(not IsPointInDragDetectArea(FMouseDownPos, X, Y) or
|
|
(ItemAtPos(Point(X, Y), True) <> FDragAndDropItemIndex)) then
|
|
begin
|
|
ItemIndex := FDragAndDropItemIndex;
|
|
BeginDrag;
|
|
FDragAndDropItemIndex := -1;
|
|
end;
|
|
if FDragAndDropObject <> nil then
|
|
begin
|
|
TreeList.DragAndDropState := ddsInProcess;
|
|
DragAndDropObject.PrevMousePos := DragAndDropObject.CurMousePos;
|
|
DragAndDropObject.CurMousePos := ClientToScreen(Point(X, Y));
|
|
DragAndDropObject.DragAndDrop(cxPointOffset(FOrgPoint, X, Y), FAccepted);
|
|
end
|
|
else
|
|
inherited MouseMove(Shift, X, Y);
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.MouseUp(
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
if DragAndDropObject <> nil then
|
|
begin
|
|
FinishDrag(True);
|
|
RefreshList;
|
|
Update;
|
|
end;
|
|
FDragAndDropItemIndex := -1;
|
|
end;
|
|
|
|
function TcxTreeListItemsCustomizeListBox.GetItemHeight(AItem: Integer): Integer;
|
|
begin
|
|
if FIsBandListBox then
|
|
Result := TreeList.RealBandLineHeight
|
|
else
|
|
Result := TreeList.ViewInfo.HeaderLineHeight;
|
|
if Result = 0 then Result := ItemHeight;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.KeyDown(
|
|
var Key: Word; Shift: TShiftState);
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
if (Key = VK_ESCAPE) and (FDragAndDropObject <> nil) then
|
|
begin
|
|
FDragAndDropObject.DragDropInfo.Accepted := False;
|
|
FinishDrag(False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.MeasureItem(AControl: TcxListBox;
|
|
Index: Integer; var Height: Integer);
|
|
begin
|
|
Height := GetItemHeight(Index);
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.RefreshList;
|
|
var
|
|
I: Integer;
|
|
AIndex: Integer;
|
|
begin
|
|
AIndex := ItemIndex;
|
|
Items.BeginUpdate;
|
|
Items.Clear;
|
|
with FTreeList do
|
|
try
|
|
if FIsBandListBox then
|
|
begin
|
|
for I := 0 to Bands.Count - 1 do
|
|
if not Bands[I].Visible and not Bands[I].Options.Hidden then
|
|
Self.Items.AddObject('', Bands[I].ViewInfo.BandHeader);
|
|
end
|
|
else
|
|
begin
|
|
for I := 0 to ColumnCount - 1 do
|
|
if not Columns[I].Visibility and not Columns[I].Options.Hidden then
|
|
Self.Items.AddObject('', Columns[I].ViewInfo.ColumnHeader);
|
|
end;
|
|
finally
|
|
if AIndex >= Self.Items.Count then
|
|
AIndex := Self.Items.Count - 1;
|
|
ItemIndex := AIndex;
|
|
Self.Items.EndUpdate;
|
|
end;
|
|
Update;
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.Resize;
|
|
begin
|
|
inherited Resize;
|
|
InnerListBox.Invalidate
|
|
end;
|
|
|
|
procedure TcxTreeListItemsCustomizeListBox.WMCancelMode(var Message: TWMCancelMode);
|
|
begin
|
|
inherited;
|
|
FinishDrag(False);
|
|
end;
|
|
|
|
function TcxTreeListItemsCustomizeListBox.GetPainter: TcxCustomLookAndFeelPainterClass;
|
|
begin
|
|
Result := TreeList.LookAndFeel.Painter;
|
|
end;
|
|
|
|
{ TcxTreeListCustomizationForm }
|
|
|
|
constructor TcxTreeListCustomizationForm.CreateEx(AOwner: TcxTreeListCustomizing);
|
|
begin
|
|
CreateNew(nil);
|
|
FOwner := AOwner;
|
|
FHookTimer := TcxTimer.Create(Self);
|
|
FHookTimer.Enabled := False;
|
|
FHookTimer.Interval := 10;
|
|
FHookTimer.OnTimer := HookTimerHandler;
|
|
|
|
FDeactivationTimer := TTimer.Create(Self);
|
|
FDeactivationTimer.Enabled := False;
|
|
FDeactivationTimer.Interval := 10;
|
|
end;
|
|
|
|
destructor TcxTreeListCustomizationForm.Destroy;
|
|
begin
|
|
FreeAndNil(FHookTimer);
|
|
FreeAndNil(FDeactivationTimer);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxTreeListCustomizationForm.GetTreeList: TcxCustomTreeListControl;
|
|
begin
|
|
Result := Customizing.TreeList;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizationForm.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited;
|
|
with Params do
|
|
begin
|
|
Style := Style or WS_POPUP;
|
|
if not TreeList.IsDestroying then
|
|
WndParent := TreeList.Handle
|
|
else
|
|
WndParent := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizationForm.DeactivationTimeHandler(Sender: TObject);
|
|
begin
|
|
if not Active then
|
|
begin
|
|
StopDeactivationTimer;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizationForm.StartDeactivationTimer(
|
|
Sender: TcxTreeListItemsCustomizeListBox);
|
|
begin
|
|
FCustomizingListBox := Sender;
|
|
FDeactivationTimer.Enabled := True;
|
|
FDeactivationTimer.OnTimer := DeactivationTimeHandler;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizationForm.StopDeactivationTimer;
|
|
begin
|
|
if FCustomizingListBox <> nil then
|
|
try
|
|
FCustomizingListBox.FinishDrag(False);
|
|
FDeactivationTimer.Enabled := False;
|
|
FDeactivationTimer.OnTimer := nil;
|
|
finally
|
|
FCustomizingListBox := nil;
|
|
Invalidate;
|
|
Update;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizationForm.HookTimerHandler(Sender: TObject);
|
|
begin
|
|
if IsIconic(Application.Handle) then
|
|
Visible := False
|
|
else
|
|
if not TreeList.Visible or not IsWindowVisible(TreeList.Handle) then
|
|
Customizing.Visible := False
|
|
else
|
|
if not Visible then
|
|
begin
|
|
ShowWindow(Handle, SW_SHOWNOACTIVATE);
|
|
Visible := True;
|
|
end;
|
|
end;
|
|
|
|
{ TcxTreeListCustomizing }
|
|
|
|
constructor TcxTreeListCustomizing.Create(AOwner: TPersistent);
|
|
begin
|
|
FTreeList := TcxCustomTreeListControl(AOwner);
|
|
FVisible := False;
|
|
FRowCount := 10;
|
|
FLastPosition := cxPoint(-1000, -1000);
|
|
end;
|
|
|
|
destructor TcxTreeListCustomizing.Destroy;
|
|
begin
|
|
Visible := False;
|
|
ReleaseControls;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TcxTreeListCustomizing then
|
|
begin
|
|
RowCount := TcxTreeListCustomizing(Source).RowCount;
|
|
Visible := TcxTreeListCustomizing(Visible).Visible;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.MakeBandSheetVisible;
|
|
begin
|
|
Visible := True;
|
|
if FBandListBox.Parent = FTabSheetBands then
|
|
FPageControl.ActivePage := FTabSheetBands;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.MakeColumnSheetVisible;
|
|
begin
|
|
Visible := True;
|
|
if FHeaderListBox.Parent = FTabSheetHeaders then
|
|
FPageControl.ActivePage := FTabSheetHeaders;
|
|
end;
|
|
|
|
function TcxTreeListCustomizing.PtInCustomizingBox(const APoint: TPoint): Boolean;
|
|
begin
|
|
Result := Visible and (FForm <> nil) and PtInRect(FForm.BoundsRect, APoint);
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.AdjustControls;
|
|
var
|
|
AParent: TWinControl;
|
|
begin
|
|
with TreeList do
|
|
begin
|
|
AParent := FForm;
|
|
if not IsSimpleMode then
|
|
begin
|
|
SetControlParent(FPageControl, FForm);
|
|
SetControlParent(FTabSheetBands, FPageControl);
|
|
FTabSheetBands.PageControl := FPageControl;
|
|
SetControlParent(FBandListBox, FTabSheetBands);
|
|
if ColumnCount > 0 then
|
|
begin
|
|
SetControlParent(FTabSheetHeaders, FPageControl);
|
|
FTabSheetHeaders.PageControl := FPageControl;
|
|
AParent := FTabSheetHeaders;
|
|
end;
|
|
end;
|
|
if ColumnCount > 0 then
|
|
SetControlParent(FHeaderListBox, AParent);
|
|
end;
|
|
ShowCustomizingForm;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.Activate(Sender: TObject);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.Close(Sender: TObject; var Action: TCloseAction);
|
|
|
|
function CheckIndex(AListBox: TcxListBox): Integer;
|
|
begin
|
|
if (AListBox = nil) or (AListBox.Parent = nil) then
|
|
Result := -1
|
|
else
|
|
Result := AListBox.ItemIndex;
|
|
end;
|
|
|
|
begin
|
|
if FForm <> nil then
|
|
TcxTreeListCustomizationForm(FForm).HookTimer.Enabled := False;
|
|
FLastPosition := FForm.BoundsRect.TopLeft;
|
|
FLastHeaderIndex := CheckIndex(FHeaderListBox);
|
|
FLastBandIndex := CheckIndex(FBandListBox);
|
|
Action := caHide;
|
|
FVisible := False;
|
|
TreeList.DoOnCustomizationVisibleChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.CreateControls;
|
|
begin
|
|
if FForm <> nil then
|
|
begin
|
|
FForm.Show;
|
|
Exit;
|
|
end;
|
|
CreateCustomizingForm;
|
|
FForm.OnClose := Close;
|
|
FHeaderListBox := TcxTreeListItemsCustomizeListBox.CreateEx(nil, TreeList, False);
|
|
if not IsSimpleMode then
|
|
begin
|
|
FBandListBox := TcxTreeListItemsCustomizeListBox.CreateEx(nil, TreeList, True);
|
|
FPageControl := TPageControl.Create(nil);
|
|
FPageControl.HotTrack := True;
|
|
FTabSheetBands := TTabSheet.Create(FPageControl);
|
|
FTabSheetBands.Caption := cxGetResourceString(@scxBandsCaption);
|
|
FTabSheetBands.TabVisible := True;
|
|
FTabSheetHeaders := TTabSheet.Create(FPageControl);
|
|
FTabSheetHeaders.Caption := cxGetResourceString(@scxColumnsCaption);
|
|
FTabSheetBands.TabVisible := True;
|
|
end;
|
|
AdjustControls;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.CreateCustomizingForm;
|
|
var
|
|
I: Integer;
|
|
const
|
|
UnusedItems: array[0..4, 0..1] of Integer =
|
|
((7, MF_BYPOSITION), (5, MF_BYPOSITION), (SC_MAXIMIZE, MF_BYCOMMAND),
|
|
(SC_MINIMIZE, MF_BYCOMMAND), (SC_RESTORE, MF_BYCOMMAND));
|
|
begin
|
|
FForm := TcxTreeListCustomizationForm.CreateEx(Self);
|
|
with FForm do
|
|
begin
|
|
Visible := False;
|
|
Caption := cxGetResourceString(@scxCustomizeCaption);
|
|
BorderStyle := bsSizeToolWin;
|
|
BorderIcons := [biSystemMenu];
|
|
Font.Assign(TreeList.Font);
|
|
ClientWidth := SizeDelta.cx * cxTextWidth(Font, '0');
|
|
FLineHeight := cxTextHeight(Font) + SizeDelta.cy;
|
|
ClientHeight := (RowCount + 1) * FLineHeight;
|
|
Color := clBtnFace;
|
|
OnActivate := Self.Activate;
|
|
OnClose := Self.Close;
|
|
OnShow := VisibleChanged;
|
|
OnHide := VisibleChanged;
|
|
for I := 0 to High(UnusedItems) do
|
|
DeleteMenu(GetSystemMenu(Handle, False), UnusedItems[I, 0], UnusedItems[I, 1]);
|
|
end;
|
|
end;
|
|
|
|
function TcxTreeListCustomizing.IsSimpleMode: Boolean;
|
|
begin
|
|
with TreeList.OptionsView do
|
|
Result := SimpleCustomizeBox or not Bands;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.LookAndFeelChanged;
|
|
begin
|
|
if FBandListBox <> nil then
|
|
FBandListBox.Invalidate;
|
|
if FHeaderListBox <> nil then
|
|
FHeaderListBox.Invalidate;
|
|
if FPageControl <> nil then
|
|
FPageControl.Invalidate;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.ReleaseControls;
|
|
begin
|
|
TreeList.Designers.Remove(Self);
|
|
if FForm <> nil then
|
|
try
|
|
FLastPosition := Point(FForm.Left, FForm.Top);
|
|
FLastBandIndex := -1;
|
|
FLastHeaderIndex := -1;
|
|
FForm.Free
|
|
finally
|
|
FForm := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.SetControlParent(AControl, AParent: TWinControl);
|
|
begin
|
|
AControl.Parent := AParent;
|
|
if AParent <> nil then
|
|
begin
|
|
AControl.Align := alClient;
|
|
TControlAccess(AControl).ParentFont := True;
|
|
TControlAccess(AControl).ParentColor := True;
|
|
Visible := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.ShowCustomizingForm;
|
|
var
|
|
R: TRect;
|
|
begin
|
|
if (CustomizingPos.X <> -1000) and (CustomizingPos.Y <> -1000) then
|
|
begin
|
|
FForm.Left := CustomizingPos.X;
|
|
FForm.Top := CustomizingPos.Y;
|
|
end
|
|
else
|
|
begin
|
|
if GetParentForm(TreeList) = nil then
|
|
R := TreeList.BoundsRect
|
|
else
|
|
R := GetParentForm(TreeList).BoundsRect;
|
|
FForm.Left := R.Right - FForm.Width;
|
|
FForm.Top := R.Bottom - FForm.Height;
|
|
if FForm.Left < 0 then FForm.Left := 0;
|
|
if FForm.Top < 0 then FForm.Top := 0;
|
|
end;
|
|
ValidateListBox(FHeaderListBox, FLastHeaderIndex);
|
|
ValidateListBox(FBandListBox, FLastBandIndex);
|
|
FForm.Show;
|
|
end;
|
|
|
|
function TcxTreeListCustomizing.SizeDelta: TSize;
|
|
begin
|
|
Result := cxSize(28, 4);
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.ComponentRemoved(Sender: TObject);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.Modified;
|
|
begin
|
|
if (FHeaderListBox <> nil) and (FHeaderListBox.Parent <> nil) then
|
|
FHeaderListBox.RefreshList;
|
|
if (FBandListBox <> nil) and (FBandListBox.Parent <> nil) then
|
|
FBandListBox.RefreshList;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.ValidateListBox(
|
|
AListBox: TcxTreeListItemsCustomizeListBox; AIndex: Integer);
|
|
begin
|
|
if (AListBox = nil) or (AListBox.Parent = nil) then Exit;
|
|
AListBox.RefreshList;
|
|
if (AIndex >= 0) and (AIndex < AListBox.Items.Count) then
|
|
AListBox.ItemIndex := AIndex;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.VisibleChanged(Sender: TObject);
|
|
begin
|
|
TreeList.DoOnCustomizationVisibleChanged;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.Update;
|
|
begin
|
|
if FBandListBox <> nil then FBandListBox.Invalidate;
|
|
if FHeaderListBox <> nil then FHeaderListBox.Invalidate;
|
|
end;
|
|
|
|
function TcxTreeListCustomizing.GetForm: TForm;
|
|
begin
|
|
Result := FForm;
|
|
end;
|
|
|
|
function TcxTreeListCustomizing.GetVisible: Boolean;
|
|
begin
|
|
Result := FVisible and ((FForm <> nil) and FForm.Visible);
|
|
FVisible := Result;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.SetRowCount(Value: Integer);
|
|
begin
|
|
if Value < 2 then Value := 2;
|
|
if Value <> FRowCount then
|
|
FRowCount := Value;
|
|
end;
|
|
|
|
procedure TcxTreeListCustomizing.SetVisible(Value: Boolean);
|
|
|
|
function CanVisible: Boolean;
|
|
begin
|
|
with TreeList.OptionsView do
|
|
Result := ((TreeList.Bands.Count > 0) and Bands and not SimpleCustomizeBox) or
|
|
(Headers and (TreeList.ColumnCount > 0));
|
|
end;
|
|
|
|
begin
|
|
if Value <> FVisible then
|
|
begin
|
|
if Value and not CanVisible then Exit;
|
|
FVisible := Value;
|
|
if FForm <> nil then
|
|
TcxTreeListCustomizationForm(FForm).HookTimer.Enabled := False;
|
|
if not Value then
|
|
ReleaseControls
|
|
else
|
|
begin
|
|
CreateControls;
|
|
TreeList.Designers.Add(Self);
|
|
Form.Visible := True;
|
|
TcxTreeListCustomizationForm(FForm).HookTimer.Enabled := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ TcxCustomTreeListControl }
|
|
|
|
constructor TcxCustomTreeListControl.Create(AOwner: TComponent);
|
|
begin
|
|
FNodesList := TList.Create;
|
|
FDeletedNodes := TList.Create;
|
|
inherited Create(AOwner);
|
|
ControlStyle := ControlStyle + [csDisplayDragImage];
|
|
FNeedMakeVisible := True;
|
|
Width := 250;
|
|
Height := 150;
|
|
if Assigned(DesignerNavigatorProc) then
|
|
DesignerNavigatorProc(Self, True);
|
|
end;
|
|
|
|
destructor TcxCustomTreeListControl.Destroy;
|
|
begin
|
|
Customizing.Visible := False;
|
|
if Assigned(DesignerNavigatorProc) then
|
|
DesignerNavigatorProc(Self, False);
|
|
BeginUpdate;
|
|
try
|
|
inherited Destroy;
|
|
finally
|
|
FNodesList.Free;
|
|
FDeletedNodes.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.AdjustColumnsWidth;
|
|
var
|
|
I: Integer;
|
|
APrevValue: Boolean;
|
|
begin
|
|
APrevValue := OptionsView.ColumnAutoWidth;
|
|
OptionsView.ColumnAutoWidth := True;
|
|
BeginUpdate;
|
|
try
|
|
for I := 0 to VisibleColumnCount - 1 do
|
|
VisibleColumns[I].Width := VisibleColumns[I].RealWidth;
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
VisibleBands[I].Width := VisibleBands[I].RealWidth;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
OptionsView.ColumnAutoWidth := APrevValue;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ApplyBestFit;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
FContentIndentWidth := 0;
|
|
HandleNeeded;
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
VisibleBands[I].ApplyBestFit;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Clear;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
DoClear;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoBandSizeChanged(ABand: TcxTreeListBand);
|
|
begin
|
|
Modified;
|
|
LayoutChanged;
|
|
DoOnBandSizeChanged(ABand);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoColumnSizeChanged(AColumn: TcxTreeListColumn);
|
|
begin
|
|
Modified;
|
|
DoOnColumnSizeChanged(AColumn);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoCreateColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := GetTreeListColumnClass.Create(Owner);
|
|
Result.EditingControl := Self;
|
|
Modified;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CreateColumn(
|
|
ABand: TcxTreeListBand = nil): TcxTreeListColumn;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
Result := DoCreateColumn;
|
|
if ABand = nil then
|
|
begin
|
|
if Bands.Count = 0 then Bands.Add;
|
|
if VisibleBandCount > 0 then
|
|
ABand := VisibleBands[0]
|
|
else
|
|
ABand := Bands[0]
|
|
end;
|
|
if (ABand <> nil) and Result.Visible then
|
|
Result.Position.FColIndex := ABand.FColumns.Count;
|
|
Result.OwnerBand := ABand;
|
|
ViewInfo.IsDirty := True;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DeleteAllColumns;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
ViewInfo.NodesViewInfo.Clear;
|
|
while ColumnCount > 0 do TObject(ContainerList.List^[0]).Free;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DeleteSelection;
|
|
begin
|
|
DoDeleteSelection;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DragDrop(Source: TObject; X, Y: Integer);
|
|
var
|
|
AFocusedIndex: Integer;
|
|
begin
|
|
if Source <> Self then
|
|
begin
|
|
if Assigned(OnDragDrop) then
|
|
OnDragDrop(Self, Source, X, Y);
|
|
Controller.DragDrop(Source, X, Y);
|
|
Exit;
|
|
end;
|
|
HitTest.HitPoint := Point(X, Y);
|
|
AFocusedIndex := -1;
|
|
try
|
|
if DragNode <> nil then
|
|
AFocusedIndex := DragNode.RecordIndex;
|
|
if Assigned(OnDragDrop) then
|
|
OnDragDrop(Self, Source, X, Y);
|
|
Controller.DragDrop(Source, X, Y);
|
|
if FocusedNode <> nil then
|
|
FocusedNode.MakeVisible;
|
|
finally
|
|
FDragNode := nil;
|
|
if AFocusedIndex < DataController.RecordCount then
|
|
DataController.FocusedRecordIndex := AFocusedIndex;
|
|
if FocusedNode <> nil then
|
|
FocusedNode.MakeVisible;
|
|
RestoreDragPos;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetIndentWidth(IsLeftMost: Boolean): Integer;
|
|
begin
|
|
if IsLeftMost then
|
|
Result := FContentIndentWidth
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.MakeDefaultLayout;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
OptionsView.Bands := False;
|
|
while Bands.Count > 1 do
|
|
Bands[Bands.Count - 1].Free;
|
|
if Bands.Count = 0 then Bands.Add;
|
|
Bands[0].RestoreDefaults;
|
|
Bands[0].Visible := True;
|
|
for I := 0 to ColumnCount - 1 do
|
|
with Columns[I] do
|
|
begin
|
|
RestoreDefaults;
|
|
Position.BandIndex := 0;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
Modified;
|
|
FDefaultLayout := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.FullCollapse;
|
|
begin
|
|
Nodes.Root.Collapse(True);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.FullExpand;
|
|
begin
|
|
Nodes.Root.Expand(True);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.FullRefresh;
|
|
begin
|
|
LayoutChanged;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.Find(AData: Pointer;
|
|
AStart: TcxTreeListNode; AExpandedOnly, AForward: Boolean;
|
|
AFilter: TcxTreeListFindFunc): TcxTreeListNode;
|
|
begin
|
|
Result := cxFind(Self, AData, AStart, AExpandedOnly, AForward, AFilter);
|
|
end;
|
|
|
|
type
|
|
PFindTextInfo = ^TFindTextInfo;
|
|
TFindTextInfo = record
|
|
Text: string;
|
|
Column: TcxTreeListColumn;
|
|
end;
|
|
|
|
function FindTextFilter(ANode: TcxTreeListNode; AData: Pointer): Boolean;
|
|
begin
|
|
with PFindTextInfo(AData)^ do
|
|
Result := AnsiStrPos(PChar(ANode.Texts[Column.ItemIndex]), PChar(Text)) <> nil;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.FindNodeByText(const AText: string;
|
|
AColumn: TcxTreeListColumn; AStartNode: TcxTreeListNode = nil;
|
|
AExpandedOnly: Boolean = False; AForward: Boolean = True): TcxTreeListNode;
|
|
var
|
|
AFindInfo: TFindTextInfo;
|
|
begin
|
|
AFindInfo.Text := AText;
|
|
AFindInfo.Column := AColumn;
|
|
Result := Find(@AFindInfo, AStartNode, AExpandedOnly, AForward, FindTextFilter)
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetFocusedNode(
|
|
Value: TcxTreeListNode; AShift: TShiftState);
|
|
var
|
|
ARecordIndex: Integer;
|
|
begin
|
|
ARecordIndex := cxInvalidIndex;
|
|
if (Value <> nil) and Value.IsVisible then
|
|
ARecordIndex := Value.RecordIndex
|
|
else
|
|
if Value <> nil then Exit;
|
|
if ARecordIndex = cxInvalidIndex then
|
|
DataController.FocusedRecordIndex := cxInvalidIndex
|
|
else
|
|
begin
|
|
if OptionsBehavior.AlwaysShowEditor then
|
|
Controller.SetFocusedRecordItem(ARecordIndex, FocusedColumn)
|
|
else
|
|
Controller.FocusedRecordIndex := ARecordIndex;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetColumnSortOrder(AColumn: TcxTreeListColumn;
|
|
ASortOrder: TcxDataSortOrder; AShift: TShiftState);
|
|
begin
|
|
Controller.DoChangeColumnSortOrder(AColumn, ASortOrder, AShift);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SelectAll;
|
|
begin
|
|
if not OptionsSelection.MultiSelect or (Nodes.Count = 0) then Exit;
|
|
BeginUpdateSelection;
|
|
try
|
|
DoSelectAll;
|
|
finally
|
|
EndUpdateSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CancelEdit;
|
|
begin
|
|
Controller.EditingController.HideEdit(False);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.HideEdit;
|
|
begin
|
|
Controller.EditingController.HideEdit(True);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Select(Node: TcxTreeListNode;
|
|
ShiftState: TShiftState = []);
|
|
begin
|
|
Controller.Select(Node, ShiftState);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Select(const ANodes: array of TcxTreeListNode);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
BeginUpdateSelection;
|
|
try
|
|
ClearSelection;
|
|
for I := Low(ANodes) to High(ANodes) do
|
|
ANodes[I].Selected := True;
|
|
finally
|
|
EndUpdateSelection;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Select(ANodes: TList);
|
|
begin
|
|
BeginUpdateSelection;
|
|
if Nodes <> nil then
|
|
try
|
|
ClearSelection;
|
|
FSelection.Count := ANodes.Count;
|
|
if FSelection.Count > 0 then
|
|
System.Move(ANodes.List^, FSelection.List^[0], SizeOf(Integer) * FSelection.Count);
|
|
finally
|
|
EndUpdateSelection;
|
|
end
|
|
else
|
|
CancelUpdateSelection;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Deselect(Node: TcxTreeListNode);
|
|
begin
|
|
Node.Selected := False;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ShowEdit;
|
|
begin
|
|
if not OptionsData.Editing then Exit;
|
|
DataController.Edit;
|
|
Controller.EditingController.ShowEdit();
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ShowEditByKey(AKey: Char);
|
|
begin
|
|
BeforeShowingEdit;
|
|
with Controller do
|
|
EditingController.ShowEdit(FocusedItem, AKey);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ShowEditByMouse(X, Y: Integer; AShift: TShiftState);
|
|
begin
|
|
BeforeShowingEdit;
|
|
with Controller do
|
|
EditingController.ShowEdit(FocusedItem, AShift, X, Y);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreFromIniFile(const AStorageName: string;
|
|
AChildrenCreating: Boolean = False; AChildrenDeleting: Boolean = False);
|
|
var
|
|
AStorage: TcxStorage;
|
|
begin
|
|
AStorage := TcxStorage.Create(AStorageName);
|
|
try
|
|
IsRestore := True;
|
|
AStorage.NamePrefix := Name;
|
|
if AChildrenCreating then
|
|
AStorage.Modes := [smChildrenCreating];
|
|
if AChildrenDeleting then
|
|
AStorage.Modes := AStorage.Modes + [smChildrenDeleting];
|
|
BeginUpdate;
|
|
try
|
|
AStorage.UseInterfaceOnly := True;
|
|
AStorage.RestoreFromIni(Self);
|
|
finally
|
|
IsRestore := False;
|
|
EndUpdate;
|
|
end;
|
|
finally
|
|
AStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreFromRegistry(const AStorageName: string;
|
|
AChildrenCreating: Boolean = False; AChildrenDeleting: Boolean = False);
|
|
var
|
|
AStorage: TcxStorage;
|
|
begin
|
|
AStorage := TcxStorage.Create(AStorageName);
|
|
try
|
|
IsRestore := True;
|
|
AStorage.UseInterfaceOnly := True;
|
|
AStorage.NamePrefix := Name;
|
|
if AChildrenCreating then
|
|
AStorage.Modes := [smChildrenCreating];
|
|
if AChildrenDeleting then
|
|
AStorage.Modes := AStorage.Modes + [smChildrenDeleting];
|
|
BeginUpdate;
|
|
try
|
|
AStorage.RestoreFromRegistry(Self);
|
|
finally
|
|
IsRestore := False;
|
|
EndUpdate;
|
|
end;
|
|
finally
|
|
AStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreFromStream(AStream: TStream;
|
|
AChildrenCreating: Boolean = False; AChildrenDeleting: Boolean = False);
|
|
var
|
|
AStorage: TcxStorage;
|
|
begin
|
|
AStorage := TcxStorage.Create(AStream);
|
|
try
|
|
IsRestore := True;
|
|
AStorage.UseInterfaceOnly := True;
|
|
AStorage.NamePrefix := Name;
|
|
if AChildrenCreating then
|
|
AStorage.Modes := [smChildrenCreating];
|
|
if AChildrenDeleting then
|
|
AStorage.Modes := AStorage.Modes + [smChildrenDeleting];
|
|
BeginUpdate;
|
|
try
|
|
AStorage.RestoreFromStream(Self);
|
|
finally
|
|
IsRestore := False;
|
|
EndUpdate;
|
|
end;
|
|
finally
|
|
AStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.StoreToIniFile(AStorageName: string;
|
|
AReCreate: Boolean = True);
|
|
var
|
|
AStorage: TcxStorage;
|
|
begin
|
|
AStorage := TcxStorage.Create(AStorageName);
|
|
try
|
|
AStorage.UseInterfaceOnly := True;
|
|
AStorage.NamePrefix := Name;
|
|
AStorage.ReCreate := AReCreate;
|
|
AStorage.StoreToIni(Self);
|
|
finally
|
|
AStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.StoreToRegistry(AStorageName: string;
|
|
AReCreate: Boolean = True);
|
|
var
|
|
AStorage: TcxStorage;
|
|
begin
|
|
AStorage := TcxStorage.Create(AStorageName);
|
|
try
|
|
AStorage.UseInterfaceOnly := True;
|
|
AStorage.NamePrefix := Name;
|
|
AStorage.ReCreate := AReCreate;
|
|
AStorage.StoreToRegistry(Self);
|
|
finally
|
|
AStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.StoreToStream(AStream: TStream);
|
|
var
|
|
AStorage: TcxStorage;
|
|
begin
|
|
AStorage := TcxStorage.Create(AStream);
|
|
try
|
|
AStorage.UseInterfaceOnly := True;
|
|
AStorage.NamePrefix := Name;
|
|
AStorage.StoreToStream(Self);
|
|
finally
|
|
AStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CellRect(
|
|
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TRect;
|
|
var
|
|
AInfo: TcxTreeListEditCellViewInfo;
|
|
begin
|
|
AInfo := Controller.GetCellFromViewInfoEx(AColumn, ANode);
|
|
if AInfo <> nil then
|
|
Result := AInfo.ClipRect
|
|
else
|
|
Result := cxInvalidRect;
|
|
end;
|
|
|
|
// searching
|
|
function TcxCustomTreeListControl.FindNext(AForward: Boolean): Boolean;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
const
|
|
ALocateKeys: array[Boolean] of Word = (VK_UP, VK_DOWN);
|
|
begin
|
|
if Searching then
|
|
begin
|
|
ANode := FocusedNode;
|
|
Controller.IncSearchKeyDown(ALocateKeys[AForward], [ssCtrl]);
|
|
end
|
|
else
|
|
ANode := nil;
|
|
Result := ANode <> FocusedNode;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CancelSearching;
|
|
begin
|
|
Controller.CancelIncSearching;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetEditRect(
|
|
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TRect;
|
|
var
|
|
AInfo: TcxTreeListEditCellViewInfo;
|
|
begin
|
|
AInfo := Controller.GetCellFromViewInfoEx(AColumn, ANode);
|
|
if AInfo <> nil then
|
|
Result := AInfo.EditRect
|
|
else
|
|
Result := cxInvalidRect;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetNodeAt(
|
|
X, Y: Integer): TcxTreeListNode;
|
|
begin
|
|
HitTest.ReCalculate(cxPoint(X, Y));
|
|
if HitTest.HitAtNode then
|
|
Result := HitTest.HitNode
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CopyAllToClipboard;
|
|
begin
|
|
DoWriteToClipboard(False);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CopySelectedToClipboard;
|
|
begin
|
|
DoWriteToClipboard(True);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreColumnsDefaults;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].RestoreDefaults;
|
|
RestoreColumnsWidths;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreColumnsWidths;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].RestoreDefaults;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Subselect(Node: TcxTreeListNode);
|
|
begin
|
|
if not CanMultiSelect then
|
|
cxTreeListError(scxStr(@scxMultiSelectRequired))
|
|
else
|
|
Node.Selected := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ClearSelection(KeepPrimary: Boolean = False);
|
|
begin
|
|
Controller.CancelSelection(KeepPrimary)
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ClearSorting;
|
|
begin
|
|
Sorted := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.ColumnByName(
|
|
const AName: string): TcxTreeListColumn;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
for I := 0 to ColumnCount - 1 do
|
|
if CompareText(Columns[I].Name, AName) = 0 then
|
|
begin
|
|
Result := Columns[I];
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSelections(AList: TList): TcxTreeListNode;
|
|
begin
|
|
AList.Clear;
|
|
if IsMultiSelect then
|
|
begin
|
|
AList.Count := FSelection.Count;
|
|
if FSelection.Count > 0 then
|
|
Move(FSelection.List^, AList.List^, FSelection.Count * SizeOf(Integer));
|
|
end
|
|
else
|
|
AList.Add(FocusedNode);
|
|
Result := FocusedNode;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoBOF;
|
|
begin
|
|
FocusedNode := Nodes.Root.GetFirstChild;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoEOF;
|
|
begin
|
|
FocusedNode := cxGetLatest(Nodes.Root.GetLastChild);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoNext;
|
|
begin
|
|
if not IsEOF and (FocusedNode <> nil) then
|
|
FocusedNode := FocusedNode.GetNextVisible;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoNextPage;
|
|
begin
|
|
Controller.DoNextPage(True, []);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoPrev;
|
|
begin
|
|
if not IsBOF and (FocusedNode <> nil) then
|
|
FocusedNode := FocusedNode.GetPrevVisible;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoPrevPage;
|
|
begin
|
|
Controller.DoNextPage(False, []);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsBOF: Boolean;
|
|
begin
|
|
Result := (FocusedNode <> nil) and (FocusedNode.GetPrevVisible = nil);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsEOF: Boolean;
|
|
begin
|
|
Result := (FocusedNode <> nil) and (FocusedNode.GetNextVisible = nil);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.AfterLayoutChanged;
|
|
begin
|
|
with ViewInfo.NodesViewInfo do
|
|
try
|
|
if FNeedSynchronize then
|
|
begin
|
|
SynchronizeTopNode;
|
|
FNeedSynchronize := False;
|
|
end;
|
|
finally
|
|
if IsNeedSortPost then DoSortNodes;
|
|
inherited AfterLayoutChanged;
|
|
DoLayoutChangedEvent;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.BeforeUpdate;
|
|
begin
|
|
DoValidateDeletedNodes;
|
|
if IsLocked then Exit;
|
|
PostUpdateFocusedRecord;
|
|
RestoreTopPos;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CheckCreateDesignSelectionHelper;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ControlUpdateData(
|
|
AInfo: TcxUpdateControlInfo);
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
if AInfo is TcxUpdateRecordInfo then
|
|
CancelSearching;
|
|
if AInfo is TcxDataChangedInfo then
|
|
begin
|
|
with TcxDataChangedInfo(AInfo) do
|
|
begin
|
|
if (Kind in [dcField, dcRecord]) and not IsEditing then
|
|
begin
|
|
ANode := Nodes.Items[RecordIndex];
|
|
if Kind = dcField then
|
|
UpdateColumn(ANode, Columns[ItemIndex])
|
|
else
|
|
UpdateNode(ANode);
|
|
AInfo := nil;
|
|
end;
|
|
end;
|
|
end;
|
|
inherited ControlUpdateData(AInfo);
|
|
if not IsLocked then
|
|
begin
|
|
ViewInfo.NodesViewInfo.UpdateData;
|
|
ViewInfo.UpdateFootersViewInfo;
|
|
end;
|
|
RefreshNavigatorButtons;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.UpdateColumn(
|
|
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn);
|
|
begin
|
|
UpdateNode(ANode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.UpdateNode(ANode: TcxTreeListNode);
|
|
var
|
|
AViewInfo: TcxTreeListNodeViewInfo;
|
|
begin
|
|
if ViewInfo.NodesViewInfo.FindNodeViewInfo(ANode, AViewInfo) then
|
|
begin
|
|
AViewInfo.Update(True);
|
|
if Sorted then
|
|
begin
|
|
DoSorting;
|
|
try
|
|
ANode.Parent.AlphaSort(False);
|
|
if ANode.Focused then ANode.MakeVisible;
|
|
finally
|
|
DoOnAfterSorting;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CreateSubClasses;
|
|
begin
|
|
inherited CreateSubClasses;
|
|
FNavigatorNotifier := TcxNavigatorControlNotifier.Create;
|
|
FSortedColumns := TList.Create;
|
|
FDesigners := TList.Create;
|
|
FSelection := TList.Create;
|
|
FOptionsCustomizing := GetOptionsCustomizingClass.Create(Self);
|
|
FOptionsSelection := GetOptionsSelectionClass.Create(Self);
|
|
FNodes := GetNodesClass.Create(Self);
|
|
FPreview := GetPreviewClass.Create(Self);
|
|
FBandsVisibleList := TList.Create;
|
|
FBands := TcxTreeListBands.Create(Self);
|
|
FColumnsVisibleList := TList.Create;
|
|
FSortOrderList := TList.Create;
|
|
FChangeImagesLink := TChangeLink.Create;
|
|
FChangeImagesLink.OnChange := OnChangeImages;
|
|
FChangeStateImagesLink := TChangeLink.Create;
|
|
FChangeStateImagesLink.OnChange := OnChangeImages;
|
|
FCustomizing := GetTreeListCustomizingClass.Create(Self);
|
|
TcxDataControllerAccess(DataController).OnRecordChanged := DoRecordChanged;
|
|
TcxDataControllerAccess(DataController).OnDataChanged := DoDataChangedEvent;
|
|
FDelayTimer := TTimer.Create(Self);
|
|
FDelayTimer.Enabled := False;
|
|
FDelayTimer.Interval := 0;
|
|
FDelayTimer.OnTimer := DoChangedTimer;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DataChanged;
|
|
begin
|
|
inherited DataChanged;
|
|
DoSortNodes;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DataLayoutChanged;
|
|
begin
|
|
inherited DataLayoutChanged;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DestroySubClasses;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
UpdateDesignerForms;
|
|
BeginUpdate;
|
|
try
|
|
for I := 0 to FSortOrderList.Count - 1 do
|
|
Dispose(PcxDataSortInfo(FSortOrderList.List^[I]));
|
|
FreeAndNil(FNavigatorNotifier);
|
|
FreeAndNil(FNodes);
|
|
FreeAndNil(FColumnsVisibleList);
|
|
FreeAndNil(FBandsVisibleList);
|
|
FreeAndNil(FSortOrderList);
|
|
FreeAndNil(FAutoWidthController);
|
|
FreeAndNil(FPreview);
|
|
DeleteAllColumns;
|
|
FreeAndNil(FBands);
|
|
FreeAndNil(FOptionsCustomizing);
|
|
FreeAndNil(FOptionsSelection);
|
|
FreeAndNil(FChangeImagesLink);
|
|
FreeAndNil(FChangeStateImagesLink);
|
|
FreeAndNil(FCustomizing);
|
|
FreeAndNil(FSortedColumns);
|
|
finally
|
|
FreeAndNil(FSelection);
|
|
FreeAndNil(FDesigners);
|
|
FOptionsCustomizing.Free;
|
|
inherited DestroySubClasses;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoLayoutChanged;
|
|
begin
|
|
Bands.RefreshBandStates;
|
|
Bands.Changed;
|
|
FHeaderLineCount := 0;
|
|
PostUpdateFocusedRecord;
|
|
Controller.HotTrackNode := nil;
|
|
RestoreCursor;
|
|
ViewInfo.NodesViewInfo.CancelUpdatePost;
|
|
RefreshVisibleIndexes;
|
|
FMaxIndentWidth := LookAndFeelPainter.SmallExpandButtonSize +
|
|
cxTreeListIndentOffsetSize;
|
|
if Images <> nil then
|
|
cxSetMax(FMaxIndentWidth, Images.Width + cxTreeListIndentOffsetSize div 2);
|
|
if StateImages <> nil then
|
|
cxSetMax(FMaxIndentWidth, StateImages.Width + cxTreeListIndentOffsetSize div 2);
|
|
FLevelIndentWidth := FMaxIndentWidth;
|
|
BeforeCalculate;
|
|
Nodes.CalculateInfo(False);
|
|
RealignBands;
|
|
AssignLeftMostWidths;
|
|
inherited DoLayoutChanged;
|
|
CheckFocusedItem;
|
|
UpdateDesignerForms;
|
|
Controller.ForceFocusedRecord := -1;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.InitScrollBarsParameters;
|
|
begin
|
|
if IsLocked then Exit;
|
|
with ViewInfo do
|
|
begin
|
|
SetScrollBarInfo(sbHorizontal, 0, HorzScrollSize, HorzScrollInc,
|
|
cxRectWidth(ClientBounds), HorzScrollPos, True, True);
|
|
with Self.Nodes do
|
|
SetScrollBarInfo(sbVertical, 0, VisibleCount - 1, 1, Self.VisibleCount,
|
|
TopVisibleIndex, VisibleCount > Self.VisibleCount{) and (Self.VisibleCount > 0)}, True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.LookAndFeelChanged(
|
|
Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);
|
|
begin
|
|
HideEdit;
|
|
ViewInfo.NodesViewInfo.Clear;
|
|
inherited LookAndFeelChanged(Sender, AChangedValues);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ReadState(Reader: TReader);
|
|
begin
|
|
SaveColumnsParams;
|
|
inherited ReadState(Reader);
|
|
AssignColumnsParams;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Updated;
|
|
begin
|
|
inherited Updated;
|
|
BeginUpdate;
|
|
try
|
|
AssignColumnsParams;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Updating;
|
|
begin
|
|
SaveColumnsParams;
|
|
inherited Updating;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.AssignColumnsParams;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].Position.Load;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SaveColumnsParams;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].Position.Save;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DragDropImageDisplayRect: TRect;
|
|
begin
|
|
with GetDragDropViewParams do
|
|
begin
|
|
Result := inherited DragDropImageDisplayRect;
|
|
Result.Bottom := cxTextHeight(Font);
|
|
Result.Right := VisibleColumns[0].DisplayWidth;
|
|
Result := cxRectOffset(Result, [ScreenToClient(GetMouseCursorPos),
|
|
cxTreeListDragDropTextAreaOffset]);
|
|
Result := cxRectInflate(Result, cxTextOffset, cxTextOffset);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DrawDragDropImage(
|
|
ADragBitmap: TBitmap; ACanvas: TcxCanvas);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
cxApplyViewParams(ACanvas, GetDragDropViewParams);
|
|
R := Rect(0, 0, ADragBitmap.Width, ADragBitmap.Height);
|
|
ACanvas.FillRect(R);
|
|
ACanvas.FrameRect(R, clBlack, 1, cxBordersAll);
|
|
ACanvas.Brush.Style := bsClear;
|
|
ACanvas.DrawTexT(GetDragDropText, cxTextRect(R),
|
|
cxAlignLeft or cxAlignVCenter or cxSingleLine);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetDragDropText: string;
|
|
begin
|
|
Result := FDragNode.Texts[VisibleColumns[0].ItemIndex];
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetDragDropViewParams: TcxViewParams;
|
|
begin
|
|
Styles.DoGetContentParams(FDragNode, VisibleColumns[0], Result);
|
|
with Styles.GetSelectionParams do
|
|
begin
|
|
Result.Color := Color;
|
|
if Styles.SelectionFontAssigned then
|
|
Result.Font := Font;
|
|
Result.TextColor := TextColor;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetImageListHeight(
|
|
AImageList: TCustomImageList): Integer;
|
|
begin
|
|
Result := AImageList.Height;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetDragObjectClass: TDragControlObjectClass;
|
|
begin
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.StartDrag(DragObject: TDragObject): Boolean;
|
|
begin
|
|
Result := DragNode <> nil;
|
|
{ HitTest.HitPoint := ScreenToClient(GetMouseCursorPos);
|
|
with HitTest do
|
|
Result := HitAtNode and HitNode.Selected and not HitAtIndent;}
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GetStoredChildren(AChildren: TStringList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
AChildren.AddObject('', Bands);
|
|
for I := 0 to ColumnCount - 1 do
|
|
AChildren.AddObject('', Columns[I]);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetStoredObjectName: string;
|
|
begin
|
|
Result := Name;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetStoredObjectProperties(
|
|
AProperties: TStrings): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GetStoredPropertyValue(
|
|
const AName: string; var AValue: Variant);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreTopPos;
|
|
begin
|
|
if FTopPos <> -1 then
|
|
begin
|
|
Nodes.CalculateInfo(False);
|
|
Nodes.TopIndex := 0;
|
|
Nodes.TopNode := Nodes.Root.FFirst;
|
|
Nodes.TopNode := Nodes.GetVisibleNode(FTopPos);
|
|
Nodes.TopIndex := FTopPos;
|
|
FTopPos := -1;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.StoreTopPos;
|
|
begin
|
|
FTopPos := Nodes.TopIndex;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetStoredPropertyValue(
|
|
const AName: string; const AValue: Variant);
|
|
begin
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.StoredCreateChild(
|
|
const AObjectName, AClassName: string): TObject;
|
|
begin
|
|
if AClassName = GetTreeListColumnClass.ClassName then
|
|
begin
|
|
Result := CreateColumn;
|
|
TcxTreeListColumn(Result).Name := AObjectName;
|
|
end
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.StoredDeleteChild(
|
|
const AObjectName: string; AObject: TObject);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GetChildren(
|
|
Proc: TGetChildProc; Root: TComponent);
|
|
|
|
procedure DoStore(AColumn: TcxTreeListColumn);
|
|
begin
|
|
if AColumn.Owner = Root then
|
|
Proc(AColumn);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited GetChildren(Proc, Root);
|
|
RefreshVisibleIndexes;
|
|
for I := 0 to ColumnCount - 1 do DoStore(Columns[I]);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsUpdating: Boolean;
|
|
begin
|
|
Result := csUpdating in ComponentState;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
if FocusedNode <> nil then
|
|
FocusedNode.MakeVisible;
|
|
DataChanged;
|
|
RestoreCursor;
|
|
RealignBands;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Modified;
|
|
begin
|
|
if HandleAllocated then
|
|
inherited Modified;
|
|
FDefaultLayout := False;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Notification(
|
|
AComponent: TComponent; Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if Operation = opRemove then
|
|
begin
|
|
if AComponent = Images then Images := nil;
|
|
if AComponent = StateImages then StateImages := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetName(const NewName: TComponentName);
|
|
begin
|
|
inherited SetName(NewName);
|
|
UpdateDesignerForms;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.AssignColumnWidths;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
VisibleBands[I].AssignColumnWidths;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.AssignLeftMostWidths;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if CanAddIndentWidth(FContentIndentWidth) then
|
|
begin
|
|
for I := 0 to VisibleColumnCount - 1 do
|
|
if VisibleColumns[I].IsLeftMost then
|
|
VisibleColumns[I].FWidth := VisibleColumns[I].DisplayWidth;
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
with VisibleBands[I] do
|
|
if IsLeftMost then
|
|
begin
|
|
FCalculatedWidth := DisplayWidth;
|
|
if FWidth <> 0 then
|
|
FWidth := FCalculatedWidth;
|
|
RealignColumns;
|
|
end;
|
|
FContentIndentWidth := 0;
|
|
RealignBands;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.BoundsChanged;
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.AddNode(ANode, ARelative: TcxTreeListNode;
|
|
AData: Pointer; AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode;
|
|
begin
|
|
Result := Nodes.InternalAddNode(ANode, ARelative, AttachMode);
|
|
Result.FData := AData;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.BeforeAddNode(
|
|
ANewNode, ANewParent: TcxTreeListNode; AMode: TcxTreeListNodeAddMode);
|
|
begin
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanAddIndentWidth(
|
|
const AIndentWidth: Integer): Boolean;
|
|
begin
|
|
Result := not OptionsBehavior.AutomateLeftMostIndent and
|
|
(AIndentWidth <> 0) and not OptionsView.ColumnAutoWidth;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanColumnVisible(
|
|
AColumn: TcxTreeListColumn): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanMultiSelect: Boolean;
|
|
begin
|
|
Result := OptionsSelection.MultiSelect;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.BeforeCalculate;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.BeforeShowingEdit;
|
|
begin
|
|
with Controller do
|
|
SetFocusedRecordItem(FocusedRecordIndex, FocusedItem);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CalculateLeftMostIndentWidth;
|
|
begin
|
|
FContentIndentWidth := 0;
|
|
if (Nodes.VisibleCount > 0) and (VisibleBandCount > 0) then
|
|
with VisibleBands[0] do
|
|
begin
|
|
FContentIndentWidth := Max(0, GetLevelIndentsWidth(Nodes.MaxLevel, True, nil) +
|
|
BandRows.LeftMostMinWidth - BandRows.LeftMostWidth);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CheckFocusedItem;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
ARecordIndex: Integer;
|
|
AItem: TcxTreeListColumn;
|
|
begin
|
|
if (ChangesCount <> 1) or (Controller.FocusedRecordIndex = cxInvalidIndex) then Exit;
|
|
ANode := FocusedNode;
|
|
if ANode = nil then
|
|
ANode := Nodes.Root.GetFirstChild;
|
|
if (ANode <> nil) then
|
|
while (ANode.FParent <> nil) and not ANode.IsVisible do ANode := ANode.FParent;
|
|
if ANode <> nil then
|
|
ARecordIndex := ANode.RecordIndex
|
|
else
|
|
ARecordIndex := cxInvalidIndex;
|
|
AItem := FocusedColumn;
|
|
if OptionsSelection.CellSelect and (VisibleColumnCount > 0) and
|
|
(((AItem = nil) or AItem.IsHidden)) then
|
|
begin
|
|
if DoIsGroupNode(ANode) and (OptionsView.CategorizedColumn <> nil) then
|
|
AItem := OptionsView.CategorizedColumn
|
|
else
|
|
AItem := VisibleColumns[0];
|
|
end;
|
|
with Controller do
|
|
if (AItem <> FocusedItem) or (ARecordIndex <> FocusedRecordIndex) and not IsDragMode then
|
|
Controller.SetFocusedRecordItem(ARecordIndex, AItem);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ColumnSortOrderChanged(
|
|
AColumn: TcxTreeListColumn);
|
|
begin
|
|
if AColumn.GetRealSortOrder = soNone then
|
|
FSortedColumns.Remove(AColumn)
|
|
else
|
|
if FSortedColumns.IndexOf(AColumn) = cxInvalidIndex then
|
|
FSortedColumns.Add(AColumn);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoAssignNodes(Source: TcxTreeListNodes);
|
|
begin
|
|
// todo: do nothing
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoClear;
|
|
begin
|
|
Nodes.Clear;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoDeleteSelection;
|
|
var
|
|
AList: TList;
|
|
begin
|
|
AList := GetSelectionsEx;
|
|
BeginUpdate;
|
|
try
|
|
DeleteSelectionList(AList);
|
|
finally
|
|
FreeAndNil(AList);
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.AddToDelitionList(ANode: TcxTreeListNode);
|
|
begin
|
|
FDeletedNodes.Add(Pointer(ANode.RecordIndex));
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoRemoveNode(ANode: TcxTreeListNode);
|
|
begin
|
|
if not SafeDelete and cxInRange(ANode.RecordIndex, 0, FNodesList.Count - 1) then
|
|
begin
|
|
FNodesList.List^[ANode.RecordIndex] := nil;
|
|
AddToDelitionList(ANode);
|
|
end;
|
|
if HitTest.FHitNode = ANode then
|
|
HitTest.FHitNode := nil;
|
|
FSelection.Remove(ANode);
|
|
if FCheckedList <> nil then
|
|
FCheckedList.Remove(ANode);
|
|
if LockUpdate = 0 then
|
|
DoValidateDeletedNodes;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoCheckDeletedNode(ANode: TcxTreeListNode);
|
|
|
|
function Validate(var ACheckedNode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := ACheckedNode = ANode;
|
|
if Result then
|
|
ACheckedNode := nil;
|
|
end;
|
|
|
|
begin
|
|
if Validate(Controller.IncSearchNode) then
|
|
Controller.CancelIncSearching;
|
|
Validate(Controller.HotTrackNode);
|
|
Validate(Controller.SelectionAnchorNode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoDeleteNode(ANode: TcxTreeListNode);
|
|
begin
|
|
if IsDestroying or SafeDelete then Exit;
|
|
UpdateFocusedRecordPost;
|
|
DoRemoveNode(ANode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoInplaceEditContainerItemRemoved(
|
|
AItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
TcxTreeListColumn(AItem).OwnerBand := nil;
|
|
inherited DoInplaceEditContainerItemRemoved(AItem);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoInternalMoveTo(AttachNode: TcxTreeListNode;
|
|
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean);
|
|
|
|
function CheckNodesList: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := 0;
|
|
while I < ANodes.Count do
|
|
begin
|
|
if TcxTreeListNode(ANodes[I]).CanMove(AttachNode, AttachMode) then
|
|
Inc(I)
|
|
else
|
|
ANodes.Delete(I);
|
|
end;
|
|
Result := ANodes.Count > 0;
|
|
end;
|
|
|
|
var
|
|
IsDone: Boolean;
|
|
begin
|
|
IsDone := False;
|
|
if IsCopy and (AttachMode = tlamInsert) then
|
|
AttachNode := AttachNode.Parent;
|
|
if not CheckNodesList then Exit;
|
|
DoOnMoveTo(AttachNode, AttachMode, ANodes, IsCopy, IsDone);
|
|
if not IsDone then
|
|
begin
|
|
Freeze;
|
|
try
|
|
DoMoveTo(AttachNode, AttachMode, ANodes, IsCopy);
|
|
finally
|
|
UnFreeze;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoMoveTo(AttachNode: TcxTreeListNode;
|
|
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with ANodes do
|
|
begin
|
|
for I := Count - 1 downto 0 do
|
|
begin
|
|
if IsCopy then
|
|
InternalCopy(TcxTreeListNode(List^[I]), AttachNode)
|
|
else
|
|
InternalMove(TcxTreeListNode(List^[I]), AttachNode, AttachMode);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnAfterSorting;
|
|
begin
|
|
if Assigned(FOnAfterSorting) then FOnAfterSorting(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnBandSizeChanged(ABand: TcxTreeListBand);
|
|
begin
|
|
if Assigned(FOnBandSizeChanged) then
|
|
FOnBandSizeChanged(Self, ABand);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnColumnSizeChanged(
|
|
AColumn: TcxTreeListColumn);
|
|
begin
|
|
if Assigned(FOnColumnSizeChanged) then
|
|
FOnColumnSizeChanged(Self, AColumn);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnCollapsed(ANode: TcxTreeListNode);
|
|
begin
|
|
if Assigned(FOnCollapsed) then
|
|
FOnCollapsed(Self, ANode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnCollapsing(
|
|
ANode: TcxTreeListNode; var Allow: Boolean);
|
|
begin
|
|
if Assigned(FOnCollapsing) then
|
|
FOnCollapsing(Self, ANode, Allow);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnCompare(
|
|
ANode1, ANode2: TcxTreeListNode; var ACompare: Integer);
|
|
begin
|
|
ACompare := 1;
|
|
if Assigned(FOnCompare) then
|
|
FOnCompare(Self, ANode1, ANode2, ACompare);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnCustomizationVisibleChanged;
|
|
begin
|
|
if Assigned(FOnCustomizationVisibleChanged) then
|
|
FOnCustomizationVisibleChanged(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnDeletion(ANode: TcxTreeListNode);
|
|
begin
|
|
if Assigned(FOnDeletion) then
|
|
FOnDeletion(Self, ANode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnExpanded(ANode: TcxTreeListNode);
|
|
begin
|
|
if Assigned(FOnExpanded) then
|
|
FOnExpanded(Self, ANode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnExpanding(
|
|
ANode: TcxTreeListNode; var Allow: Boolean);
|
|
begin
|
|
if Assigned(FOnExpanding) then
|
|
FOnExpanding(Self, ANode, Allow);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnGetNodeHeight(
|
|
ANode: TcxTreeListNode; var AHeight: Integer);
|
|
begin
|
|
if Assigned(FOnGetNodeHeight) then
|
|
FOnGetNodeHeight(Self, ANode, AHeight)
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnHotTrackNode(
|
|
ANode: TcxTreeListNode; AShift: TShiftState; var ACursor: TCursor);
|
|
begin
|
|
ACursor := Cursor;
|
|
if Assigned(FOnHotTrackNode) then
|
|
FOnHotTrackNode(Self, ANode, AShift, ACursor);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnMoveTo(AttachNode: TcxTreeListNode;
|
|
AttachMode: TcxTreeListNodeAttachMode; Nodes: TList; var IsCopy, Done: Boolean);
|
|
begin
|
|
if Assigned(FOnMoveTo) then
|
|
FOnMoveTo(Self, AttachNode, AttachMode, Nodes, IsCopy, Done);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnIsGroupNode(
|
|
ANode: TcxTreeListNode; var IsGroup: Boolean);
|
|
begin
|
|
if Assigned(FOnIsGroupNode) then
|
|
FOnIsGroupNode(Self, ANode, IsGroup);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoOnTopRecordIndexChanged;
|
|
begin
|
|
if Assigned(FOnTopRecordIndexChanged) then
|
|
FOnTopRecordIndexChanged(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoStartDrag(var DragObject: TDragObject);
|
|
begin
|
|
if DragMode = dmManual then
|
|
DragPos := ScreenToClient(GetMouseCursorPos);
|
|
if HitTest.HitNode = nil then
|
|
HitTest.FHitNode := FDragNode;
|
|
inherited DoStartDrag(DragObject);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoWriteHeaderToText: string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := '';
|
|
for I := 0 to VisibleColumnCount - 1 do
|
|
begin
|
|
if I > 0 then
|
|
Result := Result + cxColumnTextSeparator;
|
|
Result := Result + VisibleColumns[I].Caption.Text;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoWriteNodeToText(ANode: TcxTreeListNode): string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := '';
|
|
for I := 0 to VisibleColumnCount - 1 do
|
|
begin
|
|
if Result <> '' then
|
|
Result := Result + cxColumnTextSeparator;
|
|
Result := Result + VisibleColumns[I].DisplayTexts[ANode.RecordIndex];
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoWriteToClipboard(AOnlySelected: Boolean);
|
|
var
|
|
AText: string;
|
|
begin
|
|
if DoWriteToText(AOnlySelected, AText) then
|
|
ClipBoard.AsText := AText
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoWriteToText(AOnlySelected: Boolean; out AText: string): Boolean;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
ANode := Nodes.Root.GetFirstChild;
|
|
if OptionsView.Headers then
|
|
AText := DoWriteHeaderToText
|
|
else
|
|
AText := '';
|
|
while ANode <> nil do
|
|
begin
|
|
if not AOnlySelected or ANode.Selected then
|
|
AText := AText + cxLineSeparator + DoWriteNodeToText(ANode);
|
|
ANode := ANode.GetNext;
|
|
end;
|
|
Result := AText <> '';
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoUpdateDesignerForms;
|
|
begin
|
|
if FNeedUpdateDesigners and (IsLocked and not IsDestroying) then Exit;
|
|
FNeedUpdateDesigners := True;
|
|
if IsDestroying or not IsLocked then
|
|
UpdateDesignerForms;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoDeleteRecords;
|
|
begin
|
|
if FDeletedNodes.Count <> 0 then
|
|
begin
|
|
DataController.Cancel;
|
|
TcxDataControllerAccess(DataController).DeleteRecords(FDeletedNodes)
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoValidateDeletedNodes;
|
|
var
|
|
I, ACount: Integer;
|
|
begin
|
|
ACount := FDeletedNodes.Count;
|
|
if ACount = 0 then Exit;
|
|
BeginUpdate;
|
|
try
|
|
FNodesList.Pack;
|
|
FDeletedNodes.Sort(cxIntegerListCompare);
|
|
for I := Integer(FDeletedNodes[0]) to FNodesList.Count - 1 do
|
|
TcxTreeListNode(FNodesList.List^[I]).RecordIndex := I;
|
|
if not FSafeDelete then DoDeleteRecords;
|
|
finally
|
|
FDeletedNodes.Clear;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DeleteSelectionList(AList: TList);
|
|
var
|
|
I: Integer;
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
FCheckedList := AList;
|
|
try
|
|
I := -1;
|
|
while AList.Count > 0 do
|
|
try
|
|
I := AList.Count;
|
|
ANode := TcxTreeListNode(AList.List^[AList.Count - 1]);
|
|
if ANode.Selected then
|
|
ANode.Free;
|
|
finally
|
|
if I = AList.Count then AList.Delete(I - 1);
|
|
I := AList.Count;
|
|
end
|
|
finally
|
|
FCheckedList := nil;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetCountNodeForBestFit: Integer;
|
|
begin
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetImageIndentWidth(
|
|
AType: TcxTreeListImageIndexType): Integer;
|
|
begin
|
|
Result := FMaxIndentWidth;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetIsActive: Boolean;
|
|
begin
|
|
Result := Controller.Focused;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetFixedContentSize: Integer;
|
|
begin
|
|
Result := 0;
|
|
if (Bands.FirstVisible <> nil) and (Bands.FirstVisible.FixedKind = tlbfLeft) then
|
|
Inc(Result, Bands.FirstVisible.DisplayWidth);
|
|
if (Bands.LastVisible <> nil) and (Bands.LastVisible.FixedKind = tlbfRight) then
|
|
Inc(Result, Bands.LastVisible.DisplayWidth);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetLevelIndentCount(
|
|
ALevel: Integer; AWithImages: Boolean; ANode: TcxTreeListNode): Integer;
|
|
begin
|
|
Result := ALevel + Byte(OptionsView.ShowRoot);
|
|
if AWithImages then
|
|
Result := Result + Byte((Images <> nil) and (DoGetNodeImageIndex(ANode, tlitImageIndex) >= 0));
|
|
if (StateImages <> nil) and (DoGetNodeImageIndex(ANode, tlitStateIndex) >= 0) then
|
|
Inc(Result);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetLevelIndentsWidth(ALevel: Integer;
|
|
AWithImages: Boolean; ANode: TcxTreeListNode): Integer;
|
|
begin
|
|
Result := GetLevelIndentCount(ALevel, AWithImages, ANode) * FLevelIndentWidth;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetMaxBandWidth(ABand: TcxTreeListBand): Integer;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
if not OptionsView.ColumnAutoWidth then
|
|
Result := MaxInt
|
|
else
|
|
begin
|
|
Result := cxRectWidth(ClientBounds) -
|
|
FixedBandCount * OptionsView.FixedSeparatorWidth -
|
|
OptionsView.IndicatorWidth * Byte(OptionsView.Indicator);
|
|
J := FBandsVisibleList.IndexOf(ABand);
|
|
if J = FBandsVisibleList.Count - 1 then
|
|
for I := VisibleBandCount - 2 downto 0 do
|
|
Dec(Result, VisibleBands[I].BandRows.ColumnsMinWidth)
|
|
else
|
|
begin
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
if I < J then
|
|
Dec(Result, VisibleBands[I].DisplayWidth)
|
|
else
|
|
if I > J then
|
|
Dec(Result, VisibleBands[I].BandRows.ColumnsMinWidth);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetMouseWheelScrollingKind: TcxMouseWheelScrollingKind;
|
|
begin
|
|
Result := mwskVertical;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetStartNodeForBestFit: TcxTreeListNode;
|
|
begin
|
|
Result := Nodes.Root.GetFirstChild;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.HasImages: Boolean;
|
|
begin
|
|
Result := (StateImages <> nil) or (Images <> nil);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.ImagesIndentWidth: Integer;
|
|
begin
|
|
Result := 0;
|
|
if StateImages <> nil then
|
|
Inc(Result, FLevelIndentWidth);
|
|
if Images <> nil then
|
|
Inc(Result, FLevelIndentWidth);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.InsertNode(IsAppend: Boolean): Boolean;
|
|
var
|
|
ANode, AttachNode: TcxTreeListNode;
|
|
const
|
|
AMode: array[Boolean] of TcxTreeListNodeAttachMode = (tlamAdd, tlamInsert);
|
|
begin
|
|
AttachNode := FocusedNode;
|
|
Result := False;
|
|
if AttachNode <> nil then
|
|
begin
|
|
if IsAppend and (AttachNode.Parent.Parent = nil) then
|
|
AttachNode := nil;
|
|
BeginUpdate;
|
|
try
|
|
ANode := AddNode(nil, AttachNode, nil, AMode[IsAppend]);
|
|
Result := ANode <> nil;
|
|
if Result then ANode.Focused := True;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end
|
|
else
|
|
if IsAppend then
|
|
AddNode(nil, nil, nil, tlamAdd).Focused := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.InternalMove(
|
|
ANode, ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode);
|
|
begin
|
|
if (ANode = nil) or (ADestNode = nil) or ADestNode.HasAsParent(ANode) or
|
|
((ADestNode = ANode.Parent) and (AMode = tlamAddChild)) or (ANode = ADestNode) then Exit;
|
|
Nodes.InternalAddNode(ANode, ADestNode, AMode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.InternalCopy(
|
|
ANode, ADestNode: TcxTreeListNode);
|
|
var
|
|
I: Integer;
|
|
ANewNode: TcxTreeListNode;
|
|
begin
|
|
ANewNode := AddNode(nil, ADestNode, nil, tlamAddChild);
|
|
for I := 0 to ANode.ValueCount - 1 do
|
|
ANewNode.Values[I] := ANode.Values[I];
|
|
ANewNode.FState := ANode.FState;
|
|
ANewNode.Data := ANode.Data;
|
|
ANode := ANode.GetFirstChild;
|
|
while ANode <> nil do
|
|
begin
|
|
InternalCopy(ANode, ANewNode);
|
|
ANode := ANode.FNext;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsMultiSelect: Boolean;
|
|
begin
|
|
Result := OptionsSelection.MultiSelect;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsCancelOperation: Boolean;
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
Result := not SafeDelete and not SkipCancelOperation;
|
|
if not Result then Exit;
|
|
AIndex := DataController.RecordCount;
|
|
DataController.Post;
|
|
Result := DataController.RecordCount <> AIndex;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsSmartLoad: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsNodeInserted(ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := dceInsert in DataController.EditState;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsNodeEdited(ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := dceEdit in DataController.EditState;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.MakeNodeVisible(ANode: TcxTreeListNode);
|
|
var
|
|
AIndex: Integer;
|
|
IsInvalidValid: Boolean;
|
|
begin
|
|
if (ANode <> nil) and (ANode.IsVisible) then
|
|
begin
|
|
IsInvalidValid := Nodes.IsInvalidState and IsLocked;
|
|
AIndex := Nodes.TopIndex;
|
|
Nodes.CalculateInfo(False);
|
|
if not IsInvalidValid {and not IsLocked} then
|
|
ViewInfo.NodesViewInfo.MakeNodeVisible(ANode)
|
|
else
|
|
begin
|
|
Nodes.TopIndex := 0;
|
|
Nodes.TopNode := Nodes.Root.FFirst;
|
|
Nodes.TopNode := Nodes.GetVisibleNode(AIndex);
|
|
Nodes.TopIndex := AIndex;
|
|
ANode.MakeVisible;
|
|
StoreTopPos;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RefreshVisibleIndexes;
|
|
|
|
procedure AddToVisibleList(AColumn: TcxTreeListColumn);
|
|
begin
|
|
if AColumn.Visibility and not AColumn.IsPreview then
|
|
FColumnsVisibleList.Add(AColumn);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FBandsVisibleList.Sort(cxCompareVisibleBands);
|
|
FColumnsVisibleList.Clear;
|
|
with ColumnsList do
|
|
begin
|
|
FColumnsVisibleList.Capacity := Count;
|
|
// todo :// sizing
|
|
// for I := 0 to Bands.Count - 1 do
|
|
// if Bands[I].Visible then Bands[I].RebuildRows;
|
|
for I := 0 to Count - 1 do
|
|
AddToVisibleList(TcxTreeListColumn(List^[I]));
|
|
end;
|
|
FColumnsVisibleList.Sort(cxCompareColumnsPosEx);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreCursor;
|
|
begin
|
|
if FUseGlassCursor = 1 then
|
|
begin
|
|
Dec(FUseGlassCursor);
|
|
Screen.Cursor := FStoredCursor;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreSorting;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetGlassCursor;
|
|
begin
|
|
with TcxTreeListOptionsBehavior(OptionsBehavior) do
|
|
if (FUseGlassCursor > 0) or not ShowHourGlass then Exit;
|
|
FUseGlassCursor := 1;
|
|
if OptionsBehavior.HotTrack and (Controller.HotTrackNode <> nil) then
|
|
FStoredCursor := Controller.PrevCursor
|
|
else
|
|
FStoredCursor := Screen.Cursor;
|
|
Screen.Cursor := crHourGlass;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.SkipFocusedRecordChanged: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.SkipCancelOperation: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SortingStateChanged(
|
|
AColumn: TcxTreeListColumn; AShift: TShiftState);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.OnChangeImages(Sender: TObject);
|
|
begin
|
|
UpdateViewStyles;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SaveDragPos;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RestoreDragPos;
|
|
begin
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.RealBandLineHeight: Integer;
|
|
begin
|
|
Result := FRealBandLineHeight;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ReadData(AStream: TStream);
|
|
var
|
|
ASignature: TcxTreeListDataSignature;
|
|
begin
|
|
AStream.ReadBuffer(ASignature, SizeOf(ASignature));
|
|
with ASignature do
|
|
if (Size <> AStream.Size) then
|
|
cxTreeListError(scxStr(@scxInvalidStreamFormat));
|
|
AStream.Position := SizeOf(ASignature);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RealignBands;
|
|
var
|
|
AAutoWidth: TcxAutoWidthObject;
|
|
I: Integer;
|
|
begin
|
|
CalculateLeftMostIndentWidth;
|
|
Bands.RealignColumns;
|
|
if OptionsView.ColumnAutoWidth then
|
|
begin
|
|
AAutoWidth := TcxAutoWidthObject.Create(VisibleBandCount);
|
|
try
|
|
with OptionsView do
|
|
AAutoWidth.AvailableWidth := cxRectWidth(ClientBounds) - FContentIndentWidth -
|
|
FixedBandCount * FixedSeparatorWidth - IndicatorWidth * Byte(Indicator);
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
VisibleBands[I].InitAutoWidthItem(AAutoWidth.AddItem);
|
|
AAutoWidth.Calculate;
|
|
for I := 0 to VisibleBandCount - 1 do
|
|
VisibleBands[I].FCalculatedWidth := AAutoWidth.Items[I].AutoWidth;
|
|
finally
|
|
AAutoWidth.Free;
|
|
end;
|
|
end;
|
|
Bands.RealignColumns;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.WriteData(AStream: TStream);
|
|
var
|
|
ASignature: TcxTreeListDataSignature;
|
|
begin
|
|
ASignature.Version := cxTreeListVersion;
|
|
ASignature.Size := AStream.Size;
|
|
AStream.Position := 0;
|
|
AStream.WriteBuffer(ASignature, SizeOf(ASignature));
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.SupportsBandColumnEditor: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.SupportsItemsEditor: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.SupportsCreateAllItems: Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetVersion: string;
|
|
begin
|
|
Result := cxTLMajorVersion + '.' + IntToStr(dxBuildNumber);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CreateAllItems;
|
|
begin
|
|
end;
|
|
|
|
// IcxNavigator
|
|
procedure TcxCustomTreeListControl.RefreshNavigatorButtons;
|
|
begin
|
|
if not (IsLoading or IsDestroying) and (FNavigatorNotifier <> nil) then
|
|
FNavigatorNotifier.RefreshNavigatorButtons;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoAction(AButtonIndex: Integer);
|
|
begin
|
|
case AButtonIndex of
|
|
NBDI_FIRST:
|
|
GotoBOF;
|
|
NBDI_PRIORPAGE:
|
|
GotoPrevPage;
|
|
NBDI_PRIOR:
|
|
GotoPrev;
|
|
NBDI_NEXT:
|
|
GotoNext;
|
|
NBDI_NEXTPAGE:
|
|
GotoNextPage;
|
|
NBDI_LAST:
|
|
GotoEOF;
|
|
NBDI_INSERT:
|
|
if FocusedNode <> nil then
|
|
AddNode(nil, FocusedNode, nil, tlamInsert).Focused := True
|
|
else
|
|
AddNode(nil, Nodes.Root, nil, tlamAdd).Focused := True;
|
|
NBDI_APPEND:
|
|
if FocusedNode <> nil then
|
|
AddNode(nil, FocusedNode.Parent, nil, tlamAdd).Focused := True
|
|
else
|
|
AddNode(nil, Nodes.Root, nil, tlamAdd).Focused := True;
|
|
NBDI_DELETE:
|
|
Self.DeleteSelection;
|
|
NBDI_EDIT:
|
|
ShowEdit;
|
|
NBDI_POST:
|
|
begin
|
|
DataController.PostEditingData;
|
|
DataController.Post;
|
|
end;
|
|
NBDI_CANCEL:
|
|
begin
|
|
DataController.Cancel;
|
|
TcxEditingControllerAccess(Controller.EditingController).UpdateEditValue;
|
|
end;
|
|
NBDI_REFRESH:
|
|
DataController.Refresh;
|
|
NBDI_SAVEBOOKMARK:
|
|
SaveBookmark;
|
|
NBDI_GOTOBOOKMARK:
|
|
GotoBookmark;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetNotifier: TcxNavigatorControlNotifier;
|
|
begin
|
|
Result := FNavigatorNotifier;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsActionSupported(AButtonIndex: Integer): Boolean;
|
|
begin
|
|
Result := AButtonIndex in [NBDI_FIRST..NBDI_GOTOBOOKMARK];
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanAppend: Boolean;
|
|
begin
|
|
Result := CanInsert;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanEdit: Boolean;
|
|
begin
|
|
Result := OptionsData.Editing and (HasData or CanInsert) and not IsEditing;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanDelete: Boolean;
|
|
begin
|
|
Result := OptionsData.Deleting and HasData;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CanInsert: Boolean;
|
|
begin
|
|
Result := OptionsData.Inserting and ((FocusedNode <> nil) or not HasData);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.ClearBookmark;
|
|
begin
|
|
DataController.ClearBookmark;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GotoBookmark;
|
|
begin
|
|
DataController.GotoBookmark;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.HasData: Boolean;
|
|
begin
|
|
Result := (VisibleColumnCount > 0) and (Nodes.Count > 0);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsBookmarkAvailable: Boolean;
|
|
begin
|
|
Result := DataController.IsBookmarkAvailable and HasData;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SaveBookmark;
|
|
begin
|
|
DataController.SaveBookmark;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.UseRowIndexForNewRecord: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.Freeze;
|
|
begin
|
|
Inc(FFreezeCount);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsLocked: Boolean;
|
|
begin
|
|
Result := inherited IsLocked or (FFreezeCount <> 0) or
|
|
(csUpdating in ComponentState);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsFreeze: Boolean;
|
|
begin
|
|
Result := FFreezeCount > 0;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.UnFreeze;
|
|
begin
|
|
Dec(FFreezeCount);
|
|
if FFreezeCount = 0 then
|
|
begin
|
|
BeforeUpdate;
|
|
LayoutChanged;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CreateNode: TcxTreeListNode;
|
|
begin
|
|
Result := TcxUnboundTreeListNode.Create(Nodes);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoCanNodeCollapse(
|
|
ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := ANode.HasChildren;
|
|
if Result then
|
|
DoOnCollapsing(ANode, Result);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoCanNodeExpand(
|
|
ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := ANode.HasChildren and not IsCancelOperation;
|
|
if Result then
|
|
DoOnExpanding(ANode, Result);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoCreateNode: TcxTreeListNode;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
DoValidateDeletedNodes;
|
|
Result := CreateNode;
|
|
finally
|
|
NeedSortPost;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoGetNodeImageIndex(
|
|
ANode: TcxTreeListNode; AIndex: TcxTreeListImageIndexType): TImageIndex;
|
|
begin
|
|
LockChanges := True;
|
|
try
|
|
if ANode = nil then
|
|
Result := -1
|
|
else
|
|
begin
|
|
Result := ANode.FImageIndexes[AIndex];
|
|
if (AIndex = tlitSelectedIndex) and (Result = -1) and OptionsView.UseImageIndexForSelected then
|
|
Result := ANode.FImageIndexes[tlitImageIndex];
|
|
if Assigned(OnGetNodeImageIndex) then
|
|
OnGetNodeImageIndex(Self, ANode, AIndex, Result);
|
|
end;
|
|
finally
|
|
LockChanges := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoGetNodeValueCount: Integer;
|
|
begin
|
|
Result := ColumnCount;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoNodeChanged(
|
|
ANode: TcxTreeListNode);
|
|
begin
|
|
LayoutChanged;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoIsGroupNode(
|
|
ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := False;
|
|
if (ANode <> nil) and (OptionsView.PaintStyle = tlpsCategorized) then
|
|
begin
|
|
Result := ANode.HasChildren;
|
|
DoOnIsGroupNode(ANode, Result);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSelectAll;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
ANode := Nodes.Root.FFirst;
|
|
if ANode <> nil then FSelection.Clear;
|
|
FSelection.Capacity := Nodes.VisibleCount + 1;
|
|
while ANode <> nil do
|
|
begin
|
|
if DoCanSelectNode(ANode) then
|
|
FSelection.Add(ANode);
|
|
ANode := ANode.GetNext
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSetNodeExpanded(
|
|
ANode: TcxTreeListNode; AExpanded: Boolean);
|
|
|
|
procedure DoChanging(AAllowFunc: TAllowExpandChangingFunc; AState: Integer);
|
|
begin
|
|
if AAllowFunc then
|
|
begin
|
|
FPostChanged := True;
|
|
ANode.FState := AState;
|
|
if ANode.FCount > 0 then
|
|
ANode.FState := ANode.FState or tlnsHasChildren
|
|
else
|
|
ANode.FState := ANode.FState and not tlnsHasChildren;
|
|
if AExpanded then
|
|
DoOnExpanded(ANode)
|
|
else
|
|
DoOnCollapsed(ANode);
|
|
Nodes.IsInvalidState := True;
|
|
LayoutChanged;
|
|
end;
|
|
end;
|
|
|
|
const
|
|
AExpandedState = tlnsCollapsed or tlnsHasChildren;
|
|
begin
|
|
if IsCancelOperation then Exit;
|
|
StoreTopPos;
|
|
// Controller.EditingController.StopEditShowingTimer;
|
|
FNeedMakeVisible := False;
|
|
if (ANode.Expanded <> AExpanded) and ANode.HasChildren then
|
|
begin
|
|
if AExpanded then
|
|
DoChanging(ANode.CanExpand, ANode.FState and not AExpandedState)
|
|
else
|
|
DoChanging(ANode.CanCollapse, ANode.FState or AExpandedState);
|
|
end;
|
|
FNeedMakeVisible := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSetNodeImageIndex(
|
|
ANode: TcxTreeListNode; AIndex: TcxTreeListImageIndexType; Value: TImageIndex);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSetNodeFocused(
|
|
ANode: TcxTreeListNode; Value: Boolean; Shift: TShiftState = []);
|
|
begin
|
|
if Value then
|
|
FocusedNode := ANode
|
|
else
|
|
if ANode.Focused then FocusedNode := nil;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSorting;
|
|
begin
|
|
if Assigned(FOnSorting) then FOnSorting(Self);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetColumnById(
|
|
AItemIndex: Integer): TcxTreeListColumn;
|
|
begin
|
|
if cxInRange(AItemIndex, 0, ColumnCount - 1) then
|
|
Result := Columns[AItemIndex]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetNodeByID(
|
|
ARecordIndex: Integer): TcxTreeListNode;
|
|
begin
|
|
if cxInRange(ARecordIndex, 0, FNodesList.Count - 1) then
|
|
Result := FNodesList.List^[ARecordIndex]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSelectionsEx: TList;
|
|
begin
|
|
Result := TList.Create;
|
|
GetSelections(Result);
|
|
if (FocusedNode <> nil) and not FocusedNode.Selected then
|
|
Result.Add(FocusedNode);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CancelSortPost;
|
|
begin
|
|
FNeedSortPost := False;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DisableSorting;
|
|
begin
|
|
Inc(FSortLocking);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSortNodes;
|
|
begin
|
|
if (FSortLocking = 0) and not IsDestroying and
|
|
(DataController.RecordCount = FNodesList.Count) then
|
|
begin
|
|
DoSorting;
|
|
try
|
|
CancelSortPost;
|
|
if Sorted then
|
|
try
|
|
RecreateSortOrdersList;
|
|
finally
|
|
Nodes.Root.AlphaSort(True);
|
|
end
|
|
else
|
|
if FNeedRestoreSorting then
|
|
begin
|
|
FNeedRestoreSorting := False;
|
|
RestoreSorting;
|
|
end;
|
|
finally
|
|
DoOnAfterSorting;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.EnableSorting;
|
|
begin
|
|
Dec(FSortLocking);
|
|
if FSortLocking = 0 then DoSortNodes;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.NeedSortPost;
|
|
begin
|
|
FNeedSortPost := True;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.BeginUpdateSelection;
|
|
begin
|
|
Inc(FSelectionUpdateLocked);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CancelUpdateSelection;
|
|
begin
|
|
Dec(FSelectionUpdateLocked);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.EndUpdateSelection;
|
|
begin
|
|
Dec(FSelectionUpdateLocked);
|
|
if FSelectionUpdateLocked = 0 then UpdateSelection;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.UpdateSelection;
|
|
begin
|
|
ViewInfo.NodesViewInfo.CheckSelectionMode := True;
|
|
try
|
|
ViewInfo.UpdateSelection;
|
|
finally
|
|
ViewInfo.NodesViewInfo.CheckSelectionMode := False;
|
|
DoSelectionChanged;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CancelFocusedRecordUpdatePost;
|
|
begin
|
|
FNeedFocusedRecordUpdatePost := False;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.PostUpdateFocusedRecord;
|
|
var
|
|
ANode: TcxTreeListNode;
|
|
begin
|
|
try
|
|
if (ViewInfo.NodesViewInfo.Count <> 0) and FNeedFocusedRecordUpdatePost then
|
|
begin
|
|
ANode := Nodes.GetVisibleNode(Nodes.FFocusedIndex);
|
|
if ANode <> nil then
|
|
begin
|
|
ANode.MakeVisible;
|
|
ANode.Focused := True;
|
|
end;
|
|
end;
|
|
finally
|
|
CancelFocusedRecordUpdatePost;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.UpdateFocusedRecordPost;
|
|
begin
|
|
if IsDestroying then Exit;
|
|
if not FNeedFocusedRecordUpdatePost and (FocusedNode <> nil) then
|
|
begin
|
|
FNeedFocusedRecordUpdatePost := True;
|
|
FNodes.FFocusedIndex := FocusedNode.VisibleIndex;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsSelectionLocked: Boolean;
|
|
begin
|
|
Result := FSelectionUpdateLocked <> 0;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsNeedSortPost: Boolean;
|
|
begin
|
|
Result := FNeedSortPost;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.RecreateSortOrdersList;
|
|
|
|
procedure AddSortInfo(AColumn: TcxTreeListColumn);
|
|
var
|
|
ASortInfo: PcxDataSortInfo;
|
|
begin
|
|
if AColumn.GetRealSortOrder = soNone then Exit;
|
|
New(PcxDataSortInfo(ASortInfo));
|
|
with ASortInfo^ do
|
|
begin
|
|
Field := TcxDataControllerAccess(DataController).Fields[AColumn.ItemIndex];
|
|
SortOrder := AColumn.GetRealSortOrder;
|
|
end;
|
|
FSortOrderList.Add(ASortInfo);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to SortOrderList.Count - 1 do
|
|
Dispose(PcxDataSortInfo(SortOrderList.List^[I]));
|
|
FSortOrderList.Clear;
|
|
for I := 0 to SortedColumnCount - 1 do
|
|
AddSortInfo(SortedColumns[I]);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.CheckEvent(AHasHandler: Boolean): Boolean;
|
|
begin
|
|
FPostChanged := True;
|
|
Result := AHasHandler;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoBandHeaderClick(ABand: TcxTreeListBand);
|
|
begin
|
|
if CheckEvent(Assigned(FOnBandHeaderClick)) then
|
|
FOnBandHeaderClick(Self, ABand);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoColumnHeaderClick(AColumn: TcxTreeListColumn);
|
|
begin
|
|
if CheckEvent(Assigned(FOnColumnHeaderClick)) then
|
|
FOnColumnHeaderClick(Self, AColumn);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoChanged(BlockChangedEvent: Boolean = True);
|
|
begin
|
|
if BlockChangedEvent and (OptionsBehavior.ChangeDelay > 0) then Exit;
|
|
try
|
|
if FPostChanged and CheckEvent(Assigned(FOnChange)) then
|
|
FOnChange(Self);
|
|
finally
|
|
FPostChanged := False;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoCanSelectNode(ANode: TcxTreeListNode): Boolean;
|
|
begin
|
|
Result := True;
|
|
if IsMultiSelect and (ANode <> nil) and CheckEvent(Assigned(FOnCanSelectNode)) then
|
|
FOnCanSelectNode(Self, ANode, Result);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoDataChangedEvent(Sender: TObject);
|
|
begin
|
|
if CheckEvent(Assigned(FOnDataChanged)) then
|
|
FOnDataChanged(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoEditChanged(
|
|
AItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
CheckEvent(False);
|
|
inherited DoEditChanged(AItem);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoEdited(
|
|
AItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
CheckEvent(False);
|
|
inherited DoEdited(AItem);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.DoEditing(
|
|
AItem: TcxCustomInplaceEditContainer): Boolean;
|
|
begin
|
|
CheckEvent(False);
|
|
Result := inherited DoEditing(AItem);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoEditValueChanged(
|
|
AItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
CheckEvent(False);
|
|
inherited DoEditValueChanged(AItem);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoInitEdit(
|
|
AItem: TcxCustomInplaceEditContainer; AEdit: TcxCustomEdit);
|
|
begin
|
|
CheckEvent(False);
|
|
inherited DoInitEdit(AItem, AEdit);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoFocusedItemChanged(
|
|
APrevFocusedItem, AFocusedItem: TcxCustomInplaceEditContainer);
|
|
begin
|
|
if CheckEvent(Assigned(FOnFocusedColumnChanged)) then
|
|
FOnFocusedColumnChanged(Self,
|
|
TcxTreeListColumn(APrevFocusedItem), TcxTreeListColumn(AFocusedItem));
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoFocusedRecordChanged(
|
|
APrevIndex, AFocusedIndex: Integer);
|
|
begin
|
|
if CheckEvent(Assigned(FOnFocusedNodeChanged)) then
|
|
FOnFocusedNodeChanged(Self, GetNodeByID(APrevIndex), GetNodeByID(AFocusedIndex));
|
|
if not OptionsSelection.MultiSelect then DoSelectionChanged;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoLayoutChangedEvent;
|
|
begin
|
|
if CheckEvent(Assigned(FOnLayoutChanged)) then
|
|
FOnLayoutChanged(Self);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoRecordChanged(
|
|
Sender: TcxCustomDataController; ARecordIndex, AItemIndex: Integer);
|
|
begin
|
|
if CheckEvent(Assigned(FOnNodeChanged)) then
|
|
FOnNodeChanged(Self, GetNodeByID(ARecordIndex), GetColumnById(AItemIndex));
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoSelectionChanged;
|
|
begin
|
|
if CheckEvent(Assigned(FOnSelectionChanged)) and not IsSelectionLocked then
|
|
FOnSelectionChanged(Self);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetBandItemClass: TcxTreeListBandClass;
|
|
begin
|
|
Result := TcxTreeListBand;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetControllerClass: TcxCustomControlControllerClass;
|
|
begin
|
|
Result := TcxTreeListController;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetControlStylesClass: TcxCustomControlStylesClass;
|
|
begin
|
|
Result := TcxTreeListStyles;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetHitTestControllerClass: TcxHitTestControllerClass;
|
|
begin
|
|
Result := TcxTreeListHitTest;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetNodesClass: TcxTreeListNodesClass;
|
|
begin
|
|
Result := TcxTreeListNodes;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsViewClass: TcxControlOptionsViewClass;
|
|
begin
|
|
Result := TcxTreeListOptionsView;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsCustomizingClass:
|
|
TcxTreeListOptionsCustomizingClass;
|
|
begin
|
|
Result := TcxTreeListOptionsCustomizing;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsBehaviorClass: TcxControlOptionsBehaviorClass;
|
|
begin
|
|
Result := TcxTreeListOptionsBehavior;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsDataClass: TcxControlOptionsDataClass;
|
|
begin
|
|
Result := TcxTreeListOptionsData;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsSelectionClass: TcxTreeListOptionsSelectionClass;
|
|
begin
|
|
Result := TcxTreeListOptionsSelection;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetPainterClass: TcxCustomControlPainterClass;
|
|
begin
|
|
Result := TcxTreeListControlPainter;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetPreviewClass: TcxTreeListPreviewClass;
|
|
begin
|
|
Result := TcxTreeListPreview;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetTreeListColumnClass: TcxTreeListColumnClass;
|
|
begin
|
|
Result := TcxTreeListColumn;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetTreeListCustomizingClass: TcxTreeListCustomizingClass;
|
|
begin
|
|
Result := TcxTreeListCustomizing;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetViewInfoClass: TcxCustomControlViewInfoClass;
|
|
begin
|
|
Result := TcxTreeListViewInfo;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOnAfterSummary: TcxAfterSummaryEvent;
|
|
begin
|
|
Result := DataController.Summary.OnAfterSummary;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOnEditing: TcxTreeListEditingEvent;
|
|
begin
|
|
Result := TcxTreeListEditingEvent(inherited OnEditing);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOnEdited: TcxTreeListColumnChangedEvent;
|
|
begin
|
|
Result := TcxTreeListColumnChangedEvent(inherited OnEdited);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOnEditValueChanged: TcxTreeListColumnChangedEvent;
|
|
begin
|
|
Result := TcxTreeListColumnChangedEvent(inherited OnEditValueChanged);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOnSummary: TcxSummaryEvent;
|
|
begin
|
|
Result := DataController.Summary.FooterSummaryItems.OnSummary;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSearching: Boolean;
|
|
begin
|
|
Result := Controller.IsIncSearching;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSearchingText: string;
|
|
begin
|
|
Result := Controller.IncSearchText
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetBands: TcxTreeListBands;
|
|
begin
|
|
Result := FBands;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetBandPanelHeight: Integer;
|
|
begin
|
|
with OptionsView do
|
|
Result := ViewInfo.BandLineHeight * BandLineCount * Byte(Bands);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetColumn(
|
|
AIndex: Integer): TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(ColumnsList[AIndex]);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetColumnCount: Integer;
|
|
begin
|
|
Result := ColumnsList.Count;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetColumnsList: TList;
|
|
begin
|
|
Result := inherited ContainerList;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetController: TcxTreeListController;
|
|
begin
|
|
Result := TcxTreeListController(inherited Controller);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetCount: Integer;
|
|
begin
|
|
Result := Nodes.Root.Count;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetDefaultRowHeight: Integer;
|
|
begin
|
|
Result := FDefaultRowHeight;
|
|
if Result = 0 then
|
|
Result := ViewInfo.DefaultEditHeight;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetFixedBandCount: Integer;
|
|
begin
|
|
if VisibleBandCount <> 0 then
|
|
with Bands do
|
|
begin
|
|
Result := Byte(FirstVisible.FixedKind = tlbfLeft) +
|
|
Byte(LastVisible.FixedKind = tlbfRight);
|
|
end
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetFooterHeight: Integer;
|
|
begin
|
|
Result := cxRectHeight(ViewInfo.FooterRect);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetFocusedColumn: TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(Controller.FocusedItem);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetFocusedNode: TcxTreeListNode;
|
|
begin
|
|
Result := Controller.FocusedNode;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetHeaderHeight: Integer;
|
|
begin
|
|
with OptionsView do
|
|
Result := Byte(Headers) * HeaderLineCount * ViewInfo.HeaderLineHeight;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetHeaderPanelHeight: Integer;
|
|
begin
|
|
Result := HeaderHeight + BandPanelHeight;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetHitTest: TcxTreeListHitTest;
|
|
begin
|
|
Result := TcxTreeListHitTest(Controller.HitTestController);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetLastNode: TcxTreeListNode;
|
|
begin
|
|
Result := cxGetLatest(Nodes.Root.GetLastChild, False);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetLastVisibleNode: TcxTreeListNode;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := VisibleCount - 1;
|
|
Result := TopVisibleNode;
|
|
while (I > 0) and (Result <> nil) do
|
|
begin
|
|
Result := Result.GetNextVisible;
|
|
Dec(I);
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetNavigatorIsActive: Boolean;
|
|
begin
|
|
Result := DataController.Active;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetInplaceColumnIndex: Integer;
|
|
begin
|
|
if IsEditing then
|
|
Result := Controller.EditingController.EditingItem.ItemIndex
|
|
else
|
|
Result := -1;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetInplaceEditor: TcxCustomEdit;
|
|
begin
|
|
if IsEditing then
|
|
Result := Controller.EditingController.Edit
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetIsEditing: Boolean;
|
|
begin
|
|
Result := Controller.IsEditing;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetItem(Index: Integer): TcxTreeListNode;
|
|
begin
|
|
Result := Nodes.Root.Items[Index];
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsBehavior: TcxTreeListOptionsBehavior;
|
|
begin
|
|
Result := TcxTreeListOptionsBehavior(inherited OptionsBehavior);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsData: TcxTreeListOptionsData;
|
|
begin
|
|
Result := TcxTreeListOptionsData(inherited OptionsData);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetOptionsView: TcxTreeListOptionsView;
|
|
begin
|
|
Result := TcxTreeListOptionsView(inherited OptionsView);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSelection(Index: Integer): TcxTreeListNode;
|
|
begin
|
|
if (Index = 0) and not OptionsSelection.MultiSelect and (FocusedNode <> nil) then
|
|
Result := FocusedNode
|
|
else
|
|
Result := TcxTreeListNode(FSelection[Index]);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSelectionCount: Integer;
|
|
begin
|
|
Result := FSelection.Count;
|
|
if not OptionsSelection.MultiSelect and (FocusedNode <> nil) then
|
|
Result := 1;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSortedColumnCount: Integer;
|
|
begin
|
|
Result := FSortedColumns.Count;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSortedColumn(
|
|
Index: Integer): TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(FSortedColumns[Index]);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetStyles: TcxTreeListStyles;
|
|
begin
|
|
Result := TcxTreeListStyles(inherited Styles);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSummary: TcxDataSummary;
|
|
begin
|
|
Result := DataController.Summary;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetSorted: Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
for I := 0 to ColumnCount - 1 do
|
|
if Columns[I].GetRealSortOrder <> soNone then
|
|
begin
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetTopNode: TcxTreeListNode;
|
|
begin
|
|
Result := Nodes.Root.GetFirstChild;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetTopVisibleIndex: Integer;
|
|
begin
|
|
Result := ViewInfo.NodesViewInfo.TopVisibleIndex;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetTopVisibleNode: TcxTreeListNode;
|
|
begin
|
|
Result := ViewInfo.NodesViewInfo.TopNode;
|
|
if Result = nil then
|
|
Result := Nodes.TopNode;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetVisibleCount: Integer;
|
|
begin
|
|
with ViewInfo.NodesViewInfo do
|
|
begin
|
|
if TopNode <> nil then
|
|
Result := VisibleCount
|
|
else
|
|
Result := -1;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetViewInfo: TcxTreeListViewInfo;
|
|
begin
|
|
Result := TcxTreeListViewInfo(inherited ViewInfo);
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetVisibleBand(
|
|
AIndex: Integer): TcxTreeListBand;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := Bands.GetAbsoluteIndex(AIndex);
|
|
if I <> - 1 then
|
|
Result := Bands.GetItem(I)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetVisibleBandCount: Integer;
|
|
begin
|
|
Result := FBandsVisibleList.Count;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetVisibleColumn(
|
|
AIndex: Integer): TcxTreeListColumn;
|
|
begin
|
|
Result := TcxTreeListColumn(FColumnsVisibleList[AIndex])
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetVisibleColumnCount: Integer;
|
|
begin
|
|
Result := FColumnsVisibleList.Count;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.IsDefaultRowHeightAssigned: Boolean;
|
|
begin
|
|
Result := FDefaultRowHeight <> 0;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetBands(Value: TcxTreeListBands);
|
|
begin
|
|
FBands.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetColumn(
|
|
AIndex: Integer; Value: TcxTreeListColumn);
|
|
begin
|
|
TcxTreeListColumn(ColumnsList[AIndex]).Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetDefaultRowHeight(Value: Integer);
|
|
begin
|
|
if Value < 0 then Value := 0;
|
|
with ViewInfo do
|
|
begin
|
|
if (DefaultEditHeight > 0) and (Value < DefaultEditHeight) then
|
|
Value := DefaultEditHeight;
|
|
end;
|
|
FDefaultRowHeight := Value;
|
|
LayoutChanged;
|
|
Modified;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetDefaultLayout(Value: Boolean);
|
|
begin
|
|
if Value <> FDefaultLayout then
|
|
begin
|
|
FDefaultLayout := Value;
|
|
if Value then
|
|
MakeDefaultLayout;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetFocusedColumn(Value: TcxTreeListColumn);
|
|
begin
|
|
if (Value <> nil) and Value.Visibility then
|
|
Controller.FocusedItem := Value
|
|
else
|
|
if Value = nil then
|
|
Controller.FocusedItem := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetFocusedNodeProp(Value: TcxTreeListNode);
|
|
begin
|
|
SetFocusedNode(Value, []);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetImages(Value: TCustomImageList);
|
|
begin
|
|
SetInternalImageList(Value, FImages, FChangeImagesLink);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetInternalImageList(
|
|
AList: TCustomImageList; var Value: TCustomImageList; ALink: TChangeLink);
|
|
begin
|
|
Freeze;
|
|
try
|
|
cxSetImageList(AList, Value, ALink, Self);
|
|
finally
|
|
UnFreeze;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetLastVisibleNode(Value: TcxTreeListNode);
|
|
begin
|
|
if (Value <> nil) and Value.IsVisible then
|
|
ViewInfo.NodesViewInfo.SetLastVisibleNode(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetNodes(Value: TcxTreeListNodes);
|
|
begin
|
|
FNodes.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOnAfterSummary(Value: TcxAfterSummaryEvent);
|
|
begin
|
|
DataController.Summary.OnAfterSummary := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOnEdited(Value: TcxTreeListColumnChangedEvent);
|
|
begin
|
|
inherited OnEdited := TcxecItemEvent(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOnEditing(Value: TcxTreeListEditingEvent);
|
|
begin
|
|
inherited OnEditing := TcxecEditingEvent(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOnEditValueChanged(
|
|
Value: TcxTreeListColumnChangedEvent);
|
|
begin
|
|
inherited OnEditValueChanged := TcxecItemEvent(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOnSummary(Value: TcxSummaryEvent);
|
|
begin
|
|
DataController.Summary.FooterSummaryItems.OnSummary := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOptionsBehavior(
|
|
Value: TcxTreeListOptionsBehavior);
|
|
begin
|
|
inherited OptionsBehavior := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOptionsCustomizing(
|
|
Value: TcxTreeListOptionsCustomizing);
|
|
begin
|
|
FOptionsCustomizing.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOptionsData(Value: TcxTreeListOptionsData);
|
|
begin
|
|
inherited OptionsData := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOptionsView(Value: TcxTreeListOptionsView);
|
|
begin
|
|
inherited OptionsView := Value;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetOptionsSelection(
|
|
Value: TcxTreeListOptionsSelection);
|
|
begin
|
|
FOptionsSelection.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetPreview(Value: TcxTreeListPreview);
|
|
begin
|
|
FPreview.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetSearchingText(const Value: string);
|
|
begin
|
|
if Value = '' then
|
|
CancelSearching
|
|
else
|
|
Controller.IncSearchingText := Value
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetSorted(Value: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not Value then
|
|
begin
|
|
for I := 0 to ColumnCount - 1 do
|
|
Columns[I].SortOrder := soNone;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetStateImages(Value: TCustomImageList);
|
|
begin
|
|
SetInternalImageList(Value, FStateImages, FChangeStateImagesLink);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetStyles(Value: TcxTreeListStyles);
|
|
begin
|
|
Styles.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetTopVisibleIndex(AValue: Integer);
|
|
begin
|
|
if IsLocked then
|
|
begin
|
|
Nodes.TopIndex := AValue;
|
|
Nodes.TopNode := Nodes.GetVisibleNode(AValue);
|
|
ViewInfo.DoCalculate;
|
|
end
|
|
else
|
|
if cxValidateIntDefEx(AValue, TopVisibleIndex, 0, Nodes.VisibleCount - 1) then
|
|
ViewInfo.DoScrollVertical(AValue - TopVisibleIndex);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetTopVisibleNode(ANode: TcxTreeListNode);
|
|
begin
|
|
Nodes.CalculateInfo(False);
|
|
if (ANode <> nil) and ANode.IsVisible then
|
|
SetTopVisibleIndex(ANode.VisibleIndex);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetVisibleBand(
|
|
Index: Integer; AValue: TcxTreeListBand);
|
|
begin
|
|
VisibleBands[Index].Assign(AValue);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetVisibleColumn(
|
|
Index: Integer; AValue: TcxTreeListColumn);
|
|
begin
|
|
TcxTreeListColumn(FColumnsVisibleList[Index]).Assign(AValue);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.DoChangedTimer(Sender: TObject);
|
|
begin
|
|
if not IsDestroying and not IsLoading then
|
|
DoChanged(False);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.UpdateDesignerForms;
|
|
var
|
|
AIntf: IcxTreeListDesigner;
|
|
I: Integer;
|
|
begin
|
|
if not FNeedUpdateDesigners then Exit;
|
|
for I := 0 to Designers.Count - 1 do
|
|
if Supports(TObject(Designers[I]), IcxTreeListDesigner, AIntf) then
|
|
begin
|
|
if IsDestroying then
|
|
AIntf.ComponentRemoved(Self)
|
|
else
|
|
AIntf.Modified;
|
|
end;
|
|
FNeedUpdateDesigners := False;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetObjectName: string;
|
|
begin
|
|
Result := GetStoredObjectName;
|
|
end;
|
|
|
|
function TcxCustomTreeListControl.GetProperties(AProperties: TStrings): Boolean;
|
|
begin
|
|
Result := GetStoredObjectProperties(AProperties);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.GetPropertyValue(
|
|
const AName: string; var AValue: Variant);
|
|
begin
|
|
GetStoredPropertyValue(AName, AValue);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.SetPropertyValue(
|
|
const AName: string; const AValue: Variant);
|
|
begin
|
|
SetStoredPropertyValue(AName, AValue);
|
|
end;
|
|
|
|
procedure TcxCustomTreeListControl.CMDrag(var Message: TCMDrag);
|
|
const
|
|
AcceptedCursors: array[Boolean] of TCursor = (crDrag, crDragCopy);
|
|
begin
|
|
DragCursor := AcceptedCursors[Controller.IsDragCopy];
|
|
inherited;
|
|
end;
|
|
|
|
{ TcxTreeList }
|
|
|
|
destructor TcxTreeList.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TcxTreeList.Add: TcxTreeListNode;
|
|
begin
|
|
Result := Add(nil);
|
|
end;
|
|
|
|
function TcxTreeList.Add(ASibling: TcxTreeListNode;
|
|
AData: Pointer = nil): TcxTreeListNode;
|
|
begin
|
|
if ASibling <> nil then
|
|
ASibling := ASibling.Parent;
|
|
Result := AddNode(nil, ASibling, AData, tlamAdd);
|
|
end;
|
|
|
|
function TcxTreeList.AddChild(AParent: TcxTreeListNode;
|
|
AData: Pointer = nil): TcxTreeListNode;
|
|
begin
|
|
Result := AddNode(nil, AParent, AData, tlamAddChild);
|
|
end;
|
|
|
|
function TcxTreeList.AddChildFirst(AParent: TcxTreeListNode;
|
|
AData: Pointer = nil): TcxTreeListNode;
|
|
begin
|
|
Result := AddNode(nil, AParent, AData, tlamAddChildFirst);
|
|
end;
|
|
|
|
function TcxTreeList.AddFirst: TcxTreeListNode;
|
|
begin
|
|
Result := AddFirst(nil);
|
|
end;
|
|
|
|
function TcxTreeList.AddFirst(ASibling: TcxTreeListNode; // need test???
|
|
AData: Pointer = nil): TcxTreeListNode;
|
|
begin
|
|
if ASibling <> nil then
|
|
ASibling := ASibling.Parent;
|
|
Result := AddNode(nil, ASibling, AData, tlamAddFirst);
|
|
end;
|
|
|
|
function TcxTreeList.AddNode(ANode, ARelative: TcxTreeListNode;
|
|
AData: Pointer; AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode;
|
|
begin
|
|
Result := inherited AddNode(ANode, ARelative, AData, AttachMode);
|
|
end;
|
|
|
|
function TcxTreeList.Insert(ASibling: TcxTreeListNode;
|
|
AData: Pointer = nil): TcxTreeListNode;
|
|
begin
|
|
Result := AddNode(nil, ASibling, AData, tlamInsert);
|
|
end;
|
|
|
|
function TcxTreeList.InsertEx(ANode, ASibling: TcxTreeListNode;
|
|
AData: Pointer = nil): TcxTreeListNode;
|
|
begin
|
|
Result := AddNode(ANode, ASibling, AData, tlamInsert);
|
|
end;
|
|
|
|
procedure TcxTreeList.LoadFromFile(const AFileName: string);
|
|
var
|
|
AFileStream: TFileStream;
|
|
begin
|
|
AFileStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
|
|
try
|
|
LoadFromStream(AFileStream);
|
|
finally
|
|
FreeAndNil(AFileStream);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeList.LoadFromStream(AStream: TStream);
|
|
begin
|
|
SetGlassCursor;
|
|
try
|
|
ReadData(AStream);
|
|
finally
|
|
RestoreCursor;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeList.SaveToFile(const AFileName: string);
|
|
var
|
|
AFileStream: TFileStream;
|
|
begin
|
|
AFileStream := TFileStream.Create(AFileName, fmCreate);
|
|
try
|
|
SaveToStream(AFileStream);
|
|
finally
|
|
FreeAndNil(AFileStream);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeList.SaveToStream(AStream: TStream);
|
|
var
|
|
ASignature: TcxTreeListDataSignature;
|
|
begin
|
|
AStream.WriteBuffer(ASignature, SizeOf(ASignature));
|
|
DataController.SaveToStream(AStream);
|
|
WriteData(AStream);
|
|
end;
|
|
|
|
procedure TcxTreeList.DoAssignNodes(Source: TcxTreeListNodes);
|
|
var
|
|
AStream: TMemoryStream;
|
|
begin
|
|
if Source.TreeList is TcxTreeList then
|
|
begin
|
|
AStream := TMemoryStream.Create;
|
|
try
|
|
TcxTreeList(Source.TreeList).SaveToStream(AStream);
|
|
AStream.Position := 0;
|
|
LoadFromStream(AStream);
|
|
finally
|
|
FreeAndNil(AStream);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeList.DoSetNodeImageIndex(ANode: TcxTreeListNode;
|
|
AIndex: TcxTreeListImageIndexType; Value: TImageIndex);
|
|
begin
|
|
if ANode = nil then Exit;
|
|
TcxUnboundTreeListNode(ANode).FImageIndexes[AIndex] := Value;
|
|
if not LockChanges then DoNodeChanged(ANode);
|
|
end;
|
|
|
|
procedure TcxTreeList.DefineProperties(Filer: TFiler);
|
|
begin
|
|
inherited DefineProperties(Filer);
|
|
Filer.DefineBinaryProperty('Data', ReadBinaryData, SaveToStream, Nodes.Count > 0);
|
|
end;
|
|
|
|
procedure TcxTreeList.Loaded;
|
|
begin
|
|
if FLoadingTemporaryStream <> nil then
|
|
begin
|
|
LoadFromStream(FLoadingTemporaryStream);
|
|
FreeAndNil(FLoadingTemporaryStream);
|
|
end;
|
|
inherited Loaded;
|
|
if (TopVisibleNode <> nil) and (FocusedNode = nil) then
|
|
TopVisibleNode.Focused := True;
|
|
end;
|
|
|
|
function TcxTreeList.SupportsBandColumnEditor: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TcxTreeList.SupportsItemsEditor: Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxTreeList.ReadData(AStream: TStream);
|
|
|
|
procedure DoReadNodesData;
|
|
var
|
|
AIndex: Integer;
|
|
ANewNode, ANode, ARoot: TcxTreeListNode;
|
|
begin
|
|
ARoot := Nodes.Root;
|
|
ANode := ARoot;
|
|
AStream.ReadBuffer(ARoot.FCount, SizeOf(Integer));
|
|
if ARoot.FCount = 0 then Exit;
|
|
AIndex := 0;
|
|
repeat
|
|
ANewNode := ExCreateNode(ANode, ANode.FLast, AIndex);
|
|
ANewNode.ReadData(AStream);
|
|
NodesList.List^[ANewNode.RecordIndex] := ANewNode;
|
|
if ANewNode.FCount > 0 then
|
|
begin
|
|
ANode := ANewNode;
|
|
AIndex := 0;
|
|
Continue;
|
|
end
|
|
else
|
|
while ANewNode.FParent <> nil do
|
|
begin
|
|
ANode := ANewNode.FParent;
|
|
AIndex := ANode.FLast.FIndex + 1;
|
|
if AIndex < ANode.Count then
|
|
Break
|
|
else
|
|
ANewNode := ANode;
|
|
end;
|
|
until (ANode = ARoot) and (AIndex = ANode.Count);
|
|
end;
|
|
|
|
begin
|
|
inherited ReadData(AStream);
|
|
BeginUpdate;
|
|
try
|
|
Nodes.Clear;
|
|
Nodes.IsInternalCreating := True;
|
|
Nodes.IsInvalidState := True;
|
|
try
|
|
DataController.LoadFromStream(AStream);
|
|
NodesList.Count := DataController.RecordCount;
|
|
DoReadNodesData;
|
|
except
|
|
Nodes.Clear;
|
|
raise;
|
|
end;
|
|
finally
|
|
Nodes.IsInternalCreating := False;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxTreeList.ReadBinaryData(AStream: TStream);
|
|
var
|
|
ASignature: TcxTreeListDataSignature;
|
|
begin
|
|
AStream.ReadBuffer(ASignature, SizeOf(ASignature));
|
|
with ASignature do
|
|
if {(Version and cxTreeListVersion = 0) or} (Size <> AStream.Size) then
|
|
cxTreeListError(scxStr(@scxInvalidStreamFormat));
|
|
if FLoadingTemporaryStream = nil then
|
|
FLoadingTemporaryStream := TMemoryStream.Create;
|
|
AStream.Position := 0;
|
|
FLoadingTemporaryStream.CopyFrom(AStream, ASignature.Size);
|
|
FLoadingTemporaryStream.Position := 0;
|
|
end;
|
|
|
|
procedure TcxTreeList.WriteData(AStream: TStream);
|
|
|
|
procedure DoWriteNodesData;
|
|
var
|
|
ANode, ARoot: TcxTreeListNode;
|
|
begin
|
|
ARoot := Nodes.Root;
|
|
ANode := ARoot.GetFirstChild;
|
|
AStream.WriteBuffer(Nodes.Root.FCount, SizeOf(Integer));
|
|
while ANode <> nil do
|
|
begin
|
|
ANode.WriteData(AStream);
|
|
if ANode.FCount > 0 then
|
|
ANode := ANode.GetFirstChild
|
|
else
|
|
begin
|
|
while (ANode <> nil)and (ANode.FNext = nil)do ANode := ANode.FParent;
|
|
if ANode <> nil then ANode := ANode.FNext;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
DoWriteNodesData;
|
|
inherited WriteData(AStream);
|
|
end;
|
|
|
|
function TcxTreeList.ExCreateNode(AParent, APrev: TcxTreeListNode;
|
|
var AIndex: Integer): TcxTreeListNode;
|
|
begin
|
|
Result := DoCreateNode;
|
|
Result.FParent := AParent;
|
|
if APrev <> nil then
|
|
APrev.FNext := Result
|
|
else
|
|
AParent.FFirst := Result;
|
|
Result.FIndex := AIndex;
|
|
Result.FPrev := APrev;
|
|
AParent.FLast := Result;
|
|
Inc(AIndex);
|
|
end;
|
|
|
|
initialization
|
|
SortingManager := TSortingManager.Create;
|
|
Classes.RegisterClass(TcxTreeListStyleSheet);
|
|
|
|
finalization
|
|
FreeAndNil(SortingManager);
|
|
Classes.UnRegisterClass(TcxTreeListStyleSheet);
|
|
|
|
end.
|
|
|