dockmanager example: some minor fixes, win32 still deserves an workaround

git-svn-id: trunk@22981 -
This commit is contained in:
dodi 2009-12-05 20:46:56 +00:00
parent c3417c257b
commit 09e0a01c88
6 changed files with 104 additions and 73 deletions

View File

@ -4,6 +4,9 @@
<PathDelim Value="\"/>
<Version Value="7"/>
<General>
<Flags>
<MainUnitHasUsesSectionForAllUnits Value="False"/>
</Flags>
<SessionStorage Value="InIDEConfig"/>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
@ -24,13 +27,16 @@
<LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<RequiredPackages Count="3">
<Item1>
<PackageName Value="EasyDockMgr"/>
<PackageName Value="SynEdit"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
<PackageName Value="EasyDockMgr"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="3">
<Unit0>
@ -63,6 +69,7 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)\"/>
<OtherUnitFiles Value="..\..\..\components\synedit\"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Other>

View File

@ -9,6 +9,8 @@ uses
Interfaces, // this includes the LCL widgetset
Forms, fMasterSite, fclientform, EasyDockMgr;
{$IFDEF WINDOWS}{$R MakeSite.rc}{$ENDIF}
begin
Application.Initialize;
Application.CreateForm(TMasterSite, MasterSite);

View File

@ -956,7 +956,7 @@ type
Level: byte;
Orientation: TDockOrientation;
//Width, Height: word;
NameLen: byte; //+chars
NameLen: integer; //+chars
end;
var
@ -1058,6 +1058,8 @@ procedure TEasyTree.LoadFromStream(Stream: TStream);
i: integer;
ctl: TControl;
begin
(* undock all currently docked clients, prior to restoring a layout
*)
for i := FDockSite.DockClientCount - 1 downto 0 do begin
ctl := FDockSite.DockClients[i];
ctl.ManualDock(nil);
@ -1086,20 +1088,6 @@ procedure TEasyTree.LoadFromStream(Stream: TStream);
NewCtl := TPanel.Create(DockSite);
NewCtl.Name := ZoneName;
end;
{$IFDEF old}
try
DebugLn('try rename %s into %s', [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
NewCtl.Visible := True;
NewZone.ChildControl := NewCtl;

View File

@ -38,6 +38,7 @@ Disallow undocking/floating of a NOT docked dockbook.
Fix: flag StayDocked.
Clients are not properly undocked on close!?
(see undockFix)
*)
(* Applications
@ -62,6 +63,12 @@ HostDockSite.UpdateDockCaption (provide composed dock caption)
{$mode objfpc}{$H+}
{$IFDEF WIN32}
{$DEFINE undockFix} //seems to be required for win32 widgetset
{$ELSE}
//no problems on Linux/gtk2
{$ENDIF}
interface
uses
@ -150,6 +157,7 @@ begin
end of the application.
Fix: check ctl.ComponentState for csDestroying.
*)
{$IFDEF undockFix}
for i := DockClientCount - 1 downto 0 do begin
ctl := DockClients[i];
if not (csDestroying in ctl.ComponentState) then
@ -157,6 +165,8 @@ begin
DebugLn('Undocked %s P=%p H=%p', [ctl.Name,
pointer(ctl.Parent), pointer(ctl.HostDockSite)]);
end;
{$ELSE}
{$ENDIF}
inherited Destroy;
end;
@ -171,7 +181,7 @@ begin
(* When an empty notebook is closed, it shall be freed.
Otherwise the clients must be handled (close forms)
This code is never reached???
This code is never reached when we are docked
*)
{$IFDEF new}
//BeginFormUpdate;
@ -349,6 +359,8 @@ var
s: string;
ctl: TControl;
begin
(* This is a suggestion for handling arguments in ReloadDockedControl.
*)
lst := TStringList.Create;
lst.CommaText := AName;
for i := 0 to lst.Count - 1 do begin

View File

@ -16,7 +16,7 @@ As with DockBook, closing docked forms results in Exceptions :-(
{$mode objfpc}{$H+}
{$DEFINE appdock}
{$DEFINE appdock} //using DockMaster/AppDockManager?
interface
@ -44,15 +44,14 @@ type
end;
var
//FloatingSite: TFloatingSite;
DockGrip: TPicture;
implementation
uses
LCLproc, //debugging only
EasyDockSite, //our DockManager
uMakeSite;
EasyDockSite, //EasyTree DockManager
uMakeSite; //AppDockManager
type
{$IFDEF appdock}

View File

@ -31,6 +31,10 @@ uses
fFloatingSite;
type
//events triggered from load/save docked controls
TOnReloadControl = function(const CtrlName: string; ASite: TWinControl): TControl of object;
TOnSaveControl = function(ACtrl: TControl): string of object;
sDockSides = TAlignSet;
TDockPanel = class(TPanel)
@ -65,6 +69,8 @@ type
function WrapDockable(Client: TControl): TFloatingSite;
private
LastPanel: TDockPanel; //last elastic panel created
FOnSave: TOnSaveControl;
FOnRestore: TOnReloadControl;
{$IFDEF ownPanels}
//elastic panels are in Components[]
{$ELSE}
@ -84,6 +90,8 @@ type
procedure LoadFromStream(Stream: TStream);
procedure SaveToStream(Stream: TStream);
function ReloadDockedControl(const AName: string; Site: TWinControl): TControl;
property OnSave: TOnSaveControl read FOnSave write FOnSave;
property OnRestore: TOnReloadControl read FOnRestore write FOnRestore;
end;
function TryRename(AComp: TComponent; const NewName: string): boolean;
@ -94,6 +102,7 @@ var
implementation
uses
//SynEdit, //try editor notebooks
LCLIntf, LCLProc;
type
@ -221,29 +230,15 @@ 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?)
*)
{$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;
//get the form
Result := ReloadForm(AName, fMultiInst);
if Result = nil then
exit;
MakeDockable(Result, fWrap);
end;
function TDockMaster.MakeDockable(AForm: TWinControl; fWrap: boolean): TForm;
@ -312,11 +307,12 @@ var
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.
Called from AppDockManager on ReloadDockedControl.
NoteBook identified by comma separated names in AName.
FileEditor identified by dot in name? (not here)
*)
if Pos(',', AName) > 0 then begin
//restore NoteBook
@ -326,27 +322,24 @@ begin
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
//try handler
ctl := nil;
if assigned(FOnRestore) then
ctl := FOnRestore(AName, nb);
if ctl = nil then
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;
ctl.ManualDock(nb);
end;
finally
lst.Free;
end;
end else begin
//restore control (form?)
Result := ReloadForm(AName, True);
Result := nil;
if assigned(FOnRestore) then
Result := FOnRestore(AName, Site);
if Result = nil then
Result := ReloadForm(AName, True);
end;
end;
@ -357,16 +350,22 @@ var
begin
(* Handler for Form.OnEndDock.
When a form becomes floating, dock immediately into a new floating host docksite.
Prevent wrapping controls in destruction?
Since this event is raised during dragging, we should not try to wrap a control
that still has its (old?) HostDockSite set. If Nil it seems to be acceptable
to set a new dock site, but this would be easier if we simply could update the
Target.
Made WrapDockable check for detailed conditions.
*)
if Target <> nil then
exit; //docked, not floating
ctl := Sender as TControl;
if ctl.HostDockSite = nil then begin
//DebugLn('--- floating');
WrapDockable(ctl);
end else begin
//DebugLn('--- in ' + HostDockSite.Name);
end;
//if not (csDestroying in ctl.ComponentState) and (ctl.HostDockSite = nil) then begin
//if (ctl.HostDockSite = nil) then
WrapDockable(ctl);
end;
type
@ -569,14 +568,16 @@ begin
Result type? (a TWinControl is sufficient as a DockSite)
*)
//search existing forms
Result := Screen.FindForm(AName);
if Result <> nil then
exit; //found it
if AName <> '' then begin
Result := Screen.FindForm(AName);
if Result <> nil then
exit; //found it
end;
//check if Factory can provide the form
if assigned(Factory) then begin
TWinControlAccess(Factory).ReloadDockedControl(AName, ctl);
if ctl is TCustomForm then begin
Result := TCustomForm(ctl);
if ctl is TWinControl then begin
Result := TWinControl(ctl);
exit;
end; //else assume that we should do everything?
FreeAndNil(ctl);
@ -584,7 +585,7 @@ begin
//search/create ourselves
fo := Owner; //our owner also owns the forms
if AName = '' then begin
Result := TForm.Create(fo); //named Form1, Form2...
Result := TForm.Create(fo); //named Form1, Form2... - not now???
end else begin
//create new instance
if fMultiInst then
@ -603,19 +604,41 @@ begin
if Result.Name <> AName then
TryRename(Result, AName);
end;
Result.Visible := True; //required for docking
end;
function TDockMaster.WrapDockable(Client: TControl): TFloatingSite;
var
Site: TFloatingSite absolute Result;
ctl: TControlAccess absolute Client;
r: TRect;
begin
(* Wrap a control into a floating site.
Prevent wrapping under certain conditions:
- client under destruction
- client already docked
- invisible client?
*)
if (csDestroying in Client.ComponentState)
or assigned(Client.HostDockSite) //already wrapped
or not Client.Visible //or force visible (below)?
then
exit(nil); //do nothing with client under destruction!
Site := TFloatingSite.Create(Self); //we own the new site
//Site := TFloatingSite.Create(Application);
try
{$IFDEF old}
Site.BoundsRect := Client.BoundsRect; //the new position and extension
{$ELSE}
//keep undocked extent
r := Client.BoundsRect;
r.Right := r.Left + Client.UndockWidth;
r.Bottom := r.Top + Client.UndockHeight;
//site.ClientRect := r;
Site.BoundsRect := r;
{$ENDIF}
Client.Align := alClient;
Client.Visible := True; //otherwise docking may be rejected
//Client.Visible := True; //otherwise docking may be rejected
Client.ManualDock(Site);
except
DebugLn('error WrapDockable: ' + Client.Name);