View Issue Details

IDProjectCategoryView StatusLast Update
0013034LazarusLCLpublic2013-09-03 12:07
ReporterHans-Peter Diettrich Assigned ToPaul Ishenin  
PrioritynormalSeveritymajorReproducibilityalways
Status closedResolutionfixed 
Product Version0.9.27 (SVN) 
Fixed in Version0.9.27 (SVN) 
Summary0013034: Missing dock manager notifications
DescriptionWhen a docking site is resized, the FDockManager.ResetBounds() method should be invoked, i.e. in TWinControl.WMSize().

Another notification is required when the visibility of a docked control changes, e.g. in TWinControl.CMVisibleChanged(). An according method could be added to the TDockManager base class. Delphi requires that a dock manager subclasses the WndProc of the dock site, because this notification was forgotten in the IDockManager interface - IMO we should cure this design flaw properly.

More notifications seem to be required, e.g. when a docked control is resized by a splitter control. Again Delphi requires subclassing of the WndProc, to emulate an splitter/sizer there, instead of using dedicated splitter controls, as is the current approach in the LCL. IMO the resizing of docked controls could be handled in a cheaper way, e.g. by drawing an sizing/docking frame, as already implemented for resizing forms or in the drag performer.
Additional InformationThese are essential notifications for all layout managers. It might be a good idea to create a TLayoutManager base class, with all the required notification methods; then TDockManager can inherit from that base class, extending it with docking specific methods. OTOH a dock manager should be able to inherit the implementation of an specific layout manager, what suggests to me to turn the TDockManager class into an IDockManager interface, just like in Delphi. Please note that such a change also would eliminate the current risk of memory leaks, when a user defined dock manager replaces an pre-created dock manager.

The same considerations may apply to an layout manager interface instead of a class. This should be kept in mind, when this issue is fixed.
Tagsdocking
Fixed in Revision18573
LazTarget1.4
Widgetset
Attached Files

Activities

2009-02-04 17:33

 

DockResize.patch (526 bytes)   
Index: wincontrol.inc
===================================================================
--- wincontrol.inc	(revision 18561)
+++ wincontrol.inc	(working copy)
@@ -7107,7 +7107,8 @@
       ' -> New=',Dbgs(Bounds(ALeft,ATop,AWidth,AHeight))]);
       {$ENDIF}
       inherited SetBounds(ALeft, ATop, AWidth, AHeight);
-      //NewBounds:=Bounds(Left, Top, Width, Height);
+      if FUseDockManager and (FDockManager <> nil) then
+        FDockManager.ResetBounds(False);
     finally
       UnlockRealizeBounds;
     end;
DockResize.patch (526 bytes)   

Hans-Peter Diettrich

2009-02-04 17:34

reporter   ~0025113

DockResize.patch calles DockManager.ResetBounds from TWinControl.SetBounds

2009-02-04 17:56

 

DockMgr2.patch (4,608 bytes)   
Index: wincontrol.inc
===================================================================
--- wincontrol.inc	(revision 18561)
+++ wincontrol.inc	(working copy)
@@ -4288,8 +4288,8 @@
     end;
     // paint controls
     //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' PaintControls ...');
-    if FDockSite and FUseDockManager and Assigned(FDockManager) then
-      FDockManager.PaintSite(DC);
+    if FDockSite and FUseDockManager and Assigned(DockManager) then
+      DockManager.PaintSite(DC);
     PaintControls(DC, nil);
   finally
     if TheMessage.DC = 0 then
@@ -4753,8 +4753,8 @@
            Exit
          else
          begin
-           if FDockSite and FUseDockManager and Assigned(FDockManager) then
-             FDockManager.MouseMessage(Message);
+           if FDockSite and FUseDockManager and Assigned(DockManager) then
+             DockManager.MouseMessage(Message);
          end;
          {$IFDEF VerboseMouseBugfix}
          DebugLn('TWinControl.WndPRoc B ',Name,':',ClassName);
@@ -4772,8 +4772,8 @@
     CM_MOUSEENTER,
     CM_MOUSELEAVE:
       begin
-        if FDockSite and FUseDockManager and Assigned(FDockManager) then
-          FDockManager.MouseMessage(Message);
+        if FDockSite and FUseDockManager and Assigned(DockManager) then
+          DockManager.MouseMessage(Message);
       end;
   end;
 
@@ -4905,13 +4905,21 @@
  ------------------------------------------------------------------------------}
 function TWinControl.CreateDockManager: TDockManager;
 begin
-  if (FDockManager = nil) and DockSite and UseDockManager then
+  if (DockManager = nil) and DockSite and UseDockManager then
     // this control can dock other controls, so it needs a TDockManager
     Result := DefaultDockTreeClass.Create(Self)
   else
-    Result := FDockManager;
+    Result := DockManager;
 end;
 
+procedure TWinControl.SetDockManager(AMgr: TDockManager);
+begin
+  //use FDockManager only here!
+  if assigned(DockManager) and (DockManager <> AMgr) then
+    FDockManager.Free;
+  FDockManager := AMgr; //can be nil
+end;
+
 {------------------------------------------------------------------------------
   procedure TWinControl.SetUseDockManager(const AValue: Boolean);
  ------------------------------------------------------------------------------}
@@ -4920,7 +4928,7 @@
   if FUseDockManager=AValue then exit;
   FUseDockManager:=AValue;
   if FUseDockManager and ([csDesigning,csDestroying]*ComponentState=[]) then
-    FDockManager := CreateDockManager;
+    DockManager := CreateDockManager;
 end;
 
 procedure TWinControl.DoFloatMsg(ADockSource: TDragDockObject);
@@ -5895,11 +5903,7 @@
 
   FreeThenNil(FBrush);
   FreeThenNil(FChildSizing);
-  if (FDockManager<>nil) then
-    if FDockManager.AutoFreeByControl then
-      FreeThenNil(FDockManager)
-    else
-      FDockManager:=nil;
+  FreeThenNil(FDockManager);
   FreeThenNil(FDockClients);
   FreeThenNil(FTabList);
   //DebugLn('[TWinControl.Destroy] D  ',Name,':',ClassName);
@@ -7008,11 +7012,11 @@
     if not NewDockSite then begin
       FreeAndNil(FDockClients);
       FDockClients := nil;
-      FDockManager := nil;
+      DockManager := nil;
     end
     else begin
       if FDockClients = nil then FDockClients := TFPList.Create;
-      FDockManager := CreateDockManager;
+      DockManager := CreateDockManager;
     end;
   end;
 end;
@@ -7028,8 +7032,8 @@
     DisableAlign;
     try
       DragDockObject.Control.Dock(Self, DestRect);
-      if FUseDockManager and (FDockManager <> nil) then
-        FDockManager.InsertControl(DragDockObject.Control,
+      if FUseDockManager and (DockManager <> nil) then
+        DockManager.InsertControl(DragDockObject.Control,
           DragDockObject.DropAlign, DragDockObject.DropOnControl);
     finally
       EnableAlign;
@@ -7044,8 +7048,8 @@
 begin
   Result := true;
   DebugLn(['TWinControl.DoUnDockClientMsg ',DbgSName(Self),' ',DbgSName(Client),' ',DbgSName(Client.Parent)]);
-  if FUseDockManager and (FDockManager <> nil) then
-    FDockManager.RemoveControl(Client);
+  if FUseDockManager and (DockManager <> nil) then
+    DockManager.RemoveControl(Client);
 end;
 
 {------------------------------------------------------------------------------
@@ -7107,7 +7111,8 @@
       ' -> New=',Dbgs(Bounds(ALeft,ATop,AWidth,AHeight))]);
       {$ENDIF}
       inherited SetBounds(ALeft, ATop, AWidth, AHeight);
-      //NewBounds:=Bounds(Left, Top, Width, Height);
+      if FUseDockManager and (DockManager <> nil) then
+        DockManager.ResetBounds(False);
     finally
       UnlockRealizeBounds;
     end;
DockMgr2.patch (4,608 bytes)   

Hans-Peter Diettrich

2009-02-04 17:58

reporter   ~0025115

DockMgr2.patch prevents orphaned dock managers.
It includes DockResize.patch(?)

2009-02-04 18:00

 

DockMgr2a.patch (1,200 bytes)   
Index: controls.pp
===================================================================
--- controls.pp	(revision 18561)
+++ controls.pp	(working copy)
@@ -1680,6 +1680,7 @@
     procedure ReloadDockedControl(const AControlName: string;
                                   var AControl: TControl); dynamic;
     function CreateDockManager: TDockManager; dynamic;
+    procedure SetDockManager(AMgr: TDockManager);
     procedure DoFloatMsg(ADockSource: TDragDockObject); override;//CM_FLOAT
     procedure DoGetDockCaption(AControl: TControl; var ACaption: String); virtual;
   protected
@@ -1760,7 +1761,7 @@
     property DefWndProc: Pointer read FDefWndProc write FDefWndPRoc;
     property DockClientCount: Integer read GetDockClientCount;
     property DockClients[Index: Integer]: TControl read GetDockClients;
-    property DockManager: TDockManager read FDockManager write FDockManager;
+    property DockManager: TDockManager read FDockManager write SetDockManager;
     property DockSite: Boolean read FDockSite write SetDockSite default False;
     property DoubleBuffered: Boolean read FDoubleBuffered write FDoubleBuffered;
     property Handle: HWND read GetHandle write SetHandle;
DockMgr2a.patch (1,200 bytes)   

Paul Ishenin

2009-02-05 03:08

manager   ~0025125

Thanks, applied. I only reverted a part where you free dockmanager when you should stay it live. Look at AutoFreeByConrol usage. It is invented for reason - for anchor dock manager of Mattias. Dont remove it from the code.

Please close if ok.

Hans-Peter Diettrich

2009-02-05 11:23

reporter   ~0025135

I'll open another issue for remaining problems.
I don't understand why the AnchorDockManager must stay alive, but if you say so...

Issue History

Date Modified Username Field Change
2009-01-24 05:14 Hans-Peter Diettrich New Issue
2009-01-30 10:04 Vincent Snijders LazTarget => post 1.2
2009-01-30 10:04 Vincent Snijders Status new => acknowledged
2009-01-30 10:04 Vincent Snijders Tag Attached: docking
2009-02-04 17:33 Hans-Peter Diettrich File Added: DockResize.patch
2009-02-04 17:34 Hans-Peter Diettrich Note Added: 0025113
2009-02-04 17:56 Hans-Peter Diettrich File Added: DockMgr2.patch
2009-02-04 17:58 Hans-Peter Diettrich Note Added: 0025115
2009-02-04 18:00 Hans-Peter Diettrich File Added: DockMgr2a.patch
2009-02-05 03:08 Paul Ishenin Fixed in Revision => 18573
2009-02-05 03:08 Paul Ishenin Status acknowledged => resolved
2009-02-05 03:08 Paul Ishenin Fixed in Version => 0.9.27 (SVN)
2009-02-05 03:08 Paul Ishenin Resolution open => fixed
2009-02-05 03:08 Paul Ishenin Assigned To => Paul Ishenin
2009-02-05 03:08 Paul Ishenin Note Added: 0025125
2009-02-05 11:23 Hans-Peter Diettrich Status resolved => closed
2009-02-05 11:23 Hans-Peter Diettrich Note Added: 0025135
2013-09-03 12:07 Martin Friebe LazTarget post 1.2 => 1.4