Creating a Component Editor and a Property Editor for FireMonkey Components
Go Up to FireMonkey Components Guide
In this tutorial, you create a Property Editor and a Component Editor for a FireMonkey component.
The parent component for these editors is TClockLabel, the component that you create in the related tutorial Creating a Styled FireMonkey Component by Extending an Existing Component. This tutorial assumes that you already have created TClockLabel as a starting point.
TClockLabel Component:
A component editor is an IDE feature that you can invoke by double-clicking a component, or by right-clicking a component and selecting Show Editor on the context menu.
Invoking a Component Editor from a Custom Component:
Sample Component Editor shown as a Dialog:
Contents
A property editor is an IDE feature that you can provide as a way to edit a property (or a set of properties) in a separate dialog invoked from the Object Inspector.
To invoke a property editor from the Object Inspector, click the ellipsis [...] in the Value column for a given property.
Invoking a Property Editor from the Object Inspector:
In this tutorial, the component editor and the property editor display the same dialog box to edit the Format property of the TClockLabel component.
Step 1: Create a Design-Time Package
To create a property editor or component editor, you need to have a design-time package to hold these property editors.
- Right-click the ClockLabelProjectGroup in the Project Manager, and select Add New Project from the context menu:
- Select File > New > Other > Delphi Projects.
- Then select Package in the New Items dialog box:
- Save this package as dclClockLabel.
- Select Project > Options > Description for dclClockLabel.
Step 2: Add a FireMonkey HD Form to Edit Properties
To edit a property of the TClockLabel component in a dialog box, now you need to add a Form that can edit the property.
- Make sure that the dclClockLabel project is active. If not, double-click dclClockLabelproject to make it the active project.
- Select File > New > Other > Delphi Files > Multi-Device Form.
- Confirm that this form is for FireMonkey by selecting Yes:
- Save the new form as ClockLabelDialog.
- In the Object Inspector, change the Name of the form to be ClockLabelDlg.
- Add and configure several FireMonkey controls, and update the look and feel of this dialog so that you have the following image:
object ClockLabelDlg: TClockLabelDlg
Left = 0
Top = 0
Caption = 'Designer for Clock Label'
ClientHeight = 136
ClientWidth = 383
Visible = False
StyleLookup = 'backgroundstyle'
object ClockLabel1: TClockLabel
Position.Point = '(104,96)'
Width = 257.000000000000000000
Height = 15.000000000000000000
TabOrder = 0
Text = '5/8/2012 1:50:42 PM'
Format = 'c'
end
object EditFormat: TEdit
Position.Point = '(16,52)'
Width = 233.000000000000000000
Height = 22.000000000000000000
TabOrder = 1
KeyboardType = Default
Password = False
end
object Label1: TLabel
Position.Point = '(16,32)'
Width = 177.000000000000000000
Height = 15.000000000000000000
TabOrder = 2
Text = 'DateTime Format for ClockLabel:'
end
object btnOK: TButton
Position.Point = '(280,24)'
Width = 80.000000000000000000
Height = 22.000000000000000000
TabOrder = 3
ModalResult = 1
Text = 'OK'
Default = True
end
object btnCancel: TButton
Position.Point = '(280,56)'
Width = 80.000000000000000000
Height = 22.000000000000000000
TabOrder = 4
ModalResult = 2
Text = 'Cancel'
Cancel = True
end
object btnPreview: TButton
Position.Point = '(16,92)'
Width = 80.000000000000000000
Height = 22.000000000000000000
TabOrder = 5
Text = 'Preview'
end
end
- 7. Select the Edit box (EditFormat), and create an OnChange event handler for it as EditFormatChange:
procedure TClockLabelDlg.EditFormatChange(Sender: TObject);
begin
ClockLabel1.Format := EditFormat.Text;
end;
- 8. To compile this package, you need to add the following packages to the Requires section:
- fmx
- ClockLabel
- designide
A component editor is a class that is inherited from TComponentEditor.
Create a new unit and a class in it as follows:
- Create a new unit and save it as ClockLabelEditors.pas.
- Add a reference to the following two units in the uses clause:
uses
DesignEditors, DesignIntf;
- 3. Create a new class as a sub-class of TComponentEditor.
type
TClockLabelComponentEditor = class(TComponentEditor)
end;
As discussed earlier, a component editor can display a context menu for the target component. When the user right-clicks the component, the GetVerbCount and GetVerb methods of the component editor are called to build the context menu.
You can override these methods to add commands (verbs) to the context menu as follows:
type
TClockLabelComponentEditor = class(TComponentEditor)
public
function GetVerbCount: Integer; override;
function GetVerb(Index: Integer): string; override;
end;
function TClockLabelComponentEditor.GetVerbCount: Integer;
begin
Result := 1;
end;
function TClockLabelComponentEditor.GetVerb(Index: Integer): string;
begin
case Index of
0: Result := '&Show Editor';
else
raise ENotImplemented.Create('TClockLabelEditor has only one verb (index = 0) supported.');
end;
end;
Implement a command
When the command provided by GetVerb is selected in the Designer, the ExecuteVerb method is called. For every command you provide in the GetVerb method, you should implement an action in the ExecuteVerb method. You can access the component that is being edited using the Component property of the editor. To open a dialog defined earlier, now you need to add reference to the ClockLabelDIalog unit.
type
TClockLabelComponentEditor = class(TComponentEditor)
private
procedure ShowDesigner;
public
procedure ExecuteVerb(Index: Integer); override;
end;
procedure TClockLabelComponentEditor.ShowDesigner;
var
DesignerForm: TClockLabelDlg;
begin
DesignerForm := TClockLabelDlg.Create(nil);
try
// Set curent value to designer form
DesignerForm.ClockLabel1.Format := (Component as TClockLabel).Format;
DesignerForm.EditFormat.Text := (Component as TClockLabel).Format;
// Show ModalForm, and then take result
if DesignerForm.ShowModal = mrOK then
(Component as TClockLabel).Format := DesignerForm.ClockLabel1.Format;
Designer.Modified;
finally
DesignerForm.Free;
end;
end;
procedure TClockLabelComponentEditor.ExecuteVerb(Index: Integer);
begin
case Index of
0: ShowDesigner;
else
raise ENotImplemented.Create('TClockLabelEditor has only one verb (index = 0) supported.');
end;
end;
Register the component editor in the IDE
To register a component editor to IDE, you need to call the RegisterComponentEditor routine from a register procedure, as follows:
procedure Register;
begin
RegisterComponentEditor(TClockLabel, TClockLabelComponentEditor);
end;
After you build and install the package, your new component editor is ready to use.
Go back to TestClockLabelUnit, and invoke the context menu on TClockLabel. Now you should see the Show Editor command.
Step 4: Create a Property Editor to Invoke a Dialog Box from the Object Inspector
The steps to create a property editor are almost the same as the steps for creating a component editor.
A property editor is a sub-class of TPropertyEditor. In addition to the standard TPropertyEditor class, the designide unit defines several other useful classes. Because the Format property is a string value, this sample uses as a starting point TStringProperty, which is a sub-class of TPropertyEditor.
Set the attributes of the property editor
The property editor must provide information that the Object Inspector can use to determine the tools to display. For example, the Object Inspector needs to know whether the property has subproperties or can display a list of possible values.
To specify editor attributes, you need to override the property editor's GetAttributes method. GetAttributes is a method that returns a set of values of type TPropertyAttributes. In this tutorial, GetAttributes returns [paDialog] so that the IDE knows there is a dialog box available (see the list of available values in Specifying Editor Attributes).
To display a dialog box, the IDE calls the Edit method of the property editor. So the code should like this:
TClockLabelPropertyEditor = class(TStringProperty)
private
procedure ShowDesigner;
public
function GetAttributes: TPropertyAttributes; override;
procedure Edit; override;
end;
{ TClockLabelPropertyEditor }
function TClockLabelPropertyEditor.GetAttributes: TPropertyAttributes;
begin
Result := [paDialog];
end;
procedure TClockLabelPropertyEditor.Edit;
begin
ShowDesigner;
end;
procedure TClockLabelPropertyEditor.ShowDesigner;
var
DesignerForm: TClockLabelDlg;
begin
DesignerForm :=TClockLabelDlg.Create(nil);
try
// Set curent value to designer form
DesignerForm.ClockLabel1.Format := GetStrValue;
DesignerForm.EditFormat.Text := GetStrValue;
// Show MordalForm, and then take result
if DesignerForm.ShowModal = mrOK then
SetStrValue(DesignerForm.ClockLabel1.Format);
finally
DesignerForm.Free;
end;
end;
Finally, just as you registered a new Component Editor earlier, you need to register a new Property Editor by adding a call to RegisterPropertyEditor to the Register procedure:
RegisterPropertyEditor(TypeInfo(string), TClockLabel, 'Format', TClockLabelPropertyEditor);