dockmanager example: cleanup, added and use uMiniRestore

git-svn-id: trunk@22544 -
This commit is contained in:
dodi 2009-11-12 10:11:03 +00:00
parent 6b0be3249d
commit d8b319efd5
13 changed files with 258 additions and 140 deletions

1
.gitattributes vendored
View File

@ -2797,6 +2797,7 @@ examples/dockmanager/package/ffloatingsite.lfm svneol=native#text/plain
examples/dockmanager/package/ffloatingsite.lrs svneol=native#text/plain examples/dockmanager/package/ffloatingsite.lrs svneol=native#text/plain
examples/dockmanager/package/ffloatingsite.pas svneol=native#text/pascal examples/dockmanager/package/ffloatingsite.pas svneol=native#text/pascal
examples/dockmanager/package/pen.ico -text examples/dockmanager/package/pen.ico -text
examples/dockmanager/package/uminirestore.pas svneol=native#text/pascal
examples/dockmanager/package/zoneheader.inc svneol=native#text/pascal examples/dockmanager/package/zoneheader.inc svneol=native#text/pascal
examples/dockmanager/patches/FloatHostDockable.patch svneol=native#text/pascal examples/dockmanager/patches/FloatHostDockable.patch svneol=native#text/pascal
examples/dockmanager/patches/NewClients.patch svneol=native#text/pascal examples/dockmanager/patches/NewClients.patch svneol=native#text/pascal

View File

@ -14,7 +14,6 @@ uses
begin begin
Application.Initialize; Application.Initialize;
Application.CreateForm(TEditorSite, EditorSite); Application.CreateForm(TEditorSite, EditorSite);
Application.CreateForm(TViewWindow, ViewWindow);
Application.Run; Application.Run;
end. end.

View File

@ -1,5 +1,3 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TViewWindow','FORMDATA',[ LazarusResources.Add('TViewWindow','FORMDATA',[
'TPF0'#11'TViewWindow'#10'ViewWindow'#4'Left'#3'A'#1#6'Height'#3','#1#3'Top'#3 'TPF0'#11'TViewWindow'#10'ViewWindow'#4'Left'#3'A'#1#6'Height'#3','#1#3'Top'#3
+'L'#1#5'Width'#3#144#1#7'Caption'#6#10'ViewWindow'#12'ClientHeight'#3','#1#11 +'L'#1#5'Width'#3#144#1#7'Caption'#6#10'ViewWindow'#12'ClientHeight'#3','#1#11

View File

@ -1,4 +1,12 @@
unit fClientForm; unit fClientForm;
(* A form for easy docking into multi-client floating sites.
When the form becomes floating, it docks itself into a new floating dockhost
site, that can accept further clients.
Since not all window managers allow to dock forms,
docking is allowed only from a dedicated (pin) icon.
*)
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
@ -21,13 +29,13 @@ type
{ public declarations } { public declarations }
end; end;
var //var ViewWindow: TViewWindow; //useless
ViewWindow: TViewWindow;
implementation implementation
uses uses
LCLProc, fFloatingSite; //LCLProc, //debugging only
fFloatingSite;
{ TViewWindow } { TViewWindow }
@ -35,18 +43,24 @@ procedure TViewWindow.FormEndDock(Sender, Target: TObject; X, Y: Integer);
var var
Site: TFloatingSite; Site: TFloatingSite;
begin begin
(* When we become floating, dock immediately into a new floating host docksite.
*)
if HostDockSite = nil then begin if HostDockSite = nil then begin
DebugLn('--- floating'); //DebugLn('--- floating');
Site := TFloatingSite.Create(Application); Site := TFloatingSite.Create(Application); //the new site
Site.BoundsRect := self.BoundsRect; Site.BoundsRect := self.BoundsRect; //the new position and extension
ManualDock(Site); ManualDock(Site);
end else end else begin
DebugLn('--- in ' + HostDockSite.Name); //DebugLn('--- in ' + HostDockSite.Name);
end;
end; end;
procedure TViewWindow.Image1MouseMove(Sender: TObject; Shift: TShiftState; procedure TViewWindow.Image1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer); X, Y: Integer);
begin begin
(* The mouse is moved over our docking gadget.
When the left button is pressed, start dragging (for docking).
*)
if ssLeft in Shift then begin if ssLeft in Shift then begin
BeginDrag(False); BeginDrag(False);
end; end;

View File

@ -11,6 +11,7 @@ inherited EditorSite: TEditorSite
OnDeactivate = FormDeactivate OnDeactivate = FormDeactivate
OnHide = FormHide OnHide = FormHide
OnResize = FormResize OnResize = FormResize
OnWindowStateChange = FormWindowStateChange
ShowInTaskBar = stAlways ShowInTaskBar = stAlways
inherited pnlLeft: TPanel inherited pnlLeft: TPanel
Height = 256 Height = 256

View File

@ -1,40 +1,39 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TEditorSite','FORMDATA',[ LazarusResources.Add('TEditorSite','FORMDATA',[
'TPF0'#241#11'TEditorSite'#10'EditorSite'#4'Left'#3'b'#1#6'Height'#3','#1#5'W' 'TPF0'#241#11'TEditorSite'#10'EditorSite'#4'Left'#3'b'#1#6'Height'#3','#1#5'W'
+'idth'#3#144#1#7'Caption'#6#10'EditorSite'#12'ClientHeight'#3#25#1#11'Client' +'idth'#3#144#1#7'Caption'#6#10'EditorSite'#12'ClientHeight'#3#25#1#11'Client'
+'Width'#3#144#1#4'Menu'#7#9'MainMenu1'#10'OnActivate'#7#12'FormActivate'#8'O' +'Width'#3#144#1#4'Menu'#7#9'MainMenu1'#10'OnActivate'#7#12'FormActivate'#8'O'
+'nCreate'#7#10'FormCreate'#12'OnDeactivate'#7#14'FormDeactivate'#6'OnHide'#7 +'nCreate'#7#10'FormCreate'#12'OnDeactivate'#7#14'FormDeactivate'#6'OnHide'#7
+#8'FormHide'#8'OnResize'#7#10'FormResize'#13'ShowInTaskBar'#7#8'stAlways'#0 +#8'FormHide'#8'OnResize'#7#10'FormResize'#19'OnWindowStateChange'#7#21'FormW'
+#241#6'TPanel'#7'pnlLeft'#6'Height'#3#0#1#0#0#241#9'TSplitter'#9'splitLeft'#6 +'indowStateChange'#13'ShowInTaskBar'#7#8'stAlways'#0#241#6'TPanel'#7'pnlLeft'
+'Height'#3#0#1#0#0#241#6'TPanel'#8'pnlRight'#4'Left'#3#144#1#6'Height'#3#0#1 +#6'Height'#3#0#1#0#0#241#9'TSplitter'#9'splitLeft'#6'Height'#3#0#1#0#0#241#6
+#0#0#241#6'TPanel'#9'pnlBottom'#3'Top'#3#4#1#5'Width'#3#144#1#0#0#241#9'TSpl' +'TPanel'#8'pnlRight'#4'Left'#3#144#1#6'Height'#3#0#1#0#0#241#6'TPanel'#9'pnl'
+'itter'#10'splitRight'#4'Left'#3#140#1#6'Height'#3#0#1#0#0#241#10'TStatusBar' +'Bottom'#3'Top'#3#4#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#10'splitRight'#4
+#10'StatusBar1'#3'Top'#3#5#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#11'splitB' +'Left'#3#140#1#6'Height'#3#0#1#0#0#241#10'TStatusBar'#10'StatusBar1'#3'Top'#3
+'ottom'#3'Top'#3#0#1#5'Width'#3#144#1#0#0#242#2#7#9'TMainMenu'#9'MainMenu1'#4 +#5#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#11'splitBottom'#3'Top'#3#0#1#5'Wi'
+'left'#3#240#0#3'top'#2'0'#0#9'TMenuItem'#6'mnFile'#7'Caption'#6#5'&File'#0#9 +'dth'#3#144#1#0#0#242#2#7#9'TMainMenu'#9'MainMenu1'#4'left'#3#240#0#3'top'#2
+'TMenuItem'#6'mnOpen'#7'Caption'#6#5'&Open'#7'OnClick'#7#11'mnOpenClick'#0#0 +'0'#0#9'TMenuItem'#6'mnFile'#7'Caption'#6#5'&File'#0#9'TMenuItem'#6'mnOpen'#7
+#9'TMenuItem'#9'MenuItem1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#6'mnExit'#7'Ca' +'Caption'#6#5'&Open'#7'OnClick'#7#11'mnOpenClick'#0#0#9'TMenuItem'#9'MenuIte'
+'ption'#6#5'E&xit'#7'OnClick'#7#11'mnExitClick'#0#0#0#9'TMenuItem'#6'mnView' +'m1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#6'mnExit'#7'Caption'#6#5'E&xit'#7'On'
+#7'Caption'#6#5'&View'#0#9'TMenuItem'#9'MenuItem2'#7'Caption'#6#16'Object In' +'Click'#7#11'mnExitClick'#0#0#0#9'TMenuItem'#6'mnView'#7'Caption'#6#5'&View'
+'spector'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem3'#7'Cap' +#0#9'TMenuItem'#9'MenuItem2'#7'Caption'#6#16'Object Inspector'#7'OnClick'#7
+'tion'#6#8'Messages'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuI' +#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem3'#7'Caption'#6#8'Messages'#7
+'tem4'#7'Caption'#6#13'Code Explorer'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'T' +'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem4'#7'Caption'#6#13
+'MenuItem'#9'MenuItem5'#7'Caption'#6#9'ToDo List'#7'OnClick'#7#13'ViewMenuCl' +'Code Explorer'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem5'
+'ick'#0#0#9'TMenuItem'#9'MenuItem6'#7'Caption'#6#13'Debug windows'#0#9'TMenu' +#7'Caption'#6#9'ToDo List'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9
+'Item'#9'MenuItem7'#7'Caption'#6#7'Watches'#7'OnClick'#7#13'ViewMenuClick'#0 +'MenuItem6'#7'Caption'#6#13'Debug windows'#0#9'TMenuItem'#9'MenuItem7'#7'Cap'
+#0#9'TMenuItem'#9'MenuItem8'#7'Caption'#6#11'BreakPoints'#7'OnClick'#7#13'Vi' +'tion'#6#7'Watches'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuIt'
+'ewMenuClick'#0#0#9'TMenuItem'#9'MenuItem9'#7'Caption'#6#15'Local Variables' +'em8'#7'Caption'#6#11'BreakPoints'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMen'
+#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem10'#7'Caption'#6 +'uItem'#9'MenuItem9'#7'Caption'#6#15'Local Variables'#7'OnClick'#7#13'ViewMe'
+#9'Registers'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem11' +'nuClick'#0#0#9'TMenuItem'#10'MenuItem10'#7'Caption'#6#9'Registers'#7'OnClic'
+#7'Caption'#6#10'Call Stack'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem' +'k'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem11'#7'Caption'#6#10'Call'
+#10'MenuItem12'#7'Caption'#6#9'Assembler'#7'OnClick'#7#13'ViewMenuClick'#0#0 +' Stack'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem12'#7'Ca'
+#9'TMenuItem'#10'MenuItem13'#7'Caption'#6#12'Debug Output'#7'OnClick'#7#13'V' +'ption'#6#9'Assembler'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'Me'
+'iewMenuClick'#0#0#0#0#9'TMenuItem'#10'MenuItem14'#7'Caption'#6#8'&Windows'#0 +'nuItem13'#7'Caption'#6#12'Debug Output'#7'OnClick'#7#13'ViewMenuClick'#0#0#0
+#9'TMenuItem'#12'mnWindowDump'#7'Caption'#6#5'&Dump'#7'OnClick'#7#17'mnWindo' +#0#9'TMenuItem'#10'MenuItem14'#7'Caption'#6#8'&Windows'#0#9'TMenuItem'#12'mn'
+'wDumpClick'#0#0#9'TMenuItem'#10'mnMinimize'#7'Caption'#6#12'Minimize all'#7 +'WindowDump'#7'Caption'#6#5'&Dump'#7'OnClick'#7#17'mnWindowDumpClick'#0#0#9
+'OnClick'#7#15'mnMinimizeClick'#0#0#9'TMenuItem'#9'mnRestore'#7'Caption'#6#11 +'TMenuItem'#10'mnMinimize'#7'Caption'#6#12'Minimize all'#7'OnClick'#7#15'mnM'
+'Restore all'#7'OnClick'#7#14'mnRestoreClick'#0#0#0#0#242#2#8#11'TOpenDialog' +'inimizeClick'#0#0#9'TMenuItem'#9'mnRestore'#7'Caption'#6#11'Restore all'#7
+#11'OpenDialog1'#6'Filter'#6#25'*.pas|*.pas|All Files|*.*'#4'left'#3'5'#1#3 +'OnClick'#7#14'mnRestoreClick'#0#0#0#0#242#2#8#11'TOpenDialog'#11'OpenDialog'
+'top'#2'0'#0#0#0 +'1'#6'Filter'#6#25'*.pas|*.pas|All Files|*.*'#4'left'#3'5'#1#3'top'#2'0'#0#0
+#0
]); ]);

View File

@ -1,7 +1,7 @@
unit fEditorSite; unit fEditorSite;
(* EditorSite by DoDi <DrDiettrich1@aol.com> (* EditorSite by DoDi <DrDiettrich1@aol.com>
mimics an Delphi editor window, that allows to Mimics an Delphi editor window, that allows to dock other windows to it,
- dock other windows to it with several extensions:
- optionally enlarging the window - optionally enlarging the window
- detach a page into a new editor window - detach a page into a new editor window
- move a page into a different editor window - move a page into a different editor window
@ -10,24 +10,26 @@ mimics an Delphi editor window, that allows to
Some quirks should be handled properly in a true IDE implementation: Some quirks should be handled properly in a true IDE implementation:
For simplicity an IDE main menu has been added to the main window, For simplicity an IDE main menu has been added to the main window,
that allows to create several project window dummies, that allows to create several project (View) window dummies,
which can be docked to the editor window. which can be docked to each other, or to the editor window.
Mixed docking of editor pages and View windows is not blocked, so that Mixed docking of editor pages and View windows (currently) is not blocked,
you can have multiple edit views within the editor window. so that you can have multiple edit views within the editor window.
Secondary editor windows should have the same docking capabilities. Secondary editor windows should have the same docking capabilities.
(not yet)
Known bugs: Known bugs:
- The IDE suspects dangling references - KEEP these references! - The IDE suspects dangling references - KEEP these references!
Please report if you know how to fix this issue. Please report if you know how to fix this issue.
+ Problems with non-form project windows.
Since the IDE windows are all forms, we only handle this case now.
*) *)
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
{$DEFINE clientform} //clients are forms? {$DEFINE minimize} //test application minimize/restore
{.$DEFINE stdfloat} //using standard floating host?
interface interface
@ -66,6 +68,7 @@ type
procedure FormDeactivate(Sender: TObject); procedure FormDeactivate(Sender: TObject);
procedure FormHide(Sender: TObject); procedure FormHide(Sender: TObject);
procedure FormResize(Sender: TObject); procedure FormResize(Sender: TObject);
procedure FormWindowStateChange(Sender: TObject);
procedure mnMinimizeClick(Sender: TObject); procedure mnMinimizeClick(Sender: TObject);
procedure mnRestoreClick(Sender: TObject); procedure mnRestoreClick(Sender: TObject);
procedure mnWindowDumpClick(Sender: TObject); procedure mnWindowDumpClick(Sender: TObject);
@ -87,6 +90,7 @@ implementation
uses uses
LCLProc, LCLProc,
uMiniRestore,
fClientForm, fClientForm,
fFloatingSite; fFloatingSite;
@ -102,30 +106,21 @@ begin
FEdit.Parent := self; FEdit.Parent := self;
FEdit.Visible := True; FEdit.Visible := True;
FEdit.DragMode := dmManual; //disallow undocking FEdit.DragMode := dmManual; //disallow undocking
//FEdit.pnlDock.DragMode := dmManual;
FAutoExpand := True;
end; end;
function TEditorSite.CreateDockable(const cap: string): TWinControl; function TEditorSite.CreateDockable(const cap: string): TWinControl;
var var
Site: TFloatingSite; Site: TFloatingSite;
{$IFDEF clientform}
Client: TViewWindow; Client: TViewWindow;
{$ELSE}
Client: TWinControl;
{$ENDIF}
begin begin
{$IFDEF clientform} (* Create a client form, and dock it into a floating dock host site.
We must force docking here, later the client will dock itself into
a float host site, when it becomes floating.
*)
//create the form
Client := TViewWindow.Create(Application); Client := TViewWindow.Create(Application);
Client.Label1.Caption := cap; Client.Label1.Caption := cap;
Client.Visible := True; Client.Visible := True;
//Client.FloatingDockSiteClass := TFloatingSite;
{$ELSE}
Client := TPanel.Create(self);
Client.DragMode := dmAutomatic;
Client.DragKind := dkDock;
Client.Visible := True;
{$ENDIF}
//name it //name it
Client.Caption := cap; Client.Caption := cap;
try try
@ -133,19 +128,9 @@ begin
except except
//here: simply ignore duplicate name //here: simply ignore duplicate name
end; end;
{$IFDEF stdfloat}
Client.ManualDock(nil);
{$ELSE}
//Client.FloatingDockSiteClass := TFloatingSite; //Client.FloatingDockSiteClass := TFloatingSite;
{$IFDEF old}
//ManualFloat doesn't work as expected :-(
//Client.Align := alClient; //required for proper docking
Client.ManualFloat(Rect(200,200, 400,400));
{$ELSE}
Site := TFloatingSite.Create(Application); Site := TFloatingSite.Create(Application);
Client.ManualDock(Site, nil, alClient); Client.ManualDock(Site, nil, alClient);
{$ENDIF}
{$ENDIF}
Result := Client; Result := Client;
end; end;
@ -158,11 +143,31 @@ begin
CreateDockable(item.Caption); CreateDockable(item.Caption);
end; end;
function TEditorSite.OpenFile(const FileName: string): TObject;
begin
//todo: load the file
CurEdit := TEditPage.Create(self);
CurEdit.LoadFile(FileName);
CurEdit.ManualDock(FEdit);
//make it visible
Result := CurEdit; //or what?
end;
procedure TEditorSite.mnOpenClick(Sender: TObject);
begin
if OpenDialog1.Execute then begin
OpenFile(OpenDialog1.FileName);
end;
end;
procedure TEditorSite.mnExitClick(Sender: TObject); procedure TEditorSite.mnExitClick(Sender: TObject);
begin begin
Close; Close;
end; end;
// ----------- application window handling -------------
procedure TEditorSite.FormActivate(Sender: TObject); procedure TEditorSite.FormActivate(Sender: TObject);
begin begin
//DebugLn('--- Activate'); //DebugLn('--- Activate');
@ -175,13 +180,18 @@ end;
procedure TEditorSite.FormHide(Sender: TObject); procedure TEditorSite.FormHide(Sender: TObject);
begin begin
DebugLn('--- FormHide'); //not when minimized manually (win32) //DebugLn('--- FormHide'); //not when minimized manually (win32)
//mnMinimizeClick(Sender); //mnMinimizeClick(Sender);
end; end;
procedure TEditorSite.FormResize(Sender: TObject); procedure TEditorSite.FormResize(Sender: TObject);
begin begin
DebugLn('--- Resize'); //DebugLn('--- Resize');
end;
procedure TEditorSite.FormWindowStateChange(Sender: TObject);
begin
DoMiniRestore;
end; end;
procedure TEditorSite.mnMinimizeClick(Sender: TObject); procedure TEditorSite.mnMinimizeClick(Sender: TObject);
@ -189,6 +199,7 @@ var
i: integer; i: integer;
f: TForm; f: TForm;
begin begin
{$IFDEF minimize}
for i := 0 to Screen.FormCount - 1 do begin for i := 0 to Screen.FormCount - 1 do begin
f := Screen.Forms[i]; f := Screen.Forms[i];
//if f = self then f.WindowState := wsMinimized else //if f = self then f.WindowState := wsMinimized else
@ -197,18 +208,16 @@ begin
f.WindowState := wsMinimized; f.WindowState := wsMinimized;
end; end;
end; end;
{$ELSE}
{$ENDIF}
end; end;
procedure TEditorSite.mnRestoreClick(Sender: TObject); procedure TEditorSite.mnRestoreClick(Sender: TObject);
begin begin
{$IFDEF minimize}
WindowState := wsNormal; WindowState := wsNormal;
end; {$ELSE}
{$ENDIF}
procedure TEditorSite.mnOpenClick(Sender: TObject);
begin
if OpenDialog1.Execute then begin
OpenFile(OpenDialog1.FileName);
end;
end; end;
procedure TEditorSite.mnWindowDumpClick(Sender: TObject); procedure TEditorSite.mnWindowDumpClick(Sender: TObject);
@ -243,16 +252,6 @@ begin
DebugLn('---'); DebugLn('---');
end; end;
function TEditorSite.OpenFile(const FileName: string): TObject;
begin
//todo: load the file
CurEdit := TEditPage.Create(self);
CurEdit.LoadFile(FileName);
CurEdit.ManualDock(FEdit);
//make it visible
Result := CurEdit; //or what?
end;
initialization initialization
{$I feditorsite.lrs} {$I feditorsite.lrs}

View File

@ -17,7 +17,7 @@
<Description Value="EasyDocking Manager and Notebook"/> <Description Value="EasyDocking Manager and Notebook"/>
<License Value="LGPL"/> <License Value="LGPL"/>
<Version Major="1"/> <Version Major="1"/>
<Files Count="8"> <Files Count="9">
<Item1> <Item1>
<Filename Value="easydocksite.pas"/> <Filename Value="easydocksite.pas"/>
<UnitName Value="EasyDockSite"/> <UnitName Value="EasyDockSite"/>
@ -51,6 +51,10 @@
<HasRegisterProc Value="True"/> <HasRegisterProc Value="True"/>
<UnitName Value="fElasticSite"/> <UnitName Value="fElasticSite"/>
</Item8> </Item8>
<Item9>
<Filename Value="uminirestore.pas"/>
<UnitName Value="uMiniRestore"/>
</Item9>
</Files> </Files>
<Type Value="RunAndDesignTime"/> <Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="2"> <RequiredPkgs Count="2">

View File

@ -7,7 +7,8 @@ unit EasyDockMgr;
interface interface
uses uses
EasyDockSite, fDockBook, fFloatingSite, fElasticSite, LazarusPackageIntf; EasyDockSite, fDockBook, fFloatingSite, fElasticSite, uMiniRestore,
LazarusPackageIntf;
implementation implementation

View File

@ -6,9 +6,7 @@ object FloatingSite: TFloatingSite
Caption = 'FloatingSite' Caption = 'FloatingSite'
DockSite = True DockSite = True
OnDockDrop = FormDockDrop OnDockDrop = FormDockDrop
OnDockOver = FormDockOver
OnUnDock = FormUnDock OnUnDock = FormUnDock
ShowInTaskBar = stNever
UseDockManager = True UseDockManager = True
LCLVersion = '0.9.29' LCLVersion = '0.9.29'
Visible = True Visible = True

View File

@ -3,7 +3,6 @@
LazarusResources.Add('TFloatingSite','FORMDATA',[ LazarusResources.Add('TFloatingSite','FORMDATA',[
'TPF0'#13'TFloatingSite'#12'FloatingSite'#4'Left'#3#175#1#6'Height'#3#9#1#3'T' 'TPF0'#13'TFloatingSite'#12'FloatingSite'#4'Left'#3#175#1#6'Height'#3#9#1#3'T'
+'op'#3#242#1#5'Width'#3'y'#1#7'Caption'#6#12'FloatingSite'#8'DockSite'#9#10 +'op'#3#242#1#5'Width'#3'y'#1#7'Caption'#6#12'FloatingSite'#8'DockSite'#9#10
+'OnDockDrop'#7#12'FormDockDrop'#10'OnDockOver'#7#12'FormDockOver'#8'OnUnDock' +'OnDockDrop'#7#12'FormDockDrop'#8'OnUnDock'#7#10'FormUnDock'#14'UseDockManag'
+#7#10'FormUnDock'#13'ShowInTaskBar'#7#7'stNever'#14'UseDockManager'#9#10'LCL' +'er'#9#10'LCLVersion'#6#6'0.9.29'#7'Visible'#9#0#0
+'Version'#6#6'0.9.29'#7'Visible'#9#0#0
]); ]);

View File

@ -1,8 +1,13 @@
unit fFloatingSite; unit fFloatingSite;
(* Floating dock host. (* Floating dock host.
Host one or more docked clients.
To distinguish multiple clients, use the form header style (named caption).
Destroy the site on the last undock.
ToDo: Handle flaws of the Delphi docking model (improper undock).
- show summary caption - Disallow TControls to float (else nothing but trouble).
- For the IDE, floating client forms must wrap themselves into a new
host site, to allow for continued docking of other clients.
*) *)
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
@ -16,8 +21,6 @@ type
TFloatingSite = class(TForm) TFloatingSite = class(TForm)
procedure FormDockDrop(Sender: TObject; Source: TDragDockObject; procedure FormDockDrop(Sender: TObject; Source: TDragDockObject;
X, Y: Integer); X, Y: Integer);
procedure FormDockOver(Sender: TObject; Source: TDragDockObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure FormUnDock(Sender: TObject; Client: TControl; procedure FormUnDock(Sender: TObject; Client: TControl;
NewTarget: TWinControl; var Allow: Boolean); NewTarget: TWinControl; var Allow: Boolean);
private private
@ -34,8 +37,8 @@ var
implementation implementation
uses uses
EasyDockSite, LCLproc, //debugging only
LCLproc; EasyDockSite; //our DockManager
{ TFloatingSite } { TFloatingSite }
@ -45,6 +48,9 @@ var
s: string; s: string;
ctl: TControl; ctl: TControl;
begin begin
(* Show the combined captions of all clients.
Exclude client to be undocked.
*)
s := ''; s := '';
for i := 0 to DockClientCount - 1 do begin for i := 0 to DockClientCount - 1 do begin
ctl := DockClients[i]; ctl := DockClients[i];
@ -52,63 +58,54 @@ begin
s := s + GetDockCaption(ctl) + ', '; s := s + GetDockCaption(ctl) + ', ';
end; end;
SetLength(s, Length(s) - 2); //strip trailing ", " SetLength(s, Length(s) - 2); //strip trailing ", "
Caption := s; //GetDockCaption(self); Caption := s;
end; end;
procedure TFloatingSite.FormDockDrop(Sender: TObject; Source: TDragDockObject; procedure TFloatingSite.FormDockDrop(Sender: TObject; Source: TDragDockObject;
X, Y: Integer); X, Y: Integer);
begin begin
(* Update the caption.
*)
AdjustCaption(nil); AdjustCaption(nil);
end; end;
procedure TFloatingSite.FormDockOver(Sender: TObject; Source: TDragDockObject;
X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
//DebugLn('DockOver');
end;
procedure TFloatingSite.FormUnDock(Sender: TObject; Client: TControl; procedure TFloatingSite.FormUnDock(Sender: TObject; Client: TControl;
NewTarget: TWinControl; var Allow: Boolean); NewTarget: TWinControl; var Allow: Boolean);
begin begin
(* Check for undock last client: (* Check for undock last client, if allowed kill empty docksite.
- disallow to Nil (move window?)
- if allowed, kill empty docksite.
Refresh caption after undock. Refresh caption after undock.
Shit: in both cases the docking management does the opposite of what it should do :-( Shit: in both cases the docking management does the opposite of what it should do :-(
When the last control is dragged away, it's hosted in a *new* site. When the last control is dragged away, it's hosted in a *new* site.
When a second control is dragged away, the entire site is moved. When a second control is dragged away, the entire site is moved.
Fix: disallow TControls to become floating.
*) *)
//try to distinguish between TControl and TWinControl (TCustomForm?)
Allow := (NewTarget <> nil) or (Client is TWinControl); //seems to be safe
if not Allow then
exit; //all done
if DockClientCount <= 1 then begin if DockClientCount <= 1 then begin
if NewTarget = nil then begin Release; //destroy empty site
//Allow := False; //deny
Allow := True; //move form - where???
Release;
end else
Release;
end else begin end else begin
//allow float - action required? AdjustCaption(Client); //update caption, excluding removed client
(* strange behaviour: client is undocked, but stays in the site. DockManager.ResetBounds(True); //required with gtk2!?
The site is moved to the drop location.
*)
//Allow := NewTarget <> nil; //simply disallow undock to floating state (for now)
Allow := True; //bug!!!
//DragManager. - not helpful - where is the DockObject???
end;
if Allow then begin
AdjustCaption(Client);
end; end;
end; end;
procedure TFloatingSite.Loaded; procedure TFloatingSite.Loaded;
begin begin
(* select and configure the docking manager.
*)
inherited Loaded; inherited Loaded;
if DockManager = nil then if DockManager = nil then
DockManager := TEasyTree.Create(self); DockManager := TEasyTree.Create(self);
if DockManager is TEasyTree then begin if DockManager is TEasyTree then begin
TEasyTree(DockManager).HideSingleCaption := True; //adjust as desired (order required!?)
TEasyTree(DockManager).SetStyle(hsForm); TEasyTree(DockManager).HideSingleCaption := True; //only show headers for multiple clients
TEasyTree(DockManager).SetStyle(hsForm); //show client name in the header
end; end;
end; end;

View File

@ -0,0 +1,108 @@
unit uMiniRestore;
(* Attempt to fix taskbar issues, related to application minimize/restore.
Symptoms
--------
On Linux/KDE all forms are listed in the taskbar, while only the main form
should be found there. This makes the restauration of an entire application
almost impossible, because all forms must be restored manually! :-(
The Application.OnMinimize/Restore handlers are never invoked, because the
according methods in TApplication are never invoked.
Usage
-----
In your MainForm.OnWindowStateChange call DoMiniRestore,
or set the handler to DummyInstance.MiniRestore.
Approach
--------
This workaround hides all forms when the main form is minimized, and
restores them when the main form is restored. [Note: hide, not minimize!]
(a single click on the taskbar entry of the application is sufficient :-)
This feature is enabled on the first minimize of the main form, and eventually
should be disabled when the main form is closed, to prevent side effects.
Currently the auto-hidden windows are only hidden (Visbible=False).
A combination with other properties could be used, to distinguish these from
intentionally hidden windows.
Screen.ActiveForm seems to reflect the focused form in OnWindowStateChange
of the main form. This form is remembered and focused after a restore.
*)
{$mode objfpc}{$H+}
interface
uses
Forms;
type
TMiniRestore = class
class procedure MiniRestore(Sender: TObject);
end;
procedure DoMiniRestore;
var
DummyInstance: TMiniRestore;//never instantiated
EnableMinRestore: boolean; //eventually clear this before application shutdown
OldFocus: TCustomForm; //the focused form on minimize
implementation
class procedure TMiniRestore.MiniRestore(Sender: TObject);
begin
DoMiniRestore;
end;
procedure DoMiniRestore;
var
i: integer;
f, mf: TCustomForm;
ws: TWindowState;
begin
(* Depending on the state of the main form, hide or restore all application forms.
*)
//check enabled and action
mf := Application.MainForm;
ws := mf.WindowState;
case ws of
wsMaximized: exit; //do nothing
wsMinimized:
begin
EnableMinRestore := True; //do minimize, allow for restore
OldFocus := Screen.ActiveCustomForm; //save focus window
end
else
if not EnableMinRestore then
exit; //disabled
end;
//for all forms...
for i := 0 to Screen.CustomFormCount - 1 do begin
f := Screen.CustomForms[i];
case ws of
wsNormal:
if (f <> mf) and (f.WindowState = wsNormal)
and (f.ShowInTaskBar = stDefault)
and not f.Visible then begin
//f.WindowState := wsNormal;
f.Show;
end;
wsMinimized:
if (f <> mf) and (f.WindowState = wsNormal) and f.Visible then begin
//f.WindowState := wsMinimized;
//f.ShowInTaskBar := stDefault;
f.Hide;
end;
end;
end;
//set the focus
if (ws = wsNormal) and assigned(OldFocus) then
OldFocus.SetFocus;
end;
end.