{********************************************************************} { } { 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 Variants, Classes, SysUtils, Clipbrd, Windows, Messages, ExtCtrls, Controls, Forms, StdCtrls, Menus, Graphics, ImgList, ComCtrls, Contnrs, Math, cxControls, cxContainer, cxCheckBox, cxCheckListBox, cxGraphics, cxVariants, cxNavigator, cxStorage, cxClasses, cxEdit, cxListBox, cxInplaceContainer, cxLookAndFeels, cxLookAndFeelPainters, cxData, cxDataUtils, cxCustomData, cxStyles, cxGeometry, cxTLStrs, cxScrollBar, cxLibraryConsts, cxDataStorage, cxPC, dxCore, cxLookupEdit, dxUxTheme; const cxTLMajorVersion = '5'; // default size values for treelist items cxTreeListDefWidth = 100; cxTreeListDefMinWidth = 20; // default values for treelist options view cxTreeListHeaderMovingZoneSize = 20; cxTreeListDefIndicatorWidth = 12; cxTreeListDefSeparatorWidth = 2; cxTreeListDefDropArrowColor = $00FF00; CustomizationPopupColumnOffset = 10; cxTreeListResizeInc = 50; // 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_HitAtBackground = 4; tlhc_HitAtBand = 5; tlhc_HitAtBandContainer = 6; tlhc_HitAtBandCustomizing = 7; tlhc_HitAtBandHeader = 8; tlhc_HitAtButton = 9; tlhc_HitAtCheckButton = 10; tlhc_HitAtColumn = 11; tlhc_HitAtColumnCustomizing = 12; tlhc_HitAtColumnHeader = 13; tlhc_HitAtFooter = 14; tlhc_HitAtFooterItem = 15; tlhc_HitAtGroupFooter = 16; tlhc_HitAtGroupFooterItem = 17; tlhc_HitAtImage = 18; tlhc_HitAtIndent = 19; tlhc_HitAtIndicator = 20; tlhc_HitAtNode = 21; tlhc_HitAtNodePreview = 22; tlhc_HitAtSeparator = 23; tlhc_HitAtSizingHorz = 24; tlhc_HitAtSizingVert = 25; tlhc_HitAtStateImage = 26; // events state tlesNone = $0000; tlesChanged = $0001; tlesSelection = $0002; // hit test and sizing constants cxtlHitDelta = 3; cxtlScrollDelta = 10; cxtlSizingMarkWidth = 1; // cxtlEditCell = 1; cxtlPreviewCell = 2; cxtlBandPartCell = 3; cxtlColumnHeaderCell = 4; cxtlBandHeaderCell = 5; cxtlIndentCell = 6; cxtlIndicatorCell = 7; cxtlBackgroundCell = 8; cxtlFooterCell = 9; // popup menu commands // Summary commands tlcmNone = 0; tlcmSum = 1; tlcmMin = 2; tlcmMax = 3; tlcmCount = 4; tlcmAverage = 5; tlcmAllNodes = 6; // Column Header commands tlcmSortAscending = 20; tlcmSortDescending = 21; tlcmClearSorting = 22; tlcmFooter = 23; tlcmGroupFootersInvisible = 24; tlcmGroupFootersVisibleWhenExpanded = 25; tlcmGroupFootersAlwaysVisible = 26; tlcmRemoveThisColumn = 27; tlcmFieldChooser = 28; tlcmHorzAlignmentLeft = 29; tlcmHorzAlignmentRight = 30; tlcmHorzAlignmentCenter = 31; tlcmVertAlignmentTop = 32; tlcmVertAlignmentBottom = 33; tlcmVertAlignmentCenter = 34; tlcmBestFit = 35; tlcmBestFitAllColumns = 36; tlcmUser = tlcmBestFitAllColumns + 1000; // overs cvis_ViewInfoCalculate = 4; // cxColumnTextSeparator = #9; cxLineSeparator = #13#10; cxTreeListScrollWidthDragInterval = 50; cxTreeListIndentOffsetSize = 6; cxTreeListEditCellHeightOffset = 2; cxTreeListDragDropTextAreaOffset: TPoint = (X: 20; Y:0); {$UNDEF CXTEST} type EcxTreeList = class(Exception); TcxCustomTreeListClass = class of TcxCustomTreeList; TcxTreeListController = class; TcxTreeListDataController = class; TcxTreeListColumn = class; TcxTreeListColumnSummary = class; TcxTreeListPopupMenu = class; TcxTreeListPopupMenus = class; TcxTreeListSummary = class; TcxTreeListSummaryItem = class; TcxTreeListSummaryItems = class; TcxTreeListBand = class; TcxTreeListBands = class; TcxTreeListBandRow = class; TcxTreeListBandRows = class; TcxTreeListOptionsBehavior = class; TcxTreeListOptionsSelection = class; TcxTreeListOptionsCustomizing = class; TcxTreeListOptionsCustomizingClass = class of TcxTreeListOptionsCustomizing; TcxTreeListHitTest = class; TcxTreeListNodeViewData = class; TcxTreeListLevelInfo = class; TcxTreeListViewInfo = class; TcxTreeListCustomCellViewInfo = class; TcxTreeListCustomCellViewInfoClass = class of TcxTreeListCustomCellViewInfo; TcxTreeListCustomHeaderCellViewInfo = class; TcxTreeListHeaderCellViewInfo = class; TcxTreeListColumnHeaderCellViewInfo = class; TcxTreeListEditCellViewInfo = class; TcxTreeListIndicatorCellViewInfo = class; TcxTreeListCustomizationForm = class; TcxTreeListOptionsView = class; TcxTreeListPainter = class; TcxTreeListNode = class; TcxTreeListNodeClass = class of TcxTreeListNode; TcxTreeListPreview = class; TcxTreeListPreviewClass = class of TcxTreeListPreview; TcxCustomTreeList = class; TcxTreeListCustomizing = class; TcxTreeListItemsCustomizeListBox = class; TcxTreeListStyles = class; // overriding types PIntArray = ^TIntArray; TIntArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer; TcxTreeListBandFixedKind = (tlbfNone, tlbfLeft, tlbfRight); TcxTreeListBandExpandable = (tlbeDefault, tlbeExpandable, tlbeNotExpandable); TcxTreeListGridLines = (tlglNone, tlglHorz, tlglVert, tlglBoth); TcxTreeListImageIndexType = (tlitImageIndex, tlitSelectedIndex, tlitStateIndex, tlitOverlayIndex, tlitOverlayStateIndex); 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; { IcxTreeListListener } IcxTreeListDesigner = interface ['{1F4D4387-57E1-4756-9093-1124077A0F54}'] procedure ComponentModified; procedure ComponentRemoved(Sender: TObject); end; IcxTreeListDesignTimeOperations = interface ['{781A0614-EA26-4214-85D2-10C7DA2AF22B}'] function SupportBandColumnEditor: Boolean; function SupportItemsEditor: Boolean; function SupportCreateAllItems: Boolean; procedure CreateAllItems; end; PcxTreeListNodeData = ^TcxTreeListNodeData; TcxTreeListNodeData = record Node: TcxTreeListNode; NodeData: Pointer; end; TcxTreeListChange = (tcStructure, tcData, tcLayout, tcImages, tcColumns, tcSortOrder, tcLoading, tcSelection, tcFocusedNode); TcxTreeListChanges = set of TcxTreeListChange; { TcxTreeListSummaryInfo } TcxTreeListSummaryInfo = record Value: Variant; TempValue: Variant; Count: Integer; end; TcxTreeListSummaryInfos = array of TcxTreeListSummaryInfo; { TcxTreeListNode } TcxTreeListNodeState = (nsDeleting, nsHasChildren, nsValuesAssigned, nsCollapsed, nsValidIndexes, nsInternalDelete, nsHidden, nsHeightAssigned, nsInserting, nsEditing, nsCheck, nsDisabled, Reserved); TcxTreeListNodeStates = set of TcxTreeListNodeState; TcxTreeListNodeCheckInfo = (nciChecked, nciGrayed, nciAllowGrayed, nciCheckGroup, nciRadioGroup, nciCheckValid, nciChangeCheck); TcxTreeListNodeCheckInfos = set of TcxTreeListNodeCheckInfo; TcxTreeListNodeCheckGroupType = (ncgNone, ncgCheckGroup, ncgRadioGroup); TcxTreeListNode = class(TPersistent, IUnknown, IcxDragSizing) private FAbsoluteIndex: Integer; FCount: Integer; FData: Pointer; FFirst: TcxTreeListNode; FHandle: Pointer; FHeight: Integer; FIndex: Integer; FLast: TcxTreeListNode; FNext: TcxTreeListNode; FOriginalIndex: Integer; FTreeList: TcxCustomTreeList; FParent: TcxTreeListNode; FPrev: TcxTreeListNode; FViewData: TcxTreeListNodeViewData; function GetAbsoluteIndex: Integer; function GetAllowGrayed: Boolean; function GetChecked: Boolean; function GetCheckedCount: Integer; function GetChildVisibleCount: Integer; function GetCheckGroupType: TcxTreeListNodeCheckGroupType; function GetCheckState: TcxCheckBoxState; function GetEnabled: Boolean; function GetExpanded: Boolean; function GetFocused: Boolean; function GetGrayedCount: Integer; function GetHasCheckbox: Boolean; function GetHasChildren: Boolean; function GetHasVisibleChildren: Boolean; function GetHotTrack: Boolean; function GetIndex: Integer; function GetIsDeleting: Boolean; function GetIsFirst: Boolean; function GetIsGroupNode: Boolean; function GetIsHidden: Boolean; function GetIsLast: Boolean; function GetIsPrinted: Boolean; function GetIsRadioGroup: Boolean; function GetIsVisible: Boolean; function GetItem(AIndex: Integer): TcxTreeListNode; function GetLevel: Integer; function GetRoot: TcxTreeListNode; function GetSelected: Boolean; function GetSummary: TcxTreeListSummary; function GetNodeImageIndex(AIndex: Integer): TImageIndex; function GetText(AIndex: Integer): string; function GetValue(AIndex: Integer): Variant; function GetValueCount: Integer; function GetVisible: Boolean; function GetVisibleIndex: Integer; procedure AdjustIndexes; procedure InternalInsert(AValue: TcxTreeListNode); procedure InternalRemove(AValue: TcxTreeListNode); procedure SetAllowGrayed(AValue: Boolean); procedure SetChecked(AValue: Boolean); procedure SetCheckGroupType(AValue: TcxTreeListNodeCheckGroupType); procedure SetCheckState(AValue: TcxCheckBoxState); procedure SetEnabled(AValue: Boolean); procedure SetExpanded(AValue: Boolean); procedure SetFirst(AValue: TcxTreeListNode); procedure SetFocused(AValue: Boolean); procedure SetFooterSummaryValue(AIndex: Integer; AValue: Variant); procedure SetHasChildren(AValue: Boolean); procedure SetHeight(AValue: Integer); procedure SetItem(AIndex: Integer; AValue: TcxTreeListNode); procedure SetLast(AValue: TcxTreeListNode); procedure SetNodeImageIndex(AIndex: Integer; AValue: TImageIndex); procedure SetParentFor(AValue: TcxTreeListNode; AValidateIndexes: Boolean = True); procedure SetText(AIndex: Integer; const AValue: string); procedure SetSelected(AValue: Boolean); procedure SetValue(AIndex: Integer; const AValue: Variant); procedure SetVisible(AValue: Boolean); protected FImageIndexes: TcxTreeListNodeImageIndexes; FSummaryInfo: TcxTreeListSummaryInfos; FVisibleIndex: Integer; CheckInfo: TcxTreeListNodeCheckInfos; State: TcxTreeListNodeStates; procedure AssignData(ASource: TcxTreeListNode); virtual; function GetFooterSummaryCount: Integer; virtual; function GetFooterSummaryText(AIndex: Integer): string; virtual; function GetFooterSummaryValue(AIndex: Integer): Variant; virtual; function GetInserting: Boolean; 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 InternalFree; procedure InitializeHandle; virtual; procedure ReadData(AStream: TStream; AVersion: Integer); virtual; procedure SetChildrenCheckState(AValue: TcxCheckBoxState; AExclude: TcxTreeListNode); 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 PopulateItems(AList: TList); procedure SetSizeDelta(ADirection: TcxDragSizingDirection; ADelta: Integer); procedure UpdateItems(AList: TList); // IUnknown function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; property CheckedCount: Integer read GetCheckedCount; property GrayedCount: Integer read GetGrayedCount; property Handle: Pointer read FHandle write FHandle; property OriginalIndex: Integer read FOriginalIndex; property IsPrinted: Boolean read GetIsPrinted; property IsRadioGroup: Boolean read GetIsRadioGroup; property Summary: TcxTreeListSummary read GetSummary; property ViewData: TcxTreeListNodeViewData read FViewData write FViewData; public constructor Create(AOwner: TcxCustomTreeList); virtual; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure AssignValues(const AValues: array of 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 CheckClick; 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(ANode: TcxTreeListNode): TcxTreeListNode; function getNextSibling: TcxTreeListNode; {GetNextSibling conflicts with C++ macro} function GetNextSiblingVisible: TcxTreeListNode; function GetNextVisible: TcxTreeListNode; function GetPrev: TcxTreeListNode; function GetPrevChild(ANode: TcxTreeListNode): TcxTreeListNode; function getPrevSibling: TcxTreeListNode; {GetPrevSibling conflicts with a C++ macro} function GetPrevSiblingVisible: TcxTreeListNode; function GetPrevVisible: TcxTreeListNode; function getFirstChild: TcxTreeListNode; {GetFirstChild conflicts with C++ macro} function GetFirstChildVisible: TcxTreeListNode; function GetLastChild: TcxTreeListNode; function GetLastChildVisible: TcxTreeListNode; // function HasAsParent(ANode: TcxTreeListNode): Boolean; function IndexOf(ANode: TcxTreeListNode): Integer; function InsertChild(ABeforeNode: TcxTreeListNode): TcxTreeListNode; virtual; procedure Invalidate; function IsSibling(ANode: TcxTreeListNode): Boolean; procedure LoadChildren; procedure MakeVisible; procedure MoveTo(ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode); virtual; procedure Repaint(ARecalculate: Boolean); virtual; property AbsoluteIndex: Integer read GetAbsoluteIndex; property AllowGrayed: Boolean read GetAllowGrayed write SetAllowGrayed; property Checked: Boolean read GetChecked write SetChecked; property CheckGroupType: TcxTreeListNodeCheckGroupType read GetCheckGroupType write SetCheckGroupType; property CheckState: TcxCheckBoxState read GetCheckState write SetCheckState; property ChildVisibleCount: Integer read GetChildVisibleCount; property Count: Integer read FCount; property Data: Pointer read FData write FData; property Deleting: Boolean read GetIsDeleting; property Enabled: Boolean read GetEnabled write SetEnabled; property Expanded: Boolean read GetExpanded write SetExpanded; property Focused: Boolean read GetFocused write SetFocused; property FooterSummaryCount: Integer read GetFooterSummaryCount; property FooterSummaryTexts[Index: Integer]: string read GetFooterSummaryText; property FooterSummaryValues[Index: Integer]: Variant read GetFooterSummaryValue write SetFooterSummaryValue; property HasCheckbox: Boolean read GetHasCheckbox; property HasChildren: Boolean read GetHasChildren write SetHasChildren; property HasVisibleChildren: Boolean read GetHasVisibleChildren; property Height: Integer read FHeight write SetHeight; property HotTrack: Boolean read GetHotTrack; property ImageIndex: TImageIndex index 0 read GetNodeImageIndex write SetNodeImageIndex; property Index: Integer read GetIndex; property Inserting: Boolean read GetInserting; property IsFirst: Boolean read GetIsFirst; property IsFirstVisible: Boolean read GetIsFirstVisible; property IsGroupNode: Boolean read GetIsGroupNode; property IsHidden: Boolean read GetIsHidden; 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 OverlayIndex: TImageIndex index 3 read GetNodeImageIndex write SetNodeImageIndex; property OverlayStateIndex: TImageIndex index 4 read GetNodeImageIndex write SetNodeImageIndex; property Parent: TcxTreeListNode read FParent; property Root: TcxTreeListNode read GetRoot; 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: TcxCustomTreeList read FTreeList; property ValueCount: Integer read GetValueCount; property Values[Index: Integer]: Variant read GetValue write SetValue; property Visible: Boolean read GetVisible write SetVisible; property VisibleIndex: Integer read GetVisibleIndex; end; { TcxTreeListRootNode } TcxTreeListRootNode = class(TcxTreeListNode) protected function GetFooterSummaryCount: Integer; override; function GetFooterSummaryText(AIndex: Integer): string; override; procedure InitializeHandle; override; end; { TcxUnboundTreeListNode } TcxUnboundTreeListNode = class(TcxTreeListNode) protected procedure ReadData(AStream: TStream; AVersion: Integer); override; procedure WriteData(AStream: TStream); override; public constructor Create(AOwner: TcxCustomTreeList); override; procedure Assign(Source: TPersistent); override; end; { TcxTreeListColumnStyles } TcxTreeListColumnStyles = class(TcxEditContainerStyles) private function GetBand: TcxTreeListBand; function GetColumn: TcxTreeListColumn; function GetTreeList: TcxCustomTreeList; protected procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; function GetContentParams(ANode: TcxTreeListNode): TcxViewParams; property Band: TcxTreeListBand read GetBand; property Column: TcxTreeListColumn read GetColumn; property TreeList: TcxCustomTreeList read GetTreeList; 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 FBand: TcxTreeListBand; FBandIndex: Integer; FColIndex: Integer; FLineCount: Integer; FRow: TcxTreeListBandRow; FRowIndex: Integer; FVisibleColIndex: Integer; function GetBandIndex: Integer; function GetColIndex: Integer; function GetColumn: TcxTreeListColumn; function GetIsUpdating: Boolean; function GetRowIndex: Integer; function GetTreeList: TcxCustomTreeList; function GetVisibleBandIndex: Integer; function GetVisibleRowIndex: Integer; procedure SetBandIndex(AValue: Integer); procedure SetColIndex(AValue: Integer); procedure SetLineCount(AValue: Integer); procedure SetRow(AValue: TcxTreeListBandRow); procedure SetRowIndex(AValue: Integer); protected procedure Changed; virtual; function IsPositionChanged: Boolean; virtual; procedure Restore; virtual; procedure Store; virtual; property IsUpdating: Boolean read GetIsUpdating; 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); property Band: TcxTreeListBand read FBand; property Column: TcxTreeListColumn read GetColumn; property Row: TcxTreeListBandRow read FRow write SetRow; property TreeList: TcxCustomTreeList read GetTreeList; property VisibleBandIndex: Integer read GetVisibleBandIndex; property VisibleColIndex: Integer read FVisibleColIndex; property VisibleRowIndex: Integer read GetVisibleRowIndex; published property ColIndex: Integer read GetColIndex write SetColIndex; property LineCount: Integer read FLineCount write SetLineCount default 1; property RowIndex: Integer read GetRowIndex 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; FMultiLine: Boolean; FShowEndEllipsis: Boolean; FText: string; FOnChange: TNotifyEvent; procedure SetAlignHorz(AValue: TAlignment); procedure SetAlignVert(AValue: TcxAlignmentVert); procedure SetGlyph(AValue: TBitmap); procedure SetGlyphAlignHorz(AValue: TAlignment); procedure SetGlyphAlignVert(AValue: TcxAlignmentVert); procedure SetMultiLine(AValue: Boolean); procedure SetShowEndEllipsis(AValue: Boolean); procedure SetText(const AValue: string); protected procedure Changed; virtual; function GetText: string; virtual; function IsTextStored: Boolean; virtual; property OnChange: TNotifyEvent read FOnChange write FOnChange; public constructor Create(AOwner: TPersistent); override; 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 read FMultiLine write SetMultiLine default False; property ShowEndEllipsis: Boolean read FShowEndEllipsis write SetShowEndEllipsis default True; property Text: string read GetText write SetText stored IsTextStored; end; { TcxTreeListColumnOptions } TcxTreeListColumnOptions = class(TcxCustomEditContainerItemOptions) private FCellEndEllipsis: Boolean; FFooter: Boolean; FGroupFooter: Boolean; FHidden: Boolean; FSizing: Boolean; FVertSizing: Boolean; function GetColumn: TcxTreeListColumn; procedure SetCellEndEllipsis(AValue: Boolean); procedure SetFooter(AValue: Boolean); procedure SetGroupFooter(AValue: Boolean); procedure SetSizing(AValue: Boolean); procedure SetVertSizing(AValue: Boolean); protected procedure Changed; override; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; procedure RestoreDefaults; virtual; property Column: TcxTreeListColumn read GetColumn; published property CellEndEllipsis: Boolean read FCellEndEllipsis write SetCellEndEllipsis default True; property Footer: Boolean read FFooter write SetFooter default True; property GroupFooter: Boolean read FGroupFooter write SetGroupFooter default True; property Hidden: Boolean read FHidden write FHidden default False; property Sizing: Boolean read FSizing write SetSizing default True; property VertSizing: Boolean read FVertSizing write SetVertSizing default True; property Customizing; property Editing; property Focusing; property IncSearch; property Moving; property ShowEditButtons; property Sorting; property TabStop; end; { TcxTreeListSummaryItem } TcxTreeListSummaryItemGetTextEvent = procedure(Sender: TcxTreeListSummaryItem; const AValue: Variant; var AText: string) of object; TcxTreeListSummaryItem = class(TcxCustomDataSummaryItem) private FAbsoluteIndex: Integer; FAlignHorz: TAlignment; FAlignVert: TcxAlignmentVert; FAllNodes: Boolean; FCalculatedColumn: TcxTreeListColumn; FMultiLine: Boolean; FVisible: Boolean; FVisibleIndexInColumn: Integer; FOnGetText: TcxTreeListSummaryItemGetTextEvent; function GetCalculatedColumn: TcxTreeListColumn; function GetColumn: TcxTreeListColumn; function IsCalculatedColumnStored: Boolean; procedure SetAlignHorz(AValue: TAlignment); procedure SetAlignVert(AValue: TcxAlignmentVert); procedure SetAllNodes(AValue: Boolean); procedure SetCalculatedColumn(AValue: TcxTreeListColumn); procedure SetMultiLine(AValue: Boolean); procedure SetVisible(AValue: Boolean); protected procedure AssignValues(Source: TcxCustomDataSummaryItem); override; function GetDataController: TcxCustomDataController; override; function GetValueFormat(AValueType: TcxSummaryValueType; const AValue: Variant; AIsFooter: Boolean): string; override; procedure Notification(AComponent: TComponent; Operation: TOperation); public constructor Create(Collection: TCollection); override; function FormatValue(const AValue: Variant; AIsFooter: Boolean): string; override; property AbsoluteIndex: Integer read FAbsoluteIndex write FAbsoluteIndex; property Column: TcxTreeListColumn read GetColumn; property VisibleIndexInColumn: Integer read FVisibleIndexInColumn; published property AlignHorz: TAlignment read FAlignHorz write SetAlignHorz default taLeftJustify; property AlignVert: TcxAlignmentVert read FAlignVert write SetAlignVert default vaTop; property AllNodes: Boolean read FAllNodes write SetAllNodes default True; property CalculatedColumn: TcxTreeListColumn read GetCalculatedColumn write SetCalculatedColumn stored IsCalculatedColumnStored; property MultiLine: Boolean read FMultiLine write SetMultiLine default False; property Visible: Boolean read FVisible write SetVisible default True; property Format; property Kind; property OnGetText: TcxTreeListSummaryItemGetTextEvent read FOnGetText write FOnGetText; end; TcxTreeListSummaryItemClass = class of TcxTreeListSummaryItem; { TcxTreeListColumnSummary } TcxTreeListColumnSummary = class(TcxOwnedPersistent) private FFooterSummaryItems: TcxTreeListSummaryItems; FGroupFooterSummaryItems: TcxTreeListSummaryItems; function GetColumn: TcxTreeListColumn; function GetFooterVisibleCount: Integer; function GetGroupFooterVisibleCount: Integer; procedure SetFooterSummaryItems(AValue: TcxTreeListSummaryItems); procedure SetGroupFooterSummaryItems(AValue: TcxTreeListSummaryItems); protected procedure Changed(ARedrawOnly: Boolean); public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; property Column: TcxTreeListColumn read GetColumn; property FooterVisibleCount: Integer read GetFooterVisibleCount; property GroupFooterVisibleCount: Integer read GetGroupFooterVisibleCount; published property FooterSummaryItems: TcxTreeListSummaryItems read FFooterSummaryItems write SetFooterSummaryItems; property GroupFooterSummaryItems: TcxTreeListSummaryItems read FGroupFooterSummaryItems write SetGroupFooterSummaryItems; end; { TcxTreeListSummaryItems } TcxTreeListSummaryItems = class(TcxCollection) private FSummary: TcxTreeListColumnSummary; FVisibleCount: Integer; function GetColumn: TcxTreeListColumn; function GetItem(AIndex: Integer): TcxTreeListSummaryItem; procedure SetItem(AIndex: Integer; AValue: TcxTreeListSummaryItem); protected function GetOwner: TPersistent; override; procedure Update(Item: TCollectionItem); override; public constructor Create(ASummary: TcxTreeListColumnSummary; AItemClass: TcxTreeListSummaryItemClass); virtual; function Add: TcxTreeListSummaryItem; function GetItemByKind(AKind: TcxSummaryKind): TcxTreeListSummaryItem; property Column: TcxTreeListColumn read GetColumn; property Items[Index: Integer]: TcxTreeListSummaryItem read GetItem write SetItem; default; property Summary: TcxTreeListColumnSummary read FSummary; property VisibleCount: Integer read FVisibleCount; end; TcxTreeListColumnSummaryClass = class of TcxTreeListColumnSummary; { 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, IcxStoredObject) private FCaption: TcxTreeListCaption; FCalculatedWidth: Integer; FData: Integer; FHeaderCell: TcxTreeListColumnHeaderCellViewInfo; FMinWidth: Integer; FOnChangeName: TNotifyEvent; FPosition: TcxTreeListColumnPosition; FSortIndex: Integer; FSortOrder: TcxDataSortOrder; FSummary: TcxTreeListColumnSummary; FSummaryFooter: TPersistent; FVisible: Boolean; FWidth: Integer; FOnGetDisplayText: TcxTreeListOnGetDisplayTextEvent; // IcxStoredObject events FOnGetStoredProperties: TcxGetStoredPropertiesEvent; FOnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent; FOnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent; function GetActuallyVisible: Boolean; function GetDataController: TcxTreeListDataController; function GetDataBinding: TcxItemDataBinding; function GetDisplayText(ANode: TcxTreeListNode): string; function GetDisplayWidth: Integer; function GetEditingProperties: TcxTreeListGetEditPropertiesEvent; function GetEditProperties: TcxTreeListGetEditPropertiesEvent; function GetHasIndent: Boolean; function GetID: Integer; function GetIndentWidth: Integer; function GetIsFixed: Boolean; function GetIsHidden: Boolean; function GetIsLeft: Boolean; function GetIsPreview: Boolean; function GetIsRight: Boolean; function GetIsLoading: Boolean; function GetIsReading: Boolean; function GetIsUpdating: Boolean; function GetIsWidthStored: Boolean; function GetItemIndex: Integer; function GetOptions: TcxTreeListColumnOptions; function GetSortIndex: Integer; function GetStyles: TcxTreeListColumnStyles; function GetTreeList: TcxCustomTreeList; function GetValueByNode(ANode: TcxTreeListNode): Variant; function GetValueDef: TcxValueDef; function GetVisibleIndex: Integer; function GetWidth: Integer; procedure SetCaption(AValue: TcxTreeListCaption); procedure SetDataBinding(AValue: TcxItemDataBinding); procedure SetDisplayWidth(AValue: Integer); procedure SetEditingProperties(AValue: TcxTreeListGetEditPropertiesEvent); procedure SetEditProperties(AValue: TcxTreeListGetEditPropertiesEvent); procedure SetIsPreview(AValue: Boolean); procedure SetItemIndex(AValue: Integer); procedure SetMinWidth(AValue: Integer); procedure SetOptions(AValue: TcxTreeListColumnOptions); procedure SetPosition(AValue: TcxTreeListColumnPosition); procedure SetSortIndex(AValue: Integer); procedure SetSortOrder(AValue: TcxDataSortOrder); procedure SetStyles(AValue: TcxTreeListColumnStyles); procedure SetSummary(AValue: TcxTreeListColumnSummary); procedure SetSummaryFooter(AValue: TPersistent); procedure SetValueByNode(ANode: TcxTreeListNode; const AValue: Variant); procedure SetVisible(AValue: Boolean); procedure SetWidth(AValue: Integer); protected //editing function CanEdit: Boolean; override; function GetEditValue: Variant; override; function CanInitEditing: Boolean; override; procedure AssignWidth; procedure CancelSorting; function CanFocus: Boolean; override; function CanMoving: Boolean; virtual; function CanSort: Boolean; virtual; procedure ChangeCaption(Sender: TObject); virtual; procedure Changed; override; procedure ForceWidth(AWidth: Integer); function GetHeaderFooterBestfitSize: Integer; virtual; function GetOptionsClass: TcxCustomEditContainerItemOptionsClass; override; function GetRealSortOrder: TcxDataSortOrder; virtual; function GetStylesClass: TcxEditContainerStylesClass; override; function GetSummaryClass: TcxTreeListColumnSummaryClass; virtual; procedure SetEditingControl(Value: TcxEditingControl); override; procedure SetName(const Value: TComponentName); override; procedure SetParentComponent(Value: TComponent); override; // 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; // 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 ChangeSortOrder(ASortOrder: TcxDataSortOrder; AShift: TShiftState); procedure ConvertOldFooterSummaries; 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; function GetCellHeight(ANode: TcxTreeListNode; AWidth, ALines: Integer; AFont: TFont; const AValue: Variant): Integer; function GetPositionClass: TcxTreeListColumnPositionClass; virtual; function HasDataTextHandler: Boolean; override; procedure InitAutoWidthItem(AItem: TcxAutoWidthItem); virtual; procedure SetCurrentValue(const Value: Variant); override; property Data: Integer read FData write FData; property DataController: TcxTreeListDataController read GetDataController; property HasIndent: Boolean read GetHasIndent; property HeaderCell: TcxTreeListColumnHeaderCellViewInfo read FHeaderCell; property ID: Integer read GetID; property IsFixed: Boolean read GetIsFixed; property IsLoading: Boolean read GetIsLoading; property IsReading: Boolean read GetIsReading; property IsUpdating: Boolean read GetIsUpdating; property ValueDef: TcxValueDef read GetValueDef; 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 ActuallyVisible: Boolean read GetActuallyVisible; property DisplayTexts[ANode: TcxTreeListNode]: string read GetDisplayText; property DisplayWidth: Integer read GetDisplayWidth write SetDisplayWidth; property IndentWidth: Integer read GetIndentWidth; property IsHidden: Boolean read GetIsHidden; property IsLeft: Boolean read GetIsLeft; property IsPreview: Boolean read GetIsPreview write SetIsPreview; property IsRight: Boolean read GetIsRight; property PropertiesValue; property TreeList: TcxCustomTreeList read GetTreeList; property VisibleIndex: Integer read GetVisibleIndex; property Editing; property EditValue; property Focused; property ItemIndex read GetItemIndex write SetItemIndex; property Value; property ValueCount; property Values[ANode: TcxTreeListNode]: Variant read GetValueByNode write SetValueByNode; published property SummaryFooter: TPersistent read FSummaryFooter write SetSummaryFooter stored False; property Visible: Boolean read FVisible 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 SetSortOrder default soNone; property SortIndex: Integer read GetSortIndex write SetSortIndex default -1; property Styles: TcxTreeListColumnStyles read GetStyles write SetStyles; property Summary: TcxTreeListColumnSummary read FSummary write SetSummary; property OnGetDisplayText: TcxTreeListOnGetDisplayTextEvent read FOnGetDisplayText write FOnGetDisplayText; property OnGetEditingProperties: TcxTreeListGetEditPropertiesEvent read GetEditingProperties write SetEditingProperties; property OnGetEditProperties: TcxTreeListGetEditPropertiesEvent read GetEditProperties write SetEditProperties; // IcxStoredObject events property OnGetStoredProperties: TcxGetStoredPropertiesEvent read FOnGetStoredProperties write FOnGetStoredProperties; property OnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent read FOnGetStoredPropertyValue write FOnGetStoredPropertyValue; property OnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent read FOnSetStoredPropertyValue write FOnSetStoredPropertyValue; property PropertiesClassName; property Properties; property PropertiesEvents; property RepositoryItem; end; TcxTreeListColumnClass = class of TcxTreeListColumn; { TcxTreeListSizingDragAndDropObject } TcxTreeListSizingDragAndDropObject = class(TcxSizingDragAndDropObject) private FOffset: TPoint; FDragItem: TObject; protected procedure BeginDragAndDrop; override; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override; function GetSizingMarkBounds: TRect; override; end; { TcxTreeListDragAndDropObject } TcxTreeListDropInfo = class public Accepted: Boolean; Band: TcxTreeListBand; ColIndex: Integer; Customizing: Boolean; DropPos: TPoint; Position: TcxPosition; end; TcxTreeListDragAndDropObject = class(TcxCustomControlDragAndDropObject) private FArrows: TcxPlaceArrows; FDropInfo: TcxTreeListDropInfo; function DrawArrowsNeeded: Boolean; function GetBands: TcxTreeListBands; function GetCustomizing: Boolean; function GetDestBand: TcxTreeListBand; function GetDragHeader: TcxTreeListHeaderCellViewInfo; function GetDropPosition: TcxPosition; function GetHitTest: TcxTreeListHitTest; function GetOptionsCustomize: TcxTreeListOptionsCustomizing; function GetPainter: TcxTreeListPainter; function GetTreeList: TcxCustomTreeList; function GetViewInfo: TcxTreeListViewInfo; protected FOrigin: TPoint; procedure BeginDragAndDrop; override; procedure ChangeArrowsPosition; function CanCustomize: Boolean; virtual; abstract; function CanDrop: Boolean; virtual; abstract; function CanRemove: Boolean; virtual; abstract; function CheckInCustomizing(const APoint: TPoint): Boolean; procedure CheckDragPosition; virtual; abstract; function CreateDropInfo: TcxTreeListDropInfo; virtual; procedure DragAndDrop(const P: TPoint; var Accepted: Boolean); override; function Drop: Boolean; virtual; abstract; procedure EndDragAndDrop(Accepted: Boolean); override; function GetArrowAreaBounds: TRect; virtual; function GetDisplayRect: TRect; override; function GetDragAndDropCursor(Accepted: Boolean): TCursor; override; procedure InitDropInfo(const P: TPoint); virtual; procedure InitializeScrollArea(const Area: TRect); virtual; procedure MakeCustomizingPageVisible; virtual; abstract; procedure Paint; override; public constructor Create(AControl: TcxControl); override; destructor Destroy; override; property Arrows: TcxPlaceArrows read FArrows; property Bands: TcxTreeListBands read GetBands; property Customizing: Boolean read GetCustomizing; property DestBand: TcxTreeListBand read GetDestBand; property DragHeader: TcxTreeListHeaderCellViewInfo read GetDragHeader; property DropInfo: TcxTreeListDropInfo read FDropInfo; property DropPosition: TcxPosition read GetDropPosition; property HitTest: TcxTreeListHitTest read GetHitTest; property OptionsCustomizing: TcxTreeListOptionsCustomizing read GetOptionsCustomize; property Painter: TcxTreeListPainter read GetPainter; property TreeList: TcxCustomTreeList read GetTreeList; property ViewInfo: TcxTreeListViewInfo read GetViewInfo; end; { TcxTreeListDragAndDropBandObject } TcxTreeListDragAndDropBandObject = class(TcxTreeListDragAndDropObject) private procedure AfterDropPositionChange; procedure BeforeDropPositionChange; function GetBand: TcxTreeListBand; function GetDropColIndex: Integer; function GetDropParentBandIndex: Integer; protected function CanCustomize: Boolean; override; function CanDrop: Boolean; override; function CanRemove: Boolean; override; function CheckBandInsertAt(ABand: TcxTreeListBand): Boolean; procedure CheckDragPosition; override; function Drop: Boolean; override; function GetBoundsForInsert(ABand: TcxTreeListBand): TRect; procedure MakeCustomizingPageVisible; override; public property Band: TcxTreeListBand read GetBand; end; { TcxTreeListDragAndDropColumnObject } TcxTreeListColumnDropInfo = class(TcxTreeListDropInfo) public Area: TRect; Column: TcxTreeListColumn; RowIndex: Integer; InsertRow: Boolean; end; TcxTreeListDragAndDropColumnObject = class(TcxTreeListDragAndDropObject) private function GetColumn: TcxTreeListColumn; function GetDropInfo: TcxTreeListColumnDropInfo; protected function CanCustomize: Boolean; override; function CanDrop: Boolean; override; procedure CheckDropColumnIndex(ARow: TcxTreeListBandRow; var AColIndex: Integer); function CanRemove: Boolean; override; function ChangeColumnOnly: Boolean; function CheckBandDropArea(ABand: TcxTreeListBand): Boolean; procedure CheckDragPosition; override; function CreateDropInfo: TcxTreeListDropInfo; override; function Drop: Boolean; override; function GetArrowAreaBounds: TRect; override; procedure InitDropInfoFromColumn(AColumn: TcxTreeListColumn); procedure MakeCustomizingPageVisible; override; public property Column: TcxTreeListColumn read GetColumn; property DropInfo: TcxTreeListColumnDropInfo read GetDropInfo; end; { TcxTreeListCellNavigator } TcxTreeListCellNavigator = class(TcxCustomCellNavigator) private FColumnChanged: Boolean; FCurrentNavigationColumn: TcxTreeListColumn; function GetCellIndex(AColumn: TcxTreeListColumn; ARow: TcxTreeListBandRow): Integer; function GetController: TcxTreeListController; function GetFocusedNode: TcxTreeListNode; function GetTreeList: TcxCustomTreeList; 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; function GetNode(ARowIndex: Integer): TcxTreeListNode; procedure Init(var ARowIndex, ACellIndex, ARowCount: Integer); override; function IsGroupRow(ARowIndex: Integer): Boolean; procedure SaveCurrentNavigationColumn; procedure SetFocusCell(ARowIndex, ACellIndex: Integer; AShift: TShiftState); override; public procedure FocusNextCell(AForward, ANextRow: Boolean; AShift: TShiftState = []); override; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure Refresh; override; property Controller: TcxTreeListController read GetController; property TreeList: TcxCustomTreeList read GetTreeList; property FocusedNode: TcxTreeListNode read GetFocusedNode; end; { TcxTreeListPopup } TcxTreeListPopup = class(TcxCustomPopupWindow) private FOwner: TcxTreeListIndicatorCellViewInfo; function GetTreeList: TcxCustomTreeList; procedure SetOwner(AValue: TcxTreeListIndicatorCellViewInfo); protected function CalculateOwnerBounds: TRect; virtual; procedure CreateListBox; virtual; abstract; function GetClientMinWidth: Integer; virtual; procedure InitPopup; override; function NeedIgnoreMouseMessageAfterCloseUp(AWnd: THandle; AMsg: Cardinal; AShift: TShiftState; const APos: TPoint): Boolean; override; procedure Paint; override; procedure VisibleChanged; override; public constructor Create(AOwnerControl: TWinControl); override; procedure Popup; reintroduce; virtual; property BorderWidths; property TreeList: TcxCustomTreeList read GetTreeList; property ClientMinWidth: Integer read GetClientMinWidth; property Owner: TcxTreeListIndicatorCellViewInfo read FOwner write SetOwner; end; { TcxTreeListCustomizationPopup } TcxTreeListCustomizationPopup = class(TcxTreeListPopup) private FCheckListBox: TcxCheckListBox; procedure CheckListBoxClick(Sender: TObject); procedure CheckListBoxCheckClick(Sender: TObject; AIndex: Integer; APrevState, ANewState: TcxCheckBoxState); procedure CheckListBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure CheckListBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); protected procedure AddCheckListBoxItems; virtual; abstract; procedure AdjustCheckListBoxSize(AFixedHeight: Boolean = False); virtual; procedure CheckClicked(AIndex: Integer; AChecked: Boolean); virtual; procedure CreateListBox; override; function GetCheckListBoxColumnWidth: Integer; virtual; procedure GetCheckListBoxSelectedItems(AItems: TList); function GetDropDownCount: Integer; virtual; abstract; procedure InitPopup; override; procedure ItemClicked(AItem: TObject; AChecked: Boolean); virtual; abstract; procedure RefreshCheckListBoxItems; procedure SetCheckListBoxSelectedItems(AItems: TList); property CheckListBoxColumnWidth: Integer read GetCheckListBoxColumnWidth; public procedure CloseUp; override; procedure CorrectBoundsWithDesktopWorkArea(var APosition: TPoint); override; property CheckListBox: TcxCheckListBox read FCheckListBox; end; { TcxTreeListColumnsCustomizationPopup } TcxTreeListColumnsCustomizationPopup = class(TcxTreeListCustomizationPopup) protected procedure AddCheckListBoxItems; override; function GetDropDownCount: Integer; override; procedure ItemClicked(AItem: TObject; AChecked: Boolean); override; end; { TcxTreeListBandsCustomizationPopup } TcxTreeListBandsCustomizationPopup = class(TcxTreeListCustomizationPopup) protected procedure AddCheckListBoxItems; override; function GetDropDownCount: Integer; override; procedure ItemClicked(AItem: TObject; AChecked: Boolean); override; end; TcxTreeListEditingController = class(TcxEditingController) end; { TcxTreeListController } TcxTreeListController = class(TcxCustomControlController) private FBandsCustomizationPopup: TcxTreeListBandsCustomizationPopup; FClickedObject: TObject; FColumnsCustomizationPopup: TcxTreeListColumnsCustomizationPopup; FDragDropInProcess: Boolean; FFocusedNode: TcxTreeListNode; FFocusedNodeIndex: Integer; FForcingWidthBand: TcxTreeListBand; FForcingWidthColumn: TcxTreeListColumn; FHotTrackColumn: TcxTreeListColumn; FHotTrackNode: TcxTreeListNode; FHotTrackShift: TShiftState; FIncSearchNode: TcxTreeListNode; FIncSearchText: string; FPressedHeader: TcxTreeListCustomHeaderCellViewInfo; FPrevFocusedNode: TcxTreeListNode; FResizeDirection: TcxDragSizingDirection; FSearchNotification: Boolean; FSelectionAnchor: TcxTreeListNode; function GetBandsCustomizationPopup: TcxTreeListBandsCustomizationPopup; function GetColumnsCustomizationPopup: TcxTreeListColumnsCustomizationPopup; function GetDataController: TcxTreeListDataController; function GetEditingController: TcxTreeListEditingController; function GetFocusedNodeIndex: Integer; function GetHitTest: TcxTreeListHitTest; function GetIsDragCopy: Boolean; function GetOptionsBehavior: TcxTreeListOptionsBehavior; function GetOptionsSelection: TcxTreeListOptionsSelection; function GetSelection: TList; function GetSelectionAnchor: TcxTreeListNode; function GetTreeList: TcxCustomTreeList; procedure SetForcingWidthColumn(AColumn: TcxTreeListColumn); procedure SetIncSearchNode(ANode: TcxTreeListNode); procedure SetPressedHeader(AHeader: TcxTreeListCustomHeaderCellViewInfo); protected DragNodesList: TList; DragNode: TcxTreeListNode; PrevCursor: TCursor; // 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 CheckFocusedNodeItem; procedure ChangeFocusedNode(ANode: TcxTreeListNode); virtual; function GetFocusedRecordIndex: Integer; override; procedure SetFocusedNode(ANode: TcxTreeListNode); virtual; procedure SetFocusedNodeItem(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn); virtual; procedure SetFocusedRecordIndex(Value: Integer); override; // Drag drop procedure BeforeStartDrag; override; function CreateAutoScrollObject(Kind: TScrollBarKind; const ARect: TRect; ACode: TScrollCode): TcxAutoScrollingObject; 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 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 IsKeyForController(AKey: Word; AShift: TShiftState): Boolean; override; function IsNodeKeyHandle(ANode: TcxTreeListNode; var AKey: Word; Shift: TShiftState): Boolean; 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; // incremental search 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 GetNextNodeForIncSearch(ANode: TcxTreeListNode; AGoForward: Boolean): TcxTreeListNode; procedure CheckLocate(AFound: Boolean); procedure SearchLocate(AItem: TcxCustomInplaceEditContainer; const AValue: string); override; procedure SearchLocateNext(AItem: TcxCustomInplaceEditContainer; AForward: Boolean); override; // design selection 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; AShift: TShiftState); virtual; procedure SelectRange(const AStartNode, AFinishNode: TcxTreeListNode); procedure ViewInfoChanged; override; property DataController: TcxTreeListDataController read GetDataController; property EditingController: TcxTreeListEditingController read GetEditingController; property SearchNotification: Boolean read FSearchNotification write FSearchNotification; public procedure AfterPaint; override; procedure BeginDragAndDrop; override; function CanDrag(X, Y: Integer): Boolean; override; function CanDeleteSelection: Boolean; function CanInsertNode: Boolean; function CanSelectNode(ANode: TcxTreeListNode): Boolean; function CheckCustomizationPopup: Boolean; procedure CheckDeletedNode(ANode: TcxTreeListNode); procedure CheckFocusedNode; procedure CheckHeaderClick(AShift: TShiftState); procedure CheckNodeContentClick(Shift: TShiftState); procedure DblClick; override; function DeleteConfirmation: Boolean; function DoHeaderMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): Boolean; virtual; function DoNodeMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer): Boolean; virtual; procedure DoMouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure DoMouseMove(Shift: TShiftState; X, Y: Integer); override; procedure DoMouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; procedure EndDragAndDrop(Accepted: Boolean); override; function FindNearestFocusableNode(AVisibleIndex: Integer): TcxTreeListNode; function FindNearestFocusableColumn(AVisibleIndex: Integer): TcxTreeListColumn; function HitAtNodeContent: Boolean; function GetCursor(X, Y: Integer): TCursor; override; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; procedure KeyDown(var Key: Word; Shift: TShiftState); override; procedure KeyUp(var Key: Word; Shift: TShiftState); override; procedure MakeFocusedItemVisible; override; procedure MakeFocusedRecordVisible; override; procedure Reset; virtual; procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; procedure SetSelection(AList: TList); procedure SetFocusedRecordItem(ARecordIndex: Integer; AItem: TcxCustomInplaceEditContainer); override; procedure SetHotTrackCursor(ACursor: TCursor); procedure SetHotTrackNode(ANode: TcxTreeListNode; AShift: TShiftState); procedure ShowEdit(AShift: TShiftState; X, Y: Integer); function StartDragAndDrop(const P: TPoint): Boolean; override; procedure UpdateHotTrackNode(AShift: TShiftState); overload; procedure UpdateHotTrackNode(X, Y: Integer; AShift: TShiftState); overload; property BandsCustomizationPopup: TcxTreeListBandsCustomizationPopup read GetBandsCustomizationPopup; property ClickedObject: TObject read FClickedObject write FClickedObject; property ColumnsCustomizationPopup: TcxTreeListColumnsCustomizationPopup read GetColumnsCustomizationPopup; property DragDropInProcess: Boolean read FDragDropInProcess write FDragDropInProcess; property FocusedNode: TcxTreeListNode read FFocusedNode write SetFocusedNode; property FocusedNodeIndex: Integer read GetFocusedNodeIndex write FFocusedNodeIndex; property ForcingWidthBand: TcxTreeListBand read FForcingWidthBand write FForcingWidthBand; property ForcingWidthColumn: TcxTreeListColumn read FForcingWidthColumn write SetForcingWidthColumn; property HitTest: TcxTreeListHitTest read GetHitTest; property HotTrackColumn: TcxTreeListColumn read FHotTrackColumn write FHotTrackColumn; property HotTrackNode: TcxTreeListNode read FHotTrackNode write FHotTrackNode; property HotTrackShift: TShiftState read FHotTrackShift write FHotTrackShift; property IncSearchNode: TcxTreeListNode read FIncSearchNode write SetIncSearchNode; property IncSearchText: string read FIncSearchText write FIncSearchText; property IsDragCopy: Boolean read GetIsDragCopy; property OptionsBehavior: TcxTreeListOptionsBehavior read GetOptionsBehavior; property OptionsSelection: TcxTreeListOptionsSelection read GetOptionsSelection; property PressedHeader: TcxTreeListCustomHeaderCellViewInfo read FPressedHeader write SetPressedHeader; property PrevFocusedNode: TcxTreeListNode read FPrevFocusedNode; property Selection: TList read GetSelection; property SelectionAnchor: TcxTreeListNode read GetSelectionAnchor write FSelectionAnchor; property TreeList: TcxCustomTreeList read GetTreeList; end; { TcxTreeListHitTest } TcxTreeListHitTest = class(TcxCustomHitTestController) private FDragItem: TObject; FHitBand: TcxTreeListBand; FHitColumn: TcxTreeListColumn; FHitNode: TcxTreeListNode; function GetHitAtImages: Boolean; function GetHitAtFooterArea: Boolean; function GetHitAtHeader: Boolean; function GetHitCell: TcxCustomViewInfoItem; function GetTreeList: TcxCustomTreeList; function GetViewInfo: TcxTreeListViewInfo; protected function AllowDesignMouseEvents(X, Y: Integer; AShift: TShiftState): Boolean; override; function CanShowHint(AItem: TObject): Boolean; override; procedure CheckFooterColumn; procedure CheckSelection(AShift: TShiftState); virtual; procedure DoCalculate; override; function GetCurrentCursor: TCursor; override; function GetState(Index: Integer): Boolean; procedure SetHitState(Index: Integer; Value: Boolean); property DragItem: TObject read FDragItem write FDragItem; property HitAtFooterArea: Boolean read GetHitAtFooterArea; property HitAtHeader: Boolean read GetHitAtHeader; property ViewInfo: TcxTreeListViewInfo read GetViewInfo; public function CanMoving: Boolean; virtual; function CanSizing: Boolean; virtual; property Cursor: TCursor read GetCurrentCursor; property HitAtBackground: Boolean index tlhc_HitAtBackground read GetState; property HitAtBand: Boolean index tlhc_HitAtBand read GetState; property HitAtBandContainer: Boolean index tlhc_HitAtBandContainer read GetState; property HitAtBandCustomizing: Boolean index tlhc_HitAtBandCustomizing read GetState; property HitAtBandHeader: Boolean index tlhc_HitAtBandHeader read GetState; property HitAtButton: Boolean index tlhc_HitAtButton read GetState; property HitAtCheckButton: Boolean index tlhc_HitAtCheckButton read GetState; property HitAtColumn: Boolean index tlhc_HitAtColumn read GetState; property HitAtColumnCustomizing: Boolean index tlhc_HitAtColumnCustomizing 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 HitAtGroupFooter: Boolean index tlhc_HitAtGroupFooter read GetState; property HitAtGroupFooterItem: Boolean index tlhc_HitAtGroupFooterItem 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 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 HitAtStateImage: Boolean index tlhc_HitAtStateImage read GetState; property HitBand: TcxTreeListBand read FHitBand; property HitCell: TcxCustomViewInfoItem read GetHitCell; property HitColumn: TcxTreeListColumn read FHitColumn; property HitNode: TcxTreeListNode read FHitNode; property TreeList: TcxCustomTreeList read GetTreeList; end; { TcxTreeListHitTestArea } TcxTreeListHitTestArea = class private FArea: TRect; FLink: TcxTreeListCustomCellViewInfo; protected procedure Calculate; virtual; abstract; function GetHitTest(AHitTest: TcxTreeListHitTest): Boolean; virtual; procedure InitHitTest(AHitTest: TcxTreeListHitTest); virtual; abstract; public constructor Create(ALink: TcxTreeListCustomCellViewInfo); virtual; property Area: TRect read FArea write FArea; property Link: TcxTreeListCustomCellViewInfo read FLink; end; { TcxTreeListHeaderSizingArea } TcxTreeListHeaderSizingArea = class(TcxTreeListHitTestArea) private FDirection: TcxDragSizingDirection; protected procedure Calculate; override; procedure InitHitTest(AHitTest: TcxTreeListHitTest); override; public constructor CreateEx(ALink: TcxTreeListCustomCellViewInfo; ADirection: TcxDragSizingDirection); property Direction: TcxDragSizingDirection read FDirection; end; { TcxTreeListNodeSizingArea } TcxTreeListNodeSizingArea = class(TcxTreeListHitTestArea) protected procedure Calculate; override; function GetHitTest(AHitTest: TcxTreeListHitTest): Boolean; override; procedure InitHitTest(AHitTest: TcxTreeListHitTest); override; public constructor Create(ALink: TcxTreeListCustomCellViewInfo); override; destructor Destroy; override; end; { TcxTreeListCustomCellViewInfo } TcxTreeListSeparators = array[0..1] of TRect; TcxTreeListCustomCellViewInfo = class(TcxCustomViewInfoItem, IUnknown) private function GetExtPaintStyle: Boolean; function GetHitTestController: TcxTreeListHitTest; function GetOptionsView: TcxTreeListOptionsView; function GetStyles: TcxTreeListStyles; function GetTreeList: TcxCustomTreeList; function GetVisibleRect: TRect; protected FAttachNode: TcxTreeListNode; FBorderColor: TColor; FBorders: TcxBorders; FNode: TcxTreeListNode; procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; function CellHasOrigin: Boolean; virtual; function GetCellOrigin: TPoint; virtual; function GetClipRect: TRect; function GetControl: TcxEditingControl; override; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; procedure SetBounds(const ABounds, AVisibleBounds: TRect); procedure SetHitTestCodes(const ACodes: array of Integer); function GetSelected: Boolean; virtual; // IUnknown function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; property AttachNode: TcxTreeListNode read FAttachNode; property HitTest: TcxTreeListHitTest read GetHitTestController; property OptionsView: TcxTreeListOptionsView read GetOptionsView; property Selected: Boolean read GetSelected; property Styles: TcxTreeListStyles read GetStyles; public constructor CreateEx(ATreeList: TcxCustomTreeList; const ABounds, AVisibleRect: TRect); virtual; property BorderColor: TColor read FBorderColor write FBorderColor; property Borders: TcxBorders read FBorders; property ExtPaintStyle: Boolean read GetExtPaintStyle; property Node: TcxTreeListNode read FNode; property TreeList: TcxCustomTreeList read GetTreeList; property VisibleRect: TRect read GetVisibleRect; end; { TcxTreeListBackgroundCellViewInfo } TcxTreeListBackgroundCellViewInfo = class(TcxTreeListCustomCellViewInfo) protected function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; procedure Scroll(const DX, DY: Integer); override; public class function CustomDrawID: Integer; override; end; { TcxTreeListFooterCellViewInfo } TcxTreeListFooterCellViewInfo = class(TcxTreeListCustomCellViewInfo, IcxHotTrackElement) private FColumn: TcxTreeListColumn; FHidden: Boolean; FText: string; function GetShowEndEllipsis: Boolean; protected procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; procedure DrawText(ACanvas: TcxCanvas); virtual; function GetAlignHorz: TAlignment; virtual; function GetAlignVert: TcxAlignmentVert; virtual; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; function GetItem: TcxTreeListSummaryItem; virtual; function GetMultiline: Boolean; virtual; procedure Initialize(ANode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn); virtual; procedure Scroll(const DX, DY: Integer); override; // 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); public constructor CreateEx(ATreeList: TcxCustomTreeList; const ABounds, AVisibleRect: TRect); override; class function CustomDrawID: Integer; override; property AlignHorz: TAlignment read GetAlignHorz; property AlignVert: TcxAlignmentVert read GetAlignVert; property AttachNode; property Column: TcxTreeListColumn read FColumn; property Hidden: Boolean read FHidden; property MultiLine: Boolean read GetMultiLine; property ShowEndEllipsis: Boolean read GetShowEndEllipsis; property Text: string read FText; property TreeList; end; { TcxTreeListFooterSingleCellViewInfo } TcxTreeListFooterSingleCellViewInfo = class(TcxTreeListFooterCellViewInfo) private FSummaryItem: TcxTreeListSummaryItem; protected function GetItem: TcxTreeListSummaryItem; override; function GetSelected: Boolean; override; procedure Initialize(ANode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn; ASummaryItem: TcxTreeListSummaryItem); reintroduce; overload; public property SummaryItem: TcxTreeListSummaryItem read FSummaryItem; end; { TcxTreeListFooterMultiItemsCellViewInfo } TcxTreeListFooterMultiItemsCellViewInfo = class(TcxTreeListFooterCellViewInfo) private FNeedShowHint: Boolean; FSummaryItems: TcxTreeListSummaryItems; FHintRect: TRect; FVisibleCount: Integer; function GetSeparator: string; protected function CanDifferentStyles: Boolean; procedure DrawText(ACanvas: TcxCanvas); override; function GetAlignHorz: TAlignment; override; function GetAlignVert: TcxAlignmentVert; override; function GetItem: TcxTreeListSummaryItem; override; function GetSelected: Boolean; override; procedure Initialize(ADataNode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn; ASummaryItems: TcxTreeListSummaryItems); reintroduce; overload; function IsNeedHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; override; public property Separator: string read GetSeparator; property SummaryItems: TcxTreeListSummaryItems read FSummaryItems; property VisibleCount: Integer read FVisibleCount; end; { TcxTreeListCustomHeaderCellViewInfo } TcxTreeListCustomHeaderCellViewInfo = class(TcxTreeListCustomCellViewInfo, IcxHotTrackElement) private FIsLast: Boolean; FNeighbors: TcxNeighbors; FState: TcxButtonState; FTextBounds: TRect; function GetHotTrack: Boolean; function GetPressed: Boolean; procedure SetHotTrack(AValue: Boolean); procedure SetPressed(AValue: Boolean); procedure SetState(AValue: TcxButtonState); protected BordersMargins: TRect; function CanNeighborFor(ACandidate: TcxTreeListHeaderCellViewInfo): Boolean; virtual; procedure CheckClipping(const ADisplayRect, AAvailableRect: TRect); override; function CheckNeighbors(ACandidate: TcxTreeListHeaderCellViewInfo; AShift: Integer): Boolean; virtual; procedure Click; virtual; procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetAlignHorz: TAlignment; virtual; function GetAlignVert: TcxAlignmentVert; virtual; function GetIsVisible: Boolean; virtual; function GetMultiline: Boolean; virtual; function GetShowEndEllipsis: Boolean; virtual; function GetText: string; virtual; // 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); public constructor CreateEx(ATreeList: TcxCustomTreeList; const ABounds, AVisibleRect: TRect); override; property HotTrack: Boolean read GetHotTrack write SetHotTrack; property IsLast: Boolean read FIsLast; property MultiLine: Boolean read GetMultiLine; property Neighbors: TcxNeighbors read FNeighbors; property Pressed: Boolean read GetPressed write SetPressed; property State: TcxButtonState read FState write SetState; property TextBounds: TRect read FTextBounds; end; { TcxTreeListIndicatorCellViewInfo } TcxTreeListIndicatorPosition = (tlipBands, tlipColumns, tlipContent, tlipFooter); TcxTreeListIndicatorCellViewInfo = class(TcxTreeListCustomHeaderCellViewInfo) private FKind: TcxIndicatorKind; FPosition: TcxTreeListIndicatorPosition; FSizingArea: TcxTreeListNodeSizingArea; procedure SetKind(AValue: TcxIndicatorKind); protected function ActualIndicatorKind: TcxIndicatorKind; procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; function GetPopup: TcxTreeListCustomizationPopup; procedure Initialize(ANode: TcxTreeListNode; APosition: TcxTreeListIndicatorPosition); virtual; function IsQuickCustomizationEnabled: Boolean; procedure Scroll(const DX, DY: Integer); override; procedure ShowPopup; function ClosePopupWhenNilOwner: Boolean; function GetOwnerBounds: TRect; procedure PopupClosed; property SizingArea: TcxTreeListNodeSizingArea read FSizingArea write FSizingArea; public destructor Destroy; override; class function CustomDrawID: Integer; override; property Kind: TcxIndicatorKind read FKind write SetKind; property Position: TcxTreeListIndicatorPosition read FPosition; end; { TcxTreeListHeaderCellViewInfo } TcxTreeListHeaderCellViewInfo = class(TcxTreeListCustomHeaderCellViewInfo, IcxDragSizing) private FCaption: TcxTreeListCaption; FGlyphPosition: TPoint; FItem: TPersistent; FSortMarkBounds: TRect; function GetDragSizing: IcxDragSizing; function GetGlyph: TBitmap; function GetGlyphAlignHorz: TAlignment; function GetGlyphAlignVert: TcxAlignmentVert; protected FHintCalculated: Boolean; GlyphClipping: Boolean; procedure DoCalculate; override; procedure DoCalculateGlyphPosition; procedure DoDraw(ACanvas: TcxCanvas); override; function GetAlignHorz: TAlignment; override; function GetAlignVert: TcxAlignmentVert; override; function GetFixed: Boolean; virtual; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; function GetMultiline: Boolean; override; function GetSelected: Boolean; override; function GetShowEndEllipsis: Boolean; override; function GetSortOrder: TcxDataSortOrder; virtual; function GetText: string; override; procedure Initialize(ACaption: TcxTreeListCaption); procedure Scroll(const DX, DY: Integer); override; procedure SetHitItem; virtual; property DragSizing: IcxDragSizing read GetDragSizing implements IcxDragSizing; property Item: TPersistent read FItem; public property AlignHorz: TAlignment read GetAlignHorz; property AlignVert: TcxAlignmentVert read GetAlignVert; property Fixed: Boolean read GetFixed; property Glyph: TBitmap read GetGlyph; property GlyphAlignHorz: TAlignment read GetGlyphAlignHorz; property GlyphAlignVert: TcxAlignmentVert read GetGlyphAlignVert; property GlyphPosition: TPoint read FGlyphPosition; property ShowEndEllipsis: Boolean read GetShowEndEllipsis; property SortMarkBounds: TRect read FSortMarkBounds; property SortOrder: TcxDataSortOrder read GetSortOrder; property Text: string read GetText; property TextBounds; property TreeList; end; { TcxTreeListBandHeaderCellViewInfo } TcxTreeListBandHeaderCellViewInfo = class(TcxTreeListHeaderCellViewInfo) private function GetBand: TcxTreeListBand; protected procedure Click; override; procedure DoCalculate; override; function GetFixed: Boolean; override; function GetIsVisible: Boolean; override; procedure SetHitItem; override; public class function CustomDrawID: Integer; override; property Band: TcxTreeListBand read GetBand; end; { TcxTreeListColumnHeaderCellViewInfo } TcxTreeListColumnHeaderCellViewInfo = class(TcxTreeListHeaderCellViewInfo) private function GetBand: TcxTreeListBand; function GetColumn: TcxTreeListColumn; protected procedure Click; override; procedure DoCalculate; override; function GetFixed: Boolean; override; function GetIsVisible: Boolean; override; function GetSortOrder: TcxDataSortOrder; override; procedure SetHitItem; override; public class function CustomDrawID: Integer; override; property Band: TcxTreeListBand read GetBand; property Column: TcxTreeListColumn read GetColumn; end; { TcxTreeListBandCellViewInfo } TcxTreeListBandPart = (tlbpHeader, tlbpContent, tlbpGroupFooter, tlbpFooter, tlbpSeparator); TcxTreeListBandCellViewInfo = class(TcxTreeListCustomCellViewInfo) private FBand: TcxTreeListBand; FPart: TcxTreeListBandPart; protected procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; procedure Initialize(ABand: TcxTreeListBand; ANode, AAttachNode: TcxTreeListNode; APart: TcxTreeListBandPart); procedure Scroll(const DX, DY: Integer); override; public class function CustomDrawID: Integer; override; property Band: TcxTreeListBand read FBand; property Part: TcxTreeListBandPart read FPart; property AttachNode; end; { TcxTreeListEditCellViewInfo } TcxTreeListEditCellViewInfo = class(TcxEditCellViewInfo) private FBorderColor: TColor; FNodeViewData: TcxTreeListNodeViewData; function GetBand: TcxTreeListBand; function GetEditing: Boolean; function GetNode: TcxTreeListNode; function GetOptionsView: TcxTreeListOptionsView; function GetTreeList: TcxCustomTreeList; protected function ContentOffset: TRect; override; procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; function GetButtonTransparency: TcxEditButtonTransparency; override; function GetCellOrg: TPoint; override; function GetColumn: TcxTreeListColumn; virtual; function GetDisplayValue: Variant; override; function GetEditRect: TRect; override; function GetEditViewParams: TcxViewParams; override; function GetFocused: Boolean; override; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; function GetHotTrack: Boolean; virtual; function GetIncSearchParams: TcxViewParams; // IcxHotTrackElement function GetOrigin: TPoint; override; function IsNeedHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; override; function GetRecordIndex: Integer; override; function GetSelected: Boolean; virtual; function GetSelectedTextColor: Integer; override; function GetSelectedBKColor: Integer; override; function GetViewInfoData: Pointer; override; function IsAutoHeight: Boolean; override; function IsEditHotTrack(const APoint: TPoint): Boolean; virtual; function IsEndEllipsis: Boolean; override; function IsFixed: Boolean; virtual; function IsTransparent: Boolean; override; procedure Scroll(const DX, DY: Integer); override; public class function CustomDrawID: Integer; override; property Band: TcxTreeListBand read GetBand; property BorderColor: TColor read FBorderColor write FBorderColor; property Column: TcxTreeListColumn read GetColumn; property Editing: Boolean read GetEditing; property EditRect: TRect read GetEditRect; property Focused: Boolean read GetFocused; property HotTrack: Boolean read GetHotTrack; property Node: TcxTreeListNode read GetNode; property NodeViewData: TcxTreeListNodeViewData read FNodeViewData; property OptionsView: TcxTreeListOptionsView read GetOptionsView; property Selected: Boolean read GetSelected; property TreeList: TcxCustomTreeList read GetTreeList; end; { TcxTreeListGroupNodeEditViewInfo } TcxTreeListGroupNodeEditViewInfo = class(TcxTreeListEditCellViewInfo) protected function GetColumn: TcxTreeListColumn; override; function GetFocused: Boolean; override; function IsFixed: Boolean; override; procedure Scroll(const DX, DY: Integer); override; end; { TcxTreeListPreviewCellViewInfo } TcxTreeListPreviewCellViewInfo = class(TcxTreeListEditCellViewInfo) private FPreview: TcxTreeListPreview; protected function ContentOffset: TRect; override; procedure DoCalculate; override; function GetButtonTransparency: TcxEditButtonTransparency; override; function GetColumn: TcxTreeListColumn; override; function GetEditViewParams: TcxViewParams; override; function GetHotTrack: Boolean; override; function GetMaxLineCount: Integer; override; function IsAutoHeight: Boolean; override; function IsEditHotTrack(const APoint: TPoint): Boolean; override; procedure Scroll(const DX, DY: Integer); override; public constructor Create(AOwner: TObject); override; class function CustomDrawID: Integer; override; property Preview: TcxTreeListPreview read FPreview; end; { TcxTreeListIndentCellViewInfo } TcxTreeListIndentLine = (ilVertUp, ilVertDown, ilHorz); TcxTreeListIndentLines = set of TcxTreeListIndentLine; TcxTreeListNodeIndentKind = (nikLevel, nikImage, nikState, nikCheck, nikFooter); TcxTreeListIndentCellViewInfo = class(TcxTreeListCustomCellViewInfo, IcxHotTrackElement) private FButton: Boolean; FGlyphRect: TRect; FHorzTreeLine: TRect; FHotTrack: Boolean; FImageIndex: Integer; FImages: TCustomImageList; FIndex: Integer; FKind: TcxTreeListNodeIndentKind; FLevelNode: TcxTreeListNode; FLines: TcxTreeListIndentLines; FOverlayIndex: Integer; FVertTreeLine: TRect; function GetCheckState: TcxCheckBoxState; function GetFixed: Boolean; function GetHasImage: Boolean; function GetIsExpanded: Boolean; protected procedure DoCalculate; override; procedure DoDraw(ACanvas: TcxCanvas); override; procedure DrawCheck(ACanvas: TcxCanvas); virtual; procedure DrawImage(ACanvas: TcxCanvas); virtual; procedure DrawLines(ACanvas: TcxCanvas); virtual; procedure DrawTreeLine(ACanvas: TcxCanvas; const ARect: TRect); function GetCheckBoxViewInfo(ACanvas: TcxCanvas): TcxCustomEditViewInfo; function GetHitTest(AHitTest: TcxCustomHitTestController): Boolean; override; procedure InitializeLevelIndent(ANode, AAttachNode: TcxTreeListNode; AIndex: Integer); overload; procedure InitializeImageIndent(AImages: TCustomImageList); virtual; procedure Scroll(const DX, DY: Integer); override; procedure SetSize(ATop, AHeight: Integer); // 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); public class function CustomDrawID: Integer; override; property Button: Boolean read FButton; property CheckState: TcxCheckBoxState read GetCheckState; property Fixed: Boolean read GetFixed; property GlyphRect: TRect read FGlyphRect write FGlyphRect; property HasImage: Boolean read GetHasImage; property HorzTreeLine: TRect read FHorzTreeLine; property HotTrack: Boolean read FHotTrack; property ImageIndex: Integer read FImageIndex; property Images: TCustomImageList read FImages; property Index: Integer read FIndex; property IsExpanded: Boolean read GetIsExpanded; property Kind: TcxTreeListNodeIndentKind read FKind; property LevelNode: TcxTreeListNode read FLevelNode; property Lines: TcxTreeListIndentLines read FLines; property OverlayIndex: Integer read FOverlayIndex; property VertTreeLine: TRect read FVertTreeLine; property ViewParams; property TreeList; end; { TcxTreeListNodeViewData } TcxTreeListNodeViewData = class public Bounds: TRect; Cells: TcxCustomControlCells; CheckFooterRgn: Boolean; ContentBounds: TRect; DrawFocusRect: Boolean; Focused: Boolean; FocusRectBounds: TRect; GroupFooterCount: Integer; Height: Integer; ImageIndent: TcxTreeListIndentCellViewInfo; IndentWidth: Integer; Node: TcxTreeListNode; Origin: TPoint; PreviewHeight: Integer; RowsHeight: Integer; RowsOffset: Integer; Selected: Boolean; StateImageIndent: TcxTreeListIndentCellViewInfo; ViewInfo: TcxTreeListViewInfo; constructor Create(AViewInfo: TcxTreeListViewInfo; ANode: TcxTreeListNode; ACapacity: Integer); virtual; destructor Destroy; override; function GetRealBounds: TRect; function GetRealContentBounds: TRect; procedure Paint(ACanvas: TcxCanvas; AHandler: TcxCustomDrawCellEvent); procedure Scroll(DX, DY: Integer; ALeftFixed, ARightFixed: Boolean); virtual; function Update(AForceUpdate: Boolean): Boolean; end; { TcxTreeListViewInfo } TcxTreeListViewInfo = class(TcxCustomControlViewInfo) private FBandHeaderLineHeight: Integer; FBandLineHeight: Integer; FBounds: TRect; FCells: TcxCustomControlCells; FContentParts: array[TcxTreeListBandFixedKind] of TRect; FContentHeight: Integer; FContentWidth: Integer; FCheckBoxProperties: TcxCustomEditProperties; FCheckBoxViewData: TcxCustomEditViewData; FCheckBoxViewInfo: TcxCustomEditViewInfo; FDefaultCellHeight: Integer; FDragItem: TObject; FFakeCell: TcxTreeListEditCellViewInfo; FFooterLineHeight: Integer; FGridLineColor: TColor; FGridLines: TcxBorders; FHeaderCells: TList; FHeaderLineHeight: Integer; FHitTestCells: TcxObjectList; FHorzBackgroundCell: TcxTreeListBackgroundCellViewInfo; FHScrollArea: TRect; FHScrollInc: Integer; FHScrollPage: Integer; FHScrollPos: Integer; FHScrollSize: Integer; FMultiRows: Boolean; FNodesHeight: Integer; FNodesViewData: TcxObjectList; FNodesVisibleCount: Integer; FPrevFont: TFont; FPrevFontHeight: Integer; FPreviewLineHeight: Integer; FRows: PIntegerArray; FTreeLineColor: TColor; function GetBands: TcxTreeListBands; function GetBandsHeight: Integer; function GetBorderSize: Integer; function GetCalculateInProcess: Boolean; function GetCheckBoxSize: TSize; function GetColumn(AIndex: Integer): TcxTreeListColumn; function GetColumnCount: Integer; function GetColumnDefaultEditHeight(AColumn: TcxTreeListColumn): Integer; function GetColumnsRowCount: Integer; function GetContentPart(AKind: TcxTreeListBandFixedKind): TRect; function GetCount: Integer; function GetDefaultRowHeight: Integer; function GetFixedSeparatorWidth: Integer; function GetFooterHeight: Integer; function GetFooterLineCount: Integer; function GetGroupFooterHeight: Integer; function GetGroupFooterLineCount: Integer; function GetHeadersHeight: Integer; function GetImages: TCustomImageList; function GetIndentBand: TcxTreeListBand; function GetIndentLeftMost: Boolean; function GetIndicatorWidth: Integer; function GetLastNode: TcxTreeListNode; function GetLevelInfo(ALevel: Integer): TcxTreeListLevelInfo; function GetNodeViewData(AIndex: Integer): TcxTreeListNodeViewData; function GetOptionsView: TcxTreeListOptionsView; function GetOriginalViewInfo: TcxTreeListViewInfo; function GetPainter: TcxCustomLookAndFeelPainterClass; function GetPreview: TcxTreeListPreview; function GetRoot: TcxTreeListNode; function GetRowOffset(AIndex: Integer): Integer; function GetSummary: TcxTreeListSummary; function GetStateImages: TCustomImageList; function GetStyles: TcxTreeListStyles; function GetTopNode: TcxTreeListNode; function GetTreeList: TcxCustomTreeList; function GetVScrollPage: Integer; function GetVScrollPos: Integer; function GetVScrollSize: Integer; procedure SetCalculateInProcess(AValue: Boolean); procedure SetHScrollPos(APosition: Integer); procedure SetLastNode(ANode: TcxTreeListNode); procedure SetRowOffset(AIndex: Integer; const AValue: Integer); protected function AddBackgroundPart(const ABounds: TRect): TcxTreeListBackgroundCellViewInfo; function AddBandHeader(ABand: TcxTreeListBand; var ABounds: TRect; const AClipRect: TRect): TcxTreeListBandHeaderCellViewInfo; function AddBandPart(APart: TcxTreeListBandPart; ABand: TcxTreeListBand; ANode, AAttachNode: TcxTreeListNode; ABounds, AClipRect: TRect): TcxTreeListBandCellViewInfo; function AddBandSeparator(ANode: TcxTreeListNode; var ABounds: TRect; const AClipBounds: TRect): TcxTreeListBandCellViewInfo; procedure AddBandsHeaders(AKind: TcxTreeListBandFixedKind; const ABounds, AClipBounds: TRect); procedure AddCell(ACellClass: TcxTreeListCustomCellViewInfoClass; const ABounds, AVisibleRect: TRect; var AInstance); function AddColumnHeader(AColumn: TcxTreeListColumn; var ABounds: TRect; const AClipBounds: TRect): TcxTreeListColumnHeaderCellViewInfo; function AddEditCell(AViewData: TcxTreeListNodeViewData; AColumn: TcxTreeListColumn; ABounds, AClipRect: TRect; AClass: TcxEditCellViewInfoClass): TcxTreeListEditCellViewInfo; procedure AddColumnFooterItems(ADataNode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn; const ABounds, AClipRect: TRect); procedure AddFixedSeparators(ABounds: TRect; AAttachNode: TcxTreeListNode); procedure AddFooter(AAttachNode: TcxTreeListNode; AIndex, AIndent: Integer; const ABounds: TRect); procedure AddHeaderHitTestAreas(ACell: TcxTreeListHeaderCellViewInfo; AHorz, AVert: Boolean); function AddImageIndent(ANode: TcxTreeListNode; AImages: TCustomImageList; var ABounds: TRect; const AClipRect: TRect): TcxTreeListIndentCellViewInfo; function AddIndent(ANode, AAttachNode: TcxTreeListNode; ALevel: Integer; AKind: TcxTreeListNodeIndentKind; var ABounds: TRect; const AClipRect: TRect): TcxTreeListIndentCellViewInfo; function AddIndentCheck(ANode: TcxTreeListNode; var ABounds: TRect; const AClipRect: TRect): TcxTreeListIndentCellViewInfo; function AddIndicator(ANode: TcxTreeListNode; APosition: TcxTreeListIndicatorPosition; var ABounds: TRect): TcxTreeListIndicatorCellViewInfo; procedure AddNodeBands(AViewData: TcxTreeListNodeViewData); procedure AddNodeCategorized(AViewData: TcxTreeListNodeViewData); procedure AddNodeColumns(AViewData: TcxTreeListNodeViewData); procedure AddNodeFooters(AViewData: TcxTreeListNodeViewData); procedure AddNodeIndents(AViewData: TcxTreeListNodeViewData); function AddNodePreview(AViewData: TcxTreeListNodeViewData): TcxTreeListEditCellViewInfo; procedure AddNodeStandardContent(AViewData: TcxTreeListNodeViewData); function AddNodeViewData(ANode: TcxTreeListNode; AInsert: Boolean): TcxTreeListNodeViewData; procedure AdjustNodeIndents(AViewData: TcxTreeListNodeViewData); procedure AfterCalculate; virtual; procedure BeforeCalculate; virtual; procedure CalculateBackgroundParts; virtual; procedure CalculateBandsLayout; virtual; procedure CalculateColumnsLayout; virtual; function CalculateDefaultEditHeight: Integer; override; procedure CalculateDefaultHeights; override; procedure CalculateFooterLayout; virtual; procedure CalculateHeadersNeighbors; procedure CalculateHitTest(AHitTest: TcxTreeListHitTest); virtual; procedure CalculateHorzScrollInfo(AAvailableWidth, AContentWidth: Integer); virtual; function CalculateNodeAutoHeight(AViewData: TcxTreeListNodeViewData): Integer; procedure CalculateNodesOrigin; virtual; procedure CalculateNodesViewData; virtual; procedure CalculateNodesViewDataBackward(ANode: TcxTreeListNode; ACheckHeight: Boolean; var AvailableHeight: Integer); virtual; procedure CalculateNodesViewDataForward(ANode: TcxTreeListNode; var AvailableHeight: Integer); virtual; procedure CellsChanged; function CheckScrollPosition(AScrollCode: TScrollCode; APos, APage, AInc, AMax : Integer; var AScrollPos: Integer): Boolean; virtual; procedure CorrectBorders; virtual; procedure Clear; procedure DeleteNodeViewData(AIndex: Integer); procedure DoCalculate; override; function GetContentBounds: TRect; virtual; function GetFontHeight(const AFont: TFont): Integer; function GetIsIndicatorVisible: Boolean; virtual; function GetIsPrinting: Boolean; virtual; function GetLevelContentOffset(ALevel: Integer): Integer; function GetNodeContentOffset(ANode: TcxTreeListNode): Integer; function HasFooter(ANode: TcxTreeListNode): Boolean; virtual; function HasStateIndent(ANode: TcxTreeListNode): Boolean; procedure InflateBoundsForGridLines(var ABounds, AClipRect: TRect); procedure InitializeRows(const ANewHeight: Integer; var AViewData: TcxTreeListNodeViewData); procedure InitScrollBarsParameters; virtual; procedure InvalidateRect(const ARect: TRect); procedure MakeVisible(ANode: TcxTreeListNode); procedure RecalculateHitTestCells; procedure RecreateCheckBoxViewData; procedure ScrollHorz(AScrollCode: TScrollCode; var AScrollPos: Integer); procedure ScrollVert(AScrollCode: TScrollCode; var AScrollPos: Integer); procedure SetDirty; procedure UpdateScrollBars; virtual; procedure UpdateSelection; override; procedure ValidateScrollPos(var APosition: Integer; const APage, AMax: Integer); property CalculateInProcess: Boolean read GetCalculateInProcess write SetCalculateInProcess; property FakeCell: TcxTreeListEditCellViewInfo read FFakeCell; property HitTestCells: TcxObjectList read FHitTestCells; property IsPrinting: Boolean read GetIsPrinting; property RowOffset[Index: Integer]: Integer read GetRowOffset write SetRowOffset; public constructor Create(AOwner: TcxEditingControl); override; destructor Destroy; override; function GetEditCell(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxTreeListEditCellViewInfo; function Validate: Boolean; property BandHeaderLineHeight: Integer read FBandHeaderLineHeight; property BandLineHeight: Integer read FBandLineHeight; property Bands: TcxTreeListBands read GetBands; property BandsHeight: Integer read GetBandsHeight; property BorderSize: Integer read GetBorderSize; property Bounds: TRect read FBounds write FBounds; property Cells: TcxCustomControlCells read FCells write FCells; property CheckboxSize: TSize read GetCheckBoxSize; property CheckBoxViewInfo: TcxCustomEditViewInfo read FCheckBoxViewInfo; property CheckBoxViewData: TcxCustomEditViewData read FCheckBoxViewData; property ColumnCount: Integer read GetColumnCount; property Columns[Index: Integer]: TcxTreeListColumn read GetColumn; property ColumnsRowCount: Integer read GetColumnsRowCount; property ContentBounds: TRect read GetContentBounds; property ContentHeight: Integer read FContentHeight write FContentHeight ; property ContentParts[AKind: TcxTreeListBandFixedKind]: TRect read GetContentPart; property ContentWidth: Integer read FContentWidth; property Count: Integer read GetCount; property DefaultCellHeight: Integer read FDefaultCellHeight; property DefaultRowHeight: Integer read GetDefaultRowHeight; property FixedSeparatorWidth: Integer read GetFixedSeparatorWidth; property FooterHeight: Integer read GetFooterHeight; property FooterLineCount: Integer read GetFooterLineCount; property FooterLineHeight: Integer read FFooterLineHeight; property GridLineColor: TColor read FGridLineColor; property GridLines: TcxBorders read FGridLines write FGridLines; property GroupFooterHeight: Integer read GetGroupFooterHeight; property GroupFooterLineCount: Integer read GetGroupFooterLineCount; property HeaderLineHeight: Integer read FHeaderLineHeight; property HeadersHeight: Integer read GetHeadersHeight; property HorzBackgroundCell: TcxTreeListBackgroundCellViewInfo read FHorzBackgroundCell; property HScrollArea: TRect read FHScrollArea; property HScrollInc: Integer read FHScrollInc; property HScrollPage: Integer read FHScrollPage; property HScrollPos: Integer read FHScrollPos write SetHScrollPos; property HScrollSize: Integer read FHScrollSize; property IndentBand: TcxTreeListBand read GetIndentBand; property IndentLeftMost: Boolean read GetIndentLeftMost; property IsIndicatorVisible: Boolean read GetIsIndicatorVisible; property LevelInfo[ALevel: Integer]: TcxTreeListLevelInfo read GetLevelInfo; property VScrollPage: Integer read GetVScrollPage; property VScrollPos: Integer read GetVScrollPos; property VScrollSize: Integer read GetVScrollSize; property Images: TCustomImageList read GetImages; property IndicatorWidth: Integer read GetIndicatorWidth; property LastNode: TcxTreeListNode read GetLastNode write SetLastNode; property MultiRows: Boolean read FMultiRows; property NodesHeight: Integer read FNodesHeight; property NodesViewData: TcxObjectList read FNodesViewData; property NodesVisibleCount: Integer read FNodesVisibleCount; property NodeViewData[Index: Integer]: TcxTreeListNodeViewData read GetNodeViewData; property OptionsView: TcxTreeListOptionsView read GetOptionsView; property OriginalViewInfo: TcxTreeListViewInfo read GetOriginalViewInfo; property Painter: TcxCustomLookAndFeelPainterClass read GetPainter; property Preview: TcxTreeListPreview read GetPreview; property PreviewLineHeight: Integer read FPreviewLineHeight; property Root: TcxTreeListNode read GetRoot; property Summary: TcxTreeListSummary read GetSummary; property StateImages: TCustomImageList read GetStateImages; property Styles: TcxTreeListStyles read GetStyles; property TopNode: TcxTreeListNode read GetTopNode; property TreeList: TcxCustomTreeList read GetTreeList; property TreeLineColor: TColor read FTreeLineColor; end; { TcxTreeListPainter } TcxTreeListPainter = class(TcxCustomControlPainter) private FChanged: Boolean; FCustomDrawSupported: Boolean; function GetCells: TcxCustomControlCells; function GetTreeList: TcxCustomTreeList; function GetViewInfo: TcxTreeListViewInfo; protected procedure DoPaint; override; procedure CheckBuffer(AWidth, AHeight: Integer); procedure CheckCustomDrawSupport; virtual; procedure CheckDirty; procedure CustomDrawCell(ACanvas: TcxCanvas; ACell: TcxCustomViewInfoItem; var ADone: Boolean); virtual; procedure SetBuffered(Value: Boolean); override; public constructor Create(AOwner: TcxEditingControl); override; procedure Paint; override; procedure CheckSize(const AWidth, AHeight: Integer); property Cells: TcxCustomControlCells read GetCells; property Changed: Boolean read FChanged write FChanged; property CustomDrawSupported: Boolean read FCustomDrawSupported write FCustomDrawSupported; property TreeList: TcxCustomTreeList read GetTreeList; property ViewInfo: TcxTreeListViewInfo read GetViewInfo; end; { TcxTreeListBandOptions } TcxTreeListBandOptions = class(TcxOwnedPersistent) private FCustomizing: Boolean; FHidden: Boolean; FMoving: Boolean; FOnlyOwnColumns: Boolean; FSizing: Boolean; FVertSizing: Boolean; procedure SetSizing(AValue: Boolean); procedure SetVertSizing(AValue: Boolean); protected procedure Changed; virtual; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; procedure RestoreDefaults; virtual; published property Customizing: Boolean read FCustomizing write FCustomizing default True; property Hidden: Boolean read FHidden write FHidden default False; property Moving: Boolean read FMoving write FMoving default True; property OnlyOwnColumns: Boolean read FOnlyOwnColumns write FOnlyOwnColumns default False; property Sizing: Boolean read FSizing write SetSizing default True; property VertSizing: Boolean read FVertSizing write SetVertSizing default True; end; TcxTreeListBandOptionsClass = class of TcxTreeListBandOptions; { TcxTreeListBandStyles } TcxTreeListBandStyles = class(TcxStyles) private function GetBand: TcxTreeListBand; function GetTreeList: TcxCustomTreeList; protected procedure Changed(AIndex: Integer); override; procedure DoGetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AParams: TcxViewParams); virtual; procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; function GetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxViewParams; property Band: TcxTreeListBand read GetBand; property TreeList: TcxCustomTreeList read GetTreeList; 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; { TcxTreeListBandPosition } TcxTreeListBandPosition = class(TcxOwnedPersistent) private FBandIndex: Integer; FColIndex: Integer; FParentBand: TcxTreeListBand; function GetBand: TcxTreeListBand; function GetBandIndex: Integer; function GetColIndex: Integer; function GetTreeList: TcxCustomTreeList; function GetVisibleColIndex: Integer; procedure SetBandIndex(AValue: Integer); procedure SetColIndex(AValue: Integer); function IsColIndexStored: Boolean; function IsLocked: Boolean; protected procedure Changed; virtual; function CheckBandIndex(var AIndex: Integer): Boolean; function IsPositionChanged: Boolean; procedure Restore; procedure Store; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; property Band: TcxTreeListBand read GetBand; property ParentBand: TcxTreeListBand read FParentBand; property TreeList: TcxCustomTreeList read GetTreeList; property VisibleColIndex: Integer read GetVisibleColIndex; published property BandIndex: Integer read GetBandIndex write SetBandIndex default -1; property ColIndex: Integer read GetColIndex write SetColIndex stored IsColIndexStored; end; { TcxTreeListBand } TcxTreeListBand = class(TcxInterfacedCollectionItem, IUnknown, IcxDragSizing, IcxStoredObject) private FBandRows: TcxTreeListBandRows; FCalculatedWidth: Integer; FCaption: TcxTreeListCaption; FChildBands: TList; FChildVisibleBands: TList; FColumns: TList; FExpandable: TcxTreeListBandExpandable; FFixedKind: TcxTreeListBandFixedKind; FHasEmptyArea: Boolean; FHeaderCell: TcxTreeListBandHeaderCellViewInfo; FLineCount: Integer; FMinWidth: Integer; FOptions: TcxTreeListBandOptions; FPosition: TcxTreeListBandPosition; FStyles: TcxTreeListBandStyles; FVisible: Boolean; FVisibleColumns: TList; FWidth: Integer; // IcxStoredObject events FOnGetStoredProperties: TcxGetStoredPropertiesEvent; FOnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent; FOnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent; function GetActuallyExpandable: Boolean; function GetActuallyVisible: Boolean; function GetBands: TcxTreeListBands; function GetCalculatedWidth: Integer; function GetColumn(AIndex: Integer): TcxTreeListColumn; function GetColumnCount: Integer; function GetChildBand(AIndex: Integer): TcxTreeListBand; function GetChildBandCount: Integer; function GetDisplayWidth: Integer; function GetFirstChildBottomBand: TcxTreeListBand; function GetHasEmptyArea: Boolean; function GetIndentWidth: Integer; function GetIsBottom: Boolean; function GetIsFirstInGroup: Boolean; function GetIsLastAsChild: Boolean; function GetIsLastInGroup: Boolean; function GetIsLeftMost: Boolean; function GetIsLoading: Boolean; function GetIsRightMost: Boolean; function GetIsRoot: Boolean; function GetIsWidthFixed: Boolean; function GetLevel: Integer; function GetParentBand: TcxTreeListBand; function GetParentBandWidthAssigned: TcxTreeListBand; function GetRootIndex: Integer; function GetRootParentBand: TcxTreeListBand; function GetTreeList: TcxCustomTreeList; function GetVisibleIndex: Integer; function GetVisibleColumn(AIndex: Integer): TcxTreeListColumn; function GetVisibleColumnCount: Integer; function GetVisibleRootIndex: Integer; procedure SetCaption(AValue: TcxTreeListCaption); procedure SetCalculatedWidth(AValue: Integer); procedure SetColumn(AIndex: Integer; AValue: TcxTreeListColumn); procedure SetDisplayWidth(AValue: Integer); procedure SetExpandable(AValue: TcxTreeListBandExpandable); procedure SetFixedKind(AValue: TcxTreeListBandFixedKind); procedure SetMinWidth(AValue: Integer); procedure SetOptions(AValue: TcxTreeListBandOptions); procedure SetPosition(AValue: TcxTreeListBandPosition); procedure SetRootIndex(AValue: Integer); procedure SetStyles(AValue: TcxTreeListBandStyles); procedure SetVisible(AValue: Boolean); procedure SetVisibleColumn(AIndex: Integer; AValue: TcxTreeListColumn); procedure SetWidth(AValue: Integer); protected function ActualMinWidth: Integer; procedure AdjustSubItems; procedure AssignChildBandWidths; procedure AssignColumnsWidth; procedure AssignWidth; procedure InitAutoWidthItem(AItem: TcxAutoWidthItem); function IsBandFixedDuringSizing: Boolean; function IsOnlyOwnColumns: Boolean; procedure CalculateLineCount(ACurrentLine: Integer); function CanDropColumnAt(const APoint: TPoint; out ARowIndex, AColIndex: Integer): Boolean; virtual; procedure CheckExpandable(var ABand: TcxTreeListBand); procedure ForceWidth(AValue: Integer); function GetMaxDeltaWidth: Integer; function CanMoving: Boolean; virtual; procedure ChangeCaption(Sender: TObject); virtual; function GetOptionsClass: TcxTreeListBandOptionsClass; virtual; procedure AddBand(ABand: TcxTreeListBand); procedure AddColumn(AColumn: TcxTreeListColumn); procedure ColumnSizeChanged(AColumn: TcxTreeListColumn); procedure DeleteColumn(AColumn: TcxTreeListColumn); procedure LayoutChanged; procedure MoveBandsToRoot; procedure MoveColumnsTo(ABand: TcxTreeListBand); procedure Refresh; procedure RemoveBand(ABand: TcxTreeListBand); procedure RemoveChildBands; procedure RemoveColumns; procedure SetIndex(Value: Integer); override; // 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 CalculatedWidth: Integer read GetCalculatedWidth write SetCalculatedWidth; property ChildVisibleBands: TList read FChildVisibleBands; property FirstChildBottomBand: TcxTreeListBand read GetFirstChildBottomBand; property HasEmptyArea: Boolean read GetHasEmptyArea write FHasEmptyArea; property HeaderCell: TcxTreeListBandHeaderCellViewInfo read FHeaderCell write FHeaderCell; property IsFirstInGroup: Boolean read GetIsFirstInGroup; property IsLastInGroup: Boolean read GetIsLastInGroup; property IsWidthFixed: Boolean read GetIsWidthFixed; property ParentBandWidthAssigned: TcxTreeListBand read GetParentBandWidthAssigned; public constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure ApplyBestFit; function IndexOf(AChildBand: TcxTreeListBand): Integer; function HasAsParent(ABand: TcxTreeListBand): Boolean; procedure MoveBand(ABand: TcxTreeListBand; AColIndex: Integer); procedure RestoreDefaults; virtual; procedure RestoreWidths; property ActuallyExpandable: Boolean read GetActuallyExpandable; property ActuallyVisible: Boolean read GetActuallyVisible; property BandRows: TcxTreeListBandRows read FBandRows; property Bands: TcxTreeListBands read GetBands; property ChildBandCount: Integer read GetChildBandCount; property ChildBands[Index: Integer]: TcxTreeListBand read GetChildBand; property ColumnCount: Integer read GetColumnCount; property Columns[Index: Integer]: TcxTreeListColumn read GetColumn write SetColumn; property DisplayWidth: Integer read GetDisplayWidth write SetDisplayWidth; property IndentWidth: Integer read GetIndentWidth; property IsBottom: Boolean read GetIsBottom; property IsLastAsChild: Boolean read GetIsLastAsChild; property IsLeftMost: Boolean read GetIsLeftMost; property IsLoading: Boolean read GetIsLoading; property IsRightMost: Boolean read GetIsRightMost; property IsRoot: Boolean read GetIsRoot; property Level: Integer read GetLevel; property LineCount: Integer read FLineCount; property ParentBand: TcxTreeListBand read GetParentBand; property RootIndex: Integer read GetRootIndex write SetRootIndex; property RootParentBand: TcxTreeListBand read GetRootParentBand; property TreeList: TcxCustomTreeList read GetTreeList; property VisibleColumnCount: Integer read GetVisibleColumnCount; property VisibleColumns[Index: Integer]: TcxTreeListColumn read GetVisibleColumn write SetVisibleColumn; property VisibleIndex: Integer read GetVisibleIndex; property VisibleRootIndex: Integer read GetVisibleRootIndex; property Index; published property Caption: TcxTreeListCaption read FCaption write SetCaption; property Expandable: TcxTreeListBandExpandable read FExpandable write SetExpandable default tlbeDefault; property FixedKind: TcxTreeListBandFixedKind read FFixedKind write SetFixedKind default tlbfNone; property MinWidth: Integer read FMinWidth write SetMinWidth default cxTreeListDefMinWidth; property Options: TcxTreeListBandOptions read FOptions write SetOptions; property Position: TcxTreeListBandPosition read FPosition write SetPosition; property Styles: TcxTreeListBandStyles read FStyles write SetStyles; property Visible: Boolean read FVisible write SetVisible default True; property Width: Integer read FWidth write SetWidth default 0; // IcxStoredObject events property OnGetStoredProperties: TcxGetStoredPropertiesEvent read FOnGetStoredProperties write FOnGetStoredProperties; property OnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent read FOnGetStoredPropertyValue write FOnGetStoredPropertyValue; property OnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent read FOnSetStoredPropertyValue write FOnSetStoredPropertyValue; end; TcxTreeListBandClass = class of TcxTreeListBand; { TcxTreeListBands } TcxTreeListBands = class(TCollection, {$IFNDEF DELPHI6} IUnknown, {$ENDIF} IcxStoredObject, IcxStoredParent) private FBottomItems: TList; FColumnsLineCount: Integer; FExpandableBand: TcxTreeListBand; FLineCount: Integer; FRootItems: TList; FTreeList: TcxCustomTreeList; FVisibleItems: TList; FVisibleLeftFixedCount: Integer; FVisibleRightFixedCount: Integer; FVisibleRootItems: TList; FVisibleRootLeftFixedCount: Integer; FVisibleRootRightFixedCount: Integer; function GetBottomItem(AIndex: Integer): TcxTreeListBand; function GetBottomItemCount: Integer; function GetFirstVisibleBand: TcxTreeListBand; function GetItem(AIndex: Integer): TcxTreeListBand; function GetLastVisibleBand: TcxTreeListBand; function GetRootItemCount: Integer; function GetRootItem(AIndex: Integer): TcxTreeListBand; function GetVisibleItem(AIndex: Integer): TcxTreeListBand; function GetVisibleItemCount: Integer; function GetVisibleRootItem(AIndex: Integer): TcxTreeListBand; function GetVisibleRootItemCount: Integer; procedure SetItem(AIndex: Integer; AValue: TcxTreeListBand); protected procedure Adjust(ABands: TList = nil; AWidth: Integer = 0); virtual; procedure AssignColumnsWidth; procedure AssignRootItemWidths; function CanExpandableLeftMostOnly: Boolean; virtual; procedure ClearCalculatedWidths; function GetFirstVisibleIndex(AFixedKind: TcxTreeListBandFixedKind): Integer; function GetFirstVisibleRootIndex(AFixedKind: TcxTreeListBandFixedKind): Integer; function GetLastVisibleIndex(AFixedKind: TcxTreeListBandFixedKind): Integer; function GetLastVisibleRootIndex(AFixedKind: TcxTreeListBandFixedKind): Integer; function GetVisibleCountByKind(AFixedKind: TcxTreeListBandFixedKind): Integer; function GetOwner: TPersistent; override; procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override; function PopulateVisibleChildren(ABand: TcxTreeListBand): Integer; procedure RefreshInformation; procedure Update(Item: TCollectionItem); override; // 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: TcxCustomTreeList); virtual; destructor Destroy; override; procedure Assign(ASource: TPersistent); override; function Add: TcxTreeListBand; procedure RestoreDefaults; virtual; procedure RestoreWidths; virtual; function VisibleIndexOf(ABand: TcxTreeListBand): Integer; property BottomItemCount: Integer read GetBottomItemCount; property BottomItems[Index: Integer]: TcxTreeListBand read GetBottomItem; property ColumnsLineCount: Integer read FColumnsLineCount; property ExpandableBand: TcxTreeListBand read FExpandableBand; property FirstVisible: TcxTreeListBand read GetFirstVisibleBand; property Items[AIndex: Integer]: TcxTreeListBand read GetItem write SetItem; default; property LastVisible: TcxTreeListBand read GetLastVisibleBand; property LineCount: Integer read FLineCount; property RootItemCount: Integer read GetRootItemCount; property RootItems[Index: Integer]: TcxTreeListBand read GetRootItem; property TreeList: TcxCustomTreeList read FTreeList; property VisibleItemCount: Integer read GetVisibleItemCount; property VisibleItems[Index: Integer]: TcxTreeListBand read GetVisibleItem; property VisibleLeftFixedCount: Integer read FVisibleLeftFixedCount; property VisibleRightFixedCount: Integer read FVisibleRightFixedCount; property VisibleRootItemCount: Integer read GetVisibleRootItemCount; property VisibleRootItems[Index: Integer]: TcxTreeListBand read GetVisibleRootItem; property VisibleRootLeftFixedCount: Integer read FVisibleRootLeftFixedCount; property VisibleRootRightFixedCount: Integer read FVisibleRootRightFixedCount; end; { TcxTreeListBandRow } TcxTreeListBandRow = class private FBandRows: TcxTreeListBandRows; FItems: TList; FLineCount: Integer; FLineOffset: Integer; FMinWidth: Integer; FVisibleItems: TList; FWidth: Integer; function GetBand: TcxTreeListBand; function GetCount: Integer; function GetFirst: TcxTreeListColumn; function GetIndex: Integer; function GetIsFirst: Boolean; function GetIsLast: Boolean; function GetItem(AIndex: Integer): TcxTreeListColumn; function GetVisibleIndex: Integer; function GetVisibleItem(AIndex: Integer): TcxTreeListColumn; function GetVisibleItemCount: Integer; function GetLast: TcxTreeListColumn; function GetTreeList: TcxCustomTreeList; protected procedure AdjustColumns; procedure AssignColumnsWidth; procedure CheckEmpty; procedure Refresh; virtual; public constructor Create(AOwner: TcxTreeListBandRows); virtual; destructor Destroy; override; function IndexOf(AColumn: TcxTreeListColumn): Integer; property Band: TcxTreeListBand read GetBand; 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 FLineCount; property LineOffset: Integer read FLineOffset; property MinWidth: Integer read FMinWidth; property TreeList: TcxCustomTreeList read GetTreeList; property VisibleIndex: Integer read GetVisibleIndex; property VisibleItemCount: Integer read GetVisibleItemCount; property VisibleItems[Index: Integer]: TcxTreeListColumn read GetVisibleItem; property Width: Integer read FWidth; end; { TcxTreeListBandRows } TcxTreeListBandRows = class private FBand: TcxTreeListBand; FItems: TcxObjectList; FLineCount: Integer; FRowMaxWidth: Integer; FRowMinWidth: Integer; FVisibleItems: TList; function GetCount: Integer; function GetFirst: TcxTreeListBandRow; function GetItem(Index: Integer): TcxTreeListBandRow; function GetItemEx(Index: Integer): TcxTreeListBandRow; function GetLast: TcxTreeListBandRow; function GetVisibleItemCount: Integer; function GetVisibleItem(AIndex: Integer): TcxTreeListBandRow; protected function Add: TcxTreeListBandRow; function CheckRowIndex(ARowIndex: Integer): TcxTreeListBandRow; procedure CheckRowEmpty(ARowIndex: Integer); function Insert(AIndex: Integer): TcxTreeListBandRow; procedure Refresh; virtual; public constructor Create(AOwner: TcxTreeListBand); virtual; destructor Destroy; override; property Band: TcxTreeListBand read FBand; property Count: Integer read GetCount; property First: TcxTreeListBandRow read GetFirst; property Items[Index: Integer]: TcxTreeListBandRow read GetItem; default; property Last: TcxTreeListBandRow read GetLast; property LineCount: Integer read FLineCount; property RowMaxWidth: Integer read FRowMaxWidth; property RowMinWidth: Integer read FRowMinWidth; property VisibleItemCount: Integer read GetVisibleItemCount; property VisibleItems[Index: Integer]: TcxTreeListBandRow read GetVisibleItem; end; { TcxTreeListOptionsView } TcxTreeListGroupFootersMode = (tlgfInvisible, tlgfVisibleWhenExpanded, tlgfAlwaysVisible); TcxTreeListTreeLineStyle = (tllsNone, tllsDot, tllsSolid); TcxTreeListPaintStyle = (tlpsStandard, tlpsCategorized); TcxTreeListOptionsView = class(TcxControlOptionsView, IUnknown) private FBandLineHeight: Integer; FBands: Boolean; FButtons: Boolean; FCategorizedColumn: TcxTreeListColumn; FCheckGroups: Boolean; FColumnAutoWidth: Boolean; FDropArrowColor: TColor; FDynamicIndent: Boolean; FDynamicFocusedStateImages: Boolean; FExtPaintStyle: Boolean; FFixedSeparatorColor: TColor; FFixedSeparatorWidth: Integer; FFooter: Boolean; FGridLineColor: TColor; FGridLines: TcxTreeListGridLines; FGroupFooters: TcxTreeListGroupFootersMode; FHeaders: Boolean; FIndicator: Boolean; FIndicatorWidth: Integer; FPaintStyle: TcxTreeListPaintStyle; FShowRoot: Boolean; FSimpleCustomizeBox: Boolean; FTreeLineColor: TColor; FTreeLineStyle: TcxTreeListTreeLineStyle; FUseImageIndexForSelected: Boolean; FUseNodeColorForIndent: Boolean; function GetIsIndicatorVisible: Boolean; function GetTreeList: TcxCustomTreeList; procedure SetBandLineHeight(AValue: Integer); procedure SetBands(AValue: Boolean); procedure SetButtons(AValue: Boolean); procedure SetCategorizedColumn(AValue: TcxTreeListColumn); procedure SetCheckGroups(AValue: Boolean); procedure SetColumnAutoWidth(AValue: Boolean); procedure SetDynamicIndent(AValue: Boolean); procedure SetDynamicFocusedStateImages(AValue: Boolean); procedure SetExtPaintStyle(AValue: Boolean); procedure SetFixedSeparatorColor(AValue: TColor); procedure SetFixedSeparatorWidth(AValue: Integer); procedure SetFooter(AValue: Boolean); procedure SetGridLineColor(AValue: TColor); procedure SetGridLines(AValue: TcxTreeListGridLines); procedure SetGroupFooters(AValue: TcxTreeListGroupFootersMode); procedure SetHeaders(AValue: Boolean); procedure SetIndicator(AValue: Boolean); procedure SetIndicatorWidth(AValue: Integer); procedure SetPaintStyle(AValue: TcxTreeListPaintStyle); procedure SetShowRoot(AValue: Boolean); procedure SetSimpleCustomizeBox(AValue: Boolean); procedure SetTreeLineColor(AValue: TColor); procedure SetTreeLineStyle(AValue: TcxTreeListTreeLineStyle); procedure SetUseImageIndexForSelected(AValue: Boolean); procedure SetUseNodeColorForIndent(AValue: Boolean); protected procedure Changed; override; function GetControl: TObject; // helper functions function HorzIncrement: Integer; function IsCategorizedPaint: Boolean; function IsExtPaintStyle: 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: TcxCustomTreeList read GetTreeList; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; function GetCategorizedColumn: TcxTreeListColumn; procedure RestoreDefaults; virtual; property IsIndicatorVisible: Boolean read GetIsIndicatorVisible; published property BandLineHeight: Integer read FBandLineHeight write SetBandLineHeight default 0; property Bands: Boolean read FBands write SetBands default False; property Buttons: Boolean read FButtons write SetButtons default True; property CategorizedColumn: TcxTreeListColumn read FCategorizedColumn write SetCategorizedColumn; property ColumnAutoWidth: Boolean read FColumnAutoWidth write SetColumnAutoWidth default False; property CheckGroups: Boolean read FCheckGroups write SetCheckGroups default False; property DropArrowColor: TColor read FDropArrowColor write FDropArrowColor default cxTreeListDefDropArrowColor; property DynamicIndent: Boolean read FDynamicIndent write SetDynamicIndent default False; property DynamicFocusedStateImages: Boolean read FDynamicFocusedStateImages write SetDynamicFocusedStateImages default False; property ExtPaintStyle: Boolean read FExtPaintStyle write SetExtPaintStyle default False; property FixedSeparatorColor: TColor read FFixedSeparatorColor write SetFixedSeparatorColor default clDefault; property FixedSeparatorWidth: Integer read FFixedSeparatorWidth write SetFixedSeparatorWidth default cxTreeListDefSeparatorWidth; property Footer: Boolean read FFooter write SetFooter default False; property GridLineColor: TColor read FGridLineColor write SetGridLineColor default clDefault; property GridLines: TcxTreeListGridLines read FGridLines write SetGridLines default tlglNone; property GroupFooters: TcxTreeListGroupFootersMode read FGroupFooters write SetGroupFooters default tlgfInvisible; property Headers: Boolean read FHeaders write SetHeaders default True; property Indicator: Boolean read FIndicator write SetIndicator default False; property IndicatorWidth: Integer read FIndicatorWidth write SetIndicatorWidth default cxTreeListDefIndicatorWidth; property PaintStyle: TcxTreeListPaintStyle read FPaintStyle write SetPaintStyle default tlpsStandard; property ShowRoot: Boolean read FShowRoot write SetShowRoot default True; property SimpleCustomizeBox: Boolean read FSimpleCustomizeBox write SetSimpleCustomizeBox default False; property TreeLineColor: TColor read FTreeLineColor write SetTreeLineColor default clDefault; property TreeLineStyle: TcxTreeListTreeLineStyle read FTreeLineStyle write SetTreeLineStyle default tllsDot; property UseImageIndexForSelected: Boolean read FUseImageIndexForSelected write SetUseImageIndexForSelected default True; property UseNodeColorForIndent: Boolean read FUseNodeColorForIndent write SetUseNodeColorForIndent default True; property CellAutoHeight; property CellEndEllipsis; property CellTextMaxLineCount; property ScrollBars; property ShowEditButtons; end; { TcxTreeListOptionsCustomizing } TcxTreeListOptionsCustomizing = class(TcxOwnedPersistent) private FBandCustomizing: Boolean; FBandHiding: Boolean; FBandHorzSizing: Boolean; FBandMoving: Boolean; FBandsQuickCustomization: Boolean; FBandsQuickCustomizationMaxDropDownCount: Integer; FBandVertSizing: Boolean; FColumnCustomizing: Boolean; FColumnHiding: Boolean; FColumnHorzSizing: Boolean; FColumnMoving: Boolean; FColumnsQuickCustomization: Boolean; FColumnsQuickCustomizationMaxDropDownCount: Integer; FColumnVertSizing: Boolean; FDynamicSizing: Boolean; FNestedBands: Boolean; FNodeSizing: Boolean; FRowSizing: Boolean; function GetTreeList: TcxCustomTreeList; procedure SetBandCustomizing(AValue: Boolean); procedure SetBandHiding(AValue: Boolean); procedure SetBandHorzSizing(AValue: Boolean); procedure SetBandMoving(AValue: Boolean); procedure SetBandsQuickCustomization(AValue: Boolean); procedure SetBandVertSizing(AValue: Boolean); procedure SetColumnCustomizing(AValue: Boolean); procedure SetColumnHiding(AValue: Boolean); procedure SetColumnHorzSizing(AValue: Boolean); procedure SetColumnMoving(AValue: Boolean); procedure SetColumnsQuickCustomization(AValue: Boolean); procedure SetColumnVertSizing(AValue: Boolean); procedure SetDynamicSizing(AValue: Boolean); procedure SetNestedBands(AValue: Boolean); procedure SetNodeSizing(AValue: Boolean); procedure SetRowSizing(AValue: Boolean); protected procedure Changed; virtual; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; property TreeList: TcxCustomTreeList read GetTreeList; published property BandCustomizing: Boolean read FBandCustomizing write SetBandCustomizing default True; property BandHorzSizing: Boolean read FBandHorzSizing write SetBandHorzSizing default True; property BandHiding: Boolean read FBandHiding write SetBandHiding default False; property BandMoving: Boolean read FBandMoving write SetBandMoving default True; property BandsQuickCustomization: Boolean read FBandsQuickCustomization write SetBandsQuickCustomization default False; property BandsQuickCustomizationMaxDropDownCount: Integer read FBandsQuickCustomizationMaxDropDownCount write FBandsQuickCustomizationMaxDropDownCount default 0; property BandVertSizing: Boolean read FBandVertSizing write SetBandVertSizing default True; property ColumnCustomizing: Boolean read FColumnCustomizing write SetColumnCustomizing default True; property ColumnHiding: Boolean read FColumnHiding write SetColumnHiding default False; property ColumnHorzSizing: Boolean read FColumnHorzSizing write SetColumnHorzSizing default True; property ColumnMoving: Boolean read FColumnMoving write SetColumnMoving default True; property ColumnsQuickCustomization: Boolean read FColumnsQuickCustomization write SetColumnsQuickCustomization default False; property ColumnsQuickCustomizationMaxDropDownCount: Integer read FColumnsQuickCustomizationMaxDropDownCount write FColumnsQuickCustomizationMaxDropDownCount default 0; property ColumnVertSizing: Boolean read FColumnVertSizing write SetColumnVertSizing default True; property DynamicSizing: Boolean read FDynamicSizing write SetDynamicSizing default False; property NestedBands: Boolean read FNestedBands write SetNestedBands default True; property NodeSizing: Boolean read FNodeSizing write SetNodeSizing default False; property RowSizing: Boolean read FRowSizing write SetRowSizing default False; end; { TcxTreeListOptionsSelection } TcxTreeListOptionsSelection = class(TcxOwnedPersistent) private FCellSelect: Boolean; FHideFocusRect: Boolean; FHideSelection: Boolean; FInvertSelect: Boolean; FMultiSelect: Boolean; function GetTreeList: TcxCustomTreeList; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; property TreeList: TcxCustomTreeList read GetTreeList; published property CellSelect: Boolean read FCellSelect write FCellSelect default True; property HideFocusRect: Boolean read FHideFocusRect write FHideFocusRect default True; property HideSelection: Boolean read FHideSelection write FHideSelection default False; property InvertSelect: Boolean read FInvertSelect write FInvertSelect default True; property MultiSelect: Boolean read FMultiSelect write FMultiSelect default False; end; TcxTreeListOptionsSelectionClass = class of TcxTreeListOptionsSelection; { TcxTreeListOptionsBehavior } TcxTreeListOptionsBehavior = class(TcxControlOptionsBehavior) private FAutoDragCopy: Boolean; FConfirmDelete: Boolean; FDragCollapse: Boolean; FDragExpand: Boolean; FDragFocusing: Boolean; FExpandOnDblClick: Boolean; FExpandOnIncSearch: Boolean; FFooterHints: Boolean; FHeaderHints: Boolean; FHotTrack: Boolean; FMultiSort: Boolean; FShowHourGlass: Boolean; FSorting: Boolean; FWaitExpandingTime: Integer; function GetChangeDelay: Integer; function GetIncSearchItem: TcxTreeListColumn; function GetTreeList: TcxCustomTreeList; procedure ReadBoolean(AReader: TReader); procedure SetChangeDelay(AValue: Integer); procedure SetFooterHints(AValue: Boolean); procedure SetHeaderHints(AValue: Boolean); procedure SetIncSearchItem(AValue: TcxTreeListColumn); protected procedure DefineProperties(Filer: TFiler); override; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; property TreeList: TcxCustomTreeList read GetTreeList; published property AutoDragCopy: Boolean read FAutoDragCopy write FAutoDragCopy default False; property ChangeDelay: Integer read GetChangeDelay write SetChangeDelay default 0; property ConfirmDelete: Boolean read FConfirmDelete write FConfirmDelete default True; property DragCollapse: Boolean read FDragCollapse write FDragCollapse default True; property DragDropText; property DragExpand: Boolean read FDragExpand write FDragExpand default True; property DragFocusing: Boolean read FDragFocusing write FDragFocusing default False; property ExpandOnDblClick: Boolean read FExpandOnDblClick write FExpandOnDblClick default True; property ExpandOnIncSearch: Boolean read FExpandOnIncSearch write FExpandOnIncSearch default False; property FocusCellOnCycle; property FooterHints: Boolean read FFooterHints write SetFooterHints default False; property HeaderHints: Boolean read FHeaderHints write SetHeaderHints default False; property HotTrack: Boolean read FHotTrack write FHotTrack default False; property IncSearch; property IncSearchItem: TcxTreeListColumn read GetIncSearchItem write SetIncSearchItem default nil; property MultiSort: Boolean read FMultiSort write FMultiSort default True; property ShowHourGlass: Boolean read FShowHourGlass write FShowHourGlass default True; property Sorting: Boolean read FSorting write FSorting default True; property WaitForExpandNodeTime: Integer read FWaitExpandingTime write FWaitExpandingTime default 500; end; { TcxTreeListOptionsData } TcxTreeListOptionsData = class(TcxControlOptionsData) private FDeleting: Boolean; FInserting: Boolean; FSummaryNullIgnore: Boolean; function GetAnsiSort: Boolean; function GetCaseInsensitive: Boolean; procedure SetAnsiSort(Value: Boolean); procedure SetCaseInsensitive(Value: Boolean); procedure SetSummaryNullIgnore(Value: Boolean); protected procedure Changed; override; 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 read FDeleting write FDeleting default True; property Inserting: Boolean read FInserting write FInserting default False; property SummaryNullIgnore: Boolean read FSummaryNullIgnore write SetSummaryNullIgnore default False; end; { TcxTreeListPreview } TcxTreeListPreviewPlace = (tlppBottom, tlppTop); TcxTreeListPreview = class(TcxOwnedInterfacedPersistent) private FAutoHeight: Boolean; FColumn: TcxTreeListColumn; FLeftIndent: Integer; FMaxLineCount: Integer; FPlace: TcxTreeListPreviewPlace; FRightIndent: Integer; FVisible: Boolean; function GetActive: Boolean; function GetTreeList: TcxCustomTreeList; procedure SetAutoHeight(AValue: Boolean); procedure SetColumn(AValue: TcxTreeListColumn); procedure SetLeftIndent(AValue: Integer); procedure SetMaxLineCount(AValue: Integer); procedure SetPlace(AValue: TcxTreeListPreviewPlace); procedure SetRightIndent(AValue: Integer); procedure SetVisible(AValue: Boolean); protected procedure Changed; virtual; function GetControl: TObject; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; property Active: Boolean read GetActive; property TreeList: TcxCustomTreeList 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 5; property MaxLineCount: Integer read FMaxLineCount write SetMaxLineCount default 3; property Place: TcxTreeListPreviewPlace read FPlace write SetPlace default tlppBottom; property RightIndent: Integer read FRightIndent write SetRightIndent default 5; 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 } TcxTreeListGetBandContentStyleEvent = procedure(Sender: TcxCustomTreeList; ABand: TcxTreeListBand; ANode: TcxTreeListNode; var AStyle: TcxStyle) of object; TcxTreeListGetBandStyleEvent = procedure(Sender: TcxCustomTreeList; ABand: TcxTreeListBand; var AStyle: TcxStyle) of object; TcxTreeListGetColumnFooterStyleEvent = procedure(Sender: TcxCustomTreeList; AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; AFooterItem: TcxTreeListSummaryItem; var AStyle: TcxStyle) of object; TcxTreeListGetColumnStyleEvent = procedure(Sender: TcxCustomTreeList; AColumn: TcxTreeListColumn; var AStyle: TcxStyle) of object; TcxTreeListGetContentStyleEvent = procedure(Sender: TcxCustomTreeList; AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; var AStyle: TcxStyle) of object; TcxTreeListGetNodeIndentStyleEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; ALevel: Integer; var AStyle: TcxStyle) of object; TcxTreeListGetPreviewStyleEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; var AStyle: TcxStyle) of object; TcxTreeListStyles = class(TcxCustomControlStyles) private FOnGetBandBackgroundStyle: TcxTreeListGetBandStyleEvent; FOnGetBandContentStyle: TcxTreeListGetBandContentStyleEvent; FOnGetBandHeaderStyle: TcxTreeListGetBandStyleEvent; FOnGetBandFooterStyle: TcxTreeListGetBandContentStyleEvent; FOnGetColumnFooterStyle: TcxTreeListGetColumnFooterStyleEvent; FOnGetColumnHeaderStyle: TcxTreeListGetColumnStyleEvent; FOnGetContentStyle: TcxTreeListGetContentStyleEvent; FOnGetHotTrackStyle: TcxTreeListGetContentStyleEvent; FOnGetNodeIndentStyle: TcxTreeListGetNodeIndentStyleEvent; FOnGetPreviewStyle: TcxTreeListGetPreviewStyleEvent; function GetLoolAndFeel: TcxLookAndFeel; function GetTreeList: TcxCustomTreeList; protected procedure DoGetBandBackgroundParams(ABand: TcxTreeListBand; var AParams: TcxViewParams); virtual; procedure DoGetBandContentParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode; var AParams: TcxViewParams); virtual; procedure DoGetBandFooterParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode; var AParams: TcxViewParams); virtual; procedure DoGetBandHeaderParams(ABand: TcxTreeListBand; var AParams: TcxViewParams); virtual; procedure DoGetColumnFooterParams(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem; var AParams: TcxViewParams); virtual; procedure DoGetColumnHeaderParams(AColumn: TcxTreeListColumn; var AParams: TcxViewParams); virtual; procedure DoGetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AParams: TcxViewParams); virtual; procedure DoGetNodeContentParams(ANode: TcxTreeListNode; AStyle: TcxStyle; var AParams: TcxViewParams); virtual; procedure DoGetPreviewParams(ANode: TcxTreeListNode; var AParams: TcxViewParams); virtual; procedure GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); override; function SelectionFontAssigned: Boolean; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; function GetBandBackgroundParams(ABand: TcxTreeListBand): TcxViewParams; function GetBandContentParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode): TcxViewParams; function GetBandFooterParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode): TcxViewParams; function GetBandHeaderParams(ABand: TcxTreeListBand): TcxViewParams; function GetColumnFooterParams(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem = nil): TcxViewParams; function GetColumnHeaderParams(AColumn: TcxTreeListColumn): TcxViewParams; function GetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxViewParams; function GetFooterParams: TcxViewParams; function GetIncSearchParams: TcxViewParams; function GetIndentParams(ANode: TcxTreeListNode; AIndent: Integer): TcxViewParams; function GetIndicatorParams: TcxViewParams; function GetPreviewParams(ANode: TcxTreeListNode): TcxViewParams; property LookAndFeel: TcxLookAndFeel read GetLoolAndFeel; property TreeList: TcxCustomTreeList read GetTreeList; 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: TcxTreeListGetBandStyleEvent read FOnGetBandBackgroundStyle write FOnGetBandBackgroundStyle; property OnGetBandContentStyle: TcxTreeListGetBandContentStyleEvent read FOnGetBandContentStyle write FOnGetBandContentStyle; property OnGetBandFooterStyle: TcxTreeListGetBandContentStyleEvent read FOnGetBandFooterStyle write FOnGetBandFooterStyle; property OnGetBandHeaderStyle: TcxTreeListGetBandStyleEvent read FOnGetBandHeaderStyle write FOnGetBandHeaderStyle; property OnGetColumnFooterStyle: TcxTreeListGetColumnFooterStyleEvent read FOnGetColumnFooterStyle write FOnGetColumnFooterStyle; property OnGetColumnHeaderStyle: TcxTreeListGetColumnStyleEvent read FOnGetColumnHeaderStyle write FOnGetColumnHeaderStyle; property OnGetContentStyle: TcxTreeListGetContentStyleEvent read FOnGetContentStyle write FOnGetContentStyle; property OnGetHotTrackStyle: TcxTreeListGetContentStyleEvent read FOnGetHotTrackStyle write FOnGetHotTrackStyle; property OnGetNodeIndentStyle: TcxTreeListGetNodeIndentStyleEvent read FOnGetNodeIndentStyle write FOnGetNodeIndentStyle; property OnGetPreviewStyle: TcxTreeListGetPreviewStyleEvent read FOnGetPreviewStyle write FOnGetPreviewStyle; property Background; property Content; property Inactive; property Selection; property StyleSheet; end; { TcxTreeListItemsCustomizeListBox } TcxTreeListItemsCustomizeListBox = class(TcxListBox) private FHeaders: TcxObjectList; FTreeList: TcxCustomTreeList; function GetHeader(AIndex: Integer): TcxTreeListHeaderCellViewInfo; function GetPainter: TcxCustomLookAndFeelPainterClass; protected procedure AddItem(ACaption: TcxTreeListCaption); function CreateCell: TcxTreeListHeaderCellViewInfo; virtual; abstract; procedure DblClick; override; procedure DoDrawItem(AControl: TcxListBox; ACanvas: TcxCanvas; AIndex: Integer; ARect: TRect; AState: TOwnerDrawState); virtual; procedure DoDrawItemEx(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); function GetItemHeight(AItem: Integer): Integer; virtual; function GetOrigin(AHeader: TcxTreeListHeaderCellViewInfo): TPoint; procedure PopulateItems; virtual; abstract; procedure MakeItemVisible(AHeader: TcxTreeListHeaderCellViewInfo); virtual; abstract; procedure MeasureItem(AControl: TcxListBox; Index: Integer; var Height: Integer); virtual; procedure Paint; override; procedure RefreshList; procedure Resize; override; function StartDragAndDrop(const P: TPoint): Boolean; override; property Headers[Index: Integer]: TcxTreeListHeaderCellViewInfo read GetHeader; property Painter: TcxCustomLookAndFeelPainterClass read GetPainter; public constructor CreateEx(AOwner: TComponent; ATreeList: TcxCustomTreeList; AParent: TWinControl); destructor Destroy; override; property TreeList: TcxCustomTreeList read FTreeList; end; TcxTreeListColumnsCustomizeListBox = class(TcxTreeListItemsCustomizeListBox) protected function CreateCell: TcxTreeListHeaderCellViewInfo; override; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; procedure MakeItemVisible(AHeader: TcxTreeListHeaderCellViewInfo); override; procedure PopulateItems; override; end; TcxTreeListBandsCustomizeListBox = class(TcxTreeListItemsCustomizeListBox) protected function CreateCell: TcxTreeListHeaderCellViewInfo; override; function GetDragAndDropObjectClass: TcxDragAndDropObjectClass; override; procedure MakeItemVisible(AHeader: TcxTreeListHeaderCellViewInfo); override; procedure PopulateItems; override; end; { TcxTreeListCustomizationForm } TcxTreeListCustomizationForm = class(TForm) private FDragDropListBox: TcxTreeListItemsCustomizeListBox; FHookTimer: TcxTimer; FOwner: TcxTreeListCustomizing; function GetTreeList: TcxCustomTreeList; protected procedure CreateParams(var Params: TCreateParams); override; procedure FinishDragDrop(Sender: TcxTreeListItemsCustomizeListBox); procedure StartDragDrop(Sender: TcxTreeListItemsCustomizeListBox); procedure TimerHandler(Sender: TObject); public constructor CreateEx(AOwner: TcxTreeListCustomizing); destructor Destroy; override; property HookTimer: TcxTimer read FHookTimer; property Customizing: TcxTreeListCustomizing read FOwner; property DragDropListBox: TcxTreeListItemsCustomizeListBox read FDragDropListBox; property TreeList: TcxCustomTreeList read GetTreeList; end; { TcxTreeListCustomizing } TcxTreeListCustomizing = class(TcxOwnedInterfacedPersistent, IcxTreeListDesigner) private FBandListBox: TcxTreeListItemsCustomizeListBox; FBounds: TRect; FForm: TcxTreeListCustomizationForm; FHeaderListBox: TcxTreeListItemsCustomizeListBox; FIsPositionAssigned: Boolean; FPageControl: TcxPageControl; FRowCount: Integer; FTabSheetBands: TcxTabSheet; FTabSheetHeaders: TcxTabSheet; function GetForm: TForm; function GetIsSimpleMode: Boolean; function GetPosition: TPoint; function GetTreeList: TcxCustomTreeList; function GetVisible: Boolean; procedure SetPosition(const AValue: TPoint); procedure SetRowCount(AValue: Integer); procedure SetVisible(AValue: Boolean); protected procedure CalculateSize(var AWidth, AHeight: Integer); procedure Close(Sender: TObject; var Action: TCloseAction); virtual; procedure CreateControls; virtual; procedure CreateCustomizingForm; virtual; procedure FinishCustomizing(const ABounds: TRect); virtual; procedure HideCustomizingForm; procedure SetControlParent(AControl, AParent: TWinControl); procedure ShowCustomizingForm; procedure Update; virtual; // IcxTreeListDesigner procedure ComponentModified; virtual; procedure ComponentRemoved(Sender: TObject); virtual; property BandListBox: TcxTreeListItemsCustomizeListBox read FBandListBox; property HeaderListBox: TcxTreeListItemsCustomizeListBox read FHeaderListBox; property SimpleMode: Boolean read GetIsSimpleMode; public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure MakeBandPageVisible; procedure MakeColumnPageVisible; function PtInCustomizingBox(const APoint: TPoint): Boolean; property Form: TForm read GetForm; property IsPositionAssigned: Boolean read FIsPositionAssigned write FIsPositionAssigned; property Position: TPoint read GetPosition write SetPosition; property RowCount: Integer read FRowCount write SetRowCount default 10; property TreeList: TcxCustomTreeList read GetTreeList; property Visible: Boolean read GetVisible write SetVisible; end; TcxTreeListCustomizingClass = class of TcxTreeListCustomizing; { TcxTreeListDataController } TcxTreeListForEachNodeProc = procedure(ANode: TcxTreeListNode; Data: Pointer) of object; TcxTreeListDataController = class(TcxControlDataController) private FAllocatedRecords: Integer; FEditingNode: TcxTreeListNode; FIsValueChanged: Boolean; FNodesCount: Integer; function GetHasEditData: Boolean; function GetRoot: TcxTreeListNode; function GetTreeList: TcxCustomTreeList; function GetValueDef(AIndex: Integer): TcxValueDef; procedure FreeRecordProc(ANode: TcxTreeListNode; AData: Pointer); procedure InsertValueDef(AColumn: TcxTreeListColumn); procedure InsertValueDefProc(ANode: TcxTreeListNode; AData: Pointer); procedure SetEditingNode(AValue: TcxTreeListNode); procedure SetIsValueChanged(AValue: Boolean); procedure RemoveValueDef(AColumn: TcxTreeListColumn); procedure RemoveValueDefProc(ANode: TcxTreeListNode; AData: Pointer); protected function Compare(AValueDef: TcxValueDef; AHandle1, AHandle2: Pointer): Integer; function CopyData(ASource: TcxTreeListNode): Pointer; procedure DestroyHandles; procedure ForEachRecord(AProc: TcxTreeListForEachNodeProc; AData: Pointer); function IsLoading: Boolean; override; procedure PostRecord; virtual; procedure PostValues; virtual; procedure SetNodeData(ASource: Pointer; ADest: TcxTreeListNode); function StringCompare(const V1, V2: Variant): Integer; virtual; procedure SyncFocused(ANode: TcxTreeListNode); virtual; property EditingNode: TcxTreeListNode read FEditingNode write SetEditingNode; property IsValueChanged: Boolean read FIsValueChanged write SetIsValueChanged; property TreeList: TcxCustomTreeList read GetTreeList; property ValueDefs[AIndex: Integer]: TcxValueDef read GetValueDef; public constructor Create(AOwner: TComponent); override; function AddItem(AItem: TObject): TcxCustomDataField; override; function AllocateRecord: Pointer; procedure ChangeValueTypeClass(AItemIndex: Integer; AValueTypeClass: TcxValueTypeClass); override; function CompareNodesByColumns(ANode1, ANode2: TcxTreeListNode; AColumns: TList): Integer; virtual; procedure FreeNodeRecord(ANode: TcxTreeListNode); procedure FreeRecord(var ARecord: Pointer); function GetDisplayText(ARecordIndex, AItemIndex: Integer): string; override; function GetNodeDisplayText(ANode: TcxTreeListNode; AIndex: Integer): Variant; virtual; function GetNodeValue(ANode: TcxTreeListNode; AIndex: Integer): Variant; virtual; function GetValue(ARecordIndex, AItemIndex: Integer): Variant; override; function GetValueForCompare(ANode: TcxTreeListNode; AField: TcxCustomDataField): Variant; procedure InitializeNodeFromRecordIndex(ANode: TcxTreeListNode); procedure InitializeRecordIndexFromNode(ANode: TcxTreeListNode); procedure Cancel; override; procedure Edit; override; procedure Post(AForcePost: Boolean = False); override; procedure PostEditingData; override; procedure RemoveItem(AItem: TObject); override; function SetEditValue(AItemIndex: Integer; const AValue: Variant; AEditValueSource: TcxDataEditValueSource): Boolean; override; procedure SetNodeValue(ANode: TcxTreeListNode; AIndex: Integer; const AValue: Variant); virtual; procedure SetValue(ARecordIndex, AItemIndex: Integer; const Value: Variant); override; procedure UpdateItemIndexes; override; property AllocatedRecords: Integer read FAllocatedRecords; property HasEditData: Boolean read GetHasEditData; property NodesCount: Integer read FNodesCount; property Root: TcxTreeListNode read GetRoot; end; { TcxTreeListCustomPopupMenu } TcxTreeListCustomPopupMenu = class(TcxOwnedPersistent) private FPopupMenu: TComponent; protected function GetRoot: TComponent; virtual; abstract; function GetTreeList: TcxCustomTreeList; virtual; abstract; function Popup(X, Y: Integer): Boolean; virtual; procedure SetPopupMenu(AValue: TComponent); virtual; property PopupMenu: TComponent read FPopupMenu write SetPopupMenu; public property Root: TComponent read GetRoot; property TreeList: TcxCustomTreeList read GetTreeList; end; { TcxTreeListCustomBuiltInMenu } TcxTreeListBuiltInMenuItemType = (tlmitDefault, tlmitChecked, tlmitSubItem); TcxTreeListCustomBuiltInMenu = class(TcxTreeListCustomPopupMenu) protected function CreateMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean = True; AItemType: TcxTreeListBuiltInMenuItemType = tlmitDefault; AChecked: Boolean = False; AImageIndex: Integer = -1; AWithSeparator: Boolean = False; AInternal: Boolean = True): TComponent; virtual; abstract; procedure CreatePopupMenu; virtual; procedure DestroyPopupMenu; virtual; procedure GetBitmapFromImageList(AImages: TCustomImageList; AImageIndex: Integer; ABitmap: TBitmap); function GetImages(AInternal: Boolean): TCustomImageList; function GetPopupClass: TComponentClass; virtual; abstract; function GetRoot: TComponent; override; function GetTreeList: TcxCustomTreeList; override; procedure Initialize; procedure MenuItemClickHandler(Sender: TObject); virtual; public destructor Destroy; override; end; TcxTreeListCustomBuiltInMenuClass = class of TcxTreeListCustomBuiltInMenu; { TcxTreeListBuiltInMenu } TcxTreeListBuiltInMenu = class(TcxTreeListCustomBuiltInMenu) private function GetPopupMenu: TPopupMenu; protected function CreateMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean = True; AItemType: TcxTreeListBuiltInMenuItemType = tlmitDefault; AChecked: Boolean = False; AImageIndex: Integer = -1; AWithSeparator: Boolean = False; AInternal: Boolean = True): TComponent; override; function GetPopupClass: TComponentClass; override; function GetRoot: TComponent; override; procedure CreatePopupMenu; override; public property PopupMenu: TPopupMenu read GetPopupMenu; end; { TcxTreeListPopupMenu } TcxTreeListPopupMenuClickEvent = procedure(Sender: TcxCustomTreeList; AItem: TObject; var AHandled: Boolean) of object; TcxTreeListPopupMenuPopupEvent = procedure(Sender: TcxCustomTreeList; AContextMenu: TcxTreeListPopupMenu; var AHandled: Boolean) of object; TcxTreeListPopupMenu = class(TcxTreeListCustomPopupMenu) private FBuiltInMenu: TcxTreeListCustomBuiltInMenu; FImages: TCustomImageList; FUseBuiltInMenu: Boolean; FUserImages: TCustomImageList; FOnClick: TcxTreeListPopupMenuClickEvent; FOnPopup: TcxTreeListPopupMenuPopupEvent; function GetBuiltInMenu: TcxTreeListCustomBuiltInMenu; function GetImages: TCustomImageList; procedure SetUseBuiltInMenu(AValue: Boolean); procedure SetUserImages(AValue: TCustomImageList); protected function CreateInternalMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean = True; AItemType: TcxTreeListBuiltInMenuItemType = tlmitDefault; AChecked: Boolean = False; AImageIndex: Integer = -1; AWithSeparator: Boolean = False): TComponent; procedure CreateItems; virtual; procedure DoExecute(ACommand: Integer); virtual; procedure DoMenuItemClick(Sender: TObject); procedure DoClick(AItem: TObject; var AHandled: Boolean); virtual; function DoPopup: Boolean; virtual; function DoShowPopupMenu(const P: TPoint): Boolean; virtual; function GetResourceImagesCount: Integer; virtual; function GetResourceImagesNamePrefix: string; virtual; function GetRoot: TComponent; override; function GetTreeList: TcxCustomTreeList; override; procedure InitializeInternalMenu; function IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; virtual; procedure LoadResourceImages; virtual; procedure Notification(AComponent: TComponent; Operation: TOperation); virtual; function Popup(X, Y: Integer): Boolean; override; procedure SetPopupMenu(AValue: TComponent); override; property Images: TCustomImageList read GetImages; public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; function CreateMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean = True; AItemType: TcxTreeListBuiltInMenuItemType = tlmitDefault; AChecked: Boolean = False; AImageIndex: Integer = -1; AWithSeparator: Boolean = False): TComponent; property BuiltInMenu: TcxTreeListCustomBuiltInMenu read GetBuiltInMenu; property UserImages: TCustomImageList read FUserImages write SetUserImages; published property PopupMenu; property UseBuiltInMenu: Boolean read FUseBuiltInMenu write SetUseBuiltInMenu default False; property OnClick: TcxTreeListPopupMenuClickEvent read FOnClick write FOnClick; property OnPopup: TcxTreeListPopupMenuPopupEvent read FOnPopup write FOnPopup; end; TcxTreeListPopupMenuClass = class of TcxTreeListPopupMenu; { TcxTreeListFooterPopupMenu } TcxTreeListFooterPopupMenuItem = (tlfmiSum, tlfmiMin, tlfmiMax, tlfmiAverage, tlfmiCount, tlfmiNone, tlfmiAllNodes); TcxTreeListFooterPopupMenuItems = set of TcxTreeListFooterPopupMenuItem; TcxTreeListFooterPopupMenu = class(TcxTreeListPopupMenu) private FItems: TcxTreeListFooterPopupMenuItems; FSummaryItems: TcxTreeListSummaryItems; function GetVisibleItemKinds: TcxSummaryKinds; function IsAllNodes: Boolean; function IsItemEnabled(AKind: TcxSummaryKind): Boolean; function IsItemsStored: Boolean; protected procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; function GetResourceImagesCount: Integer; override; function GetResourceImagesNamePrefix: string; override; function IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; override; property SummaryItems: TcxTreeListSummaryItems read FSummaryItems; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; published property Items: TcxTreeListFooterPopupMenuItems read FItems write FItems stored IsItemsStored; end; { TcxTreeListGroupFooterPopupMenu } TcxTreeListGroupFooterPopupMenu = class(TcxTreeListFooterPopupMenu) protected function IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; override; end; { TcxTreeListColumnHeaderPopupMenu } TcxTreeListColumnHeaderPopupMenuItem = (tlchmiSortAscending, tlchmiSortDescending, tlchmiClearSorting, tlchmiFooter, tlchmiGroupFooters, tlchmiRemoveThisColumn, tlchmiFieldChooser, tlchmiHorzAlignment, tlchmiVertAlignment, tlchmiBestFit, tlchmiBestFitAllColumns); TcxTreeListColumnHeaderPopupMenuItems = set of TcxTreeListColumnHeaderPopupMenuItem; TcxTreeListColumnHeaderPopupMenu = class(TcxTreeListPopupMenu) private FColumn: TcxTreeListColumn; FItems: TcxTreeListColumnHeaderPopupMenuItems; FSeparatorNeeded: Boolean; procedure CreateAlignmentSubMenus; function IsItemsStored: Boolean; function IsSeparatorNeeded: Boolean; protected procedure CreateItems; override; procedure DoExecute(ACommand: Integer); override; function GetResourceImagesCount: Integer; override; function GetResourceImagesNamePrefix: string; override; function IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; override; property Column: TcxTreeListColumn read FColumn write FColumn; public constructor Create(AOwner: TPersistent); override; procedure Assign(Source: TPersistent); override; published property Items: TcxTreeListColumnHeaderPopupMenuItems read FItems write FItems stored IsItemsStored; end; { TcxTreeListPopupMenus } TcxTreeListPopupMenus = class(TcxOwnedPersistent) private FMenus: TObjectList; FColumnHeaderMenu: TcxTreeListColumnHeaderPopupMenu; FFooterMenu: TcxTreeListFooterPopupMenu; FGroupFooterMenu: TcxTreeListGroupFooterPopupMenu; function GetHitTest: TcxTreeListHitTest; function GetTreeList: TcxCustomTreeList; procedure SetColumnHeaderMenu(AValue: TcxTreeListColumnHeaderPopupMenu); procedure SetFooterMenu(AValue: TcxTreeListFooterPopupMenu); procedure SetGroupFooterMenu(AValue: TcxTreeListGroupFooterPopupMenu); protected procedure CreateMenus; function DoShowPopupMenu(const P: TPoint): Boolean; procedure Notification(AComponent: TComponent; Operation: TOperation); property HitTest: TcxTreeListHitTest read GetHitTest; public constructor Create(AOwner: TPersistent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; property TreeList: TcxCustomTreeList read GetTreeList; published property ColumnHeaderMenu: TcxTreeListColumnHeaderPopupMenu read FColumnHeaderMenu write SetColumnHeaderMenu; property FooterMenu: TcxTreeListFooterPopupMenu read FFooterMenu write SetFooterMenu; property GroupFooterMenu: TcxTreeListGroupFooterPopupMenu read FGroupFooterMenu write SetGroupFooterMenu; end; { TcxTreeListSummary } TcxTreeListSummary = class private FAbsoluteFooterSummaryItems: TList; FAbsoluteGroupFooterSummaryItems: TList; FFooterSummaryRowCount: Integer; FFooterSummaryVisibleCount: Integer; FGroupFooterSummaryRowCount: Integer; FGroupFooterSummaryVisibleCount: Integer; FIsDirty: Boolean; FTreeList: TcxCustomTreeList; function GetFooterSummaryCount: Integer; function GetFooterSummaryItem(AIndex: Integer): TcxTreeListSummaryItem; function GetFooterSummaryText(ASummaryItem: TcxTreeListSummaryItem): string; function GetFooterSummaryValue(ASummaryItem: TcxTreeListSummaryItem): Variant; function GetGroupFooterSummaryCount: Integer; function GetGroupFooterSummaryItem(AIndex: Integer): TcxTreeListSummaryItem; function GetGroupFooterSummaryText(ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode): string; function GetGroupFooterSummaryValue(ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode): Variant; function GetRoot: TcxTreeListNode; procedure SetFooterSummaryValue(ASummaryItem: TcxTreeListSummaryItem; const Value: Variant); procedure SetGroupFooterSummaryValue(ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode; const Value: Variant); protected procedure AddSummaryItems(AAbsoluteSummaryItems: TList; ASummaryItems: TcxTreeListSummaryItems; AIsVisible: Boolean; var AVisibleCount, AVisibleRowCount: Integer); procedure Calculate; procedure CalculateNode(ADestNode, AValueNode: TcxTreeListNode; AItems: TList); procedure CheckChanges; virtual; function DoProcessSummaryValue(ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem; var ASummaryValue: Variant; var ASummaryCount: Integer; var AValue: Variant; var ACount: Integer): Boolean; procedure FinalizeValues(ANode: TcxTreeListNode; AItems: TList); procedure InitializeValues(ANode: TcxTreeListNode; AItems: TList); procedure Notification(AComponent: TComponent; Operation: TOperation); procedure ProcessNode(AParent: TcxTreeListNode); procedure ProcessSummaryValue(ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem; var ASummaryValue: Variant; var ASummaryCount: Integer); procedure ProcessSummaryValues(ADestNode, AValueNode: TcxTreeListNode; AItems: TList); property IsDirty: Boolean read FIsDirty write FIsDirty; property Root: TcxTreeListNode read GetRoot; public constructor Create(ATreeList: TcxCustomTreeList); virtual; destructor Destroy; override; procedure Recalculate; property FooterSummaryCount: Integer read GetFooterSummaryCount; property FooterSummaryRowCount: Integer read FFooterSummaryRowCount; property FooterSummaryVisibleCount: Integer read FFooterSummaryVisibleCount; property FooterSummaryItems[Index: Integer]: TcxTreeListSummaryItem read GetFooterSummaryItem; property FooterSummaryTexts[ASummaryItem: TcxTreeListSummaryItem]: string read GetFooterSummaryText; property FooterSummaryValues[ASummaryItem: TcxTreeListSummaryItem]: Variant read GetFooterSummaryValue write SetFooterSummaryValue; property GroupFooterSummaryCount: Integer read GetGroupFooterSummaryCount; property GroupFooterSummaryRowCount: Integer read FGroupFooterSummaryRowCount; property GroupFooterSummaryVisibleCount: Integer read FGroupFooterSummaryVisibleCount; property GroupFooterSummaryItems[Index: Integer]: TcxTreeListSummaryItem read GetGroupFooterSummaryItem; property GroupFooterSummaryTexts[ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode]: string read GetGroupFooterSummaryText; property GroupFooterSummaryValues[ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode]: Variant read GetGroupFooterSummaryValue write SetGroupFooterSummaryValue; property TreeList: TcxCustomTreeList read FTreeList; end; TcxTreeListSummaryClass = class of TcxTreeListSummary; { TcxTreeListLevelInfo } TcxTreeListLevelInfo = class private FImages: TCustomImageList; FImagesChangeLink: TChangeLink; FOffset: Integer; FSize: TSize; FStateImages: TCustomImageList; FStateImagesChangeLink: TChangeLink; FTreeList: TcxCustomTreeList; FWidth: Integer; function GetTotalWidth: Integer; function GetDynamicIndent: Boolean; procedure SetImages(AValue: TCustomImageList); procedure SetStateImages(AValue: TCustomImageList); protected procedure Changed(Sender: TObject); procedure Notification(AComponent: TComponent; Operation: TOperation); function Update(const AOffset: Integer): Integer; public constructor Create(ATreeList: TcxCustomTreeList); destructor Destroy; override; property DynamicIndent: Boolean read GetDynamicIndent; property Images: TCustomImageList read FImages write SetImages; property Offset: Integer read FOffset write FOffset; property Size: TSize read FSize; property StateImages: TCustomImageList read FStateImages write SetStateImages; property TotalWidth: Integer read GetTotalWidth; property TreeList: TcxCustomTreeList read FTreeList; property Width: Integer read FWidth; end; { TcxTreeListLikeParams } TcxTreeListLikeParams = class private FPercent: Char; FUnderline: Char; public constructor Create(APercent: Char = '%'; AUnderline: Char = '_'); property Percent: Char read FPercent write FPercent; property UnderLine: Char read FUnderline write FUnderline; end; { TcxCustomTreeList } TcxTreeListNodeChangedEvent = procedure( Sender: TcxCustomTreeList; ANode: TcxTreeListNode) of object; TcxTreeListNodeCheckChangedEvent = procedure( Sender: TcxCustomTreeList; ANode: TcxTreeListNode; AState: TcxCheckBoxState) of object; TcxTreeListNodeChangingEvent = procedure( Sender: TcxCustomTreeList; ANode: TcxTreeListNode; var Allow: Boolean) of object; TcxTreeListColumnChangedEvent = procedure( Sender: TcxCustomTreeList; AColumn: TcxTreeListColumn) of object; TcxTreeListBandChangedEvent = procedure( Sender: TcxCustomTreeList; ABand: TcxTreeListBand) of object; TcxTreeListMoveToEvent = procedure(Sender: TcxCustomTreeList; AttachNode: TcxTreeListNode; AttachMode: TcxTreeListNodeAttachMode; Nodes: TList; var IsCopy, Done: Boolean) of object; TcxTreeListNodeCompareEvent = procedure(Sender: TcxCustomTreeList; ANode1, ANode2: TcxTreeListNode; var ACompare: Integer) of object; TcxTreeListFocusedNodeChangedEvent = procedure(Sender: TcxCustomTreeList; APrevFocusedNode, AFocusedNode: TcxTreeListNode) of object; TcxTreeListGetCellHintEvent = procedure(Sender: TcxCustomTreeList; ACell: TObject; var AText: string; var ANeedShow: Boolean) of object; TcxTreeListGetLevelImagesEvent = procedure(Sender: TcxCustomTreeList; ALevel: Integer; var AImages, AStateImages: TCustomImageList) of object; TcxTreeListGetNodeImageIndexEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; AIndexType: TcxTreeListImageIndexType; var AIndex: TImageIndex) of object; TcxTreeListGetNodeHeightEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; var AHeight: Integer) of object; TcxTreeListGetPreviewTextEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; var AText: string) of object; TcxTreeListGetNodePreviewHeightEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; const ADisplayValue: Variant; var AHeight: Integer) of object; TcxTreeListIsGroupNodeEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; var IsGroup: Boolean) of object; TcxTreeListEditingEvent = procedure(Sender: TcxCustomTreeList; AColumn: TcxTreeListColumn; var Allow: Boolean) of object; TcxTreeListFocusedColumnChanged = procedure(Sender: TcxCustomTreeList; APrevFocusedColumn, AFocusedColumn: TcxTreeListColumn) of object; TcxTreeListHotTrackNodeEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; AShift: TShiftState; var ACursor: TCursor) of object; TcxTreeListNodeDataChangedEvent = procedure(Sender: TcxCustomTreeList; ANode: TcxTreeListNode; AColumn: TcxTreeListColumn) of object; TcxTreeListCustomDrawBandCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListBandCellViewInfo; var ADone: Boolean) of object; TcxTreeListCustomDrawBackgroundCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListCustomCellViewInfo; var ADone: Boolean) of object; TcxTreeListCustomDrawHeaderCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListHeaderCellViewInfo; var ADone: Boolean) of object; TcxTreeListCustomDrawEditCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListEditCellViewInfo; var ADone: Boolean) of object; TcxTreeListCustomDrawIndentCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListIndentCellViewInfo; var ADone: Boolean) of object; TcxTreeListCustomDrawIndicatorCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListIndicatorCellViewInfo; var ADone: Boolean) of object; TcxTreeListCustomDrawFooterCellEvent = procedure(Sender: TcxCustomTreeList; ACanvas: TcxCanvas; AViewInfo: TcxTreeListFooterCellViewInfo; var ADone: Boolean) of object; TcxTreeListFindMode = (tlfmNormal, tlfmLike, tlfmExact); //// V5 TcxTreeListSummaryEventArguments = record Node: TcxTreeListNode; SummaryItem: TcxTreeListSummaryItem; end; TcxTreeListSummaryEventOutArguments = record Value: Variant; SummaryValue: Variant; CountValue: Integer; Done: Boolean; end; TcxTreeListSummaryEvent = procedure(ASender: TcxCustomTreeList; const Arguments: TcxTreeListSummaryEventArguments; var OutArguments: TcxTreeListSummaryEventOutArguments) of object; TcxCustomTreeList = class(TcxExtEditingControl, IcxNavigator, IcxStoredParent, IcxStoredObject, IcxTreeListDesignTimeOperations, IdxSkinSupport) private FAbsoluteItems: TList; FAbsoluteVisibleItems: TList; FBands: TcxTreeListBands; FDefaultLevelInfo: TcxTreeListLevelInfo; FChanges: TcxTreeListChanges; FChangesLocked: Boolean; FCustomizing: TcxTreeListCustomizing; FDefaultIndentSize: TSize; FDefaultLayout: Boolean; FDefaultRowHeight: Integer; FDelayTimer: TTimer; FDesigners: TList; FDragNode: TcxTreeListNode; FExpansionLevel: Integer; FIgnoreLoadingStatus: Boolean; FIsCancelOperation: Boolean; FIsRestoring: Boolean; FLevelsInfo: TcxObjectList; FLockChanges: Boolean; FNavigatorNotifier: TcxNavigatorControlNotifier; FNeedSort: Boolean; FOptionsCustomizing: TcxTreeListOptionsCustomizing; FOptionsSelection: TcxTreeListOptionsSelection; FPopupMenus: TcxTreeListPopupMenus; FPopupMenusEvents: TNotifyEvent; FPostChanged: Boolean; FPreview: TcxTreeListPreview; FRoot: TcxTreeListNode; FSortedColumns: TList; FSelectionList: TList; FStoredCursor: TCursor; FStylesEvents: TNotifyEvent; FSummary: TcxTreeListSummary; FTopVisibleNode: TcxTreeListNode; FVisibleColumns: TList; FOnBandHeaderClick: TcxTreeListBandChangedEvent; FOnBandSizeChanged: TcxTreeListBandChangedEvent; FOnCanFocusNode: TcxTreeListNodeChangingEvent; FOnCanSelectNode: TcxTreeListNodeChangingEvent; FOnChange: TNotifyEvent; FOnColumnHeaderClick: TcxTreeListColumnChangedEvent; FOnColumnSizeChanged: TcxTreeListColumnChangedEvent; FOnCompare: TcxTreeListNodeCompareEvent; // FGlassCursorRefCount: Integer; FOnBeginDragNode: TcxTreeListNodeChangingEvent; FOnCollapsed: TcxTreeListNodeChangedEvent; FOnCollapsing: TcxTreeListNodeChangingEvent; FOnCustomDrawBackgroundCell: TcxTreeListCustomDrawBackgroundCellEvent; FOnCustomDrawBandCell: TcxTreeListCustomDrawBandCellEvent; FOnCustomDrawBandHeaderCell: TcxTreeListCustomDrawHeaderCellEvent; FOnCustomDrawDataCell: TcxTreeListCustomDrawEditCellEvent; FOnCustomDrawFooterCell: TcxTreeListCustomDrawFooterCellEvent; FOnCustomDrawHeaderCell: TcxTreeListCustomDrawHeaderCellEvent; FOnCustomDrawIndentCell: TcxTreeListCustomDrawIndentCellEvent; FOnCustomDrawIndicatorCell: TcxTreeListCustomDrawIndicatorCellEvent; FOnCustomDrawPreviewCell: TcxTreeListCustomDrawEditCellEvent; FOnCustomizationVisibleChanged: TNotifyEvent; FOnDeletion: TcxTreeListNodeChangedEvent; FOnExpanded: TcxTreeListNodeChangedEvent; FOnExpanding: TcxTreeListNodeChangingEvent; FOnGetLevelImages: TcxTreeListGetLevelImagesEvent; FOnGetNodeHeight: TcxTreeListGetNodeHeightEvent; FOnGetNodeImageIndex: TcxTreeListGetNodeImageIndexEvent; FOnGetNodePreviewHeight: TcxTreeListGetNodePreviewHeightEvent; // TL5 FOnAfterSummary: TNotifyEvent; FOnDataChanged: TNotifyEvent; FOnFocusedColumnChanged: TcxTreeListFocusedColumnChanged; FOnFocusedNodeChanged: TcxTreeListFocusedNodeChangedEvent; FOnGetCellHint: TcxTreeListGetCellHintEvent; // IcxStoredObject events FOnGetStoredProperties: TcxGetStoredPropertiesEvent; FOnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent; FOnInitStoredObject: TcxInitStoredObjectEvent; FOnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent; FOnHotTrackNode: TcxTreeListHotTrackNodeEvent; FOnIsGroupNode: TcxTreeListIsGroupNodeEvent; FOnLayoutChanged: TNotifyEvent; FOnMoveTo: TcxTreeListMoveToEvent; FOnNodeChanged: TcxTreeListNodeDataChangedEvent; FOnNodeCheckChanged: TcxTreeListNodeCheckChangedEvent; FOnSelectionChanged: TNotifyEvent; FOnSorted: TNotifyEvent; FOnSorting: TNotifyEvent; FOnSummary: TcxTreeListSummaryEvent; FOnTopRecordIndexChanged: TNotifyEvent; function GetAvailableContentWidth: Integer; function GetAbsoluteCount: Integer; function GetAbsoluteItem(AIndex: Integer): TcxTreeListNode; function GetAbsoluteItemsList: TList; function GetAbsoluteVisibleCount: Integer; function GetAbsoluteVisibleItem(AIndex: Integer): TcxTreeListNode; function GetAbsoluteVisibleItemsList: TList; function GetBands: TcxTreeListBands; function GetColumn(AIndex: Integer): TcxTreeListColumn; function GetColumnCount: Integer; function GetColumnsList: TList; function GetController: TcxTreeListController; function GetCount: Integer; function GetDataController: TcxTreeListDataController; function GetDefaultRowHeight: Integer; function GetFocusedColumn: TcxTreeListColumn; function GetFocusedNode: TcxTreeListNode; function GetHitTest: TcxTreeListHitTest; function GetImages: TCustomImageList; function GetIndentWidth: Integer; function GetInplaceEditor: TcxCustomEdit; function GetIsCancelOperation: Boolean; function GetIsEditing: Boolean; function GetIsInserting: Boolean; function GetItem(Index: Integer): TcxTreeListNode; function GetLastNode: TcxTreeListNode; function GetLastVisibleNode: TcxTreeListNode; function GetLevelInfo(ALevel: Integer): TcxTreeListLevelInfo; function GetNavigatorIsActive: Boolean; function GetOnEdited: TcxTreeListColumnChangedEvent; function GetOnEditing: TcxTreeListEditingEvent; function GetOnEditValueChanged: TcxTreeListColumnChangedEvent; function GetOptionsBehavior: TcxTreeListOptionsBehavior; function GetOptionsData: TcxTreeListOptionsData; function GetOptionsView: TcxTreeListOptionsView; function GetSearching: Boolean; function GetSearchingText: string; function GetSelection(AIndex: Integer): TcxtreeListNode; function GetSelectionCount: Integer; function GetSorted: Boolean; function GetSortedColumnCount: Integer; function GetSortedColumn(Index: Integer): TcxTreeListColumn; function GetStateImages: TCustomImageList; function GetStyles: TcxTreeListStyles; function GetTopNode: TcxTreeListNode; function GetTopVisibleNode: TcxTreeListNode; function GetVisibleCount: Integer; function GetViewInfo: TcxTreeListViewInfo; function GetVisibleColumn(AIndex: Integer): TcxTreeListColumn; function GetVisibleColumnCount: Integer; procedure SetAbsoluteItem(AIndex: Integer; AValue: TcxTreeListNode); procedure SetAbsoluteVisibleItem(AIndex: Integer; AValue: TcxTreeListNode); procedure SetBands(Value: TcxTreeListBands); procedure SetColumn(AIndex: Integer; Value: TcxTreeListColumn); procedure SetDefaultRowHeight(AValue: Integer); procedure SetDefaultLayout(AValue: Boolean); procedure SetFocusedColumn(AValue: TcxTreeListColumn); procedure SetFocusedNodeProp(Value: TcxTreeListNode); procedure SetImages(AValue: TCustomImageList); procedure SetIsRestoring(AValue: Boolean); procedure SetLastVisibleNode(AValue: TcxTreeListNode); procedure SetOnEdited(Value: TcxTreeListColumnChangedEvent); procedure SetOnEditing(Value: TcxTreeListEditingEvent); procedure SetOnEditValueChanged(Value: TcxTreeListColumnChangedEvent); procedure SetOptionsBehavior(Value: TcxTreeListOptionsBehavior); procedure SetOptionsCustomizing(Value: TcxTreeListOptionsCustomizing); procedure SetOptionsData(Value: TcxTreeListOptionsData); procedure SetOptionsSelection(Value: TcxTreeListOptionsSelection); procedure SetOptionsView(Value: TcxTreeListOptionsView); procedure SetPopupMenus(Value: TcxTreeListPopupMenus); procedure SetPreview(Value: TcxTreeListPreview); procedure SetSearchingText(const Value: string); procedure SetSorted(Value: Boolean); procedure SetStateImages(AValue: TCustomImageList); procedure SetStyles(Value: TcxTreeListStyles); procedure SetTopVisibleNode(ANode: TcxTreeListNode); 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 // V5 procedure AddChanges(AChanges: TcxTreeListChanges); function AddNode(ANode, ARelative: TcxTreeListNode; AData: Pointer; AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode; virtual; function AddNodeInternal(ANode, ARelative: TcxTreeListNode; AddMethod: TcxTreeListNodeAttachMode): TcxTreeListNode; virtual; procedure AfterMouseDown(AButton: TMouseButton; X, Y: Integer); override; procedure AssignData(ASource: TcxCustomTreeList); virtual; procedure AssignOptions(ASource: TcxCustomTreeList); virtual; procedure BeforeUpdate; override; procedure BoundsChanged; override; procedure CalculateForceIndentWidth; function CanCompare: Boolean; virtual; procedure CheckChanges; virtual; procedure CheckEvents; procedure CheckLevelsInfo; virtual; procedure CheckSelectionAndFocused; procedure CheckSortOrderList; procedure CheckStructure; virtual; procedure ClearCalculatedWidths; procedure ColumnSortOrderChanged(AColumn: TcxTreeListColumn; AShift: TShiftState); function CreateNode: TcxTreeListNode; virtual; procedure CreateSubClasses; override; procedure DestroySubClasses; override; procedure DoAfterSummary; virtual; procedure DoBandHeaderClick(ABand: TcxTreeListBand); virtual; function DoBeginDragNode(ANode: TcxTreeListNode): Boolean; function DoCanFocusNode(ANode: TcxTreeListNode): Boolean; virtual; function DoCanNodeCollapse(ANode: TcxTreeListNode): Boolean; virtual; function DoCanNodeExpand(ANode: TcxTreeListNode): Boolean; virtual; function DoCanSelectNode(ANode: TcxTreeListNode): Boolean; virtual; procedure DoChanged(BlockChangedEvent: Boolean = True); virtual; procedure DoColumnHeaderClick(AColumn: TcxTreeListColumn); virtual; procedure DoCompare(ANode1, ANode2: TcxTreeListNode; var ACompare: Integer); virtual; procedure DoCustomizationVisibleChanged; virtual; procedure DoDataChangedEvent(Sender: TObject); virtual; procedure DoDeletion(ANode: TcxTreeListNode); virtual; procedure DoEditValueChanged(AItem: TcxCustomInplaceEditContainer); override; procedure DoExpand(ANode: TcxTreeListNode); virtual; procedure DoFocusedItemChanged(APrevFocusedItem, AFocusedItem: TcxCustomInplaceEditContainer); virtual; procedure DoFocusedNodeChanged(APrevNode, AFocusedNode: TcxTreeListNode); virtual; procedure DoGetCellHint(ACell: TObject; var AText: string; var ANeedShow: Boolean); override; procedure DoGetLevelImages(AInfo: TcxTreeListLevelInfo; ALevel: Integer); virtual; procedure DoGetNodeHeight(ANode: TcxTreeListNode; var AHeight: Integer); virtual; function DoGetNodeImageIndex(ANode: TcxTreeListNode; AIndex: TcxTreeListImageIndexType): TImageIndex; virtual; procedure DoGetPreviewHeight(ANode: TcxTreeListNode; var AHeight: Integer); virtual; procedure DoHotTrackNode(ANode: TcxTreeListNode; AShift: TShiftState; var ACursor: TCursor); virtual; function DoIsGroupNode(ANode: TcxTreeListNode): Boolean; virtual; procedure DoLayoutChangedEvent; virtual; function DoMoveToEvent(AttachNode: TcxTreeListNode; AttachMode: TcxTreeListNodeAttachMode; Nodes: TList; var IsCopy: Boolean): Boolean; virtual; procedure DoNodeChanged(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn); virtual; procedure DoNodeCheckChanged(ANode: TcxTreeListNode; AState: TcxCheckBoxState); virtual; procedure DoNodeCollapsed(ANode: TcxTreeListNode); virtual; procedure DoNodeExpanded(ANode: TcxTreeListNode); virtual; procedure DoSelectAll; virtual; procedure DoSelectionChanged; virtual; procedure DoSetNodeFocused(ANode: TcxTreeListNode; AValue: Boolean; Shift: TShiftState = []); virtual; procedure DoSorted; virtual; procedure DoSorting; virtual; procedure DoSortNodes; virtual; procedure DoStartDrag(var DragObject: TDragObject); override; procedure DoTopRecordIndexChanged; virtual; procedure ForceLayoutChanged; virtual; // used classes function GetBandItemClass: TcxTreeListBandClass; virtual; function GetControllerClass: TcxCustomControlControllerClass; override; function GetControlStylesClass: TcxCustomControlStylesClass; override; function GetDataControllerClass: TcxCustomDataControllerClass; override; function GetEditingControllerClass: TcxEditingControllerClass; override; function GetHitTestControllerClass: TcxHitTestControllerClass; override; function GetOptionsBehaviorClass: TcxControlOptionsBehaviorClass; override; function GetOptionsCustomizingClass: TcxTreeListOptionsCustomizingClass; virtual; function GetOptionsDataClass: TcxControlOptionsDataClass; override; function GetOptionsSelectionClass: TcxTreeListOptionsSelectionClass; virtual; function GetOptionsViewClass: TcxControlOptionsViewClass; override; function GetPainterClass: TcxCustomControlPainterClass; override; function GetPreviewClass: TcxTreeListPreviewClass; virtual; function GetRootClass: TcxTreeListNodeClass; virtual; function GetSummaryClass: TcxTreeListSummaryClass; virtual; function GetTreeListColumnClass: TcxTreeListColumnClass; virtual; function GetTreeListCustomizingClass: TcxTreeListCustomizingClass; virtual; function GetViewInfoClass: TcxCustomControlViewInfoClass; override; // function GetCountNodeForBestFit: Integer; virtual; function GetDefaultColumnContainer: TcxTreeListBand; function GetSameColumn(AColumn: TcxTreeListColumn): TcxTreeListColumn; function GetStartNodeForBestFit: TcxTreeListNode; virtual; function IsLocked: Boolean; override; function IsTreeListLocked: Boolean; virtual; procedure ImageChanged; procedure ImagesChanged(Sender: TObject); virtual; procedure InternalClearAll; procedure InternalCopy(ANode, ADestNode: TcxTreeListNode); virtual; procedure InternalDelete(ANodes: TList); procedure InternalMove(ANode, ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode); virtual; procedure InvalidateRectEx(const R: TRect; EraseBackground: Boolean); override; function IsNodeEdited(ANode: TcxTreeListNode): Boolean; function IsNodeInserting(ANode: TcxTreeListNode): Boolean; virtual; procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); override; procedure RefreshFields; virtual; procedure SetNodeParent(ANewNode, ANewParent: TcxTreeListNode; AMode: TcxTreeListNodeAddMode); procedure StructureChanged; virtual; procedure UpdateFocusedNode(AColumn: TcxTreeListColumn); virtual; procedure ValidateStates; procedure BeforeShowingEdit; function CanMultiSelect: Boolean; virtual; procedure DoBandSizeChanged(ABand: TcxTreeListBand); virtual; procedure DoClear; virtual; procedure DoColumnSizeChanged(AColumn: TcxTreeListColumn); virtual; function DoCreateColumn: TcxTreeListColumn; procedure DoDeleteSelection; virtual; procedure DoDeleteNode(ANode: TcxTreeListNode); virtual; 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 DoOnBandSizeChanged(ABand: TcxTreeListBand); virtual; procedure DoOnColumnSizeChanged(AColumn: TcxTreeListColumn); virtual; // function DoWriteHeaderToText: string; virtual; function DoWriteNodeToText(ANode: TcxTreeListNode): string; virtual; procedure DoWriteToClipboard(AOnlySelected: Boolean); virtual; function DoWriteToText(AOnlySelected: Boolean; out AText: string): Boolean; procedure DeleteNodes(AList: TList); virtual; function GetIsActive: Boolean; virtual; function GetFixedContentSize: Integer; virtual; function GetMaxBandWidth(ABand: TcxTreeListBand): Integer; function GetMouseWheelScrollingKind: TcxMouseWheelScrollingKind; override; procedure InitInsertingNode(ANode: TcxTreeListNode); virtual; function InsertNode(ARelative: TcxTreeListNode; IsAppend: Boolean): Boolean; virtual; procedure MakeNodeVisible(ANode: TcxTreeListNode); virtual; procedure RestoreCursor; procedure SetGlassCursor; procedure SortingStateChanged(AColumn: TcxTreeListColumn; AShift: TShiftState); // IcxTreeListDesignTimeOperations implementation function SupportBandColumnEditor: Boolean; virtual; function SupportItemsEditor: Boolean; virtual; function SupportCreateAllItems: Boolean; 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; // updates // nodes // procedure DoSetNodeSelected(ANode: TcxTreeListNode; Value: Boolean; Shift: TShiftState = []); virtual; function GetSelectionsEx: TList; // sorting // overrided methods procedure CheckCreateDesignSelectionHelper; override; procedure ControlUpdateData(AInfo: TcxUpdateControlInfo); override; procedure DataChanged; override; procedure DataLayoutChanged; override; procedure DoLayoutChanged; override; function DoShowPopupMenu(AMenu: TComponent; X, Y: Integer): Boolean; override; function DragDropImageDisplayRect: TRect; override; procedure DrawDragDropImage(ADragBitmap: TBitmap; ACanvas: TcxCanvas); override; function GetDragDropText: string; virtual; function GetDragDropViewParams: TcxViewParams; virtual; function GetDragObjectClass: TDragControlObjectClass; override; procedure InitScrollBarsParameters; override; // inherits for loading bug fixing procedure AssignItemsPosition; procedure ReadState(Reader: TReader); override; procedure SaveItemsPosition; procedure Updated; override; procedure Updating; override; // 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 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 AbsoluteItemsList: TList read GetAbsoluteItemsList; property AbsoluteVisibleItemsList: TList read GetAbsoluteVisibleItemsList; property AvailableContentWidth: Integer read GetAvailableContentWidth; property ChangeDelayTimer: TTimer read FDelayTimer; property Changes: TcxTreeListChanges read FChanges write FChanges; property ChangesLocked: Boolean read FChangesLocked write FChangesLocked; property ColumnsList: TList read GetColumnsList; property Controller: TcxTreeListController read GetController; property DataController: TcxTreeListDataController read GetDataController; property IgnoreLoadingStatus: Boolean read FIgnoreLoadingStatus write FIgnoreLoadingStatus; property IsCancelOperation: Boolean read GetIsCancelOperation write FIsCancelOperation; property IndentWidth: Integer read GetIndentWidth; property IsRestoring: Boolean read FIsRestoring write SetIsRestoring; property LockChanges: Boolean read FLockChanges write FLockChanges; property LevelsInfo[ALevel: Integer]: TcxTreeListLevelInfo read GetLevelInfo; property StoredCursor: TCursor read FStoredCursor; property ViewInfo: TcxTreeListViewInfo read GetViewInfo; property OnAfterSummary: TNotifyEvent read FOnAfterSummary write FOnAfterSummary; property OnBandHeaderClick: TcxTreeListBandChangedEvent read FOnBandHeaderClick write FOnBandHeaderClick; property OnBandSizeChanged: TcxTreeListBandChangedEvent read FOnBandSizeChanged write FOnBandSizeChanged; property OnBeginDragNode: TcxTreeListNodeChangingEvent read FOnBeginDragNode write FOnBeginDragNode; property OnCanFocusNode: TcxTreeListNodeChangingEvent read FOnCanFocusNode write FOnCanFocusNode; 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: TcxTreeListColumnChangedEvent read FOnColumnSizeChanged write FOnColumnSizeChanged; property OnCompare: TcxTreeListNodeCompareEvent read FOnCompare write FOnCompare; property OnCustomDrawBackgroundCell: TcxTreeListCustomDrawBackgroundCellEvent read FOnCustomDrawBackgroundCell write FOnCustomDrawBackgroundCell; property OnCustomDrawBandCell: TcxTreeListCustomDrawBandCellEvent read FOnCustomDrawBandCell write FOnCustomDrawBandCell; property OnCustomDrawBandHeaderCell: TcxTreeListCustomDrawHeaderCellEvent read FOnCustomDrawBandHeaderCell write FOnCustomDrawBandHeaderCell; property OnCustomDrawDataCell: TcxTreeListCustomDrawEditCellEvent read FOnCustomDrawDataCell write FOnCustomDrawDataCell; property OnCustomDrawFooterCell: TcxTreeListCustomDrawFooterCellEvent read FOnCustomDrawFooterCell write FOnCustomDrawFooterCell; property OnCustomDrawHeaderCell: TcxTreeListCustomDrawHeaderCellEvent read FOnCustomDrawHeaderCell write FOnCustomDrawHeaderCell; property OnCustomDrawIndentCell: TcxTreeListCustomDrawIndentCellEvent read FOnCustomDrawIndentCell write FOnCustomDrawIndentCell; property OnCustomDrawIndicatorCell: TcxTreeListCustomDrawIndicatorCellEvent read FOnCustomDrawIndicatorCell write FOnCustomDrawIndicatorCell; property OnCustomDrawPreviewCell: TcxTreeListCustomDrawEditCellEvent read FOnCustomDrawPreviewCell write FOnCustomDrawPreviewCell; property OnCustomizationFormVisibleChanged: TNotifyEvent read FOnCustomizationVisibleChanged write FOnCustomizationVisibleChanged; property OnDeletion: TcxTreeListNodeChangedEvent read FOnDeletion write FOnDeletion; property OnExpanded: TcxTreeListNodeChangedEvent read FOnExpanded write FOnExpanded; property OnExpanding: TcxTreeListNodeChangingEvent read FOnExpanding write FOnExpanding; property OnGetCellHint: TcxTreeListGetCellHintEvent read FOnGetCellHint write FOnGetCellHint; property OnGetLevelImages: TcxTreeListGetLevelImagesEvent read FOnGetLevelImages write FOnGetLevelImages; property OnGetNodeHeight: TcxTreeListGetNodeHeightEvent read FOnGetNodeHeight write FOnGetNodeHeight; property OnGetNodeImageIndex: TcxTreeListGetNodeImageIndexEvent read FOnGetNodeImageIndex write FOnGetNodeImageIndex; property OnGetNodePreviewHeight: TcxTreeListGetNodePreviewHeightEvent read FOnGetNodePreviewHeight write FOnGetNodePreviewHeight; property OnHotTrackNode: TcxTreeListHotTrackNodeEvent read FOnHotTrackNode write FOnHotTrackNode; property OnIsGroupNode: TcxTreeListIsGroupNodeEvent read FOnIsGroupNode write FOnIsGroupNode; property OnMoveTo: TcxTreeListMoveToEvent read FOnMoveTo write FOnMoveTo; property OnNodeChanged: TcxTreeListNodeDataChangedEvent read FOnNodeChanged write FOnNodeChanged; property OnNodeCheckChanged: TcxTreeListNodeCheckChangedEvent read FOnNodeCheckChanged write FOnNodeCheckChanged; property OnSelectionChanged: TNotifyEvent read FOnSelectionChanged write FOnSelectionChanged; property OnSorted: TNotifyEvent read FOnSorted write FOnSorted; property OnSorting: TNotifyEvent read FOnSorting write FOnSorting; property OnSummary: TcxTreeListSummaryEvent read FOnSummary write FOnSummary; property OnTopRecordIndexChanged: TNotifyEvent read FOnTopRecordIndexChanged write FOnTopRecordIndexChanged; property PopupMenusEvents: TNotifyEvent read FPopupMenusEvents write FPopupMenusEvents; property StylesEvents: TNotifyEvent read FStylesEvents write FStylesEvents; // property OnDataChanged: TNotifyEvent read FOnDataChanged write FOnDataChanged; property OnEdited: TcxTreeListColumnChangedEvent read GetOnEdited write SetOnEdited; property OnEditing: TcxTreeListEditingEvent read GetOnEditing write SetOnEditing; property OnEditValueChanged: TcxTreeListColumnChangedEvent read GetOnEditValueChanged write SetOnEditValueChanged; property OnFocusedColumnChanged: TcxTreeListFocusedColumnChanged read FOnFocusedColumnChanged write FOnFocusedColumnChanged; property OnFocusedNodeChanged: TcxTreeListFocusedNodeChangedEvent read FOnFocusedNodeChanged write FOnFocusedNodeChanged; property OnLayoutChanged: TNotifyEvent read FOnLayoutChanged write FOnLayoutChanged; // IcxStoredObject events property OnGetStoredProperties: TcxGetStoredPropertiesEvent read FOnGetStoredProperties write FOnGetStoredProperties; property OnGetStoredPropertyValue: TcxGetStoredPropertyValueEvent read FOnGetStoredPropertyValue write FOnGetStoredPropertyValue; property OnInitStoredObject: TcxInitStoredObjectEvent read FOnInitStoredObject write FOnInitStoredObject; property OnSetStoredPropertyValue: TcxSetStoredPropertyValueEvent read FOnSetStoredPropertyValue write FOnSetStoredPropertyValue; // public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure AdjustColumnsWidth; procedure ApplyBestFit; procedure Cancel; procedure Clear; function CreateColumn(ABand: TcxTreeListBand = nil): TcxTreeListColumn; virtual; procedure DeleteAllColumns; virtual; procedure DeleteSelection; procedure DragDrop(Source: TObject; X, Y: Integer); override; procedure Edit; {$IFDEF DELPHI12} procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; {$ENDIF} procedure MakeDefaultLayout; virtual; procedure Post; procedure FullCollapse; procedure FullExpand; procedure FullRefresh; virtual; function Find(AData: Pointer; AStart: TcxTreeListNode; AExpandedOnly, AForward: Boolean; AFilter: TcxTreeListFindFunc; AIgnoreStartNode: Boolean = False): TcxTreeListNode; virtual; function FindNodeByText(const AText: string; AColumn: TcxTreeListColumn; AStartNode: TcxTreeListNode = nil; AExpandedOnly: Boolean = False; AForward: Boolean = True; ACaseSensitive: Boolean = True; AMode: TcxTreeListFindMode = tlfmNormal; ALikeParams: TcxTreeListLikeParams = nil; AIgnoreStartNode: Boolean = False): TcxTreeListNode; procedure SelectAll; procedure Select(Node: TcxTreeListNode; ShiftState: TShiftState = []); overload; virtual; procedure Select(const ANodes: array of TcxTreeListNode); overload; virtual; procedure Select(ANodesList: TList); overload; virtual; procedure SetFocusedNode(ANode: TcxTreeListNode; 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 AbsoluteCount: Integer read GetAbsoluteCount; property AbsoluteItems[Index: Integer]: TcxTreeListNode read GetAbsoluteItem write SetAbsoluteItem; property AbsoluteVisibleCount: Integer read GetAbsoluteVisibleCount; property AbsoluteVisibleItems[Index: Integer]: TcxTreeListNode read GetAbsoluteVisibleItem write SetAbsoluteVisibleItem; property Bands: TcxTreeListBands read GetBands write SetBands; property ColumnCount: Integer read GetColumnCount; property Columns[Index: Integer]: TcxTreeListColumn read GetColumn write SetColumn; property Count: Integer read GetCount; property Customizing: TcxTreeListCustomizing read FCustomizing write FCustomizing; property DefaultIndentSize: TSize read FDefaultIndentSize; property DefaultLayout: Boolean read FDefaultLayout write SetDefaultLayout default False; property DefaultRowHeight: Integer read GetDefaultRowHeight write SetDefaultRowHeight default 0; property Designers: TList read FDesigners; // for internal use ! property DragNode: TcxTreeListNode read FDragNode; property ExpansionLevel: Integer read FExpansionLevel; property FocusedColumn: TcxTreeListColumn read GetFocusedColumn write SetFocusedColumn; property FocusedNode: TcxTreeListNode read GetFocusedNode write SetFocusedNodeProp; property HitTest: TcxTreeListHitTest read GetHitTest; property Images: TCustomImageList read GetImages write SetImages; property InplaceEditor: TcxCustomEdit read GetInplaceEditor; property IsActive: Boolean read GetIsActive; property IsEditing: Boolean read GetIsEditing; property IsInserting: Boolean read GetIsInserting; property Items[Index: Integer]: TcxTreeListNode read GetItem; property LastNode: TcxTreeListNode read GetLastNode; property LastVisibleNode: TcxTreeListNode read GetLastVisibleNode write SetLastVisibleNode; 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 PopupMenus: TcxTreeListPopupMenus read FPopupMenus write SetPopupMenus; property Preview: TcxTreeListPreview read FPreview write SetPreview; property Root: TcxTreeListNode read FRoot; property Searching: Boolean read GetSearching; property SearchingText: string read GetSearchingText write SetSearchingText; property SelectionCount: Integer read GetSelectionCount; property SelectionList: TList read FSelectionList; property Selections[Index: Integer]: TcxTreeListNode read GetSelection; property Sorted: Boolean read GetSorted write SetSorted; property SortedColumnCount: Integer read GetSortedColumnCount; property SortedColumns[Index: Integer]: TcxTreeListColumn read GetSortedColumn; property StateImages: TCustomImageList read GetStateImages write SetStateImages; property Styles: TcxTreeListStyles read GetStyles write SetStyles; property Summary: TcxTreeListSummary read FSummary; property TopNode: TcxTreeListNode read GetTopNode; property TopVisibleNode: TcxTreeListNode read GetTopVisibleNode write SetTopVisibleNode; property VisibleColumnCount: Integer read GetVisibleColumnCount; property VisibleColumns[Index: Integer]: TcxTreeListColumn read GetVisibleColumn write SetVisibleColumn; property VisibleCount: Integer read GetVisibleCount; property BorderSize; property LookAndFeel; property Color; published { V5 deprecated properties } property BufferedPaint stored False; end; { TcxTreeList } TcxTreeList = class(TcxCustomTreeList) private FDataStream: TMemoryStream; function InternalCreateNode(AParent, APrev: TcxTreeListNode; var AIndex: Integer): TcxTreeListNode; protected procedure AssignData(ASource: TcxCustomTreeList); override; procedure CorrectHandles; procedure DefineProperties(Filer: TFiler); override; procedure Loaded; override; function SupportItemsEditor: Boolean; override; procedure ReadData(AStream: TStream); virtual; procedure ReadStructure(AStream: TStream; AVersion: Integer); procedure WriteData(AStream: TStream); virtual; procedure WriteStructure(AStream: TStream); public 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 Root; property SelectionCount; property Selections; property Sorted; property SortedColumnCount; property SortedColumns; property TopVisibleNode; property VisibleColumnCount; property VisibleColumns; property VisibleCount; published property Align; property Anchors; property Bands; property BorderStyle; property Constraints; property Cursor; property DefaultLayout; property DefaultRowHeight; property DragCursor; property DragKind; property DragMode; property Enabled; property Font; property HelpContext; property HelpKeyword; property HelpType; property Hint; property Images; property LookAndFeel; property OptionsBehavior; property OptionsCustomizing; property OptionsData; property OptionsSelection; property OptionsView; property ParentColor; property ParentFont; property PopupMenu; property PopupMenus; property Preview; property StateImages; property Styles; property TabOrder; property TabStop; property Visible; property OnAfterSummary; property OnBandHeaderClick; property OnBandSizeChanged; property OnBeginDragNode; property OnCanFocusNode; property OnCanResize; property OnCanSelectNode; property OnChange; property OnClick; property OnCollapsed; property OnCollapsing; property OnColumnHeaderClick; property OnColumnSizeChanged; property OnCompare; property OnConstrainedResize; property OnContextPopup; property OnCustomDrawBackgroundCell; property OnCustomDrawBandCell; property OnCustomDrawBandHeaderCell; property OnCustomDrawDataCell; property OnCustomDrawFooterCell; property OnCustomDrawHeaderCell; property OnCustomDrawIndentCell; property OnCustomDrawIndicatorCell; property OnCustomDrawPreviewCell; 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 OnGetCellHint; property OnGetLevelImages; property OnGetNodeHeight; property OnGetNodeImageIndex; property OnGetNodePreviewHeight; property OnGetSiteInfo; property OnGetStoredProperties; property OnGetStoredPropertyValue; property OnHotTrackNode; property OnInitEdit; property OnInitStoredObject; 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 OnNodeCheckChanged; property OnResize; property OnSelectionChanged; property OnSetStoredPropertyValue; property OnSorted; property OnSorting; property OnStartDock; property OnStartDrag; property OnSummary; property OnTopRecordIndexChanged; property OnUnDock; property PopupMenusEvents; property StylesEvents; end; procedure cxTreeListError(const Description: string); function cxCompareNodesByLevel(ANode1, ANode2: TcxTreeListNode): Integer; var cxTreeListBuiltInMenuClass: TcxTreeListCustomBuiltInMenuClass = TcxTreeListBuiltInMenu; DesignerNavigatorProc: procedure(AListener: TObject; AddListener: Boolean) of object; implementation uses Types, RTLConsts, cxLike; {$R cxTL.res} const CRLF = #13#10; Weights: array[TcxTreeListBandFixedKind] of Integer = (0, -1, 1); cxTreeListVersion = $00050000; cxInvalidIndex = -1; cxMinCapacityInc = 32; cxMaxCapacityInc = 32768; cxDefaultImageIndexes: TcxTreeListNodeImageIndexes = (0, 0, -1, -1, -1); // internal column state tlcsVisible = $08; // internal band state tlbsVisible = $00; tlbsFixedLeft = $02; tlbsFixedRight = $04; tlbsAllFixed = tlbsFixedRight or tlbsFixedLeft; ColumnPropertiesName: array[0..10] of string = ('Visible', 'Index', 'LineCount', 'ColIndex', 'RowIndex', 'BandIndex', 'Caption', 'SortOrder', 'SortIndex', 'RealMinWidth', 'RealWidth'); BandPropertiesName: array[0..6] of string = ('Caption', 'RealMinWidth', 'RealWidth', 'Visible', 'Index', 'BandIndex', 'ColIndex'); GridLineBorders: array[TcxTreeListGridLines] of TcxBorders = ([], [bTop, bBottom], [bLeft, bRight], cxBordersAll); OddEvenStyleIndexes: array[Boolean] of Integer =(tlsv_ContentEven, tlsv_ContentOdd); type TAllowExpandChangingFunc = function: Boolean of object; TcxDefColorFunc = function: TColor of object; TcxTreeListStreamHeader = packed record Minor, Major: Word; Size: Integer; end; PcxTreeListValueDefData = ^TcxTreeListValueDefData; TcxTreeListValueDefData = packed record Index: Integer; ValueDef: TcxValueDef; end; { TcxFakeCellViewInfo } TcxFakeCellViewInfo = class(TcxTreeListEditCellViewInfo) private function GetTreeListViewInfo: TcxTreeListViewInfo; protected FCalcHeight: Boolean; FColumn: TcxTreeListColumn; function GetButtonTransparency: TcxEditButtonTransparency; override; function GetControl: TcxEditingControl; override; function GetEditContainer: TcxCustomInplaceEditContainer; override; function GetFocused: Boolean; override; function GetSelected: Boolean; override; procedure Initialize(ANode: TcxTreeListNode; AHeight, AWidth: Integer; ACalcHeight: Boolean); function IsAutoHeight: Boolean; override; function IsEndEllipsis: Boolean; override; public constructor Create(AOwner: TObject); override; destructor Destroy; override; function MeasureHeight(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; AIsCategory: Boolean): Integer; function MeasureWidth(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode): Integer; property TreeListViewInfo: TcxTreeListViewInfo read GetTreeListViewInfo; end; { TcxTreeListCellPos } TcxTreeListCellPos = class public Item: TObject; Node: TcxTreeListNode; constructor Create(ANode: TcxTreeListNode; AItem: TObject); end; function cxFind(ATreeList: TcxCustomTreeList; AData: Pointer; AStart: TcxTreeListNode; AExpandedOnly, AForward: Boolean; AFilter: TcxTreeListFindFunc; AIgnoreStartNode: Boolean): TcxTreeListNode; function LoadChildren(ANode: TcxTreeListNode): Boolean; begin with ANode do begin if (FCount = 0) and HasChildren and not Expanded and not AExpandedOnly then ANode.LoadChildren; 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.Root then Result := nil; end; end; function GetAnother(ANode: TcxTreeListNode): TcxTreeListNode; begin if AForward then Result := GetNext(ANode) else Result := GetPrev(ANode); end; var ACurrent: TcxTreeListNode; begin Result := nil; ACurrent := AStart; if ACurrent = nil then ACurrent := ATreeList.Root.FFirst; ATreeList.BeginUpdate; try while (ACurrent <> nil) and (Result = nil) do begin if AFilter(ACurrent, AData) then begin Result := ACurrent; if AIgnoreStartNode and (Result = AStart) then begin Result := nil; ACurrent := GetAnother(ACurrent); end; end else ACurrent := GetAnother(ACurrent); 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.Count > 0) and not (nsCollapsed in Result.State) do Result := Result.FLast else while Result.HasChildren do begin Result.LoadChildren; if Result.Count > 0 then Result := Result.FLast else Break; end; end; 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; function cxGetNativeColor(AColor: TColor; ADefColorFunc: TcxDefColorFunc): TColor; begin if AColor = clDefault then Result := ADefColorFunc else Result := AColor; end; function cxCompareBandsByPosition( ABand1, ABand2: TcxTreeListBand): Integer; begin Result := ABand1.Position.FBandIndex - ABand2.Position.FBandIndex; if Result = 0 then Result := ABand1.Position.FColIndex - ABand2.Position.FColIndex; if Result = 0 then Result := ABand1.Index - ABand2.Index; end; function cxCompareColumnsByPosition( AColumn1, AColumn2: TcxTreeListColumn): Integer; begin Result := AColumn1.Position.FBandIndex - AColumn2.Position.FBandIndex; if Result = 0 then Result := AColumn1.Position.FRowIndex - AColumn2.Position.FRowIndex; if Result = 0 then Result := AColumn1.Position.FColIndex - AColumn2.Position.FColIndex; if Result = 0 then Result := AColumn1.ItemIndex - AColumn2.ItemIndex; end; function cxCompareColumnsBySortIndex( AColumn1, AColumn2: TcxTreeListColumn): Integer; begin if (AColumn2.SortIndex < 0) and (AColumn1.SortIndex >= 0) then Result := -1 else Result := AColumn1.SortIndex - AColumn2.SortIndex; if Result = 0 then Result := Byte(AColumn1.ActuallyVisible) - Byte(AColumn2.ActuallyVisible); if Result = 0 then Result := cxCompareColumnsByPosition(AColumn1, AColumn2); end; function cxCompareVisibleBands(AItem1, AItem2: Pointer): Integer; begin with TcxTreeListBand(AItem1) do begin Result := Weights[FixedKind] - Weights[TcxTreeListBand(AItem2).FixedKind]; if Result = 0 then Result := Index - TcxTreeListBand(AItem2).Index; end; end; function cxCompareBands(ABand1, ABand2: TcxTreeListBand): Integer; const Weight: array[TcxTreeListBandFixedKind] of Integer = (0, -1, 1); begin Result := Weight[ABand1.FixedKind] - Weight[ABand2.FixedKind]; if Result = 0 then Result := ABand1.Index - ABand2.Index; end; function cxCompareNodes(ANode1, ANode2: TcxTreeListNode): Integer; begin ANode1.TreeList.DoCompare(ANode1, ANode2, Result); end; function cxCompareNodesByAbsoluteIndex( ANode1, ANode2: TcxTreeListNode): Integer; begin Result := ANode1.AbsoluteIndex - ANode2.AbsoluteIndex; end; function cxCompareNodesByRecordIndex( ANode1, ANode2: TcxTreeListNode): Integer; begin Result := Integer(ANode2.Handle) - Integer(ANode1.Handle); end; function cxCompareNodesByLevel( ANode1, ANode2: TcxTreeListNode): Integer; begin Result := ANode2.Level - ANode1.Level; end; function cxCompareCells(ACell1, ACell2: TcxCustomViewInfoItem): Integer; begin Result := ACell1.CustomDrawID - ACell2.CustomDrawID; if Result = 0 then begin Result := ACell1.BoundsRect.Top - ACell2.BoundsRect.Top; if Result = 0 then Result := ACell1.BoundsRect.Left - ACell2.BoundsRect.Left; end; end; function cxCompareHitTestCells(ACell1, ACell2: TcxTreeListHitTestArea): Integer; begin if ACell1.Link = ACell2.Link then Result := ACell1.Area.Top - ACell2.Area.Top else Result := cxCompareCells(ACell1.Link, ACell2.Link); end; procedure cxValidateSingleLine(APos: TcxTreeListColumnPosition); begin APos.FRowIndex := 0; APos.FLineCount := 1; end; procedure cxTreeListError(const Description: string); begin raise EcxTreeList.Create(Description); end; procedure cxTLUnused; begin cxTreeListError('V5 unused'); end; procedure cxError(Condition: Boolean; const Description: string; Args: array of const); overload; begin if Condition then raise Exception.CreateFmt(Description, Args); end; { TcxTreeListHitTest } function TcxTreeListHitTest.CanMoving: Boolean; begin Result := not CanSizing and ((HitAtBandHeader and HitBand.CanMoving) or (HitAtColumnHeader and HitColumn.CanMoving)); end; function TcxTreeListHitTest.CanSizing: Boolean; begin Result := HitAtSizingHorz or HitAtSizingVert; end; function TcxTreeListHitTest.AllowDesignMouseEvents( X, Y: Integer; AShift: TShiftState): Boolean; begin Result := not TreeList.IsLocked and (inherited AllowDesignMouseEvents(X, Y, AShift) or (TreeList.DragAndDropState <> ddsNone) or HitAtBandHeader or HitAtColumnHeader or HitAtBandCustomizing or HitAtColumnCustomizing or CanSizing or HitAtButton or (HitCell is TcxTreeListFooterCellViewInfo) and not TcxTreeListFooterCellViewInfo(HitCell).Hidden); end; function TcxTreeListHitTest.CanShowHint(AItem: TObject): Boolean; begin if AItem is TcxTreeListHeaderCellViewInfo then Result := TreeList.OptionsBehavior.HeaderHints else if AItem is TcxTreeListFooterCellViewInfo then Result := TreeList.OptionsBehavior.FooterHints else Result := inherited CanShowHint(AItem); end; procedure TcxTreeListHitTest.CheckFooterColumn; var AColumnRect, R: TRect; ARow: TcxTreeListBandRow; AColumn: TcxTreeListColumn; AColIndex, ARowIndex, AVisibleRowCount: Integer; begin if (HitBand = nil) or not (HitTestItem is TcxTreeListBandCellViewInfo) then Exit; with TcxTreeListBandCellViewInfo(HitTestItem) do R := cxRectOffset(DisplayRect, GetCellOrigin); AVisibleRowCount := HitBand.BandRows.VisibleItemCount; for ARowIndex := AVisibleRowCount - 1 downto 0 do begin ARow := HitBand.BandRows.VisibleItems[ARowIndex]; for AColIndex := 0 to ARow.VisibleItemCount - 1 do begin AColumn := ARow.VisibleItems[AColIndex]; AColumnRect := AColumn.HeaderCell.DisplayRect; if cxInRange(HitX, AColumnRect.Left, AColumnRect.Right) and cxInRange(HitY, R.Top + MulDiv(cxRectHeight(R), ARow.LineOffset, AVisibleRowCount), R.Bottom) then begin FHitColumn := AColumn; SetHitState(tlhc_HitAtColumn, True); end; end; end; end; procedure TcxTreeListHitTest.CheckSelection(AShift: TShiftState); var AController: TcxTreeListController; I: Integer; begin if not TreeList.IsDesigning then Exit; AController := TcxTreeListController(Controller); if HitAtBandHeader then AController.SelectObject(HitBand, AShift) else if HitAtColumnHeader then AController.SelectObject(HitColumn, AShift) else if HitCell is TcxTreeListFooterSingleCellViewInfo then AController.SelectObject(TcxTreeListFooterSingleCellViewInfo(HitCell).SummaryItem, AShift) else if HitCell is TcxTreeListFooterMultiItemsCellViewInfo then for I := 0 to TcxTreeListFooterMultiItemsCellViewInfo(HitCell).SummaryItems.Count - 1 do if TcxTreeListFooterMultiItemsCellViewInfo(HitCell).SummaryItems[I].Visible then begin AController.SelectObject(TcxTreeListFooterMultiItemsCellViewInfo(HitCell).SummaryItems[I], AShift); AShift := [ssShift]; end; end; procedure TcxTreeListHitTest.DoCalculate; begin ClearState; FHitBand := nil; FHitColumn := nil; FHitNode := nil; if not IsMouseEvent then HitTestItem := nil; FDragItem := nil; if not TreeList.IsLocked then ViewInfo.CalculateHitTest(Self); if HitAtFooter or HitAtGroupFooter then CheckFooterColumn; end; function TcxTreeListHitTest.GetCurrentCursor: TCursor; const ACursors: array[Boolean, Boolean] 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 then Result := ACursors[TreeList.DragAndDropState <> ddsNone, HitAtSizingVert]; end; function TcxTreeListHitTest.GetState(Index: Integer): Boolean; begin Result := (HitState and (1 shl Index)) <> 0; 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; function TcxTreeListHitTest.GetHitAtImages: Boolean; begin Result := HitAtImage or HitAtStateImage; end; function TcxTreeListHitTest.GetHitAtFooterArea: Boolean; begin Result := HitAtFooter or HitAtFooterItem or HitAtGroupFooter or HitAtGroupFooterItem; end; function TcxTreeListHitTest.GetHitAtHeader: Boolean; begin Result := (HitAtBandHeader or HitAtColumnHeader or HitAtBandCustomizing or HitAtColumnCustomizing) and (HitTestItem is TcxTreeListCustomHeaderCellViewInfo); end; function TcxTreeListHitTest.GetHitCell: TcxCustomViewInfoItem; begin Result := HitTestItem as TcxCustomViewInfoItem; end; function TcxTreeListHitTest.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Control); end; function TcxTreeListHitTest.GetViewInfo: TcxTreeListViewInfo; begin Result := TcxTreeListViewInfo(inherited ViewInfo); end; { TcxTreeListHitTestArea } constructor TcxTreeListHitTestArea.Create( ALink: TcxTreeListCustomCellViewInfo); begin FLink := ALink; end; function TcxTreeListHitTestArea.GetHitTest( AHitTest: TcxTreeListHitTest): Boolean; begin Result := PtInRect(Area, AHitTest.HitPoint); if Result then InitHitTest(AHitTest); end; { TcxTreeListHeaderSizingArea } constructor TcxTreeListHeaderSizingArea.CreateEx( ALink: TcxTreeListCustomCellViewInfo; ADirection: TcxDragSizingDirection); begin inherited Create(ALink); FDirection := ADirection; Calculate; end; procedure TcxTreeListHeaderSizingArea.Calculate; begin FArea := cxRectInflate(FLink.DisplayRect, cxtlHitDelta, cxtlHitDelta); if Direction = dsdHorz then begin if FLink.DisplayRect.Right > FLink.VisibleRect.Right then FArea := cxNullRect else FArea.Left := FArea.Right - cxtlHitDelta * 2 end else FArea.Top := FArea.Bottom - cxtlHitDelta * 2; if FLink.HasClipping then IntersectRect(FArea, FArea, cxRectInflate(FLink.VisibleRect, 0, cxtlHitDelta)); end; procedure TcxTreeListHeaderSizingArea.InitHitTest(AHitTest: TcxTreeListHitTest); const AStates: array[TcxDragSizingDirection] of Integer = (tlhc_HitAtSizingHorz, tlhc_HitAtSizingVert); begin AHitTest.SetHitState(AStates[Direction], True); TcxTreeListHeaderCellViewInfo(Link).SetHitItem; AHitTest.DragItem := TcxTreeListHeaderCellViewInfo(Link).Item; if AHitTest.IsItemEditCell then AHitTest.HitTestItem := nil; end; { TcxTreeListNodeSizingArea } constructor TcxTreeListNodeSizingArea.Create(ALink: TcxTreeListCustomCellViewInfo); begin inherited Create(ALink); Calculate; end; destructor TcxTreeListNodeSizingArea.Destroy; begin if FLink <> nil then TcxTreeListIndicatorCellViewInfo(FLink).SizingArea := nil; inherited Destroy; end; procedure TcxTreeListNodeSizingArea.Calculate; begin FArea := cxRectOffset(FLink.DisplayRect, FLink.GetCellOrigin); FArea.Top := FArea.Bottom - cxtlHitDelta; FArea.Bottom := FArea.Bottom + cxtlHitDelta; end; function TcxTreeListNodeSizingArea.GetHitTest( AHitTest: TcxTreeListHitTest): Boolean; begin Result := PtInRect(Area, AHitTest.HitPoint); if Result and Link.TreeList.OptionsCustomizing.RowSizing then Result := Link.TreeList.TopVisibleNode = Link.Node; if Result then InitHitTest(AHitTest); end; procedure TcxTreeListNodeSizingArea.InitHitTest(AHitTest: TcxTreeListHitTest); begin AHitTest.SetHitState(tlhc_HitAtSizingVert, True); AHitTest.SetHitState(tlhc_HitAtNode, True); AHitTest.FHitNode := TcxTreeListIndentCellViewInfo(FLink).AttachNode; AHitTest.FDragItem := AHitTest.FHitNode; end; { TcxCustomTreeList } constructor TcxCustomTreeList.Create(AOwner: TComponent); begin inherited Create(AOwner); FAbsoluteItems := TList.Create; FAbsoluteVisibleItems := TList.Create; ControlStyle := ControlStyle + [csDisplayDragImage]; Width := 250; Height := 150; FRoot := GetRootClass.Create(Self); if Assigned(DesignerNavigatorProc) then DesignerNavigatorProc(Self, True); FChanges := [tcStructure]; end; destructor TcxCustomTreeList.Destroy; begin DataController.Cancel; BeginUpdate; DoClear; ViewInfo.Clear; Customizing.Visible := False; FAbsoluteItems.Free; FAbsoluteVisibleItems.Free; if Assigned(DesignerNavigatorProc) then DesignerNavigatorProc(Self, False); FreeAndNil(FRoot); inherited Destroy; end; procedure TcxCustomTreeList.Assign(Source: TPersistent); begin if Source is TcxCustomTreeList then begin BeginUpdate; try DefaultRowHeight := TcxCustomTreeList(Source).DefaultRowHeight; AssignData(Source as TcxCustomTreeList); AssignOptions(Source as TcxCustomTreeList); DataController.Assign(TcxCustomTreeList(Source).DataController); Styles.Assign(TcxCustomTreeList(Source).DataController); AddChanges([tcStructure..tcSelection]); finally EndUpdate; end; end else inherited Assign(Source); end; procedure TcxCustomTreeList.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].DisplayWidth; for I := 0 to Bands.VisibleItemCount - 1 do Bands.VisibleItems[I].Width := Bands.VisibleItems[I].DisplayWidth; finally EndUpdate; end; OptionsView.ColumnAutoWidth := APrevValue; end; procedure TcxCustomTreeList.ApplyBestFit; var I: Integer; begin BeginUpdate; try for I := 0 to Bands.VisibleItemCount - 1 do Bands.VisibleItems[I].ApplyBestFit; finally EndUpdate; end; end; procedure TcxCustomTreeList.Cancel; begin DataController.Cancel; end; procedure TcxCustomTreeList.Clear; begin BeginUpdate; try DoClear; finally EndUpdate; end; end; procedure TcxCustomTreeList.DoBandSizeChanged(ABand: TcxTreeListBand); begin Modified; LayoutChanged; DoOnBandSizeChanged(ABand); end; procedure TcxCustomTreeList.DoColumnSizeChanged(AColumn: TcxTreeListColumn); begin Modified; DoOnColumnSizeChanged(AColumn); end; function TcxCustomTreeList.DoCreateColumn: TcxTreeListColumn; function GetItemName: string; var I: Integer; begin Result := GetTreeListColumnClass.ClassName; for I := Length(Result) downto 1 do if dxCharInSet(Result[I], ['A'..'Z']) then begin Delete(Result, 1, I - 1); Break; end; end; begin Result := GetTreeListColumnClass.Create(Owner); Result.EditingControl := Self; Result.Name := CreateUniqueName(Owner, Self, Result, scxTLPrefixName, ''); Modified; UpdateDesignerForms; end; function TcxCustomTreeList.CreateColumn( ABand: TcxTreeListBand = nil): TcxTreeListColumn; begin BeginUpdate; try Result := DoCreateColumn; ClearCalculatedWidths; if ABand = nil then ABand := GetDefaultColumnContainer; Result.Position.BandIndex := ABand.Index; finally EndUpdate; end; end; procedure TcxCustomTreeList.DeleteAllColumns; begin BeginUpdate; try ViewInfo.SetDirty; DataController.DestroyHandles; while ColumnCount > 0 do Columns[0].Free; finally EndUpdate; end; end; procedure TcxCustomTreeList.DeleteSelection; begin DoDeleteSelection; end; procedure TcxCustomTreeList.DragDrop(Source: TObject; X, Y: 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); try if Assigned(OnDragDrop) then OnDragDrop(Self, Source, X, Y); Controller.DragDrop(Source, X, Y); FocusedNode := DragNode; finally FDragNode := nil; if FocusedNode <> nil then FocusedNode.MakeVisible; end; end; procedure TcxCustomTreeList.Edit; begin if OptionsData.Editing then DataController.Edit; end; procedure TcxCustomTreeList.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 TcxCustomTreeList.Post; begin DataController.Post; end; procedure TcxCustomTreeList.FullCollapse; begin SetGlassCursor; try Root.Collapse(True); finally RestoreCursor; end; end; procedure TcxCustomTreeList.FullExpand; begin SetGlassCursor; try Root.Expand(True); finally RestoreCursor; end; end; procedure TcxCustomTreeList.FullRefresh; begin AddChanges([tcStructure..tcFocusedNode]); LayoutChanged; end; function TcxCustomTreeList.Find(AData: Pointer; AStart: TcxTreeListNode; AExpandedOnly, AForward: Boolean; AFilter: TcxTreeListFindFunc; AIgnoreStartNode: Boolean = False): TcxTreeListNode; begin Result := cxFind(Self, AData, AStart, AExpandedOnly, AForward, AFilter, AIgnoreStartNode); end; type PFindTextInfo = ^TFindTextInfo; TFindTextInfo = record Text: string; Column: TcxTreeListColumn; CaseSensitive: Boolean; Mode: TcxTreeListFindMode; LikeParams: TcxTreeListLikeParams; IgnoreStartNode: Boolean; end; function FindTextFilter(ANode: TcxTreeListNode; AData: Pointer): Boolean; var ANodeText: string; APercent, AUnderline: Char; begin with PFindTextInfo(AData)^ do begin ANodeText := ANode.Texts[Column.ItemIndex]; if not CaseSensitive then begin ANodeText := AnsiUpperCase(ANodeText); Text := AnsiUpperCase(Text); end; case Mode of tlfmLike: begin if LikeParams = nil then begin APercent := '%'; AUnderline := '_'; end else begin APercent := LikeParams.Percent; AUnderline := LikeParams.UnderLine; end; Result := LikeStr(ANodeText, Text, APercent, AUnderLine); end; tlfmExact: begin Result := ANodeText = Text; end; else Result := AnsiStrPos(PChar(ANodeText), PChar(Text)) <> nil; end; end; end; function TcxCustomTreeList.FindNodeByText(const AText: string; AColumn: TcxTreeListColumn; AStartNode: TcxTreeListNode = nil; AExpandedOnly: Boolean = False; AForward: Boolean = True; ACaseSensitive: Boolean = True; AMode: TcxTreeListFindMode = tlfmNormal; ALikeParams: TcxTreeListLikeParams = nil; AIgnoreStartNode: Boolean = False): TcxTreeListNode; var AFindInfo: TFindTextInfo; begin AFindInfo.Text := AText; AFindInfo.Column := AColumn; AFindInfo.CaseSensitive := ACaseSensitive; AFindInfo.Mode := AMode; AFindInfo.LikeParams := ALikeParams; AFindInfo.IgnoreStartNode := AIgnoreStartNode; Result := Find(@AFindInfo, AStartNode, AExpandedOnly, AForward, FindTextFilter, AIgnoreStartNode); end; procedure TcxCustomTreeList.SetFocusedNode( ANode: TcxTreeListNode; AShift: TShiftState); begin if (ANode = nil) or not ANode.IsVisible then Exit; if OptionsBehavior.AlwaysShowEditor then Controller.SetFocusedRecordItem(Integer(ANode), FocusedColumn) else Controller.FocusedNode := ANode; end; procedure TcxCustomTreeList.SelectAll; begin if not OptionsSelection.MultiSelect or (AbsoluteVisibleCount = 0) then Exit; BeginUpdate; try DoSelectAll; finally EndUpdate; end; end; procedure TcxCustomTreeList.CancelEdit; begin Controller.EditingController.HideEdit(False); end; procedure TcxCustomTreeList.HideEdit; begin Controller.EditingController.HideEdit(True); end; procedure TcxCustomTreeList.Select(Node: TcxTreeListNode; ShiftState: TShiftState = []); begin Controller.Select(Node, ShiftState); end; procedure TcxCustomTreeList.Select(const ANodes: array of TcxTreeListNode); var I: Integer; begin BeginUpdate; try ClearSelection; for I := Low(ANodes) to High(ANodes) do ANodes[I].Selected := True; finally EndUpdate; end; end; procedure TcxCustomTreeList.Select(ANodesList: TList); begin if (ANodesList <> nil) and (ANodesList.Count > 0) then Exit; BeginUpdate; try ClearSelection; SelectionList.Assign(ANodesList); DoSelectionChanged; finally EndUpdate; end end; procedure TcxCustomTreeList.Deselect(Node: TcxTreeListNode); begin Node.Selected := False; end; procedure TcxCustomTreeList.ShowEdit; begin if not OptionsData.Editing then Exit; DataController.Edit; Controller.EditingController.ShowEdit(); end; procedure TcxCustomTreeList.ShowEditByKey(AKey: Char); begin BeforeShowingEdit; with Controller do EditingController.ShowEdit(FocusedItem, AKey); end; procedure TcxCustomTreeList.ShowEditByMouse(X, Y: Integer; AShift: TShiftState); begin BeforeShowingEdit; with Controller do EditingController.ShowEdit(FocusedItem, AShift, X, Y); end; procedure TcxCustomTreeList.RestoreFromIniFile(const AStorageName: string; AChildrenCreating: Boolean = False; AChildrenDeleting: Boolean = False); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName); try AStorage.NamePrefix := Name; if AChildrenCreating then AStorage.Modes := [smChildrenCreating]; if AChildrenDeleting then AStorage.Modes := AStorage.Modes + [smChildrenDeleting]; BeginUpdate; try IsRestoring := True; try AStorage.UseInterfaceOnly := True; AStorage.RestoreFromIni(Self); finally IsRestoring := False; end; finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomTreeList.RestoreFromRegistry(const AStorageName: string; AChildrenCreating: Boolean = False; AChildrenDeleting: Boolean = False); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStorageName); try AStorage.UseInterfaceOnly := True; AStorage.NamePrefix := Name; if AChildrenCreating then AStorage.Modes := [smChildrenCreating]; if AChildrenDeleting then AStorage.Modes := AStorage.Modes + [smChildrenDeleting]; BeginUpdate; try IsRestoring := True; try AStorage.RestoreFromRegistry(Self); finally IsRestoring := False; end; finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomTreeList.RestoreFromStream(AStream: TStream; AChildrenCreating: Boolean = False; AChildrenDeleting: Boolean = False); var AStorage: TcxStorage; begin AStorage := TcxStorage.Create(AStream); try AStorage.UseInterfaceOnly := True; AStorage.NamePrefix := Name; if AChildrenCreating then AStorage.Modes := [smChildrenCreating]; if AChildrenDeleting then AStorage.Modes := AStorage.Modes + [smChildrenDeleting]; BeginUpdate; try IsRestoring := True; try AStorage.RestoreFromStream(Self); finally IsRestoring := False; end; finally EndUpdate; end; finally AStorage.Free; end; end; procedure TcxCustomTreeList.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 TcxCustomTreeList.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 TcxCustomTreeList.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 TcxCustomTreeList.CellRect( ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TRect; var AViewInfo: TcxTreeListEditCellViewInfo; begin AViewInfo := ViewInfo.GetEditCell(ANode, AColumn); if AViewInfo <> nil then Result := AViewInfo.ClipRect else Result := cxInvalidRect; end; // searching function TcxCustomTreeList.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 TcxCustomTreeList.CancelSearching; begin Controller.CancelIncSearching; end; function TcxCustomTreeList.GetEditRect( ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TRect; var AViewInfo: TcxTreeListEditCellViewInfo; begin AViewInfo := ViewInfo.GetEditCell(ANode, AColumn); if AViewInfo <> nil then Result := AViewInfo.EditRect else Result := cxInvalidRect; end; function TcxCustomTreeList.GetNodeAt( X, Y: Integer): TcxTreeListNode; begin HitTest.ReCalculate(cxPoint(X, Y)); if HitTest.HitAtNode then Result := HitTest.HitNode else Result := nil; end; procedure TcxCustomTreeList.CopyAllToClipboard; begin DoWriteToClipboard(False); end; procedure TcxCustomTreeList.CopySelectedToClipboard; begin DoWriteToClipboard(True); end; procedure TcxCustomTreeList.RestoreColumnsDefaults; var I: Integer; begin BeginUpdate; try for I := 0 to ColumnCount - 1 do Columns[I].RestoreDefaults; RestoreColumnsWidths; finally EndUpdate; end; end; procedure TcxCustomTreeList.RestoreColumnsWidths; var I: Integer; begin BeginUpdate; try for I := 0 to ColumnCount - 1 do Columns[I].RestoreDefaults; finally EndUpdate; end; end; procedure TcxCustomTreeList.Subselect(Node: TcxTreeListNode); begin if not CanMultiSelect then cxTreeListError(cxGetResourceString(@scxMultiSelectRequired)) else Node.Selected := True; end; procedure TcxCustomTreeList.ClearSelection(KeepPrimary: Boolean = False); begin Controller.CancelSelection(KeepPrimary) end; procedure TcxCustomTreeList.ClearSorting; begin Sorted := False; end; function TcxCustomTreeList.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 TcxCustomTreeList.GetSelections(AList: TList): TcxTreeListNode; begin AList.Clear; if OptionsSelection.MultiSelect then AList.Assign(SelectionList) else if FocusedNode <> nil then AList.Add(FocusedNode); Result := FocusedNode; end; procedure TcxCustomTreeList.GotoBOF; begin FocusedNode := Root.GetFirstChild; end; procedure TcxCustomTreeList.GotoEOF; begin FocusedNode := cxGetLatest(Root.GetLastChild); end; procedure TcxCustomTreeList.GotoNext; begin if not IsEOF and (FocusedNode <> nil) then FocusedNode := FocusedNode.GetNextVisible; end; procedure TcxCustomTreeList.GotoNextPage; begin Controller.DoNextPage(True, []); end; procedure TcxCustomTreeList.GotoPrev; begin if not IsBOF and (FocusedNode <> nil) then FocusedNode := FocusedNode.GetPrevVisible; end; procedure TcxCustomTreeList.GotoPrevPage; begin Controller.DoNextPage(False, []); end; function TcxCustomTreeList.IsBOF: Boolean; begin Result := (FocusedNode <> nil) and (FocusedNode.GetPrevVisible = nil); end; function TcxCustomTreeList.IsEOF: Boolean; begin Result := (FocusedNode <> nil) and (FocusedNode.GetNextVisible = nil); end; procedure TcxCustomTreeList.CheckCreateDesignSelectionHelper; begin end; procedure TcxCustomTreeList.ControlUpdateData( AInfo: TcxUpdateControlInfo); begin inherited ControlUpdateData(AInfo); ViewInfo.Invalidate(True); RefreshNavigatorButtons; end; procedure TcxCustomTreeList.DataChanged; begin ViewInfo.SetDirty; inherited DataChanged; Include(FChanges, tcData); LayoutChanged; end; procedure TcxCustomTreeList.DataLayoutChanged; begin inherited DataLayoutChanged; Include(FChanges, tcData); LayoutChanged; end; function cxCompareColumnsVisibleOrder(AColumn1, AColumn2: TcxTreeListColumn): Integer; begin Result := Weights[AColumn1.Position.Band.FixedKind] - Weights[AColumn2.Position.Band.FixedKind]; if Result <> 0 then Exit; Result := AColumn1.Position.Band.VisibleIndex - AColumn2.Position.Band.VisibleIndex; if Result = 0 then begin Result := AColumn1.Position.VisibleRowIndex - AColumn2.Position.VisibleRowIndex; if Result = 0 then begin Result := AColumn1.Position.VisibleColIndex - AColumn2.Position.VisibleColIndex; if Result = 0 then Result := AColumn1.VisibleIndex - AColumn2.VisibleIndex; end; end; end; procedure TcxCustomTreeList.DoLayoutChanged; begin IsCancelOperation := False; CheckChanges; ImageChanged; Bands.RefreshInformation; ViewInfo.State[cvis_StyleInvalid] := True; Bands.Adjust; FVisibleColumns.Sort(@cxCompareColumnsVisibleOrder); CalculateForceIndentWidth; inherited DoLayoutChanged; UpdateDesignerForms; DoLayoutChangedEvent; end; function TcxCustomTreeList.DoShowPopupMenu(AMenu: TComponent; X, Y: Integer): Boolean; begin Result := PopupMenus.DoShowPopupMenu(Point(X, Y)); if not Result then Result := inherited DoShowPopupMenu(AMenu, X, Y); end; procedure TcxCustomTreeList.InitScrollBarsParameters; begin if ([csLoading, csDestroying, csUpdating, csReading] * ComponentState <> []) or DataController.IsLoading or (Root = nil) then Exit; ViewInfo.InitScrollBarsParameters; end; procedure TcxCustomTreeList.AssignItemsPosition; var I: Integer; AList: TList; begin IgnoreLoadingStatus := not IsLoading; AList := TList.Create; try // align bands for I := 0 to Bands.Count - 1 do AList.Add(Bands[I]); AList.Sort(@cxCompareBandsByPosition); for I := 0 to AList.Count - 1 do TcxTreeListBand(AList[I]).Position.Restore; // align columns AList.Assign(ColumnsList); AList.Sort(@cxCompareColumnsByPosition); for I := 0 to ColumnCount - 1 do TcxTreeListColumn(AList[I]).Position.Restore; finally AList.Free; end; end; procedure TcxCustomTreeList.ReadState(Reader: TReader); begin SaveItemsPosition; inherited ReadState(Reader); AssignItemsPosition; end; procedure TcxCustomTreeList.SaveItemsPosition; var I: Integer; begin for I := 0 to ColumnCount - 1 do Columns[I].Position.Store; for I := 0 to Bands.Count - 1 do Bands[I].Position.Store; end; procedure TcxCustomTreeList.Updated; begin inherited Updated; AssignItemsPosition; end; procedure TcxCustomTreeList.Updating; begin SaveItemsPosition; inherited Updating; end; function TcxCustomTreeList.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 TcxCustomTreeList.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 TcxCustomTreeList.GetDragDropText: string; begin Result := FDragNode.Texts[VisibleColumns[0].ItemIndex]; end; function TcxCustomTreeList.GetDragDropViewParams: TcxViewParams; begin Result := Styles.GetContentParams(FDragNode, VisibleColumns[0]); with Styles.GetSelectionParams do begin Result.Color := Color; if Styles.SelectionFontAssigned then Result.Font := Font; Result.TextColor := TextColor; end; end; function TcxCustomTreeList.GetDragObjectClass: TDragControlObjectClass; begin Result := nil; end; function TcxCustomTreeList.StartDrag(DragObject: TDragObject): Boolean; begin Result := DragNode <> nil; end; procedure TcxCustomTreeList.GetStoredChildren(AChildren: TStringList); var I: Integer; begin AChildren.AddObject('', Bands); for I := 0 to ColumnCount - 1 do AChildren.AddObject('', Columns[I]); end; function TcxCustomTreeList.GetStoredObjectName: string; begin Result := Name; end; function TcxCustomTreeList.GetStoredObjectProperties( AProperties: TStrings): Boolean; begin if Assigned(OnGetStoredProperties) then OnGetStoredProperties(Self, AProperties); Result := True; end; procedure TcxCustomTreeList.GetStoredPropertyValue( const AName: string; var AValue: Variant); begin if Assigned(OnGetStoredPropertyValue) then OnGetStoredPropertyValue(Self, AName, AValue); end; procedure TcxCustomTreeList.SetStoredPropertyValue( const AName: string; const AValue: Variant); begin if Assigned(OnSetStoredPropertyValue) then OnSetStoredPropertyValue(Self, AName, AValue); end; function TcxCustomTreeList.StoredCreateChild( const AObjectName, AClassName: string): TObject; begin if AClassName = GetTreeListColumnClass.ClassName then begin Result := CreateColumn; TcxTreeListColumn(Result).Name := AObjectName; if Assigned(OnInitStoredObject) then FOnInitStoredObject(Self, Result); end else Result := nil; end; procedure TcxCustomTreeList.StoredDeleteChild( const AObjectName: string; AObject: TObject); begin end; procedure TcxCustomTreeList.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); for I := 0 to ColumnCount - 1 do DoStore(Columns[I]); end; function TcxCustomTreeList.IsUpdating: Boolean; begin Result := csUpdating in ComponentState; end; procedure TcxCustomTreeList.Loaded; procedure ConvertOldFooterSummaries; var I: Integer; begin for I := 0 to ColumnCount - 1 do Columns[I].ConvertOldFooterSummaries; end; begin inherited Loaded; FSortedColumns.Sort(@cxCompareColumnsBySortIndex); if FocusedNode <> nil then FocusedNode.MakeVisible; AssignItemsPosition; ConvertOldFooterSummaries; DataChanged; StructureChanged; ForceLayoutChanged; end; procedure TcxCustomTreeList.Modified; begin if HandleAllocated then inherited Modified; FDefaultLayout := False; end; procedure TcxCustomTreeList.Notification( AComponent: TComponent; Operation: TOperation); var I: Integer; begin inherited Notification(AComponent, Operation); if PopupMenus <> nil then PopupMenus.Notification(AComponent, Operation); if not IsDestroying then begin if (Summary <> nil) and (Operation = opRemove) and (AComponent is TcxTreeListColumn) then Summary.Notification(AComponent, Operation); if Operation = opRemove then FDefaultLevelInfo.Notification(AComponent, Operation); if FLevelsInfo <> nil then for I := 0 to FLevelsInfo.Count - 1 do LevelsInfo[I].Notification(AComponent, Operation); end; end; procedure TcxCustomTreeList.SetName(const NewName: TComponentName); begin inherited SetName(NewName); UpdateDesignerForms; end; procedure TcxCustomTreeList.AddChanges(AChanges: TcxTreeListChanges); begin FChanges := FChanges + AChanges; end; function TcxCustomTreeList.AddNode(ANode, ARelative: TcxTreeListNode; AData: Pointer; AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode; begin Result := AddNodeInternal(ANode, ARelative, AttachMode); Result.FData := AData; end; function TcxCustomTreeList.AddNodeInternal(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 := CreateNode 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]); if AddMode[AddMethod] = tlnaInsert then Result.FOriginalIndex := Result.Index else Result.FOriginalIndex := Result.Parent.Count; LayoutChanged; end; procedure TcxCustomTreeList.AfterMouseDown(AButton: TMouseButton; X, Y: Integer); begin if (DragMode = dmAutomatic) and (AButton = mbLeft) and (not IsDesigning or AllowAutoDragAndDropAtDesignTime(X, Y, [])) and CanDrag(X, Y) and (DragDetect(Handle) = ddDrag) then BeginDrag(True); if AButton = mbMiddle then DoScrolling; end; procedure TcxCustomTreeList.AssignOptions(ASource: TcxCustomTreeList); begin Font := ASource.Font; Styles := ASource.Styles; Images := ASource.Images; StateImages := ASource.StateImages; OptionsCustomizing := ASource.OptionsCustomizing; OptionsView := ASource.OptionsView; OptionsBehavior := ASource.OptionsBehavior; OptionsSelection := ASource.OptionsSelection; end; procedure TcxCustomTreeList.AssignData(ASource: TcxCustomTreeList); var I: Integer; AName: string; AColumn: TcxTreeListColumn; begin Bands := ASource.Bands; SaveItemsPosition; while ContainerList.Count > ASource.ContainerList.Count do TComponent(ContainerList.Last).Free; while ContainerList.Count < ASource.ContainerList.Count do begin AName := TComponent(ASource.ContainerList[ContainerList.Count]).Name; AColumn := DoCreateColumn; if (Owner = nil) or (Owner.FindComponent(AName) = nil) then AColumn.Name := AName; end; for I := 0 to Min(ContainerList.Count, ASource.ContainerList.Count) - 1 do TcxTreeListColumn(ContainerList[I]).Assign(TPersistent(ASource.ContainerList[I])); AssignItemsPosition; Preview := ASource.Preview; end; procedure TcxCustomTreeList.BeforeUpdate; begin inherited BeforeUpdate; CheckChanges; end; procedure TcxCustomTreeList.BoundsChanged; begin AddChanges([tcLayout]); inherited BoundsChanged; end; procedure TcxCustomTreeList.CalculateForceIndentWidth; var ABand: TcxTreeListBand; AColumn: TcxTreeListColumn; I, AForceDelta: Integer; begin ABand := Bands.ExpandableBand; if (ABand = nil) or IsLoading then Exit; AForceDelta := ABand.BandRows.RowMinWidth + IndentWidth - ABand.DisplayWidth; if AForceDelta > 0 then Bands.ExpandableBand.ForceWidth(Bands.ExpandableBand.DisplayWidth + AForceDelta); for I := 0 to ABand.BandRows.VisibleItemCount - 1 do begin AColumn := ABand.BandRows.VisibleItems[I].VisibleItems[0]; AForceDelta := AColumn.MinWidth + IndentWidth - AColumn.DisplayWidth; if AForceDelta > 0 then AColumn.ForceWidth(AColumn.DisplayWidth + AForceDelta); end; end; function TcxCustomTreeList.CanCompare: Boolean; begin Result := (SortedColumnCount > 0) or Assigned(FOnCompare); end; procedure TcxCustomTreeList.CheckChanges; begin if (Changes = []) or ChangesLocked or IsLoading then Exit; BeginUpdate; try ChangesLocked := True; try TcxTreeListPainter(Painter).CheckSize(Width, Height); if tcSortOrder in Changes then Include(FChanges, tcData); if tcData in Changes then DoSortNodes; if (tcStructure in Changes) or (DataController.NodesCount <> FAbsoluteItems.Count) then CheckStructure; if [tcSelection, tcFocusedNode] * Changes <> [] then CheckSelectionAndFocused; if [tcData, tcStructure] * Changes <> [] then Summary.Calculate; if tcImages in Changes then CheckLevelsInfo; CheckEvents; Changes := []; ChangesLocked := False; except FChanges := []; BeginUpdate; raise; end; finally CancelUpdate; end; end; procedure TcxCustomTreeList.CheckEvents; begin if not IsDestroying then begin if tcFocusedNode in Changes then begin if Controller.FocusedNode = nil then Controller.CheckFocusedNode; if Controller.PrevFocusedNode <> FocusedNode then DoFocusedNodeChanged(Controller.PrevFocusedNode, FocusedNode); end; if tcSelection in Changes then DoSelectionChanged; end; Exclude(FChanges, tcFocusedNode); Exclude(FChanges, tcSelection); end; procedure TcxCustomTreeList.CheckLevelsInfo; var AOffset, I: Integer; begin FDefaultIndentSize.cy := Max(ViewInfo.DefaultRowHeight, LookAndFeelPainter.ExpandButtonSize + cxTreeListIndentOffsetSize); FDefaultIndentSize.cx := LookAndFeelPainter.ExpandButtonSize + cxTreeListIndentOffsetSize; BeginUpdate; try for I := 0 to FExpansionLevel do begin if I = FLevelsInfo.Count then FLevelsInfo.Add(TcxTreeListLevelInfo.Create(Self)); DoGetLevelImages(LevelsInfo[I], I); if not OptionsView.DynamicIndent then FDefaultIndentSize.cx := Max(FDefaultIndentSize.cx, LevelsInfo[I].Size.cx); if not OptionsView.CellAutoHeight then FDefaultIndentSize.cy := Max(FDefaultIndentSize.cy, LevelsInfo[I].Size.cy); end; for I := FExpansionLevel + 1 to FLevelsInfo.Count - 1 do FLevelsInfo[I].Free; FLevelsInfo.Count := FExpansionLevel + 1; AOffset := 0; for I := 0 to FExpansionLevel do begin AOffset := LevelsInfo[I].Update(AOffset); if (I = 0) and not OptionsView.ShowRoot then begin Dec(LevelsInfo[I].FWidth, DefaultIndentSize.cx); Dec(AOffset, DefaultIndentSize.cx); end; end; finally FChanges := FChanges - [tcImages]; CancelUpdate; end; end; procedure TcxCustomTreeList.CheckSelectionAndFocused; begin if (Controller.FocusedNode = nil) and cxInRange( Controller.FocusedNodeIndex, 0, FAbsoluteVisibleItems.Count - 1) then Controller.FFocusedNode := FAbsoluteVisibleItems[Controller.FocusedNodeIndex]; end; procedure TcxCustomTreeList.CheckSortOrderList; var I: Integer; begin for I := 0 to ColumnCount - 1 do Columns[I].FSortIndex := FSortedColumns.IndexOf(Columns[I]) end; procedure TcxCustomTreeList.CheckStructure; var ANode: TcxTreeListNode; ALevel, AHiddenLevel: Integer; begin ANode := Root.FFirst; ALevel := 0; AHiddenLevel := 0; FExpansionLevel := -1; FAbsoluteItems.Count := 0; FAbsoluteItems.Capacity := DataController.NodesCount; FAbsoluteVisibleItems.Count := 0; FAbsoluteVisibleItems.Capacity := DataController.NodesCount; Include(FChanges, tcImages); while ANode <> nil do begin ANode.FAbsoluteIndex := FAbsoluteItems.Count; FAbsoluteItems.Add(ANode); ANode.FVisibleIndex := -1; if (AHiddenLevel = 0) and not (nsHidden in ANode.State) then begin ANode.FVisibleIndex := Integer(FAbsoluteVisibleItems.Add(ANode)); FExpansionLevel := Max(FExpansionLevel, ALevel); end; if ANode.FFirst <> nil then begin Inc(ALevel); if (AHiddenLevel > 0) or (nsCollapsed in ANode.State) or (nsHidden in ANode.State) then Inc(AHiddenLevel); ANode := ANode.FFirst; end else if ANode.FNext <> nil then ANode := ANode.FNext else begin while (ANode <> Root) and (ANode.FNext = nil) do begin if AHiddenLevel > 0 then Dec(AHiddenLevel); Dec(ALevel); ANode := ANode.Parent; end; if ANode <> Root then ANode := ANode.FNext else ANode := nil; end; end; end; procedure TcxCustomTreeList.ClearCalculatedWidths; var I: Integer; begin for I := 0 to ColumnCount - 1 do Columns[I].FCalculatedWidth := 0; for I := 0 to Bands.Count - 1 do Bands[I].FCalculatedWidth := 0; end; procedure TcxCustomTreeList.ColumnSortOrderChanged( AColumn: TcxTreeListColumn; AShift: TShiftState); var AIndex: Integer; begin BeginUpdate; try if ssCtrl in AShift then AColumn.CancelSorting else begin if not IsLoading and (not OptionsBehavior.MultiSort or not (ssShift in AShift)) then begin for AIndex := 0 to ColumnCount - 1 do if Columns[AIndex] <> AColumn then Columns[AIndex].CancelSorting; end; if FSortedColumns.IndexOf(AColumn) < 0 then begin AIndex := FSortedColumns.Add(AColumn); if not IsLoading then AColumn.FSortIndex := AIndex; end; end; FChanges := FChanges + [tcData, tcSortOrder]; finally EndUpdate; end; end; function TcxCustomTreeList.CreateNode: TcxTreeListNode; begin Result := TcxUnboundTreeListNode.Create(Self); Include(FChanges, tcStructure); end; procedure TcxCustomTreeList.CreateSubClasses; begin inherited CreateSubClasses; FDefaultLevelInfo := TcxTreeListLevelInfo.Create(Self); FLevelsInfo := TcxObjectList.Create(); FNavigatorNotifier := TcxNavigatorControlNotifier.Create; FSortedColumns := TList.Create; FDesigners := TList.Create; FSelectionList := TList.Create; FOptionsCustomizing := GetOptionsCustomizingClass.Create(Self); FOptionsSelection := GetOptionsSelectionClass.Create(Self); FPopupMenus := TcxTreeListPopupMenus.Create(Self); FPreview := GetPreviewClass.Create(Self); FBands := TcxTreeListBands.Create(Self); FVisibleColumns := TList.Create; FCustomizing := GetTreeListCustomizingClass.Create(Self); FSummary := GetSummaryClass.Create(Self); FDelayTimer := TTimer.Create(Self); FDelayTimer.Enabled := False; FDelayTimer.Interval := 0; FDelayTimer.OnTimer := DoChangedTimer; end; procedure TcxCustomTreeList.DestroySubClasses; begin UpdateDesignerForms; BeginUpdate; try FreeAndNil(FNavigatorNotifier); FreeAndNil(FVisibleColumns); FreeAndNil(FPreview); DeleteAllColumns; FreeAndNil(FBands); FreeAndNil(FPopupMenus); FreeAndNil(FOptionsCustomizing); FreeAndNil(FOptionsSelection); FreeAndNil(FCustomizing); FreeAndNil(FSortedColumns); FreeAndNil(FSummary); FreeAndNil(FDefaultLevelInfo); FreeAndNil(FLevelsInfo); FreeAndNil(FDelayTimer); FreeAndNil(FSelectionList); FreeAndNil(FDesigners); FreeAndNil(FOptionsCustomizing); finally inherited DestroySubClasses; end; end; procedure TcxCustomTreeList.DoAfterSummary; begin if Assigned(FOnAfterSummary) then FOnAfterSummary(Self); end; procedure TcxCustomTreeList.DoBandHeaderClick(ABand: TcxTreeListBand); begin if Assigned(FOnBandHeaderClick) then FOnBandHeaderClick(Self, ABand); end; function TcxCustomTreeList.DoBeginDragNode( ANode: TcxTreeListNode): Boolean; begin Result := True; if Assigned(FOnBeginDragNode) then FOnBeginDragNode(Self, ANode, Result); end; function TcxCustomTreeList.DoCanFocusNode( ANode: TcxTreeListNode): Boolean; begin Result := True; if Assigned(FOnCanFocusNode) then FOnCanFocusNode(Self, ANode, Result); end; function TcxCustomTreeList.DoCanNodeCollapse( ANode: TcxTreeListNode): Boolean; begin Result := ANode.HasChildren; if Result and Assigned(FOnCollapsing) then FOnCollapsing(Self, ANode, Result); end; function TcxCustomTreeList.DoCanNodeExpand( ANode: TcxTreeListNode): Boolean; begin Result := ANode.HasChildren; if Result and Assigned(FOnExpanding) then FOnExpanding(Self, ANode, Result); end; function TcxCustomTreeList.DoCanSelectNode( ANode: TcxTreeListNode): Boolean; begin Result := True; if (ANode <> nil) and Assigned(FOnCanSelectNode) then FOnCanSelectNode(Self, ANode, Result); end; procedure TcxCustomTreeList.DoChanged(BlockChangedEvent: Boolean = True); begin if BlockChangedEvent and (OptionsBehavior.ChangeDelay > 0) then Exit; try if FPostChanged and Assigned(FOnChange) then FOnChange(Self); finally FPostChanged := False; end; end; procedure TcxCustomTreeList.DoColumnHeaderClick(AColumn: TcxTreeListColumn); begin if Assigned(FOnColumnHeaderClick) then FOnColumnHeaderClick(Self, AColumn); end; procedure TcxCustomTreeList.DoCompare( ANode1, ANode2: TcxTreeListNode; var ACompare: Integer); const AEquals: array[Boolean] of Integer = (1, 0); begin ACompare := AEquals[ANode1 = ANode2]; if not Assigned(FOnCompare) then begin if ACompare <> 0 then ACompare := DataController.CompareNodesByColumns(ANode1, ANode2, FSortedColumns) end else FOnCompare(Self, ANode1, ANode2, ACompare); end; procedure TcxCustomTreeList.DoCustomizationVisibleChanged; begin if Assigned(FOnCustomizationVisibleChanged) then FOnCustomizationVisibleChanged(Self); end; procedure TcxCustomTreeList.DoDataChangedEvent(Sender: TObject); begin if Assigned(FOnDataChanged) then FOnDataChanged(Self); end; procedure TcxCustomTreeList.DoDeletion(ANode: TcxTreeListNode); begin if Assigned(FOnDeletion) then FOnDeletion(Self, ANode); end; procedure TcxCustomTreeList.DoEditValueChanged( AItem: TcxCustomInplaceEditContainer); begin inherited DoEditValueChanged(AItem); DoChanged(); end; procedure TcxCustomTreeList.DoExpand(ANode: TcxTreeListNode); begin end; procedure TcxCustomTreeList.DoFocusedItemChanged( APrevFocusedItem, AFocusedItem: TcxCustomInplaceEditContainer); begin if Assigned(FOnFocusedColumnChanged) then FOnFocusedColumnChanged(Self, TcxTreeListColumn(APrevFocusedItem), TcxTreeListColumn(AFocusedItem)); end; procedure TcxCustomTreeList.DoFocusedNodeChanged( APrevNode, AFocusedNode: TcxTreeListNode); begin if Assigned(FOnFocusedNodeChanged) then FOnFocusedNodeChanged(Self, APrevNode, AFocusedNode); if not OptionsSelection.MultiSelect then DoSelectionChanged; end; procedure TcxCustomTreeList.DoGetCellHint(ACell: TObject; var AText: string; var ANeedShow: Boolean); begin if Assigned(FOnGetCellHint) then FOnGetCellHint(Self, ACell, AText, ANeedShow); end; procedure TcxCustomTreeList.DoGetLevelImages( AInfo: TcxTreeListLevelInfo; ALevel: Integer); var AImages, AStateImages: TCustomImageList; begin AImages := Images; AStateImages := StateImages; if Assigned(FOnGetLevelImages) then FOnGetLevelImages(Self, ALevel, AImages, AStateImages); AInfo.Images := AImages; AInfo.StateImages := AStateImages; AInfo.Update(0); end; procedure TcxCustomTreeList.DoGetNodeHeight( ANode: TcxTreeListNode; var AHeight: Integer); begin if Assigned(FOnGetNodeHeight) then FOnGetNodeHeight(Self, ANode, AHeight) end; function TcxCustomTreeList.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; procedure TcxCustomTreeList.DoGetPreviewHeight( ANode: TcxTreeListNode; var AHeight: Integer); begin if Assigned(FOnGetNodePreviewHeight) then FOnGetNodePreviewHeight(Self, ANode, ANode.Values[Preview.Column.ItemIndex], AHeight); end; procedure TcxCustomTreeList.DoHotTrackNode( ANode: TcxTreeListNode; AShift: TShiftState; var ACursor: TCursor); begin ACursor := Cursor; if Assigned(FOnHotTrackNode) then FOnHotTrackNode(Self, ANode, AShift, ACursor); end; function TcxCustomTreeList.DoIsGroupNode( ANode: TcxTreeListNode): Boolean; begin Result := (ANode <> nil) and (OptionsView.PaintStyle = tlpsCategorized) and ANode.HasChildren; if Assigned(FOnIsGroupNode) then FOnIsGroupNode(Self, ANode, Result); end; procedure TcxCustomTreeList.DoLayoutChangedEvent; begin if Assigned(FOnLayoutChanged) then FOnLayoutChanged(Self); end; function TcxCustomTreeList.DoMoveToEvent(AttachNode: TcxTreeListNode; AttachMode: TcxTreeListNodeAttachMode; Nodes: TList; var IsCopy: Boolean): Boolean; begin Result := False; if Assigned(FOnMoveTo) then FOnMoveTo(Self, AttachNode, AttachMode, Nodes, IsCopy, Result); end; procedure TcxCustomTreeList.DoNodeChanged( ANode: TcxTreeListNode; AColumn: TcxTreeListColumn); begin if DataController.IsLoading or IsLocked then begin Include(FChanges, tcData); Exit; end; if DataController.EditingNode <> ANode then begin if AColumn <> nil then Include(FChanges, tcData) else Include(FChanges, tcStructure); end; LayoutChanged; if Assigned(FOnNodeChanged) then FOnNodeChanged(Self, ANode, AColumn); end; procedure TcxCustomTreeList.DoNodeCheckChanged( ANode: TcxTreeListNode; AState: TcxCheckBoxState); begin if Assigned(FOnNodeCheckChanged) then FOnNodeCheckChanged(Self, ANode, AState); end; procedure TcxCustomTreeList.DoNodeCollapsed(ANode: TcxTreeListNode); begin if Assigned(FOnCollapsed) then FOnCollapsed(Self, ANode); end; procedure TcxCustomTreeList.DoNodeExpanded(ANode: TcxTreeListNode); begin if Assigned(FOnExpanded) then FOnExpanded(Self, ANode); end; procedure TcxCustomTreeList.DoSetNodeFocused( ANode: TcxTreeListNode; AValue: Boolean; Shift: TShiftState = []); begin if AValue then FocusedNode := ANode else if ANode.Focused then FocusedNode := nil; end; procedure TcxCustomTreeList.RefreshFields; var I: Integer; begin ViewInfo.SetDirty; for I := 0 to ContainerList.Count - 1 do TcxTreeListColumn(ContainerList[I]).DataChanged; end; procedure TcxCustomTreeList.SetNodeParent(ANewNode, ANewParent: TcxTreeListNode; AMode: TcxTreeListNodeAddMode); begin case AMode of tlnaAdd: ANewParent.SetLast(ANewNode); tlnaAddFirst: ANewParent.SetFirst(ANewNode); tlnaInsert: ANewNode.InternalInsert(ANewParent); end; AddChanges([tcStructure]); end; procedure TcxCustomTreeList.StructureChanged; begin Include(FChanges, tcStructure); LayoutChanged; end; procedure TcxCustomTreeList.UpdateFocusedNode(AColumn: TcxTreeListColumn); begin ViewInfo.UpdateSelection; end; procedure TcxCustomTreeList.ValidateStates; begin if FChanges <> [] then ForceLayoutChanged; // HandleNeeded; end; procedure TcxCustomTreeList.DoSelectionChanged; begin if Assigned(FOnSelectionChanged) then FOnSelectionChanged(Self); end; procedure TcxCustomTreeList.DoSelectAll; var I: Integer; begin SelectionList.Clear; SelectionList.Capacity := AbsoluteVisibleCount; for I := 0 to AbsoluteVisibleCount - 1 do begin if not DoCanSelectNode(AbsoluteVisibleItems[I]) then Continue; SelectionList.Add(AbsoluteVisibleItems[I]); end; end; procedure TcxCustomTreeList.DoSorted; begin if Assigned(FOnSorted) then FOnSorted(Self); end; procedure TcxCustomTreeList.DoSorting; begin if Assigned(FOnSorting) then FOnSorting(Self); end; procedure TcxCustomTreeList.DoSortNodes; begin if (not (tcSortOrder in Changes) and not Sorted) or IsLoading or IsDestroying or IsUpdating or (tcLoading in Changes) then Exit; DoSorting; try Root.AlphaSort(True); FNeedSort := False; finally DoSorted; end; end; procedure TcxCustomTreeList.DoStartDrag(var DragObject: TDragObject); begin DragPos := ScreenToClient(GetMouseCursorPos); if HitTest.HitNode = nil then HitTest.FHitNode := FDragNode; inherited DoStartDrag(DragObject); end; procedure TcxCustomTreeList.DoTopRecordIndexChanged; begin if Assigned(FOnTopRecordIndexChanged) then FOnTopRecordIndexChanged(Self); end; procedure TcxCustomTreeList.ForceLayoutChanged; begin BeforeUpdate; DoLayoutChanged; end; function TcxCustomTreeList.GetBandItemClass: TcxTreeListBandClass; begin Result := TcxTreeListBand; end; function TcxCustomTreeList.GetControllerClass: TcxCustomControlControllerClass; begin Result := TcxTreeListController; end; function TcxCustomTreeList.GetControlStylesClass: TcxCustomControlStylesClass; begin Result := TcxTreeListStyles; end; function TcxCustomTreeList.GetHitTestControllerClass: TcxHitTestControllerClass; begin Result := TcxTreeListHitTest; end; function TcxCustomTreeList.GetOptionsBehaviorClass: TcxControlOptionsBehaviorClass; begin Result := TcxTreeListOptionsBehavior; end; function TcxCustomTreeList.GetOptionsCustomizingClass: TcxTreeListOptionsCustomizingClass; begin Result := TcxTreeListOptionsCustomizing; end; function TcxCustomTreeList.GetOptionsDataClass: TcxControlOptionsDataClass; begin Result := TcxTreeListOptionsData; end; function TcxCustomTreeList.GetOptionsSelectionClass: TcxTreeListOptionsSelectionClass; begin Result := TcxTreeListOptionsSelection; end; function TcxCustomTreeList.GetOptionsViewClass: TcxControlOptionsViewClass; begin Result := TcxTreeListOptionsView; end; function TcxCustomTreeList.GetPainterClass: TcxCustomControlPainterClass; begin Result := TcxTreeListPainter; end; function TcxCustomTreeList.GetPreviewClass: TcxTreeListPreviewClass; begin Result := TcxTreeListPreview; end; function TcxCustomTreeList.GetRootClass: TcxTreeListNodeClass; begin Result := TcxTreeListRootNode; end; function TcxCustomTreeList.GetSummaryClass: TcxTreeListSummaryClass; begin Result := TcxTreeListSummary; end; function TcxCustomTreeList.GetTreeListColumnClass: TcxTreeListColumnClass; begin Result := TcxTreeListColumn; end; function TcxCustomTreeList.GetTreeListCustomizingClass: TcxTreeListCustomizingClass; begin Result := TcxTreeListCustomizing; end; function TcxCustomTreeList.GetViewInfoClass: TcxCustomControlViewInfoClass; begin Result := TcxTreeListViewInfo; end; function TcxCustomTreeList.GetDataControllerClass: TcxCustomDataControllerClass; begin Result := TcxTreeListDataController; end; function TcxCustomTreeList.GetEditingControllerClass: TcxEditingControllerClass; begin Result := TcxTreeListEditingController; end; function TcxCustomTreeList.GetDefaultColumnContainer: TcxTreeListBand; begin if Bands.Count = 0 then Result := Bands.Add else if Bands.BottomItemCount > 0 then Result := Bands.BottomItems[0] else Result := Bands[0]; end; function TcxCustomTreeList.GetSameColumn(AColumn: TcxTreeListColumn): TcxTreeListColumn; begin Result := nil; if (AColumn <> nil) and cxInRange(AColumn.ID, 0, ContainerList.Count - 1) then Result := ContainerList[AColumn.ID]; end; function TcxCustomTreeList.GetStartNodeForBestFit: TcxTreeListNode; begin Result := nil; if AbsoluteVisibleCount > 0 then begin if GetCountNodeForBestFit < 0 then Result := AbsoluteVisibleItems[0] else Result := ViewInfo.TopNode end; end; function TcxCustomTreeList.IsLocked: Boolean; begin Result := inherited IsLocked or IsTreeListLocked; end; function TcxCustomTreeList.IsTreeListLocked: Boolean; begin Result := (LockUpdate > 0) or ([csLoading, csDestroying, csUpdating, csReading] * ComponentState <> []); end; procedure TcxCustomTreeList.ImageChanged; begin if Painter is TcxTreeListPainter then TcxTreeListPainter(Painter).Changed := True; end; procedure TcxCustomTreeList.ImagesChanged(Sender: TObject); begin Include(FChanges, tcImages); LayoutChanged; end; procedure TcxCustomTreeList.InternalClearAll; begin InternalDelete(FAbsoluteItems); end; procedure TcxCustomTreeList.InternalCopy( ANode, ADestNode: TcxTreeListNode); var ANewNode: TcxTreeListNode; begin ANewNode := AddNode(nil, ADestNode, nil, tlamAddChild); ANewNode.AssignData(ANode); ANode := ANode.GetFirstChild; while ANode <> nil do begin InternalCopy(ANode, ANewNode); ANode := ANode.FNext; end; end; procedure TcxCustomTreeList.InternalDelete(ANodes: TList); var I: Integer; begin if ANodes.Count = 0 then Exit; BeginUpdate; try ANodes.Sort(@cxCompareNodesByLevel); for I := 0 to ANodes.Count - 1 do TcxTreeListNode(ANodes[I]).InternalFree; ANodes.Clear; finally EndUpdate; end; end; procedure TcxCustomTreeList.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; AddNodeInternal(ANode, ADestNode, AMode); end; procedure TcxCustomTreeList.InvalidateRectEx( const R: TRect; EraseBackground: Boolean); begin ImageChanged; inherited InvalidateRectEx(R, EraseBackground); end; function TcxCustomTreeList.IsNodeEdited(ANode: TcxTreeListNode): Boolean; begin Result := (DataController.EditingNode = ANode) and (nsEditing in ANode.State); end; function TcxCustomTreeList.IsNodeInserting(ANode: TcxTreeListNode): Boolean; begin Result := (ANode <> nil) and (nsInserting in ANode.State); end; procedure TcxCustomTreeList.LookAndFeelChanged( Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); begin HideEdit; ViewInfo.SetDirty; inherited LookAndFeelChanged(Sender, AChangedValues); end; function TcxCustomTreeList.CanMultiSelect: Boolean; begin Result := OptionsSelection.MultiSelect; end; procedure TcxCustomTreeList.BeforeShowingEdit; begin with Controller do SetFocusedRecordItem(FocusedRecordIndex, FocusedItem); end; procedure TcxCustomTreeList.DoClear; begin InternalClearAll; end; procedure TcxCustomTreeList.DoDeleteSelection; var AList: TList; begin if FocusedNode = nil then Exit; if FocusedNode.Inserting then begin DataController.Cancel; Exit; end; BeginUpdate; try AList := GetSelectionsEx; try if AList.Count > 0 then begin AList.Sort(@cxCompareNodesByLevel); DeleteNodes(AList); end; finally FreeAndNil(AList); end; finally EndUpdate; end; end; procedure TcxCustomTreeList.DoDeleteNode(ANode: TcxTreeListNode); begin Controller.CheckDeletedNode(ANode); if FTopVisibleNode = ANode then begin FTopVisibleNode := ANode.GetNextSiblingVisible; if FTopVisibleNode = nil then FTopVisibleNode := ANode.GetPrev; DoTopRecordIndexChanged; end; DataController.FreeNodeRecord(ANode); if HitTest.FHitNode = ANode then HitTest.FHitNode := nil; SelectionList.Remove(ANode); if ANode = FDragNode then FDragNode := nil; end; procedure TcxCustomTreeList.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; begin if IsCopy and (AttachMode = tlamInsert) then AttachNode := AttachNode.Parent; if not CheckNodesList or DoMoveToEvent(AttachNode, AttachMode, ANodes, IsCopy) then Exit; DoMoveTo(AttachNode, AttachMode, ANodes, IsCopy); end; procedure TcxCustomTreeList.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 TcxCustomTreeList.DoOnBandSizeChanged(ABand: TcxTreeListBand); begin if Assigned(FOnBandSizeChanged) then FOnBandSizeChanged(Self, ABand); end; procedure TcxCustomTreeList.DoOnColumnSizeChanged( AColumn: TcxTreeListColumn); begin if Assigned(FOnColumnSizeChanged) then FOnColumnSizeChanged(Self, AColumn); end; function TcxCustomTreeList.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 TcxCustomTreeList.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 + ANode.Texts[I]; end; end; procedure TcxCustomTreeList.DoWriteToClipboard(AOnlySelected: Boolean); var AText: string; begin if DoWriteToText(AOnlySelected, AText) then ClipBoard.AsText := AText end; function TcxCustomTreeList.DoWriteToText(AOnlySelected: Boolean; out AText: string): Boolean; var ANode: TcxTreeListNode; begin ANode := 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 TcxCustomTreeList.DeleteNodes(AList: TList); var I: Integer; begin BeginUpdate; try for I := 0 to AList.Count - 1 do TcxTreeListNode(AList[I]).Delete; finally EndUpdate; end; end; function TcxCustomTreeList.GetCountNodeForBestFit: Integer; begin Result := -1; end; function TcxCustomTreeList.GetIsActive: Boolean; begin Result := Controller.Focused; end; function TcxCustomTreeList.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 TcxCustomTreeList.GetMaxBandWidth(ABand: TcxTreeListBand): Integer; begin Result := MaxInt; end; function TcxCustomTreeList.GetMouseWheelScrollingKind: TcxMouseWheelScrollingKind; begin Result := mwskVertical; end; procedure TcxCustomTreeList.InitInsertingNode(ANode: TcxTreeListNode); begin ANode.MakeVisible; ANode.Focused := True; DataController.EditingNode := ANode; end; function TcxCustomTreeList.InsertNode( ARelative: TcxTreeListNode; IsAppend: Boolean): Boolean; var ANode: TcxTreeListNode; const AMode: array[Boolean] of TcxTreeListNodeAttachMode = (tlamInsert, tlamAddChild); begin BeginUpdate; try ANode := ARelative; if (ANode <> nil) and ANode.Inserting then ANode := ANode.Parent; IsAppend := IsAppend or (ANode = nil); if (ARelative <> nil) and IsAppend then ANode.LoadChildren; if ANode = nil then ANode := Root; ANode := AddNode(nil, ANode, nil, AMode[IsAppend]); Result := ANode <> nil; if Result then begin if Result then begin InitInsertingNode(ANode); Include(ANode.State, nsInserting); end; end; DataController.IsValueChanged := False; finally EndUpdate; end; end; procedure TcxCustomTreeList.MakeNodeVisible(ANode: TcxTreeListNode); begin if (ANode = nil) or not ANode.IsVisible then Exit; if FTopVisibleNode = nil then begin FTopVisibleNode := ANode; DoTopRecordIndexChanged; ViewInfo.SetDirty; end; CheckChanges; if ANode = TopVisibleNode then ANode.Repaint(True) else begin ViewInfo.Validate; if not ANode.IsPrinted then TopVisibleNode := ANode else ViewInfo.MakeVisible(ANode); ImageChanged; end; end; procedure TcxCustomTreeList.RestoreCursor; begin if not OptionsBehavior.ShowHourGlass then Exit; Dec(FGlassCursorRefCount); if FGlassCursorRefCount = 0 then Screen.Cursor := FStoredCursor; end; procedure TcxCustomTreeList.SetGlassCursor; begin if not OptionsBehavior.ShowHourGlass then Exit; if FGlassCursorRefCount = 0 then begin if OptionsBehavior.HotTrack and (Controller.HotTrackNode <> nil) then FStoredCursor := Controller.PrevCursor else FStoredCursor := Screen.Cursor; end; if HandleAllocated and Visible then Screen.Cursor := crHourGlass; Inc(FGlassCursorRefCount); end; procedure TcxCustomTreeList.SortingStateChanged( AColumn: TcxTreeListColumn; AShift: TShiftState); begin end; function TcxCustomTreeList.SupportBandColumnEditor: Boolean; begin Result := True; end; function TcxCustomTreeList.SupportItemsEditor: Boolean; begin Result := False end; function TcxCustomTreeList.SupportCreateAllItems: Boolean; begin Result := False; end; procedure TcxCustomTreeList.CreateAllItems; begin end; // IcxNavigator procedure TcxCustomTreeList.RefreshNavigatorButtons; begin if not (IsLoading or IsDestroying) and (FNavigatorNotifier <> nil) then FNavigatorNotifier.RefreshNavigatorButtons; end; procedure TcxCustomTreeList.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, Root, nil, tlamAdd).Focused := True; NBDI_APPEND: if FocusedNode <> nil then AddNode(nil, FocusedNode.Parent, nil, tlamAdd).Focused := True else AddNode(nil, Root, nil, tlamAdd).Focused := True; NBDI_DELETE: Self.DeleteSelection; NBDI_EDIT: ShowEdit; NBDI_POST: DataController.Post; NBDI_CANCEL: begin DataController.Cancel; Controller.EditingController.UpdateEditValue; end; NBDI_REFRESH: DataController.Refresh; NBDI_SAVEBOOKMARK: SaveBookmark; NBDI_GOTOBOOKMARK: GotoBookmark; end; end; function TcxCustomTreeList.GetNotifier: TcxNavigatorControlNotifier; begin Result := FNavigatorNotifier; end; function TcxCustomTreeList.IsActionSupported(AButtonIndex: Integer): Boolean; begin Result := AButtonIndex in [NBDI_FIRST..NBDI_GOTOBOOKMARK]; end; function TcxCustomTreeList.CanAppend: Boolean; begin Result := CanInsert; end; function TcxCustomTreeList.CanEdit: Boolean; begin Result := OptionsData.Editing and (HasData or CanInsert) and not IsEditing; end; function TcxCustomTreeList.CanDelete: Boolean; begin Result := OptionsData.Deleting and HasData; end; function TcxCustomTreeList.CanInsert: Boolean; begin Result := OptionsData.Inserting and ((FocusedNode <> nil) or not HasData); end; procedure TcxCustomTreeList.ClearBookmark; begin DataController.ClearBookmark; end; procedure TcxCustomTreeList.GotoBookmark; begin DataController.GotoBookmark; end; function TcxCustomTreeList.HasData: Boolean; begin Result := (VisibleColumnCount > 0) and (AbsoluteVisibleCount > 0); end; function TcxCustomTreeList.IsBookmarkAvailable: Boolean; begin Result := DataController.IsBookmarkAvailable and HasData; end; procedure TcxCustomTreeList.SaveBookmark; begin DataController.SaveBookmark; end; function TcxCustomTreeList.GetSelectionsEx: TList; begin Result := TList.Create; GetSelections(Result); if (FocusedNode <> nil) and not FocusedNode.Selected then Result.Add(FocusedNode); end; function TcxCustomTreeList.GetOnEditing: TcxTreeListEditingEvent; begin Result := TcxTreeListEditingEvent(inherited OnEditing); end; function TcxCustomTreeList.GetOnEdited: TcxTreeListColumnChangedEvent; begin Result := TcxTreeListColumnChangedEvent(inherited OnEdited); end; function TcxCustomTreeList.GetOnEditValueChanged: TcxTreeListColumnChangedEvent; begin Result := TcxTreeListColumnChangedEvent(inherited OnEditValueChanged); end; function TcxCustomTreeList.GetSearching: Boolean; begin Result := Controller.IsIncSearching; end; function TcxCustomTreeList.GetSearchingText: string; begin Result := Controller.IncSearchText end; function TcxCustomTreeList.GetAvailableContentWidth: Integer; begin Result := ClientBounds.Right - ClientBounds.Left; if Bands.VisibleLeftFixedCount > 0 then Dec(Result, OptionsView.FixedSeparatorWidth); if Bands.VisibleRightFixedCount > 0 then Dec(Result, OptionsView.FixedSeparatorWidth); if OptionsView.IsIndicatorVisible then Dec(Result, OptionsView.IndicatorWidth); if Result < 0 then Result := 0; end; function TcxCustomTreeList.GetAbsoluteCount: Integer; begin CheckChanges; Result := FAbsoluteItems.Count; end; function TcxCustomTreeList.GetAbsoluteItem( AIndex: Integer): TcxTreeListNode; begin CheckChanges; Result := TcxTreeListNode(FAbsoluteItems[AIndex]); end; function TcxCustomTreeList.GetAbsoluteItemsList: TList; begin CheckChanges; Result := FAbsoluteItems; end; function TcxCustomTreeList.GetAbsoluteVisibleCount: Integer; begin CheckChanges; Result := FAbsoluteVisibleItems.Count; end; function TcxCustomTreeList.GetAbsoluteVisibleItem( AIndex: Integer): TcxTreeListNode; begin CheckChanges; Result := TcxTreeListNode(FAbsoluteVisibleItems[AIndex]); end; function TcxCustomTreeList.GetAbsoluteVisibleItemsList: TList; begin CheckChanges; Result := FAbsoluteVisibleItems; end; procedure TcxCustomTreeList.SetAbsoluteItem( AIndex: Integer; AValue: TcxTreeListNode); begin AbsoluteItems[AIndex].Assign(AValue); end; procedure TcxCustomTreeList.SetAbsoluteVisibleItem( AIndex: Integer; AValue: TcxTreeListNode); begin AbsoluteVisibleItems[AIndex].Assign(AValue); end; function TcxCustomTreeList.GetBands: TcxTreeListBands; begin Result := FBands; end; function TcxCustomTreeList.GetColumn( AIndex: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(ColumnsList[AIndex]); end; function TcxCustomTreeList.GetColumnCount: Integer; begin Result := ColumnsList.Count; end; function TcxCustomTreeList.GetColumnsList: TList; begin Result := ContainerList; end; function TcxCustomTreeList.GetController: TcxTreeListController; begin Result := TcxTreeListController(inherited Controller); end; function TcxCustomTreeList.GetCount: Integer; begin Result := Root.Count; end; function TcxCustomTreeList.GetDataController: TcxTreeListDataController; begin Result := TcxTreeListDataController(inherited DataController); end; function TcxCustomTreeList.GetDefaultRowHeight: Integer; begin Result := FDefaultRowHeight; end; function TcxCustomTreeList.GetFocusedColumn: TcxTreeListColumn; begin Result := TcxTreeListColumn(Controller.FocusedItem); end; function TcxCustomTreeList.GetFocusedNode: TcxTreeListNode; begin Result := Controller.FocusedNode; end; function TcxCustomTreeList.GetHitTest: TcxTreeListHitTest; begin Result := TcxTreeListHitTest(Controller.HitTestController); end; function TcxCustomTreeList.GetImages: TCustomImageList; begin Result := FDefaultLevelInfo.Images; end; function TcxCustomTreeList.GetLastNode: TcxTreeListNode; begin if AbsoluteVisibleCount > 0 then Result := AbsoluteVisibleItems[AbsoluteVisibleCount - 1] else Result := nil; end; function TcxCustomTreeList.GetLastVisibleNode: TcxTreeListNode; begin ViewInfo.Validate; Result := ViewInfo.LastNode; end; function TcxCustomTreeList.GetLevelInfo( ALevel: Integer): TcxTreeListLevelInfo; begin Result := TcxTreeListLevelInfo(FLevelsInfo[ALevel]); end; function TcxCustomTreeList.GetNavigatorIsActive: Boolean; begin Result := DataController.Active; end; function TcxCustomTreeList.GetIndentWidth: Integer; begin CheckChanges; if (ExpansionLevel < 0) or (Bands.ExpandableBand = nil) then Result := 0 else Result := LevelsInfo[ExpansionLevel].TotalWidth; if OptionsView.CheckGroups then Inc(Result, ViewInfo.CheckboxSize.cx) end; function TcxCustomTreeList.GetInplaceEditor: TcxCustomEdit; begin if IsEditing then Result := Controller.EditingController.Edit else Result := nil; end; function TcxCustomTreeList.GetIsCancelOperation: Boolean; begin Result := FIsCancelOperation or (GetAsyncKeyState(VK_ESCAPE) < 0); FIsCancelOperation := Result; end; function TcxCustomTreeList.GetIsEditing: Boolean; begin Result := Controller.IsEditing; end; function TcxCustomTreeList.GetIsInserting: Boolean; begin Result := IsNodeInserting(FocusedNode); end; function TcxCustomTreeList.GetItem(Index: Integer): TcxTreeListNode; begin Result := Root.Items[Index]; end; function TcxCustomTreeList.GetOptionsBehavior: TcxTreeListOptionsBehavior; begin Result := TcxTreeListOptionsBehavior(inherited OptionsBehavior); end; function TcxCustomTreeList.GetOptionsData: TcxTreeListOptionsData; begin Result := TcxTreeListOptionsData(inherited OptionsData); end; function TcxCustomTreeList.GetOptionsView: TcxTreeListOptionsView; begin Result := TcxTreeListOptionsView(inherited OptionsView); end; function TcxCustomTreeList.GetSelection(AIndex: Integer): TcxTreeListNode; begin if (AIndex = 0) and not OptionsSelection.MultiSelect and (FocusedNode <> nil) then Result := FocusedNode else Result := TcxTreeListNode(SelectionList[AIndex]); end; function TcxCustomTreeList.GetSelectionCount: Integer; begin Result := SelectionList.Count; if not OptionsSelection.MultiSelect and (FocusedNode <> nil) then Result := 1; end; function TcxCustomTreeList.GetSortedColumnCount: Integer; begin Result := FSortedColumns.Count; end; function TcxCustomTreeList.GetSortedColumn( Index: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(FSortedColumns[Index]); end; function TcxCustomTreeList.GetStateImages: TCustomImageList; begin Result := FDefaultLevelInfo.StateImages; end; function TcxCustomTreeList.GetStyles: TcxTreeListStyles; begin Result := TcxTreeListStyles(inherited Styles); end; function TcxCustomTreeList.GetSorted: Boolean; begin Result := FSortedColumns.Count > 0; end; function TcxCustomTreeList.GetTopNode: TcxTreeListNode; begin if AbsoluteVisibleCount > 0 then Result := AbsoluteVisibleItems[0] else Result := nil; end; function TcxCustomTreeList.GetTopVisibleNode: TcxTreeListNode; begin Result := FTopVisibleNode; if Result = nil then Result := Root.getFirstChild; if (Result <> nil) and (Result.IsHidden or not Result.IsVisible) then begin if Result.GetNextVisible <> nil then Result := Result.GetNextVisible else if Result.GetPrevVisible <> nil then Result := Result.GetPrevVisible; end; end; function TcxCustomTreeList.GetVisibleCount: Integer; begin Result := ViewInfo.NodesVisibleCount; end; function TcxCustomTreeList.GetViewInfo: TcxTreeListViewInfo; begin Result := TcxTreeListViewInfo(inherited ViewInfo); end; function TcxCustomTreeList.GetVisibleColumn( AIndex: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(FVisibleColumns[AIndex]); end; function TcxCustomTreeList.GetVisibleColumnCount: Integer; begin Result := FVisibleColumns.Count; end; procedure TcxCustomTreeList.SetBands(Value: TcxTreeListBands); begin FBands.Assign(Value); end; procedure TcxCustomTreeList.SetColumn( AIndex: Integer; Value: TcxTreeListColumn); begin TcxTreeListColumn(ColumnsList[AIndex]).Assign(Value); end; procedure TcxCustomTreeList.SetDefaultRowHeight(AValue: Integer); begin if AValue < 0 then AValue := 0; if AValue = DefaultRowHeight then Exit; FDefaultRowHeight := AValue; LayoutChanged; end; procedure TcxCustomTreeList.SetDefaultLayout(AValue: Boolean); begin if AValue <> FDefaultLayout then begin FDefaultLayout := AValue; if AValue then MakeDefaultLayout; end; end; procedure TcxCustomTreeList.SetFocusedColumn(AValue: TcxTreeListColumn); begin if (AValue <> nil) and AValue.ActuallyVisible then Controller.FocusedItem := AValue else if AValue = nil then Controller.FocusedItem := AValue; end; procedure TcxCustomTreeList.SetFocusedNodeProp(Value: TcxTreeListNode); begin SetFocusedNode(Value, []); end; procedure TcxCustomTreeList.SetImages(AValue: TCustomImageList); begin FDefaultLevelInfo.Images := AValue; end; procedure TcxCustomTreeList.SetIsRestoring(AValue: Boolean); begin if FIsRestoring <> AValue then begin FIsRestoring := AValue; if not FIsRestoring then AssignItemsPosition; end; end; procedure TcxCustomTreeList.SetLastVisibleNode(AValue: TcxTreeListNode); begin ViewInfo.LastNode := AValue; LayoutChanged; end; procedure TcxCustomTreeList.SetOnEdited(Value: TcxTreeListColumnChangedEvent); begin inherited OnEdited := TcxecItemEvent(Value); end; procedure TcxCustomTreeList.SetOnEditing(Value: TcxTreeListEditingEvent); begin inherited OnEditing := TcxecEditingEvent(Value); end; procedure TcxCustomTreeList.SetOnEditValueChanged( Value: TcxTreeListColumnChangedEvent); begin inherited OnEditValueChanged := TcxecItemEvent(Value); end; procedure TcxCustomTreeList.SetOptionsBehavior( Value: TcxTreeListOptionsBehavior); begin OptionsBehavior.Assign(Value); end; procedure TcxCustomTreeList.SetOptionsCustomizing( Value: TcxTreeListOptionsCustomizing); begin FOptionsCustomizing.Assign(Value); end; procedure TcxCustomTreeList.SetOptionsData(Value: TcxTreeListOptionsData); begin inherited OptionsData := Value; end; procedure TcxCustomTreeList.SetOptionsView(Value: TcxTreeListOptionsView); begin inherited OptionsView := Value; end; procedure TcxCustomTreeList.SetPopupMenus(Value: TcxTreeListPopupMenus); begin FPopupMenus.Assign(Value); end; procedure TcxCustomTreeList.SetOptionsSelection( Value: TcxTreeListOptionsSelection); begin FOptionsSelection.Assign(Value); end; procedure TcxCustomTreeList.SetPreview(Value: TcxTreeListPreview); begin FPreview.Assign(Value); end; procedure TcxCustomTreeList.SetSearchingText(const Value: string); begin if Value = '' then CancelSearching else Controller.IncSearchingText := Value end; procedure TcxCustomTreeList.SetSorted(Value: Boolean); var I: Integer; begin if not Value then begin for I := 0 to ColumnCount - 1 do Columns[I].SortOrder := soNone; end; Root.AlphaSort(True); end; procedure TcxCustomTreeList.SetStateImages(AValue: TCustomImageList); begin FDefaultLevelInfo.StateImages := AValue; end; procedure TcxCustomTreeList.SetStyles(Value: TcxTreeListStyles); begin Styles.Assign(Value); end; procedure TcxCustomTreeList.SetTopVisibleNode(ANode: TcxTreeListNode); begin if (ANode <> TopVisibleNode) and (ANode <> nil) and ANode.IsVisible then begin FTopVisibleNode := ANode; DoTopRecordIndexChanged; LayoutChanged; end; end; procedure TcxCustomTreeList.SetVisibleColumn( Index: Integer; AValue: TcxTreeListColumn); begin VisibleColumns[Index].Assign(AValue); end; procedure TcxCustomTreeList.DoChangedTimer(Sender: TObject); begin if not IsDestroying and not IsLoading then DoChanged(False); end; procedure TcxCustomTreeList.UpdateDesignerForms; var I: Integer; AIntf: IcxTreeListDesigner; begin 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.ComponentModified; end; end; function TcxCustomTreeList.GetObjectName: string; begin Result := GetStoredObjectName; end; function TcxCustomTreeList.GetProperties(AProperties: TStrings): Boolean; begin Result := GetStoredObjectProperties(AProperties); end; procedure TcxCustomTreeList.GetPropertyValue( const AName: string; var AValue: Variant); begin GetStoredPropertyValue(AName, AValue); end; procedure TcxCustomTreeList.SetPropertyValue( const AName: string; const AValue: Variant); begin SetStoredPropertyValue(AName, AValue); end; procedure TcxCustomTreeList.CMDrag(var Message: TCMDrag); var C: Integer; const AcceptedCursors: array[Boolean, Boolean] of TCursor = ((crDrag, crDragCopy), (crcxDragMulti, crcxMultiDragCopy)); begin C := 0; if Assigned(Controller.DragNodesList) then C := Controller.DragNodesList.Count; DragCursor := AcceptedCursors[C > 1, Controller.IsDragCopy]; inherited; end; { TcxTreeListController } 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.BeforeShowEdit; begin if not EditingController.IsEditing then MakeFocusedItemVisible; end; procedure TcxTreeListController.CheckEdit; begin inherited CheckEdit; TreeList.RefreshNavigatorButtons; end; procedure TcxTreeListController.CheckFocusedNodeItem; begin if FocusedNode = nil then FocusedNode := FindNearestFocusableNode(0); if FocusedItem = nil then FocusedItem := FindNearestFocusableColumn(0); end; procedure TcxTreeListController.ChangeFocusedNode(ANode: TcxTreeListNode); begin if (ANode <> nil) and ANode.IsHidden or not TreeList.DoCanFocusNode(ANode) then Exit; if ANode <> FFocusedNode then begin if (FFocusedNode <> nil) and FFocusedNode.Inserting and (TreeList.DataController.EditingNode = nil) then DataController.Cancel else DataController.Post(True); end; TreeList.AddChanges([tcFocusedNode]); if not OptionsSelection.MultiSelect then TreeList.AddChanges([tcSelection]); FPrevFocusedNode := FFocusedNode; FFocusedNode := ANode; TreeList.DataController.SyncFocused(FFocusedNode); CancelIncSearching; end; function TcxTreeListController.GetFocusedRecordIndex: Integer; begin Result := Integer(FocusedNode); end; procedure TcxTreeListController.SetFocusedNode(ANode: TcxTreeListNode); begin if not TreeList.DoCanSelectNode(ANode) then Exit; try ChangeFocusedNode(ANode); finally if ANode <> nil then ANode.MakeVisible; TreeList.ViewInfo.UpdateSelection; end; end; procedure TcxTreeListController.SetFocusedNodeItem( ANode: TcxTreeListNode; AColumn: TcxTreeListColumn); begin SetFocusedRecordItem(Integer(ANode), AColumn); end; procedure TcxTreeListController.SetFocusedRecordIndex(Value: Integer); begin if TcxTreeListNode(Value) = FocusedNode then Exit; if Value = 0 then FocusedNode := nil else FocusedNode := TcxTreeListNode(Value); end; procedure TcxTreeListController.BeforeStartDrag; begin inherited BeforeStartDrag; DragNodesList := TreeList.GetSelectionsEx; if HitTest.HitAtNode and (HitTest.HitAtColumn or HitTest.HitAtIndicator or HitTest.HitAtImages) then begin DragNode := HitTest.HitNode; if not TreeList.DoBeginDragNode(DragNode) then DragNode := nil; end else DragNode := nil; end; function TcxTreeListController.CreateAutoScrollObject(Kind: TScrollBarKind; const ARect: TRect; ACode: TScrollCode): TcxAutoScrollingObject; begin Result := TcxControllerAutoScrollingObject.Create(Self); Result.SetParams(ARect, Kind, ACode, 1); 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); if FocusedNode <> nil then FocusedNode.MakeVisible; finally EndUpdate; end; end; end; procedure TcxTreeListController.DragEnter; var R: TRect; begin if DragDropInProcess then Exit; if TreeList.FDragNode = nil then TreeList.FDragNode := TreeList.FocusedNode; R := TreeList.ViewInfo.ContentBounds; ScrollControllers[bTop] := CreateAutoScrollObject(sbVertical, cxRectSetHeight(R, cxtlScrollDelta * 2), scLineUp); ScrollControllers[bBottom] := CreateAutoScrollObject(sbVertical, cxRectSetTop(R, R.Bottom - cxtlScrollDelta * 2), scLineDown); if (TreeList.Bands.ExpandableBand <> nil) and (TreeList.Bands.ExpandableBand.FixedKind = tlbfNone) then begin R.Left := TreeList.ViewInfo.ContentParts[tlbfNone].Left; R.Bottom := TreeList.ViewInfo.ContentParts[tlbfNone].Bottom end; ScrollControllers[bLeft] := CreateAutoScrollObject(sbHorizontal, cxRectSetWidth(R, cxtlScrollDelta * 2), scLineUp); ScrollControllers[bRight] := CreateAutoScrollObject(sbHorizontal, cxRectSetWidth(R, R.Right - cxtlScrollDelta * 2, cxtlScrollDelta * 2), scLineDown); ExpandTimer := TTimer.Create(TreeList); end; procedure TcxTreeListController.DragLeave; var ASide: TcxBorder; begin for ASide := bLeft to bBottom do FreeAndNil(ScrollControllers[ASide]); FreeAndNil(ExpandTimer); DragDropInProcess := False; 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.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 ResetButtonTimer; if HitTest.HitAtButton and (HitTest.HitNode = ExpandingNode) then ExpandingNode.Expanded := not ExpandingNode.Expanded else ExpandingNode := nil; end; procedure TcxTreeListController.ResetButtonTimer; begin if ExpandTimer <> nil then ExpandTimer.Enabled := False; 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 if AGoForward then begin if (TreeList.LastVisibleNode <> nil) and TreeList.LastVisibleNode.IsLastVisible and TreeList.LastVisibleNode.Focused and ASetCursor then Exit; if ASetCursor then begin TreeList.TopVisibleNode := GetNext(FocusedNode, True); TreeList.SetFocusedNode(TreeList.LastVisibleNode, AShift) end else TreeList.TopVisibleNode := GetNext(TreeList.LastVisibleNode, True); end else begin if (TreeList.TopVisibleNode <> nil) and TreeList.TopVisibleNode.IsFirstVisible and TreeList.TopVisibleNode.Focused and ASetCursor then Exit; if ASetCursor then begin TreeList.LastVisibleNode := GetNext(FocusedNode, False); TreeList.SetFocusedNode(TreeList.TopVisibleNode, AShift) end else TreeList.LastVisibleNode := GetNext(TreeList.TopVisibleNode, False); end; TreeList.LayoutChanged; end; procedure TcxTreeListController.FocusedRecordChanged( APrevFocusedRecordIndex, AFocusedRecordIndex: Integer); begin if AFocusedRecordIndex <> FocusedRecordIndex then CancelSelection(True); end; procedure TcxTreeListController.FocusedItemChanged( APrevFocusedItem: TcxCustomInplaceEditContainer); begin inherited FocusedItemChanged(APrevFocusedItem); TreeList.ViewInfo.UpdateSelection; TreeList.DoFocusedItemChanged(APrevFocusedItem, FocusedItem); 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; 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: begin if ssCtrl in Shift then TreeList.Select(TreeList.TopNode, Shift) else if TreeList.VisibleColumnCount > 0 then TreeList.VisibleColumns[0].Focused := True else Result := False; end; VK_SPACE: if ANode.HasCheckbox and ANode.Enabled then ANode.CheckClick else Result := False; VK_END: begin if ssCtrl in Shift then TreeList.Select(TreeList.LastNode, Shift) else if TreeList.VisibleColumnCount > 0 then TreeList.VisibleColumns[TreeList.VisibleColumnCount - 1].Focused := True else Result := False; end; VK_DELETE: begin Result := (ssCtrl in Shift) and CanDeleteSelection and DeleteConfirmation; if Result then TreeList.DeleteSelection; end; VK_INSERT: begin if (FocusedNode = nil) or (not CanInsertNode) then Result := False else TreeList.InsertNode(FocusedNode, ssCtrl in Shift); end; else Result := False end; end; function TcxTreeListController.CanDrag(X, Y: Integer): Boolean; begin HitTest.HitPoint := Point(X, Y); Result := not HitTest.CanSizing and not TreeList.IsDesigning and not IsEditing and (HitTest.HitAtNode and HitTest.HitNode.Selected and not HitTest.HitAtIndent and not HitTest.HitAtFooterArea); if Result then TreeList.FDragNode := HitTest.HitNode; end; procedure TcxTreeListController.AfterPaint; begin inherited AfterPaint; if (TreeList.DragAndDropState = ddsInProcess) and (TreeList.DragAndDropObject is TcxTreeListSizingDragAndDropObject) then TcxTreeListSizingDragAndDropObject(TreeList.DragAndDropObject).DirtyChanged; end; procedure TcxTreeListController.BeginDragAndDrop; begin inherited BeginDragAndDrop; TreeList.Update; end; function TcxTreeListController.DoHeaderMouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer): Boolean; begin Result := False; if CheckCustomizationPopup then HitTest.RecalculateOnMouseEvent(X, Y, Shift) else begin if HitTest.HitAtHeader and not HitTest.CanSizing and not (ssDouble in Shift) and (Button = mbLeft) then FClickedObject := TcxTreeListHeaderCellViewInfo(HitTest.HitTestItem).Item; if HitTest.HitAtHeader and not HitTest.CanSizing and (ClickedObject = TcxTreeListHeaderCellViewInfo(HitTest.HitTestItem).Item) then begin TcxTreeListCustomHeaderCellViewInfo(HitTest.HitTestItem).Pressed := True; Result := True; end; end; end; function TcxTreeListController.DoNodeMouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer): Boolean; begin Result := False; if CanDrag(X, Y) and HitTest.HitAtNode and IsEditing then TreeList.DragAndDropState := ddsNone; if not (ssDouble in Shift) then CheckNodeContentClick(Shift); if HitTest.HitAtCheckButton and (Button = mbLeft) then HitTest.HitNode.CheckClick else if HitTest.HitAtButton and (Button = mbLeft) then begin HitTest.HitNode.Expanded := not HitTest.HitNode.Expanded; Result := True; end; end; procedure TcxTreeListController.DoMouseDown( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var AIsHotTrack: Boolean; begin inherited MouseDown(Button, Shift, X, Y); EditingController.StopEditShowingTimer; EditingController.HideEdit(True); HitTest.RecalculateOnMouseEvent(X, Y, Shift); HitTest.CheckSelection(Shift); AIsHotTrack := HitTest.HitAtColumn and not HitTest.HitAtNodePreview and HitTest.IsItemEditCell and TcxTreeListEditCellViewInfo(HitTest.HitTestItem).IsEditHotTrack(Point(X, Y)); if not DoHeaderMouseDown(Button, Shift, X, Y) and not HitTest.CanSizing then DoNodeMouseDown(Button, Shift, X, Y); WasFocusedBeforeClick := HitTest.HitAtColumn and not HitTest.HitAtNodePreview and HitTest.HitAtNode and HitTest.HitNode.Focused and HitTest.HitColumn.Focused; if AIsHotTrack then ShowEdit(Shift, X, Y); end; procedure TcxTreeListController.DoMouseMove( Shift: TShiftState; X, Y: Integer); begin inherited DoMouseMove(Shift, X, Y); UpdateHotTrackNode(X, Y, Shift); end; procedure TcxTreeListController.DoMouseUp( Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if PressedHeader <> nil then PressedHeader.Pressed := False; HitTest.RecalculateOnMouseEvent(X, Y, Shift); DragItem := nil; HotTrackController.SetHotElement(nil, cxNullPoint); UpdateHotTrackNode(X, Y, Shift); if Button = mbLeft then CheckHeaderClick(Shift); ClickedObject := nil; (Navigator as TcxTreeListCellNavigator).SaveCurrentNavigationColumn; HitTest.RecalculateOnMouseEvent(X, Y, Shift); if not IsEditing and WasFocusedBeforeClick and (HitTest.HitNode = TreeList.FocusedNode) then begin if GetImmediateEditor then ShowEdit(Shift, X, Y) else EditingController.StartEditShowingTimer(HitTest.HitColumn); end; inherited MouseUp(Button, Shift, X, Y); end; procedure TcxTreeListController.CheckDeletedNode(ANode: TcxTreeListNode); begin if ANode = HotTrackNode then SetHotTrackNode(nil, []); if DragNodesList <> nil then DragNodesList.Remove(ANode); if ANode = FPrevFocusedNode then FPrevFocusedNode := nil; if ANode = IncSearchNode then IncSearchNode := nil; if ANode = FSelectionAnchor then FSelectionAnchor := nil; if (ANode = FFocusedNode) and (FFocusedNode <> nil) then begin FocusedNodeIndex := FFocusedNode.VisibleIndex; FFocusedNode := nil; TreeList.AddChanges([tcSelection, tcFocusedNode]); end; end; procedure TcxTreeListController.CheckFocusedNode; begin if FocusedNode = nil then ChangeFocusedNode(FindNearestFocusableNode(FocusedNodeIndex)); end; procedure TcxTreeListController.CheckHeaderClick(AShift: TShiftState); const ASortOrder: array[Boolean, TcxDataSortOrder] of TcxDataSortOrder = ((soAscending, soDescending, soAscending), (soNone, soNone, soNone)); begin if not HitTest.HitAtColumnHeader or HitTest.CanSizing or TreeList.IsDesigning or (ClickedObject <> HitTest.HitColumn) then Exit; TreeList.SetGlassCursor; try HitTest.HitColumn.ChangeSortOrder(ASortOrder[ssCtrl in AShift, HitTest.HitColumn.SortOrder], AShift); finally TreeList.RestoreCursor; end; end; procedure TcxTreeListController.CheckNodeContentClick(Shift: TShiftState); begin if HitAtNodeContent then begin TreeList.BeginUpdate; try if HitTest.HitAtColumn then FocusedItem := FindNearestFocusableColumn(HitTest.HitColumn.VisibleIndex); if FocusedItem = nil then FocusedItem := FindNearestFocusableColumn(0); Select(HitTest.HitNode, Shift) finally TreeList.CancelUpdate; end; end else if HitTest.HitAtBackground then CancelSelection; 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 := (DataController.EditingNode = nil) or (DataController.EditingNode.Inserting and DataController.IsValueChanged); if Result then DataController.Post; end; function TcxTreeListController.CanSelectNode( ANode: TcxTreeListNode): Boolean; begin Result := TreeList.DoCanFocusNode(ANode) and TreeList.DoCanSelectNode(ANode); end; function TcxTreeListController.CheckCustomizationPopup: Boolean; begin Result := (HitTest.HitAtBandCustomizing or HitTest.HitAtColumnCustomizing) and TcxTreeListIndicatorCellViewInfo(HitTest.HitTestItem).IsQuickCustomizationEnabled and not (ColumnsCustomizationPopup.JustClosed or BandsCustomizationPopup.JustClosed); if Result then TcxTreeListIndicatorCellViewInfo(HitTest.HitTestItem).ShowPopup; end; procedure TcxTreeListController.DblClick; begin if IsEditing and (FocusedNode <> nil) and FocusedNode.HasChildren then EditingController.HideEdit(True); EditingController.StopEditShowingTimer; inherited DblClick; HitTest.Recalculate; if HitTest.HitAtNode and not (HitTest.HitAtButton or HitTest.HitAtFooterArea or HitTest.HitAtCheckButton or IsEditing) and OptionsBehavior.ExpandOnDblClick then HitTest.HitNode.Expanded := not HitTest.HitNode.Expanded; if HitTest.HitAtSizingHorz then begin if HitTest.HitAtBandHeader then HitTest.HitBand.ApplyBestFit else HitTest.HitColumn.ApplyBestFit; end; ClickedObject := nil; end; function TcxTreeListController.FindNearestFocusableNode( AVisibleIndex: Integer): TcxTreeListNode; begin Result := nil; if TreeList.AbsoluteVisibleCount <= 0 then Exit; AVisibleIndex := Max(0, Min(TreeList.AbsoluteVisibleCount - 1, AVisibleIndex)); Result := TreeList.AbsoluteVisibleItems[AVisibleIndex]; while (Result <> nil) and not TreeList.DoCanFocusNode(Result) do Result := Result.GetNextVisible; if Result <> nil then Exit; Result := TreeList.AbsoluteVisibleItems[AVisibleIndex]; while (Result <> nil) and not TreeList.DoCanFocusNode(Result) do Result := Result.GetPrevVisible; end; function TcxTreeListController.FindNearestFocusableColumn( AVisibleIndex: Integer): TcxTreeListColumn; var I: Integer; begin Result := nil; AVisibleIndex := Max(0, Min(AVisibleIndex, TreeList.VisibleColumnCount - 1)); if AVisibleIndex < TreeList.VisibleColumnCount then begin for I := AVisibleIndex to TreeList.VisibleColumnCount - 1 do if TreeList.VisibleColumns[I].Options.Focusing then begin Result := TreeList.VisibleColumns[I]; Exit; end; for I := AVisibleIndex downto 0 do if TreeList.VisibleColumns[I].Options.Focusing then begin Result := TreeList.VisibleColumns[I]; Break; 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( cxGetResourceString(@scxTreeListDeletingFocusedConfirmationText), cxGetResourceString(@scxTreeListDeletingConfirmationCaption)) else Result := True; end; function TcxTreeListController.GetCursor(X, Y: Integer): TCursor; begin Result := crDefault; if not TreeList.IsDesigning and not (TreeList.FGlassCursorRefCount > 0) then begin HitTest.HitPoint := Point(X, Y); Result := HitTest.Cursor; end; end; function TcxTreeListController.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; const HeaderDragObject: array[Boolean] of TcxDragAndDropObjectClass = (TcxTreeListDragAndDropBandObject, TcxTreeListDragAndDropColumnObject); begin DragItem := HitTest.DragItem; if HitTest.CanSizing then begin FResizeDirection := TcxDragSizingDirection(HitTest.HitAtSizingVert); Result := TcxTreeListSizingDragAndDropObject; end else if HitTest.CanMoving then Result := HeaderDragObject[HitTest.HitAtColumnHeader] else if HitTest.HitAtNode then Result := nil else Result := inherited GetDragAndDropObjectClass; end; function TcxTreeListController.HitAtNodeContent: Boolean; begin Result := HitTest.HitAtNode and (HitTest.HitAtIndicator or HitTest.HitAtImages or HitTest.HitAtColumn or HitTest.HitAtBand or HitTest.HitAtNodePreview) and not HitTest.HitAtFooterArea; end; procedure TcxTreeListController.KeyDown(var Key: Word; Shift: TShiftState); var AKey: Word; APrevNode: TcxTreeListNode; begin AKey := Key; EatKeyPress := IsNodeKeyHandle(FocusedNode, Key, Shift); CheckFocusedNodeItem; if (AKey = VK_SPACE) and (FocusedNode <> nil) and OptionsSelection.MultiSelect and ([ssCtrl, ssShift] * Shift <> []) then begin if (ssCtrl in Shift) then begin FocusedNode.Selected := not FocusedNode.Selected; if FocusedNode.Selected then FSelectionAnchor := FocusedNode; end else Select(FocusedNode, Shift); Key := 0; end; if (TreeList.VisibleColumnCount = 1) and (FocusedNode <> nil) and (FocusedNode.HasChildren) and (((Key = VK_LEFT) and FocusedNode.Expanded) or ((Key = VK_RIGHT) and not FocusedNode.Expanded)) then begin FocusedNode.Expanded := not FocusedNode.Expanded; Key := 0; 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 := SelectionAnchor; Selection.Clear; if (SelectionAnchor <> nil) then Selection.Add(SelectionAnchor); Select(FocusedNode, Shift); SelectionAnchor := APrevNode; end else Select(FocusedNode, Shift); end; VK_MENU, VK_SHIFT, VK_CONTROL: begin if SelectionAnchor = nil then SelectionAnchor := FocusedNode; SetHotTrackNode(HotTrackNode, Shift); end; end; end; procedure TcxTreeListController.KeyUp(var Key: Word; Shift: TShiftState); begin inherited KeyUp(Key, Shift); case Key of VK_MENU, VK_SHIFT, VK_CONTROL: SetHotTrackNode(HotTrackNode, Shift); end; end; procedure TcxTreeListController.MakeFocusedItemVisible; var AColumn: TcxTreeListColumn; begin AColumn := TcxTreeListColumn(FocusedItem); if AColumn <> nil then begin AColumn.MakeVisible; if not TreeList.IsLocked then MakeFocusedRecordVisible; end; end; procedure TcxTreeListController.MakeFocusedRecordVisible; begin if FocusedNode <> nil then FocusedNode.MakeVisible; end; procedure TcxTreeListController.Reset; begin FPressedHeader := nil; ClickedObject := nil; end; procedure TcxTreeListController.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); begin if TreeList.IsLocked or (AScrollCode = scEndScroll) then Exit; EditingController.StopEditShowingTimer; if AScrollBarKind = sbHorizontal then TreeList.ViewInfo.ScrollHorz(AScrollCode, AScrollPos) else TreeList.ViewInfo.ScrollVert(AScrollCode, AScrollPos); UpdateHotTrackNode([]); TreeList.ViewInfo.IsDirty := False; TreeList.UpdateScrollBars; end; procedure TcxTreeListController.SetSelection(AList: TList); var AHelper: TcxCustomDesignSelectionHelper; begin if not CanCreateSelectionHelper then Exit; AHelper := cxDesignSelectionHelperClass.Create(TreeList); try AHelper.SetSelection(AList); finally AHelper.Free; end; end; procedure TcxTreeListController.SetFocusedRecordItem(ARecordIndex: Integer; AItem: TcxCustomInplaceEditContainer); begin if AItem = TreeList.Preview.Column then AItem := FocusedItem; if not TreeList.Dragging then inherited SetFocusedRecordItem(ARecordIndex, AItem); end; procedure TcxTreeListController.SetHotTrackCursor(ACursor: TCursor); begin TreeList.Cursor := ACursor; end; procedure TcxTreeListController.SetHotTrackNode( ANode: TcxTreeListNode; AShift: TShiftState); var ACursor: TCursor; APrevNode: TcxTreeListNode; begin if not TreeList.Focused or TreeList.HitTest.CanSizing then ANode := nil; if (TreeList.IsDestroying or not TreeList.OptionsBehavior.HotTrack) or ((ANode = HotTrackNode) and (HotTrackColumn = HitTest.HitColumn)) then Exit; APrevNode := HotTrackNode; HotTrackNode := ANode; HotTrackColumn := HitTest.HitColumn; HotTrackShift := AShift; if APrevNode <> nil then APrevNode.Repaint(True) else begin if TreeList.FGlassCursorRefCount > 0 then PrevCursor := TreeList.FStoredCursor else PrevCursor := TreeList.Cursor; end; if ANode <> nil then begin ANode.Repaint(True); TreeList.DoHotTrackNode(ANode, AShift, ACursor); SetHotTrackCursor(ACursor); end else SetHotTrackCursor(PrevCursor); end; procedure TcxTreeListController.ShowEdit(AShift: TShiftState; X, Y: Integer); begin if FocusedItem = nil then Exit; WasFocusedBeforeClick := False; EditingController.ShowEdit(FocusedItem, [ssLeft] * AShift, X, Y); end; function TcxTreeListController.StartDragAndDrop(const P: TPoint): Boolean; begin HitTest.HitPoint := P; Result := HitTest.CanSizing or HitTest.CanMoving; //and not (HitTest.HitAtNode and HitTest.HitNode.Selected and not HitTest.HitAtIndent); 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 and not HitTest.HitAtFooterArea then SetHottrackNode(HitTest.HitNode, AShift) else SetHottrackNode(nil, AShift); end; function TcxTreeListController.GetFocusedCellViewInfo( AEditContainer: TcxCustomInplaceEditContainer): TcxEditCellViewInfo; begin Result := nil; if (AEditContainer = nil) or TreeList.ViewInfo.IsDirty then Exit; Result := TreeList.ViewInfo.GetEditCell(FocusedNode, TcxTreeListColumn(AEditContainer)); end; function TcxTreeListController.GetNavigatorClass: TcxCustomCellNavigatorClass; begin Result := TcxTreeListCellNavigator; end; function TcxTreeListController.GetNode(ARecordIndex: Integer): TcxTreeListNode; begin if ARecordIndex >= 0 then Result := TcxTreeListNode(ARecordIndex) else Result := nil; end; procedure TcxTreeListController.CancelIncSearching; begin if TreeList.IsDestroying or TreeList.IsLoading or (IncSearchNode = nil) or SearchNotification then Exit; IncSearchText := ''; IncSearchNode := nil; inherited CancelIncSearching; end; function TcxTreeListController.DoSearch(AFromNode: TcxTreeListNode; AItemIndex: Integer; const AText: string; AGoForward: Boolean): Boolean; function DoSearchNode(AForward: Boolean; var ANode: TcxTreeListNode): Boolean; begin Result := False; ANode := AFromNode; while not Result and (ANode <> nil) do begin Result := ANode.Visible and DataCompareText(ANode.Texts[AItemIndex], AText, True); if not Result then ANode := GetNextNodeForIncSearch(ANode, AForward); end; end; var ANode: TcxTreeListNode; begin EditingController.StopEditShowingTimer; Result := DoSearchNode(AGoForward, ANode); if not Result then Result := DoSearchNode(not AGoForward, ANode); if Result then IncSearchNode := ANode; 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.GetNextNodeForIncSearch( ANode: TcxTreeListNode; AGoForward: Boolean): TcxTreeListNode; begin Result := nil; if TreeList.OptionsBehavior.ExpandOnIncSearch then begin if AGoForward then begin ANode.LoadChildren; Result := ANode.GetNext end else Result := ANode.GetPrev end else if cxInRange(ANode.VisibleIndex + cxIntOffs[AGoForward], 0, TreeList.AbsoluteVisibleCount - 1) then Result := TreeList.AbsoluteVisibleItems[ANode.VisibleIndex + cxIntOffs[AGoForward]]; end; procedure TcxTreeListController.CheckLocate(AFound: Boolean); begin if AFound then Exit; if IncSearchNode = nil then IncSearchText := '' else IncSearchText := Copy(IncSearchingText, 1, Length(IncSearchingText) - 1) end; procedure TcxTreeListController.SearchLocate( AItem: TcxCustomInplaceEditContainer; const AValue: string); var ANode: TcxTreeListNode; begin ANode := TreeList.FocusedNode; if ANode = nil then ANode := TreeList.Root.FFirst; if (AItem = nil) or (ANode = nil) then Exit; IncSearchText := AValue; CheckLocate(DoSearch(ANode, TcxTreeListColumn(AItem).ItemIndex, IncSearchText, True)); end; procedure TcxTreeListController.SearchLocateNext( AItem: TcxCustomInplaceEditContainer; AForward: Boolean); var ANode: TcxTreeListNode; begin if (AItem = nil) or (TreeList.FocusedNode = nil) then Exit; ANode := GetNextNodeForIncSearch(TreeList.FocusedNode, AForward); if ANode = nil then ANode := TreeList.FocusedNode; CheckLocate(DoSearch(ANode, TcxTreeListColumn(AItem).ItemIndex, IncSearchText, AForward)); 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 OptionsSelection.MultiSelect then begin TreeList.BeginUpdate; try SelectionAnchor := nil; Selection.Clear; if (FocusedNode <> nil) and KeepPrimary then FocusedNode.Selected := True finally TreeList.EndUpdate; end; end; end; procedure TcxTreeListController.Select( ANode: TcxTreeListNode; AShift: TShiftState); begin if not CanSelectNode(ANode) then Exit; TreeList.BeginUpdate; try if ANode = nil then begin TreeList.FocusedNode := nil; Exit; end; ANode.Focused := True; if not (ssShift in AShift) and ((ssCtrl in AShift) or not ANode.Selected) then SelectionAnchor := ANode; if not ANode.Selected and (not OptionsSelection.MultiSelect or ([ssShift, ssCtrl] * AShift = [])) then begin Selection.Clear; Selection.Add(ANode); end else if [ssCtrl, ssLeft] * AShift = [ssCtrl, ssLeft] then begin if ANode.Selected then Selection.Remove(ANode) else Selection.Add(ANode); end else if (ssLeft in AShift) and ANode.Selected then Exit else if ssShift in AShift then begin if SelectionAnchor = nil then FSelectionAnchor := FocusedNode; SelectRange(SelectionAnchor, ANode); end; TreeList.AddChanges([tcSelection]); finally TreeList.CancelUpdate; TreeList.ViewInfo.UpdateSelection; end; end; procedure TcxTreeListController.SelectRange( const AStartNode, AFinishNode: TcxTreeListNode); var I: Integer; begin if AStartNode.VisibleIndex > AFinishNode.VisibleIndex then begin SelectRange(AFinishNode, AStartNode); Exit; end; Selection.Clear; Selection.Capacity := AFinishNode.VisibleIndex - AStartNode.VisibleIndex + 1; for I := AStartNode.VisibleIndex to AFinishNode.VisibleIndex do Selection.Add(TreeList.AbsoluteVisibleItems[I]); end; procedure TcxTreeListController.ViewInfoChanged; begin Reset; TreeList.ViewInfo.IsDirty := True; inherited ViewInfoChanged; end; function TcxTreeListController.GetResizeDirection: TcxDragSizingDirection; begin Result := FResizeDirection; end; procedure TcxTreeListController.MouseLeave; begin inherited MouseLeave; if PressedHeader <> nil then PressedHeader.Pressed := False; with TreeList.ScreenToClient(GetMouseCursorPos) do UpdateHotTrackNode(X, Y, []); end; procedure TcxTreeListController.DoCancelMode; begin inherited DoCancelMode; MouseLeave; end; function TcxTreeListController.GetBandsCustomizationPopup: TcxTreeListBandsCustomizationPopup; begin if FBandsCustomizationPopup = nil then FBandsCustomizationPopup := TcxTreeListBandsCustomizationPopup.Create(TreeList); Result := FBandsCustomizationPopup; end; function TcxTreeListController.GetColumnsCustomizationPopup: TcxTreeListColumnsCustomizationPopup; begin if FColumnsCustomizationPopup = nil then FColumnsCustomizationPopup := TcxTreeListColumnsCustomizationPopup.Create(TreeList); Result := FColumnsCustomizationPopup; end; function TcxTreeListController.GetDataController: TcxTreeListDataController; begin Result := TreeList.DataController; end; function TcxTreeListController.GetEditingController: TcxTreeListEditingController; begin Result := TcxTreeListEditingController(inherited EditingController); end; function TcxTreeListController.GetFocusedNodeIndex: Integer; begin Result := FFocusedNodeIndex; if FFocusedNode <> nil then Result := FFocusedNode.VisibleIndex; end; function TcxTreeListController.GetHitTest: TcxTreeListHitTest; begin Result := TreeList.HitTest; end; function TcxTreeListController.GetOptionsBehavior: TcxTreeListOptionsBehavior; begin Result := TreeList.OptionsBehavior; end; function TcxTreeListController.GetOptionsSelection: TcxTreeListOptionsSelection; begin Result := TreeList.OptionsSelection; end; function TcxTreeListController.GetIsDragCopy: Boolean; begin Result := IsCtrlPressed and TreeList.OptionsBehavior.AutoDragCopy; end; function TcxTreeListController.GetSelection: TList; begin Result := TreeList.SelectionList; end; function TcxTreeListController.GetSelectionAnchor: TcxTreeListNode; begin Result := FSelectionAnchor; if Result = nil then Result := FocusedNode; while (Result <> nil) and not Result.IsVisible do Result := Result.Parent; end; function TcxTreeListController.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(EditingControl); end; procedure TcxTreeListController.SetForcingWidthColumn( AColumn: TcxTreeListColumn); begin FForcingWidthColumn := AColumn; end; procedure TcxTreeListController.SetIncSearchNode(ANode: TcxTreeListNode); var APrevNode: TcxTreeListNode; begin if ANode = IncSearchNode then begin if (ANode <> nil) then ANode.Repaint(True); Exit; end; FSearchNotification := True; try APrevNode := IncSearchNode; FIncSearchNode := ANode; if (APrevNode <> nil) and not APrevNode.Deleting then APrevNode.Repaint(True); if IncSearchNode <> nil then begin TreeList.FocusedNode := IncSearchNode; IncSearchNode.Repaint(True); end; finally FSearchNotification := False; end; end; procedure TcxTreeListController.SetPressedHeader( AHeader: TcxTreeListCustomHeaderCellViewInfo); begin if (FPressedHeader <> AHeader) and (FPressedHeader <> nil) then FPressedHeader.State := cxbsNormal; FPressedHeader := AHeader; if FPressedHeader <> nil then begin FPressedHeader.State := cxbsPressed; FPressedHeader.Click; end; end; { TcxTreeListSummary } constructor TcxTreeListSummary.Create(ATreeList: TcxCustomTreeList); begin inherited Create; FTreeList := ATreeList; FAbsoluteFooterSummaryItems := TList.Create; FAbsoluteGroupFooterSummaryItems := TList.Create; end; destructor TcxTreeListSummary.Destroy; begin FreeAndNil(FAbsoluteGroupFooterSummaryItems); FreeAndNil(FAbsoluteFooterSummaryItems); inherited Destroy; end; procedure TcxTreeListSummary.Recalculate; begin TreeList.StructureChanged; end; procedure TcxTreeListSummary.AddSummaryItems(AAbsoluteSummaryItems: TList; ASummaryItems: TcxTreeListSummaryItems; AIsVisible: Boolean; var AVisibleCount, AVisibleRowCount: Integer); var I: Integer; begin for I := 0 to ASummaryItems.Count - 1 do ASummaryItems[I].AbsoluteIndex := AAbsoluteSummaryItems.Add(ASummaryItems[I]); if AIsVisible then begin Inc(AVisibleCount, ASummaryItems.VisibleCount); AVisibleRowCount := Max(AVisibleRowCount, ASummaryItems.VisibleCount * ASummaryItems.Column.Position.LineCount); end; end; procedure TcxTreeListSummary.Calculate; var I: Integer; begin FAbsoluteFooterSummaryItems.Clear; FAbsoluteGroupFooterSummaryItems.Clear; FFooterSummaryRowCount := 0; FFooterSummaryVisibleCount := 0; FGroupFooterSummaryRowCount := 0; FGroupFooterSummaryVisibleCount := 0; for I := 0 to FTreeList.ColumnCount - 1 do begin AddSummaryItems(FAbsoluteFooterSummaryItems, FTreeList.Columns[I].Summary.FooterSummaryItems, FTreeList.Columns[I].ActuallyVisible and FTreeList.Columns[I].Options.Footer, FFooterSummaryVisibleCount, FFooterSummaryRowCount); AddSummaryItems(FAbsoluteGroupFooterSummaryItems, FTreeList.Columns[I].Summary.GroupFooterSummaryItems, FTreeList.Columns[I].ActuallyVisible and FTreeList.Columns[I].Options.GroupFooter, FGroupFooterSummaryVisibleCount, FGroupFooterSummaryRowCount); end; IsDirty := True; end; procedure TcxTreeListSummary.CalculateNode(ADestNode, AValueNode: TcxTreeListNode; AItems: TList); begin ProcessSummaryValues(ADestNode, AValueNode, AItems); while ADestNode <> Root do begin ADestNode := ADestNode.Parent; if ADestNode <> Root then ProcessSummaryValues(ADestNode, AValueNode, AItems); end; end; procedure TcxTreeListSummary.CheckChanges; begin if IsDirty then begin IsDirty := False; ProcessNode(Root); TreeList.DoAfterSummary; end; end; function TcxTreeListSummary.DoProcessSummaryValue(ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem; var ASummaryValue: Variant; var ASummaryCount: Integer; var AValue: Variant; var ACount: Integer): Boolean; var AArguments: TcxTreeListSummaryEventArguments; AOutArguments: TcxTreeListSummaryEventOutArguments; begin Result := Assigned(TreeList.OnSummary); if Result then begin AArguments.Node := ANode; AArguments.SummaryItem := ASummaryItem; AOutArguments.Value := AValue; AOutArguments.SummaryValue := ASummaryValue; AOutArguments.CountValue := ACount; AOutArguments.Done := False; TreeList.OnSummary(TreeList, AArguments, AOutArguments); ASummaryValue := AOutArguments.SummaryValue; ACount := AOutArguments.CountValue; AValue := AOutArguments.Value; Result := AOutArguments.Done; end; end; procedure TcxTreeListSummary.FinalizeValues(ANode: TcxTreeListNode; AItems: TList); var ASummaryItem: TcxTreeListSummaryItem; I: Integer; AVarIsDate: Boolean; ASummaryInfos: TcxTreeListSummaryInfos; begin ASummaryInfos := ANode.FSummaryInfo; for I := 0 to AItems.Count - 1 do begin ASummaryItem := AItems[I]; if VarIsEmpty(ASummaryInfos[I].TempValue) then ASummaryInfos[I].Value := Null; case ASummaryItem.Kind of skMin, skMax, skSum: ASummaryInfos[I].Value := ASummaryInfos[I].TempValue; skCount: ASummaryInfos[I].Value := ASummaryInfos[I].Count; skAverage: if (ASummaryInfos[I].Count > 0) and not VarIsEmpty(ASummaryInfos[I].TempValue) then begin AVarIsDate := VarIsDate(ASummaryInfos[I].TempValue); ASummaryInfos[I].Value := ASummaryInfos[I].TempValue / ASummaryInfos[I].Count; if AVarIsDate then VarCast(ASummaryInfos[I].Value, ASummaryInfos[I].TempValue, varDate); end; end; end; end; procedure TcxTreeListSummary.InitializeValues(ANode: TcxTreeListNode; AItems: TList); var I: Integer; ASummaryItem: TcxTreeListSummaryItem; begin SetLength(ANode.FSummaryInfo, 0); SetLength(ANode.FSummaryInfo, AItems.Count); for I := 0 to AItems.Count - 1 do begin ASummaryItem := TcxTreeListSummaryItem(AItems[I]); ANode.FSummaryInfo[I].Count := 0; if ASummaryItem.Kind in [skSum, skAverage] then ANode.FSummaryInfo[I].TempValue := 0 else ANode.FSummaryInfo[I].TempValue := Null; ANode.FSummaryInfo[I].Value := Null; end; end; procedure TcxTreeListSummary.Notification(AComponent: TComponent; Operation: TOperation); var I: Integer; begin Calculate; for I := 0 to FAbsoluteFooterSummaryItems.Count - 1 do TcxTreeListSummaryItem(FAbsoluteFooterSummaryItems[I]).Notification(AComponent, Operation); for I := 0 to FAbsoluteGroupFooterSummaryItems.Count - 1 do TcxTreeListSummaryItem(FAbsoluteGroupFooterSummaryItems[I]).Notification(AComponent, Operation); end; procedure TcxTreeListSummary.ProcessNode(AParent: TcxTreeListNode); var AList: TList; ANode: TcxTreeListNode; begin AList := FAbsoluteGroupFooterSummaryItems; if AParent = Root then AList := FAbsoluteFooterSummaryItems; InitializeValues(AParent, AList); ANode := AParent.GetFirstChildVisible; while ANode <> nil do begin CalculateNode(Root, ANode, FAbsoluteFooterSummaryItems); if AParent <> Root then CalculateNode(AParent, ANode, FAbsoluteGroupFooterSummaryItems); if ANode.HasChildren then ProcessNode(ANode) else SetLength(ANode.FSummaryInfo, 0); ANode := ANode.GetNextSiblingVisible; end; FinalizeValues(AParent, AList); end; procedure TcxTreeListSummary.ProcessSummaryValue(ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem; var ASummaryValue: Variant; var ASummaryCount: Integer); var AValue: Variant; ACount: Integer; begin ACount := 1; AValue := ANode.Values[ASummaryItem.CalculatedColumn.ItemIndex]; if not DoProcessSummaryValue(ANode, ASummaryItem, ASummaryValue, ASummaryCount, AValue, ACount) and not (TreeList.OptionsData.SummaryNullIgnore and VarIsNull(AValue)) then begin if VarIsNull(ASummaryValue) then ASummaryValue := AValue else if not VarIsNull(AValue) then case ASummaryItem.Kind of skSum, skAverage: ASummaryValue := ASummaryValue + AValue; skMin: if AValue < ASummaryValue then ASummaryValue := AValue; skMax: if AValue > ASummaryValue then ASummaryValue := AValue; end; Inc(ASummaryCount, ACount); end; end; procedure TcxTreeListSummary.ProcessSummaryValues(ADestNode, AValueNode: TcxTreeListNode; AItems: TList); var I: Integer; ASummaryItem: TcxTreeListSummaryItem; AAbsoluteItemIndex: Integer; begin for I := 0 to AItems.Count - 1 do begin ASummaryItem := AItems[I]; if(ASummaryItem.AllNodes or (AValueNode.Parent = ADestNode)) and (ASummaryItem.Kind <> skNone) then begin AAbsoluteItemIndex := ASummaryItem.AbsoluteIndex; ProcessSummaryValue(AValueNode, ASummaryItem, ADestNode.FSummaryInfo[AAbsoluteItemIndex].TempValue, ADestNode.FSummaryInfo[AAbsoluteItemIndex].Count); end; end; end; function TcxTreeListSummary.GetFooterSummaryCount: Integer; begin Result := FAbsoluteFooterSummaryItems.Count; end; function TcxTreeListSummary.GetFooterSummaryItem( AIndex: Integer): TcxTreeListSummaryItem; begin Result := TcxTreeListSummaryItem(FAbsoluteFooterSummaryItems[AIndex]); end; function TcxTreeListSummary.GetFooterSummaryText( ASummaryItem: TcxTreeListSummaryItem): string; begin Result := GetGroupFooterSummaryText(ASummaryItem, Root); end; function TcxTreeListSummary.GetFooterSummaryValue( ASummaryItem: TcxTreeListSummaryItem): Variant; begin Result := GetGroupFooterSummaryValue(ASummaryItem, Root); end; function TcxTreeListSummary.GetGroupFooterSummaryCount: Integer; begin Result := FAbsoluteGroupFooterSummaryItems.Count; end; function TcxTreeListSummary.GetGroupFooterSummaryItem( AIndex: Integer): TcxTreeListSummaryItem; begin Result := TcxTreeListSummaryItem(FAbsoluteGroupFooterSummaryItems[AIndex]); end; function TcxTreeListSummary.GetGroupFooterSummaryText( ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode): string; begin Result := ASummaryItem.FormatValue( GetGroupFooterSummaryValue(ASummaryItem, ANode), True); end; function TcxTreeListSummary.GetGroupFooterSummaryValue( ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode): Variant; begin Result := ANode.FooterSummaryValues[ASummaryItem.AbsoluteIndex]; end; function TcxTreeListSummary.GetRoot: TcxTreeListNode; begin Result := TreeList.Root; end; procedure TcxTreeListSummary.SetFooterSummaryValue( ASummaryItem: TcxTreeListSummaryItem; const Value: Variant); begin GroupFooterSummaryValues[ASummaryItem, Root] := Value; end; procedure TcxTreeListSummary.SetGroupFooterSummaryValue( ASummaryItem: TcxTreeListSummaryItem; ANode: TcxTreeListNode; const Value: Variant); begin ANode.FooterSummaryValues[ASummaryItem.AbsoluteIndex] := Value; end; { TcxTreeListSizingDragAndDropObject } procedure TcxTreeListSizingDragAndDropObject.BeginDragAndDrop; begin FOffset := cxNullPoint; FDragItem := TcxTreeListController(Controller).DragItem; with TcxTreeListController(Controller) do begin if DragItem is TcxTreeListCustomCellViewInfo then begin if GetResizeDirection = dsdHorz then FOffset.X := TcxTreeListCustomCellViewInfo(DragItem).DisplayRect.Right - CurMousePos.X else FOffset.Y := TcxTreeListCustomCellViewInfo(DragItem).DisplayRect.Bottom - CurMousePos.Y end else if DragItem is TcxTreeListNode then with TcxTreeListNode(DragItem).FViewData do FOffset.Y := Origin.Y + Height - CurMousePos.Y; end; inherited BeginDragAndDrop; end; procedure TcxTreeListSizingDragAndDropObject.DragAndDrop( const P: TPoint; var Accepted: Boolean); begin TcxTreeListController(Controller).ClickedObject := nil; TcxTreeListController(Controller).DragItem := FDragItem; inherited; end; function TcxTreeListSizingDragAndDropObject.GetSizingMarkBounds: TRect; begin Result := inherited GetSizingMarkBounds; OffsetRect(Result, FOffset.X, FOffset.Y); end; { TcxTreeListDragAndDropBandObject } function TcxTreeListDragAndDropBandObject.CanCustomize: Boolean; begin Result := Band.Options.Customizing and OptionsCustomizing.BandCustomizing; end; function TcxTreeListDragAndDropBandObject.CanDrop: Boolean; function GetNearestColIndex(AForward: Boolean): Integer; begin Result := Band.Position.VisibleColIndex; if AForward then Inc(Result) else Dec(Result); end; begin Result := TreeList.Bands.VisibleItemCount = 0; if Result or (DestBand = nil) or (DestBand = Band) then Exit; Result := DestBand.FixedKind = Band.FixedKind; if not Result and not Band.Visible and (Bands.GetVisibleCountByKind(Band.FixedKind) = 0) and DestBand.IsRoot then begin case Band.FixedKind of tlbfLeft: Result := (DropPosition = posLeft) and (DestBand.VisibleRootIndex = Bands.GetFirstVisibleRootIndex(tlbfNone)); tlbfNone: Result := (DropPosition = posRight) and (DestBand.VisibleRootIndex = Bands.GetLastVisibleRootIndex(tlbfLeft)) or (DropPosition = posLeft) and (DestBand.VisibleRootIndex = Bands.GetFirstVisibleRootIndex(tlbfRight)); tlbfRight: Result := (DropPosition = posRight) and (DestBand.VisibleRootIndex = Bands.GetLastVisibleRootIndex(tlbfNone)); end; end; if not Result or not Band.Visible then Exit; case DropInfo.Position of posLeft, posRight: Result := (DestBand.ParentBand <> Band.ParentBand) or (DestBand.Position.VisibleColIndex <> GetNearestColIndex(DropPosition = posLeft)); posTop: Result := (DestBand.ParentBand <> Band) or (Band.FChildVisibleBands.Count > 1); posBottom: Result := (Band.ParentBand <> DestBand) or (DestBand.FChildVisibleBands.Count > 1); end; end; function TcxTreeListDragAndDropBandObject.CanRemove: Boolean; begin Result := CanCustomize and (Customizing or TreeList.OptionsCustomizing.BandHiding) and not Band.Options.Hidden and (not Band.IsRoot or (Bands.VisibleItemCount > 1)); end; function TcxTreeListDragAndDropBandObject.CheckBandInsertAt( ABand: TcxTreeListBand): Boolean; var I: Integer; begin Result := PtInRect(GetBoundsForInsert(ABand), DropInfo.DropPos); if Result then begin DropInfo.Band := ABand; DropInfo.Position := GetPointPosition(ABand.HeaderCell.GetClipRect, DropInfo.DropPos, True, TreeList.OptionsCustomizing.NestedBands); end else if TreeList.OptionsCustomizing.NestedBands and not ABand.IsBottom then begin for I := 0 to ABand.ChildVisibleBands.Count - 1 do begin Result := CheckBandInsertAt(TcxTreeListBand(ABand.ChildVisibleBands[I])); if Result then Break; end; end; end; procedure TcxTreeListDragAndDropBandObject.CheckDragPosition; var I: Integer; begin DropInfo.Band := nil; DropInfo.Position := posLeft; for I := 0 to TreeList.Bands.VisibleRootItemCount - 1 do if CheckBandInsertAt(TreeList.Bands.VisibleRootItems[I]) then Break; end; function TcxTreeListDragAndDropBandObject.Drop: Boolean; begin Result := True; if CanDrop then begin BeforeDropPositionChange; Band.Position.BandIndex := GetDropParentBandIndex; Band.Position.ColIndex := GetDropColIndex; AfterDropPositionChange; Band.Visible := True; end else if (DestBand = nil) and CanRemove then Band.Visible := False else if Bands.VisibleItemCount = 0 then begin Band.Position.BandIndex := -1; Band.Visible := True; end else Result := False; end; function TcxTreeListDragAndDropBandObject.GetBoundsForInsert( ABand: TcxTreeListBand): TRect; begin Result := ABand.HeaderCell.GetClipRect; if ABand.IsRoot then Dec(Result.Top, cxTreeListHeaderMovingZoneSize); if ABand.IsBottom then Inc(Result.Bottom, cxTreeListHeaderMovingZoneSize); end; procedure TcxTreeListDragAndDropBandObject.MakeCustomizingPageVisible; begin if Band.ActuallyVisible then TreeList.Customizing.FHeaderListBox.ItemIndex := -1; TreeList.Customizing.MakeBandPageVisible; end; procedure TcxTreeListDragAndDropBandObject.AfterDropPositionChange; var I: Integer; begin case DropPosition of posTop: begin DestBand.Position.BandIndex := Band.Index; DestBand.Position.ColIndex := 0; end; posBottom: begin I := 0; while I < DestBand.ChildVisibleBands.Count do if DestBand.ChildVisibleBands[I] <> Band then tcxTreeListBand(DestBand.ChildVisibleBands[I]).Position.BandIndex := Band.Index else Inc(I); end; end; end; procedure TcxTreeListDragAndDropBandObject.BeforeDropPositionChange; var AColIndex, I: Integer; begin if (DropPosition <> posBottom) and (GetDropParentBandIndex = Band.Index) then begin AColIndex := Band.Position.ColIndex; for I := Band.ChildBandCount - 1 downto 0 do with Band.ChildBands[I].Position do begin BandIndex := Band.Position.BandIndex; ColIndex := AColIndex; end; end; end; function TcxTreeListDragAndDropBandObject.GetBand: TcxTreeListBand; begin Result := TcxTreeListBandHeaderCellViewInfo(DragHeader).Band; end; function TcxTreeListDragAndDropBandObject.GetDropParentBandIndex: Integer; begin if DropPosition = posBottom then Result := DestBand.Index else begin if DestBand = nil then Result := -1 else Result := DestBand.Position.BandIndex; end; end; function TcxTreeListDragAndDropBandObject.GetDropColIndex: Integer; begin if DropPosition = posBottom then Result := 0 else begin if DestBand = nil then Result := 0 else Result := DestBand.Position.ColIndex; if DropPosition = posRight then Inc(Result); if Band.Position.ColIndex < Result then Dec(Result); end; end; { TcxTreeListDragAndDropColumnObject } function TcxTreeListDragAndDropColumnObject.CanCustomize: Boolean; begin Result := Column.Options.Customizing and OptionsCustomizing.ColumnCustomizing; end; function TcxTreeListDragAndDropColumnObject.CanDrop: Boolean; var AIndex: Integer; begin Result := DropInfo.Accepted and (DropPosition <> posNone); if not Result or not ChangeColumnOnly then Exit; AIndex := DropInfo.ColIndex - Column.Position.VisibleColIndex; Result := (AIndex < 0) or (AIndex > 1) or not Column.Visible; end; function TcxTreeListDragAndDropColumnObject.CanRemove: Boolean; begin Result := CanCustomize and (Customizing or OptionsCustomizing.ColumnHiding) and not Column.Options.Hidden and (TreeList.VisibleColumnCount > 1); end; procedure TcxTreeListDragAndDropColumnObject.CheckDropColumnIndex( ARow: TcxTreeListBandRow; var AColIndex: Integer); begin if AColIndex < ARow.VisibleItemCount then AColIndex := ARow.VisibleItems[AColIndex].Position.ColIndex else AColIndex := ARow.Count + 1; end; function TcxTreeListDragAndDropColumnObject.ChangeColumnOnly: Boolean; begin Result := not DropInfo.InsertRow and (DestBand = Column.Position.Band) and (DropInfo.RowIndex = Column.Position.RowIndex); end; function TcxTreeListDragAndDropColumnObject.CheckBandDropArea( ABand: TcxTreeListBand): Boolean; var I: Integer; begin DropInfo.Area := cxRectSetTop(ABand.HeaderCell.GetClipRect, ABand.HeaderCell.DisplayRect.Bottom, ViewInfo.HeadersHeight + cxTreeListHeaderMovingZoneSize); Result := PtInRect(DropInfo.Area, DropInfo.DropPos) and ((ABand <> Column.Position.Band) or (ABand.VisibleColumnCount > 1)); if not Result then Exit; DropInfo.Band := ABand; Dec(DropInfo.Area.Bottom, cxTreeListHeaderMovingZoneSize); DropInfo.ColIndex := 0; DropInfo.Position := posBottom; DropInfo.InsertRow := True; DropInfo.RowIndex := ABand.BandRows.Count; if ABand.BandRows.VisibleItemCount = 0 then DropInfo.Position := posTop else if DropInfo.Area.Bottom > DropInfo.DropPos.Y then begin DropInfo.Area.Bottom := DropInfo.Area.Top; for I := 0 to ABand.BandRows.VisibleItemCount - 1 do begin Inc(DropInfo.Area.Bottom, ABand.BandRows.VisibleItems[I].LineCount * ViewInfo.HeaderLineHeight); DropInfo.RowIndex := ABand.BandRows.VisibleItems[I].Index + 1; if DropInfo.Area.Bottom > DropInfo.DropPos.Y then Break; end; end; end; procedure TcxTreeListDragAndDropColumnObject.CheckDragPosition; var I: Integer; const HorzPos: array[Boolean] of TcxPosition = (posRight, posLeft); begin DropInfo.InsertRow := False; if HitTest.HitAtBandContainer or HitTest.HitAtBandHeader then DropInfo.Band := HitTest.HitBand else DropInfo.Band := nil; DropInfo.Position := posNone; DropInfo.Accepted := HitTest.HitAtColumnHeader; if DropInfo.Accepted then InitDropInfoFromColumn(HitTest.HitColumn) else for I := 0 to Bands.BottomItemCount - 1 do begin DropInfo.Accepted := CheckBandDropArea(Bands.BottomItems[I]); if DropInfo.Accepted then Break; end; if DropInfo.Accepted and (DropInfo.Position = posNone) then begin DropInfo.Position := HorzPos[DropInfo.DropPos.X <= cxRectCenter(DropInfo.Area).X]; if (DropInfo.Position = posRight) then Inc(DropInfo.ColIndex); end; DropInfo.Accepted := DropInfo.Position <> posNone; end; function TcxTreeListDragAndDropColumnObject.CreateDropInfo: TcxTreeListDropInfo; begin Result := TcxTreeListColumnDropInfo.Create; end; function TcxTreeListDragAndDropColumnObject.Drop: Boolean; begin Result := True; if ((DestBand = nil) or DropInfo.Customizing) and CanRemove then Column.Visible := False else if DestBand <> nil then begin Column.Position.BandIndex := DestBand.Index; if DropInfo.InsertRow then Column.Position.Row := DestBand.BandRows.Insert(DropInfo.RowIndex) else Column.Position.RowIndex := DropInfo.RowIndex; CheckDropColumnIndex(Column.Position.Row, DropInfo.ColIndex); Column.Position.ColIndex := DropInfo.ColIndex; Column.Visible := True; DestBand.AdjustSubItems; end else Result := False; end; function TcxTreeListDragAndDropColumnObject.GetArrowAreaBounds: TRect; begin Result := DropInfo.Area; end; procedure TcxTreeListDragAndDropColumnObject.InitDropInfoFromColumn( AColumn: TcxTreeListColumn); begin DropInfo.Band := AColumn.Position.Band; DropInfo.ColIndex := AColumn.Position.VisibleColIndex; DropInfo.RowIndex := AColumn.Position.RowIndex; DropInfo.Area := AColumn.HeaderCell.GetClipRect; end; procedure TcxTreeListDragAndDropColumnObject.MakeCustomizingPageVisible; begin if Column.ActuallyVisible then TreeList.Customizing.FHeaderListBox.ItemIndex := -1; TreeList.Customizing.MakeColumnPageVisible; end; function TcxTreeListDragAndDropColumnObject.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListColumnHeaderCellViewInfo(DragHeader).Column; end; function TcxTreeListDragAndDropColumnObject.GetDropInfo: TcxTreeListColumnDropInfo; begin Result := TcxTreeListColumnDropInfo(inherited DropInfo); end; { TcxTreeListDragAndDropObject } constructor TcxTreeListDragAndDropObject.Create(AControl: TcxControl); begin if AControl is TcxTreeListItemsCustomizeListBox then begin inherited Create(TcxTreeListItemsCustomizeListBox(AControl).TreeList) end else inherited Create(AControl); MapWindowPoint(AControl.Handle, TreeList.Handle, FOrigin); OrgOffset := FOrigin; FArrows := TcxPlaceArrows.CreateArrows(TreeList.OptionsView.DropArrowColor, clBtnText); FDropInfo := CreateDropInfo; DragHeader.Pressed := True; end; destructor TcxTreeListDragAndDropObject.Destroy; begin FArrows.Free; FDropInfo.Free; inherited Destroy; end; procedure TcxTreeListDragAndDropObject.BeginDragAndDrop; begin inherited BeginDragAndDrop; InitializeScrollArea(ViewInfo.HScrollArea); if Customizing then MakeCustomizingPageVisible; end; procedure TcxTreeListDragAndDropObject.ChangeArrowsPosition; const Position2Border: array[TcxPosition] of TcxBorder = (bLeft, bLeft, bRight, bTop, bBottom); begin if DrawArrowsNeeded then begin Arrows.MoveTo(cxRectOffset(GetArrowAreaBounds, TreeList.ClientToScreen(Point(0, 0))), Position2Border[DropPosition]); Arrows.Visible := True; end else Arrows.Visible := False; end; function TcxTreeListDragAndDropObject.CheckInCustomizing( const APoint: TPoint): Boolean; begin Result := TreeList.Customizing.PtInCustomizingBox( TreeList.ClientToScreen(APoint)); end; function TcxTreeListDragAndDropObject.CreateDropInfo: TcxTreeListDropInfo; begin Result := TcxTreeListDropInfo.Create; end; procedure TcxTreeListDragAndDropObject.DragAndDrop( const P: TPoint; var Accepted: Boolean); var APos: TPoint; begin APos := cxPointOffset(P, FOrigin); TreeList.Controller.ClickedObject := nil; InitDropInfo(APos); ChangeArrowsPosition; Accepted := DropInfo.Customizing or (DropInfo.Band <> nil) or (Bands.VisibleItemCount = 0); inherited DragAndDrop(APos, Accepted); end; procedure TcxTreeListDragAndDropObject.EndDragAndDrop(Accepted: Boolean); begin DragHeader.Pressed := False; try DropInfo.Accepted := Accepted and (DropInfo.Accepted or DropInfo.Customizing or CanRemove) and not TreeList.Controller.DragCancel; inherited EndDragAndDrop(DropInfo.Accepted); if DropInfo.Accepted then begin TreeList.BeginUpdate; if not Drop then TreeList.CancelUpdate else begin TreeList.EndUpdate; TreeList.Modified; end; end; finally Dirty := False; TreeList.Controller.DragItem := nil; end; end; function TcxTreeListDragAndDropObject.GetArrowAreaBounds: TRect; begin Result := cxNullRect; if not CanDrop then Exit; if Bands.VisibleItemCount = 0 then Result := cxRectSetHeight(ViewInfo.Bounds, ViewInfo.FBandHeaderLineHeight) else begin Result := DestBand.HeaderCell.GetClipRect; case DropPosition of posRight: Result.Left := Result.Right; posBottom: Result.Top := Result.Bottom; end; end; end; function TcxTreeListDragAndDropObject.GetDisplayRect: TRect; begin Result := cxRectOffset(DragHeader.BoundsRect, FOrigin); end; function TcxTreeListDragAndDropObject.GetDragAndDropCursor( Accepted: Boolean): TCursor; begin if Accepted then Result := crArrow else if CanRemove then Result := crcxRemove else Result := crcxNoDrop; end; procedure TcxTreeListDragAndDropObject.InitDropInfo(const P: TPoint); begin HitTest.HitPoint := P; DropInfo.DropPos := P; DropInfo.Customizing := CanCustomize and CheckInCustomizing(P); CheckDragPosition; DropInfo.Accepted := CanDrop; end; procedure TcxTreeListDragAndDropObject.InitializeScrollArea(const Area: TRect); begin if cxRectIsNull(Area) then Exit; AddAutoScrollingObject(cxRectSetLeft(Area, Area.Left, cxtlScrollDelta), sbHorizontal, scLineUp); AddAutoScrollingObject(cxRectSetRight(Area, Area.Right, cxtlScrollDelta), sbHorizontal, scLineDown); end; procedure TcxTreeListDragAndDropObject.Paint; var ADone: Boolean; APrevState: TcxButtonState; ABorders: TcxBorders; ANeighbors: TcxNeighbors; AMargins: TRect; begin APrevState := DragHeader.State; ABorders := DragHeader.Borders; try DragHeader.FState := cxbsDefault; DragHeader.FBorders := cxBordersAll; AMargins := DragHeader.BordersMargins; DragHeader.BordersMargins := cxNullRect; ANeighbors := DragHeader.FNeighbors; DragHeader.FNeighbors := []; Canvas.WindowOrg := DragHeader.DisplayRect.TopLeft; Painter.CustomDrawCell(Canvas, DragHeader, ADone); if not ADone then DragHeader.Draw(Canvas); finally DragHeader.BordersMargins := AMargins; DragHeader.FNeighbors := ANeighbors; DragHeader.FBorders := ABorders; DragHeader.FState := APrevState; end; end; function TcxTreeListDragAndDropObject.DrawArrowsNeeded: Boolean; begin Result := CanDrop and not DropInfo.Customizing; end; function TcxTreeListDragAndDropObject.GetBands: TcxTreeListBands; begin Result := TreeList.Bands; end; function TcxTreeListDragAndDropObject.GetCustomizing: Boolean; begin Result := TreeList.Customizing.Visible; end; function TcxTreeListDragAndDropObject.GetDestBand: TcxTreeListBand; begin Result := DropInfo.Band; end; function TcxTreeListDragAndDropObject.GetDragHeader: TcxTreeListHeaderCellViewInfo; begin Result := TreeList.Controller.DragItem as TcxTreeListHeaderCellViewInfo; end; function TcxTreeListDragAndDropObject.GetDropPosition: TcxPosition; begin Result := DropInfo.Position; end; function TcxTreeListDragAndDropObject.GetHitTest: TcxTreeListHitTest; begin Result := TreeList.HitTest; end; function TcxTreeListDragAndDropObject.GetOptionsCustomize: TcxTreeListOptionsCustomizing; begin Result := TreeList.OptionsCustomizing; end; function TcxTreeListDragAndDropObject.GetPainter: TcxTreeListPainter; begin Result := TcxTreeListPainter(TreeList.Painter); end; function TcxTreeListDragAndDropObject.GetTreeList: TcxCustomTreeList; begin Result := Control as TcxCustomTreeList; end; function TcxTreeListDragAndDropObject.GetViewInfo: TcxTreeListViewInfo; begin Result := TreeList.ViewInfo; end; { TcxTreeListPopup } constructor TcxTreeListPopup.Create(AOwnerControl: TWinControl); begin inherited Create(AOwnerControl); Color := clWindow; IsTopMost := True; OwnerParent := TreeList; CreateListBox; end; function TcxTreeListPopup.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(OwnerControl); end; procedure TcxTreeListPopup.SetOwner(AValue: TcxTreeListIndicatorCellViewInfo); begin if FOwner <> AValue then begin if (AValue = nil) and Visible and FOwner.ClosePopupWhenNilOwner then CloseUp; FOwner := AValue; end; end; function TcxTreeListPopup.CalculateOwnerBounds: TRect; begin Result := FOwner.GetOwnerBounds; end; function TcxTreeListPopup.GetClientMinWidth: Integer; begin with Owner.GetOwnerBounds do Result := Right - Left - NCWidth; end; procedure TcxTreeListPopup.InitPopup; begin inherited InitPopup; BorderStyle := TreeList.LookAndFeelPainter.PopupBorderStyle; Font := TreeList.Font; OwnerBounds := CalculateOwnerBounds; end; function TcxTreeListPopup.NeedIgnoreMouseMessageAfterCloseUp(AWnd: THandle; AMsg: Cardinal; AShift: TShiftState; const APos: TPoint): Boolean; begin Result := cxRectPtIn(OwnerBounds, TreeList.ScreenToClient(APos)); end; procedure TcxTreeListPopup.Paint; begin DrawFrame; Canvas.Brush.Color := Color; Canvas.FillRect(ClientBounds); end; procedure TcxTreeListPopup.VisibleChanged; begin inherited; if not Visible and (FOwner <> nil) then FOwner.PopupClosed; end; procedure TcxTreeListPopup.Popup; begin SetCaptureControl(nil); inherited Popup(FindNextControl(nil, True, True, False)); end; { TcxTreeListCustomizationPopup } procedure TcxTreeListCustomizationPopup.CloseUp; begin inherited CloseUp; FCheckListBox.Clear; FCheckListBox.Columns := 0; end; procedure TcxTreeListCustomizationPopup.CorrectBoundsWithDesktopWorkArea( var APosition: TPoint); var ADesktopWorkArea: TRect; ADesktopSpace, AColumnCount: Integer; begin ADesktopWorkArea := GetDesktopWorkArea(OwnerScreenBounds.TopLeft); if APosition.Y < ADesktopWorkArea.Top then ADesktopSpace := APosition.Y + Height - ADesktopWorkArea.Top else if APosition.Y + Height > ADesktopWorkArea.Bottom then ADesktopSpace := ADesktopWorkArea.Bottom - APosition.Y else ADesktopSpace := 0; if ADesktopSpace <> 0 then begin AColumnCount := RoundDiv(CheckListBox.Height, ADesktopSpace - NCHeight); repeat RestoreControlsBounds; CheckListBox.Columns := AColumnCount; AdjustCheckListBoxSize; CalculateSize; APosition := CalculatePosition; Inc(AColumnCount); until (ADesktopWorkArea.Top <= APosition.Y - GetScrollBarSize.cy) and (APosition.Y + Height + GetScrollBarSize.cy <= ADesktopWorkArea.Bottom); if APosition.X + Width > ADesktopWorkArea.Right then begin RestoreControlsBounds; CheckListBox.Columns := (ADesktopWorkArea.Right - APosition.X - NCWidth) div CheckListBoxColumnWidth; AdjustCheckListBoxSize(True); CalculateSize; APosition := CalculatePosition; end; end; end; procedure TcxTreeListCustomizationPopup.AdjustCheckListBoxSize( AFixedHeight: Boolean = False); var ADropDownCount: Integer; function CalculateClientWidth: Integer; begin if FCheckListBox.Columns > 1 then Result := CheckListBoxColumnWidth * FCheckListBox.Columns else begin Result := FCheckListBox.GetBestFitWidth; if (ADropDownCount <> -1) and (FCheckListBox.Items.Count > ADropDownCount) then Inc(Result, GetScrollBarSize.cx); Inc(Result, cxTextOffset); end; end; function CalculateClientHeight: Integer; begin if ADropDownCount = -1 then Result := FCheckListBox.ClientHeight + GetScrollBarSize.cy else Result := FCheckListBox.GetHeight(ADropDownCount); end; begin if AFixedHeight then ADropDownCount := -1 else if FCheckListBox.Columns > 1 then ADropDownCount := RoundDiv(FCheckListBox.Items.Count, FCheckListBox.Columns) else begin ADropDownCount := GetDropDownCount; if (ADropDownCount = 0) or (FCheckListBox.Items.Count < ADropDownCount) then ADropDownCount := FCheckListBox.Items.Count; end; FCheckListBox.ClientWidth := CalculateClientWidth; FCheckListBox.ClientHeight := CalculateClientHeight; end; procedure TcxTreeListCustomizationPopup.CheckClicked(AIndex: Integer; AChecked: Boolean); begin ItemClicked(CheckListBox.Items[AIndex].ItemObject, AChecked); end; procedure TcxTreeListCustomizationPopup.CreateListBox; begin FCheckListBox := TcxCheckListBox.Create(Self); with FCheckListBox do begin EditValueFormat := cvfIndices; with Style do begin LookAndFeel.MasterLookAndFeel := TreeList.LookAndFeel; BorderStyle := cbsNone; HotTrack := False; TransparentBorder := False; end; StyleFocused.BorderStyle := cbsNone; StyleHot.BorderStyle := cbsNone; ParentFont := True; Parent := Self; OnClick := CheckListBoxClick; OnClickCheck := CheckListBoxCheckClick; OnKeyDown := CheckListBoxKeyDown; OnMouseDown := CheckListBoxMouseDown; end; end; function TcxTreeListCustomizationPopup.GetCheckListBoxColumnWidth: Integer; begin Result := CheckListBox.GetBestFitWidth + CustomizationPopupColumnOffset; end; procedure TcxTreeListCustomizationPopup.GetCheckListBoxSelectedItems(AItems: TList); var I: Integer; begin for I := 0 to CheckListBox.Count - 1 do if CheckListBox.Selected[I] then AItems.Add(CheckListBox.Items[I].ItemObject); end; procedure TcxTreeListCustomizationPopup.InitPopup; begin inherited InitPopup; with FCheckListBox do begin Canvas.Font := Font; DragMode := dmManual; InnerCheckListBox.MultiSelect := DragMode = dmAutomatic; end; AddCheckListBoxItems; AdjustCheckListBoxSize; end; procedure TcxTreeListCustomizationPopup.RefreshCheckListBoxItems; begin CheckListBox.Items.BeginUpdate; try CheckListBox.Clear; AddCheckListBoxItems; finally CheckListBox.Items.EndUpdate; end; end; procedure TcxTreeListCustomizationPopup.SetCheckListBoxSelectedItems(AItems: TList); var I, AIndex: Integer; begin for I := 0 to AItems.Count - 1 do begin AIndex := CheckListBox.Items.IndexOfObject(AItems[I]); if AIndex <> -1 then CheckListBox.Selected[AIndex] := True; end; end; procedure TcxTreeListCustomizationPopup.CheckListBoxClick(Sender: TObject); var AItems: TList; begin if not TreeList.IsDesigning then Exit; AItems := TList.Create; try GetCheckListBoxSelectedItems(AItems); TreeList.Controller.SetSelection(AItems); finally AItems.Free; end; end; procedure TcxTreeListCustomizationPopup.CheckListBoxCheckClick(Sender: TObject; AIndex: Integer; APrevState, ANewState: TcxCheckBoxState); begin CheckClicked(AIndex, ANewState = cbsChecked); end; procedure TcxTreeListCustomizationPopup.CheckListBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_ESCAPE then CloseUp; end; procedure TcxTreeListCustomizationPopup.CheckListBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then CheckListBoxClick(Sender); end; { TcxTreeListColumnsCustomizationPopup } procedure TcxTreeListColumnsCustomizationPopup.AddCheckListBoxItems; var I: Integer; AColumn: TcxTreeListColumn; AItem: TcxCheckListBoxItem; begin CheckListBox.Items.BeginUpdate; try for I := 0 to TreeList.ColumnCount - 1 do begin AColumn := TreeList.Columns[I]; if not AColumn.Options.Customizing or AColumn.Options.Hidden then Continue; AItem := CheckListBox.Items.Add; AItem.Checked := AColumn.Visible; AItem.ItemObject := AColumn; AItem.Text := AColumn.Caption.Text; end; finally CheckListBox.Items.EndUpdate; end; end; function TcxTreeListColumnsCustomizationPopup.GetDropDownCount: Integer; begin Result := TreeList.OptionsCustomizing.ColumnsQuickCustomizationMaxDropDownCount; end; procedure TcxTreeListColumnsCustomizationPopup.ItemClicked( AItem: TObject; AChecked: Boolean); begin TcxTreeListColumn(AItem).Visible := AChecked; TreeList.Modified; end; { TcxTreeListBandsCustomizationPopup } procedure TcxTreeListBandsCustomizationPopup.AddCheckListBoxItems; var I: Integer; ABand: TcxTreeListBand; AItem: TcxCheckListBoxItem; begin CheckListBox.Items.BeginUpdate; try CheckListBox.Items.Clear; for I := 0 to TreeList.Bands.Count - 1 do begin ABand := TreeList.Bands[I]; if not ABand.Options.Customizing or ABand.Options.Hidden then Continue; AItem := CheckListBox.Items.Add; AItem.Checked := ABand.Visible; AItem.ItemObject := ABand; AItem.Text := ABand.Caption.Text; end; finally CheckListBox.Items.EndUpdate; end; end; function TcxTreeListBandsCustomizationPopup.GetDropDownCount: Integer; begin Result := TreeList.OptionsCustomizing.BandsQuickCustomizationMaxDropDownCount; end; procedure TcxTreeListBandsCustomizationPopup.ItemClicked(AItem: TObject; AChecked: Boolean); var AItems: TList; begin TcxTreeListBand(AItem).Visible := AChecked; AItems := TList.Create; try GetCheckListBoxSelectedItems(AItems); RefreshCheckListBoxItems; SetCheckListBoxSelectedItems(AItems); finally AItems.Free; end; AdjustCheckListBoxSize; RestoreControlsBounds; CalculateSize; TreeList.Modified; end; { TcxTreeListColumnStyles } constructor TcxTreeListColumnStyles.Create(AOwner: TPersistent); begin inherited Create(AOwner); BitmapInViewParams := True; end; 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; function TcxTreeListColumnStyles.GetContentParams( ANode: TcxTreeListNode): TcxViewParams; begin GetViewParams(ecs_Content, ANode, nil, Result); end; procedure TcxTreeListColumnStyles.GetDefaultViewParams( Index: Integer; AData: TObject; out AParams: TcxViewParams); var ACellPos: TcxTreeListCellPos; begin inherited GetDefaultViewParams(Index, AData, AParams); case Index of ecs_Content: begin if Column.IsPreview then TreeList.Styles.DoGetPreviewParams(TcxTreeListNode(AData), AParams) else if Band <> nil then Band.Styles.DoGetContentParams(TcxTreeListNode(AData), Column, AParams) else TreeList.Styles.DoGetContentParams(TcxTreeListNode(AData), Column, AParams); end; tlcs_Footer: if Band <> nil then begin ACellPos := TcxTreeListCellPos.Create(TcxTreeListNode(AData), Column); try Band.Styles.GetViewParams(tlbs_Footer, ACellPos, nil, AParams); finally ACellPos.Free; end; end; tlcs_Header: TreeList.Styles.DoGetColumnHeaderParams(Column, AParams); end; end; function TcxTreeListColumnStyles.GetBand: TcxTreeListBand; begin Result := Column.Position.Band; end; function TcxTreeListColumnStyles.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListColumn(GetOwner); end; function TcxTreeListColumnStyles.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Control); end; { TcxTreeListColumnPosition } constructor TcxTreeListColumnPosition.Create(AOwner: TPersistent); begin inherited Create(AOwner); FBandIndex := -1; FColIndex := -1; FLineCount := 1; FRowIndex := -1; FVisibleColIndex := -1; end; procedure TcxTreeListColumnPosition.Assign(Source: TPersistent); begin if Source is TcxTreeListColumnPosition then begin Self.FBandIndex := TcxTreeListColumnPosition(Source).BandIndex; Self.FRowIndex := TcxTreeListColumnPosition(Source).RowIndex; Self.FColIndex := TcxTreeListColumnPosition(Source).ColIndex; Self.FLineCount := TcxTreeListColumnPosition(Source).LineCount; end else inherited Assign(Source); end; procedure TcxTreeListColumnPosition.SetPosition( AColIndex, ARowIndex: Integer; IsInsertRow: Boolean = False); begin SetPositionEx(BandIndex, AColIndex, ARowIndex, IsInsertRow); end; procedure TcxTreeListColumnPosition.SetPositionEx( ABandIndex, AColIndex, ARowIndex: Integer; IsInsertRow: Boolean = False); begin TreeList.BeginUpdate; try BandIndex := ABandIndex; ColIndex := AColIndex; if Band <> nil then begin if not IsInsertRow or not cxInRange(ARowIndex, 0, Band.BandRows.Count) then RowIndex := ARowIndex else Row := Band.BandRows.Insert(ARowIndex); end; finally TreeList.EndUpdate; end; end; procedure TcxTreeListColumnPosition.Changed; begin TreeList.StructureChanged; end; function TcxTreeListColumnPosition.IsPositionChanged: Boolean; begin Result := (BandIndex <> FBandIndex) or (ColIndex <> FColIndex) or (RowIndex <> FRowIndex); end; procedure TcxTreeListColumnPosition.Restore; begin BandIndex := FBandIndex; RowIndex := FRowIndex; ColIndex := FColIndex; end; procedure TcxTreeListColumnPosition.Store; begin FBandIndex := BandIndex; FColIndex := ColIndex; FRowIndex := RowIndex; end; function TcxTreeListColumnPosition.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListColumn(GetOwner); end; function TcxTreeListColumnPosition.GetIsUpdating: Boolean; begin Result := Column.IsLoading or Column.IsUpdating or TreeList.IsRestoring or TreeList.IsLoading or TreeList.IsUpdating; end; function TcxTreeListColumnPosition.GetTreeList: TcxCustomTreeList; begin Result := Column.TreeList; end; function TcxTreeListColumnPosition.GetBandIndex: Integer; begin if FBand = nil then Result := -1 else Result := FBand.Index; end; function TcxTreeListColumnPosition.GetColIndex: Integer; begin if Row = nil then Result := -1 else Result := Row.IndexOf(Column); end; function TcxTreeListColumnPosition.GetRowIndex: Integer; begin if Row = nil then Result := -1 else Result := Row.Index; end; function TcxTreeListColumnPosition.GetVisibleBandIndex: Integer; begin if FBand = nil then Result := -1 else Result := FBand.VisibleIndex; end; function TcxTreeListColumnPosition.GetVisibleRowIndex: Integer; begin if Row = nil then Result := -1 else Result := Row.VisibleIndex; end; procedure TcxTreeListColumnPosition.SetBandIndex(AValue: Integer); var ANewBand: TcxTreeListBand; begin if BandIndex = AValue then Exit; if Column.IsReading or Column.IsUpdating then begin FBandIndex := AValue; Exit; end; if (0 <= AValue) and (AValue < TreeList.Bands.Count) then ANewBand := TreeList.Bands[AValue] else ANewBand := nil; if (ANewBand <> nil) and not ANewBand.IsBottom then ANewBand.MoveBandsToRoot; TreeList.BeginUpdate; try if FBand <> nil then FBand.DeleteColumn(Column); FBand := nil; if ANewBand <> nil then ANewBand.AddColumn(Column); Changed; finally TreeList.EndUpdate; end; end; procedure TcxTreeListColumnPosition.SetColIndex(AValue: Integer); begin if IsUpdating then FColIndex := AValue else if (FBand <> nil) and (ColIndex >= 0) and (AValue >= 0) then begin if AValue > ColIndex then Dec(AValue); AValue := Min(Row.Count - 1, AValue); Row.FItems.Move(ColIndex, AValue); Changed; end; end; procedure TcxTreeListColumnPosition.SetLineCount(AValue: Integer); begin if AValue < 1 then AValue := 1; if FLineCount <> AValue then begin FLineCount := AValue; Changed; end; end; procedure TcxTreeListColumnPosition.SetRow(AValue: TcxTreeListBandRow); begin if AValue.Band <> Band then BandIndex := AValue.Band.Index; if FRow = AValue then Exit; if FRow <> nil then begin FRow.FItems.Remove(Column); FRow.CheckEmpty; end; if AValue <> nil then AValue.FItems.Add(Column); FRow := AValue; Changed; end; procedure TcxTreeListColumnPosition.SetRowIndex(AValue: Integer); begin if IsUpdating then FRowIndex := AValue else begin if (FBand = nil) or (RowIndex = AValue) then Exit; if AValue >= 0 then Row := Band.BandRows.CheckRowIndex(AValue); end; end; { TcxTreeListCaption } constructor TcxTreeListCaption.Create(AOwner: TPersistent); begin inherited Create(AOwner); FGlyph := TBitmap.Create; FShowEndEllipsis := True; end; destructor TcxTreeListCaption.Destroy; begin FreeAndNil(FGlyph); inherited Destroy; end; procedure TcxTreeListCaption.Assign(Source: TPersistent); begin if Source is TcxTreeListCaption then begin FAlignHorz := TcxTreeListCaption(Source).FAlignHorz; FAlignVert := TcxTreeListCaption(Source).FAlignVert; FText := TcxTreeListCaption(Source).Text; FGlyphAlignHorz := TcxTreeListCaption(Source).FGlyphAlignHorz; FGlyphAlignVert := TcxTreeListCaption(Source).FGlyphAlignVert; FMultiLine := TcxTreeListCaption(Source).FMultiLine; FShowEndEllipsis := TcxTreeListCaption(Source).FShowEndEllipsis; Glyph := TcxTreeListCaption(Source).Glyph; end else inherited Assign(Source); end; procedure TcxTreeListCaption.Changed; begin if Assigned(FOnChange) then FOnChange(Self); end; function TcxTreeListCaption.GetText: string; begin Result := FText; if (Result = '') and (GetOwner is TcxTreeListColumn) then Result := TcxTreeListColumn(GetOwner).GetDefaultCaption; end; function TcxTreeListCaption.IsTextStored: Boolean; begin Result := FText <> ''; if Result and (GetOwner is TcxTreeListColumn) then Result := FText <> TcxTreeListColumn(GetOwner).GetDefaultCaption; end; procedure TcxTreeListCaption.SetAlignHorz(AValue: TAlignment); begin if AValue <> FAlignHorz then begin FAlignHorz := AValue; Changed; end; end; procedure TcxTreeListCaption.SetAlignVert(AValue: TcxAlignmentVert); begin if AValue <> FAlignVert then begin FAlignVert := AValue; Changed; end; end; procedure TcxTreeListCaption.SetGlyph(AValue: TBitmap); begin if AValue = nil then FGlyph.FreeImage else FGlyph.Assign(AValue); Changed; end; procedure TcxTreeListCaption.SetGlyphAlignHorz(AValue: TAlignment); begin if AValue <> FGlyphAlignHorz then begin FGlyphAlignHorz := AValue; if not FGlyph.Empty then Changed; end; end; procedure TcxTreeListCaption.SetGlyphAlignVert(AValue: TcxAlignmentVert); begin if AValue <> FGlyphAlignVert then begin FGlyphAlignVert := AValue; if not FGlyph.Empty then Changed; end; end; procedure TcxTreeListCaption.SetMultiLine(AValue: Boolean); begin if AValue <> FMultiLine then begin FMultiLine := AValue; Changed; end; end; procedure TcxTreeListCaption.SetShowEndEllipsis(AValue: Boolean); begin if AValue <> FShowEndEllipsis then begin FShowEndEllipsis := AValue; Changed; end; end; procedure TcxTreeListCaption.SetText(const AValue: string); begin if AValue <> FText then begin FText := AValue; Changed; end; end; { TcxTreeListColumnOptions } constructor TcxTreeListColumnOptions.Create(AOwner: TPersistent); begin inherited Create(AOwner); RestoreDefaults; end; procedure TcxTreeListColumnOptions.Assign(Source: TPersistent); begin if Source is TcxTreeListColumnOptions then begin FCellEndEllipsis := TcxTreeListColumnOptions(Source).CellEndEllipsis; FSizing := TcxTreeListColumnOptions(Source).Sizing; FFooter := TcxTreeListColumnOptions(Source).Footer; FHidden := TcxTreeListColumnOptions(Source).Hidden; FGroupFooter := TcxTreeListColumnOptions(Source).FGroupFooter; FVertSizing := TcxTreeListColumnOptions(Source).VertSizing; end; inherited Assign(Source); end; procedure TcxTreeListColumnOptions.RestoreDefaults; begin FCellEndEllipsis := True; FSizing := True; FFooter := True; FHidden := False; FGroupFooter := True; Sorting := True; Customizing := True; Editing := True; TabStop := True; Focusing := True; Moving := True; VertSizing := True; Changed; end; procedure TcxTreeListColumnOptions.Changed; begin Column.Changed; end; function TcxTreeListColumnOptions.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListColumn(EditContainer); end; procedure TcxTreeListColumnOptions.SetCellEndEllipsis(AValue: Boolean); begin if AValue <> FFooter then begin FCellEndEllipsis := AValue; Changed; end; end; procedure TcxTreeListColumnOptions.SetFooter(AValue: Boolean); begin if AValue <> FFooter then begin FFooter := AValue; Changed; end; end; procedure TcxTreeListColumnOptions.SetGroupFooter(AValue: Boolean); begin if AValue <> FGroupFooter then begin FGroupFooter := AValue; Changed; end; end; procedure TcxTreeListColumnOptions.SetSizing(AValue: Boolean); begin if AValue <> FSizing then begin FSizing := AValue; Changed; end; end; procedure TcxTreeListColumnOptions.SetVertSizing(AValue: Boolean); begin if AValue <> FVertSizing then begin FVertSizing := AValue; Changed; end; end; { TcxTreeListSummaryItem } constructor TcxTreeListSummaryItem.Create(Collection: TCollection); begin inherited Create(Collection); FAbsoluteIndex := -1; FAllNodes := True; FVisible := True; end; function TcxTreeListSummaryItem.FormatValue(const AValue: Variant; AIsFooter: Boolean): string; begin Result := inherited FormatValue(AValue, AIsFooter); if Assigned(FOnGetText) then FOnGetText(Self, AValue, Result); end; procedure TcxTreeListSummaryItem.AssignValues(Source: TcxCustomDataSummaryItem); begin inherited AssignValues(Source); if Source is TcxTreeListSummaryItem then begin FCalculatedColumn := Column.TreeList.GetSameColumn( TcxTreeListSummaryItem(Source).CalculatedColumn); AllNodes := TcxTreeListSummaryItem(Source).AllNodes; Visible := TcxTreeListSummaryItem(Source).Visible; OnGetText := TcxTreeListSummaryItem(Source).OnGetText; end; end; function TcxTreeListSummaryItem.GetDataController: TcxCustomDataController; begin Result := nil; end; function TcxTreeListSummaryItem.GetValueFormat(AValueType: TcxSummaryValueType; const AValue: Variant; AIsFooter: Boolean): string; begin Result := inherited GetValueFormat(AValueType, AValue, AIsFooter); if Result = '' then Result := cxDataGetDataSummaryValueDefaultFormat(AValueType, AValue, AIsFooter); end; procedure TcxTreeListSummaryItem.Notification(AComponent: TComponent; Operation: TOperation); begin if (Operation = opRemove) and (AComponent = FCalculatedColumn) then CalculatedColumn := nil; end; function TcxTreeListSummaryItem.GetCalculatedColumn: TcxTreeListColumn; begin if FCalculatedColumn <> nil then Result := FCalculatedColumn else Result := Column; end; function TcxTreeListSummaryItem.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListSummaryItems(Collection).Column; end; function TcxTreeListSummaryItem.IsCalculatedColumnStored: Boolean; begin Result := FCalculatedColumn <> nil; end; procedure TcxTreeListSummaryItem.SetAlignHorz(AValue: TAlignment); begin if AValue <> FAlignHorz then begin FAlignHorz := AValue; Changed(True); end; end; procedure TcxTreeListSummaryItem.SetAlignVert(AValue: TcxAlignmentVert); begin if AValue <> FAlignVert then begin FAlignVert := AValue; Changed(True); end; end; procedure TcxTreeListSummaryItem.SetAllNodes(AValue: Boolean); begin if AValue <> FAllNodes then begin FAllNodes := AValue; Changed(True); end; end; procedure TcxTreeListSummaryItem.SetCalculatedColumn(AValue: TcxTreeListColumn); begin if AValue <> FCalculatedColumn then begin FCalculatedColumn := AValue; Changed(True); end; end; procedure TcxTreeListSummaryItem.SetMultiLine(AValue: Boolean); begin if AValue <> FMultiLine then begin FMultiLine := AValue; Changed(True); end; end; procedure TcxTreeListSummaryItem.SetVisible(AValue: Boolean); begin if AValue <> FVisible then begin FVisible := AValue; Changed(True); end; end; { TcxTreeListColumnSummary } procedure TcxTreeListColumnSummary.Assign(Source: TPersistent); begin if Source is TcxTreeListColumnSummary then begin GroupFooterSummaryItems := TcxTreeListColumnSummary(Source).GroupFooterSummaryItems; FooterSummaryItems := TcxTreeListColumnSummary(Source).FooterSummaryItems; end else inherited Assign(Source); end; procedure TcxTreeListColumnSummary.Changed(ARedrawOnly: Boolean); begin Column.TreeList.StructureChanged; end; constructor TcxTreeListColumnSummary.Create(AOwner: TPersistent); begin inherited Create(AOwner); FFooterSummaryItems := TcxTreelistSummaryItems.Create(Self, TcxTreeListSummaryItem); FGroupFooterSummaryItems := TcxTreelistSummaryItems.Create(Self, TcxTreeListSummaryItem); end; destructor TcxTreeListColumnSummary.Destroy; begin FreeAndNil(FGroupFooterSummaryItems); FreeAndNil(FFooterSummaryItems); inherited Destroy; end; function TcxTreeListColumnSummary.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListColumn(GetOwner); end; function TcxTreeListColumnSummary.GetFooterVisibleCount: Integer; begin Result := FooterSummaryItems.Count; end; function TcxTreeListColumnSummary.GetGroupFooterVisibleCount: Integer; begin Result := GroupFooterSummaryItems.Count; end; procedure TcxTreeListColumnSummary.SetFooterSummaryItems( AValue: TcxTreeListSummaryItems); begin FFooterSummaryItems.Assign(AValue); end; procedure TcxTreeListColumnSummary.SetGroupFooterSummaryItems( AValue: TcxTreeListSummaryItems); begin FGroupFooterSummaryItems.Assign(AValue); end; { TcxTreeListSummaryItems } constructor TcxTreeListSummaryItems.Create(ASummary: TcxTreeListColumnSummary; AItemClass: TcxTreeListSummaryItemClass); begin inherited Create(AItemClass); FSummary := ASummary; end; function TcxTreeListSummaryItems.Add: TcxTreeListSummaryItem; begin BeginUpdate; try Result := TcxTreeListSummaryItem(inherited Add); finally EndUpdate end; end; function TcxTreeListSummaryItems.GetItemByKind(AKind: TcxSummaryKind): TcxTreeListSummaryItem; var I: Integer; begin Result := nil; for I := 0 to Count - 1 do if Items[I].Kind = AKind then begin Result := Items[I]; Break; end; end; function TcxTreeListSummaryItems.GetOwner: TPersistent; begin Result := FSummary; end; procedure TcxTreeListSummaryItems.Update(Item: TCollectionItem); var I: Integer; AItem: TcxTreeListSummaryItem; begin FVisibleCount := 0; for I := 0 to Count - 1 do begin AItem := Items[I]; if AItem.Visible then begin AItem.FVisibleIndexInColumn := FVisibleCount; Inc(FVisibleCount); end else AItem.FVisibleIndexInColumn := -1; end; FSummary.Changed(Item <> nil); end; function TcxTreeListSummaryItems.GetItem( AIndex: Integer): TcxTreeListSummaryItem; begin Result := TcxTreeListSummaryItem(inherited GetItem(AIndex)); end; procedure TcxTreeListSummaryItems.SetItem(AIndex: Integer; AValue: TcxTreeListSummaryItem); begin inherited SetItem(AIndex, AValue); end; function TcxTreeListSummaryItems.GetColumn: TcxTreeListColumn; begin Result := Summary.Column; end; type TcxTreeListDeprecatedColumnSummaryFooter = class(TcxOwnedPersistent) private FAlignHorz: TAlignment; FAlignVert: TcxAlignmentVert; FFormat: string; FKind: TcxSummaryKind; FMultiLine: Boolean; public procedure Assign(Source: TPersistent); override; published property AlignHorz: TAlignment read FAlignHorz write FAlignHorz; property AlignVert: TcxAlignmentVert read FAlignVert write FAlignVert; property Format: string read FFormat write FFormat; property Kind: TcxSummaryKind read FKind write FKind; property MultiLine: Boolean read FMultiLine write FMultiLine; end; { TcxTreeListDeprecatedColumnSummaryFooter } procedure TcxTreeListDeprecatedColumnSummaryFooter.Assign( Source: TPersistent); var ASourceSummaryFooter: TcxTreeListDeprecatedColumnSummaryFooter; begin if Source is TcxTreeListDeprecatedColumnSummaryFooter then begin ASourceSummaryFooter := TcxTreeListDeprecatedColumnSummaryFooter(Source); AlignHorz := ASourceSummaryFooter.AlignHorz; AlignVert := ASourceSummaryFooter.AlignVert; Format := ASourceSummaryFooter.Format; Kind := ASourceSummaryFooter.Kind; MultiLine := ASourceSummaryFooter.MultiLine; end else inherited Assign(Source); end; { TcxTreeListColumn } constructor TcxTreeListColumn.Create(AOwner: TComponent); begin inherited Create(AOwner); FSortIndex := -1; FSummaryFooter := TcxTreeListDeprecatedColumnSummaryFooter.Create(Self); FSummary := GetSummaryClass.Create(Self); FCaption := TcxTreeListCaption.Create(Self); FCaption.OnChange := ChangeCaption; FPosition := GetPositionClass.Create(Self); FMinWidth := cxTreeListDefMinWidth; FVisible := True; end; destructor TcxTreeListColumn.Destroy; begin SortOrder := soNone; Position.BandIndex := -1; if TreeList <> nil then TreeList.HideEdit; if (TreeList <> nil) and not TreeList.IsDestroying then begin TreeList.AddChanges([tcColumns]); TreeList.UpdateDesignerForms; TreeList.ViewInfo.SetDirty; if TreeList <> nil then TreeList.ColumnsList.Remove(Self); if Controller.FocusedItem = Self then Controller.FocusedItem := nil; if TreeList.Preview.Column = Self then TreeList.Preview.Column := nil; if TreeList.OptionsView.CategorizedColumn = Self then TreeList.OptionsView.CategorizedColumn := nil; end; FreeAndNil(FCaption); FreeAndNil(FPosition); FreeAndNil(FSummary); 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; Summary := AColumn.Summary; Visible := AColumn.Visible; end; finally TreeList.EndUpdate; end; end; procedure TcxTreeListColumn.ApplyBestFit; var ANode: TcxTreeListNode; AWidth, ACount: Integer; begin if (TreeList = nil) or TreeList.IsLoading or TreeList.IsDestroying then Exit; TreeList.ValidateStates; ANode := TreeList.GetStartNodeForBestFit; if ANode = nil then Exit; AWidth := MinWidth + IndentWidth; ACount := TreeList.GetCountNodeForBestFit; try TreeList.HideEdit; while (ACount <> 0) and (ANode <> nil) do begin AWidth := Max(AWidth, TcxFakeCellViewInfo( TreeList.ViewInfo.FakeCell).MeasureWidth(Self, ANode)); ANode := ANode.GetNextVisible; Dec(ACount); end; SetSizeDelta(dsdHorz, Max(AWidth, GetHeaderFooterBestfitSize) - DisplayWidth); finally TreeList.Controller.CheckEdit; end; end; function TcxTreeListColumn.GetDisplayText(ANode: TcxTreeListNode): string; begin Result := VarToStr(DoOnGetDisplayText(ANode, True)); end; function TcxTreeListColumn.GetParentComponent: TComponent; begin Result := EditingControl; end; function TcxTreeListColumn.HasParent: Boolean; begin Result := True; end; procedure TcxTreeListColumn.MakeVisible; var CellR, R: TRect; begin if not ActuallyVisible or (Position.Band.FixedKind <> tlbfNone) or (HeaderCell = nil) or not HeaderCell.HasClipping then Exit; R := TreeList.ViewInfo.HScrollArea; CellR := HeaderCell.DisplayRect; if FocusedCellViewInfo <> nil then begin if (cxRectWidth(FocusedCellViewInfo.VisibleRect) < MinWidth) then CellR := FocusedCellViewInfo.BoundsRect else if (CellR.Left <= R.Left) and (CellR.Right >= R.Right) and (FocusedCellViewInfo.BoundsRect.Left > R.Left) then Exit; end; if (CellR.Right > R.Right) and (CellR.Left > R.Left) then TreeList.ViewInfo.HScrollPos := TreeList.ViewInfo.HScrollPos + (CellR.Right - R.Right) else if CellR.Left < R.Left then TreeList.ViewInfo.HScrollPos := TreeList.ViewInfo.HScrollPos - (R.Left - CellR.Left); TreeList.UpdateScrollBars; 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.AssignWidth; begin if FWidth = 0 then FWidth := DisplayWidth; end; function TcxTreeListColumn.CanMoving: Boolean; begin Result := TreeList.OptionsCustomizing.ColumnMoving and Options.Moving; end; function TcxTreeListColumn.CanSort: Boolean; begin Result := not Assigned(OnGetEditProperties) and (esoSorting in PropertiesValue.GetSupportedOperations); if not Result then Result := Assigned(TreeList.FOnCompare); end; procedure TcxTreeListColumn.ChangeCaption(Sender: TObject); begin Changed; end; procedure TcxTreeListColumn.Changed; begin inherited Changed; if TreeList <> nil then TreeList.Summary.Recalculate; end; procedure TcxTreeListColumn.ForceWidth(AWidth: Integer); begin TreeList.ValidateStates; AWidth := Max(AWidth, MinWidth); if Width = AWidth then Exit; TreeList.Controller.ForcingWidthColumn := Self; TreeList.Bands.AssignColumnsWidth; Width := AWidth; TreeList.Bands.Adjust(); TreeList.Bands.AssignColumnsWidth; TreeList.Controller.ForcingWidthColumn := nil; end; function TcxTreeListColumn.CanEdit: Boolean; begin Result := Assigned(ValueDef) and CanFocus and Options.Editing and TreeList.Options.OptionsData.Editing and (TreeList.FocusedNode <> nil) and not TreeList.FocusedNode.IsHidden; end; function TcxTreeListColumn.GetEditValue: Variant; begin if Editing then begin if TreeList.FocusedNode = nil then Result := Null else Result := DataController.GetNodeValue(TreeList.FocusedNode, ItemIndex); end else Result := Unassigned; end; function TcxTreeListColumn.CanInitEditing: Boolean; begin Result := CanEdit; if Result then begin if TreeList.DataController.EditingNode <> TreeList.FocusedNode then TreeList.Post; TreeList.DataController.Edit; end; end; procedure TcxTreeListColumn.CancelSorting; begin FSortOrder := soNone; FSortIndex := -1; TreeList.FSortedColumns.Remove(Self); TreeList.AddChanges([tcSortOrder]); end; function TcxTreeListColumn.CanFocus: Boolean; begin Result := inherited CanFocus and TreeList.OptionsSelection.CellSelect and (Self <> TreeList.Preview.Column); end; function TcxTreeListColumn.GetRealSortOrder: TcxDataSortOrder; begin Result := soNone; if CanSort then Result := FSortOrder; end; function TcxTreeListColumn.GetHeaderFooterBestfitSize: Integer; begin Result := 0; if TreeList.OptionsView.Headers then begin Result := cxTextWidth(TreeList.Styles.GetColumnHeaderParams( Self).Font, Caption.Text) + cxTextOffset * 3; if not Caption.Glyph.Empty and (Byte(Caption.GlyphAlignHorz) < 2) then Inc(Result, Caption.Glyph.Width + cxTextOffset); if SortOrder <> soNone then Inc(Result, TreeList.LookAndFeelPainter.SortingMarkAreaSize.X); end; if Options.Footer and TreeList.OptionsView.Footer and (Summary.FooterVisibleCount > 0) then begin //todo: v5 end; end; function TcxTreeListColumn.GetOptionsClass: TcxCustomEditContainerItemOptionsClass; begin Result := TcxTreeListColumnOptions; end; function TcxTreeListColumn.GetStylesClass: TcxEditContainerStylesClass; begin Result := TcxTreeListColumnStyles; end; function TcxTreeListColumn.GetSummaryClass: TcxTreeListColumnSummaryClass; begin Result := TcxTreeListColumnSummary; end; procedure TcxTreeListColumn.SetEditingControl(Value: TcxEditingControl); begin if TreeList <> nil then begin TreeList.ContainerList.Remove(Self); TreeList.AddChanges([tcColumns]); end; inherited SetEditingControl(Value); if TreeList <> nil then begin TreeList.AddChanges([tcColumns]); TreeList.UpdateDesignerForms; end; 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; function TcxTreeListColumn.CanSizing(ADirection: TcxDragSizingDirection): Boolean; begin if ADirection = dsdVert then Result := Options.VertSizing and TreeList.OptionsCustomizing.ColumnVertSizing else Result := Options.Sizing and TreeList.OptionsCustomizing.ColumnHorzSizing; end; function TcxTreeListColumn.GetAvailableMaxWidth: Integer; var I: Integer; begin if Position.Band.Width = 0 then Result := High(SmallInt) else begin if Position.Band.Width = 0 then Result := Position.Band.Width - Position.Row.MinWidth else begin Result := Position.Band.CalculatedWidth; for I := 0 to Position.Row.VisibleItemCount - 1 do begin if I = Position.VisibleColIndex then Continue; if (I < Position.VisibleColIndex) and (Position.VisibleColIndex <> Position.Row.VisibleItemCount - 1) then Dec(Result, Position.Row.VisibleItems[I].DisplayWidth) else Dec(Result, Position.Row.VisibleItems[I].MinWidth); end; end; end; end; function TcxTreeListColumn.GetRealMinSize: Integer; begin if Options.Sizing then Result := FMinWidth + IndentWidth else Result := FWidth; end; function TcxTreeListColumn.GetSizingBoundsRect( ADirection: TcxDragSizingDirection): TRect; begin if ADirection = dsdVert then Result := cxRectSetTop(TreeList.ClientRect, HeaderCell.DisplayRect.Top + TreeList.ViewInfo.HeaderLineHeight) else begin Result := cxRectSetLeft(TreeList.ClientRect, HeaderCell.DisplayRect.Left + GetRealMinSize, GetAvailableMaxWidth - GetRealMinSize); 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; begin Result := TreeList.OptionsCustomizing.DynamicSizing and TreeList.HitTest.HitAtSizingHorz; end; procedure TcxTreeListColumn.SetSizeDelta( ADirection: TcxDragSizingDirection; ADelta: Integer); begin if ADelta = 0 then Exit; TreeList.BeginUpdate; try if ADirection = dsdVert then Position.LineCount := Position.LineCount + ADelta else ForceWidth(DisplayWidth + ADelta); finally TreeList.EndUpdate; end; TreeList.LayoutChanged; TreeList.Modified; 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 := Low(ColumnPropertiesName) to High(ColumnPropertiesName) do AProperties.Add(ColumnPropertiesName[I]); if Assigned(OnGetStoredProperties) then OnGetStoredProperties(Self, AProperties); Result := True; end; function TcxTreeListColumn.GetPropertyIndex(const AName: string): Integer; var I: Integer; begin Result := -1; for I := Low(ColumnPropertiesName) 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.LineCount; 3: AValue := Position.ColIndex; 4: AValue := Position.RowIndex; 5: AValue := Position.BandIndex; 6: AValue := Caption.Text; 7: AValue := SortOrder; 9: AValue := FMinWidth; 10: AValue := FWidth; else if Assigned(OnGetStoredPropertyValue) then OnGetStoredPropertyValue(Self, AName, AValue); end; end; procedure TcxTreeListColumn.SetPropertyValue( const AName: string; const AValue: Variant); begin case GetPropertyIndex(AName) of 0: Visible := AValue; 1: ItemIndex := AValue; 2: Position.LineCount := AValue; 3: Position.ColIndex := AValue; 4: Position.RowIndex := AValue; 5: Position.BandIndex := AValue; 6: if Caption.Text = '' then Caption.Text := AValue; 7: FSortOrder := AValue; 9: FMinWidth := AValue; 10: FWidth := AValue; else if Assigned(OnSetStoredPropertyValue) then OnSetStoredPropertyValue(Self, AName, AValue); end; end; procedure TcxTreeListColumn.ChangeSortOrder( ASortOrder: TcxDataSortOrder; AShift: TShiftState); begin if not Options.Sorting or not CanSort then ASortOrder := FSortOrder; if ASortOrder <> FSortOrder then begin FSortOrder := ASortOrder; TreeList.ColumnSortOrderChanged(Self, AShift); TreeList.Modified; end; end; procedure TcxTreeListColumn.ConvertOldFooterSummaries; var ASummaryFooter: TcxTreeListDeprecatedColumnSummaryFooter; begin ASummaryFooter := TcxTreeListDeprecatedColumnSummaryFooter(SummaryFooter); if ASummaryFooter.Kind <> skNone then with FSummary.FooterSummaryItems.Add do begin AlignHorz := ASummaryFooter.AlignHorz; AlignVert := ASummaryFooter.AlignVert; MultiLine := ASummaryFooter.MultiLine; Format := ASummaryFooter.Format; Kind := ASummaryFooter.Kind; end; end; procedure TcxTreeListColumn.DoGetDisplayText( ARecordIndex: Integer; var AText: string); begin if ARecordIndex <> 0 then AText := DoGetNodeDisplayText(TcxTreeListNode(ARecordIndex), AText); 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); if AProperties.GetEditValueSource(False) = evsValue then Result := DataController.GetNodeValue(ANode, ItemIndex) else Result := DataController.GetNodeDisplayText(ANode, ItemIndex); if AValueOnly then Exit; if Assigned(OnGetDisplayText) or AsText then begin if AProperties.GetEditValueSource(False) = evsValue then begin if AsText then AText := AProperties.GetDisplayText(ANode.Values[ItemIndex], True) else AText := ''; AText := DoGetNodeDisplayText(ANode, AText); if (AText = '') and not AsText then Result := ANode.Values[ItemIndex] else Result := AText; end else Result := DoGetNodeDisplayText(ANode, Result); 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.HasDataTextHandler: Boolean; begin Result := Assigned(FOnGetDisplayText); end; procedure TcxTreeListColumn.InitAutoWidthItem(AItem: TcxAutoWidthItem); begin AItem.Width := Width; AItem.Fixed := IsFixed; AItem.MinWidth := FMinWidth + IndentWidth; if AItem.Fixed then begin AItem.Width := Max(AItem.Width, AItem.MinWidth); AItem.MinWidth := AItem.Width end; AItem.AutoWidth := -1; end; procedure TcxTreeListColumn.SetCurrentValue(const Value: Variant); begin if TreeList.FocusedNode <> nil then TreeList.FocusedNode.Values[ItemIndex] := Value; end; function TcxTreeListColumn.GetEditingProperties: TcxTreeListGetEditPropertiesEvent; begin Result := TcxTreeListGetEditPropertiesEvent(inherited OnGetEditingProperties); end; function TcxTreeListColumn.GetEditProperties: TcxTreeListGetEditPropertiesEvent; begin Result := TcxTreeListGetEditPropertiesEvent(inherited OnGetEditProperties); end; function TcxTreeListColumn.GetHasIndent: Boolean; begin Result := (Position.Band <> nil) and (Position.VisibleColIndex = 0) and Position.Band.ActuallyExpandable; end; function TcxTreeListColumn.GetID: Integer; begin Result := -1; if TreeList <> nil then Result := TreeList.ContainerList.IndexOf(Self); end; function TcxTreeListColumn.GetIndentWidth: Integer; begin Result := 0; if HasIndent then Result := Position.Band.IndentWidth; end; function TcxTreeListColumn.GetActuallyVisible: Boolean; begin Result := Visible and (Position.Band <> nil) and Position.Band.ActuallyVisible; end; function TcxTreeListColumn.GetDataController: TcxTreeListDataController; begin Result := TcxTreeListDataController(inherited DataController); end; function TcxTreeListColumn.GetDataBinding: TcxItemDataBinding; begin Result := TcxItemDataBinding(inherited DataBinding); end; function TcxTreeListColumn.GetDisplayWidth: Integer; begin TreeList.ValidateStates; if not ActuallyVisible then Result := 0 else begin Result := FCalculatedWidth; if Result = 0 then Result := Width; end; end; function TcxTreeListColumn.GetIsFixed: Boolean; var AForcingColumn: TcxTreeListColumn; APos: TcxTreeListColumnPosition; begin AForcingColumn := TreeList.Controller.ForcingWidthColumn; Result := (TreeList.Controller.ForcingWidthColumn = Self) or not Options.Sizing; if not Result and (AForcingColumn <> nil) then begin APos := AForcingColumn.Position; Result := (APos = Position) or not AForcingColumn.IsRight and (Position.Row = APos.Row) and (Position.VisibleColIndex < APos.VisibleColIndex); end; end; function TcxTreeListColumn.GetIsHidden: Boolean; begin Result := not ActuallyVisible or IsPreview; end; function TcxTreeListColumn.GetIsLeft: Boolean; begin Result := ActuallyVisible and (Position.VisibleColIndex = 0); end; function TcxTreeListColumn.GetIsPreview: Boolean; begin Result := (TreeList <> nil) and (TreeList.Preview.Column = Self); end; function TcxTreeListColumn.GetIsRight: Boolean; begin with Position do Result := ActuallyVisible and (VisibleColIndex = Row.VisibleItemCount - 1); end; function TcxTreeListColumn.GetIsLoading: Boolean; begin Result := (csLoading in ComponentState) and ((TreeList = nil) or not TreeList.IgnoreLoadingStatus); end; function TcxTreeListColumn.GetIsReading: Boolean; begin Result := csReading in ComponentState; end; function TcxTreeListColumn.GetIsUpdating: Boolean; begin Result := csUpdating in ComponentState; end; function TcxTreeListColumn.GetIsWidthStored: Boolean; begin Result := FWidth <> 0; end; function TcxTreeListColumn.GetSortIndex: Integer; begin Result := FSortIndex; if SortOrder = soNone then Result := -1; end; function TcxTreeListColumn.GetStyles: TcxTreeListColumnStyles; begin Result := TcxTreeListColumnStyles(inherited Styles); end; function TcxTreeListColumn.GetItemIndex: Integer; begin Result := TreeList.ColumnsList.IndexOf(Self); end; function TcxTreeListColumn.GetOptions: TcxTreeListColumnOptions; begin Result := TcxTreeListColumnOptions(inherited Options); end; function TcxTreeListColumn.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(EditingControl); end; function TcxTreeListColumn.GetValueByNode(ANode: TcxTreeListNode): Variant; begin Result := ANode.Values[ItemIndex]; end; function TcxTreeListColumn.GetValueDef: TcxValueDef; begin Result := TcxCustomDataHelper.GetValueDef( DataController.Fields[inherited ItemIndex]); end; function TcxTreeListColumn.GetVisibleIndex: Integer; begin Result := TreeList.FVisibleColumns.IndexOf(Self) end; function TcxTreeListColumn.GetWidth: Integer; begin Result := FWidth; if Result = 0 then Result := cxTreeListDefWidth; Result := Max(MinWidth, Result); end; procedure TcxTreeListColumn.SetCaption(AValue: TcxTreeListCaption); begin FCaption.Assign(AValue); end; procedure TcxTreeListColumn.SetDataBinding(AValue: TcxItemDataBinding); begin DataBinding.Assign(AValue); end; procedure TcxTreeListColumn.SetDisplayWidth(AValue: Integer); begin ForceWidth(AValue); end; procedure TcxTreeListColumn.SetEditingProperties( AValue: TcxTreeListGetEditPropertiesEvent); begin inherited OnGetEditingProperties := TcxGetEditPropertiesEvent(AValue); end; procedure TcxTreeListColumn.SetEditProperties( AValue: TcxTreeListGetEditPropertiesEvent); begin inherited OnGetEditProperties := TcxGetEditPropertiesEvent(AValue); end; procedure TcxTreeListColumn.SetIsPreview(AValue: Boolean); begin if Value <> IsPreview then begin if Value then TreeList.Preview.Column := Self else TreeList.Preview.Column := nil; end; end; procedure TcxTreeListColumn.SetItemIndex(AValue: Integer); function IsIndexValid(AIndex: Integer): Boolean; begin Result := (AIndex >= 0) and (AIndex < TreeList.ContainerList.Count) end; begin TreeList.BeginUpdate; try Inc(AValue, TreeList.ContainerList.Count - TreeList.ColumnsList.Count); if IsIndexValid(ItemIndex) and IsIndexValid(AValue) then TreeList.ContainerList.Exchange(ItemIndex, AValue); TreeList.DataController.UpdateItemIndexes; finally TreeList.EndUpdate; end; end; procedure TcxTreeListColumn.SetMinWidth(AValue: Integer); begin if AValue < 0 then AValue := 0; if AValue <> FMinWidth then begin FMinWidth := AValue; SetWidth(FMinWidth); end; end; procedure TcxTreeListColumn.SetOptions(AValue: TcxTreeListColumnOptions); begin Options.Assign(AValue); end; procedure TcxTreeListColumn.SetPosition(AValue: TcxTreeListColumnPosition); begin FPosition.Assign(AValue); end; procedure TcxTreeListColumn.SetSortIndex(AValue: Integer); var I: Integer; begin if SortOrder = soNone then AValue := -1; if AValue <> FSortIndex then begin FSortIndex := AValue; if IsLoading then Exit; if AValue >= 0 then begin for I := AValue to TreeList.SortedColumnCount - 1 do if TreeList.SortedColumns[I].FSortIndex > 0 then Inc(TreeList.SortedColumns[I].FSortIndex); end; TreeList.DataLayoutChanged; end; end; procedure TcxTreeListColumn.SetSortOrder(AValue: TcxDataSortOrder); begin ChangeSortOrder(AValue, []); end; procedure TcxTreeListColumn.SetStyles(AValue: TcxTreeListColumnStyles); begin Styles.Assign(AValue); end; procedure TcxTreeListColumn.SetSummary(AValue: TcxTreeListColumnSummary); begin FSummary.Assign(AValue); end; procedure TcxTreeListColumn.SetSummaryFooter(AValue: TPersistent); begin FSummaryFooter.Assign(AValue); end; procedure TcxTreeListColumn.SetValueByNode( ANode: TcxTreeListNode; const AValue: Variant); begin ANode.Values[ItemIndex] := AValue; end; procedure TcxTreeListColumn.SetVisible(AValue: Boolean); begin if AValue <> FVisible then begin FVisible := AValue; TreeList.ClearCalculatedWidths; Changed; end; end; procedure TcxTreeListColumn.SetWidth(AValue: Integer); begin AValue := Max(MinWidth + IndentWidth, AValue); if AValue < 0 then Exit; if AValue <> FWidth then begin FWidth := AValue; FCalculatedWidth := AValue; if (Position.Band <> nil) and not IsLoading and not IsUpdating then Position.Band.ColumnSizeChanged(Self); Changed; end; end; { TcxFakeCellViewInfo } constructor TcxFakeCellViewInfo.Create(AOwner: TObject); begin inherited Create(AOwner); FNodeViewData := TcxTreeListNodeViewData.Create(AOwner as TcxTreeListViewInfo, nil, 0); end; destructor TcxFakeCellViewInfo.Destroy; begin FNodeViewData.Node := nil; FNodeViewData.Free; FColumn := nil; inherited Destroy; end; function TcxFakeCellViewInfo.MeasureHeight(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; AIsCategory: Boolean): Integer; var W: Integer; begin FColumn := AColumn; W := Column.DisplayWidth - OptionsView.VertIncrement; if AIsCategory then W := TreeListViewInfo.ContentWidth; if AColumn.IndentWidth > 0 then W := W - TreeListViewInfo.GetNodeContentOffset(ANode); Initialize(ANode, W, TreeListViewInfo.DefaultEditHeight, True); Result := Max(TreeListViewInfo.DefaultEditHeight, Column.GetEditHeight(Self) + OptionsView.HorzIncrement * 2); end; function TcxFakeCellViewInfo.MeasureWidth( AColumn: TcxTreeListColumn; ANode: TcxTreeListNode): Integer; var AIndent: Integer; begin FColumn := AColumn; Initialize(ANode, 0, TreeListViewInfo.DefaultEditHeight, False); AIndent := 0; if Column.IndentWidth > 0 then AIndent := TreeListViewInfo.GetNodeContentOffset(ANode); Result := Max(Column.MinWidth + Column.IndentWidth, AIndent + Column.GetEditWidth(Self) + OptionsView.HorzIncrement * 2); end; function TcxFakeCellViewInfo.GetButtonTransparency: TcxEditButtonTransparency; begin Result := ebtNone; end; function TcxFakeCellViewInfo.GetControl: TcxEditingControl; begin Result := TreeListViewInfo.TreeList; end; function TcxFakeCellViewInfo.GetEditContainer: TcxCustomInplaceEditContainer; begin Result := FColumn; end; function TcxFakeCellViewInfo.GetFocused: Boolean; begin Result := False; end; function TcxFakeCellViewInfo.GetSelected: Boolean; begin Result := False; end; procedure TcxFakeCellViewInfo.Initialize(ANode: TcxTreeListNode; AHeight, AWidth: Integer; ACalcHeight: Boolean); begin FCalcHeight := ACalcHeight; FNodeViewData.Node := ANode; CellContentRect := cxRect(0, 0, AHeight, AWidth); Column.InitEditViewInfo(Self); end; function TcxFakeCellViewInfo.IsAutoHeight: Boolean; begin Result := FCalcHeight; end; function TcxFakeCellViewInfo.IsEndEllipsis: Boolean; begin Result := False; end; function TcxFakeCellViewInfo.GetTreeListViewInfo: TcxTreeListViewInfo; begin Result := FNodeViewData.ViewInfo; end; { TcxTreeListCellPos } constructor TcxTreeListCellPos.Create( ANode: TcxTreeListNode; AItem: TObject); begin Item := AItem; Node := ANode; end; { TcxTreeListPainter } constructor TcxTreeListPainter.Create( AOwner: TcxEditingControl); begin inherited Create(AOwner); Buffered := True; end; procedure TcxTreeListPainter.Paint; var ACanvas: TcxCanvas; begin if Buffered then begin if Changed then begin ACanvas := FCanvas; try BitmapCanvas.SetClipRegion(FCanvas.GetClipRegion, roSet); FCanvas := BitmapCanvas; DoPaint; finally FCanvas := ACanvas; end; end; Canvas.Draw(0, 0, Bitmap); end else DoPaint; CheckDirty; end; procedure TcxTreeListPainter.CheckSize(const AWidth, AHeight: Integer); begin CheckBuffer((AWidth div cxTreeListResizeInc + 1) * cxTreeListResizeInc, (AHeight div cxTreeListResizeInc + 1) * cxTreeListResizeInc); end; procedure TcxTreeListPainter.DoPaint; var I: Integer; AClipRgn: TcxRegion; begin if TreeList.IsLocked then inherited DoPaint else begin CheckCustomDrawSupport; Cells.Paint(Canvas, CustomDrawCell); AClipRgn := Canvas.GetClipRegion(); try Canvas.IntersectClipRect(ViewInfo.ContentBounds); for I := 0 to ViewInfo.Count - 1 do ViewInfo.NodeViewData[I].Paint(Canvas, CustomDrawCell); finally Canvas.SetClipRegion(AClipRgn, roSet); end; end end; procedure TcxTreeListPainter.CheckBuffer(AWidth, AHeight: Integer); begin if not Buffered or ((Bitmap.Width >= AWidth) and (Bitmap.Height >= AHeight)) then Exit; Bitmap.FreeImage; Bitmap.Height := AHeight; Bitmap.Width := AWidth; Changed := True; end; procedure TcxTreeListPainter.CheckCustomDrawSupport; begin with TreeList do begin FCustomDrawSupported := Assigned(OnCustomDrawBackgroundCell) or ((OptionsView.Headers or OptionsView.Bands) and Assigned(OnCustomDrawHeaderCell)) or (OptionsView.Footer and Assigned(OnCustomDrawFooterCell)) or (OptionsView.Indicator and Assigned(OnCustomDrawIndicatorCell)) or Assigned(OnCustomDrawBandCell) or Assigned(OnCustomDrawIndentCell) or Assigned(OnCustomDrawDataCell) or Assigned(OnCustomDrawPreviewCell); end; end; procedure TcxTreeListPainter.CheckDirty; begin { if TreeList.DragAndDropObject <> nil then TcxTreeListSizingDragAndDropObject(TreeList.DragAndDropObject).Dirty := False;} end; procedure TcxTreeListPainter.CustomDrawCell( ACanvas: TcxCanvas; ACell: TcxCustomViewInfoItem; var ADone: Boolean); begin ADone := False; if not CustomDrawSupported then Exit; with TreeList do begin case ACell.CustomDrawID of cxtlBackgroundCell: if Assigned(OnCustomDrawBackgroundCell) then OnCustomDrawBackgroundCell(TreeList, ACanvas, TcxTreeListCustomCellViewInfo(ACell), ADone); cxtlColumnHeaderCell: if Assigned(OnCustomDrawHeaderCell) then OnCustomDrawHeaderCell(TreeList, ACanvas, TcxTreeListHeaderCellViewInfo(ACell), ADone); cxtlBandHeaderCell: if Assigned(OnCustomDrawBandHeaderCell) then OnCustomDrawBandHeaderCell(TreeList, ACanvas, TcxTreeListHeaderCellViewInfo(ACell), ADone); cxtlBandPartCell: if Assigned(OnCustomDrawBandCell) then OnCustomDrawBandCell(TreeList, ACanvas, TcxTreeListBandCellViewInfo(ACell), ADone); cxtlEditCell: if Assigned(OnCustomDrawDataCell) then OnCustomDrawDataCell(TreeList, ACanvas, TcxTreeListEditCellViewInfo(ACell), ADone); cxtlFooterCell: if Assigned(OnCustomDrawFooterCell) then OnCustomDrawFooterCell(TreeList, ACanvas, TcxTreeListFooterCellViewInfo(ACell), ADone); cxtlIndentCell: if Assigned(OnCustomDrawIndentCell) then OnCustomDrawIndentCell(TreeList, ACanvas, TcxTreeListIndentCellViewInfo(ACell), ADone); cxtlIndicatorCell: if Assigned(OnCustomDrawIndicatorCell) then OnCustomDrawIndicatorCell(TreeList, ACanvas, TcxTreeListIndicatorCellViewInfo(ACell), ADone); cxtlPreviewCell: if Assigned(OnCustomDrawPreviewCell) then OnCustomDrawPreviewCell(TreeList, ACanvas, TcxTreeListEditCellViewInfo(ACell), ADone); end; end; end; procedure TcxTreeListPainter.SetBuffered(Value: Boolean); begin inherited SetBuffered(True); end; function TcxTreeListPainter.GetCells: TcxCustomControlCells; begin Result := ViewInfo.Cells; end; function TcxTreeListPainter.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Control); end; function TcxTreeListPainter.GetViewInfo: TcxTreeListViewInfo; begin Result := TcxTreeListViewInfo(inherited ViewInfo); end; { TcxTreeListPreview } constructor TcxTreeListPreview.Create(AOwner: TPersistent); begin inherited Create(AOwner); FAutoHeight := True; FLeftIndent := 5; FMaxLineCount := 3; FRightIndent := 5; 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; begin TreeList.LayoutChanged; end; function TcxTreeListPreview.GetControl: TObject; begin Result := TreeList; end; function TcxTreeListPreview.GetActive: Boolean; begin Result := Visible and (FColumn <> nil) and (TreeList.VisibleColumnCount > 0) and ((MaxLineCount <> 0) or AutoHeight) end; function TcxTreeListPreview.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(GetOwner); end; procedure TcxTreeListPreview.SetAutoHeight(AValue: Boolean); begin if AValue <> FAutoHeight then begin FAutoHeight := AValue; Changed; end; end; procedure TcxTreeListPreview.SetColumn(AValue: TcxTreeListColumn); begin if AValue <> FColumn then begin FColumn := AValue; Changed; end; end; procedure TcxTreeListPreview.SetLeftIndent(AValue: Integer); begin AValue := Max(0, AValue); if AValue <> FLeftIndent then begin FLeftIndent := AValue; Changed; end; end; procedure TcxTreeListPreview.SetMaxLineCount(AValue: Integer); begin AValue := Max(AValue, 0); if AValue <> FMaxLineCount then begin FMaxLineCount := AValue; Changed; end; end; procedure TcxTreeListPreview.SetPlace(AValue: TcxTreeListPreviewPlace); begin if AValue <> FPlace then begin FPlace := AValue; Changed; end; end; procedure TcxTreeListPreview.SetRightIndent(AValue: Integer); begin AValue := Max(AValue, 0); if AValue <> FRightIndent then begin FRightIndent := AValue; Changed; end; end; procedure TcxTreeListPreview.SetVisible(AValue: Boolean); begin if AValue <> FVisible then begin FVisible := AValue; Changed; 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; //Check Row index ACellIndex := Min(TreeList.VisibleColumnCount - 1, Max(ACellIndex, 0)); if not IsGroupRow(ARowIndex) and (ACellIndex >= 0) then begin AColumn := TreeList.VisibleColumns[ACellIndex]; ACellFound := GoToNextCellInBand(AForward, AColumn, ACellIndex); end else AColumn := nil; if not ACellFound then begin ANewRow := ARowIndex + cxIntOffs[AForward]; if cxInRange(ANewRow, 0, TreeList.AbsoluteVisibleCount - 1) then begin ARowIndex := ANewRow; GoToNextNodeCell(AForward, TreeList.AbsoluteVisibleItems[ARowIndex], AColumn, ACellIndex); end else if AForward then AppendRecord(ARowIndex, ACellIndex); end end; procedure TcxTreeListCellNavigator.AppendRecord( var ARowIndex, ACellIndex: Integer); begin if TreeList.IsEditing then DataController.Post; if TreeList.IsInserting then begin TreeList.DataController.PostRecord; if [dceChanging, dceModified] * DataController.EditState <> [] then TreeList.Post else Exit; end; if TcxTreeListController(Controller).CanInsertNode and TreeList.InsertNode(nil, True) then ARowIndex := TreeList.AbsoluteVisibleCount - 1; end; function TcxTreeListCellNavigator.GetCellContainer( ARowIndex, ACellIndex: Integer): TcxCustomInplaceEditContainer; begin if not cxInRange(ACellIndex, 0, GetCount(ARowIndex) - 1) then Result := nil else Result := TreeList.VisibleColumns[ACellIndex]; end; function TcxTreeListCellNavigator.GetNode( ARowIndex: Integer): TcxTreeListNode; begin Result := nil; if (ARowIndex < 0) or (ARowIndex >= TreeList.AbsoluteVisibleCount) then Exit; Result := TreeList.AbsoluteVisibleItems[ARowIndex]; end; procedure TcxTreeListCellNavigator.Init( var ARowIndex, ACellIndex, ARowCount: Integer); var ANode: TcxTreeListNode; begin ARowCount := TreeList.AbsoluteVisibleCount; ANode := TcxTreeListController(Controller).FocusedNode; if ANode <> nil then ARowIndex := ANode.VisibleIndex else ARowIndex := 0; if TreeList.FocusedColumn <> nil then ACellIndex := TreeList.FocusedColumn.VisibleIndex else ACellIndex := 0; end; function TcxTreeListCellNavigator.IsGroupRow(ARowIndex: Integer): Boolean; begin Result := (GetNode(ARowIndex) <> nil) and GetNode(ARowIndex).IsGroupNode; end; procedure TcxTreeListCellNavigator.SaveCurrentNavigationColumn; begin FCurrentNavigationColumn := TcxTreeListColumn(Controller.FocusedItem); end; procedure TcxTreeListCellNavigator.SetFocusCell( ARowIndex, ACellIndex: Integer; AShift: TShiftState); var ANode: TcxTreeListNode; begin if ARowIndex < 0 then Exit; ANode := GetNode(ARowIndex); if ANode.IsGroupNode then Controller.SetFocusedNodeItem(ANode, TreeList.OptionsView.GetCategorizedColumn) else Controller.SetFocusedNodeItem(ANode, TreeList.VisibleColumns[ACellIndex]); if FColumnChanged then SaveCurrentNavigationColumn; end; procedure TcxTreeListCellNavigator.FocusNextCell(AForward, ANextRow: Boolean; AShift: TShiftState = []); begin FColumnChanged := not ANextRow; inherited FocusNextCell(AForward, ANextRow, AShift); end; procedure TcxTreeListCellNavigator.KeyDown(var Key: Word; Shift: TShiftState); var ANode: TcxTreeListNode; begin if TreeList.OptionsSelection.CellSelect and ([ssShift, ssCtrl] * Shift = []) and (TreeList.VisibleColumnCount > 0) then inherited KeyDown(Key, Shift) else case Key of VK_LEFT, VK_RIGHT: begin if TreeList.ViewInfo.HScrollSize <> 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; end; procedure TcxTreeListCellNavigator.Refresh; begin inherited Refresh; end; function TcxTreeListCellNavigator.GetCellIndex( AColumn: TcxTreeListColumn; ARow: TcxTreeListBandRow): Integer; var AColumnIndex: Integer; begin AColumnIndex := AColumn.Position.VisibleColIndex; if FCurrentNavigationColumn <> nil then AColumnIndex := FCurrentNavigationColumn.Position.VisibleColIndex; Result := ARow.VisibleItems[Min(AColumnIndex, ARow.VisibleItemCount - 1)].VisibleIndex; end; function TcxTreeListCellNavigator.GetController: TcxTreeListController; begin Result := TcxTreeListController(inherited Controller); end; function TcxTreeListCellNavigator.GetFocusedNode: TcxTreeListNode; begin Result := TreeList.FocusedNode; end; function TcxTreeListCellNavigator.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(TcxTreeListController(Controller).EditingControl); end; function TcxTreeListCellNavigator.GoToNextCellInBand(AForward: Boolean; AColumn: TcxTreeListColumn; var ACellIndex: Integer): Boolean; var ARow: Integer; ARows: TcxTreeListBandRows; begin Result := False; ARows := AColumn.Position.Band.BandRows; ARow := AColumn.Position.VisibleRowIndex + cxIntOffs[AForward]; if ARows.VisibleItemCount <= 1 then Exit; while not Result and cxInRange(ARow, 0, ARows.VisibleItemCount - 1) do begin if ARows.VisibleItems[ARow].VisibleItemCount > 0 then begin ACellIndex := GetCellIndex(AColumn, ARows.VisibleItems[ARow]); Result := True; end else Inc(ARow, cxIntOffs[AForward]); end; end; function TcxTreeListCellNavigator.GoToNextNodeCell(AForward: Boolean; ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var ACellIndex: Integer): Boolean; var ARow: Integer; ARows: TcxTreeListBandRows; begin if AColumn = nil then AColumn := FCurrentNavigationColumn; Result := (ANode <> nil) and (AColumn <> nil); if Result then begin if ANode.IsGroupNode then ACellIndex := 0 else begin ARows := AColumn.Position.Band.BandRows; ARow := cxSetValue(AForward, 0, ARows.VisibleItemCount - 1); ACellIndex := GetCellIndex(AColumn, ARows.VisibleItems[ARow]); end; 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 } constructor TcxTreeListStyles.Create(AOwner: TPersistent); begin inherited Create(AOwner); BitmapInViewParams := True; end; 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 ABand.Styles.GetViewParams(tlbs_HeaderBackground, ABand, nil, Result); end; function TcxTreeListStyles.GetBandContentParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode): TcxViewParams; begin Result := ABand.Styles.GetContentParams(ANode, nil); end; function TcxTreeListStyles.GetBandFooterParams( ABand: TcxTreeListBand; ANode: TcxTreeListNode): TcxViewParams; begin ABand.Styles.GetViewParams(tlbs_Footer, ANode, nil, Result); end; function TcxTreeListStyles.GetBandHeaderParams( ABand: TcxTreeListBand): TcxViewParams; begin if ABand = nil then DoGetBandHeaderParams(nil, Result) else ABand.Styles.GetViewParams(tlbs_Header, nil, nil, Result); end; function TcxTreeListStyles.GetColumnFooterParams(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem = nil): TcxViewParams; begin DoGetColumnFooterParams(AColumn, ANode, ASummaryItem, Result); end; function TcxTreeListStyles.GetColumnHeaderParams( AColumn: TcxTreeListColumn): TcxViewParams; begin if AColumn = nil then DoGetColumnHeaderParams(nil, Result) else AColumn.Styles.GetViewParams(tlcs_Header, AColumn, nil, Result); end; function TcxTreeListStyles.GetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxViewParams; var AStyle: TcxStyle; ACellPos: TcxTreeListCellPos; begin AStyle := nil; if (ANode <> nil) and ANode.HotTrack and not TreeList.IsEditing and ((AColumn = nil) or not AColumn.IsPreview) then begin if Assigned(FOnGetHotTrackStyle) then FOnGetHotTrackStyle(TreeList, AColumn, ANode, AStyle); FillChar(Result, SizeOf(Result), 0); ACellPos := TcxTreeListCellPos.Create(ANode, AColumn); try GetViewParams(tlsv_HotTrack, ACellPos, AStyle, Result); finally ACellPos.Free; end; end else Result := AColumn.Styles.GetContentParams(ANode); end; function TcxTreeListStyles.GetFooterParams: TcxViewParams; begin GetViewParams(tlsv_Footer, nil, nil, Result); end; function TcxTreeListStyles.GetIncSearchParams: TcxViewParams; begin GetViewParams(tlsv_IncSearch, nil, nil, Result); end; function TcxTreeListStyles.GetIndentParams( ANode: TcxTreeListNode; AIndent: Integer): TcxViewParams; var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetNodeIndentStyle) then FOnGetNodeIndentStyle(TreeList, ANode, AIndent, AStyle); if not TreeList.OptionsView.UseNodeColorForIndent and (ANode <> nil) then begin AIndent := ANode.Level - AIndent + Byte(TreeList.OptionsView.ShowRoot); while AIndent > 0 do begin ANode := ANode.Parent; Dec(AIndent); end; end; DoGetNodeContentParams(ANode, AStyle, Result); end; function TcxTreeListStyles.GetIndicatorParams: TcxViewParams; begin GetViewParams(tlsv_Indicator, nil, nil, Result); end; function TcxTreeListStyles.GetPreviewParams(ANode: TcxTreeListNode): TcxViewParams; begin Result := GetContentParams(ANode, TreeList.Preview.Column); end; procedure TcxTreeListStyles.DoGetBandBackgroundParams( ABand: TcxTreeListBand; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetBandBackgroundStyle) then FOnGetBandBackgroundStyle(TreeList, ABand, AStyle); GetViewParams(tlsv_BandBackground, ABand, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetBandContentParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode; var AParams: TcxViewParams); var AStyle: TcxStyle; ACellPos: TcxTreeListCellPos; begin AStyle := nil; if Assigned(FOnGetBandContentStyle) then FOnGetBandContentStyle(TreeList, ABand, ANode, AStyle); if GetValue(tlsv_BandContent) <> nil then begin ACellPos := TcxTreeListCellPos.Create(ANode, ABand); try GetViewParams(tlsv_BandContent, ACellPos, AStyle, AParams) finally ACellPos.Free; end; end else DoGetNodeContentParams(ANode, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetBandFooterParams(ABand: TcxTreeListBand; ANode: TcxTreeListNode; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetBandFooterStyle) then FOnGetBandFooterStyle(TreeList, ABand, ANode, AStyle); GetViewParams(tlsv_Footer, ABand, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetBandHeaderParams( ABand: TcxTreeListBand; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetBandHeaderStyle) then FOnGetBandHeaderStyle(TreeList, ABand, AStyle); GetViewParams(tlsv_BandHeader, ABand, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetColumnFooterParams(AColumn: TcxTreeListColumn; ANode: TcxTreeListNode; ASummaryItem: TcxTreeListSummaryItem; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetColumnFooterStyle) then FOnGetColumnFooterStyle(TreeList, AColumn, ANode, ASummaryItem, AStyle); if AColumn <> nil then AColumn.Styles.GetViewParams(tlcs_Footer, ANode, AStyle, AParams) else GetViewParams(tlsv_ColumnFooter, AColumn, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetColumnHeaderParams( AColumn: TcxTreeListColumn; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetColumnHeaderStyle) then FOnGetColumnHeaderStyle(TreeList, AColumn, AStyle); GetViewParams(tlsv_ColumnHeader, AColumn, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetContentParams(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if AColumn.IsPreview then begin DoGetPreviewParams(ANode, AParams); Exit; end else begin if Assigned(FOnGetContentStyle) and (ANode <> nil) then FOnGetContentStyle(TreeList, AColumn, ANode, AStyle); DoGetNodeContentParams(ANode, AStyle, AParams); end; end; procedure TcxTreeListStyles.DoGetNodeContentParams( ANode: TcxTreeListNode; AStyle: TcxStyle; var AParams: TcxViewParams); begin if (ANode <> nil) and (GetValue(OddEvenStyleIndexes[Odd(ANode.VisibleIndex)]) <> nil) then GetViewParams(OddEvenStyleIndexes[Odd(ANode.VisibleIndex)], ANode, AStyle, AParams) else GetViewParams(ecs_Content, ANode, AStyle, AParams); end; procedure TcxTreeListStyles.DoGetPreviewParams( ANode: TcxTreeListNode; var AParams: TcxViewParams); var AStyle: TcxStyle; begin AStyle := nil; if Assigned(FOnGetPreviewStyle) then FOnGetPreviewStyle(TreeList, ANode, AStyle); GetViewParams(tlsv_Preview, ANode, AStyle, AParams); end; procedure TcxTreeListStyles.GetDefaultViewParams( Index: Integer; AData: TObject; out AParams: TcxViewParams); begin inherited GetDefaultViewParams(Index, AData, AParams); if (Index = tlsv_Content) and (AData is TcxTreeListCellPos) and (TcxTreeListCellPos(AData).Node <> nil) then Index := OddEvenStyleIndexes[Odd(TcxTreeListCellPos(AData).Node.VisibleIndex)]; with LookAndFeelPainter, AParams do begin Font := TcxCustomTreeList(Control).Font; case Index of tlsv_Preview: begin Color := DefaultContentColor; TextColor := DefaultPreviewTextColor; end; tlsv_HotTrack: begin with TcxTreeListCellPos(AData) do AParams := TcxTreeListColumn(Item).Styles.GetContentParams(Node); TextColor := clHighlightText; end; tlsv_Content, tlsv_BandContent: begin Color := DefaultContentColor; TextColor := DefaultContentTextColor; end; tlsv_ContentOdd: begin Color := DefaultContentOddColor; TextColor := DefaultContentTextColor; end; tlsv_ContentEven: begin Color := DefaultContentEvenColor; 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; end; end; 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.GetLoolAndFeel: TcxLookAndFeel; begin Result := TreeList.LookAndFeel; end; function TcxTreeListStyles.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(GetOwner); end; { TcxTreeListOptionsCustomizing } constructor TcxTreeListOptionsCustomizing.Create(AOwner: TPersistent); begin inherited Create(AOwner); FBandCustomizing := True; FBandHorzSizing := True; FBandMoving := True; FBandVertSizing := True; FColumnCustomizing := True; FColumnHorzSizing := True; FColumnMoving := True; FColumnVertSizing := True; FNestedBands := True; end; procedure TcxTreeListOptionsCustomizing.Assign(Source: TPersistent); begin if Source is TcxTreeListOptionsCustomizing then with TcxTreeListOptionsCustomizing(Source) do begin Self.BandCustomizing := BandCustomizing; Self.BandHiding := BandHiding; Self.BandHorzSizing := BandHorzSizing; Self.BandMoving := BandMoving; Self.BandsQuickCustomization := BandsQuickCustomization; Self.BandsQuickCustomizationMaxDropDownCount := BandsQuickCustomizationMaxDropDownCount; Self.BandVertSizing := BandVertSizing; Self.ColumnCustomizing := ColumnCustomizing; Self.ColumnHiding := Self.ColumnHiding; Self.ColumnHorzSizing := ColumnHorzSizing; Self.ColumnMoving := ColumnMoving; Self.ColumnsQuickCustomization := ColumnsQuickCustomization; Self.ColumnsQuickCustomizationMaxDropDownCount := ColumnsQuickCustomizationMaxDropDownCount; Self.ColumnVertSizing := ColumnVertSizing; Self.DynamicSizing := DynamicSizing; Self.NestedBands := NestedBands; Self.NodeSizing := NodeSizing; Self.RowSizing := RowSizing; end else inherited Assign(Source); end; procedure TcxTreeListOptionsCustomizing.Changed; begin TreeList.LayoutChanged; end; function TcxTreeListOptionsCustomizing.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(GetOwner); end; procedure TcxTreeListOptionsCustomizing.SetBandCustomizing(AValue: Boolean); begin if AValue <> FBandCustomizing then begin FBandCustomizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetBandHiding(AValue: Boolean); begin if AValue <> FBandHiding then begin FBandHiding := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetBandHorzSizing(AValue: Boolean); begin if AValue <> FBandHorzSizing then begin FBandHorzSizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetBandMoving(AValue: Boolean); begin if AValue <> FBandMoving then begin FBandMoving := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetBandsQuickCustomization( AValue: Boolean); begin if AValue <> FBandsQuickCustomization then begin FBandsQuickCustomization := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetBandVertSizing(AValue: Boolean); begin if AValue <> FBandVertSizing then begin FBandVertSizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetColumnCustomizing(AValue: Boolean); begin if AValue <> FColumnCustomizing then begin FColumnCustomizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetColumnHiding(AValue: Boolean); begin if AValue <> FColumnHiding then begin FColumnHiding := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetColumnHorzSizing(AValue: Boolean); begin if AValue <> FColumnHorzSizing then begin FColumnHorzSizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetColumnMoving(AValue: Boolean); begin if AValue <> FColumnMoving then begin FColumnMoving := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetColumnsQuickCustomization( AValue: Boolean); begin if AValue <> FColumnsQuickCustomization then begin FColumnsQuickCustomization := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetColumnVertSizing(AValue: Boolean); begin if AValue <> FColumnVertSizing then begin FColumnVertSizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetDynamicSizing(AValue: Boolean); begin if AValue <> FDynamicSizing then begin FDynamicSizing := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetNestedBands(AValue: Boolean); begin if AValue <> FNestedBands then begin FNestedBands := AValue; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetNodeSizing(AValue: Boolean); begin if AValue <> FNodeSizing then begin FNodeSizing := AValue; if AValue then FRowSizing := False; Changed; end; end; procedure TcxTreeListOptionsCustomizing.SetRowSizing(AValue: Boolean); begin if AValue <> FRowSizing then begin FRowSizing := AValue; if AValue then FNodeSizing := False; Changed; end; end; { TcxTreeListOptionsSelection } constructor TcxTreeListOptionsSelection.Create(AOwner: TPersistent); begin inherited Create(AOwner); FCellSelect := True; FHideFocusRect := True; FInvertSelect := True; end; procedure TcxTreeListOptionsSelection.Assign(Source: TPersistent); begin if Source is TcxTreeListOptionsSelection then with TcxTreeListOptionsSelection(Source) do begin Self.CellSelect := CellSelect; Self.HideFocusRect := HideFocusRect; Self.HideSelection := HideSelection; Self.InvertSelect := InvertSelect; Self.MultiSelect := MultiSelect; end else inherited Assign(Source); end; function TcxTreeListOptionsSelection.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(GetOwner); end; { TcxTreeListOptionsBehavior } constructor TcxTreeListOptionsBehavior.Create(AOwner: TPersistent); begin inherited Create(AOwner); ConfirmDelete := True; DragCollapse := True; DragExpand := True; ShowHourGlass := True; Sorting := True; MultiSort := True; WaitForExpandNodeTime := 500; ExpandOnDblClick := True; end; procedure TcxTreeListOptionsBehavior.Assign(Source: TPersistent); var ASource: TcxTreeListOptionsBehavior; begin if Source is TcxTreeListOptionsBehavior then begin ASource := TcxTreeListOptionsBehavior(Source); FAutoDragCopy := ASource.AutoDragCopy; FConfirmDelete := ASource.ConfirmDelete; FDragCollapse := ASource.DragCollapse; FDragExpand := ASource.DragExpand; FDragFocusing := ASource.DragFocusing; FExpandOnDblClick := ASource.ExpandOnDblClick; FExpandOnIncSearch := ASource.ExpandOnIncSearch; FFooterHints := ASource.FooterHints; FHeaderHints := ASource.HeaderHints; FHotTrack := ASource.HotTrack; FMultiSort := ASource.MultiSort; FShowHourGlass := ASource.ShowHourGlass; FSorting := ASource.Sorting; ChangeDelay := ASource.ChangeDelay; WaitForExpandNodeTime := ASource.WaitForExpandNodeTime; IncSearchItem := TreeList.GetSameColumn(ASource.IncSearchItem); end; inherited Assign(Source); end; procedure TcxTreeListOptionsBehavior.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); Filer.DefineProperty('AutomateLeftMostIndent', ReadBoolean, nil, True); end; function TcxTreeListOptionsBehavior.GetChangeDelay: Integer; begin Result := TreeList.FDelayTimer.Interval; end; function TcxTreeListOptionsBehavior.GetIncSearchItem: TcxTreeListColumn; begin Result := TcxTreeListColumn(inherited IncSearchItem); end; function TcxTreeListOptionsBehavior.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(GetOwner); end; procedure TcxTreeListOptionsBehavior.ReadBoolean(AReader: TReader); begin AReader.ReadBoolean; end; procedure TcxTreeListOptionsBehavior.SetChangeDelay(AValue: Integer); begin AValue := Max(0, AValue); TreeList.ChangeDelayTimer.Enabled := AValue > 0; TreeList.ChangeDelayTimer.Interval := AValue; end; procedure TcxTreeListOptionsBehavior.SetFooterHints( AValue: Boolean); begin if FFooterHints <> AValue then begin FFooterHints := AValue; Changed; end; end; procedure TcxTreeListOptionsBehavior.SetHeaderHints( AValue: Boolean); begin if FHeaderHints <> AValue then begin FHeaderHints := AValue; Changed; end; end; procedure TcxTreeListOptionsBehavior.SetIncSearchItem(AValue: TcxTreeListColumn); begin inherited IncSearchItem := AValue; 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 FDeleting := TcxTreeListOptionsData(Source).FDeleting; FInserting := TcxTreeListOptionsData(Source).FInserting; SummaryNullIgnore := TcxTreeListOptionsData(Source).SummaryNullIgnore; end; inherited Assign(Source); end; procedure TcxTreeListOptionsData.Changed; begin inherited Changed; TcxCustomTreeList(GetOwner).RefreshNavigatorButtons; end; function TcxTreeListOptionsData.GetAnsiSort: Boolean; begin Result := dcoAnsiSort in TcxCustomTreeList(GetOwner).DataController.Options; end; function TcxTreeListOptionsData.GetCaseInsensitive: Boolean; begin Result := dcoCaseInsensitive in TcxCustomTreeList(GetOwner).DataController.Options; end; procedure TcxTreeListOptionsData.SetAnsiSort(Value: Boolean); begin with TcxCustomTreeList(GetOwner).DataController do begin if Value then Options := Options + [dcoAnsiSort] else Options := Options - [dcoAnsiSort] end; end; procedure TcxTreeListOptionsData.SetCaseInsensitive(Value: Boolean); begin with TcxCustomTreeList(GetOwner).DataController do begin if Value then Options := Options + [dcoCaseInsensitive] else Options := Options - [dcoCaseInsensitive] end; end; procedure TcxTreeListOptionsData.SetSummaryNullIgnore(Value: Boolean); begin if FSummaryNullIgnore <> Value then begin FSummaryNullIgnore := Value; TcxCustomTreeList(GetOwner).Summary.Recalculate; end; end; { TcxTreeList } 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); begin SetGlassCursor; try WriteData(AStream); finally RestoreCursor; end; end; procedure TcxTreeList.AssignData(ASource: TcxCustomTreeList); var AStream: TMemoryStream; begin inherited AssignData(ASource); if ASource is TcxTreeList then begin AStream := TMemoryStream.Create; try TcxTreeList(ASource).SaveToStream(AStream); AStream.Position := 0; LoadFromStream(AStream); finally AStream.Free; end; end; end; procedure TcxTreeList.CorrectHandles; var I: Integer; begin if AbsoluteCount = 0 then Exit; FAbsoluteItems.Sort(@cxCompareNodesByRecordIndex); DataController.FAllocatedRecords := 0; for I := 0 to FAbsoluteItems.Count - 1 do DataController.InitializeNodeFromRecordIndex(TcxTreeListNode(FAbsoluteItems.List^[I])); FAbsoluteItems.Sort(@cxCompareNodesByAbsoluteIndex); end; procedure TcxTreeList.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); Filer.DefineBinaryProperty('Data', ReadData, WriteData, AbsoluteCount > 0); end; procedure TcxTreeList.Loaded; begin BeginUpdate; try inherited Loaded; Include(FChanges, tcLoading); try if FDataStream <> nil then try ReadData(FDataStream); finally FDataStream.Free; end; Exclude(FChanges, tcLoading); finally FChanges := [tcStructure..tcSortOrder]; end; finally EndUpdate; end; end; function TcxTreeList.SupportItemsEditor: Boolean; begin Result := True; end; procedure TcxTreeList.ReadData(AStream: TStream); var AHeader: TcxTreeListStreamHeader; begin if IsLoading then begin FDataStream := TMemoryStream.Create; FDataStream.CopyFrom(AStream, AStream.Size - AStream.Position); FDataStream.Position := 0; Exit; end; AStream.ReadBuffer(AHeader, SizeOf(TcxTreeListStreamHeader)); if (AHeader.Size <> AStream.Size) then cxTreeListError(cxGetResourceString(@scxInvalidStreamFormat)); BeginUpdate; try DoClear; try DataController.LoadFromStream(AStream); ReadStructure(AStream, AHeader.Major); except DoClear; raise; end; finally EndUpdate; end; end; procedure TcxTreeList.ReadStructure(AStream: TStream; AVersion: Integer); var AIndex: Integer; ANewNode, ANode: TcxTreeListNode; begin ANode := Root; AStream.ReadBuffer(Root.FCount, SizeOf(Integer)); if Root.FCount = 0 then Exit; AIndex := 0; repeat ANewNode := InternalCreateNode(ANode, ANode.FLast, AIndex); ANewNode.ReadData(AStream, AVersion); 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 = Root) and (AIndex = ANode.Count); if AStream.Position < AStream.Size then Root.ReadData(AStream, AVersion); CorrectHandles; end; procedure TcxTreeList.WriteData(AStream: TStream); var I: Integer; AHeader: TcxTreeListStreamHeader; begin AStream.Position := 0; PInteger(@AHeader)^ := cxTreeListVersion; AHeader.Size := AStream.Size; AStream.WriteBuffer(AHeader, SizeOf(AHeader)); TcxDataStorageHelper.SetRecordsCapacity(DataController.DataStorage, AbsoluteCount); for I := 0 to AbsoluteCount - 1 do DataController.InitializeRecordIndexFromNode(TcxTreeListNode(FAbsoluteItems[I])); try DataController.SaveToStream(AStream); WriteStructure(AStream); AHeader.Size := AStream.Size; AStream.Position := Integer(@AHeader.Size) - Integer(@AHeader); AStream.Write(AHeader.Size, SizeOf(AHeader.Size)); AStream.Position := AHeader.Size; finally CorrectHandles; end; end; procedure TcxTreeList.WriteStructure(AStream: TStream); var ANode: TcxTreeListNode; begin ANode := Root.GetFirstChild; AStream.WriteBuffer(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; Root.WriteData(AStream); end; function TcxTreeList.InternalCreateNode(AParent, APrev: TcxTreeListNode; var AIndex: Integer): TcxTreeListNode; begin Result := CreateNode; 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; { TcxTreeListBandOptions } constructor TcxTreeListBandOptions.Create(AOwner: TPersistent); begin inherited Create(AOwner); RestoreDefaults; end; procedure TcxTreeListBandOptions.Assign(Source: TPersistent); begin if Source is TcxTreeListBandOptions then begin FCustomizing := TcxTreeListBandOptions(Source).FCustomizing; FHidden := TcxTreeListBandOptions(Source).FHidden; FMoving := TcxTreeListBandOptions(Source).FMoving; FOnlyOwnColumns := TcxTreeListBandOptions(Source).FOnlyOwnColumns; FSizing := TcxTreeListBandOptions(Source).FSizing; FVertSizing := TcxTreeListBandOptions(Source).VertSizing; end else inherited Assign(Source); end; procedure TcxTreeListBandOptions.RestoreDefaults; begin FCustomizing := True; FHidden := False; FMoving := True; FOnlyOwnColumns := False; FSizing := True; FVertSizing := True; Changed; end; procedure TcxTreeListBandOptions.Changed; begin TcxTreeListBand(GetOwner).LayoutChanged; end; procedure TcxTreeListBandOptions.SetSizing(AValue: Boolean); begin if AValue <> FSizing then begin FSizing := AValue; Changed; end; end; procedure TcxTreeListBandOptions.SetVertSizing(AValue: Boolean); begin if AValue <> FVertSizing then begin FVertSizing := AValue; Changed; end; end; { TcxTreeListBandStyles } constructor TcxTreeListBandStyles.Create(AOwner: TPersistent); begin inherited Create(AOwner); BitmapInViewParams := True; end; procedure TcxTreeListBandStyles.Assign(Source: TPersistent); begin if Source is TcxTreeListBandStyles then begin Content := TcxTreeListBandStyles(Source).Content; Footer := TcxTreeListBandStyles(Source).Footer; Header := TcxTreeListBandStyles(Source).Header; HeaderBackground := TcxTreeListBandStyles(Source).HeaderBackground; end; inherited Assign(Source); end; function TcxTreeListBandStyles.GetContentParams( ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxViewParams; begin if AColumn <> nil then Result := AColumn.Styles.GetContentParams(ANode) else DoGetContentParams(ANode, AColumn, Result); end; function TcxTreeListBandStyles.GetBand: TcxTreeListBand; begin Result := TcxTreeListBand(GetOwner); end; function TcxTreeListBandStyles.GetTreeList: TcxCustomTreeList; begin Result := Band.TreeList; end; procedure TcxTreeListBandStyles.Changed(AIndex: Integer); begin inherited Changed(AIndex); TreeList.UpdateViewStyles; end; procedure TcxTreeListBandStyles.DoGetContentParams( ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AParams: TcxViewParams); var ACellPos: TcxTreeListCellPos; begin ACellPos := TcxTreeListCellPos.Create(ANode, AColumn); try GetViewParams(tlbs_Content, ACellPos, nil, AParams); finally ACellPos.Free; end; end; procedure TcxTreeListBandStyles.GetDefaultViewParams(Index: Integer; AData: TObject; out AParams: TcxViewParams); begin inherited GetDefaultViewParams(Index, AData, AParams); case Index of tlbs_Content: if AData is TcxTreeListCellPos then begin with TcxTreeListCellPos(AData) do begin if Item <> nil then TreeList.Styles.DoGetContentParams(Node, TcxTreeListColumn(Item), AParams) else TreeList.Styles.DoGetBandContentParams(Band, Node, AParams); end; end else TreeList.Styles.DoGetBandContentParams(Band, nil, AParams); tlbs_Footer: if AData is TcxTreeListCellPos then TreeList.Styles.GetViewParams(tlsv_ColumnFooter, TcxTreeListCellPos(AData).Item, nil, AParams) else TreeList.Styles.DoGetBandFooterParams(Band, TcxTreeListNode(AData), AParams); tlbs_Header: TreeList.Styles.DoGetBandHeaderParams(Band, AParams); tlbs_HeaderBackground: TreeList.Styles.DoGetBandBackgroundParams(Band, AParams); end; end; { TcxTreeListBandPosition } constructor TcxTreeListBandPosition.Create(AOwner: TPersistent); begin inherited Create(AOwner); FBandIndex := -1; FColIndex := -1; end; procedure TcxTreeListBandPosition.Assign(Source: TPersistent); begin if Source is TcxTreeListBandPosition then begin FBandIndex := TcxTreeListBandPosition(Source).BandIndex; FColIndex := TcxTreeListBandPosition(Source).ColIndex end else inherited Assign(Source); end; procedure TcxTreeListBandPosition.Changed; begin Band.LayoutChanged; end; function TcxTreeListBandPosition.CheckBandIndex(var AIndex: Integer): Boolean; var AColIndex, I: Integer; ABand: TcxTreeListBand; begin Result := Band.Index <> AIndex; if TreeList.IsDestroying or not Result then Exit; Result := (AIndex = -1) or ((AIndex >= 0) and (AIndex < TreeList.Bands.Count)); if not Result or (AIndex = - 1) then Exit; ABand := TreeList.Bands[AIndex]; if not ABand.HasAsParent(Band) then Exit; AColIndex := ColIndex; TreeList.BeginUpdate; try for I := Band.ChildBandCount - 1 downto 0 do with Band.ChildBands[I].Position do begin BandIndex := Self.BandIndex; ColIndex := AColIndex; end; AIndex := ABand.Index; finally TreeList.EndUpdate; end; end; function TcxTreeListBandPosition.IsPositionChanged: Boolean; begin Result := (BandIndex <> FBandIndex) or (ColIndex <> FColIndex); end; procedure TcxTreeListBandPosition.Restore; begin BandIndex := FBandIndex; if not Band.IsRoot then ColIndex := FColIndex; end; procedure TcxTreeListBandPosition.Store; begin FBandIndex := BandIndex; FColIndex := ColIndex; end; function TcxTreeListBandPosition.GetBandIndex: Integer; begin if ParentBand = nil then Result := -1 else Result := ParentBand.Index; end; function TcxTreeListBandPosition.GetColIndex: Integer; begin if ParentBand = nil then Result := Band.RootIndex else Result := ParentBand.IndexOf(Band); end; function TcxTreeListBandPosition.GetBand: TcxTreeListBand; begin Result := TcxTreeListBand(GetOwner); end; function TcxTreeListBandPosition.GetTreeList: TcxCustomTreeList; begin Result := Band.TreeList; end; function TcxTreeListBandPosition.GetVisibleColIndex: Integer; begin if ParentBand = nil then Result := Band.Bands.FVisibleRootItems.IndexOf(Self) else Result := ParentBand.FChildVisibleBands.IndexOf(Band); end; procedure TcxTreeListBandPosition.SetBandIndex(AValue: Integer); begin if IsLocked then begin FBandIndex := AValue; Exit; end; if not CheckBandIndex(AValue) or (BandIndex = AValue) then Exit; TreeList.BeginUpdate; try if ParentBand <> nil then ParentBand.RemoveBand(Band); if AValue >= 0 then begin FParentBand := TreeList.Bands[AValue]; FParentBand.AddBand(Band); end else FParentBand := nil; Band.LayoutChanged; finally TreeList.EndUpdate; end; end; procedure TcxTreeListBandPosition.SetColIndex(AValue: Integer); begin if IsLocked then FColIndex := AValue else if ColIndex <> AValue then begin if ParentBand = nil then Band.RootIndex := AValue else ParentBand.MoveBand(Band, AValue); end; end; function TcxTreeListBandPosition.IsColIndexStored: Boolean; begin Result := not Band.IsRoot; end; function TcxTreeListBandPosition.IsLocked: Boolean; begin Result := TreeList.IsDestroying or Band.IsLoading or TreeList.IsUpdating; end; { TcxTreeListBand } constructor TcxTreeListBand.Create(Collection: TCollection); begin TcxTreeListBands(Collection).TreeList.BeginUpdate; inherited Create(Collection); FChildBands := TList.Create; FChildVisibleBands := TList.Create; FVisibleColumns := TList.Create; FBandRows := TcxTreeListBandRows.Create(Self); FColumns := TList.Create; FPosition := TcxTreeListBandPosition.Create(Self); FCaption := TcxTreeListCaption.Create(Self); FCaption.OnChange := ChangeCaption; FStyles := TcxTreeListBandStyles.Create(Self); FOptions := GetOptionsClass.Create(Self); Visible := True; RestoreWidths; TcxTreeListBands(Collection).TreeList.EndUpdate; end; destructor TcxTreeListBand.Destroy; var ATreeList: TcxCustomTreeList; begin ATreeList := TreeList; ATreeList.BeginUpdate; TreeList.Controller.UnselectObject(Self); Position.BandIndex := -1; RemoveChildBands; RemoveColumns; FreeAndNil(FChildVisibleBands); FreeAndNil(FCaption); FreeAndNil(FColumns); FreeAndNil(FOptions); FreeAndNil(FPosition); FreeAndNil(FStyles); FreeAndNil(FBandRows); FreeAndNil(FVisibleColumns); FreeAndNil(FChildBands); inherited Destroy; ATreeList.EndUpdate; 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; Position := ABand.Position; Options := ABand.Options; Styles := ABand.Styles; Caption := ABand.Caption; FixedKind := ABand.FixedKind; Visible := ABand.Visible; end else inherited Assign(Source); end; procedure TcxTreeListBand.ApplyBestFit; var AColIndex: Integer; begin TreeList.ValidateStates; TreeList.BeginUpdate; try TreeList.HideEdit; FWidth := 0; if VisibleColumnCount > 0 then begin for AColIndex := 0 to VisibleColumnCount - 1 do VisibleColumns[AColIndex].ApplyBestFit; BandRows.Refresh; FCalculatedWidth := BandRows.RowMaxWidth; end else FCalculatedWidth := FMinWidth; finally TreeList.EndUpdate; end; end; function TcxTreeListBand.IndexOf(AChildBand: TcxTreeListBand): Integer; begin Result := FChildBands.IndexOf(AChildBand); end; function TcxTreeListBand.HasAsParent(ABand: TcxTreeListBand): Boolean; var AParent: TcxTreeListBand; begin Result := False; AParent := Self; while not Result and (AParent <> nil) do begin AParent := AParent.ParentBand; Result := AParent = ABand; end; end; procedure TcxTreeListBand.MoveBand(ABand: TcxTreeListBand; AColIndex: Integer); begin ABand.Position.BandIndex := Index; AColIndex := Min(Max(0, AColIndex), ChildBandCount - 1); FChildBands.Move(ABand.Position.ColIndex, AColIndex); LayoutChanged; 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; function TcxTreeListBand.ActualMinWidth: Integer; var I, ASum: Integer; begin Result := Max(MinWidth, BandRows.RowMinWidth); ASum := 0; for I := 0 to ChildVisibleBands.Count - 1 do Inc(ASum, TcxTreeListBand(ChildVisibleBands[I]).ActualMinWidth); Result := Max(Result, ASum); end; procedure TcxTreeListBand.AdjustSubItems; var I: Integer; begin BandRows.Refresh; if VisibleColumnCount > 0 then begin for I := 0 to BandRows.VisibleItemCount - 1 do BandRows.VisibleItems[I].AdjustColumns; end else Bands.Adjust(FChildVisibleBands, CalculatedWidth); end; procedure TcxTreeListBand.AssignChildBandWidths; var I: Integer; begin for I := 0 to ChildVisibleBands.Count - 1 do TcxTreeListBand(ChildVisibleBands[I]).AssignWidth; end; procedure TcxTreeListBand.AssignColumnsWidth; var I: Integer; begin for I := 0 to BandRows.Count - 1 do BandRows[I].AssignColumnsWidth; end; procedure TcxTreeListBand.AssignWidth; begin if ActuallyVisible then FWidth := FCalculatedWidth; end; procedure TcxTreeListBand.InitAutoWidthItem(AItem: TcxAutoWidthItem); begin AItem.Width := Width; if AItem.Width = 0 then AItem.Width := CalculatedWidth; AItem.Fixed := IsWidthFixed; AItem.MinWidth := Max(FMinWidth, BandRows.RowMinWidth); AItem.Width := Max(AItem.Width, AItem.MinWidth + IndentWidth); if AItem.Fixed then AItem.MinWidth := Max(AItem.MinWidth, AItem.Width); AItem.AutoWidth := -1; end; function TcxTreeListBand.IsBandFixedDuringSizing: Boolean; var AForcingBand: TcxTreeListBand; begin AForcingBand := TreeList.Controller.ForcingWidthBand; Result := (AForcingBand <> nil) and ((Self = AForcingBand) or not AForcingBand.IsLastAsChild and (ParentBand = AForcingBand.ParentBand) and (Position.VisibleColIndex < AForcingBand.Position.VisibleColIndex)); end; function TcxTreeListBand.IsOnlyOwnColumns: Boolean; begin Result := Options.OnlyOwnColumns; end; procedure TcxTreeListBand.CalculateLineCount(ACurrentLine: Integer); begin FLineCount := ACurrentLine - Level; if ParentBand <> nil then ParentBand.CalculateLineCount(Level); Refresh; end; function TcxTreeListBand.CanDropColumnAt( const APoint: TPoint; out ARowIndex, AColIndex: Integer): Boolean; begin Result := True; ARowIndex := 0; AColIndex := 0; end; procedure TcxTreeListBand.CheckExpandable(var ABand: TcxTreeListBand); begin if Expandable = tlbeNotExpandable then Exit; if (ABand = nil) or not (ABand.Expandable = tlbeExpandable) and (Expandable <> tlbeDefault) then ABand := Self; end; procedure TcxTreeListBand.ForceWidth(AValue: Integer); procedure AssignBandWidths; var ABand: TcxTreeListBand; begin if ParentBandWidthAssigned <> nil then ParentBand.AssignChildBandWidths; if not TreeList.OptionsView.ColumnAutoWidth then Exit; ABand := ParentBand; while ABand <> nil do begin ABand.AssignChildBandWidths; ABand := ABand.ParentBand; end; Bands.AssignRootItemWidths; end; begin TreeList.BeginUpdate; try AssignBandWidths; TreeList.Controller.ForcingWidthBand := Self; try Width := AValue; Bands.Adjust(); AssignBandWidths; finally TreeList.Controller.ForcingWidthBand := nil; end; finally TreeList.EndUpdate; end; end; function TcxTreeListBand.GetMaxDeltaWidth: Integer; begin Result := TreeList.GetMaxBandWidth(Self) - DisplayWidth; end; function TcxTreeListBand.CanMoving: Boolean; begin Result := Options.Moving and TreeList.OptionsCustomizing.BandMoving; end; procedure TcxTreeListBand.ChangeCaption(Sender: TObject); begin TreeList.LayoutChanged; end; function TcxTreeListBand.GetOptionsClass: TcxTreeListBandOptionsClass; begin Result := TcxTreeListBandOptions; end; procedure TcxTreeListBand.MoveColumnsTo(ABand: TcxTreeListBand); var I, J: Integer; AColumn: TcxTreeListColumn; begin if ABand = Self then Exit; for I := 0 to BandRows.Count - 1 do for J := 0 to BandRows[0].Count - 1 do begin AColumn := BandRows[0][0]; ABand.AddColumn(AColumn); AColumn.Position.RowIndex := I; AColumn.Position.ColIndex := J; end; FColumns.Clear; BandRows.FItems.Clear; Refresh; ABand.Refresh; end; procedure TcxTreeListBand.LayoutChanged; begin if Bands = nil then Exit; if TreeList.IsLocked then Bands.RefreshInformation else Bands.Update(nil); end; procedure TcxTreeListBand.MoveBandsToRoot; var AColIndex, I: Integer; begin if RootParentBand = nil then AColIndex := FPosition.ColIndex + 1 else AColIndex := RootParentBand.Position.ColIndex + 1; TreeList.BeginUpdate; try for I := ChildBandCount - 1 downto 0 do with ChildBands[I].Position do begin BandIndex := -1; ColIndex := AColIndex; end; finally TreeList.EndUpdate; end; end; procedure TcxTreeListBand.AddBand(ABand: TcxTreeListBand); begin FChildBands.Add(ABand); ABand.FixedKind := FixedKind; MoveColumnsTo(FirstChildBottomBand); Refresh; end; procedure TcxTreeListBand.AddColumn(AColumn: TcxTreeListColumn); begin FColumns.Add(AColumn); with AColumn.Position do begin FBand := Self; Row := BandRows.CheckRowIndex(0) end; end; procedure TcxTreeListBand.ColumnSizeChanged(AColumn: TcxTreeListColumn); begin FCalculatedWidth := 0; AdjustSubItems; TreeList.DoColumnSizeChanged(AColumn); end; procedure TcxTreeListBand.DeleteColumn(AColumn: TcxTreeListColumn); var AIndex: Integer; begin FColumns.Remove(AColumn); with AColumn.Position do begin AIndex := RowIndex; Row.FItems.Remove(AColumn); FRow := nil; end; BandRows.CheckRowEmpty(AIndex); end; procedure TcxTreeListBand.Refresh; var I: Integer; begin FVisibleColumns.Clear; FChildVisibleBands.Clear; BandRows.Refresh; if VisibleColumnCount > 0 then TreeList.FVisibleColumns.Assign(FVisibleColumns, laOr); for I := 0 to ChildBandCount - 1 do if ChildBands[I].Visible then FChildVisibleBands.Add(ChildBands[I]); end; procedure TcxTreeListBand.RemoveBand(ABand: TcxTreeListBand); begin FChildBands.Remove(ABand); Refresh; end; procedure TcxTreeListBand.RemoveChildBands; begin if (Bands = nil) or TreeList.IsUpdating or TreeList.IsDestroying then Exit; while ChildBandCount > 0 do begin ChildBands[0].Visible := False; ChildBands[0].Position.BandIndex := -1; end; end; procedure TcxTreeListBand.RemoveColumns; var I: Integer; begin if TreeList.IsDestroying or (FColumns = nil) then Exit; TreeList.BeginUpdate; try for I := ColumnCount - 1 downto 0 do Columns[I].Position.BandIndex := -1; finally TreeList.EndUpdate; end; end; procedure TcxTreeListBand.SetIndex(Value: Integer); var APrevIndex: Integer; begin APrevIndex := Index; inherited SetIndex(Value); if Index <> APrevIndex then LayoutChanged; end; function TcxTreeListBand.CanSizing(ADirection: TcxDragSizingDirection): Boolean; begin if ADirection = dsdVert then Result := Options.VertSizing and TreeList.OptionsCustomizing.BandVertSizing and IsBottom else Result := TreeList.OptionsCustomizing.BandHorzSizing and Options.Sizing; end; function TcxTreeListBand.GetSizingBoundsRect( ADirection: TcxDragSizingDirection): TRect; begin if ADirection = dsdVert then Result := cxRectSetTop(TreeList.ClientRect, HeaderCell.DisplayRect.Top + TreeList.ViewInfo.BandHeaderLineHeight) else Result := cxRectSetLeft(TreeList.ClientRect, Max(HeaderCell.DisplayRect.Left + ActualMinWidth + IndentWidth, HeaderCell.VisibleRect.Left)); end; function TcxTreeListBand.GetSizingIncrement( ADirection: TcxDragSizingDirection): Integer; begin Result := 1; end; function TcxTreeListBand.IsDynamicUpdate: Boolean; begin Result := TreeList.OptionsCustomizing.DynamicSizing and TreeList.HitTest.HitAtSizingHorz; end; procedure TcxTreeListBand.SetSizeDelta( ADirection: TcxDragSizingDirection; ADelta: Integer); begin if ADelta = 0 then Exit; if ADirection <> dsdHorz then TreeList.OptionsView.BandLineHeight := (TreeList.ViewInfo.BandsHeight + ADelta) div Bands.LineCount else ForceWidth(DisplayWidth + ADelta); TreeList.DoBandSizeChanged(Self); end; function TcxTreeListBand.GetObjectName: string; begin Result := 'Band' + IntToStr(Index); end; function TcxTreeListBand.GetProperties( AProperties: TStrings): Boolean; var I: Integer; begin for I := Low(BandPropertiesName) to High(BandPropertiesName) do AProperties.Add(BandPropertiesName[I]); if Assigned(OnGetStoredProperties) then OnGetStoredProperties(Self, AProperties); Result := True; end; function TcxTreeListBand.GetPropertyIndex(const AName: string): Integer; var I: Integer; begin Result := -1; for I := Low(BandPropertiesName) 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; 5: AValue := Position.BandIndex; 6: AValue := Position.ColIndex; else if Assigned(OnGetStoredPropertyValue) then OnGetStoredPropertyValue(Self, AName, AValue); 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; 5: Position.BandIndex := AValue; 6: Position.ColIndex := AValue; else if Assigned(OnSetStoredPropertyValue) then OnSetStoredPropertyValue(Self, AName, AValue); end; end; function TcxTreeListBand.GetParentBand: TcxTreeListBand; begin Result := FPosition.ParentBand; end; function TcxTreeListBand.GetParentBandWidthAssigned: TcxTreeListBand; begin Result := ParentBand; while Result <> nil do begin if Result.Width <> 0 then Break; Result := Result.ParentBand; end; end; function TcxTreeListBand.GetRootIndex: Integer; begin if Bands = nil then Result := -1 else Result := Bands.FRootItems.IndexOf(Self); end; function TcxTreeListBand.GetRootParentBand: TcxTreeListBand; begin Result := ParentBand; if Result = nil then Exit; while Result.ParentBand <> nil do Result := ParentBand.ParentBand; end; function TcxTreeListBand.GetTreeList: TcxCustomTreeList; begin Result := Bands.TreeList; end; function TcxTreeListBand.GetActuallyExpandable: Boolean; begin Result := FirstChildBottomBand = Bands.ExpandableBand; end; function TcxTreeListBand.GetActuallyVisible: Boolean; begin Result := FVisible and ((ParentBand = nil) or ParentBand.ActuallyVisible); end; function TcxTreeListBand.GetBands: TcxTreeListBands; begin Result := TcxTreeListBands(Collection); end; function TcxTreeListBand.GetCalculatedWidth: Integer; var AWidth, I: Integer; begin Refresh; if FCalculatedWidth = 0 then begin FCalculatedWidth := FWidth; if FCalculatedWidth = 0 then begin FCalculatedWidth := FWidth; if FCalculatedWidth = 0 then FCalculatedWidth := BandRows.RowMaxWidth; if (ChildBandCount > 0) then begin AWidth := 0; for I := 0 to ChildBandCount - 1 do if ChildBands[I].Visible then Inc(AWidth, ChildBands[I].CalculatedWidth); FCalculatedWidth := Max(FCalculatedWidth, AWidth); end; if FCalculatedWidth = 0 then FCalculatedWidth := Max(cxTreeListDefWidth, MinWidth); end; end; Result := Max(FCalculatedWidth, BandRows.RowMinWidth); end; function TcxTreeListBand.GetColumn(AIndex: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(FColumns[AIndex]); end; function TcxTreeListBand.GetColumnCount: Integer; begin Result := FColumns.Count; end; function TcxTreeListBand.GetChildBand(AIndex: Integer): TcxTreeListBand; begin Result := TcxTreeListBand(FChildBands[AIndex]); end; function TcxTreeListBand.GetChildBandCount: Integer; begin Result := FChildBands.Count; end; function TcxTreeListBand.GetDisplayWidth: Integer; begin Result := CalculatedWidth; end; function TcxTreeListBand.GetFirstChildBottomBand: TcxTreeListBand; begin Result := Self; while Result.ChildBandCount > 0 do Result := Result.ChildBands[0]; end; function TcxTreeListBand.GetHasEmptyArea: Boolean; begin Result := FHasEmptyArea or (BandRows.LineCount <> Bands.ColumnsLineCount); end; function TcxTreeListBand.GetIndentWidth: Integer; begin Result := 0; if ActuallyExpandable then Result := TreeList.IndentWidth; end; function TcxTreeListBand.GetIsBottom: Boolean; begin Result := ChildBandCount = 0; end; function TcxTreeListBand.GetIsFirstInGroup: Boolean; var ABand: TcxTreeListBand; begin Result := False; ABand := Bands.VisibleItems[Bands.GetFirstVisibleIndex(FixedKind)]; while not Result and (ABand <> nil) do begin Result := ABand = Self; if ABand.ChildVisibleBands.Count > 0 then ABand := TcxTreeListBand(ABand.ChildVisibleBands[0]) else ABand := nil; end; end; function TcxTreeListBand.GetIsLastAsChild: Boolean; function GetVisibleBandCount: Integer; begin if ParentBand = nil then Result := Bands.RootItemCount else Result := ParentBand.FChildVisibleBands.Count; end; begin Result := FPosition.VisibleColIndex = GetVisibleBandCount - 1; end; function TcxTreeListBand.GetIsLastInGroup: Boolean; var ABand: TcxTreeListBand; begin Result := False; ABand := Bands.VisibleItems[Bands.GetLastVisibleIndex(FixedKind)]; while not Result and (ABand <> nil) do begin Result := ABand = Self; if ABand.ChildVisibleBands.Count > 0 then ABand := TcxTreeListBand(ABand.ChildVisibleBands[ABand.ChildVisibleBands.Count - 1]) else ABand := nil; end; end; function TcxTreeListBand.GetIsLeftMost: Boolean; begin Result := IsFirstInGroup and (Bands.GetFirstVisibleIndex(FixedKind) = 0); end; function TcxTreeListBand.GetIsLoading: Boolean; begin Result := TreeList.IsLoading and not TreeList.IgnoreLoadingStatus; end; function TcxTreeListBand.GetIsRightMost: Boolean; begin Result := IsLastInGroup and (Bands.GetLastVisibleIndex(FixedKind) = Bands.VisibleItemCount - 1); end; function TcxTreeListBand.GetIsRoot: Boolean; begin Result := Position.ParentBand = nil; end; function TcxTreeListBand.GetIsWidthFixed: Boolean; var AForcingColumn: TcxTreeListColumn; begin AForcingColumn := TreeList.Controller.ForcingWidthColumn; Result := not Options.Sizing or IsBandFixedDuringSizing or ((AForcingColumn <> nil) and (AForcingColumn.Position.Band.ParentBandWidthAssigned = Self)); end; function TcxTreeListBand.GetLevel: Integer; var AParent: TcxTreeListBand; begin Result := 0; AParent := ParentBand; while AParent <> nil do begin Inc(Result); AParent := AParent.ParentBand; end; end; function TcxTreeListBand.GetVisibleColumn(AIndex: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(FVisibleColumns[AIndex]); end; function TcxTreeListBand.GetVisibleColumnCount: Integer; begin Result := FVisibleColumns.Count; end; function TcxTreeListBand.GetVisibleRootIndex: Integer; begin Result := Bands.FVisibleRootItems.IndexOf(Self); end; function TcxTreeListBand.GetVisibleIndex: Integer; begin Result := Bands.VisibleIndexOf(Self); end; procedure TcxTreeListBand.SetCalculatedWidth(AValue: Integer); begin FCalculatedWidth := AValue; AdjustSubItems; end; procedure TcxTreeListBand.SetCaption(AValue: TcxTreeListCaption); begin FCaption.Assign(AValue); end; procedure TcxTreeListBand.SetColumn(AIndex: Integer; AValue: TcxTreeListColumn); begin Columns[AIndex].Assign(AValue); end; procedure TcxTreeListBand.SetDisplayWidth(AValue: Integer); begin ForceWidth(AValue); end; procedure TcxTreeListBand.SetExpandable(AValue: TcxTreeListBandExpandable); begin if AValue <> FExpandable then begin FExpandable := AValue; LayoutChanged; end; end; procedure TcxTreeListBand.SetFixedKind(AValue: TcxTreeListBandFixedKind); var I: Integer; begin if AValue <> FixedKind then begin FFixedKind := AValue; TreeList.BeginUpdate; try for I := 0 to ChildBandCount - 1 do ChildBands[I].FixedKind := AValue; if not IsRoot and (FFixedKind <> ParentBand.FixedKind) then Position.BandIndex := -1; finally TreeList.EndUpdate; end; end; end; procedure TcxTreeListBand.SetMinWidth(AValue: Integer); begin if AValue <> FMinWidth then begin FMinWidth := AValue; LayoutChanged; end; end; procedure TcxTreeListBand.SetOptions(AValue: TcxTreeListBandOptions); begin FOptions.Assign(AValue); end; procedure TcxTreeListBand.SetPosition(AValue: TcxTreeListBandPosition); begin FPosition.Assign(AValue); end; procedure TcxTreeListBand.SetRootIndex(AValue: Integer); begin if not IsRoot or TreeList.IsDestroying then Exit; AValue := Max(0, Min(AValue, Bands.RootItemCount - 1)); if RootIndex <> AValue then Index := Bands.RootItems[AValue].Index; end; procedure TcxTreeListBand.SetStyles(AValue: TcxTreeListBandStyles); begin FStyles.Assign(AValue); end; procedure TcxTreeListBand.SetVisibleColumn( AIndex: Integer; AValue: TcxTreeListColumn); begin VisibleColumns[AIndex].Assign(AValue); end; procedure TcxTreeListBand.SetVisible(AValue: Boolean); begin if AValue <> FVisible then begin FVisible := AValue; TreeList.ClearCalculatedWidths; LayoutChanged; end; end; procedure TcxTreeListBand.SetWidth(AValue: Integer); begin if AValue < 0 then Exit; if AValue > 0 then AValue := Max(AValue, ActualMinWidth); if AValue <> FWidth then begin FWidth := AValue; FCalculatedWidth := AValue; AdjustSubItems; if ActuallyVisible then TreeList.LayoutChanged; end; end; { TcxTreeListBands } constructor TcxTreeListBands.Create(AOwner: TcxCustomTreeList); begin inherited Create(AOwner.GetBandItemClass); FTreeList := AOwner; FRootItems := TList.Create; FVisibleItems := TList.Create; FVisibleRootItems := TList.Create; FBottomItems := TList.Create; end; destructor TcxTreeListBands.Destroy; begin FBottomItems.Free; FVisibleRootItems.Free; FVisibleItems.Free; FRootItems.Free; inherited Destroy; end; procedure TcxTreeListBands.Assign(ASource: TPersistent); var I: Integer; begin if ASource is TcxTreeListBand then begin TreeList.BeginUpdate; try TreeList.SaveItemsPosition; for I := 0 to TcxTreeListBands(ASource).Count - 1 do Add.Assign(TcxTreeListBands(ASource)[I]); TreeList.AssignItemsPosition; finally TreeList.EndUpdate; end; end else inherited Assign(ASource); end; function TcxTreeListBands.Add: TcxTreeListBand; begin BeginUpdate; try Result := TcxTreeListBand(inherited Add); finally EndUpdate; end; 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; function TcxTreeListBands.VisibleIndexOf(ABand: TcxTreeListBand): Integer; begin Result := FVisibleItems.IndexOf(ABand); end; function TcxTreeListBands.PopulateVisibleChildren( ABand: TcxTreeListBand): Integer; var I: Integer; begin Result := 0; if not ABand.Visible then Exit; Inc(Result); FVisibleItems.Add(ABand); if ABand.FixedKind = tlbfLeft then Inc(FVisibleLeftFixedCount) else if ABand.FixedKind = tlbfRight then Inc(FVisibleRightFixedCount); for I := 0 to ABand.ChildBandCount - 1 do Inc(Result, PopulateVisibleChildren(ABand.ChildBands[I])); if Result = 1 then begin FBottomItems.Add(ABand); FLineCount := Max(FLineCount, ABand.Level + 1); end; end; procedure TcxTreeListBands.RefreshInformation; var I: Integer; ABand: TcxTreeListBand; begin FRootItems.Clear; FBottomItems.Clear; FVisibleItems.Clear; FVisibleRootItems.Clear; TreeList.FVisibleColumns.Clear; FLineCount := 0; FColumnsLineCount := 0; FVisibleLeftFixedCount := 0; FVisibleRightFixedCount := 0; FVisibleRootLeftFixedCount := 0; FVisibleRootRightFixedCount := 0; FExpandableBand := nil; if Count = 0 then Exit; for I := 0 to Count - 1 do begin ABand := Items[I]; ABand.FLineCount := 0; if ABand.IsRoot then begin FRootItems.Add(ABand); if ABand.ActuallyVisible then begin if ABand.FixedKind = tlbfLeft then Inc(FVisibleRootLeftFixedCount) else if ABand.FixedKind = tlbfRight then Inc(FVisibleRootRightFixedCount); FVisibleRootItems.Add(ABand); end; end; end; FVisibleRootItems.Sort(@cxCompareBands); for I := 0 to VisibleRootItemCount - 1 do PopulateVisibleChildren(VisibleRootItems[I]); FVisibleItems.Sort(@cxCompareBands); FColumnsLineCount := Byte(BottomItemCount > 0); for I := 0 to BottomItemCount - 1 do with BottomItems[I] do begin CalculateLineCount(Self.FLineCount); CheckExpandable(FExpandableBand); FColumnsLineCount := Max(FColumnsLineCount, BandRows.LineCount); end; if CanExpandableLeftMostOnly and (FExpandableBand <> nil) then FExpandableBand := BottomItems[0]; end; procedure TcxTreeListBands.Adjust( ABands: TList = nil; AWidth: Integer = 0); var I: Integer; AAutoWidth: TcxAutoWidthObject; begin if ABands = nil then begin ABands := FVisibleRootItems; AWidth := TreeList.AvailableContentWidth; ClearCalculatedWidths; RefreshInformation; end; if ABands.Count = 0 then Exit; for I := 0 to ABands.Count - 1 do TcxTreeListBand(ABands[I]).AdjustSubItems; if (ABands <> FVisibleRootItems) or TreeList.OptionsView.ColumnAutoWidth then begin AAutoWidth := TcxAutoWidthObject.Create(ABands.Count); try AAutoWidth.AvailableWidth := AWidth; for I := 0 to ABands.Count - 1 do TcxTreeListBand(ABands[I]).InitAutoWidthItem(AAutoWidth.AddItem); AAutoWidth.Calculate; for I := 0 to ABands.Count - 1 do TcxTreeListBand(ABands[I]).CalculatedWidth := AAutoWidth.Items[I].AutoWidth; finally AAutoWidth.Free; end; end; end; procedure TcxTreeListBands.AssignColumnsWidth; var I: Integer; begin for I := 0 to Count - 1 do Items[I].AssignColumnsWidth; TreeList.ClearCalculatedWidths; end; procedure TcxTreeListBands.AssignRootItemWidths; var I: Integer; begin for I := 0 to RootItemCount - 1 do RootItems[I].AssignWidth; end; function TcxTreeListBands.CanExpandableLeftMostOnly: Boolean; begin Result := TreeList.OptionsView.IsCategorizedPaint or TreeList.Preview.Active; end; procedure TcxTreeListBands.ClearCalculatedWidths; var I: Integer; begin for I := 0 to Count - 1 do Items[I].FCalculatedWidth := 0; end; function TcxTreeListBands.GetFirstVisibleIndex( AFixedKind: TcxTreeListBandFixedKind): Integer; begin case AFixedKind of tlbfNone: Result := VisibleLeftFixedCount; tlbfRight: Result := VisibleItemCount - VisibleRightFixedCount; else Result := 0; end end; function TcxTreeListBands.GetFirstVisibleRootIndex( AFixedKind: TcxTreeListBandFixedKind): Integer; begin case AFixedKind of tlbfNone: Result := VisibleRootLeftFixedCount; tlbfRight: Result := VisibleRootItemCount - VisibleRootRightFixedCount; else Result := 0; end; end; function TcxTreeListBands.GetLastVisibleIndex( AFixedKind: TcxTreeListBandFixedKind): Integer; begin case AFixedKind of tlbfLeft: Result := GetFirstVisibleIndex(tlbfNone) - 1; tlbfNone: Result := GetFirstVisibleIndex(tlbfRight) - 1; else Result := VisibleItemCount - 1; end; end; function TcxTreeListBands.GetLastVisibleRootIndex( AFixedKind: TcxTreeListBandFixedKind): Integer; begin case AFixedKind of tlbfLeft: Result := GetFirstVisibleRootIndex(tlbfNone) - 1; tlbfNone: Result := GetFirstVisibleRootIndex(tlbfRight) - 1; else Result := VisibleRootItemCount - 1; end; end; function TcxTreeListBands.GetVisibleCountByKind( AFixedKind: TcxTreeListBandFixedKind): Integer; begin Result := FVisibleLeftFixedCount; case AFixedKind of tlbfNone: Result := VisibleItemCount - FVisibleRightFixedCount - Result; tlbfRight: Result := FVisibleRightFixedCount; end; end; function TcxTreeListBands.GetOwner: TPersistent; begin Result := FTreeList; end; procedure TcxTreeListBands.Update(Item: TCollectionItem); begin inherited Update(Item); if not TreeList.IsLocked then TreeList.LayoutChanged; end; procedure TcxTreeListBands.Notify( Item: TCollectionItem; Action: TCollectionNotification); begin if (Action = cnExtracting) and (TreeList <> nil) then TcxTreeListBand(Item).RemoveColumns; inherited Notify(Item, Action); end; // 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.GetBottomItem(AIndex: Integer): TcxTreeListBand; begin Result := TcxTreeListBand(FBottomItems[AIndex]); end; function TcxTreeListBands.GetBottomItemCount: Integer; begin Result := FBottomItems.Count; end; function TcxTreeListBands.GetFirstVisibleBand: TcxTreeListBand; begin if VisibleItemCount > 0 then Result := VisibleItems[0] else Result := nil; end; function TcxTreeListBands.GetItem(AIndex: Integer): TcxTreeListBand; begin Result := TcxTreeListBand(inherited GetItem(AIndex)); end; function TcxTreeListBands.GetLastVisibleBand: TcxTreeListBand; begin if VisibleItemCount > 0 then Result := VisibleItems[VisibleItemCount - 1] else Result := nil; end; function TcxTreeListBands.GetRootItemCount: Integer; begin Result := FRootItems.Count; end; function TcxTreeListBands.GetRootItem(AIndex: Integer): TcxTreeListBand; begin Result := TcxTreeListBand(FRootItems[AIndex]); end; function TcxTreeListBands.GetVisibleItem(AIndex: Integer): TcxTreeListBand; begin Result := TcxTreeListBand(FVisibleItems[AIndex]); end; function TcxTreeListBands.GetVisibleItemCount: Integer; begin Result := FVisibleItems.Count; end; function TcxTreeListBands.GetVisibleRootItem(AIndex: Integer): TcxTreeListBand; begin Result := TcxTreeListBand(FVisibleRootItems[AIndex]) end; function TcxTreeListBands.GetVisibleRootItemCount: Integer; begin Result := FVisibleRootItems.Count; end; procedure TcxTreeListBands.SetItem(AIndex: Integer; AValue: TcxTreeListBand); begin Items[AIndex].Assign(AValue); end; { TcxTreeListBandRow } constructor TcxTreeListBandRow.Create(AOwner: TcxTreeListBandRows); begin FBandRows := AOwner; FItems := TList.Create; FVisibleItems := TList.Create; end; destructor TcxTreeListBandRow.Destroy; begin FreeAndNil(FVisibleItems); FreeAndNil(FItems); inherited Destroy; end; function TcxTreeListBandRow.IndexOf(AColumn: TcxTreeListColumn): Integer; begin Result := FItems.IndexOf(AColumn); end; procedure TcxTreeListBandRow.AdjustColumns; var I: Integer; AAutoWidth: TcxAutoWidthObject; begin if Count = 0 then Exit; AAutoWidth := TcxAutoWidthObject.Create(VisibleItemCount); try AAutoWidth.AvailableWidth := Band.CalculatedWidth; for I := 0 to VisibleItemCount - 1 do VisibleItems[I].InitAutoWidthItem(AAutoWidth.AddItem); AAutoWidth.Calculate; for I := 0 to VisibleItemCount - 1 do VisibleItems[I].FCalculatedWidth := AAutoWidth.Items[I].AutoWidth; finally AAutoWidth.Free; end; end; procedure TcxTreeListBandRow.AssignColumnsWidth; var I: Integer; begin for I := 0 to Count - 1 do if Items[I].DisplayWidth <> 0 then Items[I].FWidth := Items[I].DisplayWidth; end; procedure TcxTreeListBandRow.CheckEmpty; begin BandRows.CheckRowEmpty(Index); end; procedure TcxTreeListBandRow.Refresh; var I: Integer; AColumn: TcxTreeListColumn; begin FVisibleItems.Clear; FLineOffset := 0; FLineCount := 0; FMinWidth := 0; FWidth := 0; for I := 0 to Count - 1 do begin AColumn := Items[I]; if AColumn.Visible and not AColumn.IsPreview then begin AColumn.Position.FVisibleColIndex := FVisibleItems.Add(AColumn); FLineCount := Max(FLineCount, AColumn.Position.LineCount); Band.FHasEmptyArea := Band.FHasEmptyArea or ((FLineCount <> 0) and (FLineCount <> AColumn.Position.LineCount)); Inc(FWidth, AColumn.Width); Inc(FMinWidth, AColumn.MinWidth); end else AColumn.Position.FVisibleColIndex := -1; 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 if VisibleItemCount > 0 then Result := VisibleItems[0] else Result := nil; 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(AIndex: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(FItems[AIndex]) end; function TcxTreeListBandRow.GetVisibleIndex: Integer; begin Result := BandRows.FVisibleItems.IndexOf(Self); end; function TcxTreeListBandRow.GetVisibleItem(AIndex: Integer): TcxTreeListColumn; begin Result := TcxTreeListColumn(FVisibleItems[AIndex]); end; function TcxTreeListBandRow.GetVisibleItemCount: Integer; begin Result := FVisibleItems.Count; end; function TcxTreeListBandRow.GetLast: TcxTreeListColumn; begin if VisibleItemCount > 0 then Result := VisibleItems[VisibleItemCount - 1] else Result := nil; end; function TcxTreeListBandRow.GetTreeList: TcxCustomTreeList; begin Result := FBandRows.FBand.GetTreeList; end; { TcxTreeListBandRows } constructor TcxTreeListBandRows.Create(AOwner: TcxTreeListBand); begin FBand := AOwner; FItems := TcxObjectList.Create; FVisibleItems := TList.Create; end; destructor TcxTreeListBandRows.Destroy; begin FVisibleItems.Free; FreeAndNil(FItems); inherited Destroy; end; function TcxTreeListBandRows.Add: TcxTreeListBandRow; begin Result := TcxTreeListBandRow.Create(Self); FItems.Add(Result); end; function TcxTreeListBandRows.CheckRowIndex( ARowIndex: Integer): TcxTreeListBandRow; begin ARowIndex := Max(0, ARowIndex); if ARowIndex < Count then Result := Items[ARowIndex] else Result := Add; end; procedure TcxTreeListBandRows.CheckRowEmpty(ARowIndex: Integer); begin if (ARowIndex >= 0) and (ARowIndex < Count) and (Items[ARowIndex].Count = 0) then begin Items[ARowIndex].Free; FItems.Delete(ARowIndex); end; end; function TcxTreeListBandRows.Insert(AIndex: Integer): TcxTreeListBandRow; begin Result := TcxTreeListBandRow.Create(Self); FItems.Insert(AIndex, Result); end; procedure TcxTreeListBandRows.Refresh; var I: Integer; AItem: TcxTreeListBandRow; begin FRowMinWidth := 0; FRowMaxWidth := 0; FLineCount := 0; FVisibleItems.Clear; Band.HasEmptyArea := False; for I := 0 to Count - 1 do begin AItem := Items[I]; AItem.Refresh; if AItem.VisibleItemCount > 0 then begin FVisibleItems.Add(AItem); FRowMinWidth := Max(FRowMinWidth, AItem.MinWidth); FRowMaxWidth := Max(FRowMaxWidth, AItem.Width); AItem.FLineOffset := FLineCount; Inc(FLineCount, AItem.LineCount); Band.FVisibleColumns.Assign(AItem.FVisibleItems, laOr); end; end; 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.GetVisibleItemCount: Integer; begin Result := FVisibleItems.Count; end; function TcxTreeListBandRows.GetVisibleItem(AIndex: Integer): TcxTreeListBandRow; begin Result := TcxTreeListBandRow(FVisibleItems[AIndex]); end; { TcxTreeListNode } constructor TcxTreeListNode.Create(AOwner: TcxCustomTreeList); begin FTreeList := AOwner; FOriginalIndex := -1; FillChar(FImageIndexes, SizeOf(FImageIndexes), -1); Inc(TreeList.DataController.FNodesCount); State := [nsCollapsed]; end; destructor TcxTreeListNode.Destroy; begin TreeList.BeginUpdate; try if FViewData <> nil then FViewData.Node := nil; Dec(TreeList.DataController.FNodesCount); Include(State, nsDeleting); TreeList.AddChanges([tcStructure, tcData]); TreeList.DoDeletion(Self); if HasChildren and (Count > 0) then DeleteChildren; TreeList.DoDeleteNode(Self); TreeList.AddChanges([tcStructure]); InternalRemove(Self); finally TreeList.EndUpdate; inherited Destroy; end; end; procedure TcxTreeListNode.Assign(Source: TPersistent); var ANode: TcxTreeListNode; begin if Source is TcxTreeListNode then begin ANode := TcxTreeListNode(Source); Focused := ANode.Focused; HasChildren := ANode.HasChildren; AssignData(ANode); end else inherited Assign(Source); end; procedure TcxTreeListNode.AssignValues( const AValues: array of Variant); var I, K: Integer; begin K := 0; for I := Low(AValues) to High(AValues) do 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.CheckClick; const ANewState: array[Boolean, TcxCheckBoxState] of TcxCheckBoxState = ((cbsChecked, cbsUnchecked, cbsChecked), (cbsChecked, cbsGrayed, cbsUnchecked)); begin if not Enabled or not HasCheckbox or ((Parent.CheckGroupType = ncgRadioGroup) and Checked) then Exit; CheckState := ANewState[AllowGrayed, CheckState]; 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); var I: Integer; AList: TList; begin if not Assigned(ASortProc) and not TreeList.CanCompare and (Count > 1) then Exit; TreeList.BeginUpdate; try AList := TList.Create; try PopulateItems(AList); if not Assigned(ASortProc) then ASortProc := @cxCompareNodes; AList.Sort(@ASortProc); UpdateItems(AList); if ARecurse and (Count > 0) then begin for I := 0 to AList.Count - 1 do TcxTreeListNode(AList.List^[I]).CustomSort(ASortProc, ARecurse); end; finally AList.Free; end; finally TreeList.EndUpdate; end; 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 if nsInternalDelete in State then Include(FFirst.State, nsInternalDelete); Include(FFirst.State, nsDeleting); 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; begin Result := cxNullRect; if ViewData = nil then Exit; if AEntryOnly then Result := ViewData.GetRealBounds else Result := ViewData.GetRealContentBounds; Result := cxRectOffset(Result, ViewData.Origin); 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 or TreeList.IsCancelOperation then Exit; 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 TreeList.EndUpdate; end; end; function TcxTreeListNode.GetNextChild(ANode: TcxTreeListNode): TcxTreeListNode; begin if ANode <> nil then Result := TcxTreeListNode(ANode.FNext) else Result := nil; end; function TcxTreeListNode.GetFirstChild: TcxTreeListNode; begin Result := FFirst end; function TcxTreeListNode.GetFirstChildVisible: TcxTreeListNode; begin Result := FFirst; while (Result <> nil) and not Result.Visible do Result := Result.FNext; end; function TcxTreeListNode.GetLastChild: TcxTreeListNode; begin Result := FLast end; function TcxTreeListNode.GetLastChildVisible: TcxTreeListNode; begin Result := FLast; while (Result <> nil) and not Result.Visible do Result := Result.FPrev; end; function TcxTreeListNode.GetNext: TcxTreeListNode; var ANode: TcxTreeListNode; begin if not (nsInternalDelete in State) then LoadChildren; 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.GetNextSiblingVisible: TcxTreeListNode; begin Result := FNext; while (Result <> nil) and not Result.Visible do Result := Result.FNext; end; function TcxTreeListNode.GetPrev: TcxTreeListNode; begin Result := FPrev; if Result <> nil then Result := cxGetLatest(Result, False) else Result := Parent; if Result = TreeList.Root then Result := nil; end; function TcxTreeListNode.GetPrevSibling: TcxTreeListNode; begin Result := FPrev; end; function TcxTreeListNode.GetPrevSiblingVisible: TcxTreeListNode; begin Result := FPrev; while (Result <> nil) and not Result.Visible do Result := Result.FPrev; end; function TcxTreeListNode.GetPrevChild(ANode: TcxTreeListNode): TcxTreeListNode; begin if ANode <> nil then Result := TcxTreeListNode(ANode.FPrev) else Result := nil; end; function TcxTreeListNode.HasAsParent(ANode: TcxTreeListNode): Boolean; var AItem: TcxTreeListNode; begin Result := False; AItem := Parent; while (AItem <> nil) and not Result do begin Result := AItem = ANode; AItem := AItem.FParent; end; end; function TcxTreeListNode.IndexOf(ANode: TcxTreeListNode): Integer; begin if ANode.Parent = Self then Result := ANode.FIndex else Result := -1; end; function TcxTreeListNode.InsertChild( ABeforeNode: TcxTreeListNode): TcxTreeListNode; begin Result := TreeList.AddNode(nil, ABeforeNode, nil, tlamInsert); end; procedure TcxTreeListNode.Invalidate; begin if ViewData <> nil then TreeList.InvalidateRectEx(DisplayRect(false), False); end; function TcxTreeListNode.IsSibling(ANode: TcxTreeListNode): Boolean; begin Result := (ANode <> nil) and (ANode.FParent = FParent); end; procedure TcxTreeListNode.LoadChildren; begin if (Count <> 0) or not HasChildren or Expanded or TreeList.IsDestroying then Exit; TreeList.BeginUpdate; try TreeList.DoExpand(Self); finally if Count > 0 then TreeList.EndUpdate else TreeList.CancelUpdate; end; end; procedure TcxTreeListNode.MakeVisible; var ANode: TcxTreeListNode; begin 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); begin if FViewData = nil then Exit; ViewData.Update(True); end; function TcxTreeListNode.GetNextSiblingEx( ANode: TcxTreeListNode; AForward: Boolean): TcxTreeListNode; begin if AForward then Result := ANode.FNext else Result := ANode.FPrev; end; procedure TcxTreeListNode.AssignData(ASource: TcxTreeListNode); var I: Integer; begin State := ASource.State; CheckInfo := ASource.CheckInfo; if (ASource.Parent <> nil) and (Parent <> nil) then Parent.CheckInfo := Parent.CheckInfo + ASource.Parent.CheckInfo * [nciCheckGroup, nciRadioGroup]; for I := 0 to ASource.ValueCount - 1 do Values[I] := ASource.Values[I]; end; function TcxTreeListNode.GetFooterSummaryCount: Integer; begin if HasChildren then Result := Summary.GroupFooterSummaryCount else Result := 0; end; function TcxTreeListNode.GetFooterSummaryText(AIndex: Integer): string; begin Result := Summary.GroupFooterSummaryTexts[ Summary.GroupFooterSummaryItems[AIndex], Self]; end; function TcxTreeListNode.GetFooterSummaryValue(AIndex: Integer): Variant; begin cxError(not cxInRange(AIndex, 0, FooterSummaryCount - 1), SListIndexError, [AIndex]); Summary.CheckChanges; Result := FSummaryInfo[AIndex].Value; end; function TcxTreeListNode.GetInserting: Boolean; begin Result := TreeList.IsNodeInserting(Self); end; function TcxTreeListNode.GetIsFirstVisible: Boolean; begin Result := FVisibleIndex = 0; end; function TcxTreeListNode.GetIsLastVisible: Boolean; begin Result := (FVisibleIndex >= 0) and (FVisibleIndex = TreeList.AbsoluteVisibleCount - 1); end; function TcxTreeListNode.GetNextVisibleEx(IsPrev: Boolean): TcxTreeListNode; begin if IsPrev then Result := GetPrevVisible else Result := GetNextVisible; end; function TcxTreeListNode.GetOwner: TPersistent; begin Result := TreeList; end; procedure TcxTreeListNode.InternalFree; begin Include(State, nsInternalDelete); Free; end; procedure TcxTreeListNode.InitializeHandle; begin if FHandle = nil then FHandle := TreeList.DataController.AllocateRecord; end; function OldState2State(AState: Integer): TcxTreeListNodeStates; const tlnsHasChildren = $0004; tlnsCollapsed = $0010; begin Result := []; if AState and tlnsHasChildren = tlnsHasChildren then Include(Result, nsHasChildren); if AState and tlnsCollapsed = tlnsCollapsed then Include(Result, nsCollapsed); end; procedure TcxTreeListNode.ReadData(AStream: TStream; AVersion: Integer); var AOldState: Integer; begin if AVersion = 4 then begin AStream.ReadBuffer(AOldState, SizeOf(Integer)); State := OldState2State(AOldState); end else AStream.ReadBuffer(State, SizeOf(State)); if nsCheck in State then AStream.ReadBuffer(CheckInfo, SizeOf(CheckInfo)); if nsHeightAssigned in State then AStream.ReadBuffer(FHeight, SizeOf(Integer)); FCount := 0; if nsHasChildren in State then AStream.ReadBuffer(FCount, SizeOf(Integer)); end; procedure TcxTreeListNode.SetChildrenCheckState( AValue: TcxCheckBoxState; AExclude: TcxTreeListNode); var ANode: TcxTreeListNode; begin ANode := FLast; while ANode <> nil do begin if ANode <> AExclude then ANode.CheckState := AValue; ANode := ANode.FPrev; end; end; procedure TcxTreeListNode.WriteData(AStream: TStream); begin if FCount > 0 then Include(State, nsHasChildren); if CheckInfo <> [] then Include(State, nsCheck); AStream.WriteBuffer(State, SizeOf(State)); if nsCheck in State then AStream.WriteBuffer(CheckInfo, SizeOf(CheckInfo)); if nsHeightAssigned in State then AStream.WriteBuffer(FHeight, SizeOf(Integer)); if (FCount > 0) or (nsHasChildren in State) 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 if ViewData = nil then Result := cxEmptyRect else begin Result := cxRectSetTop(TreeList.ClientBounds, FViewData.Origin.Y + TreeList.ViewInfo.ColumnsRowCount * (TreeList.ViewInfo.DefaultCellHeight + cxTextOffset * 2) + TreeList.ViewInfo.GroupFooterHeight * ViewData.GroupFooterCount, TreeList.ClientHeight); end; end; function TcxTreeListNode.GetSizingIncrement( ADirection: TcxDragSizingDirection): Integer; begin Result := 1; end; function TcxTreeListNode.IsDynamicUpdate: Boolean; begin Result := TreeList.OptionsCustomizing.DynamicSizing; end; procedure TcxTreeListNode.PopulateItems(AList: TList); var I: Integer; ANode: TcxTreeListNode; begin I := 0; AList.Count := Count; ANode := FFirst; while ANode <> nil do begin AList.List^[I] := ANode; ANode := ANode.FNext; Inc(I); end; end; procedure TcxTreeListNode.SetSizeDelta( ADirection: TcxDragSizingDirection; ADelta: Integer); begin if ADelta = 0 then Exit; if TreeList.OptionsCustomizing.RowSizing then TreeList.DefaultRowHeight := Max(TreeList.ViewInfo.DefaultCellHeight, Max(TreeList.ViewInfo.DefaultCellHeight, TreeList.DefaultRowHeight) + ADelta) else begin if Height = 0 then Height := TreeList.ViewInfo.DefaultRowHeight * TreeList.ViewInfo.ColumnsRowCount; Height := Max(TreeList.ViewInfo.DefaultCellHeight * TreeList.ViewInfo.ColumnsRowCount, Height + ADelta); end; TreeList.Modified; end; procedure TcxTreeListNode.UpdateItems(AList: TList); var I, L: Integer; AItems: PPointerList; ANode: TcxTreeListNode; AChanged: Boolean; begin if Count = 0 then Exit; L := Count - 1; AItems := AList.List; AChanged := False; for I := 0 to L do begin ANode := TcxTreeListNode(AItems^[I]); AChanged := AChanged or (ANode.FIndex <> I); ANode.FIndex := I; if I > 0 then ANode.FPrev := AItems^[I - 1] else ANode.FPrev := nil; if I < L then ANode.FNext := AItems^[I + 1] else ANode.FNext := nil; end; FFirst := TcxTreeListNode(AItems^[0]); FLast := TcxTreeListNode(AItems^[L]); if AChanged then TreeList.StructureChanged; 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 <> TreeList.Root) do Result := Result.FParent; end; function TcxTreeListNode.GetAbsoluteIndex: Integer; begin Result := FAbsoluteIndex; end; function TcxTreeListNode.GetAllowGrayed: Boolean; begin Result := (nciAllowGrayed in CheckInfo) and ((Parent = nil) or (Parent.CheckGroupType <> ncgRadioGroup)); end; function TcxTreeListNode.GetChecked: Boolean; begin Result := (nciChecked in CheckInfo) or ((nciGrayed in CheckInfo) and (Parent <> nil) and Parent.IsRadioGroup); end; function TcxTreeListNode.GetCheckedCount: Integer; var ANode: TcxTreeListNode; begin Result := 0; ANode := FFirst; while ANode <> nil do begin if ANode.CheckState = cbsChecked then Inc(Result); ANode := ANode.FNext; end; end; function TcxTreeListNode.GetChildVisibleCount: Integer; var ANode: TcxTreeListNode; begin Result := 0; ANode := FFirst; while ANode <> nil do begin if not (nsHidden in ANode.State) then Inc(Result); ANode := ANode.FNext; end; end; function TcxTreeListNode.GetCheckGroupType: TcxTreeListNodeCheckGroupType; begin if nciCheckGroup in CheckInfo then Result := ncgCheckGroup else if nciRadioGroup in CheckInfo then Result := ncgRadioGroup else Result := ncgNone; end; function TcxTreeListNode.GetCheckState: TcxCheckBoxState; begin Result := cbsUnchecked; if nciGrayed in CheckInfo then Result := cbsGrayed else if nciChecked in CheckInfo then Result := cbsChecked; end; function TcxTreeListNode.GetEnabled: Boolean; begin Result := not (nsDisabled in State); end; function TcxTreeListNode.GetExpanded: Boolean; begin Result := (Count > 0) and (not (nsCollapsed in State) or (FParent = nil)); end; function TcxTreeListNode.GetFocused: Boolean; begin Result := TreeList.Controller.FocusedNode = Self; end; function TcxTreeListNode.GetGrayedCount: Integer; var ANode: TcxTreeListNode; begin Result := 0; ANode := FFirst; while ANode <> nil do begin if ANode.CheckState = cbsGrayed then Inc(Result); ANode := ANode.FNext; end; end; function TcxTreeListNode.GetHasCheckbox: Boolean; begin Result := TreeList.OptionsView.CheckGroups and (Parent <> nil) and (Parent.CheckGroupType <> ncgNone) end; function TcxTreeListNode.GetHasChildren: Boolean; begin Result := (nsHasChildren in State) or (ChildVisibleCount > 0); end; function TcxTreeListNode.GetHasVisibleChildren: Boolean; var ANode: TcxTreeListNode; begin Result := HasChildren and (Count = 0); if not HasChildren or (Count = 0) then Exit; ANode := FFirst; while not Result and (ANode <> nil) do begin Result := not (nsHidden in ANode.State); ANode := ANode.FNext; end; end; function TcxTreeListNode.GetIndex: Integer; begin if Parent <> nil then Parent.AdjustIndexes; Result := FIndex; end; function TcxTreeListNode.GetIsDeleting: Boolean; var ANode: TcxTreeListNode; begin Result := False; ANode := Self; while not Result and (ANode <> nil) do begin Result := nsDeleting in ANode.State; 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.GetIsHidden: Boolean; var ANode: TcxTreeListNode; begin ANode := Parent; Result := not Visible; while not Result and (ANode <> TreeList.Root) do begin Result := not ANode.Visible; ANode := ANode.Parent; end; end; function TcxTreeListNode.GetIsLast: Boolean; begin Result := (FParent = nil) or (FParent.FLast = Self); end; function TcxTreeListNode.GetIsPrinted: Boolean; begin Result := ViewData <> nil; end; function TcxTreeListNode.GetIsRadioGroup: Boolean; begin Result := CheckGroupType = ncgRadioGroup; end; function TcxTreeListNode.GetIsVisible: Boolean; var ANode: TcxTreeListNode; begin Result := FParent <> nil; ANode := Self; while Result and (ANode.FParent <> nil) and (ANode.FParent <> TreeList.Root) do begin Result := not (nsCollapsed in ANode.FParent.State); ANode := ANode.FParent; end; end; function TcxTreeListNode.GetItem(AIndex: Integer): TcxTreeListNode; begin cxError((AIndex < 0) or (AIndex >= FCount), cxGetResourceString(@scxIndexOutOfBounds), [AIndex]); if Parent <> nil then Parent.AdjustIndexes; if (FLast.Index shr 1) <= AIndex then begin Result := FLast; while Result.FIndex <> AIndex do Result := Result.FPrev; end else begin Result := FFirst; while Result.FIndex <> AIndex do Result := Result.FNext; end; 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.GetRoot: TcxTreeListNode; begin Result := Self; while Result.Parent <> nil do Result := Result.Parent; end; function TcxTreeListNode.GetSelected: Boolean; begin if TreeList.OptionsSelection.MultiSelect then Result := TreeList.SelectionList.IndexOf(Self) <> cxInvalidIndex else Result := Focused; end; function TcxTreeListNode.GetSummary: TcxTreeListSummary; begin Result := TreeList.Summary; end; function TcxTreeListNode.GetNextVisible: TcxTreeListNode; var I: Integer; begin Result := nil; for I := FAbsoluteIndex + 1 to TreeList.AbsoluteCount - 1 do if TcxTreeListNode(TreeList.FAbsoluteItems.List^[I]).VisibleIndex >= 0 then begin Result := TcxTreeListNode(TreeList.FAbsoluteItems.List^[I]); Break; end; end; function TcxTreeListNode.GetNodeImageIndex(AIndex: Integer): TImageIndex; begin Result := TreeList.DoGetNodeImageIndex(Self, TcxTreeListImageIndexType(AIndex)); end; function TcxTreeListNode.GetPrevVisible: TcxTreeListNode; var I: Integer; begin Result := nil; for I := FAbsoluteIndex - 1 downto 0 do if TcxTreeListNode(TreeList.FAbsoluteItems.List^[I]).VisibleIndex >= 0 then begin Result := TcxTreeListNode(TreeList.FAbsoluteItems.List^[I]); Break; end; end; function TcxTreeListNode.GetText(AIndex: Integer): string; begin Result := TreeList.Columns[AIndex].DisplayTexts[Self]; end; function TcxTreeListNode.GetValue(AIndex: Integer): Variant; begin Result := TreeList.DataController.GetNodeValue(Self, AIndex); end; function TcxTreeListNode.GetValueCount: Integer; begin Result := TreeList.ColumnCount; end; function TcxTreeListNode.GetVisible: Boolean; begin Result := not (nsHidden in State); end; function TcxTreeListNode.GetVisibleIndex: Integer; begin if IsVisible then Result := FVisibleIndex else Result := -1; end; procedure TcxTreeListNode.AdjustIndexes; var AIndex: Integer; ANode: TcxTreeListNode; begin if nsValidIndexes in State then Exit; AIndex := 0; ANode := FFirst; while ANode <> nil do begin ANode.FIndex := AIndex; ANode := ANode.FNext; Inc(AIndex); end; Include(State, nsValidIndexes); end; procedure TcxTreeListNode.InternalInsert(AValue: TcxTreeListNode); begin if FParent <> nil then InternalRemove(Self); FPrev := AValue.FPrev; if FPrev <> nil then FPrev.FNext := Self else AValue.FParent.FFirst := Self; FNext := AValue; if FNext <> nil then FNext.FPrev := Self else AValue.FParent.FLast := Self; AValue.FParent.SetParentFor(Self); end; procedure TcxTreeListNode.InternalRemove(AValue: TcxTreeListNode); begin if AValue.FParent <> nil then begin Exclude(AValue.FParent.State, nsValidIndexes); Dec(AValue.FParent.FCount); if AValue.FParent.FFirst = AValue then AValue.FParent.FFirst := AValue.FNext; if AValue.FParent.FLast = AValue then AValue.FParent.FLast := AValue.FPrev; if AValue.FParent.FCount = 0 then AValue.FParent.State := AValue.FParent.State - [nsHasChildren] + [nsCollapsed]; end; if AValue.FNext <> nil then AValue.FNext.FPrev := AValue.FPrev; if AValue.FPrev <> nil then AValue.FPrev.FNext := AValue.FNext; AValue.FPrev := nil; AValue.FNext := nil; AValue.FParent := nil; end; procedure TcxTreeListNode.SetAllowGrayed(AValue: Boolean); begin if AValue then Include(CheckInfo, nciAllowGrayed) else Exclude(CheckInfo, nciAllowGrayed); end; procedure TcxTreeListNode.SetChecked(AValue: Boolean); begin if AValue then CheckState := cbsChecked else CheckState := cbsUnchecked; end; procedure TcxTreeListNode.SetCheckGroupType( AValue: TcxTreeListNodeCheckGroupType); const AState: array[TcxTreeListNodeCheckGroupType] of TcxTreeListNodeCheckInfos = ([], [nciCheckGroup], [nciRadioGroup]); begin if AValue <> CheckGroupType then begin CheckInfo := CheckInfo - [nciCheckGroup, nciRadioGroup] + AState[AValue]; TreeList.LayoutChanged; end; end; procedure TcxTreeListNode.SetCheckState(AValue: TcxCheckBoxState); var ACheckedCount: Integer; const AState: array[TcxCheckBoxState] of TcxTreeListNodeCheckInfos = ([], [nciChecked], [nciGrayed]); AParentCheckState: array[Boolean] of TcxCheckBoxState = (cbsGrayed, cbsChecked); begin if AValue = CheckState then Exit; CheckInfo := CheckInfo - [nciChecked, nciGrayed] + AState[AValue] + [nciChangeCheck]; try if (CheckState in [cbsChecked, cbsUnchecked]) and HasChildren then begin LoadChildren; if not IsRadioGroup or (CheckState = cbsUnchecked) or (CheckedCount = 0) then SetChildrenCheckState(CheckState, nil); end; if Parent <> nil then begin if Parent.IsRadioGroup and Checked then Parent.SetChildrenCheckState(cbsUnchecked, Self); if not (nciChangeCheck in Parent.CheckInfo) then begin ACheckedCount := Parent.CheckedCount; if (ACheckedCount = 0) and (Parent.GrayedCount = 0) then Parent.CheckState := cbsUnchecked else Parent.CheckState := AParentCheckState[(ACheckedCount = Parent.Count) or ((ACheckedCount > 0) and Parent.IsRadioGroup)]; end; end; finally CheckInfo := CheckInfo - [nciChangeCheck]; if (Parent <> nil) and (Parent.CheckGroupType <> ncgNone) then Repaint(True); TreeList.DoNodeCheckChanged(Self, CheckState); end; end; procedure TcxTreeListNode.SetEnabled(AValue: Boolean); begin if AValue then Exclude(State, nsDisabled) else Include(State, nsDisabled); TreeList.LayoutChanged; end; procedure TcxTreeListNode.SetExpanded(AValue: Boolean); var AExpanded: Boolean; begin if AValue <> Expanded then begin AExpanded := Expanded; if Parent = nil then Exit; TreeList.BeginUpdate; try TreeList.AddChanges([tcStructure]); if AValue then begin if not TreeList.DoCanNodeExpand(Self) then Exit; TreeList.DoExpand(Self); Exclude(State, nsCollapsed); TreeList.DoNodeExpanded(Self); end else begin if not TreeList.DoCanNodeCollapse(Self) then Exit; Include(State, nsCollapsed); TreeList.DoNodeCollapsed(Self); end; if AExpanded <> Expanded then TreeList.StructureChanged; finally TreeList.EndUpdate; end end; end; procedure TcxTreeListNode.SetFirst(AValue: TcxTreeListNode); begin InternalRemove(AValue); if FFirst <> nil then begin AValue.FNext := FFirst; FFirst.FPrev := AValue; end else FLast := AValue; FFirst := AValue; SetParentFor(AValue, False); end; procedure TcxTreeListNode.SetFocused(AValue: Boolean); begin if AValue <> Focused then begin TreeList.Controller.FocusedNode := Self; TreeList.ViewInfo.UpdateSelection; end; end; procedure TcxTreeListNode.SetFooterSummaryValue(AIndex: Integer; AValue: Variant); begin cxError(not cxInRange(AIndex, 0, FooterSummaryCount - 1), SListIndexError, [AIndex]); FSummaryInfo[AIndex].Value := AValue; end; procedure TcxTreeListNode.SetHasChildren(AValue: Boolean); begin if HasChildren <> AValue then begin if AValue then Include(State, nsHasChildren) else if FCount = 0 then Exclude(State, nsHasChildren); TreeList.DoNodeChanged(Self, nil); end; end; procedure TcxTreeListNode.SetHeight(AValue: Integer); begin AValue := Max(0, AValue); if AValue <> FHeight then begin FHeight := AValue; if FHeight = 0 then Exclude(State, nsHeightAssigned) else Include(State, nsHeightAssigned); TreeList.LayoutChanged; end; end; procedure TcxTreeListNode.SetItem(AIndex: Integer; AValue: TcxTreeListNode); begin GetItem(AIndex).Assign(AValue); end; procedure TcxTreeListNode.SetLast(AValue: TcxTreeListNode); begin InternalRemove(AValue); if FLast <> nil then begin AValue.FPrev := FLast; FLast.FNext := AValue; end else FFirst := AValue; FLast := AValue; SetParentFor(AValue, False); end; procedure TcxTreeListNode.SetNodeImageIndex( AIndex: Integer; AValue: TImageIndex); begin if FImageIndexes[TcxTreeListImageIndexType(AIndex)] <> AValue then begin FImageIndexes[TcxTreeListImageIndexType(AIndex)] := AValue; TreeList.DoNodeChanged(Self, nil); end; end; procedure TcxTreeListNode.SetParentFor( AValue: TcxTreeListNode; AValidateIndexes: Boolean = True); begin AValue.FParent := Self; Inc(FCount); if AValidateIndexes then Exclude(State, nsValidIndexes); TreeList.DoNodeChanged(AValue, nil); end; procedure TcxTreeListNode.SetText(AIndex: Integer; const AValue: string); begin SetValue(AIndex, AValue); end; procedure TcxTreeListNode.SetSelected(AValue: Boolean); begin if Selected <> AValue then try if not AValue then begin TreeList.SelectionList.Remove(Self); TreeList.DoSelectionChanged; end else TreeList.Select(Self); finally TreeList.ViewInfo.UpdateSelection; end; end; procedure TcxTreeListNode.SetValue(AIndex: Integer; const AValue: Variant); begin if Focused and (TreeList.DataController.EditingNode <> nil) then TreeList.DataController.SetEditValue(AIndex, AValue, evsValue) else TreeList.DataController.SetNodeValue(Self, AIndex, AValue); end; procedure TcxTreeListNode.SetVisible(AValue: Boolean); begin if AValue <> Visible then begin if not AValue then Include(State, nsHidden) else Exclude(State, nsHidden); TreeList.DoNodeChanged(Self, nil); end; end; { TcxTreeListRootNode } function TcxTreeListRootNode.GetFooterSummaryCount: Integer; begin Result := Summary.FooterSummaryCount; end; function TcxTreeListRootNode.GetFooterSummaryText( AIndex: Integer): string; begin Result := Summary.FooterSummaryTexts[ Summary.FooterSummaryItems[AIndex]]; end; procedure TcxTreeListRootNode.InitializeHandle; begin FHandle := nil; end; { TcxUnboundTreeListNode } constructor TcxUnboundTreeListNode.Create(AOwner: TcxCustomTreeList); 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; AVersion: Integer); begin AStream.ReadBuffer(FHandle, SizeOf(Integer)); inherited ReadData(AStream, AVersion); if AVersion = 4 then AStream.ReadBuffer(FImageIndexes, SizeOf(Integer) * 3) else AStream.ReadBuffer(FImageIndexes, SizeOf(FImageIndexes)); end; procedure TcxUnboundTreeListNode.WriteData(AStream: TStream); begin AStream.WriteBuffer(FHandle, SizeOf(Integer)); inherited WriteData(AStream); AStream.WriteBuffer(FImageIndexes, SizeOf(FImageIndexes)) end; { TcxTreeListItemsCustomizeListBox } constructor TcxTreeListItemsCustomizeListBox.CreateEx(AOwner: TComponent; ATreeList: TcxCustomTreeList; AParent: TWinControl); begin inherited Create(AOwner); FTreeList := ATreeList; Align := alClient; Parent := AParent; Color := clBtnFace; Style.HotTrack := False; Style.LookAndFeel.MasterLookAndFeel := TreeList.LookAndFeel; Style.TransparentBorder := False; ParentFont := True; OnMeasureItem := MeasureItem; InnerListBox.OnDrawItem := DoDrawItemEx; OnDrawItem := DoDrawItem; ListStyle := lbOwnerDrawVariable; ItemHeight := GetItemHeight(0); FHeaders := TcxObjectList.Create; RefreshList; end; destructor TcxTreeListItemsCustomizeListBox.Destroy; begin FreeAndNil(FHeaders); inherited Destroy; end; procedure TcxTreeListItemsCustomizeListBox.AddItem( ACaption: TcxTreeListCaption); var ACell: TcxTreeListHeaderCellViewInfo; begin ACell := CreateCell; ACell.Initialize(ACaption); Items.AddObject(ACaption.Text, ACell); FHeaders.Add(ACell); end; procedure TcxTreeListItemsCustomizeListBox.DblClick; var AIndex: Integer; begin AIndex := ItemAtPos(ScreenToClient(GetMouseCursorPos), True); if AIndex >= 0 then begin FinishDragAndDrop(False); MakeItemVisible(Headers[AIndex]); end; end; procedure TcxTreeListItemsCustomizeListBox.DoDrawItem(AControl: TcxListBox; ACanvas: TcxCanvas; AIndex: Integer; ARect: TRect; AState: TOwnerDrawState); var ASaveState: TcxButtonState; begin ASaveState := Headers[AIndex].State; try if [odFocused, odSelected] * AState <> [] then Headers[AIndex].FState := cxbsPressed; Headers[AIndex].Draw(ACanvas); SelectClipRgn(ACanvas.Handle, 0); finally Headers[AIndex].FState := ASaveState; end; end; procedure TcxTreeListItemsCustomizeListBox.DoDrawItemEx(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin end; function TcxTreeListItemsCustomizeListBox.GetItemHeight(AItem: Integer): Integer; begin Result := Painter.HeaderHeight(cxTextHeight(Font)); end; function TcxTreeListItemsCustomizeListBox.GetOrigin(AHeader: TcxTreeListHeaderCellViewInfo): TPoint; begin Result := ClientToScreen(AHeader.BoundsRect.TopLeft); end; procedure TcxTreeListItemsCustomizeListBox.MeasureItem(AControl: TcxListBox; Index: Integer; var Height: Integer); begin Height := GetItemHeight(Index); end; procedure TcxTreeListItemsCustomizeListBox.Paint; begin with Painter do begin DrawBorder(Canvas, ClientRect); IntersectClipRect(Handle, BorderSize, BorderSize, ClientWidth - BorderSize, ClientHeight - BorderSize); inherited Paint; end; end; procedure TcxTreeListItemsCustomizeListBox.RefreshList; begin if csDestroying in ComponentState then Exit; Items.BeginUpdate; try Clear; FHeaders.Clear; PopulateItems; Resize; finally Items.EndUpdate; end; end; procedure TcxTreeListItemsCustomizeListBox.Resize; var I: Integer; begin inherited Resize; for I := 0 to Count - 1 do Headers[I].SetBounds(Rect(0, I * ItemHeight, ClientWidth - Painter.BorderSize * 2, (I + 1) * ItemHeight), ClientRect); Invalidate; end; function TcxTreeListItemsCustomizeListBox.StartDragAndDrop( const P: TPoint): Boolean; var AIndex: Integer; begin AIndex := ItemAtPos(P, True); Result := AIndex >= 0; if Result then TreeList.Controller.DragItem := Headers[AIndex]; end; function TcxTreeListItemsCustomizeListBox.GetHeader( AIndex: Integer): TcxTreeListHeaderCellViewInfo; begin Result := FHeaders[AIndex] as TcxTreeListHeaderCellViewInfo; end; function TcxTreeListItemsCustomizeListBox.GetPainter: TcxCustomLookAndFeelPainterClass; begin Result := TreeList.LookAndFeel.Painter; end; { TcxTreeListColumnsCustomizeListBox } function TcxTreeListColumnsCustomizeListBox.CreateCell: TcxTreeListHeaderCellViewInfo; begin Result := TcxTreeListColumnHeaderCellViewInfo.CreateEx(TreeList, ClientRect, ClientRect); end; function TcxTreeListColumnsCustomizeListBox.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := TcxTreeListDragAndDropColumnObject; end; procedure TcxTreeListColumnsCustomizeListBox.MakeItemVisible( AHeader: TcxTreeListHeaderCellViewInfo); var ABand: TcxTreeListBand; begin ABand := TcxTreeListColumnHeaderCellViewInfo(AHeader).Band; if (ABand <> nil) and ABand.ActuallyVisible then TcxTreeListColumnHeaderCellViewInfo(AHeader).Column.Visible := True; end; procedure TcxTreeListColumnsCustomizeListBox.PopulateItems; var I: Integer; begin for I := 0 to TreeList.ColumnCount - 1 do if not TreeList.Columns[I].ActuallyVisible then AddItem(TreeList.Columns[I].Caption); end; { TcxTreeListBandsCustomizeListBox } function TcxTreeListBandsCustomizeListBox.CreateCell: TcxTreeListHeaderCellViewInfo; begin Result := TcxTreeListBandHeaderCellViewInfo.CreateEx( TreeList, ClientRect, ClientRect); end; function TcxTreeListBandsCustomizeListBox.GetDragAndDropObjectClass: TcxDragAndDropObjectClass; begin Result := TcxTreeListDragAndDropBandObject; end; procedure TcxTreeListBandsCustomizeListBox.MakeItemVisible( AHeader: TcxTreeListHeaderCellViewInfo); begin with TcxTreeListBandHeaderCellViewInfo(AHeader).Band do begin if (ParentBand = nil) or ParentBand.ActuallyVisible then Visible := True; end; end; procedure TcxTreeListBandsCustomizeListBox.PopulateItems; var I: Integer; begin for I := 0 to TreeList.Bands.Count - 1 do if not TreeList.Bands[I].ActuallyVisible then AddItem(TreeList.Bands[I].Caption); end; { TcxTreeListCustomizationForm } constructor TcxTreeListCustomizationForm.CreateEx(AOwner: TcxTreeListCustomizing); begin CreateNew(nil); FOwner := AOwner; FHookTimer := TcxTimer.Create(Self); FHookTimer.Enabled := False; FHookTimer.Interval := 10; FHookTimer.OnTimer := TimerHandler; Visible := False; end; destructor TcxTreeListCustomizationForm.Destroy; begin Customizing.FinishCustomizing(BoundsRect); FreeAndNil(FHookTimer); inherited Destroy; end; function TcxTreeListCustomizationForm.GetTreeList: TcxCustomTreeList; begin Result := Customizing.TreeList; end; procedure TcxTreeListCustomizationForm.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); with Params do begin Style := Style or WS_POPUP; if not TreeList.IsDestroying then WndParent := TreeList.Handle; end; end; procedure TcxTreeListCustomizationForm.FinishDragDrop( Sender: TcxTreeListItemsCustomizeListBox); begin FDragDropListBox := nil end; procedure TcxTreeListCustomizationForm.StartDragDrop( Sender: TcxTreeListItemsCustomizeListBox); begin FDragDropListBox := Sender; end; procedure TcxTreeListCustomizationForm.TimerHandler(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; if not Active and (DragDropListBox <> nil) then DragDropListBox.FinishDragAndDrop(False); end; { TcxTreeListCustomizing } constructor TcxTreeListCustomizing.Create(AOwner: TPersistent); begin inherited Create(AOwner); FRowCount := 10; FBounds := cxRect(-2000, -2000, -2000, -2000); TreeList.Designers.Add(Self); end; destructor TcxTreeListCustomizing.Destroy; begin TreeList.Designers.Remove(Self); Visible := False; 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.MakeBandPageVisible; begin Visible := True; if (FBandListBox <> nil) and (FBandListBox.Parent = FTabSheetBands) then FPageControl.ActivePage := FTabSheetBands; end; procedure TcxTreeListCustomizing.MakeColumnPageVisible; 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.CalculateSize(var AWidth, AHeight: Integer); begin AWidth := 200; AHeight := 300; end; procedure TcxTreeListCustomizing.Close(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; procedure TcxTreeListCustomizing.CreateControls; begin if not SimpleMode then begin FPageControl := TcxPageControl.Create(FForm); FPageControl.HotTrack := True; FPageControl.Focusable := False; FPageControl.LookAndFeel.MasterLookAndFeel := TreeList.LookAndFeel; FPageControl.Parent := FForm; FPageControl.BoundsRect := cxTextRect(FForm.ClientRect); FPageControl.Anchors := [akTop, akLeft, akRight, akBottom]; // bands FTabSheetBands := TcxTabSheet.Create(FForm); FTabSheetBands.Caption := cxGetResourceString(@scxBandsCaption); FTabSheetBands.PageControl := FPageControl; FTabSheetBands.TabVisible := True; FBandListBox := TcxTreeListBandsCustomizeListBox.CreateEx( FForm, TreeList, FTabSheetBands); // columns FTabSheetHeaders := TcxTabSheet.Create(FForm); FTabSheetHeaders.Caption := cxGetResourceString(@scxColumnsCaption); FTabSheetHeaders.PageControl := FPageControl; FTabSheetHeaders.Parent := FPageControl; FHeaderListBox := TcxTreeListColumnsCustomizeListBox.CreateEx( FForm, TreeList, FTabSheetHeaders); end else FHeaderListBox := TcxTreeListColumnsCustomizeListBox.CreateEx(FForm, TreeList, FForm); 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 Caption := cxGetResourceString(@scxCustomizeCaption); BorderStyle := bsSizeToolWin; BorderIcons := [biSystemMenu]; Font.Assign(TreeList.Font); { ClientWidth := SizeDelta.cx * cxTextWidth(Font, '0'); ClientHeight := (RowCount + 1) * FLineHeight; FLineHeight := cxTextHeight(Font) + SizeDelta.cy;} Color := clBtnFace; OnClose := Self.Close; for I := 0 to High(UnusedItems) do DeleteMenu(GetSystemMenu(Handle, False), UnusedItems[I, 0], UnusedItems[I, 1]); end; CreateControls; end; procedure TcxTreeListCustomizing.FinishCustomizing(const ABounds: TRect); begin FBounds := ABounds; FIsPositionAssigned := True; FBandListBox := nil; FHeaderListBox := nil; FPageControl := nil; FTabSheetBands := nil; FTabSheetHeaders := nil; FForm := nil; TreeList.DoCustomizationVisibleChanged; end; procedure TcxTreeListCustomizing.HideCustomizingForm; begin if Visible then begin FForm.HookTimer.Enabled := False; FreeAndNil(FForm); end; end; procedure TcxTreeListCustomizing.SetControlParent( AControl, AParent: TWinControl); begin AControl.Parent := AParent; if AParent <> nil then begin AControl.BoundsRect := AParent.ClientRect; Visible := True; end; end; procedure TcxTreeListCustomizing.ShowCustomizingForm; var W, H: Integer; begin if Visible then Exit; if FForm = nil then CreateCustomizingForm; if not IsPositionAssigned then begin if GetParentForm(TreeList) = nil then FBounds := TreeList.BoundsRect else FBounds := GetParentForm(TreeList).BoundsRect; CalculateSize(W, H); FBounds := cxRectSetRight(FBounds, FBounds.Right, W); FBounds := cxRectSetBottom(FBounds, FBounds.Bottom, H); end; FForm.BoundsRect := FBounds; FForm.Show; FForm.HookTimer.Enabled := True; TreeList.DoCustomizationVisibleChanged; end; procedure TcxTreeListCustomizing.ComponentModified; begin if Visible then begin if FHeaderListBox <> nil then FHeaderListBox.RefreshList; if FBandListBox <> nil then FBandListBox.RefreshList; end end; procedure TcxTreeListCustomizing.ComponentRemoved(Sender: TObject); begin 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.GetPosition: TPoint; begin if Visible then Result := Point(Form.Top, Form.Left) else Result := FBounds.TopLeft; end; function TcxTreeListCustomizing.GetTreeList: TcxCustomTreeList; begin Result := GetOwner as TcxCustomTreeList; end; function TcxTreeListCustomizing.GetIsSimpleMode: Boolean; begin Result := TreeList.OptionsView.SimpleCustomizeBox or not TreeList.OptionsView.Bands; end; function TcxTreeListCustomizing.GetVisible: Boolean; begin Result := (FForm <> nil) and FForm.Visible; end; procedure TcxTreeListCustomizing.SetPosition(const AValue: TPoint); begin FBounds.TopLeft := AValue; if Visible then begin Form.Left := AValue.X; Form.Top := AValue.Y; end; FIsPositionAssigned := True; end; procedure TcxTreeListCustomizing.SetRowCount(AValue: Integer); begin AValue := Max(AValue, 2); if AValue <> FRowCount then FRowCount := AValue; end; procedure TcxTreeListCustomizing.SetVisible(AValue: Boolean); begin if AValue then ShowCustomizingForm else HideCustomizingForm; end; { TcxTreeListCustomCellViewInfo } constructor TcxTreeListCustomCellViewInfo.CreateEx( ATreeList: TcxCustomTreeList; const ABounds, AVisibleRect: TRect); begin inherited Create(ATreeList); DisplayRect := ABounds; VisibleBounds := AVisibleRect; CheckClipping(DisplayRect, VisibleBounds); end; {procedure TcxTreeListCustomCellViewInfo.CheckClipping( const ADisplayRect, AAvailableRect: TRect); var R: TRect; begin if AAvailableRect.Right > ADisplayRect.Right then begin R := AAvailableRect; R.Right := ADisplayRect.Right; inherited CheckClipping(ADisplayRect, R); end else inherited CheckClipping(ADisplayRect, AAvailableRect); end;} procedure TcxTreeListCustomCellViewInfo.DoCalculate; begin CheckClipping(DisplayRect, VisibleBounds); end; procedure TcxTreeListCustomCellViewInfo.DoDraw(ACanvas: TcxCanvas); var P: TPoint; begin if not Visible then Exit; if not CellHasOrigin then ACanvas.FillRect(BoundsRect, ViewParams, Borders, BorderColor) else begin SetWindowOrgEx(ACanvas.Handle, 0, 0, @P); ACanvas.FillRect(cxRectOffset(BoundsRect, GetCellOrigin), ViewParams, Borders, BorderColor); SetWindowOrgEx(ACanvas.Handle, P.X, P.Y, nil); end; end; function TcxTreeListCustomCellViewInfo.CellHasOrigin: Boolean; begin Result := (FAttachNode <> nil) and (FAttachNode.FViewData <> nil); end; function TcxTreeListCustomCellViewInfo.GetClipRect: TRect; begin Result := ClipRect; if cxRectIsEmpty(DisplayRect) then begin Result := VisibleRect; if Result.Left < DisplayRect.Left then Result.Left := DisplayRect.Left; if Result.Right > DisplayRect.Right then Result.Right := DisplayRect.Right; end end; function TcxTreeListCustomCellViewInfo.GetCellOrigin: TPoint; begin if CellHasOrigin then Result := FAttachNode.ViewData.Origin else Result := cxNullPoint; end; function TcxTreeListCustomCellViewInfo.GetControl: TcxEditingControl; begin Result := TcxCustomTreeList(Owner); end; function TcxTreeListCustomCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; begin if CellHasOrigin then Result := Visible and PtInRect(cxRectOffset(ClipRect, GetCellOrigin), AHitTest.HitPoint) else Result := Visible and PtInRect(ClipRect, AHitTest.HitPoint); if not Result then Exit; if not VisibleInfoCalculated then DoCalculate; if AttachNode <> nil then begin HitTest.FHitNode := AttachNode; if Node <> nil then SetHitTestCodes([tlhc_HitAtNode]); end; TcxTreeListHitTest(AHitTest).HitTestItem := Self; end; procedure TcxTreeListCustomCellViewInfo.SetBounds( const ABounds, AVisibleBounds: TRect); begin CheckClipping(ABounds, AVisibleBounds); VisibleInfoCalculated := False; end; procedure TcxTreeListCustomCellViewInfo.SetHitTestCodes( const ACodes: array of Integer); var I: Integer; begin for I := Low(ACodes) to High(ACodes) do TreeList.HitTest.SetHitState(ACodes[I], True); end; function TcxTreeListCustomCellViewInfo.GetSelected: Boolean; begin Result := False; end; function TcxTreeListCustomCellViewInfo.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := cxE_NOINTERFACE; end; function TcxTreeListCustomCellViewInfo._AddRef: Integer; begin Result := -1; end; function TcxTreeListCustomCellViewInfo._Release: Integer; begin Result := -1; end; function TcxTreeListCustomCellViewInfo.GetExtPaintStyle: Boolean; begin Result := OptionsView.ExtPaintStyle; end; function TcxTreeListCustomCellViewInfo.GetHitTestController: TcxTreeListHitTest; begin Result := TreeList.HitTest; end; function TcxTreeListCustomCellViewInfo.GetOptionsView: TcxTreeListOptionsView; begin Result := TreeList.OptionsView; end; function TcxTreeListCustomCellViewInfo.GetStyles: TcxTreeListStyles; begin Result := TreeList.Styles; end; function TcxTreeListCustomCellViewInfo.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Owner); end; function TcxTreeListCustomCellViewInfo.GetVisibleRect: TRect; begin Result := VisibleBounds; end; { TcxTreeListBackgroundCellViewInfo } class function TcxTreeListBackgroundCellViewInfo.CustomDrawID: Integer; begin Result := cxtlBackgroundCell; end; function TcxTreeListBackgroundCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; begin Result := inherited GetHitTest(AHitTest); if Result then SetHitTestCodes([tlhc_HitAtBackground]); end; procedure TcxTreeListBackgroundCellViewInfo.Scroll(const DX, DY: Integer); begin end; { TcxTreeListFooterCellViewInfo } constructor TcxTreeListFooterCellViewInfo.CreateEx(ATreeList: TcxCustomTreeList; const ABounds, AVisibleRect: TRect); begin inherited CreateEx(ATreeList, ABounds, AVisibleRect); FBorders := cxBordersAll; end; class function TcxTreeListFooterCellViewInfo.CustomDrawID: Integer; begin Result := cxtlFooterCell; end; procedure TcxTreeListFooterCellViewInfo.DoCalculate; begin inherited DoCalculate; ItemViewParams := Styles.GetColumnFooterParams(Column, Node, GetItem); FHidden := FHidden or ((GetItem = nil) or not GetItem.Visible); end; procedure TcxTreeListFooterCellViewInfo.DoDraw(ACanvas: TcxCanvas); begin if Hidden then Exit; if not Transparent then Painter.DrawFooterCellContent(ACanvas, BoundsRect, AlignHorz, AlignVert, MultiLine, '', ViewParams.Font, ViewParams.TextColor, ViewParams.Color, DrawBackgroundHandler); DrawText(ACanvas); Painter.DrawFooterCellBorder(ACanvas, BoundsRect); if Selected then begin ACanvas.DrawFocusRect(cxRectInflate(DisplayRect, -1, -1)); ACanvas.DrawFocusRect(cxRectInflate(DisplayRect, -2, -2)); end; end; procedure TcxTreeListFooterCellViewInfo.DrawText(ACanvas: TcxCanvas); begin ACanvas.Brush.Style := bsClear; ACanvas.DrawTexT(FText, cxTextRect(BoundsRect), AlignHorz, AlignVert, MultiLine, ShowEndEllipsis); ACanvas.Brush.Style := bsSolid; end; function TcxTreeListFooterCellViewInfo.GetAlignHorz: TAlignment; begin Result := GetItem.FAlignHorz; end; function TcxTreeListFooterCellViewInfo.GetAlignVert: TcxAlignmentVert; begin Result := GetItem.FAlignVert; end; function TcxTreeListFooterCellViewInfo.GetItem: TcxTreeListSummaryItem; begin Result := nil; end; function TcxTreeListFooterCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; var R: TRect; begin Result := False; if not Visible then Exit; R := ClipRect; if AttachNode <> nil then R := cxRectOffset(R, AttachNode.ViewData.Origin); Result := PtInRect(cxRectInflate(R, cxTextOffset, cxTextOffset), AHitTest.HitPoint); if not Result then Exit; if not VisibleInfoCalculated then DoCalculate; HitTest.FHitNode := AttachNode; if AttachNode <> nil then SetHitTestCodes([tlhc_HitAtNode]); TcxTreeListHitTest(AHitTest).HitTestItem := Self; HitTest.FHitColumn := Column; SetHitTestCodes([tlhc_HitAtColumn]); if (Node = nil) or (Node.Parent = nil) then SetHitTestCodes([tlhc_HitAtFooterItem]) else SetHitTestCodes([tlhc_HitAtGroupFooterItem]); end; function TcxTreeListFooterCellViewInfo.GetMultiline: Boolean; begin Result := (Column.Position.LineCount > 1) and (GetItem <> nil) and GetItem.MultiLine; end; procedure TcxTreeListFooterCellViewInfo.Initialize( ANode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn); begin FAttachNode := AttachNode; FNode := ANode; FColumn := AColumn; FText := ''; end; procedure TcxTreeListFooterCellViewInfo.Scroll(const DX, DY: Integer); begin if Column.Position.Band.FixedKind <> tlbfNone then Exit; inherited Scroll(DX, 0); end; function TcxTreeListFooterCellViewInfo.GetOrigin: TPoint; begin Result := cxPointOffset(DisplayRect.TopLeft, GetCellOrigin); end; function TcxTreeListFooterCellViewInfo.IsNeedHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; var AFlags: Integer; AAccessibleTextBounds, ANeededTextBounds: TRect; begin AFlags := cxAlignTop or cxAlignLeft or cxDontPrint; if AIsMultiLine then AFlags := AFlags or cxWordBreak; ACanvas.Font := ViewParams.Font; AIsMultiLine := MultiLine; AAccessibleTextBounds := cxRectOffset(cxTextRect(BoundsRect), GetCellOrigin); ANeededTextBounds := AAccessibleTextBounds; AText := FText; ACanvas.TextExtent(AText, ANeededTextBounds, AFlags); Result := PtInRect(AAccessibleTextBounds, P) and not cxRectContain(AAccessibleTextBounds, ANeededTextBounds); ATextRect := ANeededTextBounds; IsNeedOffsetHint := False; end; procedure TcxTreeListFooterCellViewInfo.UpdateHotTrackState( const APoint: TPoint); begin end; function TcxTreeListFooterCellViewInfo.GetShowEndEllipsis: Boolean; begin Result := Column.Options.CellEndEllipsis; end; { TcxTreeListFooterSingleCellViewInfo } function TcxTreeListFooterSingleCellViewInfo.GetItem: TcxTreeListSummaryItem; begin Result := SummaryItem; end; function TcxTreeListFooterSingleCellViewInfo.GetSelected: Boolean; begin Result := TreeList.Controller.IsObjectSelected(GetItem); end; procedure TcxTreeListFooterSingleCellViewInfo.Initialize( ANode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn; ASummaryItem: TcxTreeListSummaryItem); begin inherited Initialize(ANode, AttachNode, AColumn); FSummaryItem := ASummaryItem; FText := Node.FooterSummaryTexts[GetItem.AbsoluteIndex]; end; { TcxTreeListFooterMultiItemsCellViewInfo } function TcxTreeListFooterMultiItemsCellViewInfo.CanDifferentStyles: Boolean; begin Result := True {Assigned(Styles.FOnGetColumnFooterStyle)} and (VisibleCount > 1); end; procedure TcxTreeListFooterMultiItemsCellViewInfo.DrawText(ACanvas: TcxCanvas); var R, R1: TRect; AText: string; AWidth, ACountInLine, I, J: Integer; begin if not CanDifferentStyles then inherited DrawText(ACanvas) else begin R := cxTextRect(DisplayRect); J := 0; FNeedShowHint := False; ACanvas.SaveClipRegion; try ACanvas.IntersectClipRect(R); FHintRect := R; R := cxRectSetHeight(R, cxTextHeight(ViewParams.Font) + cxTextOffset * 2); ACanvas.Font := ViewParams.Font; ACanvas.Brush.Style := bsClear; AWidth := 0; ACountInLine := 0; for I := 0 to SummaryItems.Count - 1 do begin if not SummaryItems[I].Visible then Continue; Inc(J); Inc(R.Left, AWidth); AText := Node.FooterSummaryTexts[SummaryItems[I].AbsoluteIndex]; if J < VisibleCount then AText := AText + ListSeparator; AWidth := cxTextWidth(ViewParams.Font, AText); if (ACountInLine = 0) or (cxRectWidth(R) >= AWidth) or not MultiLine then Inc(ACountInLine) else if (cxRectWidth(R) < AWidth) then begin R1 := cxRectSetTop(cxTextRect(DisplayRect), R.Bottom, cxRectHeight(R)); ACountInLine := 1; FNeedShowHint := FNeedShowHint or (R1.Bottom > cxTextRect(DisplayRect).Bottom); if FNeedShowHint then Inc(ACountInLine) else R := R1; end; FNeedShowHint := FNeedShowHint or ((R.Left + AWidth) > cxTextRect(DisplayRect).Right); ACanvas.Font.Color := Styles.GetColumnFooterParams(Column, Node, SummaryItems[I]).TextColor; ACanvas.Brush.Style := bsClear; ACanvas.DrawTexT(AText, R, AlignHorz, AlignVert, False, ShowEndEllipsis); ACanvas.Brush.Style := bsSolid; end; FHintRect.Bottom := R.Bottom; FHintRect.Right := R.Right; finally ACanvas.RestoreClipRegion; end; end; end; function TcxTreeListFooterMultiItemsCellViewInfo.GetAlignHorz: TAlignment; begin Result := inherited GetAlignHorz; if CanDifferentStyles and not Multiline then Result := taLeftJustify; end; function TcxTreeListFooterMultiItemsCellViewInfo.GetAlignVert: TcxAlignmentVert; begin Result := inherited GetAlignVert; if CanDifferentStyles then Result := vaTop; end; function TcxTreeListFooterMultiItemsCellViewInfo.GetItem: TcxTreeListSummaryItem; var I: Integer; begin Result := nil; for I := 0 to SummaryItems.Count - 1 do begin Result := SummaryItems[I]; if Result.Visible then Break; end; end; function TcxTreeListFooterMultiItemsCellViewInfo.GetSelected: Boolean; var I: Integer; begin Result := False; for I := 0 to SummaryItems.Count - 1 do if SummaryItems[I].Visible and TreeList.Controller.IsObjectSelected(SummaryItems[I]) then begin Result := True; Break; end; end; procedure TcxTreeListFooterMultiItemsCellViewInfo.Initialize( ADataNode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn; ASummaryItems: TcxTreeListSummaryItems); var I: Integer; begin inherited Initialize(ADataNode, AttachNode, AColumn); FSummaryItems := ASummaryItems; FVisibleCount := 0; for I := 0 to SummaryItems.Count - 1 do if SummaryItems[I].Visible then begin Inc(FVisibleCount); if FText <> '' then FText := FText + Separator; FText := FText + Node.FooterSummaryTexts[SummaryItems[I].AbsoluteIndex]; end; end; function TcxTreeListFooterMultiItemsCellViewInfo.IsNeedHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; begin if not CanDifferentStyles then Result := inherited IsNeedHint(ACanvas, P, AText, AIsMultiLine, ATextRect, IsNeedOffsetHint) else begin ACanvas.Font := ViewParams.Font; AIsMultiLine := MultiLine; Result := FNeedShowHint and PtInRect(cxRectOffset(FHintRect, GetCellOrigin), P); AText := FText; ATextRect := FHintRect; IsNeedOffsetHint := False; end; end; function TcxTreeListFooterMultiItemsCellViewInfo.GetSeparator: string; begin Result := ListSeparator; if Multiline then Result := CRLF; end; { TcxTreeListCustomHeaderCellViewInfo } constructor TcxTreeListCustomHeaderCellViewInfo.CreateEx( ATreeList: TcxCustomTreeList; const ABounds, AVisibleRect: TRect); begin inherited CreateEx(ATreeList, ABounds, AVisibleRect); FBorders := cxBordersAll; end; function TcxTreeListCustomHeaderCellViewInfo.CanNeighborFor( ACandidate: TcxTreeListHeaderCellViewInfo): Boolean; begin Result := not cxRectIsEmpty(ACandidate.DisplayRect) and not cxRectIsEmpty(DisplayRect); end; procedure TcxTreeListCustomHeaderCellViewInfo.CheckClipping( const ADisplayRect, AAvailableRect: TRect); begin inherited CheckClipping(ADisplayRect, AAvailableRect); ClipRect := cxRectInflate(ClipRect, BordersMargins); end; function TcxTreeListCustomHeaderCellViewInfo.CheckNeighbors( ACandidate: TcxTreeListHeaderCellViewInfo; AShift: Integer): Boolean; begin Result := False; if AShift = 0 then Exit; if BoundsRect.Right = ACandidate.BoundsRect.Left then begin Include(FNeighbors, nRight); Include(ACandidate.FNeighbors, nLeft); ACandidate.BordersMargins.Left := AShift; Result := True; end; if CanNeighborFor(ACandidate) and (BoundsRect.Bottom = ACandidate.BoundsRect.Top) then begin Include(FNeighbors, nBottom); Include(ACandidate.FNeighbors, nTop); ACandidate.BordersMargins.Top := AShift; Result := True; end; end; procedure TcxTreeListCustomHeaderCellViewInfo.Click; begin end; procedure TcxTreeListCustomHeaderCellViewInfo.DoCalculate; begin FTextBounds := cxTextRect(cxExcludeBorders(BoundsRect, Borders)); inherited DoCalculate; end; procedure TcxTreeListCustomHeaderCellViewInfo.DoDraw(ACanvas: TcxCanvas); var R: TRect; begin R := cxRectInflate(BoundsRect, BordersMargins); if ExtPaintStyle then Painter.DrawHeaderEx(ACanvas, R, TextBounds, Neighbors, Borders, State, GetAlignHorz, GetAlignVert, GetMultiline, GetShowEndEllipsis, GetText, ViewParams.Font, ViewParams.TextColor, ViewParams.Color, DrawBackgroundHandler) else Painter.DrawHeader(ACanvas, R, TextBounds, Neighbors, Borders, State, GetAlignHorz, GetAlignVert, GetMultiline, GetShowEndEllipsis, GetText, ViewParams.Font, ViewParams.TextColor, ViewParams.Color, DrawBackgroundHandler, IsLast) end; function TcxTreeListCustomHeaderCellViewInfo.GetAlignHorz: TAlignment; begin Result := taLeftJustify; end; function TcxTreeListCustomHeaderCellViewInfo.GetAlignVert: TcxAlignmentVert; begin Result := vaTop; end; function TcxTreeListCustomHeaderCellViewInfo.GetIsVisible: Boolean; begin Result := True; end; function TcxTreeListCustomHeaderCellViewInfo.GetMultiline: Boolean; begin Result := False; end; function TcxTreeListCustomHeaderCellViewInfo.GetShowEndEllipsis: Boolean; begin Result := False; end; function TcxTreeListCustomHeaderCellViewInfo.GetText: string; begin Result := ''; end; function TcxTreeListCustomHeaderCellViewInfo.GetOrigin: TPoint; begin Result := DisplayRect.TopLeft; end; function TcxTreeListCustomHeaderCellViewInfo.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 AText := GetText; try AFlags := cxAlignTop or cxAlignLeft or cxDontPrint; if AIsMultiLine then AFlags := AFlags or cxWordBreak; ACanvas.Font := ViewParams.Font; R := TextBounds; ACanvas.TextExtent(GetText, R, AFlags); AIsMultiLine := MultiLine; Result := PtInRect(TextBounds, P) and ((cxRectWidth(R) > cxRectWidth(TextBounds)) or (cxRectHeight(R) > cxRectHeight(TextBounds))); finally AText := GetText; ATextRect := R; IsNeedOffsetHint := False; end; end; procedure TcxTreeListCustomHeaderCellViewInfo.UpdateHotTrackState( const APoint: TPoint); begin if Pressed then Exit; if (TreeList.Controller.DragItem = nil) and PtInRect(GetClipRect, APoint) then State := cxbsHot else State := cxbsNormal; end; function TcxTreeListCustomHeaderCellViewInfo.GetHotTrack: Boolean; begin Result := State = cxbsHot; end; function TcxTreeListCustomHeaderCellViewInfo.GetPressed: Boolean; begin Result := State = cxbsPressed; end; procedure TcxTreeListCustomHeaderCellViewInfo.SetHotTrack(AValue: Boolean); begin if Pressed or not GetIsVisible then Exit; if AValue then State := cxbsHot else State := cxbsNormal; end; procedure TcxTreeListCustomHeaderCellViewInfo.SetPressed(AValue: Boolean); begin if (AValue = Pressed) or not GetIsVisible then Exit; if AValue then TreeList.Controller.PressedHeader := Self else TreeList.Controller.PressedHeader := nil; end; procedure TcxTreeListCustomHeaderCellViewInfo.SetState(AValue: TcxButtonState); begin if (State <> AValue) and GetIsVisible then begin FState := AValue; Invalidate; end; end; { TcxTreeListIndicatorCellViewInfo } destructor TcxTreeListIndicatorCellViewInfo.Destroy; begin if FSizingArea <> nil then begin TreeList.ViewInfo.HitTestCells.Remove(FSizingArea); FSizingArea.Free; end; inherited Destroy; end; class function TcxTreeListIndicatorCellViewInfo.CustomDrawID: Integer; begin Result := cxtlIndicatorCell; end; function TcxTreeListIndicatorCellViewInfo.ActualIndicatorKind: TcxIndicatorKind; begin Result := ikNone; if Node = nil then Exit; if Node.Focused then begin if Node.Selected and (TreeList.SelectionCount > 1) then Result := ikMultiArrow else Result := ikArrow; if TreeList.IsNodeEdited(Node) then Result := ikEdit else if TreeList.IsNodeInserting(Node) then Result := ikInsert end else if Node.Selected then Result := ikMultiDot; end; procedure TcxTreeListIndicatorCellViewInfo.DoCalculate; begin inherited DoCalculate; FKind := ActualIndicatorKind; case Position of tlipBands: ItemViewParams := TreeList.Styles.GetBandHeaderParams(nil); tlipColumns: ItemViewParams := TreeList.Styles.GetColumnHeaderParams(nil); tlipContent, tlipFooter: ItemViewParams := TreeList.Styles.GetIndicatorParams; end; end; procedure TcxTreeListIndicatorCellViewInfo.DoDraw(ACanvas: TcxCanvas); begin if Position = tlipContent then begin if ExtPaintStyle then Painter.DrawIndicatorItemEx(ACanvas, DisplayRect, Kind, ViewParams.Color, DrawBackgroundHandler) else Painter.DrawIndicatorItem(ACanvas, DisplayRect, Kind, ViewParams.Color, DrawBackgroundHandler); ACanvas.ExcludeClipRect(ClipRect); end else if Position = tlipFooter then Painter.DrawFooterPanel(ACanvas, DisplayRect, ViewParams, Borders) else begin inherited DoDraw(ACanvas); if (Position in [tlipBands, tlipColumns]) and IsQuickCustomizationEnabled then Painter.DrawIndicatorCustomizationMark(ACanvas, DisplayRect, ViewParams.TextColor); end; end; function TcxTreeListIndicatorCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; begin Result := inherited GetHitTest(AHitTest); if not Result then Exit; SetHitTestCodes([tlhc_HitAtIndicator]); case Position of tlipBands: if IsQuickCustomizationEnabled then SetHitTestCodes([tlhc_HitAtBandCustomizing]); tlipColumns: if IsQuickCustomizationEnabled then SetHitTestCodes([tlhc_HitAtColumnCustomizing]); tlipFooter: SetHitTestCodes([tlhc_HitAtFooter]); end; end; function TcxTreeListIndicatorCellViewInfo.GetPopup: TcxTreeListCustomizationPopup; begin if Position = tlipBands then Result := TreeList.Controller.BandsCustomizationPopup else Result := TreeList.Controller.ColumnsCustomizationPopup; end; procedure TcxTreeListIndicatorCellViewInfo.Initialize(ANode: TcxTreeListNode; APosition: TcxTreeListIndicatorPosition); begin FNode := ANode; FAttachNode := ANode; FPosition := APosition; FState := cxbsNormal; FPosition := APosition; end; function TcxTreeListIndicatorCellViewInfo.IsQuickCustomizationEnabled: Boolean; begin with TreeList.OptionsCustomizing do begin if Position = tlipBands then Result := BandsQuickCustomization and BandCustomizing else Result := ColumnsQuickCustomization and ColumnCustomizing; end; end; procedure TcxTreeListIndicatorCellViewInfo.Scroll(const DX, DY: Integer); begin inherited Scroll(0, DY); end; procedure TcxTreeListIndicatorCellViewInfo.ShowPopup; var APopup: TcxTreeListCustomizationPopup; begin APopup := GetPopup; Pressed := True; APopup.Owner := Self; APopup.Popup; end; // IcxTreeListPopupOwner function TcxTreeListIndicatorCellViewInfo.ClosePopupWhenNilOwner: Boolean; begin Result := False; end; function TcxTreeListIndicatorCellViewInfo.GetOwnerBounds: TRect; begin Result := DisplayRect; end; procedure TcxTreeListIndicatorCellViewInfo.PopupClosed; begin Pressed := False; end; procedure TcxTreeListIndicatorCellViewInfo.SetKind(AValue: TcxIndicatorKind); begin if AValue <> FKind then begin FKind := AValue; Invalidate; end; end; { TcxTreeListHeaderCellViewInfo } procedure TcxTreeListHeaderCellViewInfo.DoCalculate; begin inherited DoCalculate; FTextBounds := cxRectInflate(cxExcludeBorders(DisplayRect, Borders), -cxHeaderTextOffset, -cxHeaderTextOffset); if SortOrder <> soNone then begin FSortMarkBounds := FTextBounds; FSortMarkBounds.Left := FSortMarkBounds.Right - Painter.SortingMarkAreaSize.X; FTextBounds.Right := FSortMarkBounds.Left; end; DoCalculateGlyphPosition; end; procedure TcxTreeListHeaderCellViewInfo.DoCalculateGlyphPosition; var AWidth, AHeight: Integer; begin if Glyph.Empty then Exit; AWidth := Glyph.Width; AHeight := Glyph.Height; case GlyphAlignHorz of taLeftJustify: begin FGlyphPosition.X := FTextBounds.Left; Inc(FTextBounds.Left, AWidth + cxHeaderTextOffset); end; taRightJustify: begin Dec(FTextBounds.Right, AWidth); FGlyphPosition.X := FTextBounds.Right; Dec(FTextBounds.Right, cxHeaderTextOffset); end; taCenter: FGlyphPosition.X := (FTextBounds.Left + FTextBounds.Right - AWidth) div 2; end; case GlyphAlignVert of vaTop: FGlyphPosition.Y := FTextBounds.Top; vaBottom: FGlyphPosition.Y := FTextBounds.Bottom - AHeight; vaCenter: FGlyphPosition.Y := (FTextBounds.Bottom + FTextBounds.Top - AHeight) div 2; end; GlyphClipping := not cxInRange(FGlyphPosition.X, ClipRect.Left, ClipRect.Right - AWidth) or not cxInRange(FGlyphPosition.Y, ClipRect.Top, ClipRect.Bottom - AHeight); end; procedure TcxTreeListHeaderCellViewInfo.DoDraw(ACanvas: TcxCanvas); var AClipRgn: TcxRegion; begin inherited DoDraw(ACanvas); if not Glyph.Empty then begin AClipRgn := ACanvas.GetClipRegion; if GlyphClipping then ACanvas.IntersectClipRect(ClipRect); ACanvas.DrawGlyph(FGlyphPosition.X, FGlyphPosition.Y, Glyph); ACanvas.SetClipRegion(AClipRgn, roSet); end; if SortOrder <> soNone then Painter.DrawSortingMark(ACanvas, FSortMarkBounds, SortOrder = soAscending); if State = cxbsPressed then Painter.DrawHeaderPressed(ACanvas, DisplayRect); if Selected then begin ACanvas.DrawFocusRect(cxRectInflate( cxRectInflate(DisplayRect, BordersMargins), -1, -1)); ACanvas.DrawFocusRect(cxRectInflate( cxRectInflate(DisplayRect, BordersMargins), -2, -2)); end; end; function TcxTreeListHeaderCellViewInfo.GetDragSizing: IcxDragSizing; begin Supports(Item, IcxDragSizing, Result); end; function TcxTreeListHeaderCellViewInfo.GetFixed: Boolean; begin Result := False; end; function TcxTreeListHeaderCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; begin Result := inherited GetHitTest(AHitTest); if Result then SetHitItem; end; function TcxTreeListHeaderCellViewInfo.GetMultiline: Boolean; begin Result := FCaption.MultiLine; end; function TcxTreeListHeaderCellViewInfo.GetSelected: Boolean; begin Result := TreeList.Controller.IsObjectSelected(Item); end; function TcxTreeListHeaderCellViewInfo.GetShowEndEllipsis: Boolean; begin Result := FCaption.ShowEndEllipsis; end; function TcxTreeListHeaderCellViewInfo.GetSortOrder: TcxDataSortOrder; begin Result := soNone; end; procedure TcxTreeListHeaderCellViewInfo.Initialize(ACaption: TcxTreeListCaption); begin FCaption := ACaption; FItem := ACaption.Owner; end; procedure TcxTreeListHeaderCellViewInfo.Scroll(const DX, DY: Integer); begin if Fixed then Exit; OffsetRect(FSortMarkBounds, DX, 0); OffsetRect(FTextBounds, DX, 0); FGlyphPosition := cxPointOffset(FGlyphPosition, DX, 0); inherited Scroll(DX, 0); end; procedure TcxTreeListHeaderCellViewInfo.SetHitItem; begin HitTest.FDragItem := Self; end; function TcxTreeListHeaderCellViewInfo.GetAlignHorz: TAlignment; begin Result := FCaption.FAlignHorz; end; function TcxTreeListHeaderCellViewInfo.GetAlignVert: TcxAlignmentVert; begin Result := FCaption.FAlignVert; end; function TcxTreeListHeaderCellViewInfo.GetGlyph: TBitmap; begin Result := FCaption.Glyph; end; function TcxTreeListHeaderCellViewInfo.GetGlyphAlignHorz: TAlignment; begin Result := FCaption.GlyphAlignHorz; end; function TcxTreeListHeaderCellViewInfo.GetGlyphAlignVert: TcxAlignmentVert; begin Result := FCaption.GlyphAlignVert; end; function TcxTreeListHeaderCellViewInfo.GetText: string; begin Result := FCaption.Text; end; { TcxTreeListBandHeaderCellViewInfo } class function TcxTreeListBandHeaderCellViewInfo.CustomDrawID: Integer; begin Result := cxtlBandHeaderCell; end; procedure TcxTreeListBandHeaderCellViewInfo.Click; begin TreeList.DoBandHeaderClick(Band); end; procedure TcxTreeListBandHeaderCellViewInfo.DoCalculate; begin inherited DoCalculate; ItemViewParams := TreeList.Styles.GetBandHeaderParams(Band); end; function TcxTreeListBandHeaderCellViewInfo.GetFixed: Boolean; begin Result := Band.FixedKind <> tlbfNone; end; function TcxTreeListBandHeaderCellViewInfo.GetIsVisible: Boolean; begin Result := Band.ActuallyVisible; end; procedure TcxTreeListBandHeaderCellViewInfo.SetHitItem; begin inherited SetHitItem; HitTest.FHitBand := Band; SetHitTestCodes([tlhc_HitAtBandHeader]); end; function TcxTreeListBandHeaderCellViewInfo.GetBand: TcxTreeListBand; begin Result := Item as TcxTreeListBand; end; { TcxTreeListColumnHeaderCellViewInfo } class function TcxTreeListColumnHeaderCellViewInfo.CustomDrawID: Integer; begin Result := cxtlColumnHeaderCell; end; procedure TcxTreeListColumnHeaderCellViewInfo.Click; begin TreeList.DoColumnHeaderClick(Column); end; procedure TcxTreeListColumnHeaderCellViewInfo.DoCalculate; begin inherited DoCalculate; ItemViewParams := TreeList.Styles.GetColumnHeaderParams(Column); end; function TcxTreeListColumnHeaderCellViewInfo.GetFixed: Boolean; begin Result := Band.FixedKind <> tlbfNone; end; function TcxTreeListColumnHeaderCellViewInfo.GetIsVisible: Boolean; begin Result := Column.ActuallyVisible; end; function TcxTreeListColumnHeaderCellViewInfo.GetSortOrder: TcxDataSortOrder; begin Result := Column.GetRealSortOrder; end; procedure TcxTreeListColumnHeaderCellViewInfo.SetHitItem; begin inherited SetHitItem; HitTest.FHitColumn := Column; SetHitTestCodes([tlhc_HitAtColumnHeader]); end; function TcxTreeListColumnHeaderCellViewInfo.GetBand: TcxTreeListBand; begin Result := Column.Position.Band; end; function TcxTreeListColumnHeaderCellViewInfo.GetColumn: TcxTreeListColumn; begin Result := Item as TcxTreeListColumn; end; { TcxTreeListBandCellViewInfo } class function TcxTreeListBandCellViewInfo.CustomDrawID: Integer; begin Result := cxtlBandPartCell; end; procedure TcxTreeListBandCellViewInfo.DoCalculate; var ACanSelect: Boolean; begin inherited DoCalculate; case Part of tlbpHeader: ItemViewParams := Styles.GetBandBackgroundParams(Band); tlbpContent: begin ACanSelect := TreeList.OptionsSelection.CellSelect and TreeList.OptionsSelection.InvertSelect; if (Node <> nil) and Node.Selected and (not Node.Focused or ACanSelect) then ItemViewParams := Styles.GetSelectionParams else ItemViewParams := Styles.GetBandContentParams(Band, Node); end; tlbpFooter, tlbpGroupFooter: ItemViewParams := Styles.GetBandFooterParams(Band, Node); tlbpSeparator: begin ItemViewParams := Styles.GetBackgroundParams; ItemViewParams.Color := ColorToRgb(cxGetNativeColor(OptionsView.FFixedSeparatorColor, Painter.DefaultFixedSeparatorColor)); end; end; end; procedure TcxTreeListBandCellViewInfo.DoDraw(ACanvas: TcxCanvas); begin if Part in [tlbpFooter, tlbpGroupFooter] then Painter.DrawFooterPanel(ACanvas, DisplayRect, ViewParams, Borders) else inherited DoDraw(ACanvas); if Part = tlbpSeparator then ACanvas.ExcludeClipRect(ClipRect); end; function TcxTreeListBandCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; begin Result := inherited GetHitTest(AHitTest); if not Result then Exit; HitTest.FHitBand := Band; HitTest.FHitNode := Node; case Part of tlbpHeader: SetHitTestCodes([tlhc_HitAtBandContainer]); tlbpContent: SetHitTestCodes([tlhc_HitAtBand]); tlbpFooter: SetHitTestCodes([tlhc_HitAtFooter, tlhc_HitAtBand]); tlbpGroupFooter: SetHitTestCodes([tlhc_HitAtGroupFooter, tlhc_HitAtBand]); tlbpSeparator: SetHitTestCodes([tlhc_HitAtSeparator]); end; end; procedure TcxTreeListBandCellViewInfo.Initialize(ABand: TcxTreeListBand; ANode, AAttachNode: TcxTreeListNode; APart: TcxTreeListBandPart); begin FBand := ABand; FAttachNode := AAttachNode; FNode := ANode; FPart := APart; end; procedure TcxTreeListBandCellViewInfo.Scroll(const DX, DY: Integer); begin if (Band = nil) or (Band.FixedKind <> tlbfNone) then Exit; if Part <> tlbpContent then inherited Scroll(DX, 0) else inherited Scroll(DX, DY); end; { TcxTreeListEditCellViewInfo } class function TcxTreeListEditCellViewInfo.CustomDrawID: Integer; begin Result := cxtlEditCell; end; function TcxTreeListEditCellViewInfo.ContentOffset: TRect; begin Result := cxSimpleRect; end; function TcxTreeListEditCellViewInfo.GetColumn: TcxTreeListColumn; begin Result := TcxTreeListColumn(EditContainer); end; procedure TcxTreeListEditCellViewInfo.DoCalculate; begin ItemViewParams := GetEditViewParams; inherited DoCalculate; end; procedure TcxTreeListEditCellViewInfo.DoDraw(ACanvas: TcxCanvas); var P: TPoint; begin if CellTransparent then ACanvas.FrameRect(DisplayRect, BorderColor, 1, Borders) else begin SetWindowOrgEx(ACanvas.Handle, 0, 0, @P); ACanvas.FillRect(cxRectOffset(DisplayRect, NodeViewData.Origin), ViewParams, Borders, BorderColor); SetWindowOrgEx(ACanvas.Handle, P.X, P.Y, nil); end; EditViewInfo.PaintEx(ACanvas); if Focused and (Node.ViewData <> nil) and not Node.ViewData.DrawFocusRect then ACanvas.DrawFocusRect(cxExcludeBorders(DisplayRect, Borders)); 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.GetCellOrg: TPoint; begin Result := NodeViewData.Origin end; function TcxTreeListEditCellViewInfo.GetDisplayValue: Variant; begin Result := Column.DoOnGetDisplayText(Node, False, True); end; function TcxTreeListEditCellViewInfo.GetEditRect: TRect; begin Result := CellEditRect; if (Node <> nil) and (Node.ViewData <> nil) then Result := cxRectOffset(Result, Node.ViewData.Origin); end; function TcxTreeListEditCellViewInfo.GetEditViewParams: TcxViewParams; var AParams: TcxViewParams; begin Result := TreeList.Styles.GetContentParams(Node, Column); if Selected then begin AParams := TreeList.Styles.GetSelectionParams; Result.Color := AParams.Color; Result.TextColor := AParams.TextColor; end; end; function TcxTreeListEditCellViewInfo.GetFocused: Boolean; begin Result := Node.Focused and Column.Focused; end; function TcxTreeListEditCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; begin Result := PtInRect(cxRectOffset(ClipRect, NodeViewData.Origin), AHitTest.HitPoint); if not Result then Exit; TcxTreeListHitTest(AHitTest).FHitNode := Node; TcxTreeListHitTest(AHitTest).FHitColumn := Column; TcxTreeListHitTest(AHitTest).SetHitState(tlhc_HitAtNode, True); case CustomDrawID of cxtlPreviewCell: TcxTreeListHitTest(AHitTest).SetHitState(tlhc_HitAtNodePreview, True); else TcxTreeListHitTest(AHitTest).SetHitState(tlhc_HitAtColumn, True); end; TcxTreeListHitTest(AHitTest).HitTestItem := Self; end; function TcxTreeListEditCellViewInfo.GetHotTrack: Boolean; begin Result := Node.HotTrack; end; function TcxTreeListEditCellViewInfo.GetIncSearchParams: 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.GetOrigin: TPoint; begin Result := cxPointOffset(inherited GetOrigin, Node.ViewData.Origin); end; function TcxTreeListEditCellViewInfo.IsNeedHint(ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; begin Result := inherited IsNeedHint(ACanvas, cxPointOffset(P, cxPointInvert(Node.ViewData.Origin)), AText, AIsMultiLine, ATextRect, IsNeedOffsetHint); end; function TcxTreeListEditCellViewInfo.GetRecordIndex: Integer; begin Result := Integer(Node); end; function TcxTreeListEditCellViewInfo.GetSelected: Boolean; begin Result := Node.Selected and not (Node.Focused and Column.Editing); if not Node.Focused or not Result then Exit; if TreeList.OptionsSelection.CellSelect then begin if TreeList.OptionsSelection.InvertSelect then Result := not Focused; end end; function TcxTreeListEditCellViewInfo.GetSelectedTextColor: Integer; begin Result := GetIncSearchParams.TextColor; end; function TcxTreeListEditCellViewInfo.GetSelectedBKColor: Integer; begin Result := GetIncSearchParams.Color end; function TcxTreeListEditCellViewInfo.GetViewInfoData: Pointer; begin Result := Node; end; function TcxTreeListEditCellViewInfo.IsAutoHeight: Boolean; begin Result := TreeList.OptionsView.CellAutoHeight; end; function TcxTreeListEditCellViewInfo.IsEditHotTrack( const APoint: TPoint): Boolean; begin Result := ViewInfo.IsHotTrack(cxPointOffset(APoint, cxPointInvert(GetCellOrg))); end; function TcxTreeListEditCellViewInfo.IsEndEllipsis: Boolean; begin Result := inherited IsEndEllipsis and Column.Options.CellEndEllipsis; end; function TcxTreeListEditCellViewInfo.IsFixed: Boolean; begin Result := (Band <> nil) and (Band.FixedKind <> tlbfNone); end; function TcxTreeListEditCellViewInfo.IsTransparent: Boolean; begin Result := True; end; procedure TcxTreeListEditCellViewInfo.Scroll(const DX, DY: Integer); var AVisible: Boolean; begin if IsFixed or (DX = 0) then Exit; AVisible := Visible; CheckClipping(cxRectOffset(DisplayRect, DX, 0), VisibleBounds); ViewInfo.Left := ViewInfo.Left + DX; if AVisible <> Visible then VisibleInfoCalculated := False; end; function TcxTreeListEditCellViewInfo.GetBand: TcxTreeListBand; begin Result := Column.Position.Band; end; function TcxTreeListEditCellViewInfo.GetEditing: Boolean; begin Result := Column.Editing; end; function TcxTreeListEditCellViewInfo.GetNode: TcxTreeListNode; begin if NodeViewData = nil then Result := nil else Result := NodeViewData.Node; end; function TcxTreeListEditCellViewInfo.GetOptionsView: TcxTreeListOptionsView; begin Result := TreeList.OptionsView; end; function TcxTreeListEditCellViewInfo.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Control); end; { TcxTreeListIndentCellViewInfo } class function TcxTreeListIndentCellViewInfo.CustomDrawID: Integer; begin Result := cxtlIndentCell; end; procedure TcxTreeListIndentCellViewInfo.DoCalculate; var DY: Integer; C: TPoint; begin inherited DoCalculate; InitializeImageIndent(Images); ItemViewParams := Styles.GetIndentParams(Node, Index); FButton := TreeList.OptionsView.Buttons and (Images = nil) and (Kind = nikLevel) and (Index = Node.Level) and Node.HasVisibleChildren; if (Images = nil) and (OptionsView.TreeLineStyle <> tllsNone) then begin C := cxRectCenter(DisplayRect); DY := 0; if (Node.ViewData.PreviewHeight > 0) and (TreeList.Preview.Place = tlppTop) then DY := 1; if ilHorz in Lines then FHorzTreeLine := cxRect(C.X, C.Y - 1 + DY, DisplayRect.Right, C.Y + DY); if [ilVertUp, ilVertDown] * Lines <> [] then begin FVertTreeLine := cxRect(C.X, DisplayRect.Top, C.X + 1, DisplayRect.Bottom); if not (ilVertUp in Lines) then FVertTreeLine.Top := C.Y - 1; if not (ilVertDown in Lines) then FVertTreeLine.Bottom := C.Y - 1; end; end; FGlyphRect := cxInvalidRect; if Button then begin FGlyphRect := cxRectCenter(DisplayRect, Painter.SmallExpandButtonSize, Painter.SmallExpandButtonSize); end else if Images <> nil then FGlyphRect := cxRectCenter(DisplayRect, Images.Width, Images.Height) else if Kind = nikCheck then begin if Node.Parent.CheckGroupType = ncgRadioGroup then FGlyphRect := cxRectCenter(DisplayRect, Painter.RadioButtonSize) else FGlyphRect := DisplayRect; end; end; procedure TcxTreeListIndentCellViewInfo.DoDraw(ACanvas: TcxCanvas); begin inherited DoDraw(ACanvas); if Kind = nikCheck then DrawCheck(ACanvas) else if Images <> nil then DrawImage(ACanvas) else DrawLines(ACanvas); end; procedure TcxTreeListIndentCellViewInfo.DrawCheck(ACanvas: TcxCanvas); const AState: array[Boolean, Boolean] of TcxButtonState = ((cxbsDisabled, cxbsDisabled), (cxbsNormal, cxbsHot)); begin if Node.Parent.CheckGroupType = ncgRadioGroup then Painter.DrawRadioButton(ACanvas, GlyphRect.Left, GlyphRect.Top, AState[Node.Enabled, HotTrack], CheckState = cbsChecked, False, clDefault) else GetCheckBoxViewInfo(ACanvas).Paint(ACanvas) end; procedure TcxTreeListIndentCellViewInfo.DrawImage(ACanvas: TcxCanvas); begin Images.Draw(ACanvas.Canvas, GlyphRect.Left, GlyphRect.Top, ImageIndex, dsTransparent, Images.ImageType, True); Images.Draw(ACanvas.Canvas, GlyphRect.Left, GlyphRect.Top, OverlayIndex, dsTransparent, Images.ImageType, True); end; procedure TcxTreeListIndentCellViewInfo.DrawLines(ACanvas: TcxCanvas); begin if [ilVertUp, ilVertDown] * Lines <> [] then DrawTreeLine(ACanvas, VertTreeLine); if ilHorz in Lines then DrawTreeLine(ACanvas, HorzTreeLine); if Button then Painter.DrawSmallExpandButton(ACanvas, GlyphRect, IsExpanded, TreeList.ViewInfo.TreeLineColor, ViewParams.Color); end; procedure TcxTreeListIndentCellViewInfo.DrawTreeLine( ACanvas: TcxCanvas; const ARect: TRect); begin if OptionsView.TreeLineStyle = tllsDot then cxFillHalfToneRect(ACanvas.Canvas, ARect, ViewParams.Color, TreeList.ViewInfo.TreeLineColor) else ACanvas.FillRect(ARect, TreeList.ViewInfo.TreeLineColor); end; function TcxTreeListIndentCellViewInfo.GetCheckBoxViewInfo( ACanvas: TcxCanvas): TcxCustomEditViewInfo; var P: TPoint; AViewData: TcxCustomEditViewData; begin Result := TreeList.ViewInfo.CheckBoxViewInfo; AViewData := TreeList.ViewInfo.CheckBoxViewData; AViewData.EditValueToDrawValue(ACanvas, Integer(Node.CheckState), Result); P := cxInvalidPoint; AViewData.Enabled := Node.Enabled; if HotTrack then P := cxRectCenter(DisplayRect); AViewData.Calculate(ACanvas, DisplayRect, P, cxmbNone, [], Result, False); Result.Transparent := True; end; function TcxTreeListIndentCellViewInfo.GetHitTest( AHitTest: TcxCustomHitTestController): Boolean; var R: TRect; const AImages: array[Boolean] of Integer = (tlhc_HitAtImage, tlhc_HitAtStateImage); begin Result := inherited GetHitTest(AHitTest); if not Result then Exit; HitTest.FHitNode := Node; SetHitTestCodes([tlhc_HitAtIndent]); if Images <> nil then SetHitTestCodes([AImages[Kind = nikState]]) else begin R := cxRectOffset(GlyphRect, GetCellOrigin); InflateRect(R, cxTextOffset, cxTextOffset); if Kind = nikCheck then SetHitTestCodes([tlhc_HitAtCheckButton]) else if Button and PtInRect(R, AHitTest.HitPoint) then SetHitTestCodes([tlhc_HitAtButton]) end; end; procedure TcxTreeListIndentCellViewInfo.InitializeLevelIndent( ANode, AAttachNode: TcxTreeListNode; AIndex: Integer); begin FIndex := AIndex; FNode := ANode; FAttachNode := AAttachNode; FLines := []; FLevelNode := ANode; while FLevelNode.Level <> AIndex do FLevelNode := FLevelNode.Parent; if OptionsView.TreeLineStyle <> tllsNone then begin if Kind = nikFooter then begin if LevelNode.GetNextSiblingVisible <> nil then FLines := [ilVertUp, ilVertDown] end else begin if (LevelNode <> Node) or (Node.VisibleIndex <> 0) then Include(FLines, ilVertUp); if LevelNode.GetNextSiblingVisible <> nil then Include(FLines, ilVertDown) else if LevelNode <> Node then Exclude(FLines, ilVertUp); if (LevelNode = Node) then Include(FLines, ilHorz); end; end; end; procedure TcxTreeListIndentCellViewInfo.InitializeImageIndent( AImages: TCustomImageList); begin FImages := AImages; FImageIndex := -1; FOverlayIndex := -1; if (Images = nil) or not (Kind in [nikImage, nikState]) then Exit; if Kind = nikImage then begin FImageIndex := TreeList.DoGetNodeImageIndex(Node, TcxTreeListImageIndexType(Node.Selected)); if FImageIndex <> - 1 then FOverlayIndex := TreeList.DoGetNodeImageIndex(Node, tlitOverlayIndex); end else begin FImageIndex := TreeList.DoGetNodeImageIndex(Node, tlitStateIndex); if FImageIndex <> - 1 then FOverlayIndex := TreeList.DoGetNodeImageIndex(Node, tlitOverlayStateIndex); end; end; procedure TcxTreeListIndentCellViewInfo.Scroll(const DX, DY: Integer); begin if Fixed then Exit; inherited Scroll(DX, 0); end; procedure TcxTreeListIndentCellViewInfo.SetSize(ATop, AHeight: Integer); begin CheckClipping(cxRectSetTop(BoundsRect, ATop, AHeight), cxRectSetTop(VisibleBounds, ATop, AHeight)); end; // IcxHotTrackElement function TcxTreeListIndentCellViewInfo.GetOrigin: TPoint; begin Result := cxPointOffset(DisplayRect.TopLeft, GetCellOrigin); end; function TcxTreeListIndentCellViewInfo.IsNeedHint( ACanvas: TcxCanvas; const P: TPoint; out AText: TCaption; out AIsMultiLine: Boolean; out ATextRect: TRect; var IsNeedOffsetHint: Boolean): Boolean; begin Result := False; end; procedure TcxTreeListIndentCellViewInfo.UpdateHotTrackState(const APoint: TPoint); begin FHotTrack := PtInRect(cxRectOffset(DisplayRect, GetCellOrigin), APoint); TreeList.InvalidateRectEx(cxRectOffset(DisplayRect, GetCellOrigin), False); end; function TcxTreeListIndentCellViewInfo.GetCheckState: TcxCheckBoxState; begin Result := Node.CheckState; end; function TcxTreeListIndentCellViewInfo.GetFixed: Boolean; begin Result := (TreeList.Bands.ExpandableBand = nil) or (TreeList.Bands.ExpandableBand.FixedKind <> tlbfNone); end; function TcxTreeListIndentCellViewInfo.GetHasImage: Boolean; begin Result := (Images <> nil) and ((ImageIndex >= 0) or (OverlayIndex >= 0)); end; function TcxTreeListIndentCellViewInfo.GetIsExpanded: Boolean; begin Result := Button and Node.Expanded; end; { TcxTreeListGroupNodeEditViewInfo } function TcxTreeListGroupNodeEditViewInfo.GetColumn: TcxTreeListColumn; begin Result := TreeList.OptionsView.GetCategorizedColumn; end; function TcxTreeListGroupNodeEditViewInfo.GetFocused: Boolean; begin Result := Node.Focused; end; function TcxTreeListGroupNodeEditViewInfo.IsFixed: Boolean; begin Result := TreeList.Bands.VisibleLeftFixedCount > 0; end; procedure TcxTreeListGroupNodeEditViewInfo.Scroll(const DX, DY: Integer); var R: TRect; begin if IsFixed or (DX = 0) then Exit; R := DisplayRect; Inc(R.Left, DX); CheckClipping(R, VisibleBounds); ViewInfo.Left := ViewInfo.Left + DX; VisibleInfoCalculated := False; end; { TcxTreeListPreviewCellViewInfo } constructor TcxTreeListPreviewCellViewInfo.Create(AOwner: TObject); begin inherited Create(AOwner); FPreview := TreeList.Preview; end; class function TcxTreeListPreviewCellViewInfo.CustomDrawID: Integer; begin Result := cxtlPreviewCell; end; function TcxTreeListPreviewCellViewInfo.ContentOffset: TRect; begin Result := inherited ContentOffset; Result.Left := Preview.LeftIndent; Result.Right := Preview.RightIndent; end; procedure TcxTreeListPreviewCellViewInfo.DoCalculate; begin Include(ViewData.PaintOptions, epoAllowZeroHeight); inherited DoCalculate; end; function TcxTreeListPreviewCellViewInfo.GetColumn: TcxTreeListColumn; begin Result := Preview.Column; end; function TcxTreeListPreviewCellViewInfo.GetButtonTransparency: TcxEditButtonTransparency; begin Result := ebtHideInactive; end; function TcxTreeListPreviewCellViewInfo.GetEditViewParams: TcxViewParams; begin Result := TreeList.Styles.GetPreviewParams(Node); end; function TcxTreeListPreviewCellViewInfo.GetHotTrack: Boolean; begin Result := False; end; function TcxTreeListPreviewCellViewInfo.GetMaxLineCount: Integer; begin Result := Preview.MaxLineCount; end; function TcxTreeListPreviewCellViewInfo.IsAutoHeight: Boolean; begin Result := True; end; function TcxTreeListPreviewCellViewInfo.IsEditHotTrack( const APoint: TPoint): Boolean; begin Result := False; end; procedure TcxTreeListPreviewCellViewInfo.Scroll(const DX, DY: Integer); begin if TreeList.Bands.VisibleLeftFixedCount = 0 then inherited Scroll(DX, 0); end; { TcxTreeListLevelInfo } constructor TcxTreeListLevelInfo.Create(ATreeList: TcxCustomTreeList); begin FTreeList := ATreeList; FImagesChangeLink := TChangeLink.Create; FImagesChangeLink.OnChange := Changed; FStateImagesChangeLink := TChangeLink.Create; FStateImagesChangeLink.OnChange := Changed; end; destructor TcxTreeListLevelInfo.Destroy; begin Images := nil; StateImages := nil; FImagesChangeLink.Free; FStateImagesChangeLink.Free; inherited Destroy; end; procedure TcxTreeListLevelInfo.Changed(Sender: TObject); begin Update(0); TreeList.ImagesChanged(Sender); end; procedure TcxTreeListLevelInfo.Notification( AComponent: TComponent; Operation: TOperation); begin if Operation <> opRemove then Exit; if AComponent = Images then Images := nil; if AComponent = StateImages then StateImages := nil; end; function TcxTreeListLevelInfo.Update(const AOffset: Integer): Integer; begin FOffset := AOffset; FSize := TreeList.DefaultIndentSize; FWidth := FSize.cx; if Images <> nil then begin FSize.cy := Max(FSize.cy, Images.Height + cxTreeListIndentOffsetSize div 2); Inc(FWidth, Images.Width + cxTreeListIndentOffsetSize div 2); if not DynamicIndent then FSize.cx := Max(Images.Width + cxTreeListIndentOffsetSize div 2, FSize.cx); end; if StateImages <> nil then begin FSize.cy := Max(FSize.cy, StateImages.Height + cxTreeListIndentOffsetSize div 2); Inc(FWidth, StateImages.Width + cxTreeListIndentOffsetSize div 2); end; Result := FOffset + FSize.cx; end; function TcxTreeListLevelInfo.GetTotalWidth: Integer; begin Result := FOffset + Width; end; function TcxTreeListLevelInfo.GetDynamicIndent: Boolean; begin Result := TreeList.OptionsView.DynamicIndent; end; procedure TcxTreeListLevelInfo.SetImages(AValue: TCustomImageList); begin if AValue <> FImages then cxSetImageList(AValue, FImages, FImagesChangeLink, TreeList); end; procedure TcxTreeListLevelInfo.SetStateImages(AValue: TCustomImageList); begin if AValue <> StateImages then cxSetImageList(AValue, FStateImages, FStateImagesChangeLink, TreeList); end; { TcxTreeListLikeParams } constructor TcxTreeListLikeParams.Create(APercent: Char = '%'; AUnderline: Char = '_'); begin FPercent := APercent; FUnderline := AUnderline; end; { TcxTreeListNodeViewData } constructor TcxTreeListNodeViewData.Create( AViewInfo: TcxTreeListViewInfo; ANode: TcxTreeListNode; ACapacity: Integer); begin ViewInfo := AViewInfo; Node := ANode; Focused := (ANode <> nil) and ANode.Focused; Selected := (ANode <> nil) and ANode.Selected; if ANode <> nil then Node.FViewData := Self; Cells := TcxCustomControlCells.Create; Cells.Capacity := ACapacity; end; destructor TcxTreeListNodeViewData.Destroy; begin if not ViewInfo.TreeList.IsDestroying then ViewInfo.CellsChanged; FreeAndNil(Cells); if Node <> nil then Node.FViewData := nil; inherited Destroy; end; function TcxTreeListNodeViewData.GetRealBounds: TRect; begin Result := cxRectOffset(Bounds, Origin); end; function TcxTreeListNodeViewData.GetRealContentBounds: TRect; begin Result := cxRectOffset(ContentBounds, Origin) end; procedure TcxTreeListNodeViewData.Paint( ACanvas: TcxCanvas; AHandler: TcxCustomDrawCellEvent); var I: Integer; AWindowOrg: TPoint; AClipRgn, AFooterRgn: TcxRegion; begin if not ACanvas.RectVisible(cxRectInflate(GetRealBounds, 1, 1)) then Exit; AClipRgn := ACanvas.GetClipRegion(); try AWindowOrg := ACanvas.WindowOrg; ACanvas.WindowOrg := cxPointInvert(Origin); Cells.Paint(ACanvas, AHandler); if DrawFocusRect and Node.Focused then begin for I := 0 to Cells.Count - 1 do if Cells[I].Visible and (Cells[I].CustomDrawID = cxtlIndentCell) then ACanvas.ExcludeClipRect(Cells[I].VisibleRect); ACanvas.DrawFocusRect(FocusRectBounds); end; if CheckFooterRgn then begin for I := 0 to Cells.Count - 1 do if Cells[I].Visible and (Cells[I].CustomDrawID = cxtlBandPartCell) and (TcxTreeListBandCellViewInfo(Cells[I]).Part in [tlbpGroupFooter, tlbpFooter]) then begin AFooterRgn := TcxRegion.Create(cxRectOffset(TcxTreeListBandCellViewInfo(Cells[I]).ClipRect, Origin)); AClipRgn.Combine(AFooterRgn, roSubtract); end; end; ACanvas.WindowOrg := AWindowOrg; finally ACanvas.SetClipRegion(AClipRgn, roSet); end; end; procedure TcxTreeListNodeViewData.Scroll(DX, DY: Integer; ALeftFixed, ARightFixed: Boolean); var I: Integer; begin for I := 0 to Cells.Count - 1 do TcxTreeListCustomCellViewInfo(Cells[I]).Scroll(DX, 0); Origin := cxPointOffset(Origin, 0, DY); if not ARightFixed then begin Inc(ContentBounds.Right, DX); Inc(FocusRectBounds.Right, DX); end; if not ALeftFixed then begin Inc(ContentBounds.Left, DX); Inc(FocusRectBounds.Left, DX); end; end; function TcxTreeListNodeViewData.Update(AForceUpdate: Boolean): Boolean; var I: Integer; R: TRect; begin Result := (Selected <> Node.Selected) or Focused or Node.Focused or AForceUpdate; Selected := Node.Selected; Focused := Node.Focused; if not Result then Exit; for I := 0 to Cells.Count - 1 do Cells[I].VisibleInfoCalculated := False; R := GetRealBounds; R.Left := 0; Node.TreeList.InvalidateRectEx(cxRectInflate(R, 1, 1), False); end; { TcxTreeListCustomPopupMenu } function TcxTreeListCustomPopupMenu.Popup(X, Y: Integer): Boolean; begin Result := ShowPopupMenu(TreeList, FPopupMenu, X, Y); end; procedure TcxTreeListCustomPopupMenu.SetPopupMenu(AValue: TComponent); begin FPopupMenu := AValue; end; { TcxTreeListCustomBuiltInMenu } destructor TcxTreeListCustomBuiltInMenu.Destroy; begin DestroyPopupMenu; inherited Destroy; end; procedure TcxTreeListCustomBuiltInMenu.CreatePopupMenu; begin FPopupMenu := GetPopupClass.Create(TreeList); end; procedure TcxTreeListCustomBuiltInMenu.DestroyPopupMenu; begin FreeAndNil(FPopupMenu); end; procedure TcxTreeListCustomBuiltInMenu.GetBitmapFromImageList(AImages: TCustomImageList; AImageIndex: Integer; ABitmap: TBitmap); begin if (AImages <> nil) and cxInRange(AImageIndex, 0, AImages.Count - 1) then begin ABitmap.PixelFormat := pf32bit; TcxImageList.GetImageInfo(AImages.Handle, AImageIndex, ABitmap, nil); end; end; function TcxTreeListCustomBuiltInMenu.GetImages(AInternal: Boolean): TCustomImageList; begin if AInternal then Result := TcxTreeListPopupMenu(Owner).Images else Result := TcxTreeListPopupMenu(Owner).UserImages; end; function TcxTreeListCustomBuiltInMenu.GetRoot: TComponent; begin Result := FPopupMenu; end; function TcxTreeListCustomBuiltInMenu.GetTreeList: TcxCustomTreeList; begin Result := TcxTreeListPopupMenu(Owner).TreeList; end; procedure TcxTreeListCustomBuiltInMenu.Initialize; begin DestroyPopupMenu; CreatePopupMenu; end; procedure TcxTreeListCustomBuiltInMenu.MenuItemClickHandler(Sender: TObject); begin TcxTreeListPopupMenu(Owner).DoMenuItemClick(Sender); end; { TcxTreeListBuiltInMenuItem } type TcxTreeListBuiltInMenuItem = class(TMenuItem) private FInternal: Boolean; FBuiltInMenu: TcxTreeListBuiltInMenu; procedure CalculateRects(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState; out AImageAreaRect, ATextRect: TRect); procedure DrawCheck(ACanvas: TCanvas; const AImageAreaRect: TRect); procedure DoDrawImage(ACanvas: TCanvas; const AImageAreaRect: TRect; ABitmap: TBitmap; AImages: TCustomImageList; AImageIndex: Integer; ADrawMode: TcxImageDrawMode); procedure DrawBackground(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState); procedure DrawImage(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState; const AImageAreaRect: TRect); procedure DrawImageCheckedBackground(ACanvas: TCanvas; const AImageAreaRect: TRect); procedure DrawText(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState; ATextRect: TRect); protected procedure AdvancedDrawItem(ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState; TopLevel: Boolean); override; public constructor Create(ABuiltInMenu: TcxTreeListBuiltInMenu; AInternal: Boolean); reintroduce; virtual; end; constructor TcxTreeListBuiltInMenuItem.Create(ABuiltInMenu: TcxTreeListBuiltInMenu; AInternal: Boolean); begin inherited Create(nil); FInternal := AInternal; FBuiltInMenu := ABuiltInMenu; end; procedure TcxTreeListBuiltInMenuItem.AdvancedDrawItem(ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState; TopLevel: Boolean); var AImageAreaRect: TRect; ATextRect: TRect; begin if not IsWinXPOrLater or FBuiltInMenu.PopupMenu.IsRightToLeft then inherited AdvancedDrawItem(ACanvas, ARect, State, TopLevel) else begin CalculateRects(ACanvas, ARect, State, AImageAreaRect, ATextRect); DrawBackground(ACanvas, ARect, State); DrawImage(ACanvas, ARect, State, AImageAreaRect); DrawText(ACanvas, ARect, State, ATextRect); end; end; procedure TcxTreeListBuiltInMenuItem.CalculateRects(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState; out AImageAreaRect, ATextRect: TRect); begin AImageAreaRect := ARect; AImageAreaRect.Right := AImageAreaRect.Left + cxRectHeight(AImageAreaRect); ATextRect := ARect; ATextRect.Left := AImageAreaRect.Right + 3; Dec(ATextRect.Right); end; procedure TcxTreeListBuiltInMenuItem.DrawCheck(ACanvas: TCanvas; const AImageAreaRect: TRect); var ACheckRect: TRect; AcxCanvas: TcxCanvas; begin ACheckRect := cxRectCenter(AImageAreaRect, TcxCustomLookAndFeelPainter.CheckButtonSize); InflateRect(ACheckRect, -TcxCustomLookAndFeelPainter.CheckBorderSize, -TcxCustomLookAndFeelPainter.CheckBorderSize); AcxCanvas := TcxCanvas.Create(ACanvas); try AcxCanvas.Brush.Style := bsClear; TcxCustomLookAndFeelPainter.DrawCheck(AcxCanvas, ACheckRect, cxbsNormal, True, clBtnText); AcxCanvas.Brush.Style := bsSolid; finally AcxCanvas.Free; end; end; procedure TcxTreeListBuiltInMenuItem.DoDrawImage(ACanvas: TCanvas; const AImageAreaRect: TRect; ABitmap: TBitmap; AImages: TCustomImageList; AImageIndex: Integer; ADrawMode: TcxImageDrawMode); var AImageRect: TRect; begin AImageRect := Bounds(AImageAreaRect.Left + 1, AImageAreaRect.Top + 1, FBuiltInMenu.GetImages(True).Width, FBuiltInMenu.GetImages(True).Height); cxDrawImage(ACanvas.Handle, AImageRect, AImageRect, ABitmap, AImages, AImageIndex, ADrawMode); end; procedure TcxTreeListBuiltInMenuItem.DrawBackground(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState); const ABrushColor: array [Boolean] of TColor = (clHighlight, clMenuHighlight); begin if odSelected in AState then begin ACanvas.Brush.Color := ABrushColor[IsThemeActive]; ACanvas.Font.Color := clHighlightText; end; ACanvas.FillRect(ARect); end; procedure TcxTreeListBuiltInMenuItem.DrawImage(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState; const AImageAreaRect: TRect); const ADrawMode: array [Boolean] of TcxImageDrawMode = (idmDisabled, idmNormal); var AImages: TCustomImageList; begin AImages := FBuiltInMenu.GetImages(FInternal); if Checked then DrawImageCheckedBackground(ACanvas, AImageAreaRect); if (AImages <> nil) and cxInRange(ImageIndex, 0, AImages.Count - 1) then DoDrawImage(ACanvas, AImageAreaRect, Bitmap, AImages, ImageIndex, ADrawMode[Enabled]) else if Checked then DrawCheck(ACanvas, AImageAreaRect); end; procedure TcxTreeListBuiltInMenuItem.DrawImageCheckedBackground(ACanvas: TCanvas; const AImageAreaRect: TRect); begin ACanvas.Brush.Color := clBtnShadow; ACanvas.FrameRect(AImageAreaRect); ACanvas.Brush.Color := clBtnFace; ACanvas.FillRect(cxRectInflate(AImageAreaRect, -1, -1)); end; procedure TcxTreeListBuiltInMenuItem.DrawText(ACanvas: TCanvas; const ARect: TRect; AState: TOwnerDrawState; ATextRect: TRect); begin DoDrawText(ACanvas, Caption, ATextRect, odSelected in AState, DT_SINGLELINE or DT_EXPANDTABS or DT_LEFT or DT_VCENTER); if ShortCut <> 0 then begin Dec(ATextRect.Right, 10); DoDrawText(ACanvas, ShortCutToText(ShortCut), ATextRect, odSelected in AState, DT_SINGLELINE or DT_RIGHT or DT_VCENTER); end; end; { TcxTreeListBuiltInMenu } function TcxTreeListBuiltInMenu.CreateMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean; AItemType: TcxTreeListBuiltInMenuItemType; AChecked: Boolean; AImageIndex: Integer; AWithSeparator: Boolean; AInternal: Boolean): TComponent; var ASeparator: TMenuItem; begin Result := TcxTreeListBuiltInMenuItem.Create(Self, AInternal); if AWithSeparator then begin ASeparator := TMenuItem.Create(nil); ASeparator.Caption := '-'; TMenuItem(AOwner).Add(ASeparator); end; with TcxTreeListBuiltInMenuItem(Result) do begin Caption := ACaption; Checked := AChecked; Enabled := AEnabled; ImageIndex := AImageIndex; Tag := ACommand; if AInternal then GetBitmapFromImageList(GetImages(AInternal), AImageIndex, Bitmap); OnClick := MenuItemClickHandler; end; TMenuItem(AOwner).Add(TMenuItem(Result)); end; function TcxTreeListBuiltInMenu.GetPopupClass: TComponentClass; begin Result := TPopupMenu; end; function TcxTreeListBuiltInMenu.GetRoot: TComponent; begin Result := PopupMenu.Items; end; procedure TcxTreeListBuiltInMenu.CreatePopupMenu; begin inherited CreatePopupMenu; if GetImages(False) <> nil then PopupMenu.Images := GetImages(False) else PopupMenu.Images := GetImages(True); end; function TcxTreeListBuiltInMenu.GetPopupMenu: TPopupMenu; begin Result := TPopupMenu(FPopupMenu); end; { TcxTreeListPopupMenu } constructor TcxTreeListPopupMenu.Create(AOwner: TPersistent); begin inherited Create(AOwner); LoadResourceImages; end; destructor TcxTreeListPopupMenu.Destroy; begin PopupMenu := nil; FreeAndNil(FBuiltInMenu); FreeAndNil(FImages); inherited Destroy; end; procedure TcxTreeListPopupMenu.Assign(Source: TPersistent); begin if Source is TcxTreeListPopupMenu then begin UseBuiltInMenu := TcxTreeListPopupMenu(Source).UseBuiltInMenu; PopupMenu := TcxTreeListPopupMenu(Source).PopupMenu; OnClick := TcxTreeListPopupMenu(Source).OnClick; OnPopup := TcxTreeListPopupMenu(Source).OnPopup; end else inherited Assign(Source); end; function TcxTreeListPopupMenu.CreateMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean; AItemType: TcxTreeListBuiltInMenuItemType; AChecked: Boolean; AImageIndex: Integer; AWithSeparator: Boolean): TComponent; begin Result := BuiltInMenu.CreateMenuItem(AOwner, ACaption, ACommand, AEnabled, AItemType, AChecked, AImageIndex, AWithSeparator, False); end; function TcxTreeListPopupMenu.CreateInternalMenuItem(AOwner: TComponent; const ACaption: string; ACommand: Integer; AEnabled: Boolean = True; AItemType: TcxTreeListBuiltInMenuItemType = tlmitDefault; AChecked: Boolean = False; AImageIndex: Integer = -1; AWithSeparator: Boolean = False): TComponent; begin Result := BuiltInMenu.CreateMenuItem(AOwner, ACaption, ACommand, AEnabled, AItemType, AChecked, AImageIndex, AWithSeparator); end; procedure TcxTreeListPopupMenu.CreateItems; begin end; procedure TcxTreeListPopupMenu.DoExecute(ACommand: Integer); begin end; procedure TcxTreeListPopupMenu.DoMenuItemClick(Sender: TObject); var AHandled: Boolean; begin DoClick(Sender, AHandled); if not AHandled then DoExecute(TComponent(Sender).Tag); end; procedure TcxTreeListPopupMenu.DoClick(AItem: TObject; var AHandled: Boolean); begin AHandled := False; if Assigned(FOnClick) then FOnClick(TreeList, AItem, AHandled); end; function TcxTreeListPopupMenu.DoPopup: Boolean; begin Result := False; if Assigned(FOnPopup) then FOnPopup(TreeList, Self, Result); end; function TcxTreeListPopupMenu.DoShowPopupMenu(const P: TPoint): Boolean; begin Result := IsPopupSuitable(TcxTreeListPopupMenus(Owner).HitTest) and Popup(P.X, P.Y); end; function TcxTreeListPopupMenu.GetResourceImagesCount: Integer; begin Result := 0; end; function TcxTreeListPopupMenu.GetResourceImagesNamePrefix: string; begin Result := ''; end; function TcxTreeListPopupMenu.GetRoot: TComponent; begin Result := BuiltInMenu.Root; end; function TcxTreeListPopupMenu.GetTreeList: TcxCustomTreeList; begin Result := TcxTreeListPopupMenus(Owner).TreeList; end; procedure TcxTreeListPopupMenu.InitializeInternalMenu; begin BuiltInMenu.Initialize; CreateItems; end; function TcxTreeListPopupMenu.IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; begin Result := False; end; procedure TcxTreeListPopupMenu.LoadResourceImages; var B: TBitmap; I: Integer; begin FImages := TcxImageList.CreateSize(16, 16); for I := 1 to GetResourceImagesCount do begin B := TBitmap.Create; try B.LoadFromResourceName(HInstance, GetResourceImagesNamePrefix + IntToStr(I)); TcxImageList(Images).AddMasked(B, clNone); finally B.Free; end; end; end; procedure TcxTreeListPopupMenu.Notification(AComponent: TComponent; Operation: TOperation); begin if (Operation = opRemove) then if (AComponent = PopupMenu) then PopupMenu := nil else if (AComponent = UserImages) then UserImages := nil; end; function TcxTreeListPopupMenu.Popup(X, Y: Integer): Boolean; begin if UseBuiltInMenu then InitializeInternalMenu; Result := DoPopup; if not Result then if UseBuiltInMenu then Result := BuiltInMenu.Popup(X, Y) else Result := inherited Popup(X, Y); end; procedure TcxTreeListPopupMenu.SetPopupMenu(AValue: TComponent); begin if PopupMenu <> AValue then begin if PopupMenu <> nil then PopupMenu.RemoveFreeNotification(TreeList); inherited; if PopupMenu <> nil then PopupMenu.FreeNotification(TreeList); end; end; function TcxTreeListPopupMenu.GetBuiltInMenu: TcxTreeListCustomBuiltInMenu; begin if FBuiltInMenu = nil then FBuiltInMenu := cxTreeListBuiltInMenuClass.Create(Self); Result := FBuiltInMenu; end; function TcxTreeListPopupMenu.GetImages: TCustomImageList; begin Result := FImages; end; procedure TcxTreeListPopupMenu.SetUseBuiltInMenu(AValue: Boolean); begin if FUseBuiltInMenu <> AValue then begin FUseBuiltInMenu := AValue; if not FUseBuiltInMenu then FreeAndNil(FBuiltInMenu); end; end; procedure TcxTreeListPopupMenu.SetUserImages(AValue: TCustomImageList); begin if FUserImages <> AValue then begin if FUserImages <> nil then FUserImages.RemoveFreeNotification(TreeList); FUserImages := AValue; if FUserImages <> nil then FUserImages.FreeNotification(TreeList); end; end; { TcxTreeListFooterPopupMenu } constructor TcxTreeListFooterPopupMenu.Create(AOwner: TPersistent); begin inherited Create(AOwner); FItems := [tlfmiSum, tlfmiMin, tlfmiMax, tlfmiAverage, tlfmiCount, tlfmiNone, tlfmiAllNodes]; end; procedure TcxTreeListFooterPopupMenu.Assign(Source: TPersistent); begin inherited Assign(Source); if Source is TcxTreeListFooterPopupMenu then FItems := TcxTreeListFooterPopupMenu(Source).Items; end; procedure TcxTreeListFooterPopupMenu.CreateItems; var ASummaryKinds: TcxSummaryKinds; ADoesVisibleItemExist: Boolean; begin inherited; ASummaryKinds := GetVisibleItemKinds; ADoesVisibleItemExist := ASummaryKinds * [skSum..skAverage] <> []; if tlfmiSum in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListSumMenuItem), tlcmSum, IsItemEnabled(skSum), tlmitChecked, skSum in ASummaryKinds, tlcmSum - 1); if tlfmiMin in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListMinMenuItem), tlcmMin, IsItemEnabled(skMin), tlmitChecked, skMin in ASummaryKinds, tlcmMin - 1); if tlfmiMax in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListMaxMenuItem), tlcmMax, IsItemEnabled(skMax), tlmitChecked, skMax in ASummaryKinds, tlcmMax - 1); if tlfmiCount in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListCountMenuItem), tlcmCount, IsItemEnabled(skCount), tlmitChecked, skCount in ASummaryKinds, tlcmCount - 1); if tlfmiAverage in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListAvgMenuItem), tlcmAverage, IsItemEnabled(skAverage), tlmitChecked, skAverage in ASummaryKinds, tlcmAverage - 1); if tlfmiNone in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListNoneMenuItem), tlcmNone, IsItemEnabled(skNone), tlmitChecked, not ADoesVisibleItemExist, - 1, True); if tlfmiAllNodes in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListAllNodesMenuItem), tlcmAllNodes, ADoesVisibleItemExist, tlmitChecked, ADoesVisibleItemExist and IsAllNodes, - 1, True); end; procedure TcxTreeListFooterPopupMenu.DoExecute(ACommand: Integer); procedure SetItemsVisibility(AKind: TcxSummaryKind); var I: Integer; AValue: Boolean; begin AValue := (AKind <> skNone) and not (AKind in GetVisibleItemKinds); if not AValue or (SummaryItems.GetItemByKind(AKind) <> nil) then begin for I := 0 to SummaryItems.Count - 1 do if ((SummaryItems[I].Kind = AKind) or (AKind = skNone)) then SummaryItems[I].Visible := AValue; end else with SummaryItems.Add do begin Kind := AKind; AllNodes := IsAllNodes; end; end; procedure SetAllNodes(AValue: Boolean); var I: Integer; begin SummaryItems.BeginUpdate; try for I := 0 to SummaryItems.Count - 1 do SummaryItems[I].AllNodes := AValue; finally SummaryItems.EndUpdate; end; end; begin inherited; case ACommand of tlcmNone..tlcmAverage: SetItemsVisibility(TcxSummaryKind(ACommand)); tlcmAllNodes: SetAllNodes(not IsAllNodes); end; end; function TcxTreeListFooterPopupMenu.GetResourceImagesCount: Integer; begin Result := 5; end; function TcxTreeListFooterPopupMenu.GetResourceImagesNamePrefix: string; begin Result := 'TLFTRIMG'; end; function TcxTreeListFooterPopupMenu.IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; begin Result := (AHitTest.HitAtFooterItem or AHitTest.HitAtFooter) and (AHitTest.FHitColumn <> nil); if Result then FSummaryItems := AHitTest.FHitColumn.Summary.FooterSummaryItems; end; function TcxTreeListFooterPopupMenu.GetVisibleItemKinds: TcxSummaryKinds; var I: Integer; begin Result := []; for I := 0 to SummaryItems.Count - 1 do if SummaryItems[I].Visible then Include(Result, SummaryItems[I].Kind); end; function TcxTreeListFooterPopupMenu.IsAllNodes: Boolean; var I: Integer; begin Result := False; for I := 0 to SummaryItems.Count - 1 do if SummaryItems[I].AllNodes then begin Result := True; Break; end; end; function TcxTreeListFooterPopupMenu.IsItemEnabled(AKind: TcxSummaryKind): Boolean; function IsSummaryKindAllowedForValueType(AValueTypeClass: TcxValueTypeClass): Boolean; const ANumberVarTypes = [varSmallint, varInteger, varSmallint, varSingle, varByte, varDouble, varCurrency, varDate, varLongWord, varWord, varInt64, varShortInt]; ATimeVarTypes = [varDate]; var AVarType: Integer; begin Result := False; if AValueTypeClass <> nil then begin AVarType := AValueTypeClass.GetVarType; Result := ((AVarType in ANumberVarTypes) or (AVarType = TcxFMTBcdValueType.GetVarType)) and not((AVarType in ATimeVarTypes) and (AKind in [skSum, skAverage])); end; end; var AColumn: TcxTreeListColumn; begin AColumn := SummaryItems.Column; Result := (AKind in [skCount, skNone]) or not(AColumn.Properties is TcxCustomLookupEditProperties) and IsSummaryKindAllowedForValueType(AColumn.ValueDef.ValueTypeClass); end; function TcxTreeListFooterPopupMenu.IsItemsStored: Boolean; begin Result := FItems <> [tlfmiSum, tlfmiMin, tlfmiMax, tlfmiAverage, tlfmiCount, tlfmiNone, tlfmiAllNodes]; end; { TcxTreeListGroupFooterPopupMenu } function TcxTreeListGroupFooterPopupMenu.IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; begin Result := (AHitTest.HitAtGroupFooterItem or AHitTest.HitAtGroupFooter) and (AHitTest.FHitColumn <> nil); if Result then FSummaryItems := AHitTest.FHitColumn.Summary.GroupFooterSummaryItems; end; { TcxTreeListColumnHeaderPopupMenu } constructor TcxTreeListColumnHeaderPopupMenu.Create(AOwner: TPersistent); begin inherited Create(AOwner); FItems := [tlchmiSortAscending, tlchmiSortDescending, tlchmiClearSorting, tlchmiFooter, tlchmiGroupFooters, tlchmiRemoveThisColumn, tlchmiFieldChooser, tlchmiHorzAlignment, tlchmiVertAlignment, tlchmiBestFit, tlchmiBestFitAllColumns]; end; procedure TcxTreeListColumnHeaderPopupMenu.Assign(Source: TPersistent); begin inherited Assign(Source); if Source is TcxTreeListColumnHeaderPopupMenu then FItems := TcxTreeListColumnHeaderPopupMenu(Source).Items; end; procedure TcxTreeListColumnHeaderPopupMenu.CreateItems; var ASubMenu: TComponent; AAlignmentMenuItemsNeeded: Boolean; begin inherited CreateItems; if tlchmiSortAscending in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListSortAscendingMenuItem), tlcmSortAscending, True, tlmitChecked, Column.SortOrder = soAscending, 0); if tlchmiSortDescending in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListSortDescendingMenuItem), tlcmSortDescending, True, tlmitChecked, Column.SortOrder = soDescending, 1); if tlchmiClearSorting in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListClearSortingMenuItem), tlcmClearSorting, Column.SortOrder <> soNone, tlmitDefault, False, - 1); FSeparatorNeeded := True; if tlchmiFooter in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListFooterMenuItem), tlcmFooter, True, tlmitChecked, TreeList.OptionsView.Footer, 4, IsSeparatorNeeded); if tlchmiGroupFooters in Items then begin ASubMenu := CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListGroupFootersMenuItem), -1, True, tlmitSubItem, False, 5, IsSeparatorNeeded); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListGroupFootersInvisibleMenuItem), tlcmGroupFootersInvisible, True, tlmitChecked, TreeList.OptionsView.GroupFooters = tlgfInvisible); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListGroupFootersVisibleWhenExpandedMenuItem), tlcmGroupFootersVisibleWhenExpanded, True, tlmitChecked, TreeList.OptionsView.GroupFooters = tlgfVisibleWhenExpanded); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListGroupFootersAlwaysVisibleMenuItem), tlcmGroupFootersAlwaysVisible, True, tlmitChecked, TreeList.OptionsView.GroupFooters = tlgfAlwaysVisible); end; FSeparatorNeeded := True; if (tlchmiRemoveThisColumn in Items) and not Column.Options.Hidden and Column.CanMoving and (TreeList.VisibleColumnCount > 1) then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListRemoveThisColumnMenuItem), tlcmRemoveThisColumn, True, tlmitDefault, False, - 1, IsSeparatorNeeded); if tlchmiFieldChooser in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListFieldChooserMenuItem), tlcmFieldChooser, True, tlmitDefault, False, 2, IsSeparatorNeeded); FSeparatorNeeded := True; AAlignmentMenuItemsNeeded := Column.Properties <> nil; if AAlignmentMenuItemsNeeded then CreateAlignmentSubMenus; if tlchmiBestFit in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListBestFitMenuItem), tlcmBestFit, True, tlmitDefault, False, 3, IsSeparatorNeeded); if tlchmiBestFitAllColumns in Items then CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListBestFitAllColumnsMenuItem), tlcmBestFitAllColumns, True, tlmitDefault, False, - 1, True); end; procedure TcxTreeListColumnHeaderPopupMenu.DoExecute(ACommand: Integer); begin inherited; case ACommand of tlcmSortAscending: Column.SortOrder := soAscending; tlcmSortDescending: Column.SortOrder := soDescending; tlcmClearSorting: Column.SortOrder := soNone; tlcmFooter: TreeList.OptionsView.Footer := not TreeList.OptionsView.Footer; tlcmGroupFootersInvisible..tlcmGroupFootersAlwaysVisible: TreeList.OptionsView.GroupFooters := TcxTreeListGroupFootersMode(ACommand - tlcmGroupFootersInvisible); tlcmRemoveThisColumn: Column.Visible := False; tlcmFieldChooser: TreeList.Customizing.Visible := True; tlcmHorzAlignmentLeft..tlcmHorzAlignmentCenter: Column.Properties.Alignment.Horz := TcxEditHorzAlignment(ACommand - tlcmHorzAlignmentLeft); tlcmVertAlignmentTop..tlcmVertAlignmentCenter: Column.Properties.Alignment.Vert := TcxEditVertAlignment(ACommand - tlcmVertAlignmentTop); tlcmBestFit: Column.ApplyBestFit; tlcmBestFitAllColumns: TreeList.ApplyBestFit; end; end; function TcxTreeListColumnHeaderPopupMenu.GetResourceImagesCount: Integer; begin Result := 6; end; function TcxTreeListColumnHeaderPopupMenu.GetResourceImagesNamePrefix: string; begin Result := 'TLHDRIMG'; end; function TcxTreeListColumnHeaderPopupMenu.IsPopupSuitable(AHitTest: TcxTreeListHitTest): Boolean; begin Result := AHitTest.HitAtColumnHeader; if Result then Column := AHitTest.HitColumn; end; procedure TcxTreeListColumnHeaderPopupMenu.CreateAlignmentSubMenus; var ASubMenu: TComponent; begin if tlchmiHorzAlignment in Items then begin ASubMenu := CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListHorizontalAlignmentMenuItem), -1, True, tlmitSubItem, False, -1, IsSeparatorNeeded); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListHorizontalAlignmentLeftMenuItem), tlcmHorzAlignmentLeft, True, tlmitChecked, Column.Properties.Alignment.Horz = taLeftJustify); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListHorizontalAlignmentCenterMenuItem), tlcmHorzAlignmentCenter, True, tlmitChecked, Column.Properties.Alignment.Horz = taCenter); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListHorizontalAlignmentRightMenuItem), tlcmHorzAlignmentRight, True, tlmitChecked, Column.Properties.Alignment.Horz = taRightJustify); end; if tlchmiVertAlignment in Items then begin ASubMenu := CreateInternalMenuItem(Root, cxGetResourceString(@scxTreeListVerticalAlignmentMenuItem), -1, True, tlmitSubItem, False, -1, IsSeparatorNeeded); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListVerticalAlignmentTopMenuItem), tlcmVertAlignmentTop, True, tlmitChecked, Column.Properties.Alignment.Vert = taTopJustify); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListVerticalAlignmentCenterMenuItem), tlcmVertAlignmentCenter, True, tlmitChecked, Column.Properties.Alignment.Vert = taVCenter); CreateInternalMenuItem(ASubMenu, cxGetResourceString(@scxTreeListVerticalAlignmentBottomMenuItem), tlcmVertAlignmentBottom, True, tlmitChecked, Column.Properties.Alignment.Vert = taBottomJustify); end; end; function TcxTreeListColumnHeaderPopupMenu.IsItemsStored: Boolean; begin Result := FItems <> [tlchmiSortAscending, tlchmiSortDescending, tlchmiClearSorting, tlchmiFooter, tlchmiGroupFooters, tlchmiRemoveThisColumn, tlchmiFieldChooser, tlchmiHorzAlignment, tlchmiVertAlignment, tlchmiBestFit, tlchmiBestFitAllColumns]; end; function TcxTreeListColumnHeaderPopupMenu.IsSeparatorNeeded: Boolean; begin Result := FSeparatorNeeded; FSeparatorNeeded := False; end; { TcxTreeListPopupMenus } constructor TcxTreeListPopupMenus.Create(AOwner: TPersistent); begin inherited Create(AOwner); FMenus := TObjectList.Create; CreateMenus; end; destructor TcxTreeListPopupMenus.Destroy; begin FreeAndNil(FMenus); inherited Destroy; end; procedure TcxTreeListPopupMenus.Assign(Source: TPersistent); begin if Source is TcxTreeListPopupMenus then begin ColumnHeaderMenu := TcxTreeListPopupMenus(Source).ColumnHeaderMenu; GroupFooterMenu := TcxTreeListPopupMenus(Source).GroupFooterMenu; FooterMenu := TcxTreeListPopupMenus(Source).FooterMenu; end else inherited Assign(Source); end; procedure TcxTreeListPopupMenus.CreateMenus; begin FFooterMenu := TcxTreeListFooterPopupMenu.Create(Self); FMenus.Add(FFooterMenu); FGroupFooterMenu := TcxTreeListGroupFooterPopupMenu.Create(Self); FMenus.Add(FGroupFooterMenu); FColumnHeaderMenu := TcxTreeListColumnHeaderPopupMenu.Create(Self); FMenus.Add(FColumnHeaderMenu); end; function TcxTreeListPopupMenus.DoShowPopupMenu(const P: TPoint): Boolean; var I: Integer; begin Result := False; for I := 0 to FMenus.Count - 1 do if TcxTreeListPopupMenu(FMenus[I]).DoShowPopupMenu(P) then begin Result := True; Break; end; end; procedure TcxTreeListPopupMenus.Notification(AComponent: TComponent; Operation: TOperation); var I: Integer; begin for I := 0 to FMenus.Count - 1 do TcxTreeListPopupMenu(FMenus[I]).Notification(AComponent, Operation); end; function TcxTreeListPopupMenus.GetHitTest: TcxTreeListHitTest; begin Result := TreeList.HitTest; end; function TcxTreeListPopupMenus.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Owner); end; procedure TcxTreeListPopupMenus.SetColumnHeaderMenu(AValue: TcxTreeListColumnHeaderPopupMenu); begin FColumnHeaderMenu.Assign(AValue); end; procedure TcxTreeListPopupMenus.SetFooterMenu( AValue: TcxTreeListFooterPopupMenu); begin FFooterMenu.Assign(AValue); end; procedure TcxTreeListPopupMenus.SetGroupFooterMenu( AValue: TcxTreeListGroupFooterPopupMenu); begin FGroupFooterMenu.Assign(AValue); end; { TcxTreeListOptionsView } constructor TcxTreeListOptionsView.Create(AOwner: TPersistent); begin inherited Create(AOwner); FIndicatorWidth := cxTreeListDefIndicatorWidth; FFixedSeparatorWidth := cxTreeListDefSeparatorWidth; FDropArrowColor := cxTreeListDefDropArrowColor; FButtons := True; FHeaders := True; FFixedSeparatorColor := clDefault; FGridLineColor := clDefault; FTreeLineColor := clDefault; FTreeLineStyle := tllsDot; FUseNodeColorForIndent := True; FUseImageIndexForSelected := True; FShowRoot := True; end; procedure TcxTreeListOptionsView.Assign(Source: TPersistent); var ASource: TcxTreeListOptionsView; begin if Source is TcxTreeListOptionsView then begin ASource := TcxTreeListOptionsView(Source); FCategorizedColumn := TreeList.GetSameColumn(ASource.FCategorizedColumn); FBandLineHeight := ASource.FBandLineHeight; FBands := ASource.FBands; FButtons := ASource.FButtons; FColumnAutoWidth := ASource.ColumnAutoWidth; FCheckGroups := ASource.CheckGroups; FDropArrowColor := ASource.FDropArrowColor; FDropArrowColor := ASource.FDropArrowColor; FDynamicIndent := ASource.FDynamicIndent; FDynamicFocusedStateImages := ASource.FDynamicFocusedStateImages; FExtPaintStyle := ASource.FExtPaintStyle; FFixedSeparatorColor := ASource.FFixedSeparatorColor; FFixedSeparatorWidth := ASource.FixedSeparatorWidth; FGridLineColor := ASource.GridLineColor; FGridLines := ASource.FGridLines; FGroupFooters := ASource.GroupFooters; FHeaders := ASource.FHeaders; FIndicator := ASource.FIndicator; FIndicatorWidth := ASource.FIndicatorWidth; FPaintStyle := ASource.FPaintStyle; FShowRoot := ASource.FShowRoot; FSimpleCustomizeBox := ASource.FSimpleCustomizeBox; FTreeLineColor := ASource.FTreeLineColor; FTreeLineStyle := ASource.FTreeLineStyle; FUseImageIndexForSelected := ASource.FUseImageIndexForSelected; FUseNodeColorForIndent := ASource.FUseNodeColorForIndent; 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 FBandLineHeight := 0; FBands := False; FButtons := True; FColumnAutoWidth := False; FCheckGroups := False; FDropArrowColor := cxTreeListDefDropArrowColor; FDynamicIndent := False; FDynamicFocusedStateImages := False; FExtPaintStyle := False; FFixedSeparatorColor := clDefault; FFixedSeparatorWidth := cxTreeListDefSeparatorWidth; FFooter := False; FGridLineColor := clDefault; FGridLines := tlglNone; FGroupFooters := tlgfInvisible; FHeaders := True; FIndicator := False; FIndicatorWidth := cxTreeListDefIndicatorWidth; FPaintStyle := tlpsStandard; FShowRoot := True; FSimpleCustomizeBox := False; FTreeLineColor := clDefault; FTreeLineStyle := tllsDot; FUseImageIndexForSelected := True; FUseNodeColorForIndent := True; Changed; end; procedure TcxTreeListOptionsView.Changed; begin TreeList.LayoutChanged; end; function TcxTreeListOptionsView.GetControl: TObject; begin Result := TreeList; 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.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.GetIsIndicatorVisible: Boolean; begin with TreeList.OptionsCustomizing do begin Result := Indicator or (BandsQuickCustomization and BandCustomizing) or (ColumnsQuickCustomization and ColumnCustomizing); end; end; function TcxTreeListOptionsView.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(EditingControl); end; procedure TcxTreeListOptionsView.SetCategorizedColumn(AValue: TcxTreeListColumn); begin if AValue <> FCategorizedColumn then begin FCategorizedColumn := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetCheckGroups(AValue: Boolean); begin if AValue <> FCheckGroups then begin FCheckGroups := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetColumnAutoWidth(AValue: Boolean); begin if AValue <> FColumnAutoWidth then begin FColumnAutoWidth := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetDynamicIndent(AValue: Boolean); begin if AValue <> FDynamicIndent then begin FDynamicIndent := AValue; TreeList.ImagesChanged(nil); end; end; procedure TcxTreeListOptionsView.SetBandLineHeight(AValue: Integer); begin if AValue < 0 then Exit; if AValue <> FBandLineHeight then begin FBandLineHeight := AValue; if Bands then Changed; end; end; procedure TcxTreeListOptionsView.SetBands(AValue: Boolean); begin if AValue <> Bands then begin FBands := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetButtons(AValue: Boolean); begin if AValue <> FButtons then begin FButtons := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetIndicator(AValue: Boolean); begin if AValue <> FIndicator then begin FIndicator := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetIndicatorWidth(AValue: Integer); begin if AValue < 0 then Exit; if AValue <> FIndicatorWidth then begin FIndicatorWidth := AValue; if Indicator then Changed; end; end; procedure TcxTreeListOptionsView.SetDynamicFocusedStateImages(AValue: Boolean); begin if AValue <> FDynamicFocusedStateImages then begin FDynamicFocusedStateImages := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetExtPaintStyle(AValue: Boolean); begin if AValue <> FExtPaintStyle then begin FExtPaintStyle := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetFixedSeparatorColor(AValue: TColor); begin if AValue <> FFixedSeparatorColor then begin FFixedSeparatorColor := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetFixedSeparatorWidth(AValue: Integer); begin if AValue < 0 then Exit; if AValue <> FFixedSeparatorWidth then begin FFixedSeparatorWidth := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetFooter(AValue: Boolean); begin if AValue <> FFooter then begin FFooter := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetGridLineColor(AValue: TColor); begin if AValue <> FGridLineColor then begin FGridLineColor := AValue; if GridLines <> tlglNone then Changed; end; end; procedure TcxTreeListOptionsView.SetGridLines(AValue: TcxTreeListGridLines); begin if AValue <> FGridLines then begin FGridLines := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetGroupFooters( AValue: TcxTreeListGroupFootersMode); begin if AValue <> FGroupFooters then begin FGroupFooters := AValue; TreeList.StructureChanged; end; end; procedure TcxTreeListOptionsView.SetHeaders(AValue: Boolean); begin if AValue <> FHeaders then begin FHeaders := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetPaintStyle(AValue: TcxTreeListPaintStyle); begin if AValue <> FPaintStyle then begin FPaintStyle := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetShowRoot(AValue: Boolean); begin if AValue <> FShowRoot then begin FShowRoot := AValue; TreeList.ImagesChanged(nil); end; end; procedure TcxTreeListOptionsView.SetSimpleCustomizeBox(AValue: Boolean); begin if AValue <> FSimpleCustomizeBox then begin FSimpleCustomizeBox := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetTreeLineColor(AValue: TColor); begin if AValue <> FTreeLineColor then begin FTreeLineColor := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetTreeLineStyle( AValue: TcxTreeListTreeLineStyle); begin if AValue <> FTreeLineStyle then begin FTreeLineStyle := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetUseImageIndexForSelected(AValue: Boolean); begin if AValue <> FUseImageIndexForSelected then begin FUseImageIndexForSelected := AValue; Changed; end; end; procedure TcxTreeListOptionsView.SetUseNodeColorForIndent(AValue: Boolean); begin if AValue <> FUseNodeColorForIndent then begin FUseNodeColorForIndent := AValue; Changed; end; end; { TcxTreeListViewInfo } constructor TcxTreeListViewInfo.Create(AOwner: TcxEditingControl); begin inherited Create(AOwner); FHitTestCells := TcxObjectList.Create; FHeaderCells := TList.Create; FFakeCell := TcxFakeCellViewInfo.Create(Self); FCells := TcxCustomControlCells.Create; FNodesViewData := TcxObjectList.Create; FCheckBoxProperties := TcxCheckBoxProperties.Create(nil); TcxCheckBoxProperties(FCheckBoxProperties).AllowGrayed := True; TcxCheckBoxProperties(FCheckBoxProperties).ValueChecked := Integer(cbsChecked); TcxCheckBoxProperties(FCheckBoxProperties).ValueUnchecked := Integer(cbsUnchecked); TcxCheckBoxProperties(FCheckBoxProperties).ValueGrayed := Integer(cbsGrayed); FCheckBoxViewInfo := TcxCustomEditViewInfo(FCheckBoxProperties.GetViewInfoClass.Create); RecreateCheckBoxViewData; end; destructor TcxTreeListViewInfo.Destroy; begin Clear; FreeAndNil(FCheckBoxViewData); FreeAndNil(FCheckBoxViewInfo); FreeAndNil(FCheckBoxProperties); FreeAndNil(FHeaderCells); FreeAndNil(FNodesViewData); FreeAndNil(FFakeCell); FreeAndNil(FCells); FreeAndNil(FHitTestCells); inherited Destroy; end; function TcxTreeListViewInfo.GetEditCell(ANode: TcxTreeListNode; AColumn: TcxTreeListColumn): TcxTreeListEditCellViewInfo; var I: Integer; begin Result := nil; if (ANode = nil) or (ANode.ViewData = nil) then Exit; for I := 0 to ANode.ViewData.Cells.Count - 1 do if (TObject(ANode.ViewData.Cells[I]) is TcxTreeListEditCellViewInfo) and (TcxTreeListEditCellViewInfo(ANode.ViewData.Cells[I]).Column = AColumn) then begin Result := TcxTreeListEditCellViewInfo(ANode.ViewData.Cells[I]); Break; end; end; function TcxTreeListViewInfo.Validate: Boolean; begin Result := (IsDirty or (TreeList.Changes - [tcSelection, tcFocusedNode] <> [])) and not CalculateInProcess; if Result then TreeList.ForceLayoutChanged; end; function TcxTreeListViewInfo.AddBackgroundPart( const ABounds: TRect): TcxTreeListBackgroundCellViewInfo; begin AddCell(TcxTreeListBackgroundCellViewInfo, ABounds, ABounds, Result); Result.ItemViewParams := Styles.GetBackgroundParams; end; function TcxTreeListViewInfo.AddBandHeader(ABand: TcxTreeListBand; var ABounds: TRect; const AClipRect: TRect): TcxTreeListBandHeaderCellViewInfo; var R: TRect; begin R := ABounds; R.Right := ABounds.Left + ABand.DisplayWidth; R.Bottom := R.Top + ABand.LineCount * BandLineHeight; AddCell(TcxTreeListBandHeaderCellViewInfo, R, AClipRect, Result); Result.Initialize(ABand.Caption); ABounds.Left := R.Right; ABand.FHeaderCell := Result; if ABand.IsFirstInGroup and not ABand.IsLeftMost then Exclude(Result.FBorders, bLeft); if cxRectHeight(ABounds) > 0 then AddHeaderHitTestAreas(Result, ABand.CanSizing(dsdHorz), ABand.CanSizing(dsdVert)); FHeaderCells.Add(Result); end; function TcxTreeListViewInfo.AddBandPart(APart: TcxTreeListBandPart; ABand: TcxTreeListBand; ANode, AAttachNode: TcxTreeListNode; ABounds, AClipRect: TRect): TcxTreeListBandCellViewInfo; begin if APart in [tlbpContent, tlbpSeparator] then InflateBoundsForGridLines(ABounds, AClipRect); AddCell(TcxTreeListBandCellViewInfo, ABounds, AClipRect, Result); if APart = tlbpContent then Result.FBorders := GridLines; if (APart = tlbpHeader) and (bRight in GridLines) and ABand.IsRightMost and (Count > 0) then Include(Result.FBorders, bRight); Result.Initialize(ABand, ANode, AAttachNode, APart); end; function TcxTreeListViewInfo.AddBandSeparator(ANode: TcxTreeListNode; var ABounds: TRect; const AClipBounds: TRect): TcxTreeListBandCellViewInfo; begin Result := AddBandPart(tlbpSeparator, nil, ANode, ANode, cxRectSetWidth(ABounds, FixedSeparatorWidth), AClipBounds); Result.FBorders := []; Inc(ABounds.Left, FixedSeparatorWidth); end; procedure TcxTreeListViewInfo.AddBandsHeaders( AKind: TcxTreeListBandFixedKind; const ABounds, AClipBounds: TRect); procedure AddSubItems(AParent: TcxTreeListBand; var R: TRect); var I: Integer; ASubBounds: TRect; begin if not AParent.Visible then Exit; ASubBounds := R; R.Bottom := R.Top + AParent.LineCount * BandLineHeight; AddBandHeader(AParent, R, AClipBounds); ASubBounds.Top := R.Bottom; for I := 0 to AParent.ChildBandCount - 1 do AddSubItems(AParent.ChildBands[I], ASubBounds); end; var I: Integer; R: TRect; ABand: TcxTreeListBand; begin R := ABounds; for I := 0 to Bands.VisibleRootItemCount - 1 do begin ABand := Bands.VisibleRootItems[I]; if ABand.FixedKind = AKind then AddSubItems(ABand, R); end; end; procedure TcxTreeListViewInfo.AddCell( ACellClass: TcxTreeListCustomCellViewInfoClass; const ABounds, AVisibleRect: TRect; var AInstance); begin Pointer(AInstance) := ACellClass.CreateEx(TreeList, ABounds, AVisibleRect); TcxTreeListCustomCellViewInfo(AInstance).FBorderColor := GridLineColor; Cells.Add(Pointer(AInstance)); end; function TcxTreeListViewInfo.AddColumnHeader(AColumn: TcxTreeListColumn; var ABounds: TRect; const AClipBounds: TRect): TcxTreeListColumnHeaderCellViewInfo; var R: TRect; ABand: TcxTreeListBand; begin R := ABounds; R.Right := R.Left + AColumn.DisplayWidth; AddCell(TcxTreeListColumnHeaderCellViewInfo, R, AClipBounds, Result); Result.Initialize(AColumn.Caption); ABand := AColumn.Position.Band; if (AColumn.Position.VisibleColIndex = 0) and ABand.IsFirstInGroup and not ABand.IsLeftMost and (bRight in GridLines) then Exclude(Result.FBorders, bLeft); AColumn.FHeaderCell := Result; ABounds.Left := R.Right; FHeaderCells.Add(Result); if cxRectHeight(ABounds) > 0 then AddHeaderHitTestAreas(Result, AColumn.CanSizing(dsdHorz), AColumn.CanSizing(dsdVert)); end; function TcxTreeListViewInfo.AddEditCell(AViewData: TcxTreeListNodeViewData; AColumn: TcxTreeListColumn; ABounds, AClipRect: TRect; AClass: TcxEditCellViewInfoClass): TcxTreeListEditCellViewInfo; begin InflateBoundsForGridLines(ABounds, AClipRect); Result := TcxTreeListEditCellViewInfo(AClass.Create(AColumn)); Result.FNodeViewData := AViewData; Result.CellBorders := GridLines; Result.BorderColor := GridLineColor; Result.CheckClipping(ABounds, AClipRect); AColumn.InitEditViewInfo(Result); Result.CheckVisibleInfo; Cells.Add(Result); end; procedure TcxTreeListViewInfo.AddColumnFooterItems( ADataNode, AttachNode: TcxTreeListNode; AColumn: TcxTreeListColumn; const ABounds, AClipRect: TRect); var I: Integer; R: TRect; AMultiLine: Boolean; AItems: TcxTreeListSummaryItems; ACell: TcxTreeListFooterCellViewInfo; AOffset: Integer; begin R := cxRectSetTop(ABounds, AClipRect.Top + AColumn.Position.Row.LineOffset * FooterLineHeight, AColumn.Position.LineCount * FooterLineHeight); AOffset := 0; if not IsPrinting then begin InflateRect(R, -Painter.FooterCellOffset, 0); Dec(R.Bottom); AOffset := Painter.FooterCellOffset; end; if ADataNode = Root then begin AItems := AColumn.Summary.FooterSummaryItems; AMultiLine := not MultiRows and (Summary.FooterSummaryRowCount > 1); end else begin AItems := AColumn.Summary.GroupFooterSummaryItems; AMultiLine := not MultiRows and (Summary.GroupFooterSummaryRowCount > 1); end; if not AMultiLine or (AItems.Count = 0) then begin AddCell(TcxTreeListFooterMultiItemsCellViewInfo, cxRectSetHeight(R, cxRectHeight(R) - AOffset) , AClipRect, ACell); TcxTreeListFooterMultiItemsCellViewInfo(ACell).Initialize(ADataNode, AttachNode, AColumn, AItems); end else for I := 0 to AItems.Count - 1 do if AItems[I].Visible then begin AddCell(TcxTreeListFooterSingleCellViewInfo, cxRectSetHeight(R, cxRectHeight(R) - AOffset), AClipRect, ACell); TcxTreeListFooterSingleCellViewInfo(ACell).Initialize(ADataNode, AttachNode, AColumn, AItems[I]); OffsetRect(R, 0, FooterLineHeight * AColumn.Position.LineCount); end; end; procedure TcxTreeListViewInfo.AddFixedSeparators(ABounds: TRect; AAttachNode: TcxTreeListNode); var R: TRect; begin if FixedSeparatorWidth = 0 then Exit; R := cxRectSetWidth(ABounds, FixedSeparatorWidth); if Bands.VisibleLeftFixedCount > 0 then begin R := cxRectSetLeft(R, ContentParts[tlbfLeft].Right); AddBandPart(tlbpSeparator, nil, AAttachNode, AAttachNode, R, R); end; if (Bands.VisibleRootRightFixedCount > 0) and ((R.Right <= ContentParts[tlbfRight].Left) or (Bands.VisibleRootLeftFixedCount = 0)) then begin R := cxRectSetRight(R, ContentParts[tlbfRight].Left); if R.Left < IndicatorWidth then R.Left := IndicatorWidth; if R.Left >= R.Right then Exit; AddBandPart(tlbpSeparator, nil, AAttachNode, AAttachNode, R, R); end; end; procedure TcxTreeListViewInfo.AddFooter(AAttachNode: TcxTreeListNode; AIndex, AIndent: Integer; const ABounds: TRect); var I, J: Integer; ABand: TcxTreeListBand; AClipRect, ACellsClipRect, R: TRect; AColumn: TcxTreeListColumn; ADataNode: TcxTreeListNode; APart: TcxTreeListBandCellViewInfo; const BandPart: array[Boolean] of tcxTreeListBandPart = (tlbpGroupFooter, tlbpFooter); begin ADataNode := AAttachNode; if AAttachNode = Root then AAttachNode := nil; for I := 0 to AIndex - 1 do ADataNode := ADataNode.Parent; for I := 0 to Bands.BottomItemCount - 1 do begin ABand := Bands.BottomItems[I]; R := cxRectSetYPos(ABand.HeaderCell.DisplayRect, ABounds.Top, ABounds.Bottom); AClipRect := cxRectSetYPos(ABand.HeaderCell.VisibleRect, ABounds.Top, ABounds.Bottom); if (ADataNode <> Root) and (ABand = Bands.ExpandableBand) then begin Inc(R.Left, AIndent); if I = 0 then AClipRect.Left := Min(AClipRect.Left, R.Left); end; ACellsClipRect := R; if (I = 0) and not IsPrinting then Inc(ACellsClipRect.Left); if I = Bands.BottomItemCount - 1 then Dec(ACellsClipRect.Right); APart := AddBandPart(BandPart[ADataNode = Root], ABand, ADataNode, AAttachNode, R, AClipRect); APart.FBorders := [bTop, bBottom]; APart.BorderColor := Painter.FooterSeparatorColor; if (Bands.ExpandableBand = ABand) and (APart.Part = tlbpGroupFooter) then Include(APart.FBorders, bLeft); if (I = (Bands.BottomItemCount - 1)) or (APart.Part = tlbpGroupFooter) and (Bands.BottomItems[I + 1] = Bands.ExpandableBand) then Include(APart.FBorders, bRight); if not IsPrinting then begin Inc(AClipRect.Top, Painter.FooterSeparatorSize + Painter.FooterSeparatorSize + Painter.FooterCellOffset); Dec(AClipRect.Bottom, Painter.FooterBorderSize); end; for J := 0 to ABand.VisibleColumnCount - 1 do begin AColumn := ABand.VisibleColumns[J]; if ((ADataNode = Root) and not AColumn.Options.Footer) or ((ADataNode <> Root) and not AColumn.Options.GroupFooter) then Continue; if cxRectIntersect(R, ACellsClipRect, cxRectSetYPos(AColumn.HeaderCell.DisplayRect, AClipRect.Top, AClipRect.Bottom)) then begin if (ABand = Bands.ExpandableBand) and (I <> 0) and not IsPrinting then Inc(R.Left); AddColumnFooterItems(ADataNode, AAttachNode, ABand.VisibleColumns[J], R, AClipRect); end; end; AddFixedSeparators(cxRectInflate(ABounds, 0, -Painter.FooterBorderSize), AAttachNode); end; end; procedure TcxTreeListViewInfo.AddHeaderHitTestAreas( ACell: TcxTreeListHeaderCellViewInfo; AHorz, AVert: Boolean); begin if AHorz then FHitTestCells.Add(TcxTreeListHeaderSizingArea.CreateEx(ACell, dsdHorz)); if AVert then FHitTestCells.Add(TcxTreeListHeaderSizingArea.CreateEx(ACell, dsdVert)); end; function TcxTreeListViewInfo.AddImageIndent(ANode: TcxTreeListNode; AImages: TCustomImageList; var ABounds: TRect; const AClipRect: TRect): TcxTreeListIndentCellViewInfo; begin ABounds.Right := ABounds.Left + AImages.Width + cxTreeListIndentOffsetSize div 2; Result := AddIndent(ANode, ANode, -1, nikImage, ABounds, AClipRect); Result.InitializeImageIndent(AImages); end; function TcxTreeListViewInfo.AddIndent(ANode, AAttachNode: TcxTreeListNode; ALevel: Integer; AKind: TcxTreeListNodeIndentKind; var ABounds: TRect; const AClipRect: TRect): TcxTreeListIndentCellViewInfo; begin if ALevel <> -1 then ABounds.Right := ABounds.Left + LevelInfo[ALevel].Size.cx else ALevel := ANode.Level; AddCell(TcxTreeListIndentCellViewInfo, ABounds, AClipRect, Result); Result.FKind := AKind; Result.InitializeLevelIndent(ANode, AAttachNode, ALevel); ABounds.Left := ABounds.Right; if (bBottom in GridLines) and ANode.IsLastVisible and ((AKind = nikFooter) or not HasFooter(ANode)) then Include(Result.FBorders, bBottom); end; function TcxTreeListViewInfo.AddIndentCheck(ANode: TcxTreeListNode; var ABounds: TRect; const AClipRect: TRect): TcxTreeListIndentCellViewInfo; begin ABounds.Right := ABounds.Left + CheckboxSize.cx; Result := AddIndent(ANode, ANode, -1, nikCheck, ABounds, AClipRect); end; function TcxTreeListViewInfo.AddIndicator(ANode: TcxTreeListNode; APosition: TcxTreeListIndicatorPosition; var ABounds: TRect): TcxTreeListIndicatorCellViewInfo; var R: TRect; begin R := ABounds; R.Right := R.Left + OptionsView.IndicatorWidth; AddCell(TcxTreeListIndicatorCellViewInfo, R, ABounds, Result); Result.Initialize(ANode, APosition); if APosition in [tlipBands, tlipColumns] then FHeaderCells.Add(Result); ABounds.Left := R.Right; if (ANode <> nil) and (TreeList.OptionsCustomizing.NodeSizing or TreeList.OptionsCustomizing.RowSizing) then begin Result.SizingArea := TcxTreeListNodeSizingArea.Create(Result); FHitTestCells.Add(Result.SizingArea); end; end; procedure TcxTreeListViewInfo.AddNodeBands(AViewData: TcxTreeListNodeViewData); var I: Integer; ABand: TcxTreeListBand; AClipRect, R: TRect; begin AClipRect := cxRectSetTop(cxNullRect, RowOffset[0], AViewData.RowsHeight); for I := 0 to Bands.BottomItemCount - 1 do begin ABand := Bands.BottomItems[I]; R := cxRectSetTop(ABand.HeaderCell.DisplayRect, RowOffset[0], AViewData.RowsHeight); AClipRect := cxRectSetTop(ABand.HeaderCell.VisibleRect, RowOffset[0], AViewData.RowsHeight); if I = 0 then AViewData.Bounds.TopLeft := R.TopLeft; if ABand.ActuallyExpandable then Inc(R.Left, AViewData.IndentWidth + Byte(bLeft in GridLines)); if I = 0 then AViewData.ContentBounds.TopLeft := R.TopLeft; AViewData.ContentBounds.BottomRight := R.BottomRight; AViewData.Bounds.BottomRight := R.BottomRight; AddBandPart(tlbpContent, ABand, AViewData.Node, AViewData.Node, R, AClipRect); end; AddFixedSeparators(AClipRect, AViewData.Node); end; procedure TcxTreeListViewInfo.AddNodeCategorized( AViewData: TcxTreeListNodeViewData); var AHeight: Integer; begin AHeight := AViewData.Node.Height; if AHeight = 0 then AHeight := DefaultRowHeight; if OptionsView.CellAutoHeight then begin AHeight := Max(AHeight, LevelInfo[AViewData.Node.Level].Size.cy); AHeight := TcxFakeCellViewInfo(FakeCell).MeasureHeight( OptionsView.GetCategorizedColumn, AViewData.Node, True); end; TreeList.DoGetNodeHeight(AViewData.Node, AHeight); AViewData.Bounds := cxRectSetTop(ContentBounds, AViewData.Height, AHeight); if Bands.VisibleLeftFixedCount = 0 then OffsetRect(AViewData.Bounds, -HScrollPos, 0); AViewData.ContentBounds := AViewData.Bounds; Inc(AViewData.ContentBounds.Left, AViewData.IndentWidth + IndicatorWidth + Byte(bLeft in GridLines)); if (Bands.VisibleRightFixedCount > 0) and (AViewData.ContentBounds.Left > ContentParts[tlbfRight].Left) then begin AViewData.ContentBounds.Left := ContentParts[tlbfRight].Left + AViewData.IndentWidth + Byte(bLeft in GridLines); AViewData.Bounds.Left := ContentParts[tlbfRight].Left; AddFixedSeparators(AViewData.Bounds, AViewData.Node); Inc(AViewData.Bounds.Left, FixedSeparatorWidth); end; AViewData.Bounds.Right := Min(AViewData.Bounds.Right, Bounds.Right); AViewData.ContentBounds.Right := AViewData.Bounds.Right; AddEditCell(AViewData, OptionsView.GetCategorizedColumn, AViewData.ContentBounds, AViewData.Bounds, TcxTreeListGroupNodeEditViewInfo); AViewData.RowsHeight := AHeight; Inc(AViewData.Height, AHeight); end; procedure TcxTreeListViewInfo.AddNodeColumns(AViewData: TcxTreeListNodeViewData); var I: Integer; AClipRect, R: TRect; ARow: TcxTreeListBandRow; AColumn: TcxTreeListColumn; begin for I := ColumnCount - 1 downto 0 do begin AColumn := Columns[I]; ARow := AColumn.Position.Row; R := cxRectSetYPos(AColumn.HeaderCell.DisplayRect, RowOffset[ARow.LineOffset], RowOffset[ARow.LineOffset + AColumn.Position.LineCount]); if AColumn.HasIndent then Inc(R.Left, AViewData.IndentWidth + Byte(bLeft in GridLines)); AClipRect := cxRectSetYPos(AColumn.HeaderCell.VisibleRect, R.Top, R.Bottom); AddEditCell(AViewData, AColumn, R, AClipRect, TcxTreeListEditCellViewInfo); end; end; procedure TcxTreeListViewInfo.AddNodeFooters(AViewData: TcxTreeListNodeViewData); var R, ABounds: TRect; ANode, AAttachLevelNode: TcxTreeListNode; AIndex, ALevel, AOffset, AFooterLevel: Integer; begin AIndex := 1; ANode := AViewData.Node; AAttachLevelNode := ANode; AViewData.CheckFooterRgn := [bTop, bBottom] * GridLines <> []; AFooterLevel := ANode.Level; if not ANode.HasChildren or ANode.Expanded or (OptionsView.GroupFooters <> tlgfAlwaysVisible) and (ANode.Parent <> Root) then ANode := ANode.Parent else AIndex := 0; if (OptionsView.GroupFooters = tlgfAlwaysVisible) and (ANode <> AViewData.Node) and not (ANode = Root) then Dec(AFooterLevel); repeat ABounds := cxRectSetTop(AViewData.Bounds, AViewData.Height - 1 + Byte(IsPrinting), GroupFooterHeight + 1 - Byte(IsPrinting)); AOffset := LevelInfo[AFooterLevel].Offset; if OptionsView.ShowRoot or (AFooterLevel > 0) then Inc(AOffset, TreeList.DefaultIndentSize.cx); AddFooter(AViewData.Node, AIndex, AOffset, ABounds); Inc(AViewData.GroupFooterCount); if Bands.ExpandableBand <> nil then begin R := cxRectSetLeft(ABounds, Bands.ExpandableBand.HeaderCell.DisplayRect.Left); ABounds := cxRectSetLeft(ABounds, Bands.ExpandableBand.HeaderCell.VisibleRect.Left); for ALevel := Byte(not OptionsView.ShowRoot) to AFooterLevel do AddIndent(AViewData.Node, AViewData.Node, ALevel, nikFooter, R, ABounds); end; Inc(AViewData.Height, GroupFooterHeight); if ANode.GetNextSiblingVisible <> nil then Break; ANode := ANode.Parent; AAttachLevelNode := AAttachLevelNode.Parent; Dec(AFooterLevel); Inc(AIndex); until (ANode = nil) or (ANode = Root) or (AAttachLevelNode.GetNextSiblingVisible <> nil); end; procedure TcxTreeListViewInfo.AddNodeIndents(AViewData: TcxTreeListNodeViewData); var I, ALevel: Integer; ABounds, AClipRect: TRect; AIndent: TcxTreeListIndentCellViewInfo; begin AIndent := nil; ALevel := AViewData.Node.Level; with Bands.ExpandableBand do begin ABounds := cxRectSetHeight(HeaderCell.DisplayRect, DefaultRowHeight); AClipRect := cxRectSetHeight(HeaderCell.VisibleRect, DefaultRowHeight); AViewData.IndentWidth := ABounds.Left; end; for I := Byte(not OptionsView.ShowRoot) to ALevel do AIndent := AddIndent(AViewData.Node, AViewData.Node, I, nikLevel, ABounds, AClipRect); if AViewData.Node.HasCheckbox then AIndent := AddIndentCheck(AViewData.Node, ABounds, AClipRect); if HasStateIndent(AViewData.Node) then begin AIndent := AddImageIndent(AViewData.Node, LevelInfo[ALevel].StateImages, ABounds, AClipRect); AIndent.FKind := nikState; AViewData.StateImageIndent := AIndent; end; if LevelInfo[ALevel].Images <> nil then begin AIndent := AddImageIndent(AViewData.Node, LevelInfo[ALevel].Images, ABounds, AClipRect); AViewData.ImageIndent := AIndent; end; if AIndent <> nil then AViewData.IndentWidth := AIndent.BoundsRect.Right - AViewData.IndentWidth else AViewData.IndentWidth := 0; end; function TcxTreeListViewInfo.AddNodePreview( AViewData: TcxTreeListNodeViewData): TcxTreeListEditCellViewInfo; var AClipRect, ABounds: TRect; APrevHeight, AHeight: Integer; begin if Preview.MaxLineCount > 0 then AHeight := Preview.MaxLineCount * PreviewLineHeight + cxTextOffset + OptionsView.VertIncrement else AHeight := ContentHeight; AClipRect := cxRectSetTop(ContentBounds, AViewData.Height, AHeight); if IsIndicatorVisible then Inc(AClipRect.Left, OptionsView.IndicatorWidth); ABounds := AClipRect; if IndentLeftMost then begin Inc(ABounds.Left, AViewData.IndentWidth + Byte(bLeft in GridLines)); if Bands.VisibleLeftFixedCount = 0 then OffsetRect(ABounds, -HScrollPos, 0); end; Result := AddEditCell(AViewData, Preview.Column, ABounds, AClipRect, TcxTreeListPreviewCellViewInfo) as TcxTreeListPreviewCellViewInfo; APrevHeight := AHeight; if Preview.AutoHeight then AHeight := Min(AHeight, Result.CalculateEditHeight - cxTextOffset - OptionsView.VertIncrement * 2); TreeList.DoGetPreviewHeight(AViewData.Node, AHeight); if AHeight < 0 then AHeight := 0; if AHeight <> APrevHeight then begin FCells.Delete(FCells.Count - 1); FreeAndNil(Result); if AHeight > 0 then begin if Preview.AutoHeight then Inc(AHeight, OptionsView.VertIncrement * 2 + cxTextOffset); ABounds := cxRectSetHeight(ABounds, AHeight); Result := AddEditCell(AViewData, Preview.Column, ABounds, cxRectSetHeight(AClipRect, AHeight), TcxTreeListPreviewCellViewInfo); end; end; AViewData.PreviewHeight := AHeight; Inc(AViewData.Height, AHeight); end; procedure TcxTreeListViewInfo.AddNodeStandardContent( AViewData: TcxTreeListNodeViewData); var AHeight: Integer; begin AHeight := AViewData.Node.Height; if AHeight = 0 then AHeight := DefaultRowHeight * ColumnsRowCount; if OptionsView.CellAutoHeight then begin AHeight := Max(AHeight, LevelInfo[AViewData.Node.Level].Size.cy); InitializeRows(AHeight, AViewData); Dec(AViewData.Height, AHeight); AHeight := CalculateNodeAutoHeight(AViewData); end; TreeList.DoGetNodeHeight(AViewData.Node, AHeight); InitializeRows(AHeight, AViewData); AddNodeBands(AViewData); AddNodeColumns(AViewData); end; function TcxTreeListViewInfo.AddNodeViewData(ANode: TcxTreeListNode; AInsert: Boolean): TcxTreeListNodeViewData; var R: TRect; begin Result := TcxTreeListNodeViewData.Create(Self, ANode, ColumnCount + Byte(Preview.Active) + ANode.Level + 5); Result.DrawFocusRect := not TreeList.OptionsSelection.CellSelect or TreeList.OptionsSelection.InvertSelect; FCells := Result.Cells; if AInsert then NodesViewData.Insert(0, Result) else NodesViewData.Add(Result); if (Bands.ExpandableBand <> nil) then AddNodeIndents(Result); if Preview.Active and (Preview.Place = tlppTop) then AddNodePreview(Result); if (ColumnCount > 0) and ANode.IsGroupNode then begin Result.DrawFocusRect := False; AddNodeCategorized(Result) end else AddNodeStandardContent(Result); Result.FocusRectBounds := cxRectSetTop(Result.ContentBounds, Result.PreviewHeight, Result.RowsHeight - OptionsView.VertIncrement); if Preview.Active and (Preview.Place = tlppBottom) then AddNodePreview(Result); AdjustNodeIndents(Result); Result.ContentBounds := cxRectSetTop(Result.ContentBounds, 0, Result.Height - Byte(bRight in GridLines)); if HasFooter(ANode) then AddNodeFooters(Result); if IsIndicatorVisible then begin if Bands.VisibleItemCount = 0 then begin Result.Height := DefaultRowHeight; Result.Bounds.Right := IndicatorWidth end; R := cxRectSetTop(Bounds, 0, Result.Height); AddIndicator(ANode, tlipContent, R); end; Result.Bounds := cxRectSetTop(Result.Bounds, 0, Result.Height); Result.Bounds.Left := Bounds.Left; end; procedure TcxTreeListViewInfo.AdjustNodeIndents( AViewData: TcxTreeListNodeViewData); var I, AHeight, ATop: Integer; begin ATop := 0; AHeight := AViewData.Height; if not IndentLeftMost then begin ATop := RowOffset[0]; AHeight := AViewData.RowsHeight; end; for I := 0 to Cells.Count - 1 do if Cells[I] is TcxTreeListIndentCellViewInfo then TcxTreeListIndentCellViewInfo(Cells[I]).SetSize(ATop, AHeight); end; function TcxTreeListViewInfo.CalculateDefaultEditHeight: Integer; var I: Integer; begin Result := TreeList.FDefaultRowHeight; FDefaultCellHeight := 0; if Result = 0 then begin for I := 0 to ColumnCount - 1 do if not Columns[I].IsPreview then begin FDefaultCellHeight := Max(FDefaultCellHeight, GetColumnDefaultEditHeight(Columns[I])); Result := Max(Result, FDefaultCellHeight); end; end; if Preview.Active then FPreviewLineHeight := GetColumnDefaultEditHeight(Preview.Column) else FPreviewLineHeight := 0; if Result = 0 then Result := GetFontHeight(TreeList.Font) + cxTextOffset; Inc(Result, OptionsView.VertIncrement + cxTreeListEditCellHeightOffset); FHScrollInc := cxTextWidth(TreeList.Font, 'W'); if FDefaultCellHeight = 0 then FDefaultCellHeight := GetFontHeight(TreeList.Font) + cxTextOffset; Result := Max(Result, TreeList.DefaultIndentSize.cy); end; procedure TcxTreeListViewInfo.CalculateDefaultHeights; var I: Integer; begin FFooterLineHeight := 0; if not OptionsView.Bands then FBandLineHeight := 0 else begin FBandHeaderLineHeight := 0; for I := 0 to Bands.VisibleItemCount - 1 do FBandHeaderLineHeight := Max(FBandHeaderLineHeight, Painter.HeaderHeight( GetFontHeight(Styles.GetBandHeaderParams(Bands.VisibleItems[I]).Font))); FBandLineHeight := OptionsView.BandLineHeight; if FBandLineHeight = 0 then FBandLineHeight := FBandHeaderLineHeight; end; for I := 0 to ColumnCount - 1 do begin if OptionsView.Headers then FHeaderLineHeight := Max(FHeaderLineHeight, Painter.HeaderHeight( GetFontHeight(Styles.GetColumnHeaderParams(Columns[I]).Font))); if OptionsView.Footer and Columns[I].Options.Footer then FFooterLineHeight := Max(FFooterLineHeight, Painter.HeaderHeight( GetFontHeight(Styles.GetColumnFooterParams(Columns[I], Root).Font))); end; if OptionsView.Footer then begin if FFooterLineHeight = 0 then FFooterLineHeight := Painter.HeaderHeight(GetFontHeight(TreeList.Font)); end; if FHeaderLineHeight = 0 then FHeaderLineHeight := Painter.HeaderHeight(GetFontHeight(TreeList.Font)); if FFooterLineHeight = 0 then FFooterLineHeight := Painter.HeaderHeight(GetFontHeight(TreeList.Font)); Inc(FFooterLineHeight, Painter.FooterCellOffset); inherited CalculateDefaultHeights; end; procedure TcxTreeListViewInfo.AfterCalculate; var I: Integer; begin CorrectBorders; if FDragItem = nil then Exit; TreeList.Controller.DragItem := nil; for I := 0 to Cells.Count - 1 do if (Cells[I] is TcxTreeListHeaderCellViewInfo) and (TcxTreeListHeaderCellViewInfo(Cells[I]).Item = FDragItem) then TreeList.Controller.DragItem := TcxTreeListHeaderCellViewInfo(Cells[I]); end; procedure TcxTreeListViewInfo.BeforeCalculate; begin RecreateCheckBoxViewData; FBounds := TreeList.ClientBounds; FRows := AllocMem((ColumnsRowCount + 1) * SizeOf(Integer)); FGridLineColor := OptionsView.GridLineColor; if FGridLineColor = clDefault then FGridLineColor := Painter.DefaultGridLineColor; FGridLines := GridLineBorders[OptionsView.GridLines]; FTreeLineColor := ColorToRGB(cxGetNativeColor( OptionsView.TreeLineColor, Painter.DefaultGridLineColor)); end; procedure TcxTreeListViewInfo.CalculateBackgroundParts; var ABounds: TRect; begin ABounds := Bounds; // right part Inc(ABounds.Left, ContentWidth); if ContentWidth = 0 then Inc(ABounds.Left, IndicatorWidth); if not cxRectIsEmpty(ABounds) then AddBackgroundPart(ABounds); Dec(ABounds.Left, ContentWidth); //bottom part ABounds := cxRectSetYPos(ContentBounds, ContentBounds.Bottom, Bounds.Bottom - FooterHeight); if FHorzBackgroundCell <> nil then FHorzBackgroundCell.SetBounds(ABounds, ABounds) else if not cxRectIsEmpty(ABounds) then FHorzBackgroundCell := AddBackgroundPart(ABounds); end; procedure TcxTreeListViewInfo.CalculateBandsLayout; var I: Integer; AKind: TcxTreeListBandFixedKind; ABounds, AClipBounds, R: TRect; ALengths: array[TcxTreeListBandFixedKind] of Integer; begin FContentWidth := 0; ABounds := cxRectSetHeight(Bounds, BandsHeight + HeadersHeight); if IsIndicatorVisible then begin R := cxRectSetHeight(ABounds, BandsHeight); AddIndicator(nil, tlipBands, R); FContentWidth := OptionsView.IndicatorWidth; Inc(ABounds.Left, OptionsView.IndicatorWidth); end; AClipBounds := ABounds; FillChar(ALengths, SizeOf(ALengths), 0); FillChar(FContentParts, SizeOf(FContentParts), 0); for I := 0 to Bands.BottomItemCount - 1 do with Bands.BottomItems[I] do Inc(ALengths[FixedKind], DisplayWidth); Inc(FContentWidth, ALengths[tlbfLeft] + ALengths[tlbfNone] + ALengths[tlbfRight]); if Bands.VisibleLeftFixedCount > 0 then begin FContentParts[tlbfLeft] := cxRectSetWidth(ABounds, ALengths[tlbfLeft]); AddBandsHeaders(tlbfLeft, FContentParts[tlbfLeft], AClipBounds); Inc(ABounds.Left, ALengths[tlbfLeft]); AddBandSeparator(nil, ABounds, ABounds); AClipBounds.Left := ABounds.Left; Inc(FContentWidth, FixedSeparatorWidth); end; FContentParts[tlbfNone] := cxRectSetLeft(ABounds, ABounds.Left, ALengths[tlbfNone]); if Bands.VisibleRightFixedCount > 0 then begin FContentParts[tlbfRight] := cxRectSetLeft(ABounds, Min(FContentParts[tlbfNone].Right, Bounds.Right - ALengths[tlbfRight] - FixedSeparatorWidth), ALengths[tlbfRight] + FixedSeparatorWidth); ABounds.Right := FContentParts[tlbfRight].Left; AClipBounds.Left := Max(FContentParts[tlbfRight].Left, ABounds.Left); AddBandSeparator(nil, FContentParts[tlbfRight], AClipBounds); AddBandsHeaders(tlbfRight, FContentParts[tlbfRight], AClipBounds); Inc(FContentWidth, FixedSeparatorWidth); end; for AKind := Low(TcxTreeListBandFixedKind) to High(TcxTreeListBandFixedKind) do FContentParts[AKind].Bottom := Bounds.Bottom; CalculateHorzScrollInfo(cxRectWidth(ABounds), ALengths[tlbfNone]); OffsetRect(FContentParts[tlbfNone], -HScrollPos, 0); AddBandsHeaders(tlbfNone, FContentParts[tlbfNone], ABounds); end; procedure TcxTreeListViewInfo.CalculateColumnsLayout; var I, ARowIndex, AColIndex: Integer; ABand: TcxTreeListBand; ARow: TcxTreeListBandRow; AColumn: TcxTreeListColumn; ABounds, AClipBounds, ARowBounds: TRect; begin FMultiRows := False; if IsIndicatorVisible then begin ABounds := cxRectSetTop(Bounds, Bounds.Top + BandsHeight, HeadersHeight); AddIndicator(nil, tlipColumns, ABounds); end; for I := 0 to Bands.BottomItemCount - 1 do begin ABand := Bands.BottomItems[I]; ABounds := cxRectSetTop(ABand.HeaderCell.BoundsRect, Bounds.Top + BandsHeight, HeadersHeight); AClipBounds := cxRectSetTop(ABand.HeaderCell.VisibleRect, Bounds.Top + BandsHeight, HeadersHeight); AddBandPart(tlbpHeader, ABand, nil, nil, ABounds, AClipBounds); FMultiRows := FMultiRows or (ABand.BandRows.VisibleItemCount > 1); for ARowIndex := 0 to ABand.BandRows.VisibleItemCount - 1 do begin ARow := ABand.BandRows.VisibleItems[ARowIndex]; ARowBounds := cxRectSetTop(ABounds, ABounds.Top + ARow.LineOffset * HeaderLineHeight, ARow.LineCount * HeaderLineHeight); for AColIndex := 0 to ARow.VisibleItemCount - 1 do begin AColumn := ARow.VisibleItems[AColIndex]; ARowBounds.Bottom := ARowBounds.Top + AColumn.Position.LineCount * HeaderLineHeight; AddColumnHeader(AColumn, ARowBounds, AClipBounds); end; end; end; end; procedure TcxTreeListViewInfo.CalculateHeadersNeighbors; var I, J, AShift: Integer; ACell: TcxTreeListCustomHeaderCellViewInfo; begin AShift := Byte(Painter.HeaderBorders([nLeft..nBottom]) <> cxBordersAll); for I := 0 to FHeaderCells.Count - 1 do begin ACell := TcxTreeListCustomHeaderCellViewInfo(FHeaderCells[I]); ACell.FIsLast := (ACell.BoundsRect.Right = ContentBounds.Right); for J := I + 1 to FHeaderCells.Count - 1 do ACell.CheckNeighbors(TcxTreeListHeaderCellViewInfo(FHeaderCells[J]), AShift); end; end; procedure TcxTreeListViewInfo.CalculateHitTest( AHitTest: TcxTreeListHitTest); var I: Integer; begin Validate; Cells.CalculateHitTest(AHitTest); if PtInRect(ContentBounds, AHitTest.HitPoint) then begin for I := 0 to Count - 1 do if NodeViewData[I].Cells.CalculateHitTest(AHitTest) then Break; end; for I := 0 to HitTestCells.Count - 1 do if TcxTreeListHitTestArea(HitTestCells[I]).GetHitTest(AHitTest) then Break; end; procedure TcxTreeListViewInfo.CalculateHorzScrollInfo( AAvailableWidth, AContentWidth: Integer); var APos: Integer; begin FHScrollPage := AAvailableWidth; FHScrollSize := AContentWidth; APos := FHScrollPos; ValidateScrollPos(APos, FHScrollPage, FContentWidth); if AContentWidth > AAvailableWidth then begin FHScrollArea := cxRectSetXPos(ContentParts[tlbfNone], Max(ContentParts[ tlbfNone].Left, Bounds.Left), Min(ContentParts[tlbfNone].Right, Bounds.Right)); if Bands.VisibleRightFixedCount > 0 then FHScrollArea.Right := ContentParts[tlbfRight].Left - FixedSeparatorWidth; if Bands.VisibleLeftFixedCount > 0 then FHScrollArea.Left := ContentParts[tlbfLeft].Right + FixedSeparatorWidth; end else FHScrollArea := cxNullRect; HScrollPos := APos; end; procedure TcxTreeListViewInfo.CalculateFooterLayout; var ABounds: TRect; begin ABounds := Bounds; ABounds.Top := ABounds.Bottom - FooterHeight; ABounds.Right := ContentBounds.Right; if IsIndicatorVisible then AddIndicator(nil, tlipFooter, ABounds); if (Bands.VisibleItemCount > 0) and (FooterHeight > 0) then AddFooter(Root, 0, 0, ABounds); end; function TcxTreeListViewInfo.CalculateNodeAutoHeight( AViewData: TcxTreeListNodeViewData): Integer; var ARow: TcxTreeListBandRow; I, AFinishRow, AHeight: Integer; begin for I := 0 to ColumnCount - 1 do begin ARow := Columns[I].Position.Row; AHeight := TcxFakeCellViewInfo(FakeCell).MeasureHeight(Columns[I], AViewData.Node, False); AFinishRow := ARow.LineOffset + Columns[I].Position.LineCount; RowOffset[AFinishRow] := Max(RowOffset[AFinishRow] - RowOffset[ARow.LineOffset], RowOffset[ARow.LineOffset] + AHeight); end; Result := RowOffset[ColumnsRowCount] - RowOffset[0]; AViewData.RowsHeight := Result; end; procedure TcxTreeListViewInfo.CalculateNodesOrigin; var AOffset: TPoint; I, ALastPos: Integer; begin I := 0; FNodesVisibleCount := 0; AOffset := Point(0, ContentBounds.Top); ALastPos := Bounds.Bottom - FooterHeight; FContentHeight := ALastPos; while I < Count do begin NodeViewData[I].Origin := AOffset; Inc(AOffset.Y, NodeViewData[I].Height); Inc(I); if (AOffset.Y <= ALastPos) or (FNodesVisibleCount = 0) then Inc(FNodesVisibleCount) else while I < Count do DeleteNodeViewData(I); end; if AOffset.Y < ALastPos then begin FContentHeight := AOffset.Y; if FHorzBackgroundCell = nil then FHorzBackgroundCell := AddBackgroundPart(cxRectSetYPos(ContentBounds, AOffset.Y, ALastPos)) else FHorzBackgroundCell.SetBounds(cxRectSetYPos(ContentBounds, AOffset.Y, ALastPos), Bounds); end else if FHorzBackgroundCell <> nil then FHorzBackgroundCell.SetBounds(cxEmptyRect, cxEmptyRect); FContentHeight := FContentHeight - ContentBounds.Top; if (NodesVisibleCount > 0) and (TreeList.FTopVisibleNode <> NodeViewData[0].Node) then begin TreeList.FTopVisibleNode := NodeViewData[0].Node; TreeList.DoTopRecordIndexChanged; end; RecalculateHitTestCells; end; procedure TcxTreeListViewInfo.CalculateNodesViewData; var AHeight: Integer; ANode: TcxTreeListNode; begin ANode := TreeList.TopVisibleNode; if (ANode = nil) or (TreeList.AbsoluteVisibleCount = 0) then begin FContentHeight := 0; Exit; end; FContentHeight := cxRectHeight(Bounds) - HeadersHeight - BandsHeight - FooterHeight; AHeight := FContentHeight; CalculateNodesViewDataForward(ANode, AHeight); CalculateNodesViewDataBackward(ANode.GetPrevVisible, True, AHeight); CalculateNodesOrigin; end; procedure TcxTreeListViewInfo.CalculateNodesViewDataBackward( ANode: TcxTreeListNode; ACheckHeight: Boolean; var AvailableHeight: Integer); var APrevHeight: Integer; ACells: TcxCustomControlCells; AViewData: TcxTreeListNodeViewData; begin ACells := FCells; try while (ANode <> nil) and (AvailableHeight > 0) do begin APrevHeight := AvailableHeight; AViewData := AddNodeViewData(ANode, True); Dec(AvailableHeight, AViewData.Height); if ACheckHeight and (AvailableHeight < 0) and (Count > 1) then begin AvailableHeight := APrevHeight; FNodesViewData.Delete(0); AViewData.Free; Break; end; ANode := ANode.GetPrevVisible; end; finally FCells := ACells; end; end; procedure TcxTreeListViewInfo.CalculateNodesViewDataForward( ANode: TcxTreeListNode; var AvailableHeight: Integer); var ACells: TcxCustomControlCells; begin ACells := FCells; try while (ANode <> nil) and (AvailableHeight > 0) do begin Dec(AvailableHeight, AddNodeViewData(ANode, False).Height); ANode := ANode.GetNextVisible; end; finally FCells := ACells; end; end; procedure TcxTreeListViewInfo.CellsChanged; begin TreeList.Controller.ViewInfoChanged; end; function TcxTreeListViewInfo.CheckScrollPosition(AScrollCode: TScrollCode; APos, APage, AInc, AMax : Integer; var AScrollPos: 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; end; procedure TcxTreeListViewInfo.CorrectBorders; var I, L, ARow: Integer; ABand: TcxTreeListBand; begin if Painter.HeaderBorders([nLeft..nBottom]) = cxBordersAll then Exit; for I := 0 to Bands.VisibleRootItemCount - 2 do begin ABand := Bands.VisibleRootItems[I]; if ABand.FixedKind <> Bands.VisibleRootItems[I + 1].FixedKind then begin repeat Inc(ABand.HeaderCell.DisplayRect.Right, 1); if ABand.ChildVisibleBands.Count > 0 then ABand := TcxTreeListBand(ABand.ChildVisibleBands.Last); until ABand.IsBottom; for ARow := 0 to ABand.BandRows.VisibleItemCount - 1 do begin L := ABand.BandRows[ARow].VisibleItemCount - 1; if L > 0 then Inc(ABand.BandRows[ARow].VisibleItems[L].HeaderCell.DisplayRect.Right, 1); end; end; end; end; procedure TcxTreeListViewInfo.Clear; begin FHitTestCells.Clear; FDragItem := nil; if TreeList.Controller.DragItem is TcxTreeListHeaderCellViewInfo then FDragItem := TcxTreeListHeaderCellViewInfo(TreeList.Controller.DragItem).Item; TreeList.Controller.DragItem := nil; FreeMem(FRows); FHorzBackgroundCell := nil; FRows := nil; FHeaderCells.Clear; FPrevFont := nil; FCells.Clear; FNodesViewData.Clear; end; procedure TcxTreeListViewInfo.DeleteNodeViewData(AIndex: Integer); begin FNodesViewData[AIndex].Free; FNodesViewData.Delete(AIndex); end; procedure TcxTreeListViewInfo.DoCalculate; begin inherited DoCalculate; CalculateInProcess := True; CellsChanged; IsDirty := False; Clear; BeforeCalculate; try CalculateBandsLayout; CalculateColumnsLayout; CalculateNodesViewData; CalculateFooterLayout; CalculateBackgroundParts; Cells.Sort(@cxCompareCells); CalculateHeadersNeighbors; HitTestCells.Sort(@cxCompareHitTestCells); finally AfterCalculate; CalculateInProcess := False; end; end; function TcxTreeListViewInfo.GetContentBounds: TRect; begin Result := Bounds; Inc(Result.Top, HeadersHeight + BandsHeight); Result.Bottom := Result.Top + FContentHeight; Result.Right := Result.Left + FContentWidth; end; function TcxTreeListViewInfo.GetFontHeight(const AFont: TFont): Integer; begin if AFont <> FPrevFont then begin FPrevFont := AFont; FPrevFontHeight := cxTextHeight(AFont); end; Result := FPrevFontHeight; end; function TcxTreeListViewInfo.GetIsIndicatorVisible: Boolean; begin Result := OptionsView.IsIndicatorVisible; end; function TcxTreeListViewInfo.GetIsPrinting: Boolean; begin Result := False; end; function TcxTreeListViewInfo.GetLevelContentOffset(ALevel: Integer): Integer; begin Result := LevelInfo[ALevel].Offset + LevelInfo[ALevel].Width; end; function TcxTreeListViewInfo.GetNodeContentOffset(ANode: TcxTreeListNode): Integer; begin Result := GetLevelContentOffset(ANode.Level); if ANode.HasCheckbox then Result := Result + Painter.CheckButtonSize.cx + Painter.CheckBorderSize; end; function TcxTreeListViewInfo.HasFooter(ANode: TcxTreeListNode): Boolean; begin Result := False; if OptionsView.GroupFooters = tlgfAlwaysVisible then Result := (ANode.HasChildren and not ANode.Expanded) or (not ANode.HasChildren and (ANode.GetNextSiblingVisible = nil) and (ANode.Parent <> Root)) else if OptionsView.GroupFooters = tlgfVisibleWhenExpanded then Result := not ANode.Expanded and (ANode.GetNextSiblingVisible = nil) and (ANode.Level > 0); end; function TcxTreeListViewInfo.HasStateIndent(ANode: TcxTreeListNode): Boolean; begin if LevelInfo[ANode.Level].StateImages = nil then Result := False else Result := (not OptionsView.DynamicFocusedStateImages or ANode.Focused) and cxInRange(ANode.StateIndex, 0, LevelInfo[ANode.Level].StateImages.Count - 1); end; procedure TcxTreeListViewInfo.InflateBoundsForGridLines( var ABounds, AClipRect: TRect); begin if bTop in GridLines then begin if ABounds.Top = AClipRect.Top then Dec(AClipRect.Top); Dec(ABounds.Top); end; if bLeft in GridLines then begin if ABounds.Left = AClipRect.Left then Dec(AClipRect.Left); Dec(ABounds.Left); end; end; procedure TcxTreeListViewInfo.InitializeRows( const ANewHeight: Integer; var AViewData: TcxTreeListNodeViewData); var I: Integer; AScaleFactor: Double; begin if AViewData.RowsHeight = 0 then begin AViewData.RowsOffset := AViewData.Height; FRows^[0] := AViewData.Height; if ANewHeight = 0 then Exit; for I := 1 to ColumnsRowCount do FRows^[I] := MulDiv(ANewHeight, I, ColumnsRowCount) + AViewData.RowsOffset; end else if AViewData.RowsHeight <> ANewHeight then begin AScaleFactor := ANewHeight / AViewData.RowsHeight; for I := ColumnsRowCount downto 1 do FRows^[I] := Round((FRows^[I] - FRows^[I - 1]) * AScaleFactor); for I := 1 to ColumnsRowCount do FRows^[I] := FRows^[I] + FRows^[I - 1]; FRows^[ColumnsRowCount] := ANewHeight; end; AViewData.RowsHeight := ANewHeight; Inc(AViewData.Height, ANewHeight); end; procedure TcxTreeListViewInfo.InitScrollBarsParameters; begin Validate; TreeList.SetScrollBarInfo(sbHorizontal, 0, HScrollSize - 1, HScrollInc, HScrollPage, HScrollPos, True, True); TreeList.SetScrollBarInfo(sbVertical, 0, VScrollSize - 1, 1, VScrollPage, VScrollPos, True, True); end; procedure TcxTreeListViewInfo.InvalidateRect(const ARect: TRect); begin TreeList.InvalidateRectEx(ARect, False); end; procedure TcxTreeListViewInfo.MakeVisible(ANode: TcxTreeListNode); var APos: Integer; begin APos := VScrollPos + 1; while ANode.ViewData.GetRealBounds.Bottom > ContentBounds.Bottom do ScrollVert(scLineDown, APos); TreeList.ViewInfo.IsDirty := False; UpdateScrollBars; end; procedure TcxTreeListViewInfo.RecalculateHitTestCells; var I: Integer; begin for I := 0 to HitTestCells.Count - 1 do TcxTreeListHitTestArea(HitTestCells[I]).Calculate; end; procedure TcxTreeListViewInfo.RecreateCheckBoxViewData; begin FreeAndNil(FCheckBoxViewData); FCheckBoxViewData := FCheckBoxProperties.CreateViewData(TreeList.EditStyle, True); end; procedure TcxTreeListViewInfo.ScrollHorz( AScrollCode: TScrollCode; var AScrollPos: Integer); begin CheckScrollPosition(AScrollCode, HScrollPos, HScrollPage, HScrollInc, HScrollSize + HScrollInc, AScrollPos); HScrollPos := AScrollPos; end; procedure TcxTreeListViewInfo.ScrollVert( AScrollCode: TScrollCode; var AScrollPos: Integer); var ANode: TcxTreeListNode; AHeight, APrevPos: Integer; begin if (TopNode = nil) or (Count = 0) then Exit; APrevPos := VScrollPos; AHeight := 1; if (AScrollCode in [scLineUp, scPageUp]) and not TopNode.IsFirstVisible then begin if AScrollCode = scPageUp then AHeight := Max(1, cxRectHeight(Bounds) - HeadersHeight - BandsHeight - FooterHeight - NodeViewData[NodesVisibleCount - 1].Height); CalculateNodesViewDataBackward(TopNode.GetPrevVisible, False, AHeight); end else if AScrollCode = scLineDown then begin ANode := NodeViewData[Count - 1].Node; if (ANode <> TopNode) and (not ANode.IsLastVisible or (Count > NodesVisibleCount)) then begin AHeight := NodeViewData[0].Height; DeleteNodeViewData(0); if (ANode.GetNextVisible = nil) and (ANode <> TopNode) then TreeList.TopVisibleNode := TopNode.GetNextVisible else CalculateNodesViewDataForward(ANode.GetNextVisible, AHeight); end else if (ANode = TopNode) and not ANode.IsLastVisible then TreeList.TopVisibleNode := ANode.GetNextVisible; end else if AScrollCode = scPageDown then begin if (LastNode = TopNode) and (LastNode.GetNextVisible <> nil) then TreeList.TopVisibleNode := LastNode.GetNextVisible else TreeList.TopVisibleNode := LastNode; end else if AScrollCode in [scTrack, scPosition] then begin TreeList.TopVisibleNode := TreeList.AbsoluteVisibleItems[Min(TreeList.AbsoluteVisibleCount - 1, Max(0, AScrollPos))]; end; CalculateNodesOrigin; AScrollPos := VScrollPos; if APrevPos <> VScrollPos then InvalidateRect(ContentBounds); if FHorzBackgroundCell <> nil then FHorzBackgroundCell.Invalidate; end; procedure TcxTreeListViewInfo.SetDirty; begin IsDirty := True; Clear; end; procedure TcxTreeListViewInfo.UpdateScrollBars; begin if TreeList.HandleAllocated then TreeList.UpdateScrollBars; end; procedure TcxTreeListViewInfo.UpdateSelection; var I: Integer; AFullUpdate: Boolean; begin inherited UpdateSelection; if Validate then begin InvalidateRect(Bounds); Exit; end; AFullUpdate := False; for I := 0 to Count - 1 do begin if not NodeViewData[I].Update(False) then Continue; AFullUpdate := AFullUpdate or ((NodeViewData[I].StateImageIndent <> nil) <> HasStateIndent(NodeViewData[I].Node)); end; if AFullUpdate then begin DoCalculate; if OptionsView.CellAutoHeight then InvalidateRect(cxRectSetYPos(Bounds, BandsHeight + HeadersHeight, Bounds.Bottom - FooterHeight)); end; end; procedure TcxTreeListViewInfo.ValidateScrollPos( var APosition: Integer; const APage, AMax: Integer); begin if APosition + APage > AMax then APosition := Max(0, AMax - APage) else APosition := Max(APosition, 0); end; function TcxTreeListViewInfo.GetBands: TcxTreeListBands; begin Result := TreeList.Bands; end; function TcxTreeListViewInfo.GetBandsHeight: Integer; begin if OptionsView.Bands then begin Result := Bands.LineCount * BandLineHeight; if IsIndicatorVisible and (Result = 0) then Result := DefaultRowHeight; end else Result := 0; end; function TcxTreeListViewInfo.GetBorderSize: Integer; begin Result := TreeList.BorderSize; end; function TcxTreeListViewInfo.GetCalculateInProcess: Boolean; begin Result := State[cvis_ViewInfoCalculate]; end; function TcxTreeListViewInfo.GetCheckBoxSize: TSize; begin Result := Painter.CheckButtonSize; Inc(Result.cx, cxTextOffset * 2); Inc(Result.cy, cxTextOffset * 2); end; function TcxTreeListViewInfo.GetColumn(AIndex: Integer): TcxTreeListColumn; begin Result := TreeList.VisibleColumns[AIndex]; end; function TcxTreeListViewInfo.GetColumnCount: Integer; begin Result := TreeList.VisibleColumnCount; end; function TcxTreeListViewInfo.GetColumnDefaultEditHeight( AColumn: TcxTreeListColumn): Integer; begin Result := AColumn.GetEditDefaultHeight( AColumn.Styles.GetContentParams(Root.FFirst).Font); if Root.FFirst = nil then Exit; Result := Max(Result, AColumn.GetEditDefaultHeight( AColumn.Styles.GetContentParams(Root.FFirst.GetNextVisible).Font)); end; function TcxTreeListViewInfo.GetColumnsRowCount: Integer; begin Result := Bands.ColumnsLineCount; end; function TcxTreeListViewInfo.GetContentPart( AKind: TcxTreeListBandFixedKind): TRect; begin Result := FContentParts[AKind]; end; function TcxTreeListViewInfo.GetCount: Integer; begin Result := FNodesViewData.Count; end; function TcxTreeListViewInfo.GetDefaultRowHeight: Integer; begin Result := DefaultEditHeight; end; function TcxTreeListViewInfo.GetFixedSeparatorWidth: Integer; begin Result := OptionsView.FixedSeparatorWidth; end; function TcxTreeListViewInfo.GetFooterHeight: Integer; begin Result := FooterLineCount * FooterLineHeight; if (Result = 0) or IsPrinting then Exit; Result := Result + Painter.FooterSeparatorSize + Painter.FooterCellOffset + Painter.FooterBorderSize; end; function TcxTreeListViewInfo.GetFooterLineCount: Integer; begin if not OptionsView.Footer then Result := 0 else if not MultiRows then Result := Max(1, Summary.FooterSummaryRowCount) else Result := Max(1, ColumnsRowCount); end; function TcxTreeListViewInfo.GetGroupFooterHeight: Integer; begin Result := GroupFooterLineCount * FooterLineHeight; if (Result = 0) or IsPrinting then Exit; Result := Result + Painter.FooterSeparatorSize + Painter.FooterCellOffset + Painter.FooterBorderSize; end; function TcxTreeListViewInfo.GetGroupFooterLineCount: Integer; begin if OptionsView.GroupFooters = tlgfInvisible then Result := 0 else if not MultiRows then Result := Max(1, Summary.GroupFooterSummaryRowCount) else Result := Max(1, ColumnsRowCount); end; function TcxTreeListViewInfo.GetHeadersHeight: Integer; begin if OptionsView.Headers then begin Result := ColumnsRowCount * HeaderLineHeight; if IsIndicatorVisible and (Result = 0) then Result := DefaultRowHeight; end else Result := 0; end; function TcxTreeListViewInfo.GetImages: TCustomImageList; begin Result := TreeList.Images; end; function TcxTreeListViewInfo.GetIndentBand: TcxTreeListBand; begin Result := Bands.ExpandableBand; end; function TcxTreeListViewInfo.GetIndentLeftMost: Boolean; begin Result := (IndentBand <> nil) and (IndentBand = Bands.BottomItems[0]); end; function TcxTreeListViewInfo.GetIndicatorWidth: Integer; begin if IsIndicatorVisible then Result := OptionsView.IndicatorWidth else Result := 0; end; function TcxTreeListViewInfo.GetLastNode: TcxTreeListNode; begin if FNodesVisibleCount > 0 then Result := NodeViewData[FNodesVisibleCount - 1].Node else Result := nil; end; function TcxTreeListViewInfo.GetLevelInfo( ALevel: Integer): TcxTreeListLevelInfo; begin Result := TreeList.LevelsInfo[ALevel]; end; function TcxTreeListViewInfo.GetNodeViewData( AIndex: Integer): TcxTreeListNodeViewData; begin Result := TcxTreeListNodeViewData(FNodesViewData[AIndex]) end; function TcxTreeListViewInfo.GetOptionsView: TcxTreeListOptionsView; begin Result := TreeList.OptionsView; end; function TcxTreeListViewInfo.GetOriginalViewInfo: TcxTreeListViewInfo; begin Result := TreeList.ViewInfo; end; function TcxTreeListViewInfo.GetPainter: TcxCustomLookAndFeelPainterClass; begin Result := inherited LookAndFeelPainter; end; function TcxTreeListViewInfo.GetPreview: TcxTreeListPreview; begin Result := TreeList.Preview; end; function TcxTreeListViewInfo.GetRoot: TcxTreeListNode; begin Result := TreeList.Root; end; function TcxTreeListViewInfo.GetRowOffset(AIndex: Integer): Integer; begin Result := FRows^[AIndex]; end; function TcxTreeListViewInfo.GetSummary: TcxTreeListSummary; begin Result := TreeList.Summary; end; function TcxTreeListViewInfo.GetStateImages: TCustomImageList; begin Result := TreeList.StateImages; end; function TcxTreeListViewInfo.GetStyles: TcxTreeListStyles; begin Result := TreeList.Styles; end; function TcxTreeListViewInfo.GetTopNode: TcxTreeListNode; begin Result := TreeList.TopVisibleNode; if (Result <> nil) and not Result.Visible then Result := Result.GetNextVisible; if Result = nil then begin Result := TreeList.TopVisibleNode; if Result <> nil then Result := Result.GetPrevVisible; end; end; function TcxTreeListViewInfo.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(Control) end; function TcxTreeListViewInfo.GetVScrollPage: Integer; begin Result := Max(1, FNodesVisibleCount); end; function TcxTreeListViewInfo.GetVScrollPos: Integer; begin Result := 0; if TopNode <> nil then Result := TopNode.VisibleIndex; end; function TcxTreeListViewInfo.GetVScrollSize: Integer; begin Result := TreeList.AbsoluteVisibleCount; end; procedure TcxTreeListViewInfo.SetCalculateInProcess(AValue: Boolean); begin State[cvis_ViewInfoCalculate] := AValue; end; procedure TcxTreeListViewInfo.SetHScrollPos(APosition: Integer); var I: Integer; begin ValidateScrollPos(APosition, FHScrollPage, FHScrollSize); if APosition = FHScrollPos then Exit; for I := 0 to Cells.Count - 1 do TcxTreeListCustomCellViewInfo(Cells[I]).Scroll(FHScrollPos - APosition, 0); for I := 0 to Count - 1 do NodeViewData[I].Scroll(FHScrollPos - APosition, 0, Bands.VisibleLeftFixedCount > 0, Bands.VisibleRightFixedCount > 0); RecalculateHitTestCells; FHScrollPos := APosition; InvalidateRect(HScrollArea); end; procedure TcxTreeListViewInfo.SetLastNode(ANode: TcxTreeListNode); var AHeight: Integer; begin NodesViewData.Clear; AHeight := Max(1, cxRectHeight(Bounds) - HeadersHeight - BandsHeight - FooterHeight); CalculateNodesViewDataBackward(ANode, False, AHeight); if (AHeight < 0) and (Count > 1) then TreeList.TopVisibleNode := NodeViewData[1].Node else TreeList.TopVisibleNode := NodeViewData[0].Node; end; procedure TcxTreeListViewInfo.SetRowOffset( AIndex: Integer; const AValue: Integer); var I, D: Integer; begin D := AValue - FRows^[AIndex]; FRows^[AIndex] := AValue; if D > 0 then begin for I := AIndex + 1 to ColumnsRowCount do Inc(FRows^[I], D); end; end; { TcxTreeListDataController } constructor TcxTreeListDataController.Create(AOwner: TComponent); begin inherited Create(AOwner); FNodesCount := -1; end; function TcxTreeListDataController.AddItem(AItem: TObject): TcxCustomDataField; begin Result := inherited AddItem(AItem); InsertValueDef(TcxTreeListColumn(AItem)); TreeList.Controller.CancelIncSearching; end; function TcxTreeListDataController.AllocateRecord: Pointer; begin Result := TcxDataStorageHelper.AllocateRecord(DataStorage); Inc(FAllocatedRecords); end; procedure TcxTreeListDataController.ChangeValueTypeClass( AItemIndex: Integer; AValueTypeClass: TcxValueTypeClass); begin if GetItemValueTypeClass(AItemIndex) = AValueTypeClass then Exit; RemoveValueDef(TcxTreeListColumn(TreeList.ContainerList[AItemIndex])); inherited ChangeValueTypeClass(AItemIndex, AValueTypeClass); InsertValueDef(TcxTreeListColumn(TreeList.ContainerList[AItemIndex])); end; function TcxTreeListDataController.CompareNodesByColumns( ANode1, ANode2: TcxTreeListNode; AColumns: TList): Integer; var I: Integer; V1, V2: Variant; AField: TcxCustomDataField; begin Result := Byte(AColumns.Count > 0); for I := 0 to AColumns.Count - 1 do begin AField := Fields[TcxTreeListColumn(AColumns[I]).ItemIndex]; if IsConversionNeededForCompare(AField) then begin V1 := GetValueForCompare(ANode1, AField); V2 := GetValueForCompare(ANode2, AField); if VarIsStr(V1) and VarIsStr(V2) then Result := StringCompare(VarToStr(V1), VarToStr(V2)) else Result := VarCompare(V1, V2); end else Result := Compare(TcxTreeListColumn(AColumns[I]).ValueDef, ANode1.Handle, ANode2.Handle); if TcxTreeListColumn(AColumns[I]).SortOrder = soDescending then Result := -Result; if Result <> 0 then Break; end; if Result = 0 then begin Result := ANode1.OriginalIndex - ANode2.OriginalIndex; if Result = 0 then Result := 1; end; end; procedure TcxTreeListDataController.FreeNodeRecord(ANode: TcxTreeListNode); begin if ANode = EditingNode then EditingNode := nil; FreeRecord(ANode.FHandle); end; procedure TcxTreeListDataController.FreeRecord(var ARecord: Pointer); begin if ARecord = nil then Exit; TcxDataStorageHelper.FreeRecord(DataStorage, ARecord); Dec(FAllocatedRecords); end; function TcxTreeListDataController.GetDisplayText( ARecordIndex, AItemIndex: Integer): string; begin cxTLUnused; end; function TcxTreeListDataController.GetNodeDisplayText( ANode: TcxTreeListNode; AIndex: Integer): Variant; begin if ANode.Handle = nil then Result := '' else Result := TcxDataStorageHelper.GetDisplayText(ValueDefs[AIndex], ANode.Handle); end; function TcxTreeListDataController.GetNodeValue( ANode: TcxTreeListNode; AIndex: Integer): Variant; begin if ANode.Handle = nil then Result := Null else Result := TcxDataStorageHelper.GetValue(ValueDefs[AIndex], ANode.Handle); end; function TcxTreeListDataController.GetValue( ARecordIndex, AItemIndex: Integer): Variant; begin Result := GetNodeValue(TreeList.AbsoluteItems[ARecordIndex], AItemIndex); end; function TcxTreeListDataController.GetValueForCompare( ANode: TcxTreeListNode; AField: TcxCustomDataField): Variant; begin if IsSortByDisplayTextNeeded(AField) then Result := TcxDataStorageHelper.GetDisplayText( TcxCustomDataHelper.GetValueDef(AField), ANode.Handle) else Result := TcxDataStorageHelper.GetValue( TcxCustomDataHelper.GetValueDef(AField), ANode.Handle); end; procedure TcxTreeListDataController.InitializeNodeFromRecordIndex( ANode: TcxTreeListNode); begin ANode.Handle := TcxDataStorageHelper.RemoveRecord( DataStorage, Integer(ANode.Handle)); if ANode.Handle <> nil then Inc(FAllocatedRecords); end; procedure TcxTreeListDataController.InitializeRecordIndexFromNode( ANode: TcxTreeListNode); begin ANode.Handle := Pointer(TcxDataStorageHelper.AppendRecord( DataStorage, ANode.Handle)); end; procedure TcxTreeListDataController.Cancel; begin if EditingNode = nil then Exit; try if not EditingNode.Deleting and not EditingNode.Inserting then SetNodeData(Root.FHandle, EditingNode); finally FreeNodeRecord(Root); EditingNode := nil; end; end; procedure TcxTreeListDataController.Edit; begin if not TreeList.OptionsData.Editing then Exit; EditingNode := TreeList.FocusedNode; FIsValueChanged := False; end; procedure TcxTreeListDataController.Post(AForcePost: Boolean = False); begin if EditingNode = nil then Exit; TreeList.BeginUpdate; try PostEditingData; if not FIsValueChanged then Cancel else begin FreeNodeRecord(Root); TreeList.AddChanges([tcData]); end; EditingNode := nil; PostRecord; finally TreeList.EndUpdate; end; end; procedure TcxTreeListDataController.PostEditingData; begin if (EditingNode = nil) or (Root.Handle = nil) or (nsDeleting in EditingNode.State) then Exit; TreeList.UpdateData; if IsValueChanged then Exclude(EditingNode.State, nsInserting); PostValues; end; procedure TcxTreeListDataController.RemoveItem(AItem: TObject); begin RemoveValueDef(TcxTreeListColumn(AItem)); TreeList.Controller.CancelIncSearching; inherited RemoveItem(AItem); end; function TcxTreeListDataController.SetEditValue(AItemIndex: Integer; const AValue: Variant; AEditValueSource: TcxDataEditValueSource): Boolean; var V: Variant; begin if EditingNode = nil then begin Result := False; Exit; end; AItemIndex := TcxTreeListColumn(TreeList.ContainerList[AItemIndex]).ItemIndex; V := AValue; if (AEditValueSource = evsText) and (VarToStr(AValue) = '') then V := Null; // if VarCompare(V, GetNodeValue(EditingNode, AItemIndex)) <> 0 then SetNodeValue(EditingNode, AItemIndex, V); Result := True; end; procedure TcxTreeListDataController.SetNodeValue( ANode: TcxTreeListNode; AIndex: Integer; const AValue: Variant); var AColumn: TcxTreeListColumn; begin if ANode = nil then Exit; if ANode.Handle = nil then ANode.InitializeHandle; if ANode.Handle = nil then Exit; AColumn := TreeList.Columns[AIndex]; TcxDataStorageHelper.SetValue(ANode.Handle, AColumn.ValueDef, AValue); FIsValueChanged := True; if IsLoading then Exit; TreeList.DoNodeChanged(ANode, AColumn); end; procedure TcxTreeListDataController.SetValue( ARecordIndex, AItemIndex: Integer; const Value: Variant); begin cxTLUnused; end; procedure TcxTreeListDataController.UpdateItemIndexes; begin inherited UpdateItemIndexes; TreeList.AddChanges([tcColumns]); end; function TcxTreeListDataController.Compare( AValueDef: TcxValueDef; AHandle1, AHandle2: Pointer): Integer; begin if AHandle1 = nil then begin if AHandle2 = nil then Result := 0 else Result := -1; end else if AHandle2 = nil then Result := 1 else Result := TcxDataStorageHelper.Compare(AValueDef, AHandle1, AHandle2); end; function TcxTreeListDataController.CopyData(ASource: TcxTreeListNode): Pointer; var I: Integer; begin Result := AllocateRecord; for I := 0 to TreeList.ColumnCount - 1 do begin TcxDataStorageHelper(DataStorage).SetValue(Result, ValueDefs[I], GetNodeValue(ASource, I)); end; end; procedure TcxTreeListDataController.DestroyHandles; begin ForEachRecord(FreeRecordProc, nil); end; procedure TcxTreeListDataController.ForEachRecord( AProc: TcxTreeListForEachNodeProc; AData: Pointer); var ANode: TcxTreeListNode; begin if (Root = nil) or (AllocatedRecords = 0) then Exit; ANode := Root; while ANode <> nil do begin AProc(ANode, AData); if ANode.FFirst <> nil then ANode := ANode.FFirst else if ANode.FNext <> nil then ANode := ANode.FNext else begin while (ANode <> nil) and (ANode.FNext = nil) do ANode := ANode.Parent; if ANode <> nil then ANode := ANode.FNext; end; end; end; function TcxTreeListDataController.IsLoading: Boolean; begin Result := inherited IsLoading; end; procedure TcxTreeListDataController.PostRecord; begin end; procedure TcxTreeListDataController.PostValues; begin end; procedure TcxTreeListDataController.SetNodeData( ASource: Pointer; ADest: TcxTreeListNode); var I: Integer; begin for I := 0 to TreeList.ColumnCount - 1 do SetNodeValue(ADest, I, TcxDataStorageHelper.GetValue(ValueDefs[I], ASource)); end; function TcxTreeListDataController.StringCompare(const V1, V2: Variant): Integer; begin if dcoAnsiSort in Options then begin if dcoCaseInsensitive in Options then Result := AnsiCompareText(V1, V2) else Result := AnsiCompareStr(V1, V2); end else begin if dcoCaseInsensitive in Options then Result := CompareStr(AnsiUpperCase(V1), AnsiUpperCase(V2)) else Result := VarCompare(V1, V2); end; end; procedure TcxTreeListDataController.SyncFocused(ANode: TcxTreeListNode); begin end; function TcxTreeListDataController.GetHasEditData: Boolean; begin Result := Root.Handle <> nil; end; function TcxTreeListDataController.GetRoot: TcxTreeListNode; begin Result := TreeList.Root; end; function TcxTreeListDataController.GetTreeList: TcxCustomTreeList; begin Result := TcxCustomTreeList(GetOwner); end; function TcxTreeListDataController.GetValueDef(AIndex: Integer): TcxValueDef; begin Result := TreeList.Columns[AIndex].ValueDef; end; procedure TcxTreeListDataController.FreeRecordProc( ANode: TcxTreeListNode; AData: Pointer); begin FreeNodeRecord(ANode); end; procedure TcxTreeListDataController.InsertValueDef(AColumn: TcxTreeListColumn); var AData: TcxTreeListValueDefData; begin if AColumn.ValueDef = nil then Exit; AData.Index := AColumn.ValueDef.ValueDefs.Count; AData.ValueDef := AColumn.ValueDef; ForEachRecord(InsertValueDefProc, @AData); end; procedure TcxTreeListDataController.InsertValueDefProc( ANode: TcxTreeListNode; AData: Pointer); var PSource: PAnsiChar; begin if ANode.FHandle = nil then Exit; ReallocMem(ANode.FHandle, PcxTreeListValueDefData(AData)^.ValueDef.ValueDefs.RecordSize); PSource := PAnsiChar(ANode.FHandle) + PcxTreeListValueDefData(AData)^.ValueDef.Offset; FillChar(PSource^, PcxTreeListValueDefData(AData)^.ValueDef.BufferSize, 0); end; procedure TcxTreeListDataController.SetEditingNode(AValue: TcxTreeListNode); var APrevNode: TcxTreeListNode; begin APrevNode := FEditingNode; if (AValue <> FEditingNode) and (FEditingNode <> nil) then begin Exclude(EditingNode.State, nsEditing); if not HasEditData and (nsInserting in EditingNode.State) then begin FEditingNode := nil; APrevNode.Free; end else if HasEditData then begin if EditingNode.Deleting then Cancel else Post end else TreeList.DoNodeChanged(EditingNode, nil); end; FEditingNode := AValue; if (FEditingNode <> nil) and ((APrevNode <> AValue) or not HasEditData) then begin Root.Handle := CopyData(AValue); Include(EditingNode.State, nsEditing); TreeList.DoNodeChanged(EditingNode, nil); end; end; procedure TcxTreeListDataController.SetIsValueChanged(AValue: Boolean); begin FIsValueChanged := AValue; end; procedure TcxTreeListDataController.RemoveValueDef(AColumn: TcxTreeListColumn); var AData: TcxTreeListValueDefData; begin AData.ValueDef := AColumn.ValueDef; ForEachRecord(RemoveValueDefProc, @AData); end; procedure TcxTreeListDataController.RemoveValueDefProc( ANode: TcxTreeListNode; AData: Pointer); var AFreeRecord: Boolean; ARecordSize: Integer; PDest, PSource: PAnsiChar; begin if (ANode.FHandle = nil) or (PcxTreeListValueDefData(AData)^.ValueDef = nil) then Exit; AFreeRecord := TcxDataStorageHelper.GetStoredCount(DataStorage) <= 1; ARecordSize := TcxDataStorageHelper.GetRecordSize(DataStorage); if AFreeRecord then FreeNodeRecord(ANode) else with PcxTreeListValueDefData(AData)^ do begin TcxDataStorageHelper.FreeBuffer(ValueDef, ANode.FHandle); PDest := PAnsiChar(ANode.FHandle) + ValueDef.Offset; PSource := PAnsiChar(PDest) + ValueDef.BufferSize; System.Move(PSource^, PDest^, ARecordSize - (PSource - PAnsiChar(ANode.FHandle))); ReallocMem(ANode.FHandle, ARecordSize - ValueDef.BufferSize); end; end; initialization Classes.RegisterClass(TcxTreeListStyleSheet); finalization Classes.UnRegisterClass(TcxTreeListStyleSheet); end.