I've never been in a situation that needed it, and this is the first time I try to have a TCollection
as TCollectionItem
of another TCollection
.
It all compiles fine, but there is no reaction when the three dots behind the TCollectionItem
's TCollection
property are clicked, ie. the dialog with the list of that sub-TCollection
does not appear.
I was under the impression that, since no fancy property editors should be necessary (the sub-TCollection
only carries items that have a string
and a single
property), the IDE would pretty much handle it automatically.
Apparently that's not the case, or I'm overseeing the obvious, which is a chronic affliction.
The implementation (run-time) unit has this:
type
TBitmapItemTag = class(TCollectionItem)
private
FTagName: string;
FTagFloat: Single;
published
property TagName: string read FTagName write FTagName;
property TagFloat: Single read FTagFloat write FTagFloat;
end;
TBitmapItemTags = class(TOwnedCollection)
end;
TBitmapItem = class(TCollectionItem)
private
FBitmap: TBitmap;
FBitmapItemTags: TBitmapItemTags;
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
published
property Bitmap: TBitmap read FBitmap write FBitmap;
property Tags: TBitmapItemTags read FBitmapItemTags write FBitmapItemTags;
end;
TBitmaps = class(TCollection)
end;
TBitmapCollection = class(TComponent)
private
FBitmaps: TBitmaps;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Bitmaps: TBitmaps read FBitmaps write FBitmaps;
end;
implementation
{ TBitmapItem }
constructor TBitmapItem.Create(Collection: TCollection);
begin
inherited Create(Collection);
FBitmap := TBitmap.Create(0, 0);
FBitmapItemTags := TBitmapItemTags.Create(Self,TBitmapItemTag);
end;
destructor TBitmapItem.Destroy;
begin
FBitmap.Free;
FBitmapItemTags.Free;
inherited;
end;
{ TBitmapCollection }
constructor TBitmapCollection.Create(AOwner: TComponent);
begin
inherited;
FBitmaps := TBitmaps.Create(TBitmapItem);
end;
destructor TBitmapCollection.Destroy;
begin
FBitmaps.Free;
inherited;
end;
The Register
procedure is implemented in the design-time unit and just calls the RegisterComponents
procedure. And holds some lazy RegisterPropertyEditor
tries that were to no avail.
If anyone can point me to the shortest path in order for the IDE to recognize the TBitmapItemTag TCollectionItem
, I'd be grateful.
You need to change TBitmaps
to derive from TOwnedCollection
instead of TCollection
.
I also suggest defining explicit constructors for TBitmapItemTags
and TBitmaps
.
You also need to add some setter methods to your object-based properties, otherwise you risk memory leaks at runtime. Your setters should be calling Assign()
on your objects to copy property values from one object to another. TCollection
already implements Assign()
for you, but you will have to implement Assign()
in your collection items.
Try this:
type
TBitmapItemTag = class(TCollectionItem)
private
FTagName: string;
FTagFloat: Single;
public
procedure Assign(ASource: TPersistent); override;
published
property TagName: string read FTagName write FTagName;
property TagFloat: Single read FTagFloat write FTagFloat;
end;
TBitmapItem = class;
TBitmapItemTags = class(TOwnedCollection)
public
constructor Create(AOwner: TBitmapItem); reintroduce;
end;
TBitmapItem = class(TCollectionItem)
private
FBitmap: TBitmap;
FTags: TBitmapItemTags;
procedure SetBitmap(AValue: TBitmap);
procedure SetTags(AValue: TBitmapItemTags);
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
procedure Assign(ASource: TPersistent); override;
published
property Bitmap: TBitmap read FBitmap write SetBitmap;
property Tags: TBitmapItemTags read FTags write SetTags;
end;
TBitmapCollection = class;
TBitmaps = class(TOwnedCollection)
public
constructor Create(AOwner: TBitmapCollection); reintroduce;
end;
TBitmapCollection = class(TComponent)
private
FBitmaps: TBitmaps;
procedure SetBitmaps(AValue: TBitmaps);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Bitmaps: TBitmaps read FBitmaps write SetBitmaps;
end;
{ TBitmapTagItem }
procedure TBitmapItemTag.Assign(ASource: TPersistent);
begin
if ASource is TBitmapItemTag then
begin
FTagName := TBitmapItemTag(ASource).TagName;
FTagFloat := TBitmapItemTag(ASource).TagFloat;
end
else
inherited;
end;
{ TBitmapItemTags }
constructor TBitmapItemTags.Create(AOwner: TBitmapItem);
begin
inherited Create(AOwner, TBitmapItemTag);
end;
{ TBitmapItem }
constructor TBitmapItem.Create(Collection: TCollection);
begin
inherited Create(Collection);
FBitmap := TBitmap.Create(0, 0);
FTags := TBitmapItemTags.Create(Self);
end;
destructor TBitmapItem.Destroy;
begin
FBitmap.Free;
FTags.Free;
inherited;
end;
procedure TBitmapItem.Assign(ASource: TPersistent);
begin
if ASource is TBitmapItem then
begin
FBitmap.Assign(TBitmapItem(ASource).Bitmap);
FTags.Assign(TBitmapItem(ASource).Tags);
end
else
inherited;
end;
procedure TBitmapItem.SetBitmap(AValue: TBitmap);
begin
FBitmap.Assign(AValue);
end;
procedure TBitmapItem.SetTags(AValue: TBitmapItemTags);
begin
FTags.Assign(AValue);
end;
{ TBitmaps }
constructor TBitmaps.Create(AOwner: TBitmapCollection);
begin
inherited Create(AOwner, TBitmapItem);
end;
{ TBitmapCollection }
constructor TBitmapCollection.Create(AOwner: TComponent);
begin
inherited;
FBitmaps := TBitmaps.Create(Self);
end;
destructor TBitmapCollection.Destroy;
begin
FBitmaps.Free;
inherited;
end;
procedure TBitmapCollection.SetBitmaps(AValue: TBitmaps);
begin
FBitmaps.Assign(AValue);
end;