Recent

Author Topic: New component with expandable property  (Read 3727 times)

ezlage

  • Guest
New component with expandable property
« on: April 12, 2018, 10:20:57 pm »
Hi!

I built a package with this type as property, but after rebuild Lazarus and adding the component to the form, I can't see the property through the Object Inspector. I did it in exactly same way as the ChildSizing of TForm. What did I wrong?

Thanks.

Code: Pascal  [Select][+][-]
  1. TLayer = class(TPersistent)
  2.   protected
  3.     FVar: string;
  4.     procedure Change; virtual;
  5.   private
  6.     FOnChange: TNotifyEvent;
  7.   public
  8.     constructor Create(AOwner: TComponent);
  9.     procedure Assign(Source: TPersistent); override;
  10.     procedure AssignTo(Dest: TPersistent); override;
  11.     function IsEqual(Layer: TLayer ): boolean;
  12.   public
  13.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  14.   published
  15.     property AVar: string read FVar write FVar;
  16.   end;

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: New component with expandable property
« Reply #1 on: April 12, 2018, 10:36:51 pm »
Do you mean that you have other class with:
Code: Pascal  [Select][+][-]
  1. published
  2.   property Layer: TLayer read FLayer write FLayer;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: New component with expandable property
« Reply #2 on: April 12, 2018, 10:41:29 pm »
Hi!

I built a package with this type as property, but after rebuild Lazarus and adding the component to the form, I can't see the property through the Object Inspector. I did it in exactly same way as the ChildSizing of TForm. What did I wrong?

Thanks.

Code: Pascal  [Select][+][-]
  1. TLayer = class(TPersistent)
  2.   protected
  3.     FVar: string;
  4.     procedure Change; virtual;
  5.   private
  6.     FOnChange: TNotifyEvent;
  7.   public
  8.     constructor Create(AOwner: TComponent);
  9.     procedure Assign(Source: TPersistent); override;
  10.     procedure AssignTo(Dest: TPersistent); override;
  11.     function IsEqual(Layer: TLayer ): boolean;
  12.   public
  13.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  14.   published
  15.     property AVar: string read FVar write FVar;
  16.   end;
which property be specific. FYI, object inspector only show published properties.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

ezlage

  • Guest
Re: New component with expandable property
« Reply #3 on: April 12, 2018, 11:00:02 pm »
Do you mean that you have other class with:
Code: Pascal  [Select][+][-]
  1. published
  2.   property Layer: TLayer read FLayer write FLayer;

Exactly!

@taazz, It's like @Blaazen said.
« Last Edit: April 12, 2018, 11:01:57 pm by ezlage »

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: New component with expandable property
« Reply #4 on: April 12, 2018, 11:22:14 pm »
This should work, it is commonly used everywhere.
Can you show more code? What that class inherits from? TCustomControl?
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

ezlage

  • Guest
Re: New component with expandable property
« Reply #5 on: April 12, 2018, 11:46:01 pm »
This should work, it is commonly used everywhere.
Can you show more code? What that class inherits from? TCustomControl?

Of course. In the attachment are: test project, types, package and component.

Code: Pascal  [Select][+][-]
  1. unit NewComponent;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils;
  9.  
  10. type
  11.  
  12.   { TExpandable }
  13.  
  14.   TExpandable = class(TPersistent)
  15.   protected
  16.     FVar: string;
  17.     procedure Change; virtual;
  18.   private
  19.     FOnChange: TNotifyEvent;
  20.   public
  21.     constructor Create(AOwner: TComponent);
  22.     procedure Assign(Source: TPersistent); override;
  23.     procedure AssignTo(Dest: TPersistent); override;
  24.     function IsEqual(Expandable: TExpandable): boolean;
  25.   public
  26.     property OnChange: TNotifyEvent read FOnChange write FOnChange;
  27.   published
  28.     property SubProperty: string read FVar write FVar;
  29.   end;
  30.  
  31.   TNewComponent = class(TComponent)
  32.   private
  33.   protected
  34.     FExpandable: TExpandable;
  35.   public
  36.   published
  37.     property Expandable: TExpandable read FExpandable write FExpandable;
  38.   end;
  39.  
  40. procedure Register;
  41.  
  42. implementation
  43.  
  44. procedure Register;
  45. begin
  46.   RegisterComponents('Misc',[TNewComponent]);
  47. end;
  48.  
  49. { TExpandable }
  50.  
  51. procedure TExpandable.Change;
  52. begin
  53.   if Assigned(FOnChange) then FOnChange(Self);
  54. end;
  55.  
  56. constructor TExpandable.Create(AOwner: TComponent);
  57. begin
  58.   inherited Create;
  59. end;
  60.  
  61. procedure TExpandable.Assign(Source: TPersistent);
  62. begin
  63.   inherited Assign(Source);
  64. end;
  65.  
  66. procedure TExpandable.AssignTo(Dest: TPersistent);
  67. begin
  68.   inherited AssignTo(Dest);
  69. end;
  70.  
  71. function TExpandable.IsEqual(Expandable: TExpandable): boolean;
  72. begin
  73.   Result:=(FVar=Expandable.SubProperty);
  74. end;
  75.  
  76. end.
« Last Edit: April 12, 2018, 11:47:53 pm by ezlage »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1314
    • Lebeau Software
Re: New component with expandable property
« Reply #6 on: April 13, 2018, 12:23:07 am »
There are quite a few issues with your code.

Code: [Select]
  protected
    FVar: string;
    procedure Change; virtual;

Your SubProperty doesn't have a setter that calls Change() when FVar changes value.  Not the cause of your issue, but should be noted anyway.  There is no point in having an OnChange event that is not fired when changes are made.

Code: [Select]
    constructor Create(AOwner: TComponent);

TPersistent doesn't have an Owner, so there is no reason to expose an Owner parameter in TExpandable's constructor, unless you want to limit it to a specific parent class, and maintain a pointer to that class during TExpandable's lifetime.

Code: [Select]
  published
    property Expandable: TExpandable read FExpandable write FExpandable;

Note that this is a memory leak waiting to happen.  TNewComponent needs to maintain ownership of its FExpandable object at all times.  If outside code were ever to assign a TExpandable object to this property, you would leak the previous object!  This type of property needs a setter that calls FExpandable.Assign().

More importantly, your TNewComponent is *missing a constructor* to create the TExpandable object, that is why the Object Inspector can't work with the property - FExpandable is nil!

Code: [Select]
procedure TExpandable.Assign(Source: TPersistent);
begin
  inherited Assign(Source);
end;

procedure TExpandable.AssignTo(Dest: TPersistent);
begin
  inherited AssignTo(Dest);
end;

You are not testing the Source/Dest to see if a TExpandable object is being assigned to another TExpandable object so the FVar member can be copied.

With that said, the code should look more like this:

Code: [Select]
unit NewComponent;
     
{$mode objfpc}{$H+}
     
interface
     
uses
  Classes, SysUtils;
     
type
     
  { TExpandable }
     
  TExpandable = class(TPersistent)
  private
    FVar: string;
    FOnChange: TNotifyEvent;
    procedure SetSubProperty(const Value: string);
  protected
    procedure Change; virtual;
  public
    procedure Assign(Source: TPersistent); override;
    procedure AssignTo(Dest: TPersistent); override;
    function IsEqual(Expandable: TExpandable): boolean;
  public
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  published
    property SubProperty: string read FVar write SetSubProperty;
  end;
     
  TNewComponent = class(TComponent)
  private
    FExpandable: TExpandable;
    procedure SetExpandable(Value: TExpandable);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Expandable: TExpandable read FExpandable write SetExpandable;
  end;
     
procedure Register;
     
implementation
     
procedure Register;
begin
  RegisterComponents('Misc',[TNewComponent]);
end;
     
{ TExpandable }
     
procedure TExpandable.Change;
begin
  if Assigned(FOnChange) then FOnChange(Self);
end;
         
procedure TExpandable.SetSubProperty(const Value: string);
begin
  if FVar <> Value then
  begin
    FVar := Value;
    Change;
  end;
end;

procedure TExpandable.Assign(Source: TPersistent);
begin
  if Source is TExpandable then
    SubProperty := TExpandable(Source).SubProperty
  else
    inherited Assign(Source);
end;
     
procedure TExpandable.AssignTo(Dest: TPersistent);
begin
  if Dest is TExpandable then
    TExpandable(Dest).SubProperty := SubProperty
  else
    inherited AssignTo(Dest);
end;
     
function TExpandable.IsEqual(Expandable: TExpandable): boolean;
begin
  Result := (FVar = Expandable.SubProperty);
end;
     
{ TNewComponent }

constructor TNewComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FExpandable := TExpandable.Create;
end;

destructor TNewComponent.Destroy;
begin
  FExpandable.Free;
  inherited Destroy;
end;

procedure TNewComponent.SetExpandable(Value: TExpandable);
begin
  FExpandable.Assign(Value);
end;

end.
« Last Edit: April 13, 2018, 12:25:17 am by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

lainz

  • Hero Member
  • *****
  • Posts: 4468
    • https://lainz.github.io/
Re: New component with expandable property
« Reply #7 on: April 13, 2018, 12:42:29 am »
Remy, just amazing explanation.

Things I often forget to add to my components.

ezlage

  • Guest
Re: New component with expandable property
« Reply #8 on: April 14, 2018, 06:30:24 am »
Working now, Remy Lebeau.
Thank you very much!

 

TinyPortal © 2005-2018