The TTreeNodeShape class is the fundamental building block of TeeTree. Each node is a full standalone component with comprehensive properties, methods, and events.
Overview
Unlike traditional tree controls where nodes are simple data items, TeeTree nodes are complete visual components with rich formatting capabilities.
// Creating a node
var
Node: TTreeNodeShape;
begin
Node := Tree.Shapes. Add ( 'My Node' );
Node.Color := clYellow;
Node.Border.Width := 2 ;
end ;
Every node in TeeTree is a TTreeNodeShape instance derived from TCustomTreeElement, which provides core functionality shared with connections.
Node Properties
Position and Size
Nodes have explicit position and size properties:
// Position (top-left corner)
Node.X0 := 100 ; // or Node.Left := 100;
Node.Y0 := 50 ; // or Node.Top := 50;
// Size (bottom-right corner)
Node.X1 := 200 ;
Node.Y1 := 100 ;
// Alternative: Width and Height
Node.Width := 100 ;
Node.Height := 50 ;
Left and Top are aliases for X0 and Y0 respectively. Use whichever is more intuitive for your code.
Visual Appearance
// Background color
Node.Color := clWhite; // Default white
Node.Brush.Color := clYellow; // Alternative way
// Border
Node.Border.Color := clBlack;
Node.Border.Width := 1 ;
Node.Border.Style := psSolid;
// Transparency
Node.Transparency := 50 ; // 0-100%
Node.Transparent := True ; // No interior fill
// Apply gradient fill
with Node.Gradient do
begin
Visible := True ;
StartColor := clWhite;
EndColor := clBlue;
Direction := gdTopBottom;
end ;
// Gradient clipping
Node.GradientClip := True ; // Clip to shape bounds
with Node.Shadow do
begin
Visible := True ;
Size := 5 ;
Color := clGray;
Transparency := 50 ;
end ;
Node Styles
Nodes support various visual styles:
type
TTreeShapeStyle = (
tssRectangle, // Default
tssCircle,
tssVertLine,
tssHorizLine,
tssLine,
tssInvertLine,
tssDiamond,
tssTriangleTop,
tssTriangleBottom,
tssTriangleLeft,
tssTriangleRight,
tssRoundRectangle,
tssCustom,
tssChamfer
);
// Apply style
Node.Style := tssRoundRectangle;
Node.RoundSize := 10 ; // Corner radius
When using tssCustom style, you’ll need to override the GetShapePoints method to define your custom shape.
Text Properties
Nodes have sophisticated text handling:
// Simple text assignment
Node.SimpleText := 'Hello World' ;
// Multi-line text
Node.Text.Clear;
Node.Text. Add ( 'Line 1' );
Node.Text. Add ( 'Line 2' );
// Text formatting
Node.Text.HorizAlign := htaCenter; // htaLeft, htaRight
Node.Text.VertAlign := vtaCenter; // vtaTop, vtaBottom
Node.Text.Angle := 45 ; // 0..360 degrees
Node.Text.ClipText := False ; // Allow text outside bounds
// Font
Node.Font. Name := 'Arial' ;
Node.Font.Size := 12 ;
Node.Font.Style := [fsBold];
Node.Font.Color := clBlack;
AutoSize
Nodes can automatically size themselves based on content:
Node.AutoSize := True ; // Default
Node.SimpleText := 'This text determines the node size' ;
// Disable for manual sizing
Node.AutoSize := False ;
Node.Width := 200 ;
Node.Height := 100 ;
When AutoSize is enabled, the node calculates its size based on text and image dimensions plus margins.
Images
Nodes can display images in various positions:
// Using stock images
Node.ImageIndex := tiFolderClose;
Node.Expanded := False ;
// Using custom image
Node.Image.LoadFromFile( 'myimage.png' );
// Image alignment
Node.ImageAlignment := iaLeft; // iaAutomatic, iaLeftTop, iaRight, etc.
// Custom image size
Node.ImageWidth := 32 ;
Node.ImageHeight := 32 ;
// Using ImageList
Node.ImageListIndex := 0 ; // Index in Tree.Images
Image Alignment Options
type
TTreeImageAlignment = (
iaAutomatic, // Smart positioning
iaLeftTop,
iaRightBottom,
iaLeftBottom,
iaRightTop,
iaLeft,
iaTop,
iaRight,
iaBottom,
iaCenter
);
Parent-Child Relationships
Nodes form hierarchies through parent-child relationships:
// Create hierarchy
var
Parent, Child1, Child2: TTreeNodeShape;
begin
Parent := Tree.Shapes. Add ( 'Parent' );
Child1 := Parent.AddChild( 'Child 1' );
Child2 := Parent.AddChild( 'Child 2' );
// Alternative: Set parent explicitly
Child1.Parent := Parent;
end ;
// Access children
for i := 0 to Parent.Children.Count - 1 do
ProcessChild(Parent.Children[i]);
// Check if node has children
if Node.HasChildren then
Node.Expanded := True ;
When a parent node is destroyed, all its children are automatically freed.
Child Management Methods
// Add children
Child := Node.AddChild( 'New Child' ); // Add at end
Child := Node.AddChildFirst( 'First Child' ); // Add at beginning
Child := Node.Insert( 1 , 'Insert at Index 1' ); // Insert at position
// Add with data
Child := Node.AddChildObject( 'Child' , MyDataPointer);
// Add sibling
Brother := Node.AddBrother( 'Sibling Node' );
// Node count
Count := Node.Count; // Number of direct children
Expand and Collapse
Nodes can be expanded or collapsed to show/hide children:
// Expand/Collapse
Node.Expanded := True ;
Node.Expanded := False ;
// Toggle
Node.Toggle;
// Collapse recursively
Node.Collapse( True ); // Collapse this and all descendants
// Show CrossBox
Node.ShowCross := scAuto; // scAuto, scAlways, scNever
CrossBox Styles
type
TTreeNodeShapeShowCross = (
scAuto, // Show only when node has children
scAlways, // Always show
scNever // Never show
);
AutoPosition
Control automatic positioning of nodes:
// Enable both Left and Top auto-positioning
Node.AutoPosition.Left := True ; // Default
Node.AutoPosition.Top := True ; // Default
// Manual X position, automatic Y
Node.AutoPosition.Left := False ;
Node.AutoPosition.Top := True ;
Node.X0 := 100 ; // Fixed X position
The ChildManager class calculates positions for nodes with AutoPosition enabled. See Child Managers for details.
Selection and Interaction
// Select a node
Node.Selected := True ;
// Check if selected
if Node.Selected then
ShowMessage( 'Node is selected' );
// Add to tree selection
Tree.Selected. Add (Node);
// Events
Node.OnClick := NodeClickHandler;
Node.OnDblClick := NodeDblClickHandler;
Node.OnMouseEnter := NodeMouseEnterHandler;
Node.OnMouseLeave := NodeMouseLeaveHandler;
Event Handlers
procedure TForm1.NodeClickHandler (Sender: TTreeNodeShape;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer );
begin
ShowMessage( 'Clicked: ' + Sender.SimpleText);
end ;
Node Navigation
// Access parent and siblings
ParentNode := Node.Parent;
RootNode := Node.Root;
PreviousNode := Node.PreviousBrother;
// Get node level (depth in tree)
Level := Node.Level; // 0 for root nodes
// Brother index (position among siblings)
Index := Node.BrotherIndex;
Node.BrotherIndex := 0 ; // Move to first position
Visibility Control
// Show/Hide
Node.Visible := True ;
Node.Show;
Node.Hide;
// Check if inside tree bounds
if Node.InsideTreeBounds then
ProcessNode(Node);
Data Association
// Store custom data
Node.Data := MyDataPointer;
Node.TagObject := MyObject;
Node.Tag := 123 ;
// Retrieve data
MyData := PMyDataType(Node.Data);
MyObj := Node.TagObject as TMyClass;
The Data property is a raw pointer. Ensure proper memory management. TagObject provides automatic reference counting on supported platforms.
Advanced Features
Checkboxes
// Use checkbox images
Node.ImageIndex := tiUnChecked;
Node.Checked := False ;
// Toggle checkbox
Node.ToggleCheck;
Node.Checked := True ; // Now shows tiChecked
// Check all selected
Tree.Selected.ToggleCheck;
Custom Drawing
// Override DrawShapeCanvas for custom rendering
type
TMyNode = class (TTreeNodeShape)
protected
procedure DrawShapeCanvas ( const ACanvas: TCanvas3D;
const R: TRect); override ;
end ;
Z-Order
// Control drawing order
Node.BringToFront;
Node.SendToBack;
Utility Methods
// Geometry
CenterX := Node.XCenter;
CenterY := Node.YCenter;
Bounds := Node.Bounds; // TRect
Adjusted := Node.AdjustedRectangle; // Includes image
// Sorting children
Node.SortChildsText( True , False ); // Ascending, case-sensitive
// Select all children
Node.SelectChilds;
// Move node
Node.MoveRelative( 10 , 20 , True ); // DeltaX, DeltaY, MoveChildren
// Resize
Node.Resize(rcRightBottom, 10 , 10 ); // Corner, DeltaX, DeltaY
Best Practices
Use AutoSize Let nodes automatically size themselves based on content for consistent appearance
Leverage Parent-Child Use parent-child relationships instead of manual positioning when possible
Cache References Store node references in data structures for quick access instead of searching
Handle Events Use node events for interactive features rather than polling
Next Steps
Connections Learn how to link nodes together
Child Managers Understand automatic layout management
Styling Guide Master visual customization