0

I want to write a custom property editor for my custom component. I have a component declaration like below:

type
   TEJsonQuery = class(TComponent)
   private
      FSql: TStrings;

      procedure SetSQL(const Value: TStrings);
      { Private declarations }
   protected
      { Protected declarations }
   public
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
      { Public declarations }
   published
      property SQL: TStrings read FSql write SetSQL;
      { Published declarations }
   end;

constructor TEJsonQuery.Create;
begin
   inherited Create(AOwner);
   FSql := TStringList.Create;
end;

procedure TEJsonQuery.SetSQL(const Value: TStrings);
begin
   if SQL.Text <> Value.Text then
   begin
      //Close;
      SQL.BeginUpdate;
      try
         SQL.Assign(Value);
      finally
         SQL.EndUpdate;
      end;
   end;
end;

destructor TEJsonQuery.Destroy;
begin
   inherited Destroy;
   FSql.Free;
end;

And a property editor declaration like below:

type
   TQuerySQLProperty = class(TStringProperty)
   public
      function GetAttributes: TPropertyAttributes; override;
      procedure Edit; override;
   end;

   Tfrm_JsonQuerySQL = class(TForm)
      btn_JsonQuerySQL: TButton;
      mem_SQL: TMemo;
    btn_OK: TButton;
    btn_Cancel: TButton;
   private
      { Private declarations }
   public
      { Public declarations }
   end;

var
   frm_JsonQuerySQL: Tfrm_JsonQuerySQL;

procedure Register;

implementation

{$R *.dfm}

procedure Register;
begin
   RegisterComponents('MyComponents', [TEJsonQuery]);
   RegisterPropertyEditor(TypeInfo(TStrings), TEJsonQuery, 'SQL', TQuerySQLProperty);
end;

procedure TQuerySqlProperty.Edit;
begin
   frm_Ekol_JsonQuerySQL := Tfrm_Ekol_JsonQuerySQL.Create(Application);
   try
      Assert(False, '"' + GetStrValue + '"');
      frm_Ekol_JsonQuerySQL.mem_SQL.Lines.Text := GetStrValue;
      // show the dialog box
      if frm_Ekol_JsonQuerySQL.ShowModal = mrOK then
      begin
         SetStrValue(frm_Ekol_JsonQuerySQL.mem_SQL.Lines.Text);
      end;
   finally
      frm_Ekol_JsonQuerySQL.Free;
   end;
end;

function TQuerySQLProperty.GetAttributes: TPropertyAttributes;
begin
   // editor, sorted list, multiple selection
   // Result := [paDialog, paMultiSelect, paValueList, paSortList];
   Result := [paDialog];
end;

Property editor opens if Assert(False, '"' + GetStrValue + '"'); is commented with empty memo because GetStrValue returns empty string.

Enes Köroğlu
  • 184
  • 5
  • 15
  • 2
    The SQL property is a TStrings property, not a string property, and GetStrValue only works on string properties, and if more than one component is selected, it returns the value of GetComponent(0). GetStrValue is a virtual property, so you can implement your own, but simpler might be to redefine your SQL property as a string property rather than a TStrings property. – Dsm Jul 11 '17 at 09:26
  • I have two component and the other one inherits SQL property from ancestor class and changing SQL property's type is not possible for it. Should i cast GetComponent(0) to myclass and reach to sql property or should find SQL property with rtti or something like that? – Enes Köroğlu Jul 11 '17 at 10:21
  • Casting would work, especially if surrounding with a **if Component(0) is TEJSONQuery**. No need to use RTTI, though, just use the 'Text' property of the SQL property. – Dsm Jul 11 '17 at 10:27

1 Answers1

3

The SQL property is a TStrings property, not a string property, and GetStrValue only works on string properties, and if more than one component is selected, it returns the value of GetComponent(0). GetStrValue is a virtual property, so you can implement your own.

Here is what I have in mind:

type
  TQuerySqlProperty = ...
  public
    function GetStrValue : string; override;
    ...
  end;
  ...

function TQuerySqlProperty.GetStrValue : string;
begin
  if GetComponent(0) is TEJsonQuery then
  begin
    Result := (GetComponent(0) as TEJsonQuery ).SQL.Text;
  end
  else
  begin
    Result := inherited;
  end;
end;
Enes Köroğlu
  • 184
  • 5
  • 15
Dsm
  • 5,870
  • 20
  • 24
  • This time it shows sql.text value in object inspector instead of "(TStrings)", is it possible to hide sql.text content from object inspector. I want to show content only when clicked to 3 dots in my custom screen. – Enes Köroğlu Jul 12 '17 at 08:47
  • Not to override GetXxxValue method solved the problem :) Instead I wrote a new method and used it which is named other than GetXxxValue – Enes Köroğlu Jul 12 '17 at 10:02
  • I did consider that possibility, but I thought seeing the SQL in the editor would be useful. – Dsm Jul 12 '17 at 10:09
  • I did not like but if someone wants that to see SQL and not to be able to edit, can use `Result := [paDialog, paReadOnly];`in GetAttributes method than SQL.Text will be read only viewable. – Enes Köroğlu Jul 12 '17 at 10:27
  • Fair enough. Of course we have guess some of the subtleties of what askers are trying to achieve... :-) – Dsm Jul 12 '17 at 10:29