[Lazarus] Saving user created component structure to LFM file

"Leonardo M. Ramé" l.rame at griensu.com
Mon Jan 12 15:11:39 CET 2009


In Delphi you have to explicitly set the subcomponent:

Example:

constructor TMyComponent.create....
begin
   ...
  FSubComponent := TSubComponent.Create(Self);
  ...
  FSubComponent.SetSubComponent(True);
  ...
end;

Leonardo M. Ramé
Griensu S.A. - Medical IT Córdoba
Tel.: 0351 - 4247979




Martin Friebe escribió:
> Mattias Gaertner wrote:
>   
>>> [...]
>>> Thanks, I think I found a better way.
>>>
>>> The outer container has no nested components of it's own. It seems I
>>> can hook into (override) TComponent.WriteState which is calling 
>>> WriteComponentData (properties, then Children). Since no children are 
>>> there, I can make my own calls to WriteComponent from there,
>>> supplying all the components, of all the helper objects.
>>>
>>> On Read, I can Hook into ReadState. I can let the reader add them 
>>> normally, and sort them out/once they have been read by the reader.
>>>
>>> The remaining question is: Does that look like something that will
>>> stay compatible with future code? The generated LFM file definitely
>>> looks like any LFM file (it has a component, with properties first
>>> then other nested Components)
>>>     
>>>       
>> To store a property that is a component and which is not owned by the
>> Lookuproot (form, datamodule, frame) you must set the csSubComponent
>> flag in ComponentStyle.
>>   
>>     
> yes, I found the csSubComponent. But it stores the only the properties 
> of the SubComponent, not the Component's Class.
>
> SubComponent does (Within the list of properties of the actual component):
>    MySubCompProp.Value1  = 120
>    MySubCompProp.Foo  = 'abc'
>
> And also subcomps, look (correctly) at the definition of the property. 
> It the Property is defined as TFoo (" property mySubCompProp: TFoo reads 
> FMyFoo write FMyFoo;" , then all properties known by this class (TFoo) 
> are stored. In My case the actual Object may be a descend and of TFoo 
> (that is the objects stored in FMyFoo), and have additional Properties 
> (This additional Properties would be lost)
>
>
> My Components are in a TList, the have different classes, so I need to 
> save them the same way like nested components:
>   object MySubCompFromListClassABC: TSubCompClassABC
>       Value1 = 120
>   end;
>
>
> The Real Background is SynEdits Gutter.
>
> The Gutter, I have managed to get saved. (via csSubComponent).
> But then the Gutter has a list of GutterParts (all of them Objects (and 
> I can/will make them Components)). I need to save all those GutterParts.
> [ I know, I will also need a Property Editor for the object inspector, 
> but that's not the issue ]
>
> If A Gutter is created, with a new SynEdit, and *not* loaded from LFM; 
> then it creates a default set.
> If it is loaded, it needs to remove the default set (can be done in 
> ReadState of SynEdit (SynEdit can inform the gutter) / Can depend on The 
> LCL Version, so loading a 0.9.26 form, will keep the defaults, as no 
> saved parts can exist)
>
>   
>> To store a list use TCollection. If you can not use TCollection please
>> explain why not.
>>   
>>     
> Because All collection Items a of the same class. If I make that 
> TGutterPartBase, then only properties exposed by TGutterPartBase are 
> saved. but each GutterPart has additional published properties. (Same 
> applies, if I make the CollectionItem a wrapper class with a property 
> "property TheRealGutterPart: TGutterPartBase" => because as 
> csSubComponen it does not save the class-info)
> Also even If I manage to get this subclasses into the collection (which 
> is hard enough, as it is not supposed to be), If the collection is 
> loaded, it restores them all to the base class, because it never saved 
> the class-info
>   
>> To store data of arbitrary length/format, use DefineProperties. This
>> has a drawback: In case of an error the IDE can not help fixing it.
>>   
>>     
> DefineProperties only takes simple values. Because in define properties 
> I must give it the name. Then In Read/WriteProc I deal with the value. 
> So define Property will always create an LFM entry like:
>      MyDefinedPropertyName = xxx
> xxx Comes from the writecallback.
>
> If the write callback attempts to do WriteComponent, then this will fail 
> later, when the binary format is translated into text-lfm-format 
> (because  " MyDefinedPropertyName = MyObject: TMyClass" is not allowed
>
> That is even, if the WriteCallback starts a list first, it will still fail.
>     MyDefinedPropertyName = ( 
>               MyObject: TMyClass
>                 ....
>
> With "DefineProperties"  I have 2 (undesirable) possibilities:
> 1) use DefineBinarryProperties => and write my own format, no one can 
> edit it, and why invent the wheel again?
> 2) use DefineProperties and define a large set of properties:
>   - define a classname property for each of my objects
>   - and define a property for each value that each of my objects needs 
> to store.
>   Again there is code (WriteComponent) that does streaming of objects 
> including class info; why invent the wheel again?
>
> ---------------
>
> So as I see it I found 2 possibilities
>
> 1) The GutterParts are created as components owned by the SynEdit (or 
> does it have to be the form; if it does have to be the form then there 
> will be issues if there is more than one synedit.... ). that will be a 
> lot of easy to break maintenance work. because you need to search 
> through the component list to find the Objects.
> And when loading I still need to remove the Objects created in 
> Synedit.Create or I get double entries.
> - Also I tried it, and SynEdit did not seem to stream them (MyGutterPart 
> := TcomponentBasedClass.Create(TheSynEditAsOwner);) => nothing in the lfm
>
> 2) Maintain the objects as they are, but use SynEdit.WriteState to 
> append them to the lfm
>   (They can easily be caught, if they get read (by the default reader) 
> during loading
>
>
> Best Regards
> Martin
> _______________________________________________
> Lazarus mailing list
> Lazarus at lazarus.freepascal.org
> http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
>
>   



More information about the Lazarus mailing list