YOUSEFUL / DELPHI / COMPONENTS

TAtlasTree

A tree view with lazy child loading, safe node moves, caption search, sorting and JSON persistence.

Visual control Palette: Atlas Unit Atlas.Tree · Inherits TCustomTreeView · Product Atlas VCL

Description

TAtlasTree (unit Atlas.Tree) is a VCL tree view with helpers for application hierarchies. Nodes are ordinary TTreeNode objects owned by the tree; a node reference becomes invalid when the node is deleted or the tree is reloaded. The tree needs a window handle before nodes are added, so set Parent first: adding a node to a tree without a parent raises EInvalidOperation (... has no parent window).

Lazy loading. AddNode(Parent, Caption, True) creates a node with an expand button and no children. The first time it expands (after OnExpanding), the tree calls OnLoadChildren inside Items.BeginUpdate/EndUpdate; add the children there with AddNode. If the handler adds nothing, the expand button disappears. If it raises, the children it added are removed, the node stays lazy so the next expand tries again, and the exception propagates. The handler runs once per node: collapsing and expanding again does not reload.

Persistence. ToJSON and LoadJSON store captions, the expanded state and the lazy flag; not images, Data pointers or the selection. LoadJSON builds the new nodes in a hidden staging tree and replaces the current nodes only when the whole document is valid.

Captions can be edited in place by the user because ReadOnly is False after Create; set it to True or handle OnEditing. TAtlasThemer sets Color and Font.Color. Tree-specific errors raise EAtlasTreeError.

Members

MemberKindWhat it does
CreateconstructorCreates a 320 x 360 tree with in-place caption editing allowed (ReadOnly False), the selection visible when unfocused (HideSelection False) and double buffering.
AddNodemethodAdds a node as the last child of Parent, or as the last root node when Parent is nil, and returns it.
MoveNodemethodMoves Node, with its children, to become the last child of NewParent, or the last root node when NewParent is nil.
FindCaptionmethodReturns the first node after StartAfter (from the first node when nil) whose caption equals Caption, ignoring the case of ASCII letters, searching depth-first through all loaded nodes whether expanded or not.
SortChildrenmethodSorts the direct children of Parent, or the root nodes when Parent is nil, by caption with the Windows lstrcmp comparison.
ToJSONmethodReturns the nodes as a JSON array of objects {"caption": ..., "expanded": ..., "lazy": ..., "children": [...]} in tree order.
LoadJSONmethodReplaces all nodes with the nodes of a document written by ToJSON.
ItemspropertyThe TTreeNodes collection (standard VCL): iterate with Items.GetFirstNode and GetNext, count with Items.Count, empty with Items.Clear, and wrap bulk changes in Items.BeginUpdate/EndUpdate.
SelectedpropertyThe selected node, or nil (standard VCL).
OnLoadChildreneventCalled on the first expand of a lazy node; add its children with AddNode(Node, ...).
ReadOnlypropertyStandard VCL property.
HideSelectionpropertyStandard VCL property.
AlignpropertyStandard VCL property, published by this class.
AnchorspropertyStandard VCL property, published by this class.
ColorpropertyStandard VCL property, published by this class.
FontpropertyStandard VCL property, published by this class.
ParentFontpropertyStandard VCL property, published by this class.
ShowRootpropertyStandard VCL property, published by this class.
ShowLinespropertyStandard VCL property, published by this class.
ShowButtonspropertyStandard VCL property, published by this class.
IndentpropertyStandard VCL property, published by this class.
TabOrderpropertyStandard VCL property, published by this class.
TabStoppropertyStandard VCL property, published by this class.
OnChangeeventStandard VCL event, published by this class.
OnEditedeventStandard VCL event, published by this class.
OnEditingeventStandard VCL event, published by this class.
OnExpandingeventStandard VCL event, published by this class.
OnExpandedeventStandard VCL event, published by this class.
OnCollapsingeventStandard VCL event, published by this class.
OnCollapsedeventStandard VCL event, published by this class.
OnClickeventStandard VCL event, published by this class.
OnDblClickeventStandard VCL event, published by this class.

Constructors

Create constructor

constructor Create(AOwner: TComponent); override;

Creates a 320 x 360 tree with in-place caption editing allowed (ReadOnly False), the selection visible when unfocused (HideSelection False) and double buffering.

Properties

Items property

property Items;

The TTreeNodes collection (standard VCL): iterate with Items.GetFirstNode and GetNext, count with Items.Count, empty with Items.Clear, and wrap bulk changes in Items.BeginUpdate/EndUpdate.

Selected property

property Selected;

The selected node, or nil (standard VCL).

ReadOnly property

property ReadOnly;

Standard VCL property. False after Create, so users can edit captions in place; set True to prevent it.

HideSelection property

property HideSelection;

Standard VCL property. False after Create: the selection stays visible when the tree loses focus.

Align property

property Align;

Standard VCL property, published by this class.

Anchors property

property Anchors;

Standard VCL property, published by this class.

Color property

property Color;

Standard VCL property, published by this class.

Font property

property Font;

Standard VCL property, published by this class.

ParentFont property

property ParentFont;

Standard VCL property, published by this class.

ShowRoot property

property ShowRoot;

Standard VCL property, published by this class.

ShowLines property

property ShowLines;

Standard VCL property, published by this class.

ShowButtons property

property ShowButtons;

Standard VCL property, published by this class.

Indent property

property Indent;

Standard VCL property, published by this class.

TabOrder property

property TabOrder;

Standard VCL property, published by this class.

TabStop property

property TabStop;

Standard VCL property, published by this class.

Events

OnLoadChildren event

property OnLoadChildren: TAtlasLoadChildrenEvent read FOnLoadChildren write FOnLoadChildren;

Called on the first expand of a lazy node; add its children with AddNode(Node, ...). See the description for what happens when the handler adds nothing or raises.

OnChange event

property OnChange;

Standard VCL event, published by this class.

OnEdited event

property OnEdited;

Standard VCL event, published by this class.

OnEditing event

property OnEditing;

Standard VCL event, published by this class.

OnExpanding event

property OnExpanding;

Standard VCL event, published by this class.

OnExpanded event

property OnExpanded;

Standard VCL event, published by this class.

OnCollapsing event

property OnCollapsing;

Standard VCL event, published by this class.

OnCollapsed event

property OnCollapsed;

Standard VCL event, published by this class.

OnClick event

property OnClick;

Standard VCL event, published by this class.

OnDblClick event

property OnDblClick;

Standard VCL event, published by this class.

Methods

AddNode method

function AddNode(Parent: TTreeNode; const Caption: string; LazyChildren: Boolean = False): TTreeNode;

Adds a node as the last child of Parent, or as the last root node when Parent is nil, and returns it. With LazyChildren = True the node shows an expand button and gets its children from OnLoadChildren on first expand. Raises EAtlasTreeError when Parent belongs to another tree.

pascal
Root := Tree.AddNode(nil, 'Engineering');
Tree.AddNode(Root, 'Archive', True);

MoveNode method

procedure MoveNode(Node, NewParent: TTreeNode);

Moves Node, with its children, to become the last child of NewParent, or the last root node when NewParent is nil. Raises EAtlasTreeError when Node is nil, when either node belongs to another tree, or when NewParent is Node itself or one of its descendants.

FindCaption method

function FindCaption(const Caption: string; StartAfter: TTreeNode = nil): TTreeNode;

Returns the first node after StartAfter (from the first node when nil) whose caption equals Caption, ignoring the case of ASCII letters, searching depth-first through all loaded nodes whether expanded or not. Returns nil when there is none; the search does not wrap around. Children of lazy nodes that were never expanded do not exist yet and are not found. Raises EAtlasTreeError when StartAfter belongs to another tree.

pascal
Node := Tree.FindCaption('archive');
while Node <> nil do
  Node := Tree.FindCaption('archive', Node);

SortChildren method

procedure SortChildren(Parent: TTreeNode = nil);

Sorts the direct children of Parent, or the root nodes when Parent is nil, by caption with the Windows lstrcmp comparison. Deeper levels keep their order. Raises EAtlasTreeError when Parent belongs to another tree.

ToJSON method

function ToJSON: string;

Returns the nodes as a JSON array of objects {"caption": ..., "expanded": ..., "lazy": ..., "children": [...]} in tree order. lazy is true for a node that has an expand button but no loaded children.

LoadJSON method

procedure LoadJSON(const Text: string);

Replaces all nodes with the nodes of a document written by ToJSON. Every node needs a string caption, Boolean expanded and lazy, and an array children; nesting is limited to 128 levels. When the text is not a JSON array or a node is invalid it raises EAtlasTreeError and keeps the current nodes. OnLoadChildren is not called while loading. Needs a parent window.

Examples

Browse folders with lazy loading

Each folder node is lazy; its subfolders are read on first expand. The example run creates two folders and prints children after expand: 2 first: alpha.

pascal
uses System.SysUtils, System.IOUtils, Vcl.Forms, Vcl.Controls, Vcl.ComCtrls, Atlas.Tree;

type
  TFolderBrowser = class
  private
    FTree: TAtlasTree;
    function PathOf(Node: TTreeNode): string;
    procedure LoadFolders(Sender: TObject; Node: TTreeNode);
  public
    constructor Create(Form: TForm; const RootFolder: string);
    property Tree: TAtlasTree read FTree;
  end;

constructor TFolderBrowser.Create(Form: TForm; const RootFolder: string);
begin
  inherited Create;
  FTree := TAtlasTree.Create(Form);
  FTree.Parent := Form;      // the tree needs its window before nodes are added
  FTree.Align := alLeft;
  FTree.ReadOnly := True;    // folder names are not edited in place
  FTree.OnLoadChildren := LoadFolders;
  FTree.AddNode(nil, RootFolder, True);
end;

function TFolderBrowser.PathOf(Node: TTreeNode): string;
begin
  Result := Node.Text;
  while Node.Parent <> nil do
  begin
    Node := Node.Parent;
    Result := TPath.Combine(Node.Text, Result);
  end;
end;

procedure TFolderBrowser.LoadFolders(Sender: TObject; Node: TTreeNode);
var
  Folder: string;
begin
  // Runs on the first expand only. If it raises (no access, for example), the
  // tree removes what was added and the node stays expandable.
  for Folder in TDirectory.GetDirectories(PathOf(Node)) do
    FTree.AddNode(Node, ExtractFileName(Folder), True);
end;

Find, move, save and restore nodes

Moves Support under Sales, saves the tree, clears it and restores it; a file that is not a JSON array is rejected with Expected a JSON array and the three nodes are kept.

pascal
uses System.SysUtils, System.IOUtils, Vcl.ComCtrls, Atlas.Tree;

procedure SaveTree(Tree: TAtlasTree; const FileName: string);
begin
  TFile.WriteAllText(FileName, Tree.ToJSON, TEncoding.UTF8);
end;

procedure RestoreTree(Tree: TAtlasTree; const FileName: string);
begin
  try
    Tree.LoadJSON(TFile.ReadAllText(FileName, TEncoding.UTF8));
  except
    on E: EAtlasTreeError do
      Writeln('Tree not restored: ', E.Message); // the current nodes are kept
  end;
end;

procedure MoveUnder(Tree: TAtlasTree; const Caption, NewParentCaption: string);
var
  Node, NewParent: TTreeNode;
begin
  Node := Tree.FindCaption(Caption);
  NewParent := Tree.FindCaption(NewParentCaption);
  if (Node <> nil) and (NewParent <> nil) then
    Tree.MoveNode(Node, NewParent); // raises EAtlasTreeError if it would create a cycle
end;

TAtlasLoadChildrenEvent · EAtlasTreeError · TAtlasInspector

Also in Atlas VCL

TAtlasTable · TAtlasGrid · TAtlasValueEdit · TAtlasWorkbook · TAtlasSheetGrid · TAtlasPivot · TAtlasInspector · TAtlasRichEdit · TAtlasSpellChecker · TAtlasChart · TAtlasGauge · TAtlasThemer · TAtlasWizard · TAtlasWorkspace · TAtlasCommandBar · TAtlasActionTile · TAtlasTileBoard · TAtlasNavigation · TAtlasMap · TAtlasGraph · TAtlasDiagram · TAtlasPrintDocument · TAtlasSchedule · TAtlasScheduler · TAtlasTaskPlan · TAtlasGantt · TAtlasPdfDocument · TAtlasPdfViewer