View Issue Details

IDProjectCategoryView StatusLast Update
0024703LazarusPackagespublic2017-08-20 10:32
ReporterAndrey Zubarev Assigned ToJuha Manninen  
PrioritynormalSeverityminorReproducibilityhave not tried
Status closedResolutionfixed 
Product Version1.1 (SVN) 
Summary0024703: TAnchorDockMaster.MakeDockSite feature request
DescriptionCurrently to the main form you can dock on the top, bottom, left, right side. Why can not the inside? This is a fundamental limitation or just unimplemented? It would be very useful. For example now we can not make the status bar for an application using the anchordocking library. there is an superfluous splitter under the top toolbar. This all can be avoided by adding the akClient option for the TAnchorDockMaster.MakeDockSite for main form.
TagsNo tags attached.
Fixed in Revisionr55638, r55641, r55654
LazTarget-
Widgetset
Attached Files

Relationships

related to 0032302 closedJuha Manninen Wrong save-restore mainform.WindowState in TAnchorDocking with TAnchorDockPanel [Patch] 

Activities

Mattias Gaertner

2013-07-03 10:29

manager   ~0068710

What do you mean with on the inside? The left,top,right,bottom is on the inside.

Andrey Zubarev

2013-07-03 10:35

reporter   ~0068711

In the free inner region, without creating a spliters. On the similarity of the component behavior with Align:=alClient

Andrey Zubarev

2013-07-25 00:07

reporter   ~0069094

Mattias, may make sense to add a new component - "TDockPanel", by placing it on a form to be able to dock on it instead of the option "akClient"

Andrey Zubarev

2014-10-07 10:57

reporter   ~0078043

Mattias, please give opinion on the "TDockPanel" or akClient. I think that without this AnchorDocking features are essentially limited

Mattias Gaertner

2014-10-07 11:21

manager   ~0078044

Can you give an example?

Andrey Zubarev

2014-10-07 19:19

reporter  

akclient.gif (773,470 bytes)

Andrey Zubarev

2014-10-07 19:23

reporter   ~0078054

I do not know much English and can `t explain. But I added an animated gif http://bugs.freepascal.org/file_download.php?file_id=20805&type=bug to make it clear about what I mean.

Mattias Gaertner

2014-10-07 23:07

manager   ~0078058

Thanks for the example. I think, a TAnchorDockPanel is a good idea.

Andrey Zubarev

2014-11-26 16:28

reporter   ~0079406

Mattias, could you clarify some key points to create TAnchorDockPanel. Or make the blank with abstract methods? I would try to develop this

Mattias Gaertner

2014-11-26 17:39

manager   ~0079409

I would start with a TAnchorDockPanel = class(TCustomPanel).
The restore must be able to find it by name, so each panel must be registered in a list of DockMaster. The register must check if the name is unique.
Then the mouse dragover must be extended to recognize TAnchorDockPanel as a target and show a preview rectangle.
Then implement the drop (the actual docking).

Andrey Zubarev

2014-11-27 19:06

reporter   ~0079426

While I tried to replace the TAnchorDockPanel on the form with BorderStyle:=bsNone and Parent<>nil. This partially works, but still needed akClient. Because the first dock object can not dock to the whole space form only akTop, akLeft, akRight, akBottom. On TAnchorDockPanel will be as well?

Andrey Zubarev

2014-11-27 19:08

reporter   ~0079427

Last edited: 2014-11-27 19:12

View 2 revisions

>>so each panel must be registered in a list of DockMaster
This is DockMaster.MakeDockSite(testpanel, ...);?

Andrey Zubarev

2017-06-16 21:55

reporter  

anchordockpanel.patch (717,044 bytes)

Andrey Zubarev

2017-06-16 21:58

reporter   ~0101197

Add simple anchordockpanel implement, without load\save layout.
Mattias, please review, and help with load\save

Andrey Zubarev

2017-06-16 22:04

reporter   ~0101198

in patch \lazarus\components\anchordocking\miniidewithdockpanel\ - example usage of anchordockpanel

Andrey Zubarev

2017-06-20 11:19

reporter   ~0101231

Last edited: 2017-06-20 11:21

View 2 revisions

Old anchordockpanel.patch need to delete.
New patch's attached:
anchordocking-tanchordockpanel-impl.patch
miniidewithdockpanel-example.patch
I separate implementation and example of use anchordockpanel.
Now load\save layout is worked

Please review

Andrey Zubarev

2017-06-20 11:20

reporter  

anchordocking-tanchordockpanel-impl.patch (17,349 bytes)   
Index: components/anchordocking/anchordocking.lpk
===================================================================
--- components/anchordocking/anchordocking.lpk	(revision 55360)
+++ components/anchordocking/anchordocking.lpk	(working copy)
@@ -2,6 +2,7 @@
 <CONFIG>
   <Package Version="4">
     <Name Value="AnchorDocking"/>
+    <Type Value="RunAndDesignTime"/>
     <AddToProjectUsesSection Value="True"/>
     <Author Value="Mattias Gaertner mattias@freepascal.org"/>
     <CompilerOptions>
@@ -18,7 +19,7 @@
     <License Value="modified LGPL-2 like LCL
 "/>
     <Version Minor="6"/>
-    <Files Count="7">
+    <Files Count="8">
       <Item1>
         <Filename Value="anchordockpkg.pas"/>
         <Type Value="Main Unit"/>
@@ -48,6 +49,11 @@
         <Filename Value="anchordockoptionsdlg.lfm"/>
         <Type Value="LFM"/>
       </Item7>
+      <Item8>
+        <Filename Value="anchordockpanel.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="AnchorDockPanel"/>
+      </Item8>
     </Files>
     <LazDoc Paths="doc"/>
     <i18n>
Index: components/anchordocking/anchordocking.pas
===================================================================
--- components/anchordocking/anchordocking.pas	(revision 55360)
+++ components/anchordocking/anchordocking.pas	(working copy)
@@ -102,7 +102,7 @@
   LCLType, LCLIntf, LCLProc,
   Controls, Forms, ExtCtrls, ComCtrls, Graphics, Themes, Menus, Buttons,
   LazConfigStorage, Laz2_XMLCfg, LazFileCache,
-  AnchorDockStr, AnchorDockStorage;
+  AnchorDockStr, AnchorDockStorage, AnchorDockPanel;
 
 {$IFDEF DebugDisableAutoSizing}
 const ADAutoSizingReason = 'TAnchorDockMaster Delayed';
@@ -307,7 +307,7 @@
                          OnlyCheckIfPossible: boolean): boolean;
     function EnlargeSideRotateSplitter(Side: TAnchorKind;
                          OnlyCheckIfPossible: boolean): boolean;
-    procedure CreateBoundSplitter;
+    procedure CreateBoundSplitter(disabled:boolean=false);
     procedure PositionBoundSplitter;
   public
     constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
@@ -590,6 +590,8 @@
     procedure MakeDockSite(AForm: TCustomForm; Sites: TAnchors;
                            ResizePolicy: TADMResizePolicy;
                            AllowInside: boolean = false);
+    procedure MakeDockPanel(APanel:TAnchorDockPanel;
+                            ResizePolicy: TADMResizePolicy);
     procedure MakeVisible(AControl: TControl; SwitchPages: boolean);
     function ShowControl(ControlName: string; BringToFront: boolean = false): TControl;
     procedure CloseAll;
@@ -1571,7 +1573,7 @@
     end;
     if (Node.NodeType=adltnCustomSite) then begin
       AControl:=FindControl(Node.Name);
-      if IsCustomSite(AControl) then
+      if (IsCustomSite(AControl))or(AControl is TAnchorDockPanel) then
         fTreeNameToDocker[Node.Name]:=AControl;
     end;
     for i:=0 to Node.Count-1 do
@@ -1647,6 +1649,11 @@
     if (fTreeNameToDocker[Node.Name]=nil) and (BestSite<>nil) then begin
       // search the parent site of a child site
       repeat
+        if BestSite is TAnchorDockPanel then begin
+          if fTreeNameToDocker.ControlToName(BestSite)='' then
+            fTreeNameToDocker[Node.Name]:=BestSite;
+          break;
+        end;
         BestSite:=BestSite.Parent;
         if BestSite is TAnchorDockHostSite then begin
           if fTreeNameToDocker.ControlToName(BestSite)='' then
@@ -1758,11 +1765,14 @@
     aMonitor: TMonitor;
     aHostSite: TAnchorDockHostSite;
   begin
+    if not (tobject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
         aMonitor:=Screen.Monitors[Node.Monitor]
       else
         aMonitor:=Site.Monitor;
+    end;
       WorkArea:=aMonitor.WorkareaRect;
       {$IFDEF VerboseAnchorDockRestore}
       debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
@@ -1782,8 +1792,15 @@
       NewBounds:=Rect(ScaleTopLvlX(NewBounds.Left),ScaleTopLvlY(NewBounds.Top),
                       ScaleTopLvlX(NewBounds.Right),ScaleTopLvlY(NewBounds.Bottom));
     end else begin
-      NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
+      if parent is TAnchorDockPanel then
+      begin
+        NewBounds:=Rect(0,0,parent.ClientWidth,parent.ClientHeight);
+        site.Align:=alClient;
+      end
+      else
+        NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
                       ScaleChildX(NewBounds.Right),ScaleChildY(NewBounds.Bottom));
+
     end;
     {$IFDEF VerboseAnchorDockRestore}
     if Scale then
@@ -1791,7 +1808,8 @@
     {$ENDIF}
     Site.BoundsRect:=NewBounds;
     Site.Visible:=true;
-    Site.Parent:=Parent;
+    if not (tobject (Site) is TAnchorDockPanel) then
+      Site.Parent:=Parent;
     if IsCustomSite(Parent) then begin
       aManager:=TAnchorDockManager(Parent.DockManager);
       Site.Align:=Node.Align;
@@ -1808,11 +1826,14 @@
       if (Node.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then
         aHostSite.FreePages;
     end;
+    if not (tobject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       Site.WindowState:=Node.WindowState;
     end else begin
       Site.WindowState:=wsNormal;
     end;
+    end;
   end;
 
   function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite;
@@ -1875,7 +1896,7 @@
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: can not find control ',Node.Name]);
         exit;
       end;
-      if not IsCustomSite(AControl) then begin
+      if not (IsCustomSite(AControl)or (AControl is TAnchorDockPanel)) then begin
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: ',Node.Name,' is not a custom dock site ',DbgSName(AControl)]);
         exit;
       end;
@@ -2704,7 +2725,7 @@
   AManager: TAnchorDockManager;
 begin
   if AForm.Name='' then
-    raise Exception.Create('TAnchorDockMaster.MakeDockable '+
+    raise Exception.Create('TAnchorDockMaster.MakeDockSite '+
       adrsMissingControlName);
   if AForm.DockManager<>nil then
     raise Exception.Create('TAnchorDockMaster.MakeDockSite DockManager<>nil');
@@ -2733,6 +2754,34 @@
   end;
 end;
 
+procedure TAnchorDockMaster.MakeDockPanel(APanel:TAnchorDockPanel;
+                                          ResizePolicy: TADMResizePolicy);
+var
+  AManager: TAnchorDockManager;
+begin
+  if APanel.Name='' then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel '+
+      adrsMissingControlName);
+  if APanel.DockManager<>nil then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel DockManager<>nil');
+  APanel.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  try
+    if FControls.IndexOf(APanel)<0 then begin
+      FControls.Add(APanel);
+      APanel.FreeNotification(Self);
+    end;
+    AManager:=ManagerClass.Create(APanel);
+    AManager.DockableSites:=[];
+    AManager.InsideDockingAllowed:=true;
+    AManager.ResizePolicy:=ResizePolicy;
+    APanel.DockManager:=AManager;
+    APanel.UseDockManager:=true;
+    APanel.DockSite:=true;
+  finally
+    APanel.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  end;
+end;
+
 procedure TAnchorDockMaster.MakeVisible(AControl: TControl; SwitchPages: boolean);
 begin
   while AControl<>nil do begin
@@ -2806,6 +2855,23 @@
   end;
 end;
 
+function GetParentFormOrDockPanel(Control: TControl): TCustomForm;
+begin
+  while (Control <> nil) and (Control.Parent <> nil) do
+  begin
+    if (Control is TAnchorDockPanel) then
+      Break;
+    Control := Control.Parent;
+  end;
+  if Control is TCustomForm then
+    Result := TCustomForm(Control)
+  else
+  if Control is TAnchorDockPanel then
+    Result := TCustomForm(Control)
+  else
+  Result := nil;
+end;
+
 procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree);
 var
   i: Integer;
@@ -2815,6 +2881,28 @@
   LayoutNode: TAnchorDockLayoutTreeNode;
   AForm: TCustomForm;
   VisibleControls: TStringList;
+
+  procedure saveform(theForm: TCustomForm; SaveChilds:boolean);
+  begin
+    // custom dock site
+    LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+    LayoutNode.NodeType:=adltnCustomSite;
+    LayoutNode.Assign(theForm);
+    // can have one normal dock site
+    if SaveChilds then
+    begin
+    Site:=TAnchorDockManager(theForm.DockManager).GetChildSite;
+    if Site<>nil then begin
+      LayoutNode:=LayoutTree.NewNode(LayoutNode);
+      Site.SaveLayout(LayoutTree,LayoutNode);
+      {if Site.BoundSplitter<>nil then begin
+        LayoutNode:=LayoutTree.NewNode(LayoutNode);
+        Site.BoundSplitter.SaveLayout(LayoutNode);
+      end;}
+    end;
+    end;
+  end;
+
 begin
   SavedSites:=TFPList.Create;
   VisibleControls:=TStringList.Create;
@@ -2823,31 +2911,23 @@
       AControl:=Controls[i];
       if not DockedControlIsVisible(AControl) then continue;
       VisibleControls.Add(AControl.Name);
-      AForm:=GetParentForm(AControl);
+      AForm:=GetParentFormOrDockPanel(AControl);
       if AForm=nil then continue;
       if SavedSites.IndexOf(AForm)>=0 then continue;
       SavedSites.Add(AForm);
       debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AForm)]);
       DebugWriteChildAnchors(AForm,true,true);
-      if (AForm is TAnchorDockHostSite) then begin
+      if (tobject(AForm) is TAnchorDockPanel) then begin
+        saveform(GetParentFormOrDockPanel(AForm),{false}true);
+        //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+        //TAnchorDockPanel(AForm).SaveLayout(LayoutTree,LayoutNode);
+      end
+      else if (AForm is TAnchorDockHostSite) then begin
         Site:=TAnchorDockHostSite(AForm);
         LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
         Site.SaveLayout(LayoutTree,LayoutNode);
       end else if IsCustomSite(AForm) then begin
-        // custom dock site
-        LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
-        LayoutNode.NodeType:=adltnCustomSite;
-        LayoutNode.Assign(AForm);
-        // can have one normal dock site
-        Site:=TAnchorDockManager(AForm.DockManager).GetChildSite;
-        if Site<>nil then begin
-          LayoutNode:=LayoutTree.NewNode(LayoutNode);
-          Site.SaveLayout(LayoutTree,LayoutNode);
-          {if Site.BoundSplitter<>nil then begin
-            LayoutNode:=LayoutTree.NewNode(LayoutNode);
-            Site.BoundSplitter.SaveLayout(LayoutNode);
-          end;}
-        end;
+        saveform(AForm,true);
       end else
         raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
     end;
@@ -4778,7 +4858,7 @@
   end;
 end;
 
-procedure TAnchorDockHostSite.CreateBoundSplitter;
+procedure TAnchorDockHostSite.CreateBoundSplitter(disabled:boolean=false);
 begin
   if BoundSplitter<>nil then exit;
   FBoundSplitter:=DockMaster.CreateSplitter;
@@ -4785,6 +4865,12 @@
   BoundSplitter.FreeNotification(Self);
   BoundSplitter.Align:=Align;
   BoundSplitter.Parent:=Parent;
+  if disabled then
+  begin
+    BoundSplitter.Width:=0;
+    BoundSplitter.Height:=0;
+    BoundSplitter.Visible:=false;
+  end;
 end;
 
 procedure TAnchorDockHostSite.PositionBoundSplitter;
@@ -5544,10 +5630,13 @@
       ChildSite:=nil;
       if Child is TAnchorDockHostSite then begin
         ChildSite:=TAnchorDockHostSite(Child);
-        ChildSite.CreateBoundSplitter;
+        ChildSite.CreateBoundSplitter(Site is TAnchorDockPanel);
         SplitterWidth:=DockMaster.SplitterWidth;
       end;
 
+      if Site is TAnchorDockPanel then
+        ADockObject.DropAlign:=alClient;
+
       // resize Site
       NewSiteBounds:=Site.BoundsRect;
       case ADockObject.DropAlign of
@@ -5555,9 +5644,13 @@
       alRight: dec(NewSiteBounds.Right,Child.ClientWidth+SplitterWidth);
       alTop: dec(NewSiteBounds.Top,Child.ClientHeight+SplitterWidth);
       alBottom: inc(NewSiteBounds.Bottom,Child.ClientHeight+SplitterWidth);
+      alClient:begin
+                Child.BoundsRect:=Site.ClientRect;
+               end;
       end;
       if not StoredConstraintsValid then
         StoreConstraints;
+      if ADockObject.DropAlign<>alClient then
       if ADockObject.DropAlign in [alLeft,alRight] then
         Site.Constraints.MaxWidth:=0
       else
@@ -5575,8 +5668,13 @@
       alLeft: NewChildBounds:=Bounds(0,0,Child.ClientWidth,Site.ClientHeight);
       alRight: NewChildBounds:=Bounds(Site.ClientWidth-Child.ClientWidth,0,
                                       Child.ClientWidth,Site.ClientHeight);
+      alClient:begin
+                NewChildBounds:=Bounds(0,0,
+                                      Site.ClientWidth,Site.ClientHeight);
+               end;
       end;
       Child.BoundsRect:=NewChildBounds;
+      NewChildBounds:=Child.BoundsRect;
 
       if ChildSite<>nil then
         ChildSite.PositionBoundSplitter;
@@ -5640,6 +5738,12 @@
     or (Site.Parent.Parent<>nil) then
       Inside:=true;
   end;
+
+  if Site is TAnchorDockPanel then begin
+   DockRect:=Bounds(Site.ClientOrigin.x,Site.ClientOrigin.y,Site.ClientWidth,Site.ClientHeight);
+   exit;
+  end;
+
   case DropAlign of
   alLeft:
     if Inside then
@@ -5805,6 +5909,8 @@
     case ResizePolicy of
     admrpChild:
       begin
+        if (Child.Parent<>nil)and(not(Child.Parent is TAnchorDockPanel))then
+        begin
         if Child.Align in [alLeft,alRight] then
           Child.Width:=Max(1,Min(ChildMaxSize.X,Child.Width+WidthDiff))
         else begin
@@ -5814,6 +5920,7 @@
           {$ENDIF}
           Child.Height:=i;
         end;
+        end;
       end;
     end;
   end;
Index: components/anchordocking/anchordockpanel.pas
===================================================================
--- components/anchordocking/anchordockpanel.pas	(nonexistent)
+++ components/anchordocking/anchordockpanel.pas	(working copy)
@@ -0,0 +1,80 @@
+unit AnchorDockPanel;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+  AnchorDockStorage;
+
+type
+  TAnchorDockPanel = class(TPanel)
+  private
+
+  protected
+    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+      var Accept: Boolean); override;
+
+
+  public
+
+    procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree;
+                         LayoutNode: TAnchorDockLayoutTreeNode);
+    function GetOneControl: TControl;
+
+  published
+
+  end;
+
+procedure Register;
+
+implementation
+uses AnchorDocking;
+procedure TAnchorDockPanel.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+  var Accept: Boolean);
+begin
+  Accept:=true;
+end;
+
+function TAnchorDockPanel.GetOneControl: TControl;
+var
+  i: Integer;
+begin
+  for i:=0 to ControlCount-1 do begin
+    Result:=Controls[i];
+    if Result.Owner<>Self then exit;
+  end;
+  Result:=nil;
+end;
+
+procedure TAnchorDockPanel.SaveLayout(
+  LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode);
+var
+  i: Integer;
+  Site: TAnchorDockHostSite;
+  ChildNode: TAnchorDockLayoutTreeNode;
+  Child: TControl;
+  Splitter: TAnchorDockSplitter;
+  OneControl: TControl;
+begin
+  OneControl:=GetOneControl;
+  if OneControl is TAnchorDockHostSite then
+  begin
+
+    LayoutNode.NodeType:=adltnControl;
+    LayoutNode.Assign(Self);
+    LayoutNode.Name:={OneControl.}Name;
+
+    TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode);
+  end;
+end;
+
+
+procedure Register;
+begin
+  {$I anchordockpanel_icon.lrs}
+  RegisterComponents('Additional',[TAnchorDockPanel]);
+end;
+
+end.
Index: components/anchordocking/anchordockpanel_icon.lrs
===================================================================
--- components/anchordocking/anchordockpanel_icon.lrs	(nonexistent)
+++ components/anchordocking/anchordockpanel_icon.lrs	(working copy)
@@ -0,0 +1,9 @@
+LazarusResources.Add('TAnchorDockPanel','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+  +#0#0'xIDATx^'#237#149'A'#10#132'0'#12'E'#127#134'^w'#214#230#8#174#167#23#26
+  +#157'k'#204#162'"x'#140'~Q'#232#166#184#146'F'#4#243' '#144#213#127#132'@"9g'
+  +#136#8#172#16#146#176'$'#148'F563'#245#253'[P '#185'W'#215'}'#216#130'-g'#252
+  +#14','#185#1#21')'#253'q'#150'yZP'#243#130#1#143#19#184#192#5'.pA88'#185'v'#2
+  +#213'h3Ays'#191'a'#228#213'O'#255#254'K^'#1#166'zsS'#138#185#218'6'#0#0#0#0
+  +'IEND'#174'B`'#130
+]);
Index: components/anchordocking/anchordockpkg.pas
===================================================================
--- components/anchordocking/anchordockpkg.pas	(revision 55360)
+++ components/anchordocking/anchordockpkg.pas	(working copy)
@@ -8,8 +8,16 @@
 interface
 
 uses
-  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg;
+  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg, 
+  AnchorDockPanel, LazarusPackageIntf;
 
 implementation
 
+procedure Register;
+begin
+  RegisterUnit('AnchorDockPanel', @AnchorDockPanel.Register);
+end;
+
+initialization
+  RegisterPackage('AnchorDocking', @Register);
 end.

Andrey Zubarev

2017-06-20 11:20

reporter  

Andrey Zubarev

2017-06-20 22:32

reporter  

anchordocking-tanchordockpanel-impl2.patch (19,033 bytes)   
Index: components/anchordocking/anchordocking.lpk
===================================================================
--- components/anchordocking/anchordocking.lpk	(revision 55360)
+++ components/anchordocking/anchordocking.lpk	(working copy)
@@ -2,6 +2,7 @@
 <CONFIG>
   <Package Version="4">
     <Name Value="AnchorDocking"/>
+    <Type Value="RunAndDesignTime"/>
     <AddToProjectUsesSection Value="True"/>
     <Author Value="Mattias Gaertner mattias@freepascal.org"/>
     <CompilerOptions>
@@ -18,7 +19,7 @@
     <License Value="modified LGPL-2 like LCL
 "/>
     <Version Minor="6"/>
-    <Files Count="7">
+    <Files Count="8">
       <Item1>
         <Filename Value="anchordockpkg.pas"/>
         <Type Value="Main Unit"/>
@@ -48,6 +49,11 @@
         <Filename Value="anchordockoptionsdlg.lfm"/>
         <Type Value="LFM"/>
       </Item7>
+      <Item8>
+        <Filename Value="anchordockpanel.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="AnchorDockPanel"/>
+      </Item8>
     </Files>
     <LazDoc Paths="doc"/>
     <i18n>
Index: components/anchordocking/anchordocking.pas
===================================================================
--- components/anchordocking/anchordocking.pas	(revision 55360)
+++ components/anchordocking/anchordocking.pas	(working copy)
@@ -102,7 +102,7 @@
   LCLType, LCLIntf, LCLProc,
   Controls, Forms, ExtCtrls, ComCtrls, Graphics, Themes, Menus, Buttons,
   LazConfigStorage, Laz2_XMLCfg, LazFileCache,
-  AnchorDockStr, AnchorDockStorage;
+  AnchorDockStr, AnchorDockStorage, AnchorDockPanel;
 
 {$IFDEF DebugDisableAutoSizing}
 const ADAutoSizingReason = 'TAnchorDockMaster Delayed';
@@ -307,7 +307,7 @@
                          OnlyCheckIfPossible: boolean): boolean;
     function EnlargeSideRotateSplitter(Side: TAnchorKind;
                          OnlyCheckIfPossible: boolean): boolean;
-    procedure CreateBoundSplitter;
+    procedure CreateBoundSplitter(disabled:boolean=false);
     procedure PositionBoundSplitter;
   public
     constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
@@ -590,6 +590,8 @@
     procedure MakeDockSite(AForm: TCustomForm; Sites: TAnchors;
                            ResizePolicy: TADMResizePolicy;
                            AllowInside: boolean = false);
+    procedure MakeDockPanel(APanel:TAnchorDockPanel;
+                            ResizePolicy: TADMResizePolicy);
     procedure MakeVisible(AControl: TControl; SwitchPages: boolean);
     function ShowControl(ControlName: string; BringToFront: boolean = false): TControl;
     procedure CloseAll;
@@ -1571,7 +1573,7 @@
     end;
     if (Node.NodeType=adltnCustomSite) then begin
       AControl:=FindControl(Node.Name);
-      if IsCustomSite(AControl) then
+      if (IsCustomSite(AControl))or(AControl is TAnchorDockPanel) then
         fTreeNameToDocker[Node.Name]:=AControl;
     end;
     for i:=0 to Node.Count-1 do
@@ -1647,6 +1649,11 @@
     if (fTreeNameToDocker[Node.Name]=nil) and (BestSite<>nil) then begin
       // search the parent site of a child site
       repeat
+        if BestSite is TAnchorDockPanel then begin
+          if fTreeNameToDocker.ControlToName(BestSite)='' then
+            fTreeNameToDocker[Node.Name]:=BestSite;
+          break;
+        end;
         BestSite:=BestSite.Parent;
         if BestSite is TAnchorDockHostSite then begin
           if fTreeNameToDocker.ControlToName(BestSite)='' then
@@ -1758,16 +1765,21 @@
     aMonitor: TMonitor;
     aHostSite: TAnchorDockHostSite;
   begin
+    if not (tobject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
         aMonitor:=Screen.Monitors[Node.Monitor]
       else
         aMonitor:=Site.Monitor;
+    end;
       WorkArea:=aMonitor.WorkareaRect;
       {$IFDEF VerboseAnchorDockRestore}
       debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
       {$ENDIF}
-    end;
+    end
+    else
+      GetParentForm(Site).BoundsRect:=Node.BoundsRect;
     if IsCustomSite(Site) then begin
       aManager:=TAnchorDockManager(Site.DockManager);
       if Node.Count>0 then begin
@@ -1782,8 +1794,15 @@
       NewBounds:=Rect(ScaleTopLvlX(NewBounds.Left),ScaleTopLvlY(NewBounds.Top),
                       ScaleTopLvlX(NewBounds.Right),ScaleTopLvlY(NewBounds.Bottom));
     end else begin
-      NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
+      if parent is TAnchorDockPanel then
+      begin
+        NewBounds:=Rect(0,0,parent.ClientWidth,parent.ClientHeight);
+        site.Align:=alClient;
+      end
+      else
+        NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
                       ScaleChildX(NewBounds.Right),ScaleChildY(NewBounds.Bottom));
+
     end;
     {$IFDEF VerboseAnchorDockRestore}
     if Scale then
@@ -1791,7 +1810,8 @@
     {$ENDIF}
     Site.BoundsRect:=NewBounds;
     Site.Visible:=true;
-    Site.Parent:=Parent;
+    if not (tobject (Site) is TAnchorDockPanel) then
+      Site.Parent:=Parent;
     if IsCustomSite(Parent) then begin
       aManager:=TAnchorDockManager(Parent.DockManager);
       Site.Align:=Node.Align;
@@ -1808,11 +1828,14 @@
       if (Node.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then
         aHostSite.FreePages;
     end;
+    if not (tobject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       Site.WindowState:=Node.WindowState;
     end else begin
       Site.WindowState:=wsNormal;
     end;
+    end;
   end;
 
   function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite;
@@ -1875,7 +1898,7 @@
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: can not find control ',Node.Name]);
         exit;
       end;
-      if not IsCustomSite(AControl) then begin
+      if not (IsCustomSite(AControl)or (AControl is TAnchorDockPanel)) then begin
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: ',Node.Name,' is not a custom dock site ',DbgSName(AControl)]);
         exit;
       end;
@@ -2704,7 +2727,7 @@
   AManager: TAnchorDockManager;
 begin
   if AForm.Name='' then
-    raise Exception.Create('TAnchorDockMaster.MakeDockable '+
+    raise Exception.Create('TAnchorDockMaster.MakeDockSite '+
       adrsMissingControlName);
   if AForm.DockManager<>nil then
     raise Exception.Create('TAnchorDockMaster.MakeDockSite DockManager<>nil');
@@ -2733,6 +2756,34 @@
   end;
 end;
 
+procedure TAnchorDockMaster.MakeDockPanel(APanel:TAnchorDockPanel;
+                                          ResizePolicy: TADMResizePolicy);
+var
+  AManager: TAnchorDockManager;
+begin
+  if APanel.Name='' then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel '+
+      adrsMissingControlName);
+  if APanel.DockManager<>nil then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel DockManager<>nil');
+  APanel.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  try
+    if FControls.IndexOf(APanel)<0 then begin
+      FControls.Add(APanel);
+      APanel.FreeNotification(Self);
+    end;
+    AManager:=ManagerClass.Create(APanel);
+    AManager.DockableSites:=[];
+    AManager.InsideDockingAllowed:=true;
+    AManager.ResizePolicy:=ResizePolicy;
+    APanel.DockManager:=AManager;
+    APanel.UseDockManager:=true;
+    APanel.DockSite:=true;
+  finally
+    APanel.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  end;
+end;
+
 procedure TAnchorDockMaster.MakeVisible(AControl: TControl; SwitchPages: boolean);
 begin
   while AControl<>nil do begin
@@ -2806,6 +2857,23 @@
   end;
 end;
 
+function GetParentFormOrDockPanel(Control: TControl): TCustomForm;
+begin
+  while (Control <> nil) and (Control.Parent <> nil) do
+  begin
+    if (Control is TAnchorDockPanel) then
+      Break;
+    Control := Control.Parent;
+  end;
+  if Control is TCustomForm then
+    Result := TCustomForm(Control)
+  else
+  if Control is TAnchorDockPanel then
+    Result := TCustomForm(Control)
+  else
+  Result := nil;
+end;
+
 procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree);
 var
   i: Integer;
@@ -2815,6 +2883,28 @@
   LayoutNode: TAnchorDockLayoutTreeNode;
   AForm: TCustomForm;
   VisibleControls: TStringList;
+
+  procedure saveform(theForm: TCustomForm; SaveChilds:boolean);
+  begin
+    // custom dock site
+    LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+    LayoutNode.NodeType:=adltnCustomSite;
+    LayoutNode.Assign(theForm,tobject(theForm) is TAnchorDockPanel);
+    // can have one normal dock site
+    if SaveChilds then
+    begin
+    Site:=TAnchorDockManager(theForm.DockManager).GetChildSite;
+    if Site<>nil then begin
+      LayoutNode:=LayoutTree.NewNode(LayoutNode);
+      Site.SaveLayout(LayoutTree,LayoutNode);
+      {if Site.BoundSplitter<>nil then begin
+        LayoutNode:=LayoutTree.NewNode(LayoutNode);
+        Site.BoundSplitter.SaveLayout(LayoutNode);
+      end;}
+    end;
+    end;
+  end;
+
 begin
   SavedSites:=TFPList.Create;
   VisibleControls:=TStringList.Create;
@@ -2823,31 +2913,23 @@
       AControl:=Controls[i];
       if not DockedControlIsVisible(AControl) then continue;
       VisibleControls.Add(AControl.Name);
-      AForm:=GetParentForm(AControl);
+      AForm:=GetParentFormOrDockPanel(AControl);
       if AForm=nil then continue;
       if SavedSites.IndexOf(AForm)>=0 then continue;
       SavedSites.Add(AForm);
       debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AForm)]);
       DebugWriteChildAnchors(AForm,true,true);
-      if (AForm is TAnchorDockHostSite) then begin
+      if (tobject(AForm) is TAnchorDockPanel) then begin
+        saveform(GetParentFormOrDockPanel(AForm),{false}true);
+        //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+        //TAnchorDockPanel(AForm).SaveLayout(LayoutTree,LayoutNode);
+      end
+      else if (AForm is TAnchorDockHostSite) then begin
         Site:=TAnchorDockHostSite(AForm);
         LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
         Site.SaveLayout(LayoutTree,LayoutNode);
       end else if IsCustomSite(AForm) then begin
-        // custom dock site
-        LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
-        LayoutNode.NodeType:=adltnCustomSite;
-        LayoutNode.Assign(AForm);
-        // can have one normal dock site
-        Site:=TAnchorDockManager(AForm.DockManager).GetChildSite;
-        if Site<>nil then begin
-          LayoutNode:=LayoutTree.NewNode(LayoutNode);
-          Site.SaveLayout(LayoutTree,LayoutNode);
-          {if Site.BoundSplitter<>nil then begin
-            LayoutNode:=LayoutTree.NewNode(LayoutNode);
-            Site.BoundSplitter.SaveLayout(LayoutNode);
-          end;}
-        end;
+        saveform(AForm,true);
       end else
         raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
     end;
@@ -4778,7 +4860,7 @@
   end;
 end;
 
-procedure TAnchorDockHostSite.CreateBoundSplitter;
+procedure TAnchorDockHostSite.CreateBoundSplitter(disabled:boolean=false);
 begin
   if BoundSplitter<>nil then exit;
   FBoundSplitter:=DockMaster.CreateSplitter;
@@ -4785,6 +4867,12 @@
   BoundSplitter.FreeNotification(Self);
   BoundSplitter.Align:=Align;
   BoundSplitter.Parent:=Parent;
+  if disabled then
+  begin
+    BoundSplitter.Width:=0;
+    BoundSplitter.Height:=0;
+    BoundSplitter.Visible:=false;
+  end;
 end;
 
 procedure TAnchorDockHostSite.PositionBoundSplitter;
@@ -5544,10 +5632,13 @@
       ChildSite:=nil;
       if Child is TAnchorDockHostSite then begin
         ChildSite:=TAnchorDockHostSite(Child);
-        ChildSite.CreateBoundSplitter;
+        ChildSite.CreateBoundSplitter(Site is TAnchorDockPanel);
         SplitterWidth:=DockMaster.SplitterWidth;
       end;
 
+      if Site is TAnchorDockPanel then
+        ADockObject.DropAlign:=alClient;
+
       // resize Site
       NewSiteBounds:=Site.BoundsRect;
       case ADockObject.DropAlign of
@@ -5555,9 +5646,14 @@
       alRight: dec(NewSiteBounds.Right,Child.ClientWidth+SplitterWidth);
       alTop: dec(NewSiteBounds.Top,Child.ClientHeight+SplitterWidth);
       alBottom: inc(NewSiteBounds.Bottom,Child.ClientHeight+SplitterWidth);
+      alClient:begin
+                Child.BoundsRect:=Site.ClientRect;
+                Child.Align:=alClient;
+               end;
       end;
       if not StoredConstraintsValid then
         StoreConstraints;
+      if ADockObject.DropAlign<>alClient then
       if ADockObject.DropAlign in [alLeft,alRight] then
         Site.Constraints.MaxWidth:=0
       else
@@ -5575,8 +5671,13 @@
       alLeft: NewChildBounds:=Bounds(0,0,Child.ClientWidth,Site.ClientHeight);
       alRight: NewChildBounds:=Bounds(Site.ClientWidth-Child.ClientWidth,0,
                                       Child.ClientWidth,Site.ClientHeight);
+      alClient:begin
+                NewChildBounds:=Bounds(0,0,
+                                      Site.ClientWidth,Site.ClientHeight);
+               end;
       end;
       Child.BoundsRect:=NewChildBounds;
+      NewChildBounds:=Child.BoundsRect;
 
       if ChildSite<>nil then
         ChildSite.PositionBoundSplitter;
@@ -5640,6 +5741,12 @@
     or (Site.Parent.Parent<>nil) then
       Inside:=true;
   end;
+
+  if Site is TAnchorDockPanel then begin
+   DockRect:=Bounds(Site.ClientOrigin.x,Site.ClientOrigin.y,Site.ClientWidth,Site.ClientHeight);
+   exit;
+  end;
+
   case DropAlign of
   alLeft:
     if Inside then
@@ -5805,6 +5912,8 @@
     case ResizePolicy of
     admrpChild:
       begin
+        if (Child.Parent<>nil)and(not(Child.Parent is TAnchorDockPanel))then
+        begin
         if Child.Align in [alLeft,alRight] then
           Child.Width:=Max(1,Min(ChildMaxSize.X,Child.Width+WidthDiff))
         else begin
@@ -5814,6 +5923,7 @@
           {$ENDIF}
           Child.Height:=i;
         end;
+        end;
       end;
     end;
   end;
Index: components/anchordocking/anchordockpanel.pas
===================================================================
--- components/anchordocking/anchordockpanel.pas	(nonexistent)
+++ components/anchordocking/anchordockpanel.pas	(working copy)
@@ -0,0 +1,80 @@
+unit AnchorDockPanel;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+  AnchorDockStorage;
+
+type
+  TAnchorDockPanel = class(TPanel)
+  private
+
+  protected
+    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+      var Accept: Boolean); override;
+
+
+  public
+
+    procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree;
+                         LayoutNode: TAnchorDockLayoutTreeNode);
+    function GetOneControl: TControl;
+
+  published
+
+  end;
+
+procedure Register;
+
+implementation
+uses AnchorDocking;
+procedure TAnchorDockPanel.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+  var Accept: Boolean);
+begin
+  Accept:=true;
+end;
+
+function TAnchorDockPanel.GetOneControl: TControl;
+var
+  i: Integer;
+begin
+  for i:=0 to ControlCount-1 do begin
+    Result:=Controls[i];
+    if Result.Owner<>Self then exit;
+  end;
+  Result:=nil;
+end;
+
+procedure TAnchorDockPanel.SaveLayout(
+  LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode);
+var
+  i: Integer;
+  Site: TAnchorDockHostSite;
+  ChildNode: TAnchorDockLayoutTreeNode;
+  Child: TControl;
+  Splitter: TAnchorDockSplitter;
+  OneControl: TControl;
+begin
+  OneControl:=GetOneControl;
+  if OneControl is TAnchorDockHostSite then
+  begin
+
+    LayoutNode.NodeType:=adltnControl;
+    LayoutNode.Assign(Self);
+    LayoutNode.Name:={OneControl.}Name;
+
+    TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode);
+  end;
+end;
+
+
+procedure Register;
+begin
+  {$I anchordockpanel_icon.lrs}
+  RegisterComponents('Additional',[TAnchorDockPanel]);
+end;
+
+end.
Index: components/anchordocking/anchordockpanel_icon.lrs
===================================================================
--- components/anchordocking/anchordockpanel_icon.lrs	(nonexistent)
+++ components/anchordocking/anchordockpanel_icon.lrs	(working copy)
@@ -0,0 +1,9 @@
+LazarusResources.Add('TAnchorDockPanel','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+  +#0#0'xIDATx^'#237#149'A'#10#132'0'#12'E'#127#134'^w'#214#230#8#174#167#23#26
+  +#157'k'#204#162'"x'#140'~Q'#232#166#184#146'F'#4#243' '#144#213#127#132'@"9g'
+  +#136#8#172#16#146#176'$'#148'F563'#245#253'[P '#185'W'#215'}'#216#130'-g'#252
+  +#14','#185#1#21')'#253'q'#150'yZP'#243#130#1#143#19#184#192#5'.pA88'#185'v'#2
+  +#213'h3Ays'#191'a'#228#213'O'#255#254'K^'#1#166'zsS'#138#185#218'6'#0#0#0#0
+  +'IEND'#174'B`'#130
+]);
Index: components/anchordocking/anchordockpkg.pas
===================================================================
--- components/anchordocking/anchordockpkg.pas	(revision 55360)
+++ components/anchordocking/anchordockpkg.pas	(working copy)
@@ -8,8 +8,16 @@
 interface
 
 uses
-  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg;
+  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg, 
+  AnchorDockPanel, LazarusPackageIntf;
 
 implementation
 
+procedure Register;
+begin
+  RegisterUnit('AnchorDockPanel', @AnchorDockPanel.Register);
+end;
+
+initialization
+  RegisterPackage('AnchorDocking', @Register);
 end.
Index: components/anchordocking/anchordockstorage.pas
===================================================================
--- components/anchordocking/anchordockstorage.pas	(revision 55360)
+++ components/anchordocking/anchordockstorage.pas	(working copy)
@@ -113,7 +113,7 @@
     procedure Clear;
     function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean;
     procedure Assign(Node: TAnchorDockLayoutTreeNode); overload;
-    procedure Assign(AControl: TControl); overload;
+    procedure Assign(AControl: TControl;OverrideBoundsRect:Boolean=false); overload;
     procedure LoadFromConfig(Config: TConfigStorage); overload;
     procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload;
     procedure SaveToConfig(Config: TConfigStorage); overload;
@@ -1113,13 +1113,16 @@
   end;
 end;
 
-procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl);
+procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl;OverrideBoundsRect:Boolean=false);
 var
   AnchorControl: TControl;
   a: TAnchorKind;
 begin
   Name:=AControl.Name;
-  BoundsRect:=AControl.BoundsRect;
+  if OverrideBoundsRect then
+    BoundsRect:=GetParentForm(AControl).BoundsRect
+  else
+    BoundsRect:=AControl.BoundsRect;
   Align:=AControl.Align;
   if (AControl.Parent=nil) and (AControl is TCustomForm) then begin
     WindowState:=TCustomForm(AControl).WindowState;

Andrey Zubarev

2017-06-20 22:35

reporter   ~0101233

anchordocking-tanchordockpanel-impl.patch is old. nev version anchordocking-tanchordockpanel-impl2.patch containts mainform boundsrect load\save

Andrey Zubarev

2017-07-07 20:40

reporter   ~0101572

anchordocking-tanchordockpanel-impl2.patch is old. nev version anchordocking-tanchordockpanel-impl3.patch fix AV on closing sites

Please review

Andrey Zubarev

2017-07-07 20:40

reporter  

anchordocking-tanchordockpanel-impl3.patch (19,862 bytes)   
Index: components/anchordocking/anchordocking.lpk
===================================================================
--- components/anchordocking/anchordocking.lpk	(revision 55460)
+++ components/anchordocking/anchordocking.lpk	(working copy)
@@ -2,6 +2,7 @@
 <CONFIG>
   <Package Version="4">
     <Name Value="AnchorDocking"/>
+    <Type Value="RunAndDesignTime"/>
     <AddToProjectUsesSection Value="True"/>
     <Author Value="Mattias Gaertner mattias@freepascal.org"/>
     <CompilerOptions>
@@ -18,7 +19,7 @@
     <License Value="modified LGPL-2 like LCL
 "/>
     <Version Minor="6"/>
-    <Files Count="7">
+    <Files Count="8">
       <Item1>
         <Filename Value="anchordockpkg.pas"/>
         <Type Value="Main Unit"/>
@@ -48,6 +49,11 @@
         <Filename Value="anchordockoptionsdlg.lfm"/>
         <Type Value="LFM"/>
       </Item7>
+      <Item8>
+        <Filename Value="anchordockpanel.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="AnchorDockPanel"/>
+      </Item8>
     </Files>
     <LazDoc Paths="doc"/>
     <i18n>
Index: components/anchordocking/anchordocking.pas
===================================================================
--- components/anchordocking/anchordocking.pas	(revision 55460)
+++ components/anchordocking/anchordocking.pas	(working copy)
@@ -102,7 +102,7 @@
   LCLType, LCLIntf, LCLProc,
   Controls, Forms, ExtCtrls, ComCtrls, Graphics, Themes, Menus, Buttons,
   LazConfigStorage, Laz2_XMLCfg, LazFileCache,
-  AnchorDockStr, AnchorDockStorage;
+  AnchorDockStr, AnchorDockStorage, AnchorDockPanel;
 
 {$IFDEF DebugDisableAutoSizing}
 const ADAutoSizingReason = 'TAnchorDockMaster Delayed';
@@ -307,7 +307,7 @@
                          OnlyCheckIfPossible: boolean): boolean;
     function EnlargeSideRotateSplitter(Side: TAnchorKind;
                          OnlyCheckIfPossible: boolean): boolean;
-    procedure CreateBoundSplitter;
+    procedure CreateBoundSplitter(disabled:boolean=false);
     procedure PositionBoundSplitter;
   public
     constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
@@ -591,6 +591,8 @@
     procedure MakeDockSite(AForm: TCustomForm; Sites: TAnchors;
                            ResizePolicy: TADMResizePolicy;
                            AllowInside: boolean = false);
+    procedure MakeDockPanel(APanel:TAnchorDockPanel;
+                            ResizePolicy: TADMResizePolicy);
     procedure MakeVisible(AControl: TControl; SwitchPages: boolean);
     function ShowControl(ControlName: string; BringToFront: boolean = false): TControl;
     procedure CloseAll;
@@ -1572,7 +1574,7 @@
     end;
     if (Node.NodeType=adltnCustomSite) then begin
       AControl:=FindControl(Node.Name);
-      if IsCustomSite(AControl) then
+      if (IsCustomSite(AControl))or(AControl is TAnchorDockPanel) then
         fTreeNameToDocker[Node.Name]:=AControl;
     end;
     for i:=0 to Node.Count-1 do
@@ -1648,6 +1650,11 @@
     if (fTreeNameToDocker[Node.Name]=nil) and (BestSite<>nil) then begin
       // search the parent site of a child site
       repeat
+        if BestSite is TAnchorDockPanel then begin
+          if fTreeNameToDocker.ControlToName(BestSite)='' then
+            fTreeNameToDocker[Node.Name]:=BestSite;
+          break;
+        end;
         BestSite:=BestSite.Parent;
         if BestSite is TAnchorDockHostSite then begin
           if fTreeNameToDocker.ControlToName(BestSite)='' then
@@ -1759,16 +1766,21 @@
     aMonitor: TMonitor;
     aHostSite: TAnchorDockHostSite;
   begin
+    if not (tobject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
         aMonitor:=Screen.Monitors[Node.Monitor]
       else
         aMonitor:=Site.Monitor;
+    end;
       WorkArea:=aMonitor.WorkareaRect;
       {$IFDEF VerboseAnchorDockRestore}
       debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
       {$ENDIF}
-    end;
+    end
+    else
+      GetParentForm(Site).BoundsRect:=Node.BoundsRect;
     if IsCustomSite(Site) then begin
       aManager:=TAnchorDockManager(Site.DockManager);
       if Node.Count>0 then begin
@@ -1783,8 +1795,15 @@
       NewBounds:=Rect(ScaleTopLvlX(NewBounds.Left),ScaleTopLvlY(NewBounds.Top),
                       ScaleTopLvlX(NewBounds.Right),ScaleTopLvlY(NewBounds.Bottom));
     end else begin
-      NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
+      if parent is TAnchorDockPanel then
+      begin
+        NewBounds:=Rect(0,0,parent.ClientWidth,parent.ClientHeight);
+        site.Align:=alClient;
+      end
+      else
+        NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
                       ScaleChildX(NewBounds.Right),ScaleChildY(NewBounds.Bottom));
+
     end;
     {$IFDEF VerboseAnchorDockRestore}
     if Scale then
@@ -1792,7 +1811,8 @@
     {$ENDIF}
     Site.BoundsRect:=NewBounds;
     Site.Visible:=true;
-    Site.Parent:=Parent;
+    if not (tobject (Site) is TAnchorDockPanel) then
+      Site.Parent:=Parent;
     if IsCustomSite(Parent) then begin
       aManager:=TAnchorDockManager(Parent.DockManager);
       Site.Align:=Node.Align;
@@ -1809,11 +1829,14 @@
       if (Node.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then
         aHostSite.FreePages;
     end;
+    if not (tobject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       Site.WindowState:=Node.WindowState;
     end else begin
       Site.WindowState:=wsNormal;
     end;
+    end;
   end;
 
   function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite;
@@ -1876,7 +1899,7 @@
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: can not find control ',Node.Name]);
         exit;
       end;
-      if not IsCustomSite(AControl) then begin
+      if not (IsCustomSite(AControl)or (AControl is TAnchorDockPanel)) then begin
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: ',Node.Name,' is not a custom dock site ',DbgSName(AControl)]);
         exit;
       end;
@@ -2705,7 +2728,7 @@
   AManager: TAnchorDockManager;
 begin
   if AForm.Name='' then
-    raise Exception.Create('TAnchorDockMaster.MakeDockable '+
+    raise Exception.Create('TAnchorDockMaster.MakeDockSite '+
       adrsMissingControlName);
   if AForm.DockManager<>nil then
     raise Exception.Create('TAnchorDockMaster.MakeDockSite DockManager<>nil');
@@ -2734,6 +2757,34 @@
   end;
 end;
 
+procedure TAnchorDockMaster.MakeDockPanel(APanel:TAnchorDockPanel;
+                                          ResizePolicy: TADMResizePolicy);
+var
+  AManager: TAnchorDockManager;
+begin
+  if APanel.Name='' then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel '+
+      adrsMissingControlName);
+  if APanel.DockManager<>nil then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel DockManager<>nil');
+  APanel.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  try
+    if FControls.IndexOf(APanel)<0 then begin
+      FControls.Add(APanel);
+      APanel.FreeNotification(Self);
+    end;
+    AManager:=ManagerClass.Create(APanel);
+    AManager.DockableSites:=[];
+    AManager.InsideDockingAllowed:=true;
+    AManager.ResizePolicy:=ResizePolicy;
+    APanel.DockManager:=AManager;
+    APanel.UseDockManager:=true;
+    APanel.DockSite:=true;
+  finally
+    APanel.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  end;
+end;
+
 procedure TAnchorDockMaster.MakeVisible(AControl: TControl; SwitchPages: boolean);
 begin
   while AControl<>nil do begin
@@ -2807,6 +2858,23 @@
   end;
 end;
 
+function GetParentFormOrDockPanel(Control: TControl): TCustomForm;
+begin
+  while (Control <> nil) and (Control.Parent <> nil) do
+  begin
+    if (Control is TAnchorDockPanel) then
+      Break;
+    Control := Control.Parent;
+  end;
+  if Control is TCustomForm then
+    Result := TCustomForm(Control)
+  else
+  if Control is TAnchorDockPanel then
+    Result := TCustomForm(Control)
+  else
+  Result := nil;
+end;
+
 procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree);
 var
   i: Integer;
@@ -2816,6 +2884,28 @@
   LayoutNode: TAnchorDockLayoutTreeNode;
   AForm: TCustomForm;
   VisibleControls: TStringList;
+
+  procedure saveform(theForm: TCustomForm; SaveChilds:boolean);
+  begin
+    // custom dock site
+    LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+    LayoutNode.NodeType:=adltnCustomSite;
+    LayoutNode.Assign(theForm,tobject(theForm) is TAnchorDockPanel);
+    // can have one normal dock site
+    if SaveChilds then
+    begin
+    Site:=TAnchorDockManager(theForm.DockManager).GetChildSite;
+    if Site<>nil then begin
+      LayoutNode:=LayoutTree.NewNode(LayoutNode);
+      Site.SaveLayout(LayoutTree,LayoutNode);
+      {if Site.BoundSplitter<>nil then begin
+        LayoutNode:=LayoutTree.NewNode(LayoutNode);
+        Site.BoundSplitter.SaveLayout(LayoutNode);
+      end;}
+    end;
+    end;
+  end;
+
 begin
   SavedSites:=TFPList.Create;
   VisibleControls:=TStringList.Create;
@@ -2824,31 +2914,23 @@
       AControl:=Controls[i];
       if not DockedControlIsVisible(AControl) then continue;
       VisibleControls.Add(AControl.Name);
-      AForm:=GetParentForm(AControl);
+      AForm:=GetParentFormOrDockPanel(AControl);
       if AForm=nil then continue;
       if SavedSites.IndexOf(AForm)>=0 then continue;
       SavedSites.Add(AForm);
       debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AForm)]);
       DebugWriteChildAnchors(AForm,true,true);
-      if (AForm is TAnchorDockHostSite) then begin
+      if (tobject(AForm) is TAnchorDockPanel) then begin
+        saveform(GetParentFormOrDockPanel(AForm),{false}true);
+        //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+        //TAnchorDockPanel(AForm).SaveLayout(LayoutTree,LayoutNode);
+      end
+      else if (AForm is TAnchorDockHostSite) then begin
         Site:=TAnchorDockHostSite(AForm);
         LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
         Site.SaveLayout(LayoutTree,LayoutNode);
       end else if IsCustomSite(AForm) then begin
-        // custom dock site
-        LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
-        LayoutNode.NodeType:=adltnCustomSite;
-        LayoutNode.Assign(AForm);
-        // can have one normal dock site
-        Site:=TAnchorDockManager(AForm.DockManager).GetChildSite;
-        if Site<>nil then begin
-          LayoutNode:=LayoutTree.NewNode(LayoutNode);
-          Site.SaveLayout(LayoutTree,LayoutNode);
-          {if Site.BoundSplitter<>nil then begin
-            LayoutNode:=LayoutTree.NewNode(LayoutNode);
-            Site.BoundSplitter.SaveLayout(LayoutNode);
-          end;}
-        end;
+        saveform(AForm,true);
       end else
         raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
     end;
@@ -2869,6 +2951,8 @@
   if (AForm is TAnchorDockHostSite) then begin
     Site:=TAnchorDockHostSite(AForm);
     Site.SaveLayout(LayoutTree,LayoutTree.Root);
+  end else if (Tobject(AForm) is TAnchorDockPanel) then begin
+      (Tobject(AForm) as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root);
   end else if IsCustomSite(AForm) then begin
     LayoutTree.Root.NodeType:=adltnCustomSite;
     LayoutTree.Root.Assign(AForm);
@@ -2907,7 +2991,7 @@
 begin
   if not IsSite(AControl) then
     raise Exception.Create('TAnchorDockMaster.CreateRestoreLayout: not a site '+DbgSName(AControl));
-  AForm:=GetParentForm(AControl);
+  AForm:=GetParentFormOrDockPanel(AControl);
   Result:=TAnchorDockRestoreLayout.Create(TAnchorDockLayoutTree.Create);
   if AForm=nil then exit;
   SaveSiteLayoutToTree(AForm,Result.Layout);
@@ -4779,7 +4863,7 @@
   end;
 end;
 
-procedure TAnchorDockHostSite.CreateBoundSplitter;
+procedure TAnchorDockHostSite.CreateBoundSplitter(disabled:boolean=false);
 begin
   if BoundSplitter<>nil then exit;
   FBoundSplitter:=DockMaster.CreateSplitter;
@@ -4786,6 +4870,12 @@
   BoundSplitter.FreeNotification(Self);
   BoundSplitter.Align:=Align;
   BoundSplitter.Parent:=Parent;
+  if disabled then
+  begin
+    BoundSplitter.Width:=0;
+    BoundSplitter.Height:=0;
+    BoundSplitter.Visible:=false;
+  end;
 end;
 
 procedure TAnchorDockHostSite.PositionBoundSplitter;
@@ -5545,10 +5635,13 @@
       ChildSite:=nil;
       if Child is TAnchorDockHostSite then begin
         ChildSite:=TAnchorDockHostSite(Child);
-        ChildSite.CreateBoundSplitter;
+        ChildSite.CreateBoundSplitter(Site is TAnchorDockPanel);
         SplitterWidth:=DockMaster.SplitterWidth;
       end;
 
+      if Site is TAnchorDockPanel then
+        ADockObject.DropAlign:=alClient;
+
       // resize Site
       NewSiteBounds:=Site.BoundsRect;
       case ADockObject.DropAlign of
@@ -5556,9 +5649,14 @@
       alRight: dec(NewSiteBounds.Right,Child.ClientWidth+SplitterWidth);
       alTop: dec(NewSiteBounds.Top,Child.ClientHeight+SplitterWidth);
       alBottom: inc(NewSiteBounds.Bottom,Child.ClientHeight+SplitterWidth);
+      alClient:begin
+                Child.BoundsRect:=Site.ClientRect;
+                Child.Align:=alClient;
+               end;
       end;
       if not StoredConstraintsValid then
         StoreConstraints;
+      if ADockObject.DropAlign<>alClient then
       if ADockObject.DropAlign in [alLeft,alRight] then
         Site.Constraints.MaxWidth:=0
       else
@@ -5576,8 +5674,13 @@
       alLeft: NewChildBounds:=Bounds(0,0,Child.ClientWidth,Site.ClientHeight);
       alRight: NewChildBounds:=Bounds(Site.ClientWidth-Child.ClientWidth,0,
                                       Child.ClientWidth,Site.ClientHeight);
+      alClient:begin
+                NewChildBounds:=Bounds(0,0,
+                                      Site.ClientWidth,Site.ClientHeight);
+               end;
       end;
       Child.BoundsRect:=NewChildBounds;
+      NewChildBounds:=Child.BoundsRect;
 
       if ChildSite<>nil then
         ChildSite.PositionBoundSplitter;
@@ -5641,6 +5744,12 @@
     or (Site.Parent.Parent<>nil) then
       Inside:=true;
   end;
+
+  if Site is TAnchorDockPanel then begin
+   DockRect:=Bounds(Site.ClientOrigin.x,Site.ClientOrigin.y,Site.ClientWidth,Site.ClientHeight);
+   exit;
+  end;
+
   case DropAlign of
   alLeft:
     if Inside then
@@ -5806,6 +5915,8 @@
     case ResizePolicy of
     admrpChild:
       begin
+        if (Child.Parent<>nil)and(not(Child.Parent is TAnchorDockPanel))then
+        begin
         if Child.Align in [alLeft,alRight] then
           Child.Width:=Max(1,Min(ChildMaxSize.X,Child.Width+WidthDiff))
         else begin
@@ -5815,6 +5926,7 @@
           {$ENDIF}
           Child.Height:=i;
         end;
+        end;
       end;
     end;
   end;
Index: components/anchordocking/anchordockpanel.pas
===================================================================
--- components/anchordocking/anchordockpanel.pas	(nonexistent)
+++ components/anchordocking/anchordockpanel.pas	(working copy)
@@ -0,0 +1,80 @@
+unit AnchorDockPanel;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+  AnchorDockStorage;
+
+type
+  TAnchorDockPanel = class(TPanel)
+  private
+
+  protected
+    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+      var Accept: Boolean); override;
+
+
+  public
+
+    procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree;
+                         LayoutNode: TAnchorDockLayoutTreeNode);
+    function GetOneControl: TControl;
+
+  published
+
+  end;
+
+procedure Register;
+
+implementation
+uses AnchorDocking;
+procedure TAnchorDockPanel.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+  var Accept: Boolean);
+begin
+  Accept:=true;
+end;
+
+function TAnchorDockPanel.GetOneControl: TControl;
+var
+  i: Integer;
+begin
+  for i:=0 to ControlCount-1 do begin
+    Result:=Controls[i];
+    if Result.Owner<>Self then exit;
+  end;
+  Result:=nil;
+end;
+
+procedure TAnchorDockPanel.SaveLayout(
+  LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode);
+var
+  i: Integer;
+  Site: TAnchorDockHostSite;
+  ChildNode: TAnchorDockLayoutTreeNode;
+  Child: TControl;
+  Splitter: TAnchorDockSplitter;
+  OneControl: TControl;
+begin
+  OneControl:=GetOneControl;
+  if OneControl is TAnchorDockHostSite then
+  begin
+
+    LayoutNode.NodeType:=adltnControl;
+    LayoutNode.Assign(Self);
+    LayoutNode.Name:={OneControl.}Name;
+
+    TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode);
+  end;
+end;
+
+
+procedure Register;
+begin
+  {$I anchordockpanel_icon.lrs}
+  RegisterComponents('Additional',[TAnchorDockPanel]);
+end;
+
+end.
Index: components/anchordocking/anchordockpanel_icon.lrs
===================================================================
--- components/anchordocking/anchordockpanel_icon.lrs	(nonexistent)
+++ components/anchordocking/anchordockpanel_icon.lrs	(working copy)
@@ -0,0 +1,9 @@
+LazarusResources.Add('TAnchorDockPanel','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+  +#0#0'xIDATx^'#237#149'A'#10#132'0'#12'E'#127#134'^w'#214#230#8#174#167#23#26
+  +#157'k'#204#162'"x'#140'~Q'#232#166#184#146'F'#4#243' '#144#213#127#132'@"9g'
+  +#136#8#172#16#146#176'$'#148'F563'#245#253'[P '#185'W'#215'}'#216#130'-g'#252
+  +#14','#185#1#21')'#253'q'#150'yZP'#243#130#1#143#19#184#192#5'.pA88'#185'v'#2
+  +#213'h3Ays'#191'a'#228#213'O'#255#254'K^'#1#166'zsS'#138#185#218'6'#0#0#0#0
+  +'IEND'#174'B`'#130
+]);
Index: components/anchordocking/anchordockpkg.pas
===================================================================
--- components/anchordocking/anchordockpkg.pas	(revision 55460)
+++ components/anchordocking/anchordockpkg.pas	(working copy)
@@ -8,8 +8,16 @@
 interface
 
 uses
-  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg;
+  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg, 
+  AnchorDockPanel, LazarusPackageIntf;
 
 implementation
 
+procedure Register;
+begin
+  RegisterUnit('AnchorDockPanel', @AnchorDockPanel.Register);
+end;
+
+initialization
+  RegisterPackage('AnchorDocking', @Register);
 end.
Index: components/anchordocking/anchordockstorage.pas
===================================================================
--- components/anchordocking/anchordockstorage.pas	(revision 55460)
+++ components/anchordocking/anchordockstorage.pas	(working copy)
@@ -113,7 +113,7 @@
     procedure Clear;
     function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean;
     procedure Assign(Node: TAnchorDockLayoutTreeNode); overload;
-    procedure Assign(AControl: TControl); overload;
+    procedure Assign(AControl: TControl;OverrideBoundsRect:Boolean=false); overload;
     procedure LoadFromConfig(Config: TConfigStorage); overload;
     procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload;
     procedure SaveToConfig(Config: TConfigStorage); overload;
@@ -1113,13 +1113,16 @@
   end;
 end;
 
-procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl);
+procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl;OverrideBoundsRect:Boolean=false);
 var
   AnchorControl: TControl;
   a: TAnchorKind;
 begin
   Name:=AControl.Name;
-  BoundsRect:=AControl.BoundsRect;
+  if OverrideBoundsRect then
+    BoundsRect:=GetParentForm(AControl).BoundsRect
+  else
+    BoundsRect:=AControl.BoundsRect;
   Align:=AControl.Align;
   if (AControl.Parent=nil) and (AControl is TCustomForm) then begin
     WindowState:=TCustomForm(AControl).WindowState;

Mattias Gaertner

2017-07-07 20:59

manager  

anchordocking-tanchordockpanel-impl4.patch (20,287 bytes)   
Index: components/anchordocking/anchordocking.lpk
===================================================================
--- components/anchordocking/anchordocking.lpk	(revision 55460)
+++ components/anchordocking/anchordocking.lpk	(working copy)
@@ -2,6 +2,7 @@
 <CONFIG>
   <Package Version="4">
     <Name Value="AnchorDocking"/>
+    <Type Value="RunAndDesignTime"/>
     <AddToProjectUsesSection Value="True"/>
     <Author Value="Mattias Gaertner mattias@freepascal.org"/>
     <CompilerOptions>
@@ -18,7 +19,7 @@
     <License Value="modified LGPL-2 like LCL
 "/>
     <Version Minor="6"/>
-    <Files Count="7">
+    <Files Count="8">
       <Item1>
         <Filename Value="anchordockpkg.pas"/>
         <Type Value="Main Unit"/>
@@ -48,6 +49,11 @@
         <Filename Value="anchordockoptionsdlg.lfm"/>
         <Type Value="LFM"/>
       </Item7>
+      <Item8>
+        <Filename Value="anchordockpanel.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="AnchorDockPanel"/>
+      </Item8>
     </Files>
     <LazDoc Paths="doc"/>
     <i18n>
Index: components/anchordocking/anchordocking.pas
===================================================================
--- components/anchordocking/anchordocking.pas	(revision 55460)
+++ components/anchordocking/anchordocking.pas	(working copy)
@@ -102,7 +102,7 @@
   LCLType, LCLIntf, LCLProc,
   Controls, Forms, ExtCtrls, ComCtrls, Graphics, Themes, Menus, Buttons,
   LazConfigStorage, Laz2_XMLCfg, LazFileCache,
-  AnchorDockStr, AnchorDockStorage;
+  AnchorDockStr, AnchorDockStorage, AnchorDockPanel;
 
 {$IFDEF DebugDisableAutoSizing}
 const ADAutoSizingReason = 'TAnchorDockMaster Delayed';
@@ -307,7 +307,7 @@
                          OnlyCheckIfPossible: boolean): boolean;
     function EnlargeSideRotateSplitter(Side: TAnchorKind;
                          OnlyCheckIfPossible: boolean): boolean;
-    procedure CreateBoundSplitter;
+    procedure CreateBoundSplitter(Disabled: boolean=false);
     procedure PositionBoundSplitter;
   public
     constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
@@ -591,6 +591,8 @@
     procedure MakeDockSite(AForm: TCustomForm; Sites: TAnchors;
                            ResizePolicy: TADMResizePolicy;
                            AllowInside: boolean = false);
+    procedure MakeDockPanel(APanel:TAnchorDockPanel;
+                            ResizePolicy: TADMResizePolicy);
     procedure MakeVisible(AControl: TControl; SwitchPages: boolean);
     function ShowControl(ControlName: string; BringToFront: boolean = false): TControl;
     procedure CloseAll;
@@ -1572,7 +1574,7 @@
     end;
     if (Node.NodeType=adltnCustomSite) then begin
       AControl:=FindControl(Node.Name);
-      if IsCustomSite(AControl) then
+      if IsCustomSite(AControl) or (AControl is TAnchorDockPanel) then
         fTreeNameToDocker[Node.Name]:=AControl;
     end;
     for i:=0 to Node.Count-1 do
@@ -1648,6 +1650,11 @@
     if (fTreeNameToDocker[Node.Name]=nil) and (BestSite<>nil) then begin
       // search the parent site of a child site
       repeat
+        if BestSite is TAnchorDockPanel then begin
+          if fTreeNameToDocker.ControlToName(BestSite)='' then
+            fTreeNameToDocker[Node.Name]:=BestSite;
+          break;
+        end;
         BestSite:=BestSite.Parent;
         if BestSite is TAnchorDockHostSite then begin
           if fTreeNameToDocker.ControlToName(BestSite)='' then
@@ -1759,16 +1766,21 @@
     aMonitor: TMonitor;
     aHostSite: TAnchorDockHostSite;
   begin
+    if not (TObject (Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
         aMonitor:=Screen.Monitors[Node.Monitor]
       else
         aMonitor:=Site.Monitor;
+    end;
       WorkArea:=aMonitor.WorkareaRect;
       {$IFDEF VerboseAnchorDockRestore}
       debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
       {$ENDIF}
-    end;
+    end
+    else
+      GetParentForm(Site).BoundsRect:=Node.BoundsRect;
     if IsCustomSite(Site) then begin
       aManager:=TAnchorDockManager(Site.DockManager);
       if Node.Count>0 then begin
@@ -1783,8 +1795,15 @@
       NewBounds:=Rect(ScaleTopLvlX(NewBounds.Left),ScaleTopLvlY(NewBounds.Top),
                       ScaleTopLvlX(NewBounds.Right),ScaleTopLvlY(NewBounds.Bottom));
     end else begin
-      NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
+      if Parent is TAnchorDockPanel then
+      begin
+        NewBounds:=Rect(0,0,Parent.ClientWidth,Parent.ClientHeight);
+        Site.Align:=alClient;
+      end
+      else
+        NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
                       ScaleChildX(NewBounds.Right),ScaleChildY(NewBounds.Bottom));
+
     end;
     {$IFDEF VerboseAnchorDockRestore}
     if Scale then
@@ -1792,7 +1811,8 @@
     {$ENDIF}
     Site.BoundsRect:=NewBounds;
     Site.Visible:=true;
-    Site.Parent:=Parent;
+    if not (TObject (Site) is TAnchorDockPanel) then
+      Site.Parent:=Parent;
     if IsCustomSite(Parent) then begin
       aManager:=TAnchorDockManager(Parent.DockManager);
       Site.Align:=Node.Align;
@@ -1809,11 +1829,14 @@
       if (Node.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then
         aHostSite.FreePages;
     end;
+    if not (TObject(Site) is TAnchorDockPanel) then
+    begin
     if Parent=nil then begin
       Site.WindowState:=Node.WindowState;
     end else begin
       Site.WindowState:=wsNormal;
     end;
+    end;
   end;
 
   function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite;
@@ -1876,7 +1899,7 @@
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: can not find control ',Node.Name]);
         exit;
       end;
-      if not IsCustomSite(AControl) then begin
+      if not (IsCustomSite(AControl)or (AControl is TAnchorDockPanel)) then begin
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: ',Node.Name,' is not a custom dock site ',DbgSName(AControl)]);
         exit;
       end;
@@ -2705,7 +2728,7 @@
   AManager: TAnchorDockManager;
 begin
   if AForm.Name='' then
-    raise Exception.Create('TAnchorDockMaster.MakeDockable '+
+    raise Exception.Create('TAnchorDockMaster.MakeDockSite '+
       adrsMissingControlName);
   if AForm.DockManager<>nil then
     raise Exception.Create('TAnchorDockMaster.MakeDockSite DockManager<>nil');
@@ -2734,6 +2757,34 @@
   end;
 end;
 
+procedure TAnchorDockMaster.MakeDockPanel(APanel:TAnchorDockPanel;
+                                          ResizePolicy: TADMResizePolicy);
+var
+  AManager: TAnchorDockManager;
+begin
+  if APanel.Name='' then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel '+
+      adrsMissingControlName);
+  if APanel.DockManager<>nil then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel DockManager<>nil');
+  APanel.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  try
+    if FControls.IndexOf(APanel)<0 then begin
+      FControls.Add(APanel);
+      APanel.FreeNotification(Self);
+    end;
+    AManager:=ManagerClass.Create(APanel);
+    AManager.DockableSites:=[];
+    AManager.InsideDockingAllowed:=true;
+    AManager.ResizePolicy:=ResizePolicy;
+    APanel.DockManager:=AManager;
+    APanel.UseDockManager:=true;
+    APanel.DockSite:=true;
+  finally
+    APanel.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  end;
+end;
+
 procedure TAnchorDockMaster.MakeVisible(AControl: TControl; SwitchPages: boolean);
 begin
   while AControl<>nil do begin
@@ -2807,6 +2858,23 @@
   end;
 end;
 
+function GetParentFormOrDockPanel(Control: TControl): TCustomForm;
+begin
+  while (Control <> nil) and (Control.Parent <> nil) do
+  begin
+    if (Control is TAnchorDockPanel) then
+      Break;
+    Control := Control.Parent;
+  end;
+  if Control is TCustomForm then
+    Result := TCustomForm(Control)
+  else
+  if Control is TAnchorDockPanel then
+    Result := TCustomForm(Control)
+  else
+  Result := nil;
+end;
+
 procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree);
 var
   i: Integer;
@@ -2816,6 +2884,28 @@
   LayoutNode: TAnchorDockLayoutTreeNode;
   AForm: TCustomForm;
   VisibleControls: TStringList;
+
+  procedure SaveForm(theForm: TCustomForm; SaveChildren: boolean);
+  begin
+    // custom dock site
+    LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+    LayoutNode.NodeType:=adltnCustomSite;
+    LayoutNode.Assign(theForm,TObject(theForm) is TAnchorDockPanel);
+    // can have one normal dock site
+    if SaveChildren then
+    begin
+    Site:=TAnchorDockManager(theForm.DockManager).GetChildSite;
+    if Site<>nil then begin
+      LayoutNode:=LayoutTree.NewNode(LayoutNode);
+      Site.SaveLayout(LayoutTree,LayoutNode);
+      {if Site.BoundSplitter<>nil then begin
+        LayoutNode:=LayoutTree.NewNode(LayoutNode);
+        Site.BoundSplitter.SaveLayout(LayoutNode);
+      end;}
+    end;
+    end;
+  end;
+
 begin
   SavedSites:=TFPList.Create;
   VisibleControls:=TStringList.Create;
@@ -2824,31 +2914,23 @@
       AControl:=Controls[i];
       if not DockedControlIsVisible(AControl) then continue;
       VisibleControls.Add(AControl.Name);
-      AForm:=GetParentForm(AControl);
+      AForm:=GetParentFormOrDockPanel(AControl);
       if AForm=nil then continue;
       if SavedSites.IndexOf(AForm)>=0 then continue;
       SavedSites.Add(AForm);
       debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AForm)]);
       DebugWriteChildAnchors(AForm,true,true);
-      if (AForm is TAnchorDockHostSite) then begin
+      if (TObject(AForm) is TAnchorDockPanel) then begin
+        SaveForm(GetParentFormOrDockPanel(AForm),{false}true);
+        //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+        //TAnchorDockPanel(AForm).SaveLayout(LayoutTree,LayoutNode);
+      end
+      else if (AForm is TAnchorDockHostSite) then begin
         Site:=TAnchorDockHostSite(AForm);
         LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
         Site.SaveLayout(LayoutTree,LayoutNode);
       end else if IsCustomSite(AForm) then begin
-        // custom dock site
-        LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
-        LayoutNode.NodeType:=adltnCustomSite;
-        LayoutNode.Assign(AForm);
-        // can have one normal dock site
-        Site:=TAnchorDockManager(AForm.DockManager).GetChildSite;
-        if Site<>nil then begin
-          LayoutNode:=LayoutTree.NewNode(LayoutNode);
-          Site.SaveLayout(LayoutTree,LayoutNode);
-          {if Site.BoundSplitter<>nil then begin
-            LayoutNode:=LayoutTree.NewNode(LayoutNode);
-            Site.BoundSplitter.SaveLayout(LayoutNode);
-          end;}
-        end;
+        saveform(AForm,true);
       end else
         raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
     end;
@@ -2869,6 +2951,8 @@
   if (AForm is TAnchorDockHostSite) then begin
     Site:=TAnchorDockHostSite(AForm);
     Site.SaveLayout(LayoutTree,LayoutTree.Root);
+  end else if (TObject(AForm) is TAnchorDockPanel) then begin
+      (TObject(AForm) as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root);
   end else if IsCustomSite(AForm) then begin
     LayoutTree.Root.NodeType:=adltnCustomSite;
     LayoutTree.Root.Assign(AForm);
@@ -2907,7 +2991,7 @@
 begin
   if not IsSite(AControl) then
     raise Exception.Create('TAnchorDockMaster.CreateRestoreLayout: not a site '+DbgSName(AControl));
-  AForm:=GetParentForm(AControl);
+  AForm:=GetParentFormOrDockPanel(AControl);
   Result:=TAnchorDockRestoreLayout.Create(TAnchorDockLayoutTree.Create);
   if AForm=nil then exit;
   SaveSiteLayoutToTree(AForm,Result.Layout);
@@ -4779,7 +4863,7 @@
   end;
 end;
 
-procedure TAnchorDockHostSite.CreateBoundSplitter;
+procedure TAnchorDockHostSite.CreateBoundSplitter(Disabled: boolean);
 begin
   if BoundSplitter<>nil then exit;
   FBoundSplitter:=DockMaster.CreateSplitter;
@@ -4786,6 +4870,12 @@
   BoundSplitter.FreeNotification(Self);
   BoundSplitter.Align:=Align;
   BoundSplitter.Parent:=Parent;
+  if Disabled then
+  begin
+    BoundSplitter.Width:=0;
+    BoundSplitter.Height:=0;
+    BoundSplitter.Visible:=false;
+  end;
 end;
 
 procedure TAnchorDockHostSite.PositionBoundSplitter;
@@ -5545,10 +5635,13 @@
       ChildSite:=nil;
       if Child is TAnchorDockHostSite then begin
         ChildSite:=TAnchorDockHostSite(Child);
-        ChildSite.CreateBoundSplitter;
+        ChildSite.CreateBoundSplitter(Site is TAnchorDockPanel);
         SplitterWidth:=DockMaster.SplitterWidth;
       end;
 
+      if Site is TAnchorDockPanel then
+        ADockObject.DropAlign:=alClient;
+
       // resize Site
       NewSiteBounds:=Site.BoundsRect;
       case ADockObject.DropAlign of
@@ -5556,9 +5649,14 @@
       alRight: dec(NewSiteBounds.Right,Child.ClientWidth+SplitterWidth);
       alTop: dec(NewSiteBounds.Top,Child.ClientHeight+SplitterWidth);
       alBottom: inc(NewSiteBounds.Bottom,Child.ClientHeight+SplitterWidth);
+      alClient:begin
+                Child.BoundsRect:=Site.ClientRect;
+                Child.Align:=alClient;
+               end;
       end;
       if not StoredConstraintsValid then
         StoreConstraints;
+      if ADockObject.DropAlign<>alClient then
       if ADockObject.DropAlign in [alLeft,alRight] then
         Site.Constraints.MaxWidth:=0
       else
@@ -5576,8 +5674,13 @@
       alLeft: NewChildBounds:=Bounds(0,0,Child.ClientWidth,Site.ClientHeight);
       alRight: NewChildBounds:=Bounds(Site.ClientWidth-Child.ClientWidth,0,
                                       Child.ClientWidth,Site.ClientHeight);
+      alClient:begin
+                NewChildBounds:=Bounds(0,0,
+                                      Site.ClientWidth,Site.ClientHeight);
+               end;
       end;
       Child.BoundsRect:=NewChildBounds;
+      NewChildBounds:=Child.BoundsRect;
 
       if ChildSite<>nil then
         ChildSite.PositionBoundSplitter;
@@ -5641,6 +5744,12 @@
     or (Site.Parent.Parent<>nil) then
       Inside:=true;
   end;
+
+  if Site is TAnchorDockPanel then begin
+   DockRect:=Bounds(Site.ClientOrigin.x,Site.ClientOrigin.y,Site.ClientWidth,Site.ClientHeight);
+   exit;
+  end;
+
   case DropAlign of
   alLeft:
     if Inside then
@@ -5806,6 +5915,8 @@
     case ResizePolicy of
     admrpChild:
       begin
+        if (Child.Parent<>nil) and (not (Child.Parent is TAnchorDockPanel)) then
+        begin
         if Child.Align in [alLeft,alRight] then
           Child.Width:=Max(1,Min(ChildMaxSize.X,Child.Width+WidthDiff))
         else begin
@@ -5815,6 +5926,7 @@
           {$ENDIF}
           Child.Height:=i;
         end;
+        end;
       end;
     end;
   end;
Index: components/anchordocking/anchordockpanel.pas
===================================================================
--- components/anchordocking/anchordockpanel.pas	(nonexistent)
+++ components/anchordocking/anchordockpanel.pas	(working copy)
@@ -0,0 +1,80 @@
+unit AnchorDockPanel;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+  AnchorDockStorage;
+
+type
+  TAnchorDockPanel = class(TPanel)
+  private
+
+  protected
+    procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+      var Accept: Boolean); override;
+
+
+  public
+
+    procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree;
+                         LayoutNode: TAnchorDockLayoutTreeNode);
+    function GetOneControl: TControl;
+
+  published
+
+  end;
+
+procedure Register;
+
+implementation
+uses AnchorDocking;
+procedure TAnchorDockPanel.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+  var Accept: Boolean);
+begin
+  Accept:=true;
+end;
+
+function TAnchorDockPanel.GetOneControl: TControl;
+var
+  i: Integer;
+begin
+  for i:=0 to ControlCount-1 do begin
+    Result:=Controls[i];
+    if Result.Owner<>Self then exit;
+  end;
+  Result:=nil;
+end;
+
+procedure TAnchorDockPanel.SaveLayout(
+  LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode);
+var
+  i: Integer;
+  Site: TAnchorDockHostSite;
+  ChildNode: TAnchorDockLayoutTreeNode;
+  Child: TControl;
+  Splitter: TAnchorDockSplitter;
+  OneControl: TControl;
+begin
+  OneControl:=GetOneControl;
+  if OneControl is TAnchorDockHostSite then
+  begin
+
+    LayoutNode.NodeType:=adltnControl;
+    LayoutNode.Assign(Self);
+    LayoutNode.Name:={OneControl.}Name;
+
+    TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode);
+  end;
+end;
+
+
+procedure Register;
+begin
+  {$I anchordockpanel_icon.lrs}
+  RegisterComponents('Additional',[TAnchorDockPanel]);
+end;
+
+end.
Index: components/anchordocking/anchordockpanel_icon.lrs
===================================================================
--- components/anchordocking/anchordockpanel_icon.lrs	(nonexistent)
+++ components/anchordocking/anchordockpanel_icon.lrs	(working copy)
@@ -0,0 +1,9 @@
+LazarusResources.Add('TAnchorDockPanel','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+  +#0#0'xIDATx^'#237#149'A'#10#132'0'#12'E'#127#134'^w'#214#230#8#174#167#23#26
+  +#157'k'#204#162'"x'#140'~Q'#232#166#184#146'F'#4#243' '#144#213#127#132'@"9g'
+  +#136#8#172#16#146#176'$'#148'F563'#245#253'[P '#185'W'#215'}'#216#130'-g'#252
+  +#14','#185#1#21')'#253'q'#150'yZP'#243#130#1#143#19#184#192#5'.pA88'#185'v'#2
+  +#213'h3Ays'#191'a'#228#213'O'#255#254'K^'#1#166'zsS'#138#185#218'6'#0#0#0#0
+  +'IEND'#174'B`'#130
+]);
Index: components/anchordocking/anchordockpkg.pas
===================================================================
--- components/anchordocking/anchordockpkg.pas	(revision 55460)
+++ components/anchordocking/anchordockpkg.pas	(working copy)
@@ -8,8 +8,16 @@
 interface
 
 uses
-  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg;
+  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg, 
+  AnchorDockPanel, LazarusPackageIntf;
 
 implementation
 
+procedure Register;
+begin
+  RegisterUnit('AnchorDockPanel', @AnchorDockPanel.Register);
+end;
+
+initialization
+  RegisterPackage('AnchorDocking', @Register);
 end.
Index: components/anchordocking/anchordockstorage.pas
===================================================================
--- components/anchordocking/anchordockstorage.pas	(revision 55460)
+++ components/anchordocking/anchordockstorage.pas	(working copy)
@@ -113,7 +113,7 @@
     procedure Clear;
     function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean;
     procedure Assign(Node: TAnchorDockLayoutTreeNode); overload;
-    procedure Assign(AControl: TControl); overload;
+    procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload;
     procedure LoadFromConfig(Config: TConfigStorage); overload;
     procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload;
     procedure SaveToConfig(Config: TConfigStorage); overload;
@@ -1113,13 +1113,16 @@
   end;
 end;
 
-procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl);
+procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false);
 var
   AnchorControl: TControl;
   a: TAnchorKind;
 begin
   Name:=AControl.Name;
-  BoundsRect:=AControl.BoundsRect;
+  if OverrideBoundsRect then
+    BoundsRect:=GetParentForm(AControl).BoundsRect
+  else
+    BoundsRect:=AControl.BoundsRect;
   Align:=AControl.Align;
   if (AControl.Parent=nil) and (AControl is TCustomForm) then begin
     WindowState:=TCustomForm(AControl).WindowState;

Mattias Gaertner

2017-07-07 21:00

manager   ~0101573

I uploaded the patch with some fixed formatting.
Applying the patch breaks the IDE:

TApplication.HandleException Access violation
  Stack trace:
  $000000000048DD92 GETINFO, line 21 of include/monitor.inc
  $000000000048E0EC GETWORKAREARECT, line 72 of include/monitor.inc
  $00000000013407AA SETUPSITE, line 1777 of anchordocking.pas
  $000000000133FD7A RESTORE, line 1948 of anchordocking.pas
  $000000000133FACB RESTORE, line 1911 of anchordocking.pas
  $00000000013405D0 RESTORE, line 2028 of anchordocking.pas
  $000000000133F701 RESTORELAYOUT, line 2036 of anchordocking.pas
  $00000000013419ED FULLRESTORELAYOUT, line 2175 of anchordocking.pas
  $00000000013F2485 RESTOREDESKTOP, line 293 of anchordesktopoptions.pas
  $0000000000D22E93 RESTOREDESKTOP, line 1366 of environmentopts.pp
  $00000000004BA6F3 RESTOREIDEWINDOWS, line 2421 of main.pp
  $00000000004B55EE STARTIDE, line 1595 of main.pp
  $000000000041FF81 main, line 140 of lazarus.pp

Andrey Zubarev

2017-07-07 21:13

reporter   ~0101574

In windows Lazarus IDE works with patch.
On what operating system you have a breaks the IDE?

Mattias Gaertner

2017-07-07 21:18

manager   ~0101575

Linux/gtk2

Andrey Zubarev

2017-07-07 21:42

reporter   ~0101577

Last edited: 2017-07-07 22:05

View 2 revisions

Test in gtk2/qt/qt5 - works ok((
Show your environmentoptions.xml ?

upd.
You use multimonitor system?

Mattias Gaertner

2017-07-07 22:23

manager  

anchordocking-tanchordockpanel-impl5.patch (22,012 bytes)   
Index: components/anchordocking/anchordocking.lpk
===================================================================
--- components/anchordocking/anchordocking.lpk	(revision 55460)
+++ components/anchordocking/anchordocking.lpk	(working copy)
@@ -2,6 +2,7 @@
 <CONFIG>
   <Package Version="4">
     <Name Value="AnchorDocking"/>
+    <Type Value="RunAndDesignTime"/>
     <AddToProjectUsesSection Value="True"/>
     <Author Value="Mattias Gaertner mattias@freepascal.org"/>
     <CompilerOptions>
@@ -18,7 +19,7 @@
     <License Value="modified LGPL-2 like LCL
 "/>
     <Version Minor="6"/>
-    <Files Count="7">
+    <Files Count="8">
       <Item1>
         <Filename Value="anchordockpkg.pas"/>
         <Type Value="Main Unit"/>
@@ -48,6 +49,11 @@
         <Filename Value="anchordockoptionsdlg.lfm"/>
         <Type Value="LFM"/>
       </Item7>
+      <Item8>
+        <Filename Value="anchordockpanel.pas"/>
+        <HasRegisterProc Value="True"/>
+        <UnitName Value="AnchorDockPanel"/>
+      </Item8>
     </Files>
     <LazDoc Paths="doc"/>
     <i18n>
Index: components/anchordocking/anchordocking.pas
===================================================================
--- components/anchordocking/anchordocking.pas	(revision 55460)
+++ components/anchordocking/anchordocking.pas	(working copy)
@@ -102,7 +102,7 @@
   LCLType, LCLIntf, LCLProc,
   Controls, Forms, ExtCtrls, ComCtrls, Graphics, Themes, Menus, Buttons,
   LazConfigStorage, Laz2_XMLCfg, LazFileCache,
-  AnchorDockStr, AnchorDockStorage;
+  AnchorDockStr, AnchorDockStorage, AnchorDockPanel;
 
 {$IFDEF DebugDisableAutoSizing}
 const ADAutoSizingReason = 'TAnchorDockMaster Delayed';
@@ -307,7 +307,7 @@
                          OnlyCheckIfPossible: boolean): boolean;
     function EnlargeSideRotateSplitter(Side: TAnchorKind;
                          OnlyCheckIfPossible: boolean): boolean;
-    procedure CreateBoundSplitter;
+    procedure CreateBoundSplitter(Disabled: boolean=false);
     procedure PositionBoundSplitter;
   public
     constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override;
@@ -591,6 +591,8 @@
     procedure MakeDockSite(AForm: TCustomForm; Sites: TAnchors;
                            ResizePolicy: TADMResizePolicy;
                            AllowInside: boolean = false);
+    procedure MakeDockPanel(APanel:TAnchorDockPanel;
+                            ResizePolicy: TADMResizePolicy);
     procedure MakeVisible(AControl: TControl; SwitchPages: boolean);
     function ShowControl(ControlName: string; BringToFront: boolean = false): TControl;
     procedure CloseAll;
@@ -1572,7 +1574,7 @@
     end;
     if (Node.NodeType=adltnCustomSite) then begin
       AControl:=FindControl(Node.Name);
-      if IsCustomSite(AControl) then
+      if IsCustomSite(AControl) or (AControl is TAnchorDockPanel) then
         fTreeNameToDocker[Node.Name]:=AControl;
     end;
     for i:=0 to Node.Count-1 do
@@ -1648,6 +1650,11 @@
     if (fTreeNameToDocker[Node.Name]=nil) and (BestSite<>nil) then begin
       // search the parent site of a child site
       repeat
+        if BestSite is TAnchorDockPanel then begin
+          if fTreeNameToDocker.ControlToName(BestSite)='' then
+            fTreeNameToDocker[Node.Name]:=BestSite;
+          break;
+        end;
         BestSite:=BestSite.Parent;
         if BestSite is TAnchorDockHostSite then begin
           if fTreeNameToDocker.ControlToName(BestSite)='' then
@@ -1759,15 +1766,19 @@
     aMonitor: TMonitor;
     aHostSite: TAnchorDockHostSite;
   begin
-    if Parent=nil then begin
-      if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
-        aMonitor:=Screen.Monitors[Node.Monitor]
-      else
-        aMonitor:=Site.Monitor;
-      WorkArea:=aMonitor.WorkareaRect;
-      {$IFDEF VerboseAnchorDockRestore}
-      debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
-      {$ENDIF}
+    if TObject(Site) is TAnchorDockPanel then
+      GetParentForm(Site).BoundsRect:=Node.BoundsRect
+    else begin
+      if Parent=nil then begin
+        if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
+          aMonitor:=Screen.Monitors[Node.Monitor]
+        else
+          aMonitor:=Site.Monitor;
+        WorkArea:=aMonitor.WorkareaRect;
+        {$IFDEF VerboseAnchorDockRestore}
+        debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
+        {$ENDIF}
+      end;
     end;
     if IsCustomSite(Site) then begin
       aManager:=TAnchorDockManager(Site.DockManager);
@@ -1783,8 +1794,15 @@
       NewBounds:=Rect(ScaleTopLvlX(NewBounds.Left),ScaleTopLvlY(NewBounds.Top),
                       ScaleTopLvlX(NewBounds.Right),ScaleTopLvlY(NewBounds.Bottom));
     end else begin
-      NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
+      if Parent is TAnchorDockPanel then
+      begin
+        NewBounds:=Rect(0,0,Parent.ClientWidth,Parent.ClientHeight);
+        Site.Align:=alClient;
+      end
+      else
+        NewBounds:=Rect(ScaleChildX(NewBounds.Left),ScaleChildY(NewBounds.Top),
                       ScaleChildX(NewBounds.Right),ScaleChildY(NewBounds.Bottom));
+
     end;
     {$IFDEF VerboseAnchorDockRestore}
     if Scale then
@@ -1792,7 +1810,8 @@
     {$ENDIF}
     Site.BoundsRect:=NewBounds;
     Site.Visible:=true;
-    Site.Parent:=Parent;
+    if not (TObject(Site) is TAnchorDockPanel) then
+      Site.Parent:=Parent;
     if IsCustomSite(Parent) then begin
       aManager:=TAnchorDockManager(Parent.DockManager);
       Site.Align:=Node.Align;
@@ -1809,10 +1828,13 @@
       if (Node.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then
         aHostSite.FreePages;
     end;
-    if Parent=nil then begin
-      Site.WindowState:=Node.WindowState;
-    end else begin
-      Site.WindowState:=wsNormal;
+    if not (TObject(Site) is TAnchorDockPanel) then
+    begin
+      if Parent=nil then begin
+        Site.WindowState:=Node.WindowState;
+      end else begin
+        Site.WindowState:=wsNormal;
+      end;
     end;
   end;
 
@@ -1876,7 +1898,7 @@
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: can not find control ',Node.Name]);
         exit;
       end;
-      if not IsCustomSite(AControl) then begin
+      if not (IsCustomSite(AControl) or (AControl is TAnchorDockPanel)) then begin
         debugln(['TAnchorDockMaster.RestoreLayout.Restore WARNING: ',Node.Name,' is not a custom dock site ',DbgSName(AControl)]);
         exit;
       end;
@@ -2705,7 +2727,7 @@
   AManager: TAnchorDockManager;
 begin
   if AForm.Name='' then
-    raise Exception.Create('TAnchorDockMaster.MakeDockable '+
+    raise Exception.Create('TAnchorDockMaster.MakeDockSite '+
       adrsMissingControlName);
   if AForm.DockManager<>nil then
     raise Exception.Create('TAnchorDockMaster.MakeDockSite DockManager<>nil');
@@ -2734,6 +2756,34 @@
   end;
 end;
 
+procedure TAnchorDockMaster.MakeDockPanel(APanel:TAnchorDockPanel;
+                                          ResizePolicy: TADMResizePolicy);
+var
+  AManager: TAnchorDockManager;
+begin
+  if APanel.Name='' then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel '+
+      adrsMissingControlName);
+  if APanel.DockManager<>nil then
+    raise Exception.Create('TAnchorDockMaster.MakeDockPanel DockManager<>nil');
+  APanel.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  try
+    if FControls.IndexOf(APanel)<0 then begin
+      FControls.Add(APanel);
+      APanel.FreeNotification(Self);
+    end;
+    AManager:=ManagerClass.Create(APanel);
+    AManager.DockableSites:=[];
+    AManager.InsideDockingAllowed:=true;
+    AManager.ResizePolicy:=ResizePolicy;
+    APanel.DockManager:=AManager;
+    APanel.UseDockManager:=true;
+    APanel.DockSite:=true;
+  finally
+    APanel.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster.MakeDockPanel'){$ENDIF};
+  end;
+end;
+
 procedure TAnchorDockMaster.MakeVisible(AControl: TControl; SwitchPages: boolean);
 begin
   while AControl<>nil do begin
@@ -2807,6 +2857,22 @@
   end;
 end;
 
+function GetParentFormOrDockPanel(Control: TControl): TCustomForm;
+begin
+  while (Control <> nil) and (Control.Parent <> nil) do
+  begin
+    if (Control is TAnchorDockPanel) then
+      Break;
+    Control := Control.Parent;
+  end;
+  if Control is TCustomForm then
+    Result := TCustomForm(Control)
+  else if Control is TAnchorDockPanel then
+    Result := TCustomForm(Control)
+  else
+    Result := nil;
+end;
+
 procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree);
 var
   i: Integer;
@@ -2816,6 +2882,28 @@
   LayoutNode: TAnchorDockLayoutTreeNode;
   AForm: TCustomForm;
   VisibleControls: TStringList;
+
+  procedure SaveForm(theForm: TCustomForm; SaveChildren: boolean);
+  begin
+    // custom dock site
+    LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+    LayoutNode.NodeType:=adltnCustomSite;
+    LayoutNode.Assign(theForm,TObject(theForm) is TAnchorDockPanel);
+    // can have one normal dock site
+    if SaveChildren then
+    begin
+      Site:=TAnchorDockManager(theForm.DockManager).GetChildSite;
+      if Site<>nil then begin
+        LayoutNode:=LayoutTree.NewNode(LayoutNode);
+        Site.SaveLayout(LayoutTree,LayoutNode);
+        {if Site.BoundSplitter<>nil then begin
+          LayoutNode:=LayoutTree.NewNode(LayoutNode);
+          Site.BoundSplitter.SaveLayout(LayoutNode);
+        end;}
+      end;
+    end;
+  end;
+
 begin
   SavedSites:=TFPList.Create;
   VisibleControls:=TStringList.Create;
@@ -2824,31 +2912,22 @@
       AControl:=Controls[i];
       if not DockedControlIsVisible(AControl) then continue;
       VisibleControls.Add(AControl.Name);
-      AForm:=GetParentForm(AControl);
+      AForm:=GetParentFormOrDockPanel(AControl);
       if AForm=nil then continue;
       if SavedSites.IndexOf(AForm)>=0 then continue;
       SavedSites.Add(AForm);
       debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AForm)]);
       DebugWriteChildAnchors(AForm,true,true);
-      if (AForm is TAnchorDockHostSite) then begin
+      if TObject(AForm) is TAnchorDockPanel then begin
+        SaveForm(GetParentFormOrDockPanel(AForm),{false}true);
+        //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
+        //TAnchorDockPanel(AForm).SaveLayout(LayoutTree,LayoutNode);
+      end else if AForm is TAnchorDockHostSite then begin
         Site:=TAnchorDockHostSite(AForm);
         LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
         Site.SaveLayout(LayoutTree,LayoutNode);
       end else if IsCustomSite(AForm) then begin
-        // custom dock site
-        LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
-        LayoutNode.NodeType:=adltnCustomSite;
-        LayoutNode.Assign(AForm);
-        // can have one normal dock site
-        Site:=TAnchorDockManager(AForm.DockManager).GetChildSite;
-        if Site<>nil then begin
-          LayoutNode:=LayoutTree.NewNode(LayoutNode);
-          Site.SaveLayout(LayoutTree,LayoutNode);
-          {if Site.BoundSplitter<>nil then begin
-            LayoutNode:=LayoutTree.NewNode(LayoutNode);
-            Site.BoundSplitter.SaveLayout(LayoutNode);
-          end;}
-        end;
+        SaveForm(AForm,true);
       end else
         raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
     end;
@@ -2866,9 +2945,11 @@
   LayoutNode: TAnchorDockLayoutTreeNode;
   Site: TAnchorDockHostSite;
 begin
-  if (AForm is TAnchorDockHostSite) then begin
+  if AForm is TAnchorDockHostSite then begin
     Site:=TAnchorDockHostSite(AForm);
     Site.SaveLayout(LayoutTree,LayoutTree.Root);
+  end else if TObject(AForm) is TAnchorDockPanel then begin
+    (TObject(AForm) as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root);
   end else if IsCustomSite(AForm) then begin
     LayoutTree.Root.NodeType:=adltnCustomSite;
     LayoutTree.Root.Assign(AForm);
@@ -2907,7 +2988,7 @@
 begin
   if not IsSite(AControl) then
     raise Exception.Create('TAnchorDockMaster.CreateRestoreLayout: not a site '+DbgSName(AControl));
-  AForm:=GetParentForm(AControl);
+  AForm:=GetParentFormOrDockPanel(AControl);
   Result:=TAnchorDockRestoreLayout.Create(TAnchorDockLayoutTree.Create);
   if AForm=nil then exit;
   SaveSiteLayoutToTree(AForm,Result.Layout);
@@ -4779,7 +4860,7 @@
   end;
 end;
 
-procedure TAnchorDockHostSite.CreateBoundSplitter;
+procedure TAnchorDockHostSite.CreateBoundSplitter(Disabled: boolean);
 begin
   if BoundSplitter<>nil then exit;
   FBoundSplitter:=DockMaster.CreateSplitter;
@@ -4786,6 +4867,12 @@
   BoundSplitter.FreeNotification(Self);
   BoundSplitter.Align:=Align;
   BoundSplitter.Parent:=Parent;
+  if Disabled then
+  begin
+    BoundSplitter.Width:=0;
+    BoundSplitter.Height:=0;
+    BoundSplitter.Visible:=false;
+  end;
 end;
 
 procedure TAnchorDockHostSite.PositionBoundSplitter;
@@ -5545,10 +5632,13 @@
       ChildSite:=nil;
       if Child is TAnchorDockHostSite then begin
         ChildSite:=TAnchorDockHostSite(Child);
-        ChildSite.CreateBoundSplitter;
+        ChildSite.CreateBoundSplitter(Site is TAnchorDockPanel);
         SplitterWidth:=DockMaster.SplitterWidth;
       end;
 
+      if Site is TAnchorDockPanel then
+        ADockObject.DropAlign:=alClient;
+
       // resize Site
       NewSiteBounds:=Site.BoundsRect;
       case ADockObject.DropAlign of
@@ -5556,14 +5646,18 @@
       alRight: dec(NewSiteBounds.Right,Child.ClientWidth+SplitterWidth);
       alTop: dec(NewSiteBounds.Top,Child.ClientHeight+SplitterWidth);
       alBottom: inc(NewSiteBounds.Bottom,Child.ClientHeight+SplitterWidth);
+      alClient: ;
       end;
       if not StoredConstraintsValid then
         StoreConstraints;
       if ADockObject.DropAlign in [alLeft,alRight] then
         Site.Constraints.MaxWidth:=0
-      else
+      else if ADockObject.DropAlign in [alTop,alBottom] then
         Site.Constraints.MaxHeight:=0;
       Site.BoundsRect:=NewSiteBounds;
+      if ADockObject.DropAlign=alClient then
+        Child.Align:=alClient;
+
       //debugln(['TAnchorDockManager.InsertControl Site.BoundsRect=',dbgs(Site.BoundsRect),' NewSiteBounds=',dbgs(NewSiteBounds),' Child.ClientRect=',dbgs(Child.ClientRect)]);
       FSiteClientRect:=Site.ClientRect;
 
@@ -5576,8 +5670,11 @@
       alLeft: NewChildBounds:=Bounds(0,0,Child.ClientWidth,Site.ClientHeight);
       alRight: NewChildBounds:=Bounds(Site.ClientWidth-Child.ClientWidth,0,
                                       Child.ClientWidth,Site.ClientHeight);
+      alClient: NewChildBounds:=Bounds(0,0,
+                                       Site.ClientWidth,Site.ClientHeight);
       end;
       Child.BoundsRect:=NewChildBounds;
+      NewChildBounds:=Child.BoundsRect;
 
       if ChildSite<>nil then
         ChildSite.PositionBoundSplitter;
@@ -5641,6 +5738,12 @@
     or (Site.Parent.Parent<>nil) then
       Inside:=true;
   end;
+
+  if Site is TAnchorDockPanel then begin
+    DockRect:=Bounds(Site.ClientOrigin.x,Site.ClientOrigin.y,Site.ClientWidth,Site.ClientHeight);
+    exit;
+  end;
+
   case DropAlign of
   alLeft:
     if Inside then
@@ -5806,14 +5909,18 @@
     case ResizePolicy of
     admrpChild:
       begin
-        if Child.Align in [alLeft,alRight] then
-          Child.Width:=Max(1,Min(ChildMaxSize.X,Child.Width+WidthDiff))
+        if Child.Parent is TAnchorDockPanel then
+          //
         else begin
-          i:=Max(1,Min(ChildMaxSize.Y,Child.Height+HeightDiff));
-          {$IFDEF VerboseAnchorDockRestore}
-          debugln(['TAnchorDockManager.ResetBounds Child=',DbgSName(Child),' OldHeight=',Child.Height,' NewHeight=',i]);
-          {$ENDIF}
-          Child.Height:=i;
+          if Child.Align in [alLeft,alRight] then
+            Child.Width:=Max(1,Min(ChildMaxSize.X,Child.Width+WidthDiff))
+          else begin
+            i:=Max(1,Min(ChildMaxSize.Y,Child.Height+HeightDiff));
+            {$IFDEF VerboseAnchorDockRestore}
+            debugln(['TAnchorDockManager.ResetBounds Child=',DbgSName(Child),' OldHeight=',Child.Height,' NewHeight=',i]);
+            {$ENDIF}
+            Child.Height:=i;
+          end;
         end;
       end;
     end;
Index: components/anchordocking/anchordockpanel.pas
===================================================================
--- components/anchordocking/anchordockpanel.pas	(nonexistent)
+++ components/anchordocking/anchordockpanel.pas	(working copy)
@@ -0,0 +1,71 @@
+{ For license see anchordocking.pas
+}
+unit AnchorDockPanel;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+  AnchorDockStorage;
+
+type
+  TAnchorDockPanel = class(TPanel)
+  protected
+    procedure DragOver({%H-}Source: TObject; {%H-}X, {%H-}Y: Integer; {%H-}State: TDragState;
+      var Accept: Boolean); override;
+  public
+    procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree;
+                         LayoutNode: TAnchorDockLayoutTreeNode);
+    function GetOneControl: TControl;
+  published
+  end;
+
+procedure Register;
+
+implementation
+
+uses AnchorDocking;
+
+procedure TAnchorDockPanel.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
+  var Accept: Boolean);
+begin
+  Accept:=true;
+end;
+
+function TAnchorDockPanel.GetOneControl: TControl;
+var
+  i: Integer;
+begin
+  for i:=0 to ControlCount-1 do begin
+    Result:=Controls[i];
+    if Result.Owner<>Self then exit;
+  end;
+  Result:=nil;
+end;
+
+procedure TAnchorDockPanel.SaveLayout(
+  LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode);
+var
+  OneControl: TControl;
+begin
+  OneControl:=GetOneControl;
+  if OneControl is TAnchorDockHostSite then
+  begin
+
+    LayoutNode.NodeType:=adltnControl;
+    LayoutNode.Assign(Self);
+    LayoutNode.Name:={OneControl.}Name;
+
+    TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode);
+  end;
+end;
+
+procedure Register;
+begin
+  {$I anchordockpanel_icon.lrs}
+  RegisterComponents('Additional',[TAnchorDockPanel]);
+end;
+
+end.

Property changes on: components/anchordocking/anchordockpanel.pas
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: components/anchordocking/anchordockpanel_icon.lrs
===================================================================
--- components/anchordocking/anchordockpanel_icon.lrs	(nonexistent)
+++ components/anchordocking/anchordockpanel_icon.lrs	(working copy)
@@ -0,0 +1,9 @@
+LazarusResources.Add('TAnchorDockPanel','PNG',[
+  #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+  +#0#0'xIDATx^'#237#149'A'#10#132'0'#12'E'#127#134'^w'#214#230#8#174#167#23#26
+  +#157'k'#204#162'"x'#140'~Q'#232#166#184#146'F'#4#243' '#144#213#127#132'@"9g'
+  +#136#8#172#16#146#176'$'#148'F563'#245#253'[P '#185'W'#215'}'#216#130'-g'#252
+  +#14','#185#1#21')'#253'q'#150'yZP'#243#130#1#143#19#184#192#5'.pA88'#185'v'#2
+  +#213'h3Ays'#191'a'#228#213'O'#255#254'K^'#1#166'zsS'#138#185#218'6'#0#0#0#0
+  +'IEND'#174'B`'#130
+]);

Property changes on: components/anchordocking/anchordockpanel_icon.lrs
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: components/anchordocking/anchordockpkg.pas
===================================================================
--- components/anchordocking/anchordockpkg.pas	(revision 55460)
+++ components/anchordocking/anchordockpkg.pas	(working copy)
@@ -8,8 +8,16 @@
 interface
 
 uses
-  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg;
+  AnchorDocking, AnchorDockStorage, AnchorDockStr, AnchorDockOptionsDlg, 
+  AnchorDockPanel, LazarusPackageIntf;
 
 implementation
 
+procedure Register;
+begin
+  RegisterUnit('AnchorDockPanel', @AnchorDockPanel.Register);
+end;
+
+initialization
+  RegisterPackage('AnchorDocking', @Register);
 end.
Index: components/anchordocking/anchordockstorage.pas
===================================================================
--- components/anchordocking/anchordockstorage.pas	(revision 55460)
+++ components/anchordocking/anchordockstorage.pas	(working copy)
@@ -113,7 +113,7 @@
     procedure Clear;
     function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean;
     procedure Assign(Node: TAnchorDockLayoutTreeNode); overload;
-    procedure Assign(AControl: TControl); overload;
+    procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload;
     procedure LoadFromConfig(Config: TConfigStorage); overload;
     procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload;
     procedure SaveToConfig(Config: TConfigStorage); overload;
@@ -1113,13 +1113,16 @@
   end;
 end;
 
-procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl);
+procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false);
 var
   AnchorControl: TControl;
   a: TAnchorKind;
 begin
   Name:=AControl.Name;
-  BoundsRect:=AControl.BoundsRect;
+  if OverrideBoundsRect then
+    BoundsRect:=GetParentForm(AControl).BoundsRect
+  else
+    BoundsRect:=AControl.BoundsRect;
   Align:=AControl.Align;
   if (AControl.Parent=nil) and (AControl is TCustomForm) then begin
     WindowState:=TCustomForm(AControl).WindowState;
Index: lcl/controls.pp
===================================================================
--- lcl/controls.pp	(revision 55460)
+++ lcl/controls.pp	(working copy)
@@ -554,7 +554,7 @@
 
 type
   { TDockManager is an abstract class for managing a dock site's docked
-    controls. See TDockTree below for the more info.
+    controls. See TDockTree below for more info.
     }
   TDockManager = class(TPersistent)
   public

Mattias Gaertner

2017-07-07 22:27

manager   ~0101581

I fixed some bugs. Now it works.
My source editor is docked to the bottom of the mainbar.

But casting a non form to a form is a no-go.
Can TAnchorDockPanel be changed to a customform?

Andrey Zubarev

2017-07-07 22:42

reporter   ~0101583

Thanks!

>>Can TAnchorDockPanel be changed to a customform?
Probably yes, but why? in functionality it's a simply panel

Andrey Zubarev

2017-07-07 22:51

reporter   ~0101584

There is a check like
 if not (TObject (Site) is TAnchorDockPanel) ...
but I'm not using not form as form

Andrey Zubarev

2017-07-07 23:25

reporter   ~0101590

TAnchorDockPanel=class(TCustomForm) carries too many problems with designer and run time. in my opinion

Andrey Zubarev

2017-07-08 09:46

reporter  

Andrey Zubarev

2017-07-08 09:49

reporter   ~0101596

miniidewithdockpanel-example.patch is old. new version miniidewithdockpanel-example2.patch

This simple app with dockable forms, dockable toolbars and status bar

Juha Manninen

2017-08-06 21:04

developer   ~0102089

Last edited: 2017-08-06 21:07

View 2 revisions

I applied the anchordocking-tanchordockpanel-impl5.patch in r55638.
My IDE works well with it using both GTK2 and QT widgetsets. Thanks.

The miniidewithdockpanel-example2.patch has everything doubled. The size is twice what it should be.
The original example patch had the same problem.
I understand the example project is totally new, it does not patch existing files. Thus you should maybe just zip the files together and upload here. I would like to commit an example for this new AnchorDockPanel.

Andrey Zubarev

2017-08-06 21:17

reporter  

miniidewithdockpanel.zip (90,037 bytes)

Andrey Zubarev

2017-08-06 21:20

reporter   ~0102090

Thanks!

Technically it is new, but this is actually slightly modified original miniide example, adapted for the new docking and toolbars.

miniidewithdockpanel.zip added

Juha Manninen

2017-08-07 09:34

developer   ~0102096

I applied the example. Thanks.
I guess there should be one example project demostrating the whole thing but that can be fixed later.

Mattias Gaertner

2017-08-07 09:41

manager   ~0102097

Juha, have you seen my note "But casting a non form to a form is a no-go."?

Andrey Zubarev

2017-08-07 14:24

reporter  

anchordocking-tanchordockpanel-lesscasting.patch (7,163 bytes)   
Index: components/anchordocking/anchordocking.pas
===================================================================
--- components/anchordocking/anchordocking.pas	(revision 55641)
+++ components/anchordocking/anchordocking.pas	(working copy)
@@ -601,7 +601,7 @@
     // save/restore layouts
     procedure SaveLayoutToConfig(Config: TConfigStorage);
     procedure SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree);
-    procedure SaveSiteLayoutToTree(AForm: TCustomForm;
+    procedure SaveSiteLayoutToTree(AControl: TWinControl;
                                    LayoutTree: TAnchorDockLayoutTree);
     function CreateRestoreLayout(AControl: TControl): TAnchorDockRestoreLayout;
     function ConfigIsEmpty(Config: TConfigStorage): boolean;
@@ -1759,7 +1759,7 @@
                 div (SrcWorkArea.Bottom-SrcWorkArea.Top);
   end;
 
-  procedure SetupSite(Site: TCustomForm;
+  procedure SetupSite(Site: TWinControl;
     Node: TAnchorDockLayoutTreeNode; Parent: TWinControl);
   var
     aManager: TAnchorDockManager;
@@ -1767,7 +1767,7 @@
     aMonitor: TMonitor;
     aHostSite: TAnchorDockHostSite;
   begin
-    if TObject(Site) is TAnchorDockPanel then
+    if Site is TAnchorDockPanel then
       GetParentForm(Site).BoundsRect:=Node.BoundsRect
     else begin
       if Parent=nil then begin
@@ -1774,7 +1774,12 @@
         if (Node.Monitor>=0) and (Node.Monitor<Screen.MonitorCount) then
           aMonitor:=Screen.Monitors[Node.Monitor]
         else
-          aMonitor:=Site.Monitor;
+          begin
+            if site is TCustomForm then
+               aMonitor:=(Site as TCustomForm).Monitor
+            else
+               aMonitor:=GetParentForm(Site).Monitor;
+          end;
         WorkArea:=aMonitor.WorkareaRect;
         {$IFDEF VerboseAnchorDockRestore}
         debugln(['TAnchorDockMaster.RestoreLayout.SetupSite WorkArea=',dbgs(WorkArea)]);
@@ -1811,7 +1816,7 @@
     {$ENDIF}
     Site.BoundsRect:=NewBounds;
     Site.Visible:=true;
-    if not (TObject(Site) is TAnchorDockPanel) then
+    if not (Site is TAnchorDockPanel) then
       Site.Parent:=Parent;
     if IsCustomSite(Parent) then begin
       aManager:=TAnchorDockManager(Parent.DockManager);
@@ -1832,9 +1837,11 @@
     if not (TObject(Site) is TAnchorDockPanel) then
     begin
       if Parent=nil then begin
-        Site.WindowState:=Node.WindowState;
+        if Site is TCustomForm then
+          (Site as TCustomForm).WindowState:=Node.WindowState;
       end else begin
-        Site.WindowState:=wsNormal;
+        if Site is TCustomForm then
+          (Site as TCustomForm).WindowState:=wsNormal;
       end;
     end;
   end;
@@ -2881,19 +2888,19 @@
   Site: TAnchorDockHostSite;
   SavedSites: TFPList;
   LayoutNode: TAnchorDockLayoutTreeNode;
-  AForm: TCustomForm;
+  AFormOrDockPanel: TWinControl;
   VisibleControls: TStringList;
 
-  procedure SaveForm(theForm: TCustomForm; SaveChildren: boolean);
+  procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean);
   begin
     // custom dock site
     LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
     LayoutNode.NodeType:=adltnCustomSite;
-    LayoutNode.Assign(theForm,TObject(theForm) is TAnchorDockPanel);
+    LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel);
     // can have one normal dock site
     if SaveChildren then
     begin
-      Site:=TAnchorDockManager(theForm.DockManager).GetChildSite;
+      Site:=TAnchorDockManager(theFormOrDockPanel.DockManager).GetChildSite;
       if Site<>nil then begin
         LayoutNode:=LayoutTree.NewNode(LayoutNode);
         Site.SaveLayout(LayoutTree,LayoutNode);
@@ -2913,22 +2920,22 @@
       AControl:=Controls[i];
       if not DockedControlIsVisible(AControl) then continue;
       VisibleControls.Add(AControl.Name);
-      AForm:=GetParentFormOrDockPanel(AControl);
-      if AForm=nil then continue;
-      if SavedSites.IndexOf(AForm)>=0 then continue;
-      SavedSites.Add(AForm);
-      debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AForm)]);
-      DebugWriteChildAnchors(AForm,true,true);
-      if TObject(AForm) is TAnchorDockPanel then begin
-        SaveForm(GetParentFormOrDockPanel(AForm),{false}true);
+      AFormOrDockPanel:=GetParentFormOrDockPanel(AControl);
+      if AFormOrDockPanel=nil then continue;
+      if SavedSites.IndexOf(AFormOrDockPanel)>=0 then continue;
+      SavedSites.Add(AFormOrDockPanel);
+      debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]);
+      DebugWriteChildAnchors(AFormOrDockPanel,true,true);
+      if AFormOrDockPanel is TAnchorDockPanel then begin
+        SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true);
         //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
-        //TAnchorDockPanel(AForm).SaveLayout(LayoutTree,LayoutNode);
-      end else if AForm is TAnchorDockHostSite then begin
-        Site:=TAnchorDockHostSite(AForm);
+        //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode);
+      end else if AFormOrDockPanel is TAnchorDockHostSite then begin
+        Site:=TAnchorDockHostSite(AFormOrDockPanel);
         LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
         Site.SaveLayout(LayoutTree,LayoutNode);
-      end else if IsCustomSite(AForm) then begin
-        SaveForm(AForm,true);
+      end else if IsCustomSite(AFormOrDockPanel) then begin
+        SaveFormOrDockPanel(AFormOrDockPanel,true);
       end else
         raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
     end;
@@ -2940,28 +2947,28 @@
   end;
 end;
 
-procedure TAnchorDockMaster.SaveSiteLayoutToTree(AForm: TCustomForm;
+procedure TAnchorDockMaster.SaveSiteLayoutToTree(AControl: TWinControl;
   LayoutTree: TAnchorDockLayoutTree);
 var
   LayoutNode: TAnchorDockLayoutTreeNode;
   Site: TAnchorDockHostSite;
 begin
-  if AForm is TAnchorDockHostSite then begin
-    Site:=TAnchorDockHostSite(AForm);
+  if AControl is TAnchorDockHostSite then begin
+    Site:=TAnchorDockHostSite(AControl);
     Site.SaveLayout(LayoutTree,LayoutTree.Root);
-  end else if TObject(AForm) is TAnchorDockPanel then begin
-    (TObject(AForm) as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root);
-  end else if IsCustomSite(AForm) then begin
+  end else if AControl is TAnchorDockPanel then begin
+    (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root);
+  end else if IsCustomSite(AControl) then begin
     LayoutTree.Root.NodeType:=adltnCustomSite;
-    LayoutTree.Root.Assign(AForm);
+    LayoutTree.Root.Assign(AControl);
     // can have one normal dock site
-    Site:=TAnchorDockManager(AForm.DockManager).GetChildSite;
+    Site:=TAnchorDockManager(AControl.DockManager).GetChildSite;
     if Site<>nil then begin
       LayoutNode:=LayoutTree.NewNode(LayoutTree.Root);
       Site.SaveLayout(LayoutTree,LayoutNode);
     end;
   end else
-    raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AForm));
+    raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl));
 end;

Andrey Zubarev

2017-08-07 14:31

reporter   ~0102099

Add anchordocking-tanchordockpanel-lesscasting.patch
Less casting and renames.

But it's not quite what Mattias need. Need to review code and make a wrapper over TCustomForm and TDockPanel. But it's hard for me

Mattias Gaertner

2017-08-07 15:33

manager   ~0102101

Passing a TPanel to a TCustomForm parameter is a no-go. That hack is asking to shoot yourself in the foot.
Either change the panel class to a customform, or change the parameter, or add overloads with panel, or whatever.

Andrey Zubarev

2017-08-07 15:37

reporter   ~0102102

>>or change the parameter
Please review anchordocking-tanchordockpanel-lesscasting.patch

Andrey Zubarev

2017-08-10 10:41

reporter   ~0102130

This can be closed?
Mattias please review anchordocking-tanchordockpanel-lesscasting.patch

Juha Manninen

2017-08-10 23:00

developer   ~0102135

Sorry, I failed to notice the last comments.
I will look at the issue more tomorrow.

Juha Manninen

2017-08-13 14:27

developer   ~0102154

I applied anchordocking-tanchordockpanel-lesscasting.patch in r55654.
Yes it improves things. I did not pay atention to the wrong casts initially.
Mattias, how does it look like now?

Juha Manninen

2017-08-19 18:55

developer   ~0102237

I guess this can be resolved.

Andrey Zubarev

2017-08-19 19:01

reporter   ~0102239

Thanks!

Issue History

Date Modified Username Field Change
2013-07-03 10:08 Andrey Zubarev New Issue
2013-07-03 10:29 Mattias Gaertner LazTarget => -
2013-07-03 10:29 Mattias Gaertner Note Added: 0068710
2013-07-03 10:29 Mattias Gaertner Assigned To => Mattias Gaertner
2013-07-03 10:29 Mattias Gaertner Status new => feedback
2013-07-03 10:35 Andrey Zubarev Note Added: 0068711
2013-07-03 10:35 Andrey Zubarev Status feedback => assigned
2013-07-25 00:07 Andrey Zubarev Note Added: 0069094
2014-10-07 10:57 Andrey Zubarev Note Added: 0078043
2014-10-07 11:21 Mattias Gaertner Note Added: 0078044
2014-10-07 19:19 Andrey Zubarev File Added: akclient.gif
2014-10-07 19:23 Andrey Zubarev Note Added: 0078054
2014-10-07 23:07 Mattias Gaertner Note Added: 0078058
2014-11-26 16:28 Andrey Zubarev Note Added: 0079406
2014-11-26 17:39 Mattias Gaertner Note Added: 0079409
2014-11-27 19:06 Andrey Zubarev Note Added: 0079426
2014-11-27 19:08 Andrey Zubarev Note Added: 0079427
2014-11-27 19:12 Andrey Zubarev Note Edited: 0079427 View Revisions
2017-06-16 21:55 Andrey Zubarev File Added: anchordockpanel.patch
2017-06-16 21:58 Andrey Zubarev Note Added: 0101197
2017-06-16 22:04 Andrey Zubarev Note Added: 0101198
2017-06-20 11:19 Andrey Zubarev Note Added: 0101231
2017-06-20 11:20 Andrey Zubarev File Added: anchordocking-tanchordockpanel-impl.patch
2017-06-20 11:20 Andrey Zubarev File Added: miniidewithdockpanel-example.patch
2017-06-20 11:21 Andrey Zubarev Note Edited: 0101231 View Revisions
2017-06-20 22:32 Andrey Zubarev File Added: anchordocking-tanchordockpanel-impl2.patch
2017-06-20 22:35 Andrey Zubarev Note Added: 0101233
2017-07-07 20:40 Andrey Zubarev Note Added: 0101572
2017-07-07 20:40 Andrey Zubarev File Added: anchordocking-tanchordockpanel-impl3.patch
2017-07-07 20:59 Mattias Gaertner File Added: anchordocking-tanchordockpanel-impl4.patch
2017-07-07 21:00 Mattias Gaertner Note Added: 0101573
2017-07-07 21:13 Andrey Zubarev Note Added: 0101574
2017-07-07 21:18 Mattias Gaertner Note Added: 0101575
2017-07-07 21:42 Andrey Zubarev Note Added: 0101577
2017-07-07 22:05 Andrey Zubarev Note Edited: 0101577 View Revisions
2017-07-07 22:23 Mattias Gaertner File Added: anchordocking-tanchordockpanel-impl5.patch
2017-07-07 22:27 Mattias Gaertner Note Added: 0101581
2017-07-07 22:42 Andrey Zubarev Note Added: 0101583
2017-07-07 22:51 Andrey Zubarev Note Added: 0101584
2017-07-07 23:25 Andrey Zubarev Note Added: 0101590
2017-07-08 09:46 Andrey Zubarev File Added: miniidewithdockpanel-example2.patch
2017-07-08 09:49 Andrey Zubarev Note Added: 0101596
2017-08-06 20:57 Juha Manninen Assigned To Mattias Gaertner => Juha Manninen
2017-08-06 21:04 Juha Manninen Note Added: 0102089
2017-08-06 21:04 Juha Manninen Status assigned => feedback
2017-08-06 21:07 Juha Manninen Note Edited: 0102089 View Revisions
2017-08-06 21:17 Andrey Zubarev File Added: miniidewithdockpanel.zip
2017-08-06 21:20 Andrey Zubarev Note Added: 0102090
2017-08-06 21:20 Andrey Zubarev Status feedback => assigned
2017-08-07 09:34 Juha Manninen Fixed in Revision => r55638, r55641
2017-08-07 09:34 Juha Manninen Note Added: 0102096
2017-08-07 09:34 Juha Manninen Status assigned => resolved
2017-08-07 09:34 Juha Manninen Resolution open => fixed
2017-08-07 09:41 Mattias Gaertner Note Added: 0102097
2017-08-07 14:24 Andrey Zubarev File Added: anchordocking-tanchordockpanel-lesscasting.patch
2017-08-07 14:31 Andrey Zubarev Note Added: 0102099
2017-08-07 15:33 Mattias Gaertner Note Added: 0102101
2017-08-07 15:37 Andrey Zubarev Note Added: 0102102
2017-08-10 10:41 Andrey Zubarev Note Added: 0102130
2017-08-10 23:00 Juha Manninen Note Added: 0102135
2017-08-10 23:00 Juha Manninen Status resolved => assigned
2017-08-10 23:00 Juha Manninen Resolution fixed => reopened
2017-08-13 14:27 Juha Manninen Note Added: 0102154
2017-08-13 14:27 Juha Manninen Status assigned => feedback
2017-08-19 18:55 Juha Manninen Fixed in Revision r55638, r55641 => r55638, r55641, r55654
2017-08-19 18:55 Juha Manninen Note Added: 0102237
2017-08-19 18:55 Juha Manninen Status feedback => resolved
2017-08-19 18:55 Juha Manninen Resolution reopened => fixed
2017-08-19 19:01 Andrey Zubarev Note Added: 0102239
2017-08-19 19:01 Andrey Zubarev Status resolved => closed
2017-08-20 10:32 Juha Manninen Relationship added related to 0032302