Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create base class for EditLink #1064

Merged
merged 6 commits into from
Sep 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 52 additions & 122 deletions Demos/Advanced/Editors.pas
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, VirtualTrees, ExtDlgs, ImgList, Buttons, ExtCtrls, ComCtrls,
Mask;
StdCtrls, ExtDlgs, ImgList, Buttons, ExtCtrls, ComCtrls, Mask,
VirtualTrees, VirtualTrees.EditLink;

type
// Describes the type of value a property tree node stores in its data property.
Expand All @@ -34,25 +34,19 @@ TPropertyData = record
end;

// Our own edit link to implement several different node editors.
TPropertyEditLink = class(TInterfacedObject, IVTEditLink)
private
FEdit: TWinControl; // One of the property editor classes.
FTree: TVirtualStringTree; // A back reference to the tree calling.
FNode: PVirtualNode; // The node being edited.
FColumn: Integer; // The column of the node being edited.

// Base class for TPropertyEditLink and TGridEditLink implementing key handling
TBasePropertyEditLink = class(TWinControlEditLink)
protected
procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure SetBounds(R: TRect); override; stdcall;
end;

TPropertyEditLink = class(TBasePropertyEditLink)
public
destructor Destroy; override;

function BeginEdit: Boolean; stdcall;
function CancelEdit: Boolean; stdcall;
function EndEdit: Boolean; stdcall;
function GetBounds: TRect; stdcall;
function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
procedure ProcessMessage(var Message: TMessage); stdcall;
procedure SetBounds(R: TRect); stdcall;
procedure DoEndEdit(var Result: Boolean); override;
procedure DoPrepareEdit(var Result: Boolean); override;
end;

//----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -176,35 +170,17 @@ TGridData = class
// Our own edit link to implement several different node editors.
TGridEditLink = class(TPropertyEditLink, IVTEditLink)
public
function EndEdit: Boolean; stdcall;
function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
procedure DoEndEdit(var Result: Boolean); override;
procedure DoPrepareEdit(var Result: Boolean); override;
end;

//----------------------------------------------------------------------------------------------------------------------

implementation

uses
PropertiesDemo, GridDemo;

//----------------- TPropertyEditLink ----------------------------------------------------------------------------------

// This implementation is used in VST3 to make a connection beween the tree
// and the actual edit window which might be a simple edit, a combobox
// or a memo etc.
//----------------- TBasePropertyEditLink ----------------------------------------------------------------------------------

destructor TPropertyEditLink.Destroy;

begin
//FEdit.Free; casues issue #357. Fix:
if FEdit.HandleAllocated then
PostMessage(FEdit.Handle, CM_RELEASE, 0, 0);
inherited;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure TPropertyEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure TBasePropertyEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

var
CanAdvance: Boolean;
Expand Down Expand Up @@ -244,7 +220,9 @@ procedure TPropertyEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: T
end;
end;

procedure TPropertyEditLink.EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
//----------------------------------------------------------------------------------------------------------------------

procedure TBasePropertyEditLink.EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
case Key of
VK_ESCAPE:
Expand All @@ -257,41 +235,36 @@ procedure TPropertyEditLink.EditKeyUp(Sender: TObject; var Key: Word; Shift: TSh

//----------------------------------------------------------------------------------------------------------------------

function TPropertyEditLink.BeginEdit: Boolean;

begin
Result := True;
FEdit.Show;
FEdit.SetFocus;
end;

//----------------------------------------------------------------------------------------------------------------------
procedure TBasePropertyEditLink.SetBounds(R: TRect);

function TPropertyEditLink.CancelEdit: Boolean;
var
Dummy: Integer;

begin
Result := True;
FEdit.Hide;
// Since we don't want to activate grid extensions in the tree (this would influence how the selection is drawn)
// we have to set the edit's width explicitly to the width of the column.
FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
FEdit.BoundsRect := R;
end;

//----------------------------------------------------------------------------------------------------------------------
//----------------- TPropertyEditLink ----------------------------------------------------------------------------------

function TPropertyEditLink.EndEdit: Boolean;
procedure TPropertyEditLink.DoEndEdit(var Result: Boolean);

var
Data: PPropertyData;
Buffer: array[0..1024] of Char;
S: UnicodeString;

begin
Result := True;
inherited;

Data := FNode.GetData();
if FEdit is TComboBox then
S := TComboBox(FEdit).Text
if Edit is TComboBox then
S := TComboBox(Edit).Text
else
begin
GetWindowText(FEdit.Handle, Buffer, 1024);
GetWindowText(Edit.Handle, Buffer, 1024);
S := Buffer;
end;

Expand All @@ -301,34 +274,20 @@ function TPropertyEditLink.EndEdit: Boolean;
Data.Changed := True;
FTree.InvalidateNode(FNode);
end;
FEdit.Hide;
FTree.SetFocus;
end;

//----------------------------------------------------------------------------------------------------------------------

function TPropertyEditLink.GetBounds: TRect;

begin
Result := FEdit.BoundsRect;
end;

//----------------------------------------------------------------------------------------------------------------------

function TPropertyEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
procedure TPropertyEditLink.DoPrepareEdit(var Result: Boolean);

var
Data: PPropertyData;

begin
Result := True;
FTree := Tree as TVirtualStringTree;
FNode := Node;
FColumn := Column;
inherited;

// determine what edit type actually is needed
FEdit.Free;
FEdit := nil;
Data := Node.GetData();
case Data.ValueType of
vtString:
Expand Down Expand Up @@ -421,54 +380,31 @@ function TPropertyEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNod
end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure TPropertyEditLink.ProcessMessage(var Message: TMessage);

begin
FEdit.WindowProc(Message);
end;

//----------------------------------------------------------------------------------------------------------------------

procedure TPropertyEditLink.SetBounds(R: TRect);

var
Dummy: Integer;

begin
// Since we don't want to activate grid extensions in the tree (this would influence how the selection is drawn)
// we have to set the edit's width explicitly to the width of the column.
FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
FEdit.BoundsRect := R;
end;

//---------------- TGridEditLink ---------------------------------------------------------------------------------------

function TGridEditLink.EndEdit: Boolean;

procedure TGridEditLink.DoEndEdit(var Result: Boolean);
var
Data: TGridData;
Buffer: array[0..1024] of Char;
S: UnicodeString;
I: Integer;

begin
Result := True;
inherited;
Data := FNode.GetData<TGridData>();
if FEdit is TComboBox then
if Edit is TComboBox then
begin
S := TComboBox(FEdit).Text;
S := TComboBox(Edit).Text;
if S <> Data.Value[FColumn - 1] then
begin
Data.Value[FColumn - 1] := S;
Data.Changed := True;
end;
end
else
if FEdit is TMaskEdit then
if Edit is TMaskEdit then
begin
I := StrToInt(Trim(TMaskEdit(FEdit).EditText));
I := StrToInt(Trim(TMaskEdit(Edit).EditText));
if I <> Data.Value[FColumn - 1] then
begin
Data.Value[FColumn - 1] := I;
Expand All @@ -477,7 +413,7 @@ function TGridEditLink.EndEdit: Boolean;
end
else
begin
GetWindowText(FEdit.Handle, Buffer, 1024);
GetWindowText(Edit.Handle, Buffer, 1024);
S := Buffer;
if S <> Data.Value[FColumn - 1] then
begin
Expand All @@ -488,34 +424,28 @@ function TGridEditLink.EndEdit: Boolean;

if Data.Changed then
FTree.InvalidateNode(FNode);
FEdit.Hide;
end;

//----------------------------------------------------------------------------------------------------------------------

function TGridEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
procedure TGridEditLink.DoPrepareEdit(var Result: Boolean);

var
Data: TGridData;
begin
Result := True;
FTree := Tree as TVirtualStringTree;
FNode := Node;
FColumn := Column;
inherited;

// Determine what edit type actually is needed.
FEdit.Free;
FEdit := nil;
Data := FTree.GetNodeData<TGridData>(Node);
case Data.ValueType[FColumn - 1] of
Data := Tree.GetNodeData<TGridData>(Node);
case Data.ValueType[Column - 1] of
vtString:
begin
FEdit := TEdit.Create(nil);
with FEdit as TEdit do
begin
Visible := False;
Parent := Tree;
Text := Data.Value[FColumn - 1];
Text := Data.Value[Column - 1];
OnKeyDown := EditKeyDown;
OnKeyUp := EditKeyUp;
end;
Expand All @@ -527,10 +457,10 @@ function TGridEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; C
begin
Visible := False;
Parent := Tree;
Text := Data.Value[FColumn - 1];
Text := Data.Value[Column - 1];
// Here you would usually do a lookup somewhere to get
// values for the combobox. We only add some dummy values.
case FColumn of
case Column of
2:
begin
Items.Add('John');
Expand Down Expand Up @@ -558,7 +488,7 @@ function TGridEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; C
Visible := False;
Parent := Tree;
EditMask := '9999;0; ';
Text := Data.Value[FColumn - 1];
Text := Data.Value[Column - 1];
OnKeyDown := EditKeyDown;
OnKeyUp := EditKeyUp;
end;
Expand All @@ -570,7 +500,7 @@ function TGridEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; C
begin
Visible := False;
Parent := Tree;
Text := Data.Value[FColumn - 1];
Text := Data.Value[Column - 1];
OnKeyDown := EditKeyDown;
OnKeyUp := EditKeyUp;
end;
Expand All @@ -584,8 +514,8 @@ function TGridEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; C
begin
Visible := False;
Parent := Tree;
Text := Data.Value[FColumn - 1];
Items.Add(Data.Value[FColumn - 1]);
Text := Data.Value[Column - 1];
Items.Add(Data.Value[Column - 1]);
OnKeyDown := EditKeyDown;
OnKeyUp := EditKeyUp;
end;
Expand All @@ -602,7 +532,7 @@ function TGridEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; C
CalColors.TitleBackColor := clBtnShadow;
CalColors.TitleTextColor := clBlack;
CalColors.TrailingTextColor := clBtnFace;
Date := StrToDate(Data.Value[FColumn - 1]);
Date := StrToDate(Data.Value[Column - 1]);
OnKeyDown := EditKeyDown;
OnKeyUp := EditKeyUp;
end;
Expand Down
Loading