Title: add Multiowner Support to TComponent
Question: How To Add Multiowner Support to TComponent
Answer:
Add Multiowner Support to your Components
You maybe ask yourself what is the benefits from multiowner support ?
First I will till you what is sort of code that you maybe need to add multiowner support to.
Suppose that you have TDataSet object that hold sort of data that is needed to represented to the user using several Views ( Forms )
Like Tree view (TTreeView) and Grid (TGridView) and Chart View (TChartView) . ets
Where all of this views share the same TDataSet object as source of data
at the same time I don't want to make any memory leaks in my code .. that mean I wan't to free TDataSet object from memory when the user finishe from all views ( I mean when he close all forms connected to the same data object )
So what is the appropriate time to free TDataSet Object from memory ? Of Course the answer is when all Views are gone
So how could I know the time when the user close all the Views ?? (Another problem!!!)
TDestoryNofitier will Solve this problem
(of course TDestoryNofitier will remove itself from memory too)
procedure ShowViews(Data:TDataSet);
var
v1,v2,v3,v4:TForm;
DstNtf:TDestroyNotifier;
begin
v1:=TGridView.Create(nil);
TGridView(v1).Data:=Data;
v1.Show;
v2:=TTreeView.Create(nil);
TTreeView(v2).Data:=Data;
v2.Show;
v3:=TChartView.Create(nil);
TChartView(v3).Data:=Data;
v3.Show;
DstNtf:=TDestroyNotifier.Create;
DstNtf.AddOwnerComponent(v1);
DstNtf.AddOwnerComponent(v2);
DstNtf.AddOwnerComponent(v3);
DstNtf.AddOwnedComponent(Data);
end;
unit DestroyNotifier;
interface
uses
SysUtils,Classes,Contnrs,Forms;
type
TDestroyNotifier=class(TComponent)
private
FOwned:TObjectList;
FOwners:TObjectList;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation);override;
public
constructor Create;reintroduce;
destructor Destroy; override;
procedure AddOwnerComponent(AOwner:TComponent);
procedure AddOwnedComponent(AOwned:TComponent);
end;
implementation
{ TDestroyNotifier }
procedure TDestroyNotifier.AddOwnedComponent(AOwned: TComponent);
begin
if FOwned.IndexOf(AOwned)=-1 then
begin
if AOwned.Ownernil then
AOwned.Owner.RemoveComponent(AOwned);
AOwned.FreeNotification(Self);
FOwned.Add(AOwned);
end;
end;
procedure TDestroyNotifier.AddOwnerComponent(AOwner: TComponent);
begin
if FOwners.IndexOf(AOwner)=-1 then
begin
AOwner.FreeNotification(Self);
FOwners.Add(AOwner);
end;
end;
constructor TDestroyNotifier.Create;
begin
FOwned:=TObjectList.Create(false);
FOwners:=TObjectList.Create(false);
end;
destructor TDestroyNotifier.Destroy;
begin
FOwned.Free;
FOwners.Free;
inherited;
end;
procedure TDestroyNotifier.Notification(AComponent: TComponent;Operation: TOperation);
var
Cmp:TComponent;
begin
inherited;
if csDestroying in Application.ComponentState then
Exit;
if Operation=opRemove then
begin
if FOwners.IndexOf(AComponent)-1 then
begin
FOwners.Extract(AComponent);
AComponent.RemoveFreeNotification(Self);
if (FOwners.Count begin
while FOwned.Count0 do
begin
Cmp:=TComponent(FOwned[0]);
FOwned.Extract(Cmp);
Cmp.RemoveFreeNotification(Self);
Cmp.Free;
end;
Free;
end;
end
else if FOwned.IndexOf(AComponent)-1 then
begin
FOwned.Extract(AComponent);
AComponent.RemoveFreeNotification(Self);
end;
end;
end;
end.