Deriving a Property-editor Class

From RAD Studio
Jump to: navigation, search

Go Up to Adding Property Editors


Both the component library define several kinds of property editors, all of which descend from TPropertyEditor. When you create a property editor, your property-editor class can either descend directly from TPropertyEditor or indirectly through one of the property-editor classes described in the table below. The classes in the DesignEditors unit can be used for VCL applications.

Note:
All that is absolutely necessary for a property editor is that it descend from TBasePropertyEditor and that it support the IProperty interface. TPropertyEditor, however, provides a default implementation of the IProperty interface.

The list in the table below is not complete. The VCLEditors unit also defines some very specialized property editors used by unique properties, such as the component name. The listed property editors are the ones that are the most useful for user-defined properties.

Predefined property-editor types:

Type Properties edited

TOrdinalProperty

All ordinal-property editors (those for integer, character, and enumerated properties) descend from TOrdinalProperty.

TIntegerProperty

All integer types, including predefined and user-defined subranges.

TCharProperty

Char-type and subranges of Char, such as 'A'..'Z'.

TEnumProperty

Any enumerated type.

TFloatProperty

All floating-point numbers.

TStringProperty

Strings.

TSetElementProperty

Individual elements in sets, shown as Boolean values

TSetProperty

All sets. Sets are not directly editable, but can expand into a list of set-element properties.

TClassProperty

Classes. Displays the name of the class and allows expansion of the class's properties.

TMethodProperty

Method pointers, most notably events.

TComponentProperty

Components in the same form. The user cannot edit the component's properties, but can point to a specific component of a compatible type.

TColorProperty

Component colors. Shows color constants if applicable, otherwise displays hexadecimal value. The drop-down list contains the color constants. Double-click opens the color-selection dialog box.

TFontNameProperty

Font names. The drop-down list displays all currently installed fonts.

TFontProperty

Fonts. Allows expanding individual font properties and accessing the font dialog box.


Matching unnamed enumerations

For unnamed enumerations, the IDE shows numbers instead of the names of the elements. This section shows the mapping technique for mapping names to numbers in the set so that the names display in the Object Inspector.

The following example is a code sample that shows how to match the unnamed enumerations to specific names using the property mapper functionality:

unit DemoComponent;

interface

uses
  System.SysUtils, Vcl.Forms, System.Classes, Vcl.Controls, Vcl.Menus, TypInfo, Vcl.Graphics,
  DesignIntf, DesignEditors, DesignConst, DesignMenus, VclEditors;

  const
  Bit0     = 0;
  Bit1     = 1;
  Bit2     = 2;
  Bit3     = 3;
  Bit4     = 4;
  Bit5     = 5;
  Bit6     = 6;
  Bit7     = 7;
  BitCount = 8;

type
  TSomeBits = 0..SizeOf(Integer) * 8 - 1;
  //OR
  //TASetOfBits = Bit0..Bit7;
  TPiecesOfEight = set of TSomeBits;

  //IMPORTANT to use "VclEditors.TSetProperty"
  //The DesignEditors.TSetProperty will have the old True/False dropdown editor
  TPiecesOfEightProperty = class(VclEditors.TSetProperty)
  public
    function GetValue: string; override;
    procedure GetProperties(Proc: TGetPropProc); override;
  end;

  TPiecesOfEightElementProperty = class(TSetElementProperty)
  public
    function GetName: string; override;
  end;

  TPiecesOfEightControl = class(TComponent)
  private
    FPiecesOfEightValues: TPiecesOfEight;
  published
    property PiecesOfEight: TPiecesOfEight read FPiecesOfEightValues write FPiecesOfEightValues;
  end;

procedure Register;

implementation
const
  cBitValues : array [Bit0..Bit7] of string = (
  'Bit One'    ,
  'Bit Two'    ,
  'Bit Three'  ,
  'Bit Four'   ,
  'Bit Five'   ,
  'Bit Six'    ,
  'Bit Seven'  ,
  'Bit Eight'
  );

procedure TPiecesOfEightProperty.GetProperties(Proc: TGetPropProc);
var
  I: integer;
  E: IProperty;
begin
  with GetTypeData(GetTypeData(GetPropType)^.CompType^)^ do
  begin
    //for I := MinValue to Maxvalue do // is a smaller set is used.
    for I := MinValue to BitCount-1 do
    begin
      E := TPiecesOfEightElementProperty.Create(Self, I);
      Proc(E);
      E := nil;
    end;
  end;
end;

function TPiecesOfEightProperty.GetValue: string;
var
  I : integer;
  S: TIntegerSet;
begin
  Integer(S) := GetOrdValue;
  Result := '';
  for I := 0 to SizeOf(Integer) * 8 - 1 do
    if I in S then
      Result := Result + cBitValues[I+Low(TSomeBits) ] + ',';
  if Result.EndsWith(',') then Delete(Result, Length(Result), 1);
    Result := '[' + Result + ']';
end;

function TPiecesOfEightElementProperty.GetName: string;
begin
   Result := cBitValues[Element];
end;

//For "sets", the VCLDesigner code always maps the property editor back to: VclEditors.TSetProperty.
//So we need to make OUR set's properties map to *our* editor implementation
function SetPiecesOfEightPropertyMapper(Obj: TPersistent; PropInfo: PPropInfo): TPropertyEditorClass;
begin
  Result := nil;
  if Assigned(Obj) and (Obj.ClassType <> TPiecesOfEightControl) then Exit;
  if PropInfo.PropType^.Kind = tkSet then
    if PropInfo.PropType^ = TypeInfo(TPiecesOfEight) then
      Result := TPiecesOfEightProperty;
end;

procedure Register;
begin
  RegisterComponents('Test Group', [TPiecesOfEightControl]);
  RegisterPropertyMapper(SetPiecesOfEightPropertyMapper);
  RegisterPropertyEditor(TypeInfo(TPiecesOfEight), TPiecesOfEightControl, 'PiecesOfEight', TPiecesOfEightProperty);
end;
end.