2007-02-22 13:09:12 +00:00
|
|
|
{*********************************************************************** }
|
|
|
|
{ File: VTPropEdit.pas }
|
|
|
|
{ }
|
|
|
|
{ Purpose: }
|
|
|
|
{ source file to illustrate how to get started with VT }
|
|
|
|
{ <-- general purpose property editor with ability to dynamically refresh --> }
|
|
|
|
{ see ShowExample procedure at base of this file }
|
|
|
|
{ }
|
|
|
|
{ }
|
|
|
|
{ Note: }
|
|
|
|
{ This is an example only and time permitting I'd like to write a }
|
|
|
|
{ proper one. It is still useful, with the basic idea being that }
|
|
|
|
{ the property editor may be used either modally or not. If not then it }
|
|
|
|
{ needs a quick and simple way to update itself. }
|
|
|
|
{ }
|
|
|
|
{ The display is treated as 2 parts: }
|
|
|
|
{ 1. display of *1st column heading and sub-headings * }
|
|
|
|
{ 2. display of values }
|
|
|
|
{ }
|
|
|
|
{ If the type of object does not change then the values *only* need to be updated, otherwise }
|
|
|
|
{ completely different property headings need to be displayed. }
|
|
|
|
{ }
|
|
|
|
{ }
|
|
|
|
{ Credits: }
|
|
|
|
{ taken + modified from hard-coded example by Mike Lischke }
|
|
|
|
{ }
|
|
|
|
{ }
|
|
|
|
{ Date AP Details }
|
|
|
|
{ -------- -- -------------------------------------- }
|
|
|
|
{ 05-Nov-2002 TC Created (tomc@gripsystems.com) }
|
|
|
|
{**********************************************************************}
|
|
|
|
unit VTPropEdit;
|
|
|
|
|
|
|
|
{$mode delphi}
|
|
|
|
{$H+}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2008-12-07 14:22:32 +00:00
|
|
|
LCLIntf, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
|
|
|
StdCtrls, VirtualTrees, ExtCtrls, Contnrs, Buttons, LResources;
|
2007-02-22 13:09:12 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
{-----------------------------------------------------------------------------------
|
|
|
|
TVTPropEditData
|
|
|
|
|
|
|
|
class for storing headings, sub-headings + values (holding datatypes in objects slot
|
|
|
|
-----------------------------------------------------------------------------------}
|
|
|
|
TVTPropEditData=
|
|
|
|
class
|
|
|
|
FHeading : string; // heading
|
|
|
|
FCaptions: TStringList; // sub-headings
|
|
|
|
FValues : TStringList; // list of values in string form
|
|
|
|
|
|
|
|
public
|
|
|
|
{ Public declarations }
|
|
|
|
constructor Create( const s : string );
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
property Heading : string read FHeading write FHeading ;
|
|
|
|
property Captions : TStringList read FCaptions write FCaptions;
|
|
|
|
property Values : TStringList read FValues write FValues;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{--------------------------------------------------------------------------
|
|
|
|
TfrmPropEdit
|
|
|
|
--------------------------------------------------------------------------}
|
|
|
|
TfrmVTPropEdit =
|
|
|
|
class(TForm)
|
|
|
|
Panel1: TPanel;
|
|
|
|
VT: TVirtualStringTree;
|
|
|
|
cmb: TComboBox;
|
|
|
|
TreeImages: TImageList;
|
|
|
|
panBase: TPanel;
|
|
|
|
chkTriangleButtons: TCheckBox;
|
|
|
|
btnDynamicallyUpdate: TButton;
|
|
|
|
|
|
|
|
procedure FormCreate(Sender: TObject);
|
|
|
|
procedure FormActivate(Sender: TObject);
|
|
|
|
|
|
|
|
procedure VTChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
|
|
|
procedure VTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
|
|
|
|
procedure VTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
|
|
|
|
procedure VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
|
2009-12-31 14:06:29 +00:00
|
|
|
var Text: String);
|
2007-02-22 13:09:12 +00:00
|
|
|
procedure VTInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal);
|
|
|
|
procedure VTInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
|
|
|
|
var InitialStates: TVirtualNodeInitStates);
|
|
|
|
procedure VTPaintText(Sender: TBaseVirtualTree; const Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
|
|
|
|
TextType: TVSTTextType);
|
|
|
|
procedure VTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
|
|
|
|
procedure chkTriangleButtonsClick(Sender: TObject);
|
|
|
|
procedure ShowExample(Sender: TObject);
|
|
|
|
procedure cmbChange(Sender: TObject);
|
|
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
|
|
|
|
|
|
private
|
|
|
|
{ Private declarations }
|
|
|
|
FDataList : TObjectList;
|
|
|
|
FExample : integer;
|
|
|
|
|
|
|
|
|
|
|
|
public
|
|
|
|
{ Public declarations }
|
|
|
|
constructor Create( AOwner : TComponent ); override;
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
procedure ConfigureVT( slCaptions, slVals : TStringlist );
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
{.$R *.DFM}
|
|
|
|
|
|
|
|
uses
|
|
|
|
VTEditors;
|
|
|
|
|
|
|
|
{--------------------------------------------------------------------------
|
|
|
|
TVTPropEditData
|
|
|
|
--------------------------------------------------------------------------}
|
|
|
|
constructor TVTPropEditData.Create( const s : string );
|
|
|
|
begin
|
|
|
|
inherited Create;
|
|
|
|
FCaptions:= TStringList.Create;
|
|
|
|
FValues := TStringList.Create;
|
|
|
|
|
|
|
|
FCaptions.CommaText := s; // string to list
|
|
|
|
FHeading := FCaptions[0]; // 1st element is caption
|
|
|
|
FCaptions.Delete(0); // can now delete it
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TVTPropEditData.Destroy;
|
|
|
|
begin
|
|
|
|
FValues .Free;
|
|
|
|
FCaptions.Free;
|
|
|
|
inherited Destroy;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{--------------------------------------------------------------------------
|
|
|
|
TfrmPropEdit
|
|
|
|
--------------------------------------------------------------------------}
|
|
|
|
constructor TfrmVTPropEdit.Create( AOwner : TComponent );
|
|
|
|
begin
|
|
|
|
inherited Create(AOwner);
|
|
|
|
FDataList:= TObjectList.Create;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TfrmVTPropEdit.Destroy;
|
|
|
|
begin
|
|
|
|
FDataList.Free;
|
|
|
|
inherited Destroy;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.ConfigureVT( slCaptions, slVals : TStringlist );
|
|
|
|
var
|
|
|
|
i, j : integer;
|
|
|
|
iCnt : integer;
|
|
|
|
ped : TVTPropEditData;
|
|
|
|
begin
|
|
|
|
with VT do
|
|
|
|
begin
|
|
|
|
BeginUpdate;
|
|
|
|
try
|
|
|
|
Clear;
|
|
|
|
FDataList.Clear;
|
|
|
|
|
|
|
|
iCnt := 0;
|
|
|
|
for i := 0 to slCaptions.count-1 do
|
|
|
|
begin
|
|
|
|
// create dataobject, loading captions and parallel values
|
|
|
|
ped := TVTPropEditData.Create( slCaptions[i] );
|
|
|
|
|
|
|
|
// slVals is a linear list of *all* values for this page,
|
|
|
|
// so now need to get those vals associated with the captions
|
|
|
|
for j := iCnt to iCnt + ped.Captions.Count-1 do
|
|
|
|
ped.Values.AddObject( slVals[j], slVals.Objects[j] ); //object slot = datatype
|
|
|
|
|
|
|
|
// add to datalist
|
|
|
|
FDataList.Add( ped );
|
|
|
|
Inc( iCnt, ped.Captions.Count );
|
|
|
|
end;
|
|
|
|
RootNodeCount := FDataList.Count; // important call
|
|
|
|
|
|
|
|
finally
|
|
|
|
EndUpdate;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.FormCreate(Sender: TObject);
|
|
|
|
begin
|
|
|
|
// The VCL (D6 and lower) still uses 16 color image lists.
|
|
|
|
// We create a high color version explicitely because it looks so much nicer.
|
|
|
|
ConvertToHighColor(TreeImages);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.FormActivate(Sender: TObject);
|
|
|
|
begin
|
|
|
|
{for this example}
|
|
|
|
ShowExample(Sender);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.FormClose(Sender: TObject; var Action: TCloseAction);
|
|
|
|
begin
|
|
|
|
Action := caFree;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
|
|
|
|
begin
|
|
|
|
NodeDataSize := SizeOf(TPropertyData);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
|
|
|
|
var InitialStates: TVirtualNodeInitStates);
|
|
|
|
var
|
|
|
|
Data: PPropertyData;
|
|
|
|
ped : TVTPropEditData;
|
|
|
|
begin
|
|
|
|
Data := Sender.GetNodeData(Node);
|
|
|
|
if ParentNode = nil then
|
|
|
|
begin
|
|
|
|
InitialStates := InitialStates + [ivsHasChildren];
|
|
|
|
if FExample = 0 then
|
|
|
|
InitialStates := InitialStates + [ivsExpanded];
|
|
|
|
|
|
|
|
ped := TVTPropEditData( FDataList[Node.Index] );
|
|
|
|
if ped.Captions.count>0 then
|
|
|
|
Data.ValueType := vtNone;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
ped := TVTPropEditData( FDataList[Node.Parent.Index] );
|
|
|
|
Data.ValueType := TValueType( PtrInt(ped.Values.Objects[Node.Index]) );
|
|
|
|
Data.Value := ped.Values[Node.Index];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode; var ChildCount: Cardinal);
|
|
|
|
begin
|
|
|
|
ChildCount := TVTPropEditData( FDataList[Node.Index] ).Captions.Count;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
|
2009-12-31 14:06:29 +00:00
|
|
|
TextType: TVSTTextType; var Text: String);
|
2007-02-22 13:09:12 +00:00
|
|
|
var
|
|
|
|
Data: PPropertyData;
|
|
|
|
ped : TVTPropEditData;
|
|
|
|
begin
|
|
|
|
Text := '';
|
|
|
|
if TextType = ttNormal then
|
|
|
|
begin
|
|
|
|
case Column of
|
|
|
|
0: begin
|
|
|
|
if Sender.GetNodeLevel( Node ) = 0 then
|
|
|
|
Text := TVTPropEditData( FDataList[Node.Index] ).Heading
|
|
|
|
else {find text}
|
|
|
|
begin
|
|
|
|
ped := TVTPropEditData( FDataList[Node.Parent.Index] );
|
|
|
|
Text := ped.Captions[Node.Index];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
1: begin
|
|
|
|
if Sender.GetNodeLevel( Node ) > 0 then
|
|
|
|
begin
|
|
|
|
//Data := Sender.GetNodeData(Node);
|
|
|
|
ped := TVTPropEditData( FDataList[Node.Parent.Index] );
|
|
|
|
Text := ped.Values[Node.Index];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTEditing(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
|
|
|
|
var
|
|
|
|
Data: PPropertyData;
|
|
|
|
begin
|
|
|
|
with Sender do
|
|
|
|
begin
|
|
|
|
Data := GetNodeData(Node);
|
|
|
|
Allowed := (Node.Parent <> RootNode) and (Column = 1) and (Data.ValueType <> vtNone);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
|
|
|
begin
|
|
|
|
// Start immediate editing as soon as another node gets focused.
|
|
|
|
with Sender do
|
|
|
|
begin
|
|
|
|
if Assigned(Node) and (Node.Parent <> RootNode) and not (tsIncrementalSearching in TreeStates) then
|
|
|
|
begin
|
|
|
|
// Note: the test whether a node can really be edited is done in the OnEditing event.
|
|
|
|
EditNode(Node, 1);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTCreateEditor(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex;
|
|
|
|
out EditLink: IVTEditLink);
|
|
|
|
// This is the callback of the tree control to ask for an application defined edit link. Providing one here allows
|
|
|
|
// us to control the editing process up to which actual control will be created.
|
|
|
|
// TPropertyEditLink implements an interface and hence benefits from reference counting. We don't need to keep a
|
|
|
|
// reference to free it. As soon as the tree finished editing the class will be destroyed automatically.
|
|
|
|
begin
|
|
|
|
EditLink := TPropertyEditLink.Create;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.VTPaintText(Sender: TBaseVirtualTree; const Canvas: TCanvas; Node: PVirtualNode;
|
|
|
|
Column: TColumnIndex; TextType: TVSTTextType);
|
|
|
|
var
|
|
|
|
Data: PPropertyData;
|
|
|
|
begin
|
|
|
|
if Node.Parent = Sender.RootNode then
|
|
|
|
Canvas.Font.Style := [fsBold]
|
|
|
|
else if Column = 0 then
|
|
|
|
Canvas.Font.Color := clBlue
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Data := Sender.GetNodeData(Node);
|
|
|
|
if Data.Changed then
|
|
|
|
Canvas.Font.Color := clRed
|
|
|
|
else
|
|
|
|
Canvas.Font.Style := [];
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.chkTriangleButtonsClick(Sender: TObject);
|
|
|
|
begin
|
|
|
|
with VT do
|
|
|
|
begin
|
|
|
|
if chkTriangleButtons.checked then
|
|
|
|
ButtonStyle := bsTriangle
|
|
|
|
else
|
|
|
|
ButtonStyle := bsRectangle;
|
|
|
|
|
|
|
|
Refresh;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.cmbChange(Sender: TObject);
|
|
|
|
begin
|
|
|
|
ShowExample(Sender);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TfrmVTPropEdit.ShowExample(Sender: TObject);
|
|
|
|
var
|
|
|
|
slText : TStringlist;
|
|
|
|
slVals : TStringlist;
|
|
|
|
i : integer;
|
|
|
|
begin
|
|
|
|
if FExample = 0 then
|
|
|
|
FExample := 1
|
|
|
|
else
|
|
|
|
FExample := 0;
|
|
|
|
|
|
|
|
slText := TStringlist.Create;
|
|
|
|
slVals := TStringlist.Create;
|
|
|
|
try
|
|
|
|
case FExample of
|
|
|
|
0: begin
|
|
|
|
{each string has the heading first + sub-captions following}
|
|
|
|
slText.Add( 'Position,Left,Top,Width,Height' );
|
|
|
|
slText.Add( 'Action,ChangeDelay,EditDelay,Enabled,Visible' );
|
|
|
|
slText.Add( 'Events,OnDblClick,OnGetText,OnInitNode' );
|
|
|
|
|
|
|
|
{the values would be supplied seperately - in a list, string format}
|
|
|
|
slVals.CommaText := '1,2,3,4,11,22,33,True,01/01/2002,a,b';
|
|
|
|
for i := 0 to slVals.Count-1 do slVals.Objects[i] := Pointer(vtString);
|
|
|
|
slVals.Objects[8] := Pointer(vtdate);
|
|
|
|
end;
|
|
|
|
|
|
|
|
1: begin
|
|
|
|
{second example for dynamic change illustration}
|
|
|
|
slText.Add( 'Test,OnTest1,OnTest2,OnTest3' );
|
|
|
|
slText.Add( 'Action,ChangeDelay,EditDelay,Enabled,Visible' );
|
|
|
|
slText.Add( 'Position,Left,Top,Width,Height' );
|
|
|
|
slText.Add( 'Events,OnDblClick,OnGetText,OnInitNode' );
|
|
|
|
|
|
|
|
slVals.CommaText := 't1,t2,t3,1,2,3,4,11,22,33,True,False,a,b';
|
|
|
|
for i := 0 to slVals.Count-1 do slVals.Objects[i] := Pointer(vtString);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
{reconfigure + update UI}
|
|
|
|
ConfigureVT( slText, slVals );
|
|
|
|
|
|
|
|
finally
|
|
|
|
slText.Free;
|
|
|
|
slVals.Free;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
initialization
|
|
|
|
{$I VTPropEdit.lrs}
|
|
|
|
|
|
|
|
|
|
|
|
end.
|
|
|
|
|
|
|
|
|