Componentes.Terceros.DevExp.../official/x.48/ExpressQuantumTreeList 5/Sources/cxTLData.pas
2010-01-18 18:33:24 +00:00

1368 lines
43 KiB
ObjectPascal

{********************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressQuantumTreeList }
{ }
{ Copyright (c) 1998-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSQUANTUMTREELIST AND ALL }
{ ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{********************************************************************}
unit cxTLData;
{$I cxVer.inc}
interface
uses
Classes, SysUtils, Windows, Messages, Variants, cxVariants, cxControls, cxClasses,
cxData, cxCustomData, cxInplaceContainer, cxTL, cxTLStrs;
type
TcxCustomDataTreeList = class;
TcxVirtualTreeListNode = class;
TcxCustomVirtualTreeList = class;
TcxTreeListStructureLoader = class;
{ TcxTreeListCustomDataSource }
TcxTreeListCustomDataSource = class(TcxCustomDataSource)
protected
// Methods used in smart load mode
function GetChildCount(AParentHandle: TcxDataRecordHandle): Integer; virtual;
function GetChildRecordHandle(AParentHandle: TcxDataRecordHandle; AChildIndex: Integer): TcxDataRecordHandle; virtual;
function GetRootRecordHandle: TcxDataRecordHandle; virtual;
// Methods used in LoadAllRecords mode
function GetParentRecordHandle(ARecordHandle: TcxDataRecordHandle): TcxDataRecordHandle; virtual;
function GetRecordCount: Integer; override;
function GetRecordHandle(ARecordIndex: Integer): TcxDataRecordHandle; override;
// Common methods
procedure DeleteChildItems(AParentHandle: TcxDataRecordHandle);
procedure NodeMoveTo(ARecordHandle, AttachRecordHandle: TcxDataRecordHandle;
AttachMode: TcxTreeListNodeAttachMode; IsCopy: Boolean); virtual;
public
procedure DataChanged; override;
end;
{ TcxDataTreeListDataController }
TcxDataTreeListDataController = class(TcxTreeListDataController)
private
FDataSource: TcxTreeListCustomDataSource;
FIsDataLoaded: Boolean;
FLoader: TcxTreeListStructureLoader;
FLoadingInProcess: Boolean;
FLoadingRefCount: Integer;
function GetTreeList: TcxCustomDataTreeList;
procedure SetCustomDataSource(AValue: TcxTreeListCustomDataSource);
protected
procedure CheckData; virtual;
function CreateLoader: TcxTreeListStructureLoader; virtual; abstract;
procedure DoInitInsertingNode(ANode: TcxTreeListNode); virtual;
function GetCustomDataSource: TcxTreeListCustomDataSource; virtual;
function IsLoading: Boolean; override;
procedure Load(ANode: TcxTreeListNode); virtual;
procedure NodesMoveTo(AttachNode: TcxVirtualTreeListNode;
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean);
property IsDataLoaded: Boolean read FIsDataLoaded write FIsDataLoaded;
property Loader: TcxTreeListStructureLoader read FLoader;
property LoadingInProcess: Boolean read FLoadingInProcess write FLoadingInProcess;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property CustomDataSource: TcxTreeListCustomDataSource read GetCustomDataSource write SetCustomDataSource;
property TreeList: TcxCustomDataTreeList read GetTreeList;
end;
{ TcxVirtualTreeListDataController }
TcxVirtualTreeListDataController = class(TcxDataTreeListDataController)
private
function GetTreeList: TcxCustomVirtualTreeList;
protected
procedure CheckLoaded(ANode: TcxTreeListNode);
function CreateLoader: TcxTreeListStructureLoader; override;
procedure DeleteNode(ANode: TcxTreeListNode); override;
public
function CompareNodesByColumns(ANode1, ANode2: TcxTreeListNode; AColumns: TList): Integer; override;
function GetNodeDisplayText(ANode: TcxTreeListNode; AIndex: Integer): Variant; override;
function GetNodeValue(ANode: TcxTreeListNode; AIndex: Integer): Variant; override;
procedure SetNodeValue(ANode: TcxTreeListNode; AIndex: Integer; const AValue: Variant); override;
property TreeList: TcxCustomVirtualTreeList read GetTreeList;
end;
{ TcxVirtualTreeListNode }
TcxVirtualTreeListNode = class(TcxTreeListNode)
private
FRecordHandle: TcxDataRecordHandle;
public
property RecordHandle: TcxDataRecordHandle read FRecordHandle;
end;
{ TcxTreeListStructureLoader }
TcxTreeListStructureLoader = class
private
FDataController: TcxDataTreeListDataController;
FTreeList: TcxCustomDataTreeList;
function GetRoot: TcxTreeListNode;
protected
Nodes, Loaded: TList;
procedure AssignValues(ANode: TcxTreeListNode); virtual;
function CloneList(ASource: TList): TList;
procedure DoLoad(ALoadingNode: TcxTreeListNode); virtual; abstract;
function GetImageIndex(ANode: TcxTreeListNode; AIndexType: TcxTreeListImageIndexType): Integer; virtual;
procedure InternalDelete(ANodes: TList);
procedure InternalMove(ANode, ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode);
function IsChildrenExist(ANode: TcxTreeListNode): Boolean; virtual; abstract;
function IsLoadAllRecords: Boolean; virtual;
procedure RestorePos; virtual;
procedure SavePos; virtual;
public
constructor Create(AOwner: TcxDataTreeListDataController); virtual;
procedure Load(ANode: TcxTreeListNode); virtual;
property DataController: TcxDataTreeListDataController read FDataController;
property Root: TcxTreeListNode read GetRoot;
property TreeList: TcxCustomDataTreeList read FTreeList;
end;
{ TcxVirtualTreeListLoader }
TcxVirtualTreeListLoader = class(TcxTreeListStructureLoader)
private
function GetDataController: TcxDataTreeListDataController;
function GetDataSource: TcxTreeListCustomDataSource;
function GetTreeList: TcxCustomVirtualTreeList;
protected
function AddChild(AParent: TcxTreeListNode; ARecordHandle: TcxDataRecordHandle): TcxVirtualTreeListNode;
procedure AssignValues(ANode: TcxTreeListNode); override;
procedure DoLoad(ALoadingNode: TcxTreeListNode); override;
function ExtractNode(ARecordHandle: TcxDataRecordHandle;
var ANode: TcxVirtualTreeListNode): Boolean;
function FindParentNode(const AParentHandle: TcxDataRecordHandle; APrev: TcxVirtualTreeListNode;
var ANode: TcxVirtualTreeListNode): Boolean;
function IsChildrenExist(ANode: TcxTreeListNode): Boolean; override;
procedure LoadAllRecords; virtual;
procedure LoadLevel(AParent: TcxTreeListNode; AParentHandle: TcxDataRecordHandle); virtual;
procedure LoadValues(ANode: TcxTreeListNode);
procedure LoadVirtualLevel(ANode: TcxTreeListNode; ARecursive: Boolean); virtual;
public
property DataController: TcxDataTreeListDataController read GetDataController;
property DataSource: TcxTreeListCustomDataSource read GetDataSource;
property TreeList: TcxCustomVirtualTreeList read GetTreeList;
end;
{ TcxVirtualTreeListOptionsData }
TcxVirtualTreeListOptionsData = class(TcxTreeListOptionsData)
private
FCheckHasChildren: Boolean;
FSmartLoad: Boolean;
procedure SetSmartLoad(AValue: Boolean);
public
constructor Create(AOwner: TPersistent); override;
procedure Assign(Source: TPersistent); override;
published
property CheckHasChildren: Boolean read FCheckHasChildren write FCheckHasChildren default True;
property SmartLoad: Boolean read FSmartLoad write SetSmartLoad default False;
end;
{ TcxCustomDataTreeList }
TcxDataTreeListChange = (dtcStructure, dtcData, dtcLayout, dtcFocused);
TcxDataTreeListChanges = set of TcxDataTreeListChange;
TcxCustomDataTreeList = class(TcxCustomTreeList)
private
FDataChanges: TcxDataTreeListChanges;
FInternalCreationRefCount: Integer;
FLoadingLockCount: Integer;
FLockDataChanges: Integer;
function GetDataController: TcxDataTreeListDataController;
function GetLoader: TcxTreeListStructureLoader;
function GetOptionsData: TcxVirtualTreeListOptionsData;
procedure SetOptionsData(Value: TcxVirtualTreeListOptionsData);
protected
procedure AddDataChanges(AChanges: TcxDataTreeListChanges);
function AddNode(ANode, ARelative: TcxTreeListNode; AData: Pointer;
AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode; override;
procedure CheckChanges; override;
procedure CheckDataChanges; virtual;
function CreateNode: TcxTreeListNode; override;
procedure DataModeChanged; virtual;
procedure DeleteNodes(AList: TList); override;
procedure DoClear; override;
procedure DoExpand(ANode: TcxTreeListNode); override;
function GetOptionsDataClass: TcxControlOptionsDataClass; override;
procedure InternalCreationAddRef;
procedure InternalCreationRelease;
function IsDataSettingsValid: Boolean; virtual;
procedure LockLoading;
procedure UnlockLoading;
property DataController: TcxDataTreeListDataController read GetDataController;
property DataChanges: TcxDataTreeListChanges read FDataChanges write FDataChanges;
property InternalCreationRefCount: Integer read FInternalCreationRefCount;
property Loader: TcxTreeListStructureLoader read GetLoader;
property LoadingLockCount: Integer read FLoadingLockCount;
property LockDataChanges: Integer read FLockDataChanges;
property OptionsData: TcxVirtualTreeListOptionsData read GetOptionsData write SetOptionsData;
public
procedure FullRefresh; override;
end;
{ TcxCustomVirtualTreeList }
TcxVirtualTreeListGetChildCountEvent = procedure(Sender: TcxCustomTreeList;
AParentNode: TcxTreeListNode; var ACount: Integer) of object;
TcxVirtualTreeListNodeValueEvent = procedure(Sender: TcxCustomTreeList;
ANode: TcxTreeListNode; AColumn: TcxTreeListColumn; var AValue: Variant) of object;
TcxCustomVirtualTreeList = class(TcxCustomDataTreeList)
private
FOnGetChildCount: TcxVirtualTreeListGetChildCountEvent;
FOnGetNodeValue: TcxVirtualTreeListNodeValueEvent;
FOnSetNodeValue: TcxVirtualTreeListNodeValueEvent;
function GetDataController: TcxDataTreeListDataController;
function GetDataSource: TcxTreeListCustomDataSource;
procedure SetOnGetChildCount(AValue: TcxVirtualTreeListGetChildCountEvent);
procedure SetOnGetNodeValue(AValue: TcxVirtualTreeListNodeValueEvent);
procedure SetOnSetNodeValue(AValue: TcxVirtualTreeListNodeValueEvent);
procedure SetDataSource(Value: TcxTreeListCustomDataSource);
protected
procedure DataChanged; override;
function DoGetChildCount(ANode: TcxTreeListNode): Integer; virtual;
procedure DoLoadValues(ANode: TcxTreeListNode); virtual;
procedure DoMoveTo(AttachNode: TcxTreeListNode;
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean); override;
procedure DoSetValue(ANode: TcxTreeListNode; AIndex: Integer; var AValue: Variant); virtual;
function GetDataControllerClass: TcxCustomDataControllerClass; override;
procedure InitInsertingNode(ANode: TcxTreeListNode); override;
function InsertNode(ARelative: TcxTreeListNode; IsAppend: Boolean): Boolean; override;
function IsCompletelyVirtual: Boolean; virtual;
procedure Loaded; override;
property DataController: TcxDataTreeListDataController read GetDataController;
property OnGetChildCount: TcxVirtualTreeListGetChildCountEvent read FOnGetChildCount write SetOnGetChildCount;
property OnGetNodeValue: TcxVirtualTreeListNodeValueEvent read FOnGetNodeValue write SetOnGetNodeValue;
property OnSetNodeValue: TcxVirtualTreeListNodeValueEvent read FOnSetNodeValue write SetOnSetNodeValue;
public
destructor Destroy; override;
function HandleFromNode(ANode: TcxTreeListNode): TcxDataRecordHandle; virtual;
function NodeFromHandle(ARecordHandle: TcxDataRecordHandle): TcxTreeListNode; virtual;
property CustomDataSource: TcxTreeListCustomDataSource read GetDataSource write SetDataSource;
end;
{ TcxVirtualTreeList }
TcxVirtualTreeList = class(TcxCustomVirtualTreeList)
public
property ColumnCount;
property Columns;
property Customizing;
property DataController;
property FocusedColumn;
property FocusedNode;
property HitTest;
property IsEditing;
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 OnBandPosChanged;
property OnBandSizeChanged;
property OnBeginDragNode;
property OnCanFocusNode;
property OnCanResize;
property OnCanSelectNode;
property OnChange;
property OnClick;
property OnCollapsed;
property OnCollapsing;
property OnColumnHeaderClick;
property OnColumnPosChanged;
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 OnGetChildCount;
property OnGetDragDropText;
property OnGetLevelImages;
property OnGetNodeHeight;
property OnGetNodeImageIndex;
property OnGetNodePreviewHeight;
property OnGetNodeValue;
property OnGetSiteInfo;
property OnGetStoredProperties;
property OnGetStoredPropertyValue;
property OnHotTrackNode;
property OnInitEdit;
property OnInitStoredObject;
property OnIsGroupNode;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnLayoutChanged;
property OnLeftPosChanged;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnMoveTo;
property OnNodeChanged;
property OnNodeCheckChanged;
property OnResize;
property OnSelectionChanged;
property OnSetNodeValue;
property OnSetStoredPropertyValue;
property OnSorted;
property OnSorting;
property OnStartDock;
property OnStartDrag;
property OnSummary;
property OnTopRecordIndexChanged;
property OnUnDock;
property PopupMenusEvents;
property StylesEvents;
end;
const
cxNullRecordHandle: TcxDataRecordHandle = TcxDataRecordHandle(-1);
implementation
uses Math;
function cxCompareNodesByRecordHandle(
ANode1, ANode2: TcxVirtualTreeListNode): Integer;
begin
Result := Integer(ANode1.RecordHandle) - Integer(ANode2.RecordHandle);
end;
{ TcxTreeListCustomDataSource }
procedure TcxTreeListCustomDataSource.DataChanged;
begin
if DataController is TcxDataTreeListDataController then
TcxDataTreeListDataController(DataController).Load(nil)
else
inherited DataChanged;
end;
procedure TcxTreeListCustomDataSource.DeleteChildItems(
AParentHandle: TcxDataRecordHandle);
var
I: Integer;
AItemHandle: TcxDataRecordHandle;
begin
for I := GetChildCount(AParentHandle) - 1 downto 0 do
begin
AItemHandle := GetChildRecordHandle(AParentHandle, I);
try
DeleteChildItems(AItemHandle);
finally
DeleteRecord(AItemHandle);
end;
end;
end;
function TcxTreeListCustomDataSource.GetChildCount(
AParentHandle: TcxDataRecordHandle): Integer;
begin
Result := 0;
end;
function TcxTreeListCustomDataSource.GetChildRecordHandle(
AParentHandle: TcxDataRecordHandle; AChildIndex: Integer): TcxDataRecordHandle;
begin
Result := cxNullRecordHandle;
end;
procedure TcxTreeListCustomDataSource.NodeMoveTo(
ARecordHandle, AttachRecordHandle: TcxDataRecordHandle;
AttachMode: TcxTreeListNodeAttachMode; IsCopy: Boolean);
begin
end;
function TcxTreeListCustomDataSource.GetParentRecordHandle(
ARecordHandle: TcxDataRecordHandle): TcxDataRecordHandle;
begin
Result := cxNullRecordHandle;
end;
function TcxTreeListCustomDataSource.GetRecordCount: Integer;
begin
Result := 0;
end;
function TcxTreeListCustomDataSource.GetRecordHandle(
ARecordIndex: Integer): TcxDataRecordHandle;
begin
Result := TcxDataRecordHandle(ARecordIndex);
end;
function TcxTreeListCustomDataSource.GetRootRecordHandle: TcxDataRecordHandle;
begin
Result := cxNullRecordHandle;
end;
{ TcxDataTreeListDataController }
constructor TcxDataTreeListDataController.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLoader := CreateLoader;
end;
destructor TcxDataTreeListDataController.Destroy;
begin
FLoader.Free;
inherited Destroy;
end;
procedure TcxDataTreeListDataController.CheckData;
begin
if IsDataLoaded or LoadingInProcess or
TreeList.IsTreeListLocked or not TreeList.IsDataSettingsValid then Exit;
Load(nil);
end;
procedure TcxDataTreeListDataController.DoInitInsertingNode(
ANode: TcxTreeListNode);
begin
end;
function TcxDataTreeListDataController.GetCustomDataSource: TcxTreeListCustomDataSource;
begin
Result := FDataSource;
end;
function TcxDataTreeListDataController.IsLoading: Boolean;
begin
Result := (FLoadingRefCount > 0) or inherited IsLoading;
end;
procedure TcxDataTreeListDataController.Load(ANode: TcxTreeListNode);
var
ALoaded: Boolean;
begin
if IsDataLoading or (TreeList.LoadingLockCount > 0) or
not TreeList.IsDataSettingsValid then Exit;
TreeList.BeginUpdate;
try
FLoadingInProcess := True;
if TreeList.IsDataSettingsValid then
begin
ALoaded := IsDataLoaded;
if not ALoaded then
Loader.Load(nil)
else
Loader.Load(ANode)
end;
TreeList.AddChanges([tcData, tcStructure]);
finally
TreeList.EndUpdate;
FLoadingInProcess := False;
IsDataLoaded := True;
end;
end;
procedure TcxDataTreeListDataController.NodesMoveTo(AttachNode: TcxVirtualTreeListNode;
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean);
var
I: Integer;
begin
if CustomDataSource = nil then Exit;
CustomDataSource.CurrentProvider := Provider;
for I := 0 to ANodes.Count - 1 do
begin
CustomDataSource.NodeMoveTo(TcxVirtualTreeListNode(ANodes[I]).RecordHandle,
AttachNode.RecordHandle, AttachMode, IsCopy);
end;
end;
function TcxDataTreeListDataController.GetTreeList: TcxCustomDataTreeList;
begin
Result := TcxCustomDataTreeList(GetOwner);
end;
procedure TcxDataTreeListDataController.SetCustomDataSource(
AValue: TcxTreeListCustomDataSource);
begin
if FDataSource <> AValue then
begin
FDataSource := AValue;
Load(nil);
end;
end;
{ TcxVirtualTreeListDataController }
function TcxVirtualTreeListDataController.CompareNodesByColumns(
ANode1, ANode2: TcxTreeListNode; AColumns: TList): Integer;
begin
CheckLoaded(ANode1);
CheckLoaded(ANode2);
Result := inherited CompareNodesByColumns(ANode1, ANode2, AColumns);
end;
function TcxVirtualTreeListDataController.GetNodeDisplayText(
ANode: TcxTreeListNode; AIndex: Integer): Variant;
begin
CheckLoaded(ANode);
Result := inherited GetNodeDisplayText(ANode, AIndex);
end;
function TcxVirtualTreeListDataController.GetNodeValue(
ANode: TcxTreeListNode; AIndex: Integer): Variant;
begin
CheckLoaded(ANode);
Result := inherited GetNodeValue(ANode, AIndex);
end;
procedure TcxVirtualTreeListDataController.SetNodeValue(
ANode: TcxTreeListNode; AIndex: Integer; const AValue: Variant);
var
V: Variant;
begin
CheckLoaded(ANode);
V := AValue;
if TreeList.IsCompletelyVirtual then
TreeList.DoSetValue(ANode, AIndex, V);
inherited SetNodeValue(ANode, AIndex, V);
if not TreeList.IsCompletelyVirtual and (FLoadingRefCount = 0) and (CustomDataSource <> nil) then
CustomDataSource.SetValue(TcxVirtualTreeListNode(ANode).RecordHandle, CustomDataSource.GetItemHandle(AIndex), V);
IsValueChanged := True;
end;
procedure TcxVirtualTreeListDataController.CheckLoaded(ANode: TcxTreeListNode);
begin
if not (nsValuesAssigned in TcxVirtualTreeListNode(ANode).State) then
TcxVirtualTreeListLoader(Loader).LoadValues(ANode);
end;
function TcxVirtualTreeListDataController.CreateLoader: TcxTreeListStructureLoader;
begin
Result := TcxVirtualTreeListLoader.Create(Self);
end;
procedure TcxVirtualTreeListDataController.DeleteNode(ANode: TcxTreeListNode);
begin
if not TreeList.IsCompletelyVirtual then
CustomDataSource.DeleteRecord(TcxVirtualTreeListNode(ANode).RecordHandle)
else
inherited DeleteNode(ANode);
end;
function TcxVirtualTreeListDataController.GetTreeList: TcxCustomVirtualTreeList;
begin
Result := TcxCustomVirtualTreeList(inherited TreeList);
end;
{ TcxTreeListStructureLoader }
constructor TcxTreeListStructureLoader.Create(AOwner: TcxDataTreeListDataController);
begin
FDataController := AOwner;
FTreeList := DataController.TreeList;
end;
procedure TcxTreeListStructureLoader.Load(ANode: TcxTreeListNode);
begin
TreeList.SetGlassCursor;
try
TreeList.InternalCreationAddRef;
SavePos;
try
DoLoad(ANode);
finally
RestorePos;
TreeList.InternalCreationRelease;
end;
finally
TreeList.RestoreCursor
end;
end;
procedure TcxTreeListStructureLoader.AssignValues(ANode: TcxTreeListNode);
var
AIndex: TcxTreeListImageIndexType;
begin
if ANode = Root then Exit;
for AIndex := Low(TcxTreeListImageIndexType) to High(TcxTreeListImageIndexType) do
TcxVirtualTreeListNode(ANode).FImageIndexes[AIndex] := GetImageIndex(ANode, AIndex);
DataController.IsValueChanged := not ANode.IsEditing;
end;
function TcxTreeListStructureLoader.CloneList(ASource: TList): TList;
begin
Result := TList.Create;
Result.Count := ASource.Count;
Move(ASource.List^, Result.List^, ASource.Count * SizeOf(Pointer));
end;
function TcxTreeListStructureLoader.GetImageIndex(
ANode: TcxTreeListNode; AIndexType: TcxTreeListImageIndexType): Integer;
begin
Result := TreeList.DoGetNodeImageIndex(ANode, AIndexType);
end;
procedure TcxTreeListStructureLoader.InternalDelete(ANodes: TList);
begin
if not Assigned(ANodes) then Exit;
TreeList.InternalDelete(ANodes);
end;
procedure TcxTreeListStructureLoader.InternalMove(
ANode, ADestNode: TcxTreeListNode; AMode: TcxTreeListNodeAttachMode);
begin
TcxVirtualTreeListNode(ANode).ExtractFromParent;
TreeList.InternalMove(ANode, ADestNode, AMode);
end;
function TcxTreeListStructureLoader.IsLoadAllRecords: Boolean;
begin
Result := not TreeList.OptionsData.SmartLoad;
end;
procedure TcxTreeListStructureLoader.RestorePos;
begin
Dec(DataController.FLoadingRefCount);
DataController.DataChangedBusy := False;
DataController.IsValueChanged := DataController.EditingNode <> nil;
end;
procedure TcxTreeListStructureLoader.SavePos;
begin
Inc(DataController.FLoadingRefCount);
DataController.DataChangedBusy := True;
end;
function TcxTreeListStructureLoader.GetRoot: TcxTreeListNode;
begin
Result := TreeList.Root;
end;
{ TcxVirtualTreeListLoader }
function TcxVirtualTreeListLoader.AddChild(AParent: TcxTreeListNode;
ARecordHandle: TcxDataRecordHandle): TcxVirtualTreeListNode;
begin
Result := TcxVirtualTreeListNode(AParent.AddChild);
Result.FRecordHandle := ARecordHandle;
end;
procedure TcxVirtualTreeListLoader.AssignValues(ANode: TcxTreeListNode);
begin
Exclude(TcxVirtualTreeListNode(ANode).State, nsValuesAssigned);
DataController.FreeNodeRecord(ANode);
DataController.IsValueChanged := not ANode.IsEditing;
end;
procedure TcxVirtualTreeListLoader.DoLoad(ALoadingNode: TcxTreeListNode);
begin
if DataSource = nil then
begin
if not TcxCustomVirtualTreeList(TreeList).IsCompletelyVirtual then
TreeList.InternalClearAll;
if ALoadingNode = nil then
ALoadingNode := Root;
if IsLoadAllRecords then
LoadVirtualLevel(Root, True)
else
LoadVirtualLevel(ALoadingNode, False);
Exit;
end;
if not IsLoadAllRecords and (ALoadingNode <> nil) and (ALoadingNode.Count > 0) then
ALoadingNode := nil; // todo: refresh loaded nodes !!!
if not IsLoadAllRecords and (ALoadingNode <> nil) then
LoadLevel(ALoadingNode, TcxVirtualTreeListNode(ALoadingNode).RecordHandle)
else
begin
Nodes := CloneList(TreeList.AbsoluteItemsList);
try
Nodes.Sort(@cxCompareNodesByRecordHandle);
if IsLoadAllRecords then
LoadAllRecords
else
if ALoadingNode = nil then
LoadLevel(Root, DataSource.GetRootRecordHandle);
InternalDelete(Nodes);
finally
FreeAndNil(Nodes);
end;
end;
end;
function TcxVirtualTreeListLoader.ExtractNode(
ARecordHandle: TcxDataRecordHandle; var ANode: TcxVirtualTreeListNode): Boolean;
var
L, H, I, C: Integer;
begin
L := 0;
Result := False;
if Nodes = nil then Exit;
H := Nodes.Count - 1;
while L <= H do
begin
I := (L + H) shr 1;
ANode := TcxVirtualTreeListNode(Nodes.List^[I]);
C := Integer(ANode.RecordHandle) - Integer(ARecordHandle);
if C = 0 then
begin
Nodes.Delete(I);
Result := True;
Break;
end
else
if C < 0 then
L := I + 1
else
H := I - 1;
end;
end;
function TcxVirtualTreeListLoader.FindParentNode(
const AParentHandle: TcxDataRecordHandle; APrev: TcxVirtualTreeListNode;
var ANode: TcxVirtualTreeListNode): Boolean;
var
L, H, I, C: Integer;
begin
Result := (APrev <> nil) and (APrev.RecordHandle = AParentHandle);
if Result then
begin
ANode := APrev;
Exit;
end;
L := 0;
H := Loaded.Count - 1;
while L <= H do
begin
I := (L + H) shr 1;
ANode := TcxVirtualTreeListNode(Loaded.List^[I]);;
C := Integer(ANode.RecordHandle) - Integer(AParentHandle);
if C < 0 then
L := I + 1
else
begin
H := I - 1;
if C = 0 then
begin
Result := True;
Break;
end;
end;
end;
end;
function TcxVirtualTreeListLoader.IsChildrenExist(ANode: TcxTreeListNode): Boolean;
begin
Result := DataSource.GetChildCount(
TcxVirtualTreeListNode(ANode).RecordHandle) <> 0;
end;
procedure TcxVirtualTreeListLoader.LoadAllRecords;
var
I: Integer;
AHandle: TcxDataRecordHandle;
ANode: TcxVirtualTreeListNode;
AOrder: TList;
begin
AOrder := TList.Create;
try
Loaded := TList.Create();
try
Loaded.Capacity := DataSource.GetRecordCount;
for I := 0 to DataSource.GetRecordCount - 1 do
begin
AHandle := DataSource.GetRecordHandle(I);
if not ExtractNode(AHandle, ANode) then
ANode := AddChild(Root, AHandle)
else
ANode.SaveStateBeforeRefresh;
AssignValues(ANode);
Loaded.Add(ANode);
end;
AOrder.Assign(Loaded);
Loaded.Sort(@cxCompareNodesByRecordHandle);
ANode := nil;
for I := 0 to AOrder.Count - 1 do
begin
AHandle := DataSource.GetParentRecordHandle(
TcxVirtualTreeListNode(AOrder.List^[I]).RecordHandle);
if FindParentNode(AHandle, ANode, ANode) then
InternalMove(TcxVirtualTreeListNode(AOrder.List^[I]), ANode, tlamAddChild)
else
InternalMove(TcxVirtualTreeListNode(AOrder.List^[I]), Root, tlamAddChild);
end;
for I := 0 to Loaded.Count - 1 do
TcxVirtualTreeListNode(Loaded.List^[I]).RestoreStateAfterRefresh;
finally
Loaded.Free;
end;
finally
AOrder.Free;
end;
end;
procedure TcxVirtualTreeListLoader.LoadLevel(
AParent: TcxTreeListNode; AParentHandle: TcxDataRecordHandle);
var
I: Integer;
ALoadSubItems: Boolean;
ANewNode: TcxVirtualTreeListNode;
ARecordHandle: TcxDataRecordHandle;
begin
for I := 0 to DataSource.GetChildCount(AParentHandle) - 1 do
begin
ALoadSubItems := False;
ARecordHandle := DataSource.GetChildRecordHandle(AParentHandle, I);
if ExtractNode(ARecordHandle, ANewNode) then
begin
ALoadSubItems := ANewNode.Expanded or (ANewNode.Count > 0);
InternalMove(ANewNode, AParent, tlamAddChild)
end
else
ANewNode := AddChild(AParent, ARecordHandle);
ANewNode.HasChildren := not TreeList.OptionsData.CheckHasChildren or
(DataSource.GetChildCount(ARecordHandle) > 0);
AssignValues(ANewNode);
if ANewNode.HasChildren and ALoadSubItems then
LoadLevel(ANewNode, ANewNode.RecordHandle);
end;
end;
procedure TcxVirtualTreeListLoader.LoadValues(ANode: TcxTreeListNode);
var
I: Integer;
begin
if nsValuesAssigned in TcxVirtualTreeListNode(ANode).State then Exit;
Include(TcxVirtualTreeListNode(ANode).State, nsValuesAssigned);
inherited AssignValues(ANode);
for I := 0 to TreeList.ColumnCount - 1 do
begin
Inc(DataController.FLoadingRefCount);
try
if TreeList.IsCompletelyVirtual then
TreeList.DoLoadValues(ANode)
else
DataController.SetNodeValue(ANode, I, DataSource.GetValue(
TcxVirtualTreeListNode(ANode).RecordHandle, DataSource.GetItemHandle(I)));
finally
Dec(DataController.FLoadingRefCount);
end;
end;
DataController.IsValueChanged := not ANode.IsEditing;
end;
procedure TcxVirtualTreeListLoader.LoadVirtualLevel(
ANode: TcxTreeListNode; ARecursive: Boolean);
var
ACount, I: Integer;
AChildNode: TcxTreeListNode;
begin
ACount := TreeList.DoGetChildCount(ANode);
while ANode.Count > ACount do
ANode.GetLastChild.Delete;
AChildNode := ANode.getFirstChild;
for I := 0 to ACount - 1 do
begin
if AChildNode = nil then
AChildNode := ANode.AddChild;
AssignValues(AChildNode);
if ARecursive then
LoadVirtualLevel(AChildNode, ARecursive)
else
AChildNode.HasChildren := (AChildNode.Count <> 0) or
(not TreeList.OptionsData.CheckHasChildren or (TreeList.DoGetChildCount(AChildNode) > 0));
AChildNode := AChildNode.GetNextSibling;
end;
end;
function TcxVirtualTreeListLoader.GetDataController: TcxDataTreeListDataController;
begin
Result := TcxDataTreeListDataController(inherited DataController);
end;
function TcxVirtualTreeListLoader.GetDataSource: TcxTreeListCustomDataSource;
begin
Result := TreeList.CustomDataSource;
end;
function TcxVirtualTreeListLoader.GetTreeList: TcxCustomVirtualTreeList;
begin
Result := TcxCustomVirtualTreeList(inherited TreeList);
end;
{ TcxVirtualTreeListOptionsData }
constructor TcxVirtualTreeListOptionsData.Create(AOwner: TPersistent);
begin
inherited Create(AOwner);
FCheckHasChildren := True;
end;
procedure TcxVirtualTreeListOptionsData.Assign(Source: TPersistent);
begin
inherited Assign(Source);
if Source is TcxVirtualTreeListOptionsData then
begin
CheckHasChildren := TcxVirtualTreeListOptionsData(Source).CheckHasChildren;
SmartLoad := TcxVirtualTreeListOptionsData(Source).SmartLoad;
end;
end;
procedure TcxVirtualTreeListOptionsData.SetSmartLoad(AValue: Boolean);
begin
if FSmartLoad <> AValue then
begin
FSmartLoad := AValue;
TcxCustomDataTreeList(GetOwner).DataModeChanged;
end;
end;
{ TcxCustomDataTreeList }
procedure TcxCustomDataTreeList.AddDataChanges(AChanges: TcxDataTreeListChanges);
begin
FDataChanges := FDataChanges + AChanges;
end;
function TcxCustomDataTreeList.AddNode(ANode, ARelative: TcxTreeListNode;
AData: Pointer; AttachMode: TcxTreeListNodeAttachMode): TcxTreeListNode;
begin
Result := inherited AddNode(ANode, ARelative, AData, AttachMode);
end;
procedure TcxCustomDataTreeList.CheckChanges;
begin
CheckDataChanges;
inherited CheckChanges;
end;
procedure TcxCustomDataTreeList.CheckDataChanges;
begin
if DataController.IsLoading or (FLockDataChanges > 0) or (DataChanges = []) then Exit;
Inc(FLockDataChanges);
try
if dtcStructure in DataChanges then
begin
RefreshFields;
Include(FDataChanges, dtcData);
Exclude(FDataChanges, dtcStructure);
DataController.IsDataLoaded := False;
end;
if not IsDataSettingsValid then
begin
if Root.Count > 0 then
begin
Exclude(FDataChanges, dtcData);
DoClear;
end;
Exit;
end;
if ([dtcData, dtcStructure] * FDataChanges = [dtcData]) then
DataController.CheckData;
if DataController.IsDataLoaded then
Exclude(FDataChanges, dtcData);
//cancel changes if data loaded
if not (dtcData in DataChanges) then
FDataChanges := [];
finally
Dec(FLockDataChanges);
end;
end;
function TcxCustomDataTreeList.CreateNode: TcxTreeListNode;
begin
Result := TcxVirtualTreeListNode.Create(Self);
end;
procedure TcxCustomDataTreeList.DataModeChanged;
begin
DoClear;
FullRefresh;
end;
procedure TcxCustomDataTreeList.DeleteNodes(AList: TList);
var
I: Integer;
begin
DataController.DataChangedBusy := True;
try
for I := 0 to AList.Count - 1 do
DataController.DeleteNode(TcxTreeListNode(AList[I]))
finally
DataController.DataChangedBusy := False;
end;
end;
procedure TcxCustomDataTreeList.DoExpand(ANode: TcxTreeListNode);
begin
if (ANode.Count = 0) and ANode.HasChildren then
begin
Loader.Load(TcxVirtualTreeListNode(ANode));
ANode.HasChildren := ANode.Count > 0;
end;
end;
procedure TcxCustomDataTreeList.DoClear;
begin
DataController.CustomDataSource := nil;
inherited DoClear;
end;
function TcxCustomDataTreeList.GetOptionsDataClass: TcxControlOptionsDataClass;
begin
Result := TcxVirtualTreeListOptionsData;
end;
procedure TcxCustomDataTreeList.InternalCreationAddRef;
begin
Inc(FInternalCreationRefCount);
end;
procedure TcxCustomDataTreeList.InternalCreationRelease;
begin
Dec(FInternalCreationRefCount);
end;
function TcxCustomDataTreeList.IsDataSettingsValid: Boolean;
begin
Result := not (IsLoading or IsDestroying);
end;
procedure TcxCustomDataTreeList.LockLoading;
begin
Inc(FLoadingLockCount);
end;
procedure TcxCustomDataTreeList.UnlockLoading;
begin
Dec(FLoadingLockCount);
end;
procedure TcxCustomDataTreeList.FullRefresh;
begin
if DataController.IsDataLoading or (LoadingLockCount > 0) then Exit;
AddDataChanges([dtcStructure..dtcFocused]);
RefreshFields;
if IsTreeListLocked or not IsDataSettingsValid then
begin
DataController.FIsDataLoaded := False;
Exit;
end;
BeginUpdate;
try
InternalClearAll;
DataController.Load(nil);
finally
EndUpdate;
end;
end;
function TcxCustomDataTreeList.GetDataController: TcxDataTreeListDataController;
begin
Result := TcxDataTreeListDataController(inherited DataController);
end;
function TcxCustomDataTreeList.GetLoader: TcxTreeListStructureLoader;
begin
Result := DataController.Loader;
end;
function TcxCustomDataTreeList.GetOptionsData: TcxVirtualTreeListOptionsData;
begin
Result := TcxVirtualTreeListOptionsData(inherited OptionsData);
end;
procedure TcxCustomDataTreeList.SetOptionsData(
Value: TcxVirtualTreeListOptionsData);
begin
OptionsData.Assign(Value);
end;
{ TcxCustomVirtualTreeList }
destructor TcxCustomVirtualTreeList.Destroy;
begin
OnGetChildCount := nil;
CustomDataSource := nil;
InternalClearAll;
inherited Destroy;
end;
function TcxCustomVirtualTreeList.HandleFromNode(
ANode: TcxTreeListNode): TcxDataRecordHandle;
begin
if ANode = Root then
Result := CustomDataSource.GetRootRecordHandle
else
Result := TcxVirtualTreeListNode(ANode).RecordHandle;
end;
function TcxCustomVirtualTreeList.NodeFromHandle(
ARecordHandle: TcxDataRecordHandle): TcxTreeListNode;
var
I: Integer;
begin
Result := nil;
if CustomDataSource = nil then Exit;
for I := 0 to AbsoluteCount - 1 do
if TcxVirtualTreeListNode(AbsoluteItems[I]).RecordHandle = ARecordHandle then
begin
Result := AbsoluteItems[I];
Exit;
end;
if ARecordHandle = CustomDataSource.GetRootRecordHandle then
Result := Root;
end;
procedure TcxCustomVirtualTreeList.DataChanged;
begin
if IsLocked then Exit;
inherited DataChanged;
end;
function TcxCustomVirtualTreeList.DoGetChildCount(ANode: TcxTreeListNode): Integer;
begin
Result := 0;
if Assigned(FOnGetChildCount) then
OnGetChildCount(Self, ANode, Result);
end;
procedure TcxCustomVirtualTreeList.DoLoadValues(ANode: TcxTreeListNode);
var
I: Integer;
AValue: Variant;
begin
if not Assigned(FOnGetNodeValue) then Exit;
for I := 0 to ColumnCount - 1 do
begin
AValue := Null;
OnGetNodeValue(Self, ANode, Columns[I], AValue);
DataController.SetNodeValue(ANode, I, AValue);
end;
end;
procedure TcxCustomVirtualTreeList.DoMoveTo(AttachNode: TcxTreeListNode;
AttachMode: TcxTreeListNodeAttachMode; ANodes: TList; IsCopy: Boolean);
begin
if OptionsData.SmartLoad and (AttachMode = tlamAddChild) and
(AttachNode <> nil) and AttachNode.HasChildren then
Loader.Load(TcxVirtualTreeListNode(AttachNode));
BeginUpdate;
try
inherited DoMoveTo(AttachNode, AttachMode, ANodes, IsCopy);
if not IsCompletelyVirtual then
DataController.NodesMoveTo(TcxVirtualTreeListNode(AttachNode), AttachMode, ANodes, IsCopy);
finally
EndUpdate;
end;
end;
procedure TcxCustomVirtualTreeList.DoSetValue(
ANode: TcxTreeListNode; AIndex: Integer; var AValue: Variant);
begin
if Assigned(FOnSetNodeValue) then
FOnSetNodeValue(Self, ANode, Columns[AIndex], AValue);
end;
function TcxCustomVirtualTreeList.GetDataControllerClass: TcxCustomDataControllerClass;
begin
Result := TcxVirtualTreeListDataController;
end;
procedure TcxCustomVirtualTreeList.InitInsertingNode(ANode: TcxTreeListNode);
begin
if not IsCompletelyVirtual then
begin
BeginUpdate;
try
if ANode.Parent = Root then
TcxVirtualTreeListNode(ANode).FRecordHandle := CustomDataSource.AppendRecord
else
TcxVirtualTreeListNode(ANode).FRecordHandle := CustomDataSource.InsertRecord(
TcxVirtualTreeListNode(ANode.Parent).RecordHandle);
finally
EndUpdate;
end;
end
else
TcxVirtualTreeListLoader(Loader).LoadValues(ANode);
inherited InitInsertingNode(ANode);
end;
function TcxCustomVirtualTreeList.InsertNode(
ARelative: TcxTreeListNode; IsAppend: Boolean): Boolean;
begin
Result := (Assigned(CustomDataSource) or IsCompletelyVirtual) and
inherited InsertNode(ARelative, IsAppend);
end;
function TcxCustomVirtualTreeList.IsCompletelyVirtual: Boolean;
begin
Result := Assigned(OnGetChildCount) and Assigned(OnGetNodeValue);
end;
procedure TcxCustomVirtualTreeList.Loaded;
begin
inherited Loaded;
DataController.CheckData;
end;
function TcxCustomVirtualTreeList.GetDataController: TcxDataTreeListDataController;
begin
Result := TcxDataTreeListDataController(inherited DataController);
end;
function TcxCustomVirtualTreeList.GetDataSource: TcxTreeListCustomDataSource;
begin
Result := DataController.CustomDataSource;
if Result <> nil then
Result.CurrentProvider := DataController.Provider;
end;
procedure TcxCustomVirtualTreeList.SetOnGetChildCount(
AValue: TcxVirtualTreeListGetChildCountEvent);
begin
FOnGetChildCount := AValue;
DataChanged;
end;
procedure TcxCustomVirtualTreeList.SetOnGetNodeValue(
AValue: TcxVirtualTreeListNodeValueEvent);
begin
FOnGetNodeValue := AValue;
DataChanged;
end;
procedure TcxCustomVirtualTreeList.SetOnSetNodeValue(
AValue: TcxVirtualTreeListNodeValueEvent);
begin
FOnSetNodeValue := AValue;
DataChanged;
end;
procedure TcxCustomVirtualTreeList.SetDataSource(
Value: TcxTreeListCustomDataSource);
begin
SetGlassCursor;
try
DataController.CustomDataSource := Value;
finally
RestoreCursor;
end;
end;
end.