diff --git a/.gitattributes b/.gitattributes index 3c6217da52..1c429bbb52 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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.pas svneol=native#text/pascal 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/patches/FloatHostDockable.patch svneol=native#text/pascal examples/dockmanager/patches/NewClients.patch svneol=native#text/pascal diff --git a/examples/dockmanager/elasticsite/SiteTest.lpr b/examples/dockmanager/elasticsite/SiteTest.lpr index 07b4e6d628..42d9bb2458 100644 --- a/examples/dockmanager/elasticsite/SiteTest.lpr +++ b/examples/dockmanager/elasticsite/SiteTest.lpr @@ -14,7 +14,6 @@ uses begin Application.Initialize; Application.CreateForm(TEditorSite, EditorSite); - Application.CreateForm(TViewWindow, ViewWindow); Application.Run; end. diff --git a/examples/dockmanager/elasticsite/fclientform.lrs b/examples/dockmanager/elasticsite/fclientform.lrs index 5affc25f83..380bd4b35e 100644 --- a/examples/dockmanager/elasticsite/fclientform.lrs +++ b/examples/dockmanager/elasticsite/fclientform.lrs @@ -1,5 +1,3 @@ -{ This is an automatically generated lazarus resource file } - LazarusResources.Add('TViewWindow','FORMDATA',[ '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 diff --git a/examples/dockmanager/elasticsite/fclientform.pas b/examples/dockmanager/elasticsite/fclientform.pas index 4e83779ce6..76a076a3dd 100644 --- a/examples/dockmanager/elasticsite/fclientform.pas +++ b/examples/dockmanager/elasticsite/fclientform.pas @@ -1,4 +1,12 @@ 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+} @@ -21,13 +29,13 @@ type { public declarations } end; -var - ViewWindow: TViewWindow; +//var ViewWindow: TViewWindow; //useless implementation uses - LCLProc, fFloatingSite; + //LCLProc, //debugging only + fFloatingSite; { TViewWindow } @@ -35,18 +43,24 @@ procedure TViewWindow.FormEndDock(Sender, Target: TObject; X, Y: Integer); var Site: TFloatingSite; begin +(* When we become floating, dock immediately into a new floating host docksite. +*) if HostDockSite = nil then begin - DebugLn('--- floating'); - Site := TFloatingSite.Create(Application); - Site.BoundsRect := self.BoundsRect; + //DebugLn('--- floating'); + Site := TFloatingSite.Create(Application); //the new site + Site.BoundsRect := self.BoundsRect; //the new position and extension ManualDock(Site); - end else - DebugLn('--- in ' + HostDockSite.Name); + end else begin + //DebugLn('--- in ' + HostDockSite.Name); + end; end; procedure TViewWindow.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); 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 BeginDrag(False); end; diff --git a/examples/dockmanager/elasticsite/feditorsite.lfm b/examples/dockmanager/elasticsite/feditorsite.lfm index 447e0257e7..5df68c5d78 100644 --- a/examples/dockmanager/elasticsite/feditorsite.lfm +++ b/examples/dockmanager/elasticsite/feditorsite.lfm @@ -11,6 +11,7 @@ inherited EditorSite: TEditorSite OnDeactivate = FormDeactivate OnHide = FormHide OnResize = FormResize + OnWindowStateChange = FormWindowStateChange ShowInTaskBar = stAlways inherited pnlLeft: TPanel Height = 256 diff --git a/examples/dockmanager/elasticsite/feditorsite.lrs b/examples/dockmanager/elasticsite/feditorsite.lrs index f2bf035467..3bc8e88640 100644 --- a/examples/dockmanager/elasticsite/feditorsite.lrs +++ b/examples/dockmanager/elasticsite/feditorsite.lrs @@ -1,40 +1,39 @@ -{ This is an automatically generated lazarus resource file } - LazarusResources.Add('TEditorSite','FORMDATA',[ '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' +'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 - +#8'FormHide'#8'OnResize'#7#10'FormResize'#13'ShowInTaskBar'#7#8'stAlways'#0 - +#241#6'TPanel'#7'pnlLeft'#6'Height'#3#0#1#0#0#241#9'TSplitter'#9'splitLeft'#6 - +'Height'#3#0#1#0#0#241#6'TPanel'#8'pnlRight'#4'Left'#3#144#1#6'Height'#3#0#1 - +#0#0#241#6'TPanel'#9'pnlBottom'#3'Top'#3#4#1#5'Width'#3#144#1#0#0#241#9'TSpl' - +'itter'#10'splitRight'#4'Left'#3#140#1#6'Height'#3#0#1#0#0#241#10'TStatusBar' - +#10'StatusBar1'#3'Top'#3#5#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#11'splitB' - +'ottom'#3'Top'#3#0#1#5'Width'#3#144#1#0#0#242#2#7#9'TMainMenu'#9'MainMenu1'#4 - +'left'#3#240#0#3'top'#2'0'#0#9'TMenuItem'#6'mnFile'#7'Caption'#6#5'&File'#0#9 - +'TMenuItem'#6'mnOpen'#7'Caption'#6#5'&Open'#7'OnClick'#7#11'mnOpenClick'#0#0 - +#9'TMenuItem'#9'MenuItem1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#6'mnExit'#7'Ca' - +'ption'#6#5'E&xit'#7'OnClick'#7#11'mnExitClick'#0#0#0#9'TMenuItem'#6'mnView' - +#7'Caption'#6#5'&View'#0#9'TMenuItem'#9'MenuItem2'#7'Caption'#6#16'Object In' - +'spector'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem3'#7'Cap' - +'tion'#6#8'Messages'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuI' - +'tem4'#7'Caption'#6#13'Code Explorer'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'T' - +'MenuItem'#9'MenuItem5'#7'Caption'#6#9'ToDo List'#7'OnClick'#7#13'ViewMenuCl' - +'ick'#0#0#9'TMenuItem'#9'MenuItem6'#7'Caption'#6#13'Debug windows'#0#9'TMenu' - +'Item'#9'MenuItem7'#7'Caption'#6#7'Watches'#7'OnClick'#7#13'ViewMenuClick'#0 - +#0#9'TMenuItem'#9'MenuItem8'#7'Caption'#6#11'BreakPoints'#7'OnClick'#7#13'Vi' - +'ewMenuClick'#0#0#9'TMenuItem'#9'MenuItem9'#7'Caption'#6#15'Local Variables' - +#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem10'#7'Caption'#6 - +#9'Registers'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem11' - +#7'Caption'#6#10'Call Stack'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem' - +#10'MenuItem12'#7'Caption'#6#9'Assembler'#7'OnClick'#7#13'ViewMenuClick'#0#0 - +#9'TMenuItem'#10'MenuItem13'#7'Caption'#6#12'Debug Output'#7'OnClick'#7#13'V' - +'iewMenuClick'#0#0#0#0#9'TMenuItem'#10'MenuItem14'#7'Caption'#6#8'&Windows'#0 - +#9'TMenuItem'#12'mnWindowDump'#7'Caption'#6#5'&Dump'#7'OnClick'#7#17'mnWindo' - +'wDumpClick'#0#0#9'TMenuItem'#10'mnMinimize'#7'Caption'#6#12'Minimize all'#7 - +'OnClick'#7#15'mnMinimizeClick'#0#0#9'TMenuItem'#9'mnRestore'#7'Caption'#6#11 - +'Restore all'#7'OnClick'#7#14'mnRestoreClick'#0#0#0#0#242#2#8#11'TOpenDialog' - +#11'OpenDialog1'#6'Filter'#6#25'*.pas|*.pas|All Files|*.*'#4'left'#3'5'#1#3 - +'top'#2'0'#0#0#0 + +#8'FormHide'#8'OnResize'#7#10'FormResize'#19'OnWindowStateChange'#7#21'FormW' + +'indowStateChange'#13'ShowInTaskBar'#7#8'stAlways'#0#241#6'TPanel'#7'pnlLeft' + +#6'Height'#3#0#1#0#0#241#9'TSplitter'#9'splitLeft'#6'Height'#3#0#1#0#0#241#6 + +'TPanel'#8'pnlRight'#4'Left'#3#144#1#6'Height'#3#0#1#0#0#241#6'TPanel'#9'pnl' + +'Bottom'#3'Top'#3#4#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#10'splitRight'#4 + +'Left'#3#140#1#6'Height'#3#0#1#0#0#241#10'TStatusBar'#10'StatusBar1'#3'Top'#3 + +#5#1#5'Width'#3#144#1#0#0#241#9'TSplitter'#11'splitBottom'#3'Top'#3#0#1#5'Wi' + +'dth'#3#144#1#0#0#242#2#7#9'TMainMenu'#9'MainMenu1'#4'left'#3#240#0#3'top'#2 + +'0'#0#9'TMenuItem'#6'mnFile'#7'Caption'#6#5'&File'#0#9'TMenuItem'#6'mnOpen'#7 + +'Caption'#6#5'&Open'#7'OnClick'#7#11'mnOpenClick'#0#0#9'TMenuItem'#9'MenuIte' + +'m1'#7'Caption'#6#1'-'#0#0#9'TMenuItem'#6'mnExit'#7'Caption'#6#5'E&xit'#7'On' + +'Click'#7#11'mnExitClick'#0#0#0#9'TMenuItem'#6'mnView'#7'Caption'#6#5'&View' + +#0#9'TMenuItem'#9'MenuItem2'#7'Caption'#6#16'Object Inspector'#7'OnClick'#7 + +#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem3'#7'Caption'#6#8'Messages'#7 + +'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem4'#7'Caption'#6#13 + +'Code Explorer'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuItem5' + +#7'Caption'#6#9'ToDo List'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9 + +'MenuItem6'#7'Caption'#6#13'Debug windows'#0#9'TMenuItem'#9'MenuItem7'#7'Cap' + +'tion'#6#7'Watches'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#9'MenuIt' + +'em8'#7'Caption'#6#11'BreakPoints'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMen' + +'uItem'#9'MenuItem9'#7'Caption'#6#15'Local Variables'#7'OnClick'#7#13'ViewMe' + +'nuClick'#0#0#9'TMenuItem'#10'MenuItem10'#7'Caption'#6#9'Registers'#7'OnClic' + +'k'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem11'#7'Caption'#6#10'Call' + +' Stack'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'MenuItem12'#7'Ca' + +'ption'#6#9'Assembler'#7'OnClick'#7#13'ViewMenuClick'#0#0#9'TMenuItem'#10'Me' + +'nuItem13'#7'Caption'#6#12'Debug Output'#7'OnClick'#7#13'ViewMenuClick'#0#0#0 + +#0#9'TMenuItem'#10'MenuItem14'#7'Caption'#6#8'&Windows'#0#9'TMenuItem'#12'mn' + +'WindowDump'#7'Caption'#6#5'&Dump'#7'OnClick'#7#17'mnWindowDumpClick'#0#0#9 + +'TMenuItem'#10'mnMinimize'#7'Caption'#6#12'Minimize all'#7'OnClick'#7#15'mnM' + +'inimizeClick'#0#0#9'TMenuItem'#9'mnRestore'#7'Caption'#6#11'Restore all'#7 + +'OnClick'#7#14'mnRestoreClick'#0#0#0#0#242#2#8#11'TOpenDialog'#11'OpenDialog' + +'1'#6'Filter'#6#25'*.pas|*.pas|All Files|*.*'#4'left'#3'5'#1#3'top'#2'0'#0#0 + +#0 ]); diff --git a/examples/dockmanager/elasticsite/feditorsite.pas b/examples/dockmanager/elasticsite/feditorsite.pas index 26029b46ba..6fa9be254a 100644 --- a/examples/dockmanager/elasticsite/feditorsite.pas +++ b/examples/dockmanager/elasticsite/feditorsite.pas @@ -1,7 +1,7 @@ unit fEditorSite; (* EditorSite by DoDi -mimics an Delphi editor window, that allows to -- dock other windows to it +Mimics an Delphi editor window, that allows to dock other windows to it, +with several extensions: - optionally enlarging the window - detach a page into a new 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: For simplicity an IDE main menu has been added to the main window, -that allows to create several project window dummies, -which can be docked to the editor window. +that allows to create several project (View) window dummies, +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 -you can have multiple edit views within the editor window. +Mixed docking of editor pages and View windows (currently) is not blocked, +so that you can have multiple edit views within the editor window. Secondary editor windows should have the same docking capabilities. - +(not yet) Known bugs: - The IDE suspects dangling references - KEEP these references! 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+} -{$DEFINE clientform} //clients are forms? -{.$DEFINE stdfloat} //using standard floating host? +{$DEFINE minimize} //test application minimize/restore interface @@ -66,6 +68,7 @@ type procedure FormDeactivate(Sender: TObject); procedure FormHide(Sender: TObject); procedure FormResize(Sender: TObject); + procedure FormWindowStateChange(Sender: TObject); procedure mnMinimizeClick(Sender: TObject); procedure mnRestoreClick(Sender: TObject); procedure mnWindowDumpClick(Sender: TObject); @@ -87,6 +90,7 @@ implementation uses LCLProc, + uMiniRestore, fClientForm, fFloatingSite; @@ -102,30 +106,21 @@ begin FEdit.Parent := self; FEdit.Visible := True; FEdit.DragMode := dmManual; //disallow undocking - //FEdit.pnlDock.DragMode := dmManual; - FAutoExpand := True; end; function TEditorSite.CreateDockable(const cap: string): TWinControl; var Site: TFloatingSite; -{$IFDEF clientform} Client: TViewWindow; -{$ELSE} - Client: TWinControl; -{$ENDIF} 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.Label1.Caption := cap; Client.Visible := True; - //Client.FloatingDockSiteClass := TFloatingSite; -{$ELSE} - Client := TPanel.Create(self); - Client.DragMode := dmAutomatic; - Client.DragKind := dkDock; - Client.Visible := True; -{$ENDIF} //name it Client.Caption := cap; try @@ -133,19 +128,9 @@ begin except //here: simply ignore duplicate name end; -{$IFDEF stdfloat} - Client.ManualDock(nil); -{$ELSE} //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); - Client.ManualDock(Site, nil, alClient); - {$ENDIF} -{$ENDIF} + Site := TFloatingSite.Create(Application); + Client.ManualDock(Site, nil, alClient); Result := Client; end; @@ -158,11 +143,31 @@ begin CreateDockable(item.Caption); 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); begin Close; end; + +// ----------- application window handling ------------- + procedure TEditorSite.FormActivate(Sender: TObject); begin //DebugLn('--- Activate'); @@ -175,13 +180,18 @@ end; procedure TEditorSite.FormHide(Sender: TObject); begin - DebugLn('--- FormHide'); //not when minimized manually (win32) + //DebugLn('--- FormHide'); //not when minimized manually (win32) //mnMinimizeClick(Sender); end; procedure TEditorSite.FormResize(Sender: TObject); begin - DebugLn('--- Resize'); + //DebugLn('--- Resize'); +end; + +procedure TEditorSite.FormWindowStateChange(Sender: TObject); +begin + DoMiniRestore; end; procedure TEditorSite.mnMinimizeClick(Sender: TObject); @@ -189,6 +199,7 @@ var i: integer; f: TForm; begin +{$IFDEF minimize} for i := 0 to Screen.FormCount - 1 do begin f := Screen.Forms[i]; //if f = self then f.WindowState := wsMinimized else @@ -197,18 +208,16 @@ begin f.WindowState := wsMinimized; end; end; +{$ELSE} +{$ENDIF} end; procedure TEditorSite.mnRestoreClick(Sender: TObject); begin +{$IFDEF minimize} WindowState := wsNormal; -end; - -procedure TEditorSite.mnOpenClick(Sender: TObject); -begin - if OpenDialog1.Execute then begin - OpenFile(OpenDialog1.FileName); - end; +{$ELSE} +{$ENDIF} end; procedure TEditorSite.mnWindowDumpClick(Sender: TObject); @@ -243,16 +252,6 @@ begin DebugLn('---'); 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 {$I feditorsite.lrs} diff --git a/examples/dockmanager/package/easydockmgr.lpk b/examples/dockmanager/package/easydockmgr.lpk index 10c4916efd..256632a2ee 100644 --- a/examples/dockmanager/package/easydockmgr.lpk +++ b/examples/dockmanager/package/easydockmgr.lpk @@ -17,7 +17,7 @@ - + @@ -51,6 +51,10 @@ + + + + diff --git a/examples/dockmanager/package/easydockmgr.pas b/examples/dockmanager/package/easydockmgr.pas index d1bdf0a748..3c0e456fa4 100644 --- a/examples/dockmanager/package/easydockmgr.pas +++ b/examples/dockmanager/package/easydockmgr.pas @@ -7,7 +7,8 @@ unit EasyDockMgr; interface uses - EasyDockSite, fDockBook, fFloatingSite, fElasticSite, LazarusPackageIntf; + EasyDockSite, fDockBook, fFloatingSite, fElasticSite, uMiniRestore, + LazarusPackageIntf; implementation diff --git a/examples/dockmanager/package/ffloatingsite.lfm b/examples/dockmanager/package/ffloatingsite.lfm index e813d42ca2..a7c0bda01d 100644 --- a/examples/dockmanager/package/ffloatingsite.lfm +++ b/examples/dockmanager/package/ffloatingsite.lfm @@ -6,9 +6,7 @@ object FloatingSite: TFloatingSite Caption = 'FloatingSite' DockSite = True OnDockDrop = FormDockDrop - OnDockOver = FormDockOver OnUnDock = FormUnDock - ShowInTaskBar = stNever UseDockManager = True LCLVersion = '0.9.29' Visible = True diff --git a/examples/dockmanager/package/ffloatingsite.lrs b/examples/dockmanager/package/ffloatingsite.lrs index 911c9b0def..523ef50e70 100644 --- a/examples/dockmanager/package/ffloatingsite.lrs +++ b/examples/dockmanager/package/ffloatingsite.lrs @@ -3,7 +3,6 @@ LazarusResources.Add('TFloatingSite','FORMDATA',[ '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 - +'OnDockDrop'#7#12'FormDockDrop'#10'OnDockOver'#7#12'FormDockOver'#8'OnUnDock' - +#7#10'FormUnDock'#13'ShowInTaskBar'#7#7'stNever'#14'UseDockManager'#9#10'LCL' - +'Version'#6#6'0.9.29'#7'Visible'#9#0#0 + +'OnDockDrop'#7#12'FormDockDrop'#8'OnUnDock'#7#10'FormUnDock'#14'UseDockManag' + +'er'#9#10'LCLVersion'#6#6'0.9.29'#7'Visible'#9#0#0 ]); diff --git a/examples/dockmanager/package/ffloatingsite.pas b/examples/dockmanager/package/ffloatingsite.pas index a7f5b2f884..9599379a77 100644 --- a/examples/dockmanager/package/ffloatingsite.pas +++ b/examples/dockmanager/package/ffloatingsite.pas @@ -1,8 +1,13 @@ unit fFloatingSite; (* 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: -- show summary caption + Handle flaws of the Delphi docking model (improper undock). + - 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+} @@ -16,8 +21,6 @@ type TFloatingSite = class(TForm) procedure FormDockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer); - procedure FormDockOver(Sender: TObject; Source: TDragDockObject; - X, Y: Integer; State: TDragState; var Accept: Boolean); procedure FormUnDock(Sender: TObject; Client: TControl; NewTarget: TWinControl; var Allow: Boolean); private @@ -34,8 +37,8 @@ var implementation uses - EasyDockSite, - LCLproc; + LCLproc, //debugging only + EasyDockSite; //our DockManager { TFloatingSite } @@ -45,6 +48,9 @@ var s: string; ctl: TControl; begin +(* Show the combined captions of all clients. + Exclude client to be undocked. +*) s := ''; for i := 0 to DockClientCount - 1 do begin ctl := DockClients[i]; @@ -52,63 +58,54 @@ begin s := s + GetDockCaption(ctl) + ', '; end; SetLength(s, Length(s) - 2); //strip trailing ", " - Caption := s; //GetDockCaption(self); + Caption := s; end; procedure TFloatingSite.FormDockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer); begin +(* Update the caption. +*) AdjustCaption(nil); 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; NewTarget: TWinControl; var Allow: Boolean); begin -(* Check for undock last client: - - disallow to Nil (move window?) - - if allowed, kill empty docksite. +(* Check for undock last client, if allowed kill empty docksite. Refresh caption after undock. 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 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 NewTarget = nil then begin - //Allow := False; //deny - Allow := True; //move form - where??? - Release; - end else - Release; + Release; //destroy empty site end else begin - //allow float - action required? - (* strange behaviour: client is undocked, but stays in the site. - 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); + AdjustCaption(Client); //update caption, excluding removed client + DockManager.ResetBounds(True); //required with gtk2!? end; end; procedure TFloatingSite.Loaded; begin +(* select and configure the docking manager. +*) inherited Loaded; if DockManager = nil then DockManager := TEasyTree.Create(self); if DockManager is TEasyTree then begin - TEasyTree(DockManager).HideSingleCaption := True; - TEasyTree(DockManager).SetStyle(hsForm); + //adjust as desired (order required!?) + TEasyTree(DockManager).HideSingleCaption := True; //only show headers for multiple clients + TEasyTree(DockManager).SetStyle(hsForm); //show client name in the header end; end; diff --git a/examples/dockmanager/package/uminirestore.pas b/examples/dockmanager/package/uminirestore.pas new file mode 100644 index 0000000000..9ab8ba1ed8 --- /dev/null +++ b/examples/dockmanager/package/uminirestore.pas @@ -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. +