mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 09:18:02 +02:00
VirtualTreeView: Add dataarray sample project.
This commit is contained in:
parent
bf13d10552
commit
92271f5b1a
169
examples/virtualtreeview/vst_dataarray/Main.lfm
Normal file
169
examples/virtualtreeview/vst_dataarray/Main.lfm
Normal file
@ -0,0 +1,169 @@
|
||||
object MainForm: TMainForm
|
||||
Left = 188
|
||||
Height = 396
|
||||
Top = 104
|
||||
Width = 649
|
||||
ActiveControl = MyTree
|
||||
Caption = 'Data Array Virtual Tree Demo'
|
||||
ClientHeight = 396
|
||||
ClientWidth = 649
|
||||
Position = poScreenCenter
|
||||
LCLVersion = '3.99.0.0'
|
||||
OnClose = FormClose
|
||||
OnCreate = FormCreate
|
||||
object Label1: TLabel
|
||||
AnchorSideLeft.Control = Label3
|
||||
AnchorSideTop.Control = Edit1
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 224
|
||||
Height = 15
|
||||
Top = 319
|
||||
Width = 167
|
||||
Caption = 'Array data of the clicked node:'
|
||||
ParentColor = False
|
||||
end
|
||||
object Label2: TLabel
|
||||
AnchorSideLeft.Control = Label3
|
||||
AnchorSideBottom.Control = Label3
|
||||
Left = 224
|
||||
Height = 15
|
||||
Top = 344
|
||||
Width = 247
|
||||
Anchors = [akLeft, akBottom]
|
||||
BorderSpacing.Bottom = 6
|
||||
Caption = 'Find and show the node by specific array index'
|
||||
ParentColor = False
|
||||
end
|
||||
object Label3: TLabel
|
||||
AnchorSideLeft.Control = btnDelete
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Edit2
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 224
|
||||
Height = 15
|
||||
Top = 365
|
||||
Width = 259
|
||||
BorderSpacing.Left = 32
|
||||
BorderSpacing.Right = 6
|
||||
Caption = 'Type index to get related tree node on the screen:'
|
||||
ParentColor = False
|
||||
end
|
||||
object Button1: TButton
|
||||
AnchorSideLeft.Control = MyTree
|
||||
AnchorSideTop.Control = Edit1
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 6
|
||||
Height = 25
|
||||
Top = 314
|
||||
Width = 83
|
||||
BorderSpacing.InnerBorder = 4
|
||||
Caption = 'Add nodes'
|
||||
TabOrder = 0
|
||||
OnClick = Button1Click
|
||||
end
|
||||
object btnDelete: TButton
|
||||
AnchorSideLeft.Control = Button1
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Button1
|
||||
Left = 95
|
||||
Height = 25
|
||||
Top = 314
|
||||
Width = 97
|
||||
BorderSpacing.Left = 6
|
||||
BorderSpacing.InnerBorder = 4
|
||||
Caption = 'Delete selected'
|
||||
TabOrder = 1
|
||||
OnClick = btnDeleteClick
|
||||
end
|
||||
object Edit1: TEdit
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideTop.Control = Button1
|
||||
AnchorSideTop.Side = asrCenter
|
||||
AnchorSideRight.Control = Edit2
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = Label2
|
||||
Left = 410
|
||||
Height = 23
|
||||
Top = 315
|
||||
Width = 170
|
||||
Anchors = [akRight, akBottom]
|
||||
BorderSpacing.Around = 6
|
||||
ReadOnly = True
|
||||
TabOrder = 2
|
||||
end
|
||||
object btnCleanAll: TButton
|
||||
AnchorSideTop.Control = Edit2
|
||||
AnchorSideTop.Side = asrCenter
|
||||
Left = 56
|
||||
Height = 25
|
||||
Top = 360
|
||||
Width = 75
|
||||
BorderSpacing.InnerBorder = 4
|
||||
Caption = 'Clean all'
|
||||
TabOrder = 3
|
||||
OnClick = btnCleanAllClick
|
||||
end
|
||||
object Edit2: TEdit
|
||||
AnchorSideLeft.Control = Label3
|
||||
AnchorSideLeft.Side = asrBottom
|
||||
AnchorSideBottom.Control = Owner
|
||||
AnchorSideBottom.Side = asrBottom
|
||||
Left = 489
|
||||
Height = 23
|
||||
Top = 361
|
||||
Width = 97
|
||||
Anchors = [akLeft, akBottom]
|
||||
BorderSpacing.Bottom = 12
|
||||
TabOrder = 4
|
||||
OnChange = Edit2Change
|
||||
end
|
||||
object MyTree: TLazVirtualStringTree
|
||||
AnchorSideLeft.Control = Owner
|
||||
AnchorSideTop.Control = Owner
|
||||
AnchorSideRight.Control = Owner
|
||||
AnchorSideRight.Side = asrBottom
|
||||
AnchorSideBottom.Control = Edit1
|
||||
Left = 6
|
||||
Height = 303
|
||||
Top = 6
|
||||
Width = 637
|
||||
Anchors = [akTop, akLeft, akRight, akBottom]
|
||||
AutoScrollDelay = 1
|
||||
BorderSpacing.Around = 6
|
||||
DefaultText = 'Node'
|
||||
Header.AutoSizeIndex = 0
|
||||
Header.Columns = <
|
||||
item
|
||||
Position = 0
|
||||
Text = 'Text'
|
||||
Width = 150
|
||||
end
|
||||
item
|
||||
Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||
Position = 1
|
||||
Text = 'Pointers'
|
||||
Width = 300
|
||||
end
|
||||
item
|
||||
Position = 2
|
||||
Text = 'Random'
|
||||
Width = 100
|
||||
end>
|
||||
Header.DefaultHeight = 17
|
||||
Header.Font.Style = [fsBold]
|
||||
Header.Height = 17
|
||||
Header.Options = [hoColumnResize, hoDblClickResize, hoDrag, hoShowSortGlyphs, hoVisible]
|
||||
Header.SortColumn = 0
|
||||
RootNodeCount = 10
|
||||
TabOrder = 5
|
||||
TreeOptions.AutoOptions = [toAutoDropExpand, toAutoScroll, toAutoScrollOnExpand, toAutoTristateTracking]
|
||||
TreeOptions.SelectionOptions = [toMultiSelect]
|
||||
OnBeforeCellPaint = MyTreeBeforeCellPaint
|
||||
OnCompareNodes = MyTreeCompareNodes
|
||||
OnFocusChanged = MyTreeFocusChanged
|
||||
OnFreeNode = MyTreeFreeNode
|
||||
OnGetText = MyTreeGetText
|
||||
OnPaintText = MyTreePaintText
|
||||
OnHeaderClick = MyTreeHeaderClick
|
||||
end
|
||||
end
|
560
examples/virtualtreeview/vst_dataarray/Main.pas
Normal file
560
examples/virtualtreeview/vst_dataarray/Main.pas
Normal file
@ -0,0 +1,560 @@
|
||||
unit Main;
|
||||
|
||||
{$MODE Delphi}
|
||||
|
||||
{
|
||||
|
||||
How to use TVirtualTree with your data
|
||||
already stored somewhere (array or memory)?
|
||||
|
||||
You need to solve cross-linked problem between
|
||||
your data and TVirtualTree record node and avoid
|
||||
doubling data in TVirtualTree record node?
|
||||
|
||||
This example shows one way of what you need
|
||||
to accomplish.
|
||||
|
||||
Additionally, here you can find how to
|
||||
conditionally color you cell's background
|
||||
and font foreground and how to sort VST by
|
||||
clicking on columns.
|
||||
|
||||
Also shows which property are initially needed
|
||||
to be set for comfortable using.
|
||||
|
||||
This is my humble contribution for
|
||||
users who start to use Mike Lischke's
|
||||
TVirtualTree component.
|
||||
|
||||
Thank you Mike for such a beautiful component.
|
||||
|
||||
The initial developer of this code is Sasa Zeman.
|
||||
Mailto: public@szutils.net or sasaz72@mail.ru
|
||||
Web site: www.szutils.net
|
||||
|
||||
Created: 7 Jun 2004
|
||||
|
||||
This example is distributed "AS IS", WITHOUT
|
||||
WARRANTY OF ANY KIND, either express or implied.
|
||||
|
||||
You use it at your own risk!
|
||||
}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
LCLIntf, SysUtils, Classes, Graphics, Controls, Forms,
|
||||
Dialogs, laz.VirtualTrees, StdCtrls, LResources, Buttons;
|
||||
|
||||
type
|
||||
|
||||
{ Problem description:
|
||||
|
||||
VST is designed to use your own declared record data
|
||||
in his nodes, which are automatically created and
|
||||
destroying. That is beautiful, easy and fast.
|
||||
|
||||
But, what if you have your data already formated somewhere
|
||||
in array or memory and your algorithms are already optimized
|
||||
to use it on that way? How to use VST with them?
|
||||
|
||||
Since VST node can consist any data record, that can be only
|
||||
a index or pointer to your real data. The only problem left is
|
||||
that actions in your data must affect on corespondent VST node.
|
||||
One way is to sequentially go through the VST and find the node
|
||||
which consists equal index index, which rapidly decrease
|
||||
performance...
|
||||
|
||||
To handle this situation the most efficiently, your array data
|
||||
record must additionally consist the pointer to the VST
|
||||
corespondent node...
|
||||
}
|
||||
|
||||
TMyRecord = record
|
||||
// Point directly from my record to corespondent VST Node
|
||||
// That is useful if your action inside
|
||||
// the record involve on your VTS node,
|
||||
// for example, if disabling mean deletion
|
||||
// of corespondent node, etc.
|
||||
|
||||
NodePointer: PVirtualNode;
|
||||
Active: Boolean;
|
||||
MyText: String;
|
||||
RNDNumber: integer;
|
||||
end;
|
||||
|
||||
rTreeData = record
|
||||
//This point to my index into my array
|
||||
//Instead of index, here you can
|
||||
//store the pointer to your data.
|
||||
//That depend of what is your intentions
|
||||
//and your data structure
|
||||
|
||||
IndexInMyData: integer;
|
||||
|
||||
end;
|
||||
|
||||
{ TMainForm }
|
||||
|
||||
TMainForm = class(TForm)
|
||||
Button1: TButton;
|
||||
btnDelete: TButton;
|
||||
Edit1: TEdit;
|
||||
btnCleanAll: TButton;
|
||||
Edit2: TEdit;
|
||||
Label1: TLabel;
|
||||
Label2: TLabel;
|
||||
Label3: TLabel;
|
||||
MyTree: TLazVirtualStringTree;
|
||||
procedure MyTreeBeforeCellPaint(Sender: TBaseVirtualTree;
|
||||
TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||||
CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
|
||||
procedure MyTreeGetText(Sender: TBaseVirtualTree;
|
||||
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
|
||||
var CellText: String);
|
||||
procedure Button1Click(Sender: TObject);
|
||||
procedure MyTreeCompareNodes(Sender: TBaseVirtualTree; Node1,
|
||||
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
|
||||
{$if VTMajorVersion < 5}
|
||||
procedure MyTreeHeaderClick(Sender: TVTHeader; Column: TColumnIndex;
|
||||
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
{$else}
|
||||
procedure MyTreeHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo);
|
||||
{$endif}
|
||||
procedure btnDeleteClick(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure MyTreePaintText(Sender: TBaseVirtualTree;
|
||||
const TargetCanvas: TCanvas; Node: PVirtualNode;
|
||||
Column: TColumnIndex; TextType: TVSTTextType);
|
||||
procedure MyTreeFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure MyTreeFocusChanged(Sender: TBaseVirtualTree;
|
||||
Node: PVirtualNode; Column: TColumnIndex);
|
||||
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
procedure btnCleanAllClick(Sender: TObject);
|
||||
procedure Edit2Change(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
MyArrayData: array of TMyRecord;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.lfm}
|
||||
|
||||
uses
|
||||
Math;
|
||||
|
||||
procedure TMainForm.MyTreeGetText(Sender: TBaseVirtualTree;
|
||||
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
|
||||
var CellText: String);
|
||||
var
|
||||
Data: ^rTreeData;
|
||||
|
||||
begin
|
||||
// To get Node Data
|
||||
Data := Sender.GetNodeData(Node);
|
||||
|
||||
with MyArrayData[Data.IndexInMyData] do
|
||||
case Column of
|
||||
0: CellText := MyText;
|
||||
1:
|
||||
begin
|
||||
CellText := format('Stored %p Actual %p',
|
||||
[NodePointer,Node]);
|
||||
end;
|
||||
2: CellText := inttostr(RNDNumber);
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.Button1Click(Sender: TObject);
|
||||
var
|
||||
Node: PVirtualNode;
|
||||
Data: ^rTreeData;
|
||||
|
||||
i,Idx: integer;
|
||||
Timer: cardinal;
|
||||
begin
|
||||
|
||||
// Add 100000 new records and corespondent VST nodes
|
||||
|
||||
Timer := GetTickCount;
|
||||
|
||||
MyTree.BeginUpdate;
|
||||
|
||||
Idx := length(MyArrayData);
|
||||
SetLength(MyArrayData, length(MyArrayData)+100000);
|
||||
for i := 1 to 100000 do
|
||||
begin
|
||||
// Add a node to the root of the Tree
|
||||
Node := MyTree.AddChild(nil);
|
||||
Data := MyTree.GetNodeData(Node);
|
||||
|
||||
//Create link to your data record into VST node
|
||||
Data.IndexInMyData := Idx;
|
||||
|
||||
// Working with your array data
|
||||
with MyArrayData[Data.IndexInMyData] do
|
||||
begin
|
||||
|
||||
//Create link into your data record to VST node
|
||||
NodePointer := Node;
|
||||
|
||||
RNDNumber := round(Random(1 shl 16));
|
||||
MyText := format(' Index %d',[Data.IndexInMyData])
|
||||
|
||||
end;
|
||||
inc(Idx)
|
||||
end;
|
||||
MyTree.EndUpdate;
|
||||
|
||||
Timer := GetTickCount-Timer;
|
||||
caption := format('Adding %d ms, Total nodes %d, Total arrays %d',[Timer, MyTree.RootNodeCount,length(MyArrayData)] );
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.MyTreeCompareNodes(Sender: TBaseVirtualTree; Node1,
|
||||
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
|
||||
var
|
||||
n1,n2: ^rTreeData;
|
||||
d1,d2: ^TMyRecord;
|
||||
begin
|
||||
n1 := MyTree.GetNodeData(Node1);
|
||||
n2 := MyTree.GetNodeData(Node2);
|
||||
|
||||
// Get the pointers where your data are
|
||||
// in the array, to speed-up process
|
||||
d1 := @MyArrayData[n1.IndexInMyData];
|
||||
d2 := @MyArrayData[n2.IndexInMyData];
|
||||
|
||||
case Column of
|
||||
0: Result := CompareValue(n1.IndexInMyData,n2.IndexInMyData);
|
||||
1: ;
|
||||
2: Result := CompareValue(
|
||||
d1.RNDNumber,
|
||||
d2.RNDNumber
|
||||
)
|
||||
else
|
||||
Result := 0;
|
||||
end
|
||||
end;
|
||||
|
||||
{$if VTMajorVersion < 5}
|
||||
procedure TMainForm.MyTreeHeaderClick(Sender: TVTHeader; Column: TColumnIndex;
|
||||
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
||||
{$else}
|
||||
procedure TMainForm.MyTreeHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo);
|
||||
{$endif}
|
||||
var
|
||||
Direction : TSortDirection;
|
||||
{$if VTMajorVersion >= 5}
|
||||
Column: TColumnIndex;
|
||||
Shift: TShiftState;
|
||||
{$endif}
|
||||
begin
|
||||
{$if VTMajorVersion >= 5}
|
||||
Column := HitInfo.Column;
|
||||
Shift := HitInfo.Shift;
|
||||
{$endif}
|
||||
// Descending order with pressed Shift, otherwise Ascending
|
||||
// Or you can save Direction or use
|
||||
// MyTree.Header.SortDirection and MyTree.Header.SortColumn
|
||||
// to get automatically Descending/Ascending sorting
|
||||
// by only clicking on header
|
||||
|
||||
if ssShift in Shift
|
||||
then
|
||||
Direction := sdDescending
|
||||
else
|
||||
Direction := sdAscending;
|
||||
|
||||
// Sort all columns except the second
|
||||
if Column<>1 then
|
||||
begin
|
||||
// Set direction image on the sorted column
|
||||
MyTree.Header.SortColumn := Column;
|
||||
|
||||
// Set the right direction image
|
||||
MyTree.Header.SortDirection := Direction;
|
||||
|
||||
// Sorting process
|
||||
MyTree.SortTree(Column, Direction);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnDeleteClick(Sender: TObject);
|
||||
var
|
||||
Timer: cardinal;
|
||||
begin
|
||||
|
||||
// Delete all selected nodes
|
||||
|
||||
Timer := GetTickCount;
|
||||
|
||||
MyTree.BeginUpdate;
|
||||
MyTree.DeleteSelectedNodes;
|
||||
MyTree.EndUpdate;
|
||||
|
||||
Timer := GetTickCount-Timer;
|
||||
caption := format('Deleting %d ms, Total nodes %d, Total arrays %d',[Timer, MyTree.RootNodeCount,length(MyArrayData)] );
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
const
|
||||
|
||||
ColumnParams: array[0..2] of
|
||||
record
|
||||
Name: ShortString;
|
||||
Len: integer;
|
||||
Alignment:TAlignment;
|
||||
end =
|
||||
((Name:'Text' ; Len:150 ; Alignment: taLeftJustify),
|
||||
(Name:'Pointers' ; Len:300 ; Alignment: taLeftJustify),
|
||||
(Name:'Random' ; Len:120 ; Alignment: taLeftJustify)
|
||||
);
|
||||
|
||||
var
|
||||
NewColumn: TVirtualTreeColumn;
|
||||
i: integer;
|
||||
begin
|
||||
// Initialize size of node in MyTree
|
||||
// This is the most important to be done before any using of VST,
|
||||
// because that is the only way how VST can allocate needed
|
||||
// space for your node
|
||||
MyTree.NodeDataSize := sizeof(rTreeData);
|
||||
|
||||
// When you add data by yourself,
|
||||
// be sure that there is no node in tree
|
||||
MyTree.RootNodeCount := 0;
|
||||
|
||||
// If you want to manually set necessary events or parameters,
|
||||
// without Object Inspector. That will help in case
|
||||
// you have accidentally deleted your component
|
||||
// and you do not have a time to work with Object Inspector
|
||||
// and rearrange the events or other properties
|
||||
|
||||
// First follows the properties you may set it here or with
|
||||
// Object Inspector to be more suitable for standard using
|
||||
|
||||
// Shows the header columns
|
||||
MyTree.Header.Options :=
|
||||
MyTree.Header.Options + [hoVisible];
|
||||
|
||||
// Allows multi selection of nodes
|
||||
MyTree.TreeOptions.SelectionOptions :=
|
||||
MyTree.TreeOptions.SelectionOptions +[toMultiSelect];
|
||||
|
||||
// Allows that automatic multi selection is possible
|
||||
// beyond the screen
|
||||
MyTree.TreeOptions.AutoOptions :=
|
||||
MyTree.TreeOptions.AutoOptions + [toAutoScroll];
|
||||
|
||||
// If delay of 1000 ms is too slow during
|
||||
// automatic multi selection
|
||||
MyTree.AutoScrollDelay := 100;
|
||||
|
||||
// Disable automatic deletion of moved data during
|
||||
// Drag&Drop operation
|
||||
MyTree.TreeOptions.AutoOptions :=
|
||||
MyTree.TreeOptions.AutoOptions - [toAutoDeleteMovedNodes];
|
||||
|
||||
// To show the bacground image on VST
|
||||
MyTree.TreeOptions.PaintOptions :=
|
||||
MyTree.TreeOptions.PaintOptions +[toShowBackground];
|
||||
|
||||
// If you do not want to show the tree lines
|
||||
// MyTree.TreeOptions.PaintOptions :=
|
||||
// MyTree.TreeOptions.PaintOptions -[toShowTreeLines];
|
||||
|
||||
// If you do not want to show left margine of the main node
|
||||
// MyTree.TreeOptions.PaintOptions :=
|
||||
// MyTree.TreeOptions.PaintOptions -[toShowRoot];
|
||||
|
||||
// If you want to add your columns manually
|
||||
MyTree.Header.Columns.Clear;
|
||||
|
||||
for i := 0 to length(ColumnParams)-1 do
|
||||
with MyTree.Header, ColumnParams[i] do
|
||||
begin
|
||||
|
||||
NewColumn := Columns.Add;
|
||||
|
||||
NewColumn.Text := Name;
|
||||
NewColumn.Width := Len;
|
||||
NewColumn.Alignment := Alignment;
|
||||
|
||||
end;
|
||||
|
||||
// If you want that the second column
|
||||
// do not respond on clicking
|
||||
MyTree.Header.Columns[1].Options :=
|
||||
MyTree.Header.Columns[1].Options - [coAllowClick];
|
||||
|
||||
|
||||
// Setting used events manually
|
||||
|
||||
MyTree.OnBeforeCellPaint := MyTreeBeforeCellPaint;
|
||||
MyTree.OnCompareNodes := MyTreeCompareNodes;
|
||||
MyTree.OnFocusChanged := MyTreeFocusChanged;
|
||||
MyTree.OnFreeNode := MyTreeFreeNode;
|
||||
MyTree.OnGetText := MyTreeGetText;
|
||||
MyTree.OnHeaderClick := MyTreeHeaderClick;
|
||||
MyTree.OnPaintText := MyTreePaintText;
|
||||
|
||||
// To show headers
|
||||
MyTree.Header.Options :=
|
||||
MyTree.Header.Options + [hoVisible];
|
||||
|
||||
//To show Direction Glyphs
|
||||
MyTree.Header.Options :=
|
||||
MyTree.Header.Options + [hoShowSortGlyphs];
|
||||
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.MyTreeBeforeCellPaint(Sender: TBaseVirtualTree;
|
||||
TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||||
CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
|
||||
begin
|
||||
// This is example how to conditionally
|
||||
// color the cell's backgrounds
|
||||
|
||||
// Color cell's background only for
|
||||
// the first three columns with every second nodes
|
||||
if (Column<2) and
|
||||
((Node.Index mod 2)=0)
|
||||
then begin
|
||||
TargetCanvas.Brush.Color := clMoneyGreen;
|
||||
TargetCanvas.FillRect(CellRect);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure TMainForm.MyTreePaintText(Sender: TBaseVirtualTree;
|
||||
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
||||
TextType: TVSTTextType);
|
||||
var
|
||||
n1: ^rTreeData;
|
||||
d1: ^TMyRecord;
|
||||
begin
|
||||
|
||||
// This is example how to conditionally
|
||||
// color the cell's font color foregrounds
|
||||
|
||||
if (Column=1) and
|
||||
((Node.Index mod 2)=0)
|
||||
then
|
||||
TargetCanvas.Font.Color := clRed;
|
||||
|
||||
if (Column=2)
|
||||
then begin
|
||||
n1 := MyTree.GetNodeData(Node);
|
||||
d1 := @MyArrayData[n1.IndexInMyData];
|
||||
|
||||
// Coloring cell's data depending of your data
|
||||
if (d1.RNDNumber mod 2)=0
|
||||
then begin
|
||||
TargetCanvas.Font.Color := clBlue;
|
||||
TargetCanvas.Font.Style := [fsBold];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.MyTreeFreeNode(Sender: TBaseVirtualTree;
|
||||
Node: PVirtualNode);
|
||||
var
|
||||
n1: ^rTreeData;
|
||||
d1: ^TMyRecord;
|
||||
begin
|
||||
|
||||
// Action when you delete the VST node
|
||||
|
||||
if Node <> nil then
|
||||
begin
|
||||
n1 := MyTree.GetNodeData(Node);
|
||||
d1 := @MyArrayData[n1.IndexInMyData];
|
||||
|
||||
// Deactive record in array
|
||||
d1.Active := false;
|
||||
|
||||
// Detach pointer to this node in your data
|
||||
d1.NodePointer := nil
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.MyTreeFocusChanged(Sender: TBaseVirtualTree;
|
||||
Node: PVirtualNode; Column: TColumnIndex);
|
||||
var
|
||||
n1: ^rTreeData;
|
||||
d1: ^TMyRecord;
|
||||
begin
|
||||
// Always be sure that Node exist before you
|
||||
// delete VST node and use OnFocusChanged even
|
||||
// in your code - they will be always triggered
|
||||
// on node deletion
|
||||
|
||||
if Node<> nil then
|
||||
begin
|
||||
n1 := MyTree.GetNodeData(Node);
|
||||
d1 := @MyArrayData[n1.IndexInMyData];
|
||||
|
||||
// Store MyText from array to TEdit
|
||||
// after focused item was changed
|
||||
Edit1.Text := d1.MyText+', Number '+ IntToStr(d1.RNDNumber)
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
||||
begin
|
||||
btnCleanAll.Click
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnCleanAllClick(Sender: TObject);
|
||||
begin
|
||||
// Fast deletion of all your data and VST nodes
|
||||
|
||||
MyTree.OnFreeNode := nil;
|
||||
|
||||
MyTree.Clear;
|
||||
SetLength(MyArrayData,0);
|
||||
|
||||
MyTree.OnFreeNode := MyTreeFreeNode
|
||||
|
||||
end;
|
||||
|
||||
procedure TMainForm.Edit2Change(Sender: TObject);
|
||||
var
|
||||
Node: PVirtualNode;
|
||||
ind: integer;
|
||||
begin
|
||||
ind := StrToIntDef(Edit2.Text,0);
|
||||
|
||||
if ind<length(MyArrayData) then
|
||||
begin
|
||||
Node := MyArrayData[ind].NodePointer;
|
||||
|
||||
if Node<> nil then
|
||||
begin
|
||||
// Show it at center of VST
|
||||
MyTree.ScrollIntoView(Node,True);
|
||||
|
||||
// Get text from the array
|
||||
Edit1.Text :=
|
||||
MyArrayData[ind].MyText+', Number '+ IntToStr(MyArrayData[ind].RNDNumber)
|
||||
|
||||
end else
|
||||
Edit1.Text := 'Node do not exist!'
|
||||
end
|
||||
end;
|
||||
|
||||
|
||||
end.
|
81
examples/virtualtreeview/vst_dataarray/dataarray.lpi
Normal file
81
examples/virtualtreeview/vst_dataarray/dataarray.lpi
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="12"/>
|
||||
<PathDelim Value="\"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<LRSInOutputDirectory Value="False"/>
|
||||
<CompatibilityMode Value="True"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<ResourceType Value="res"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
</General>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<local>
|
||||
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
<FormatVersion Value="2"/>
|
||||
<Modes Count="1">
|
||||
<Mode0 Name="default">
|
||||
<local>
|
||||
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
</Mode0>
|
||||
</Modes>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="2">
|
||||
<Item1>
|
||||
<PackageName Value="laz.virtualtreeview_package"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item2>
|
||||
</RequiredPackages>
|
||||
<Units Count="2">
|
||||
<Unit0>
|
||||
<Filename Value="dataarray.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="Main.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<ComponentName Value="MainForm"/>
|
||||
<HasResources Value="True"/>
|
||||
<ResourceBaseClass Value="Form"/>
|
||||
</Unit1>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="dataarray"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<UseAnsiStrings Value="False"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<DebugInfoType Value="dsDwarf3"/>
|
||||
</Debugging>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
</Win32>
|
||||
</Options>
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
</CONFIG>
|
21
examples/virtualtreeview/vst_dataarray/dataarray.lpr
Normal file
21
examples/virtualtreeview/vst_dataarray/dataarray.lpr
Normal file
@ -0,0 +1,21 @@
|
||||
program dataarray;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||
cthreads,
|
||||
{$ENDIF}{$ENDIF}
|
||||
Interfaces, // this includes the LCL widgetset
|
||||
Forms
|
||||
{ add your units here },
|
||||
Main;
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
|
BIN
examples/virtualtreeview/vst_dataarray/dataarray.res
Normal file
BIN
examples/virtualtreeview/vst_dataarray/dataarray.res
Normal file
Binary file not shown.
2
examples/virtualtreeview/vst_dataarray/readme.txt
Normal file
2
examples/virtualtreeview/vst_dataarray/readme.txt
Normal file
@ -0,0 +1,2 @@
|
||||
This is an "official" VirtualTreeView demo project ported to and optimized for Lazarus.
|
||||
More samples can be found at https://github.com/blikblum/VirtualTreeView-Lazarus/tree/lazarus-v5/Demos.
|
11
examples/virtualtreeview/vst_dataarray/vst_dataarray.ex-meta
Normal file
11
examples/virtualtreeview/vst_dataarray/vst_dataarray.ex-meta
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"vst_dataarray" : {
|
||||
"Category" : "General",
|
||||
"Keywords" : [
|
||||
"TLazVirtualStringTree",
|
||||
"TVirtualTreeView",
|
||||
"Data"
|
||||
],
|
||||
"Description" : "This is about TLazVirtualStringTree, a component renamed from TVirtualTreeView that exists in the LazControls Component Tab. \n\nThis example demonstrates how to access data from a VirtualStringTree when they are stored somewhere in your own data structure. Further details in the header of the 'Main' unit."
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user