TLinkList - Doubly-Linked Tree List
Source: source/classes/linklist.prg
TLinkList implements a doubly-linked list with hierarchical (tree) capabilities. Each node in
the list has a Cargo DATA for arbitrary user data and supports nesting via children.
Nodes can store a prompt string, bitmap handles, open/close state, an action codeblock, and a
nesting level. The class provides tree traversal, searching, sorting, and recursive expansion
or collapse of nodes.
DATA Members
| DATA | Type | Description |
|---|---|---|
oFirst | Object | First node in the list |
oLast | Object | Last node in the list |
Cargo | Any | Arbitrary user data attached to the list (or to each node) |
Methods
| Method | Description |
|---|---|
Add( cPrompt, nLevel, hBmpOpen, hBmpClose, lOpen, bAction, uCargo ) | Add a new node with prompt, nesting level, bitmap handles, open state, action codeblock and cargo |
Eval( bAction, bFor, bWhile, lRecurs ) | Evaluate a codeblock for each node, with optional filter (bFor), condition (bWhile) and recursive traversal |
Find( uFind, lRecurs ) | Find a node by cargo value (or by other criteria), optionally recursing into children |
Sort( lAsc, lRecurs, nCol ) | Sort nodes by prompt, ascending (lAsc=.T.) or descending, optionally recursive and by column |
OpenAll() | Recursively open all nodes (set lOpen=.T.) |
Expand( nLev ) | Expand (open) nodes down to level nLev |
Collapse( nLev ) | Collapse (close) nodes above level nLev |
nCount() | Return the total number of nodes |
Levels() | Return the maximum nesting depth |
Example: Build a Tree Structure
#include "FiveWin.ch"
function Main()
local oList := TLinkList():New()
// Add nodes: prompt, level, bitmap handles (0=none), open, action, cargo
oList:Add( "Root", 0, 0, 0, .T., nil, "root" )
oList:Add( "Documents", 1, 0, 0, .T., nil, "docs" )
oList:Add( " Report.txt", 2, 0, 0, .F., nil, "report" )
oList:Add( " Invoices", 2, 0, 0, .T., nil, "invoices" )
oList:Add( " Photos", 1, 0, 0, .F., nil, "photos" )
? "Total nodes:", oList:nCount()
? "Max levels:", oList:Levels()
// Traverse the tree
oList:Eval( {|oNode| QOut( oNode:Cargo ) }, nil, nil, .T. )
// Find a node by cargo
local oFound := oList:Find( "invoices", .T. )
if oFound != nil
? "Found:", oFound:Cargo
endif
return nil