mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-23 01:39:31 +02:00
dockmanager example: some minor fixes, win32 still deserves an workaround
git-svn-id: trunk@22981 -
This commit is contained in:
parent
c3417c257b
commit
09e0a01c88
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user