mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-29 09:50:31 +02:00
dockmanager example: workarounds for HostDockSite mishandling
git-svn-id: trunk@22972 -
This commit is contained in:
parent
1eb2d6cc7f
commit
82643dcee2
@ -962,6 +962,8 @@ type
|
||||
var
|
||||
ZoneRec: RZone;
|
||||
ZoneName: string;
|
||||
const
|
||||
BookZoneName: string = '*';
|
||||
|
||||
procedure TEasyTree.SaveToStream(Stream: TStream);
|
||||
|
||||
@ -976,8 +978,18 @@ procedure TEasyTree.SaveToStream(Stream: TStream);
|
||||
child := Zone.ChildControl;
|
||||
if child = nil then
|
||||
ZoneName := ''
|
||||
else
|
||||
ZoneName := child.Name;
|
||||
{$IFDEF new}
|
||||
else if child is TEasyDockBook then begin
|
||||
ZoneName := BookZoneName;
|
||||
ZoneName := TEasyDockBook(child).GetDockCaption(child)
|
||||
//ZoneName := TWinControlAccess(child).GetDockCaption(child); // BookZoneName
|
||||
end
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
else begin
|
||||
//ZoneName := child.Name;
|
||||
ZoneName := DockSite.GetDockCaption(child); //default to child.Name
|
||||
end;
|
||||
ZoneRec.NameLen := Length(ZoneName);
|
||||
//write descriptor
|
||||
Stream.Write(ZoneRec, sizeof(ZoneRec));
|
||||
@ -1005,9 +1017,22 @@ begin
|
||||
end;
|
||||
|
||||
function TEasyTree.ReloadDockedControl(const AName: string): TControl;
|
||||
{$IFDEF new}
|
||||
var
|
||||
nb: TEasyBook;
|
||||
begin
|
||||
TWinControlAccess(DockSite).ReloadDockedControl(ZoneName, Result);
|
||||
if Pos(',', AName) > 0 then begin
|
||||
nb := NoteBookCreate(FDockSite);
|
||||
nb.SetDockCaption(AName);
|
||||
Result := nb;
|
||||
end else begin
|
||||
TWinControlAccess(DockSite).ReloadDockedControl(ZoneName???, Result);
|
||||
end;
|
||||
{$ELSE}
|
||||
begin
|
||||
TWinControlAccess(DockSite).ReloadDockedControl(AName, Result);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
procedure TEasyTree.LoadFromStream(Stream: TStream);
|
||||
|
||||
@ -1028,6 +1053,17 @@ procedure TEasyTree.LoadFromStream(Stream: TStream);
|
||||
DebugLn('reload done');
|
||||
end;
|
||||
|
||||
procedure ClearSite;
|
||||
var
|
||||
i: integer;
|
||||
ctl: TControl;
|
||||
begin
|
||||
for i := FDockSite.DockClientCount - 1 downto 0 do begin
|
||||
ctl := FDockSite.DockClients[i];
|
||||
ctl.ManualDock(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure MakeZones;
|
||||
var
|
||||
PrevZone, NewZone: TEasyZone;
|
||||
@ -1046,31 +1082,31 @@ procedure TEasyTree.LoadFromStream(Stream: TStream);
|
||||
NewCtl := ReloadDockedControl(ZoneName);
|
||||
//do we need a control in any case?
|
||||
if NewCtl = nil then begin
|
||||
//debug: create some control
|
||||
NewCtl := TPanel.Create(DockSite);
|
||||
NewCtl.Name := ZoneName;
|
||||
end;
|
||||
{$IFDEF old}
|
||||
try
|
||||
DebugLn('try rename %s into %s', [NewCtl.Name, ZoneName]);
|
||||
NewCtl.Name := ZoneName;
|
||||
if NewCtl is TEasyBook then
|
||||
//TEasyBook(NewCtl).SetDockCaption(ZoneName)
|
||||
DebugLn('!!!DockBook!!!')
|
||||
else
|
||||
NewCtl.Name := ZoneName;
|
||||
except
|
||||
DebugLn('error rename');
|
||||
end;
|
||||
NewCtl.Caption := ZoneName;
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
if NewCtl <> nil then begin
|
||||
{$IFDEF old}
|
||||
NewCtl.Align := alNone;
|
||||
NewCtl.Visible := True;
|
||||
NewCtl.Parent := DockSite;
|
||||
NewCtl.Width := ZoneRec.BottomRight.x;
|
||||
NewCtl.Height := ZoneRec.BottomRight.y;
|
||||
NewZone.ChildControl := NewCtl;
|
||||
{$ELSE}
|
||||
NewCtl.Visible := True;
|
||||
NewZone.ChildControl := NewCtl;
|
||||
SetReplacingControl(NewCtl);
|
||||
NewCtl.ManualDock(DockSite);
|
||||
NewCtl.Width := ZoneRec.BottomRight.x;
|
||||
NewCtl.Height := ZoneRec.BottomRight.y;
|
||||
{$ENDIF}
|
||||
end;
|
||||
end;
|
||||
while NewLvl < PrevLvl do begin
|
||||
@ -1090,6 +1126,8 @@ procedure TEasyTree.LoadFromStream(Stream: TStream);
|
||||
end;
|
||||
|
||||
begin
|
||||
//remove all docked controls
|
||||
ClearSite;
|
||||
//read record
|
||||
if GetRec > 0 then begin
|
||||
FTopZone.BR := ZoneRec.BottomRight;
|
||||
|
@ -108,6 +108,11 @@ type
|
||||
function GetControlTab(AControl: TControl): TTabButton;
|
||||
public
|
||||
StayDocked: boolean;
|
||||
destructor Destroy; override;
|
||||
{$IFDEF new}
|
||||
procedure SetDockCaption(const AName: string);
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
//procedure Register;
|
||||
@ -129,6 +134,32 @@ end;
|
||||
|
||||
{ TEasyDockBook }
|
||||
|
||||
destructor TEasyDockBook.Destroy;
|
||||
var
|
||||
i: integer;
|
||||
ctl: TControl;
|
||||
begin
|
||||
(* Problem with undocking?
|
||||
|
||||
The DockClients are not properly undocked when we (HostDockSite) are destroyed :-(
|
||||
|
||||
This code prevents an error when the DockClients are docked later,
|
||||
by definitely undocking all clients.
|
||||
|
||||
But then the bug will strike back when the notebook is destroyed at the
|
||||
end of the application.
|
||||
Fix: check ctl.ComponentState for csDestroying.
|
||||
*)
|
||||
for i := DockClientCount - 1 downto 0 do begin
|
||||
ctl := DockClients[i];
|
||||
if not (csDestroying in ctl.ComponentState) then
|
||||
ctl.ManualDock(nil);
|
||||
DebugLn('Undocked %s P=%p H=%p', [ctl.Name,
|
||||
pointer(ctl.Parent), pointer(ctl.HostDockSite)]);
|
||||
end;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TEasyDockBook.FormClose(Sender: TObject;
|
||||
var CloseAction: TCloseAction);
|
||||
var
|
||||
@ -149,9 +180,9 @@ begin
|
||||
ctl.ManualDock(nil);
|
||||
DebugLn('Undocked %s P=%p H=%p', [ctl.Name,
|
||||
pointer(ctl.Parent), pointer(ctl.HostDockSite)]);
|
||||
if ctl is TCustomForm then begin
|
||||
//if ctl is TCustomForm then begin
|
||||
//frm.Close;
|
||||
end;
|
||||
//end;
|
||||
end;
|
||||
//EndFormUpdate;
|
||||
{$ELSE}
|
||||
@ -310,6 +341,28 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF new}
|
||||
procedure TEasyDockBook.SetDockCaption(const AName: string);
|
||||
var
|
||||
lst: TStringList;
|
||||
i: integer;
|
||||
s: string;
|
||||
ctl: TControl;
|
||||
begin
|
||||
lst := TStringList.Create;
|
||||
lst.CommaText := AName;
|
||||
for i := 0 to lst.Count - 1 do begin
|
||||
s := lst.Strings[i];
|
||||
ReloadDockedControl(s, ctl);
|
||||
if ctl <> nil then begin
|
||||
ctl.Name := s;
|
||||
ctl.ManualDock(self, nil, alCustom);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
|
||||
procedure TEasyDockBook.ToolButton1Click(Sender: TObject);
|
||||
var
|
||||
btn: TTabButton absolute Sender;
|
||||
|
@ -76,12 +76,14 @@ type
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
procedure AddElasticSites(AForm: TCustomForm; Sides: sDockSides);
|
||||
//function CreateDockable(const AName: string; site: TWinControl; fMultiInst: boolean; fWrap: boolean = True): TWinControl;
|
||||
function CreateDockable(const AName: string; fMultiInst: boolean; fWrap: boolean = True): TWinControl;
|
||||
function MakeDockable(AForm: TWinControl; fWrap: boolean = True): TForm;
|
||||
procedure DumpSites;
|
||||
//persistence
|
||||
procedure LoadFromStream(Stream: TStream);
|
||||
procedure SaveToStream(Stream: TStream);
|
||||
function ReloadDockedControl(const AName: string; Site: TWinControl): TControl;
|
||||
end;
|
||||
|
||||
function TryRename(AComp: TComponent; const NewName: string): boolean;
|
||||
@ -210,21 +212,38 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
//function TDockMaster.CreateDockable(const AName: string; site: TWinControl;
|
||||
function TDockMaster.CreateDockable(const AName: string;
|
||||
fMultiInst: boolean; fWrap: boolean): TWinControl;
|
||||
var
|
||||
nb: TEasyBook;
|
||||
begin
|
||||
(* Create a dockable form, based on its name.
|
||||
Used also to restore a layout.
|
||||
|
||||
Not now:
|
||||
Used also to restore a DockBook (AName contains ",")
|
||||
(second chance, after LoadFromStream)
|
||||
|
||||
Options (to come or to be removed)
|
||||
fMultiInst allows to auto-create new instances (if True),
|
||||
otherwise an already existing instance is returned. (really returned?)
|
||||
*)
|
||||
//get the form
|
||||
Result := ReloadForm(AName, fMultiInst);
|
||||
if Result = nil then
|
||||
exit;
|
||||
MakeDockable(Result, fWrap);
|
||||
{$IFDEF new}
|
||||
if Pos(',', AName) > 0 then begin
|
||||
nb := NoteBookCreate(site); //DockSite???
|
||||
nb.SetDockCaption(AName);
|
||||
Result := nb;
|
||||
end else
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
begin
|
||||
//get the form
|
||||
Result := ReloadForm(AName, fMultiInst);
|
||||
if Result = nil then
|
||||
exit;
|
||||
MakeDockable(Result, fWrap);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDockMaster.MakeDockable(AForm: TWinControl; fWrap: boolean): TForm;
|
||||
@ -285,6 +304,52 @@ begin
|
||||
img.BringToFront;
|
||||
end;
|
||||
|
||||
function TDockMaster.ReloadDockedControl(const AName: string;
|
||||
Site: TWinControl): TControl;
|
||||
var
|
||||
i: integer;
|
||||
lst: TStringList;
|
||||
nb: TEasyBook absolute Result;
|
||||
s: string;
|
||||
ctl: TControl;
|
||||
//se: TSynEdit;
|
||||
begin
|
||||
(* Reload docked controls - forms or NoteBook
|
||||
NoteBook identified by comma separated names in AName,
|
||||
FileEditor identified by dot in name.
|
||||
*)
|
||||
if Pos(',', AName) > 0 then begin
|
||||
//restore NoteBook
|
||||
nb := NoteBookCreate(Site);
|
||||
lst := TStringList.Create;
|
||||
try
|
||||
lst.CommaText := AName;
|
||||
for i := 0 to lst.Count - 1 do begin
|
||||
s := lst[i];
|
||||
if Pos('.', s) > 0 then begin
|
||||
//restore editor
|
||||
{ TODO -cdocking : restore editor for file }
|
||||
end else begin
|
||||
ctl := ReloadForm(s, True); //try both multi and single instance
|
||||
if ctl <> nil then
|
||||
try
|
||||
ctl.ManualDock(nb);
|
||||
except
|
||||
DebugLn('!!!error docking ', s);
|
||||
{ TODO 1 : There exists a bug in the destruction of fDockBook (TWinControl).
|
||||
The docked clients retain the HostDockSite - which becomes invalid when destroyed! }
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
lst.Free;
|
||||
end;
|
||||
end else begin
|
||||
//restore control (form?)
|
||||
Result := ReloadForm(AName, True);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDockMaster.FormEndDock(Sender, Target: TObject; X, Y: Integer);
|
||||
var
|
||||
ctl: TControl;
|
||||
@ -880,13 +945,20 @@ end;
|
||||
|
||||
function TAppDockManager.ReloadDockedControl(const AName: string): TControl;
|
||||
begin
|
||||
(* Special connect to DockManager, and restore NoteBooks.
|
||||
*)
|
||||
if False then
|
||||
Result:=inherited ReloadDockedControl(AName); //asking DockSite (very bad idea)
|
||||
if assigned(DockMaster) then begin
|
||||
Result := DockMaster.CreateDockable(AName, True, False);
|
||||
end else begin
|
||||
//Result := DockMaster.CreateDockable(AName, FDockSite, True, False);
|
||||
//Result := DockMaster.CreateDockable(AName, True, False);
|
||||
Result := DockMaster.ReloadDockedControl(AName, FDockSite);
|
||||
end else begin //application default - search Application or Screen?
|
||||
//Owner.FindComponent(AControlName) as TControl;
|
||||
Result := Application.FindComponent(AName) as TControl;
|
||||
//Result := Application.FindComponent(AName) as TControl;
|
||||
Result := Screen.FindForm(AName);
|
||||
//if Result = nil then Result := 'T' + AName
|
||||
{ TODO -cdocking : load form by name, or create from typename }
|
||||
end;
|
||||
if Result <> nil then
|
||||
DebugLn('Reloaded %s.%s', [Result.Owner.Name, Result.Name]);
|
||||
|
Loading…
Reference in New Issue
Block a user