mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 01:43:48 +02:00
646 lines
17 KiB
ObjectPascal
646 lines
17 KiB
ObjectPascal
{ Copyright (C) 2005
|
|
|
|
*****************************************************************************
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
|
|
Author: Lagunov Aleksey
|
|
|
|
Abstract:
|
|
Property Editor for TTreeView.
|
|
}
|
|
|
|
unit TreeViewPropEdit;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils,
|
|
// LCL
|
|
LCLType, Forms, Dialogs, Buttons, Controls, StdCtrls, ComCtrls, ImgList, Spin,
|
|
ButtonPanel, ExtCtrls,
|
|
// IdeIntf
|
|
PropEdits, ComponentEditors, ObjInspStrConsts, IDEImagesIntf, IDEWindowIntf;
|
|
|
|
type
|
|
|
|
{ TTreeViewItemsEditorForm }
|
|
|
|
TTreeViewItemsEditorForm = class(TForm)
|
|
btnApply: TBitBtn;
|
|
ButtonPanel: TButtonPanel;
|
|
lblImageIndex: TLabel;
|
|
lblSelectedIndex: TLabel;
|
|
lblStateIndex: TLabel;
|
|
dlgOpen: TOpenDialog;
|
|
dlgSave: TSaveDialog;
|
|
pnlStateIndex: TPanel;
|
|
pnlSelectedIndex: TPanel;
|
|
pnlImageIndex: TPanel;
|
|
pnlImageIndexes: TPanel;
|
|
spnImageIndex: TSpinEdit;
|
|
spnSelectedIndex: TSpinEdit;
|
|
spnStateIndex: TSpinEdit;
|
|
ToolBar: TToolBar;
|
|
tbNewItem: TToolButton;
|
|
tbNewSubItem: TToolButton;
|
|
tb1: TToolButton;
|
|
tbDelete: TToolButton;
|
|
tb2: TToolButton;
|
|
tbRename: TToolButton;
|
|
tb3: TToolButton;
|
|
tbMoveDown: TToolButton;
|
|
tbMoveUp: TToolButton;
|
|
tb4: TToolButton;
|
|
tbSave: TToolButton;
|
|
tbOpen: TToolButton;
|
|
treEditor: TTreeView;
|
|
procedure btnApplyClick(Sender: TObject);
|
|
procedure FormActivate(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
|
|
procedure spnIndexChange(Sender: TObject);
|
|
procedure tbDeleteClick(Sender: TObject);
|
|
procedure tbMoveClick(Sender: TObject);
|
|
procedure tbNewItemClick(Sender: TObject);
|
|
procedure tbOpenClick(Sender: TObject);
|
|
procedure tbRenameClick(Sender: TObject);
|
|
procedure tbSaveClick(Sender: TObject);
|
|
procedure treEditorSelectionChanged(Sender: TObject);
|
|
private
|
|
fModified: Boolean;
|
|
fTreeView: TCustomTreeView;
|
|
procedure FinishNodeEditing;
|
|
procedure LoadFromTree(aTreeView: TCustomTreeView);
|
|
procedure SaveToSourceTree;
|
|
procedure UpdateEnabledStates;
|
|
procedure UpdateImageHints;
|
|
public
|
|
property Modified: Boolean read fModified write fModified;
|
|
end;
|
|
|
|
{ TTreeViewItemsProperty }
|
|
|
|
TTreeViewItemsProperty = class(TClassPropertyEditor)
|
|
public
|
|
procedure Edit; override;
|
|
function GetAttributes: TPropertyAttributes; override;
|
|
end;
|
|
|
|
{ TTreeViewComponentEditor }
|
|
|
|
TTreeViewComponentEditor = class(TComponentEditor)
|
|
public
|
|
procedure ExecuteVerb(Index: Integer); override;
|
|
function GetVerb(Index: Integer): string; override;
|
|
function GetVerbCount: Integer; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
// The function returns true if the tree has been changed
|
|
function EditTreeView(ATreeView: TCustomTreeView): boolean;
|
|
begin
|
|
with TTreeViewItemsEditorForm.Create(Application) do
|
|
try
|
|
LoadFromTree(ATreeView);
|
|
if ShowModal = mrOK then
|
|
SaveToSourceTree;
|
|
Result := Modified;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
{ TTreeViewItemsEditorForm }
|
|
|
|
procedure TTreeViewItemsEditorForm.FormActivate(Sender: TObject);
|
|
begin
|
|
Constraints.MinWidth := pnlStateIndex.Left + pnlStateIndex.Width + pnlImageIndex.Left;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.FormCreate(Sender: TObject);
|
|
begin
|
|
fModified := false;
|
|
|
|
{ Captions }
|
|
|
|
// form
|
|
self .Caption := sccsTrEdtCaption;
|
|
btnApply.Caption := sccsTrEdtApply;
|
|
|
|
// toolbar
|
|
ToolBar.ShowHint := true;
|
|
tbNewItem .Hint := sccsTrEdtNewItem + ' [Ctrl+N]';
|
|
tbNewSubItem.Hint := sccsTrEdtNewSubItem + ' [Ctrl+Shift+N]';
|
|
tbDelete .Hint := sccsTrEdtDelete + ' [Del]';
|
|
tbRename .Hint := sccsTrEdtRename + ' [F2]';
|
|
tbMoveDown .Hint := rscdMoveDown + ' [Ctrl+Shift+Down]';
|
|
tbMoveUp .Hint := rscdMoveUp + ' [Ctrl+Shift+Up]';
|
|
tbSave .Hint := sccsTrEdtSave + ' [Ctrl+S]';
|
|
tbOpen .Hint := sccsTrEdtOpen + ' [Ctrl+O]';
|
|
|
|
// image indexes
|
|
lblImageIndex .Caption := Format(sccsTrEdtLabelImageIndex, ['']);
|
|
lblSelectedIndex.Caption := Format(sccsTrEdtLabelSelIndex , ['']);
|
|
lblStateIndex .Caption := Format(sccsTrEdtLabelStateIndex, ['']);
|
|
|
|
// dialogs
|
|
dlgOpen.Title := sccsTrEdtOpenDialog;
|
|
dlgSave.Title := sccsTrEdtSaveDialog;
|
|
|
|
// button panel
|
|
ButtonPanel.ShowHint := true;
|
|
btnApply.TabOrder := 1;
|
|
|
|
{ Images }
|
|
|
|
// form
|
|
btnApply.LoadGlyphFromResource(idButtonRetry);
|
|
|
|
// toolbar
|
|
ToolBar.Images := IDEImages.Images_16;
|
|
tbNewItem .ImageIndex := IDEImages.LoadImage('new_item');
|
|
tbNewSubItem.ImageIndex := IDEImages.LoadImage('new_subitem');
|
|
tbDelete .ImageIndex := IDEImages.LoadImage('item_delete');
|
|
tbRename .ImageIndex := IDEImages.LoadImage('item_rename');
|
|
tbMoveDown .ImageIndex := IDEImages.LoadImage('item_down');
|
|
tbMoveUp .ImageIndex := IDEImages.LoadImage('item_up');
|
|
tbSave .ImageIndex := IDEImages.LoadImage('items_save');
|
|
tbOpen .ImageIndex := IDEImages.LoadImage('items_load');
|
|
|
|
{ Layout }
|
|
|
|
IDEDialogLayoutList.ApplyLayout(self);
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.FormClose(Sender: TObject;
|
|
var CloseAction: TCloseAction);
|
|
begin
|
|
IDEDialogLayoutList.SaveLayout(self);
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.FormKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
var
|
|
lWasEdited: Boolean;
|
|
begin
|
|
// form actions
|
|
if (Key = VK_RETURN) and (Shift = [ssCtrl]) then
|
|
begin
|
|
ModalResult := mrOK;
|
|
Key := 0;
|
|
end
|
|
else if (Key = VK_RETURN) and (Shift = [ssShift]) then
|
|
begin
|
|
btnApplyClick(Sender);
|
|
Key := 0;
|
|
end
|
|
else if (Key = VK_ESCAPE) and (Shift = []) then
|
|
begin
|
|
// pressing [Esc] in an open in-place editor cancel text editing
|
|
if not treEditor.IsEditing then
|
|
begin
|
|
ModalResult := mrCancel;
|
|
Key := 0;
|
|
end;
|
|
end
|
|
|
|
// create item
|
|
else if (Key = VK_N) and (Shift = [ssCtrl]) then
|
|
begin
|
|
tbNewItemClick(tbNewItem); // "Sender" is the pressed button
|
|
Key := 0;
|
|
end
|
|
else if (Key = VK_N) and (Shift = [ssCtrl, ssShift]) then
|
|
begin
|
|
tbNewItemClick(tbNewSubItem); // "Sender" is the pressed button
|
|
Key := 0;
|
|
end
|
|
|
|
// delete item
|
|
else if (Key = VK_DELETE) and (Shift = []) then
|
|
begin
|
|
// check to prevent it from working in TEdit or TSpinEdit
|
|
// or when renaming node
|
|
if treEditor.Focused and not treEditor.IsEditing then
|
|
begin
|
|
tbDeleteClick(Sender);
|
|
Key := 0;
|
|
end;
|
|
end
|
|
|
|
// rename item
|
|
// the location in the FormKeyDown makes it independent of the current focus
|
|
else if (Key = VK_F2) and (Shift = []) then
|
|
begin
|
|
if not treEditor.IsEditing then
|
|
if Assigned(treEditor.Selected) then
|
|
treEditor.Selected.EditText;
|
|
Key := 0;
|
|
end
|
|
|
|
// move item
|
|
else if (Key = VK_DOWN) and (Shift = [ssCtrl, ssShift]) then
|
|
begin
|
|
tbMoveClick(tbMoveDown); // "Sender" is the pressed button
|
|
Key := 0;
|
|
end
|
|
else if (Key = VK_UP) and (Shift = [ssCtrl, ssShift]) then
|
|
begin
|
|
tbMoveClick(tbMoveUp); // "Sender" is the pressed button
|
|
Key := 0;
|
|
end
|
|
|
|
// move selection
|
|
else if (Key in [VK_DOWN, VK_UP]) and (Shift = []) then
|
|
begin
|
|
if treEditor.IsEditing then
|
|
begin
|
|
// close text editor
|
|
// select next
|
|
if Key = VK_DOWN then
|
|
treEditor.MoveToNextNode(true)
|
|
else
|
|
treEditor.MoveToPrevNode(true);
|
|
// open text editor
|
|
if Assigned(treEditor.Selected) then
|
|
treEditor.Selected.EditText;
|
|
|
|
Key := 0;
|
|
end;
|
|
end
|
|
|
|
// save and load in/from file
|
|
else if (Key = VK_S) and (Shift = [ssCtrl]) then
|
|
begin
|
|
tbSaveClick(Sender);
|
|
Key := 0;
|
|
end
|
|
else if (Key in [VK_O]) and (Shift = [ssCtrl]) then
|
|
begin
|
|
tbOpenClick(Sender);
|
|
Key := 0;
|
|
end;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.tbRenameClick(Sender: TObject);
|
|
begin
|
|
if Assigned(treEditor.Selected) then
|
|
treEditor.Selected.EditText;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.tbNewItemClick(Sender: TObject);
|
|
var
|
|
lNewName: String;
|
|
begin
|
|
FinishNodeEditing;
|
|
|
|
lNewName := sccsTrEdtItem + IntToStr(treEditor.Items.Count);
|
|
if Sender = tbNewItem then
|
|
treEditor.Selected := treEditor.Items.Add(treEditor.Selected, lNewName)
|
|
else if Sender = tbNewSubItem then
|
|
treEditor.Selected := treEditor.Items.AddChild(treEditor.Selected, lNewName)
|
|
else
|
|
raise Exception.Create('[tbNewItemClick] Unknown Sender');
|
|
|
|
if Assigned(treEditor.Selected) then
|
|
begin
|
|
treEditor.SetFocus;
|
|
treEditor.Selected.EditText;
|
|
end;
|
|
|
|
UpdateEnabledStates;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.tbMoveClick(Sender: TObject);
|
|
var
|
|
lCurNode: TTreeNode;
|
|
begin
|
|
lCurNode := treEditor.Selected;
|
|
if lCurNode = nil then exit;
|
|
|
|
FinishNodeEditing;
|
|
|
|
if Sender = tbMoveUp then
|
|
begin
|
|
if lCurNode.GetPrevSibling = nil then exit;
|
|
lCurNode.MoveTo(lCurNode.GetPrevSibling, naInsert);
|
|
end
|
|
else if Sender = tbMoveDown then
|
|
begin
|
|
if lCurNode.GetNextSibling = nil then exit;
|
|
lCurNode.MoveTo(lCurNode.GetNextSibling, naInsertBehind);
|
|
end else
|
|
raise Exception.Create('[tbMoveClick] Unknown Sender');
|
|
|
|
treEditor.SetFocus;
|
|
|
|
UpdateEnabledStates;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.treEditorSelectionChanged(Sender: TObject);
|
|
//
|
|
procedure UpdateImageIndexes;
|
|
begin
|
|
// Remove events to avoid cyclic calling
|
|
spnImageIndex .OnChange := nil;
|
|
spnSelectedIndex.OnChange := nil;
|
|
spnStateIndex .OnChange := nil;
|
|
try
|
|
// Read the indexes of the selected item
|
|
spnImageIndex .Value := treEditor.Selected.ImageIndex;
|
|
spnSelectedIndex.Value := treEditor.Selected.SelectedIndex;
|
|
spnStateIndex .Value := treEditor.Selected.StateIndex;
|
|
finally
|
|
// Restore events
|
|
spnImageIndex .OnChange := @spnIndexChange;
|
|
spnSelectedIndex.OnChange := @spnIndexChange;
|
|
spnStateIndex .OnChange := @spnIndexChange;
|
|
end;
|
|
end;
|
|
//
|
|
begin
|
|
if Assigned(treEditor.Selected) then
|
|
begin
|
|
UpdateImageIndexes;
|
|
UpdateImageHints;
|
|
end;
|
|
|
|
UpdateEnabledStates;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.btnApplyClick(Sender: TObject);
|
|
begin
|
|
FinishNodeEditing;
|
|
SaveToSourceTree;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.tbDeleteClick(Sender: TObject);
|
|
var
|
|
lNextNode: TTreeNode;
|
|
begin
|
|
if Assigned(treEditor.Selected) then
|
|
begin
|
|
// find node for new selection
|
|
lNextNode := treEditor.Selected.GetNextSibling;
|
|
if lNextNode = nil then
|
|
lNextNode := treEditor.Selected.GetPrevSibling;
|
|
if lNextNode = nil then
|
|
lNextNode := treEditor.Selected.Parent;
|
|
|
|
// delete
|
|
treEditor.Items.Delete(treEditor.Selected);
|
|
|
|
// select "next" node
|
|
if lNextNode <> nil then
|
|
treEditor.Selected := lNextNode;
|
|
|
|
UpdateEnabledStates;
|
|
end;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.tbOpenClick(Sender: TObject);
|
|
|
|
function ConfirmTreeReplace: boolean;
|
|
begin
|
|
if treEditor.Items.Count > 0 then
|
|
result := QuestionDlg(sccsTrEdtConfirmationCaption, sccsTrEdtConfirmationTreeReplace,
|
|
TMsgDlgType.mtConfirmation, [mrYes, sccsTrEdtYes, mrNo, sccsTrEdtNo,
|
|
mrCancel, sccsTrEdtCancel], 0) = mrYes
|
|
else
|
|
result := true;
|
|
end;
|
|
|
|
begin
|
|
FinishNodeEditing;
|
|
|
|
if ConfirmTreeReplace and dlgOpen.Execute then
|
|
begin
|
|
treEditor.LoadFromFile(dlgOpen.FileName);
|
|
|
|
treEditor.FullExpand;
|
|
treEditor.Selected := treEditor.Items.GetFirstNode;
|
|
treEditor.SetFocus;
|
|
UpdateEnabledStates;
|
|
end;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.tbSaveClick(Sender: TObject);
|
|
|
|
function ImagesFound: boolean;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to treEditor.Items.Count - 1 do
|
|
if (treEditor.Items[i].ImageIndex >= 0) or
|
|
(treEditor.Items[i].SelectedIndex >= 0) or
|
|
(treEditor.Items[i].StateIndex >= 0)
|
|
then
|
|
exit(true);
|
|
result := false;
|
|
end;
|
|
|
|
function ConfirmImagesLoss: boolean;
|
|
begin
|
|
if ImagesFound then
|
|
result := QuestionDlg(sccsTrEdtConfirmationCaption, sccsTrEdtConfirmationImagesLoss,
|
|
TMsgDlgType.mtConfirmation, [mrYes, sccsTrEdtYes, mrNo, sccsTrEdtNo,
|
|
mrCancel, sccsTrEdtCancel], 0) = mrYes
|
|
else
|
|
result := true;
|
|
end;
|
|
|
|
function ConfirmFileReplace: boolean;
|
|
begin
|
|
if FileExists(dlgSave.FileName) then
|
|
result := QuestionDlg(sccsTrEdtConfirmationCaption, sccsTrEdtConfirmationFileReplace,
|
|
TMsgDlgType.mtConfirmation, [mrYes, sccsTrEdtYes, mrNo, sccsTrEdtNo,
|
|
mrCancel, sccsTrEdtCancel], 0) = mrYes
|
|
else
|
|
result := true;
|
|
end;
|
|
|
|
begin
|
|
FinishNodeEditing;
|
|
|
|
if ConfirmImagesLoss and dlgSave.Execute and ConfirmFileReplace then
|
|
treEditor.SaveToFile(dlgSave.FileName);
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.spnIndexChange(Sender: TObject);
|
|
begin
|
|
if Assigned(treEditor.Selected) then
|
|
begin
|
|
treEditor.Selected.ImageIndex := spnImageIndex.Value;
|
|
treEditor.Selected.StateIndex := spnStateIndex.Value;
|
|
if Sender = spnImageIndex then
|
|
spnSelectedIndex.Value := spnImageIndex.Value
|
|
else
|
|
treEditor.Selected.SelectedIndex := spnSelectedIndex.Value;
|
|
UpdateImageHints;
|
|
end;
|
|
end;
|
|
|
|
// Show hints and "*" in label for invalid index
|
|
procedure TTreeViewItemsEditorForm.UpdateImageHints;
|
|
//
|
|
procedure UpdateImageHint(aSpinEdit: TSpinEdit;
|
|
aIsStateImages: boolean; aLabel: TLabel; aCaption: string);
|
|
const
|
|
MAYBE_ASTERISK: array[boolean] of String[1] = ('', '*');
|
|
var
|
|
lImageList: TCustomImageList;
|
|
lPropName: string;
|
|
begin
|
|
if aIsStateImages then
|
|
begin
|
|
lImageList := treEditor.StateImages;
|
|
lPropName := fTreeView.Name + '.StateImages';
|
|
end else begin
|
|
lImageList := treEditor.Images;
|
|
lPropName := fTreeView.Name + '.Images';
|
|
end;
|
|
|
|
// check valid index
|
|
if aSpinEdit.Value >= 0 then
|
|
begin
|
|
// check assign
|
|
if lImageList = nil then
|
|
begin
|
|
aLabel.Hint := Format(sccsTrEdtImageListNotAssigned, [lPropName]);
|
|
aLabel.ShowHint := true;
|
|
end else begin
|
|
// check count
|
|
if aSpinEdit.Value >= lImageList.Count then
|
|
begin
|
|
aLabel.Hint := Format(sccsTrEdtInvalidIndex, [lPropName, lImageList.Count]);
|
|
aLabel.ShowHint := true;
|
|
end else
|
|
aLabel.ShowHint := false;
|
|
end;
|
|
end else
|
|
aLabel.ShowHint := false;
|
|
|
|
// show asterisk if necessary
|
|
aLabel.Caption := Format(aCaption, [MAYBE_ASTERISK[aLabel.ShowHint]]);
|
|
end;
|
|
//
|
|
begin
|
|
if Assigned(treEditor.Selected) then
|
|
begin
|
|
UpdateImageHint(spnImageIndex, false, lblImageIndex, sccsTrEdtLabelImageIndex);
|
|
UpdateImageHint(spnSelectedIndex, false, lblSelectedIndex, sccsTrEdtLabelSelIndex);
|
|
UpdateImageHint(spnStateIndex, true, lblStateIndex, sccsTrEdtLabelStateIndex);
|
|
end;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.FinishNodeEditing;
|
|
begin
|
|
if treEditor.IsEditing then
|
|
if treEditor.Items.Count > 0 then
|
|
treEditor.Items[0].EndEdit(false);
|
|
// Quick-and-dirty way to end editing and accepting the edited text
|
|
// no matter if the edited node was selected or not.
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.LoadFromTree(aTreeView: TCustomTreeView);
|
|
begin
|
|
fTreeView := aTreeView;
|
|
if Assigned(aTreeView) then
|
|
begin
|
|
// images
|
|
treEditor.Images := aTreeView.Images;
|
|
treEditor.StateImages := aTreeView.StateImages;
|
|
// items
|
|
treEditor.Items.Assign(aTreeView.Items);
|
|
end;
|
|
treEditor.Selected := treEditor.Items.GetFirstNode;
|
|
UpdateEnabledStates;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.SaveToSourceTree;
|
|
begin
|
|
if Assigned(fTreeView) then
|
|
fTreeView.Items.Assign(treEditor.Items);
|
|
fModified := true;
|
|
end;
|
|
|
|
procedure TTreeViewItemsEditorForm.UpdateEnabledStates;
|
|
var
|
|
lCurNode: TTreeNode;
|
|
lAssigned: Boolean;
|
|
begin
|
|
lCurNode := treEditor.Selected;
|
|
lAssigned := Assigned(lCurNode);
|
|
|
|
// control states
|
|
pnlImageIndexes .Enabled := lAssigned;
|
|
tbDelete .Enabled := lAssigned;
|
|
tbRename .Enabled := lAssigned;
|
|
tbMoveUp .Enabled := lAssigned and Assigned(lCurNode.GetPrevSibling);
|
|
tbMoveDown .Enabled := lAssigned and Assigned(lCurNode.GetNextSibling);
|
|
tbSave .Enabled := treEditor.Items.Count > 0;
|
|
|
|
// clear disabled fields
|
|
if lCurNode = nil then
|
|
begin
|
|
spnImageIndex .Value := -1;
|
|
spnSelectedIndex.Value := -1;
|
|
spnStateIndex .Value := -1;
|
|
end;
|
|
end;
|
|
|
|
{ TTreeViewItemsProperty }
|
|
|
|
procedure TTreeViewItemsProperty.Edit;
|
|
begin
|
|
if EditTreeView(GetComponent(0) as TCustomTreeView) then
|
|
Modified;
|
|
end;
|
|
|
|
function TTreeViewItemsProperty.GetAttributes: TPropertyAttributes;
|
|
begin
|
|
result := [paDialog, paReadOnly, paRevertable];
|
|
end;
|
|
|
|
{ TTreeViewComponentEditor }
|
|
|
|
procedure TTreeViewComponentEditor.ExecuteVerb(Index: Integer);
|
|
var
|
|
Hook: TPropertyEditorHook;
|
|
begin
|
|
if Index = 0 then
|
|
begin
|
|
GetHook(Hook);
|
|
if EditTreeView(GetComponent as TCustomTreeView) then
|
|
if Assigned(Hook) then
|
|
Hook.Modified(self);
|
|
end;
|
|
end;
|
|
|
|
function TTreeViewComponentEditor.GetVerb(Index: Integer): string;
|
|
begin
|
|
if Index = 0 then
|
|
result := sccsTrEdt
|
|
else
|
|
result := '';
|
|
end;
|
|
|
|
function TTreeViewComponentEditor.GetVerbCount: Integer;
|
|
begin
|
|
result := 1;
|
|
end;
|
|
|
|
initialization
|
|
RegisterPropertyEditor(ClassTypeInfo(TTreeNodes), TTreeView, 'Items', TTreeViewItemsProperty);
|
|
RegisterComponentEditor(TTreeView, TTreeViewComponentEditor);
|
|
end.
|
|
|