Recent

Author Topic: My component's property can't be loaded  (Read 12386 times)

GADZombie

  • New Member
  • *
  • Posts: 46
  • 8bitrlz
    • Zombie Mastah
My component's property can't be loaded
« on: January 27, 2014, 10:52:28 am »
Hello
I have made my own component based on TBitBtn. I have added a new event to it. It works fine. My component is visible on component tab, I can use it in IDE and it compiles fine. But there is one problem: when I use my added event (let's call it OnRoll), new procedure creates in source. I have typed a code inside and it works fine. I can see this procedure name in editor. When I save the project, I can see there is my procedure connected to OnRoll event in lzm file. But when I close Lazaurs and load this project again, this procedure disappears from editor! In source code it is still visible.
What should I do to make it save and load properly, like every other property and event?

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: My component's property can't be loaded
« Reply #1 on: January 27, 2014, 10:56:57 am »
No export but I suspect something more needs to be streamed/to from disk than is currently done.

http://wiki.lazarus.freepascal.org/Streaming_components#Streamable_properties

... and perhaps more wiki pages
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: My component's property can't be loaded
« Reply #2 on: January 27, 2014, 11:25:09 am »
What type have you declared your new event property to have?

GADZombie

  • New Member
  • *
  • Posts: 46
  • 8bitrlz
    • Zombie Mastah
Re: My component's property can't be loaded
« Reply #3 on: January 27, 2014, 01:37:27 pm »
This is the whole code. I have deleted all other changes I made and left only this not working event OnRolledChange.
It works ok. It IS saved in lfm file. But it is not loaded with project in Lazarus.

Code: [Select]
unit RollButton;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, Buttons, Controls;

type
  TRollButton = class(TBitBtn)
  private
    fRolled: boolean;
    fOnRolledChange: TNotifyEvent;

    procedure SetOnRolledChange(AValue: TNotifyEvent);
    procedure ToggleRolled();
    procedure SetRolled(value: boolean);

  protected
    procedure Click; override;

  public
    constructor Create(TheOwner: TComponent); reintroduce;
    destructor Destroy; override;

  published
    property Rolled: boolean read fRolled write SetRolled;
    property OnRolledChange: TNotifyEvent read fOnRolledChange write SetOnRolledChange;
  end;

procedure Register;

implementation

procedure TRollButton.ToggleRolled;
begin
  Rolled := not Rolled;
end;

procedure TRollButton.SetOnRolledChange(AValue: TNotifyEvent);
begin
  if FOnRolledChange = AValue then
    Exit;
  FOnRolledChange := AValue;
end;

procedure TRollButton.SetRolled(value: boolean);
var
  oldValue: boolean;
begin
  if fRolledControl <> nil then
  begin
    oldValue := fRolled;
    fRolled := value;
    if (oldValue <> fRolled) and (Assigned(fOnRolledChange)) then
      fOnRolledChange(Self);
  end
  else
    fRolled := false;
end;

procedure TRollButton.Click;
begin
  ToggleRolled;
  inherited Click;
end;

constructor TRollButton.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  fRolled := false;
end;

destructor TRollButton.Destroy;
begin
  inherited Destroy;
end;

procedure Register;
begin
  RegisterComponents('Zombie', [TRollButton]);
end;

end.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12766
  • FPC developer.
Re: My component's property can't be loaded
« Reply #4 on: January 27, 2014, 01:49:20 pm »
Methods assigned to a published property must be published too. This generates RTTI that allows the framework to resolve the methodname in the lfm to the actual method.

GADZombie

  • New Member
  • *
  • Posts: 46
  • 8bitrlz
    • Zombie Mastah
Re: My component's property can't be loaded
« Reply #5 on: January 27, 2014, 01:57:56 pm »
Thanks! I didn't know that. It means I must just move procedure SetOnRolledChange(AValue: TNotifyEvent); to published and it will work.

Bart

  • Hero Member
  • *****
  • Posts: 5712
    • Bart en Mariska's Webstek
Re: My component's property can't be loaded
« Reply #6 on: January 27, 2014, 03:06:40 pm »
Methods assigned to a published property must be published too. This generates RTTI that allows the framework to resolve the methodname in the lfm to the actual method.

I think I misunderstand you, but do you mean that any method that sets a published property needs to be published as well?

So if I declare
Code: [Select]
    property ParentFont: Boolean  read FParentFont write SetParentFont default True;

it then follows that SetParentFont needs to be published (but it isn't for TControl) as well?

Bart

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12766
  • FPC developer.
Re: My component's property can't be loaded
« Reply #7 on: January 27, 2014, 03:35:15 pm »
Methods assigned to a published property must be published too. This generates RTTI that allows the framework to resolve the methodname in the lfm to the actual method.

I think I misunderstand you, but do you mean that any method that sets a published property needs to be published as well?

No, the one you assign to it (to an (Tnotify)event style property (method var). The setter can be statically reached via the RTTI info of the property. No dynamic behaviour necessary
there.
 

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: My component's property can't be loaded
« Reply #8 on: January 27, 2014, 04:36:33 pm »
Note that although you try to protect the Click procedure you override by placing it in a protected section, this achieves nothing since it is already declared public in the ancestor, and its visibility cannot be reduced.

GADZombie

  • New Member
  • *
  • Posts: 46
  • 8bitrlz
    • Zombie Mastah
Re: My component's property can't be loaded
« Reply #9 on: January 27, 2014, 06:41:49 pm »
Note that although you try to protect the Click procedure you override by placing it in a protected section, this achieves nothing since it is already declared public in the ancestor, and its visibility cannot be reduced.

Thank you. You're right. I just checked it wrong at TCustomButton, where it is protected and I wanted to do it in the same way. But in TCustomBitBtn it is public. I can change it to public. But the visibility can be changed from public to protected, but from protected to public can't?

GADZombie

  • New Member
  • *
  • Posts: 46
  • 8bitrlz
    • Zombie Mastah
Re: My component's property can't be loaded
« Reply #10 on: January 27, 2014, 07:30:08 pm »
Bad news is, I have moved everything to published, but it still doesn't work. When I assign a procedure to even OnRolledChange, save project and reload it, assigned procedure disappears. Ofcourse in source code it is still there. What should I do?

reinerr

  • New Member
  • *
  • Posts: 37
Re: My component's property can't be loaded
« Reply #11 on: February 06, 2014, 04:19:18 am »
Try it with a direct read AND write property:
Code: [Select]
property OnRolledChange: TNotifyEvent read fOnRolledChange write fOnRolledChange;
Your code as presented doesn't need a special SetOnRolledChange but I assume that's a legacy of the code reduction you made for this demo. Still, I'm not sure why its not working but as we reduce it more we may find the cause.

PS. I don't understand what marcov is saying with "Methods assigned to a published property must be published too." Isn't this handled by the IDE?

PPS. Your code as supplied in reply #3 can't compile because it is referencing an undeclared variable fRolledControl - maybe you were still using an onld component with some other bug.
« Last Edit: February 06, 2014, 04:26:06 am by reinerr »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: My component's property can't be loaded
« Reply #12 on: February 06, 2014, 04:37:28 am »
PS. I don't understand what marcov is saying with "Methods assigned to a published property must be published too." Isn't this handled by the IDE?

No it is handled by the streaming system. Look at it like this srteaming mechanism reads property OnRolledChange and it has a value of Form1.DoMyRollchangePlease; that of course is a simple string now it has to find the Form1 component in memory resolve the DoMyRollchangePlease in to the forms method and get its address then assign that address to the property as value so it can be executed when needed.

If the DoMyRollChangePlease is not a published method then no rtti is generated and the streaming mechanism can not find in memory when it needs to and everything breaks down. BUT double clicking on the object inspector will create a published method for you automatically so in a sense IDE will try to make sure everything is set up as needed but it can't stop you from copying the created method header to private or protected portion of the class or even worst add a private specifier somewhere on the top of the class.

As for the problem it makes no sense if the property values are been kept for other components then the code shown here has nothing to prevent the streaming mechanism from doing its work, so assuming that the code cut wasn't deep enough to solve the problem without him noticing, then there is no problem with the component. It probably is somewhere else.
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

GADZombie

  • New Member
  • *
  • Posts: 46
  • 8bitrlz
    • Zombie Mastah
Re: My component's property can't be loaded
« Reply #13 on: February 06, 2014, 10:01:33 pm »
Try it with a direct read AND write property:
Code: [Select]
property OnRolledChange: TNotifyEvent read fOnRolledChange write fOnRolledChange;

Well, you might be right. I did it and it works. OnRolledChange is loaded from file in IDE.
So I've tried another thing and I left SetOnRolledChange procedure, but I have commented first if:

Code: [Select]
procedure TRollButton.SetOnRolledChange(AValue: TNotifyEvent);
begin
{  if fOnRolledChange = AValue then
    Exit;}
  fOnRolledChange := AValue;
end;

And it also works! So it looks like "if fOnRolledChange = AValue" returns true and "fOnRolledChange := AValue;" never happens. I don't know why. I even added to constructor "fOnRolledChange := nil", but it didn't help.

PS: fRolledControl is just a TComponent and it has nothing to do with fOnRolledChange.

It even works now when SetOnRolledChange is in private section, so I think it's not true that setter has to be in published section.

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: My component's property can't be loaded
« Reply #14 on: February 06, 2014, 11:22:38 pm »
Code: [Select]
constructor Create(TheOwner: TComponent); reintroduce;
Shouldn't that be 'override'? TCustomBitBtn does have Create(TheOwner: TComponent) so 'reintroduce' is not needed.

 

TinyPortal © 2005-2018