View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0034347 | Lazarus | Packages | public | 2018-09-27 12:04 | 2019-01-28 06:32 |
Reporter | Andrey Zubarev | Assigned To | Michl | ||
Priority | normal | Severity | minor | Reproducibility | have not tried |
Status | closed | Resolution | fixed | ||
Target Version | 2.2 | Fixed in Version | 2.1 (SVN) | ||
Summary | 0034347: AnchorDocking feature (new button: size reduction of the panel) | ||||
Description | Such there is in many programs. When you mouse over the panel increases, when lose the mouse decreases. Take a look at the attached screenshot of Delphi | ||||
Tags | No tags attached. | ||||
Fixed in Revision | 59681, 60099, 60233, 60234 | ||||
LazTarget | - | ||||
Widgetset | |||||
Attached Files |
|
related to | 0034363 | closed | Michl | AnchorDocking top level site with pages need header |
related to | 0034508 | closed | Michl | AnchorDocking, add an event allowing to draw a custom header |
related to | 0034614 | closed | Michl | AnchorDocking: Sites can be overlapped after minimize\unminimize |
related to | 0034612 | closed | Michl | AnchorDocking: AV on double loading layout with minimized sites |
|
|
|
What increases and decreases? |
|
Sorry for my English. See animated gif https://imgur.com/a/A5Zg7f8 |
|
Ok, I see. I don't know what is the right word for it. Minimize / normalize maybe. The window overlaps other windows until you click the upper pin-button. |
|
Tried to do, in the first looming, looks so anchordocking_minimize_docksite1.patch Problems: -ugly minimize button -minimize state not saved -form resize not handled -form undock not handled -overlap show not implemented |
|
anchordocking_minimize_docksite1.patch (12,637 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59377) +++ components/anchordocking/anchordocking.pas (working copy) @@ -123,6 +123,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +141,11 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -154,6 +164,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -263,6 +274,7 @@ FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; fUpdateLayout: integer; + FMinimized: boolean; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +331,7 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -2193,7 +2206,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -3680,6 +3693,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -5165,6 +5179,59 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +var + AControl: TControl; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterPercentPosition:Single; +begin + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then + if Splitter.Enabled or FMinimized then begin + FMinimized:=not FMinimized; + AControl.Visible:=not AControl.Visible; + Splitter.Enabled:=AControl.Visible; + if FMinimized then begin + SpliterPercentPosition:=Splitter.FPercentPosition; + UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: Splitter.MoveSplitter(Height-Header.Height); + akBottom: Splitter.MoveSplitter(Header.Height-Splitter.Top); + akLeft: Splitter.MoveSplitter(Header.Height-Splitter.Left); + akRight: Splitter.MoveSplitter(Width-Header.Height); + end; + Splitter.FPercentPosition:=SpliterPercentPosition; + end else begin + UpdateHeaderAlign; + end; + end; +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5373,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5428,27 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + Header.Align:=OppositeAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5476,6 +5560,7 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5569,6 +5654,13 @@ end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +begin + if Parent is TAnchorDockHostSite then begin + TAnchorDockHostSite(Parent).MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +5732,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +5827,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5742,11 +5848,15 @@ procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +5897,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,6 +5909,16 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; @@ -5844,6 +5964,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMDIMinButtonNormal; + if not IsEnabled then + Result := twMDIMinButtonDisabled + else + if FState in [bsDown, bsExclusive] then + Result := twMDIMinButtonPushed + else + if FState = bsHot then + Result := twMDIMinButtonHot + else + Result := twMDIMinButtonNormal; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails(twMinButtonNormal)) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6506,31 +6664,33 @@ var NewLeft, NewTop: Integer; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); - end; - end else - begin - if DockParentClientSize.cy> 0 then + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; + if FPercentPosition < 0 then + UpdatePercentPosition; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59377) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; |
|
Andrey Zubarev, with all the problems you listed, do you feel the patch should be applied into trunk? I have not tested it. I am not even the right person to test it thoroughly because I don't normally use AnchorDocking. Others please test. What do you think? |
|
Of course add in trunk cannot be. I put it out for the test, and probably someone has an opinion on this, I would like to discuss. New patch with: -ugly minimize button -minimize state not saved -form undock not handled -overlap show not implemented |
|
anchordocking_minimize_docksite2.patch (15,240 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59377) +++ components/anchordocking/anchordocking.pas (working copy) @@ -123,6 +123,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +141,11 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -154,6 +164,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -263,6 +274,7 @@ FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; fUpdateLayout: integer; + FMinimized: boolean; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +331,7 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -970,6 +983,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -2193,7 +2227,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -3680,6 +3714,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -5165,6 +5200,63 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + AControl.Visible:=not AControl.Visible; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + {if FMinimized then begin + SpliterPercentPosition:=Splitter.FPercentPosition; + UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: Splitter.MoveSplitter(Height-Header.Height); + akBottom: Splitter.MoveSplitter(Header.Height-Splitter.Top); + akLeft: Splitter.MoveSplitter(Header.Height-Splitter.Left); + akRight: Splitter.MoveSplitter(Width-Header.Height); + end; + Splitter.FPercentPosition:=SpliterPercentPosition; + end else begin + UpdateHeaderAlign; + end;} + end; + end; +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5398,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5453,27 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + Header.Align:=OppositeAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5476,6 +5585,7 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5569,6 +5679,13 @@ end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +begin + if Parent is TAnchorDockHostSite then begin + TAnchorDockHostSite(Parent).MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +5757,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +5852,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5742,11 +5873,15 @@ procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +5922,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,6 +5934,16 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; @@ -5844,6 +5989,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMDIMinButtonNormal; + if not IsEnabled then + Result := twMDIMinButtonDisabled + else + if FState in [bsDown, bsExclusive] then + Result := twMDIMinButtonPushed + else + if FState = bsHot then + Result := twMDIMinButtonHot + else + Result := twMDIMinButtonNormal; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails(twMinButtonNormal)) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6505,32 +6688,57 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59377) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; |
|
> Of course add in trunk cannot be. I put it out for the test, and probably someone has an opinion on this, I would like to discuss. :) As you notice, it is difficult to get people to test a patch. Changes applied in trunk have a little better chance of being tested. |
|
First we need to add a setting and make it off by default. Currently it looks ugly and will scare ordinary users |
|
https://imgur.com/a/pscP56l |
|
anchordocking_minimize_docksite3.patch (35,632 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59377) +++ components/anchordocking/anchordocking.pas (working copy) @@ -123,6 +123,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +141,11 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -154,6 +164,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -263,6 +274,7 @@ FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; fUpdateLayout: integer; + FMinimized: boolean; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +331,7 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -431,6 +444,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +462,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +481,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +518,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -561,6 +578,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -680,6 +698,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -970,6 +989,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1401,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1428,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1455,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1478,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1500,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1523,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1546,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2193,7 +2246,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2514,6 +2567,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2698,6 +2769,7 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; end; destructor TAnchorDockMaster.Destroy; @@ -3323,6 +3395,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3416,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3680,6 +3754,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -5165,6 +5240,64 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + AControl.Visible:=not AControl.Visible; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + Splitter.SetBoundsPercentually; + {if FMinimized then begin + SpliterPercentPosition:=Splitter.FPercentPosition; + UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: Splitter.MoveSplitter(Height-Header.Height); + akBottom: Splitter.MoveSplitter(Header.Height-Splitter.Top); + akLeft: Splitter.MoveSplitter(Header.Height-Splitter.Left); + akRight: Splitter.MoveSplitter(Width-Header.Height); + end; + Splitter.FPercentPosition:=SpliterPercentPosition; + end else begin + UpdateHeaderAlign; + end;} + end; + end; +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5439,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5494,27 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + Header.Align:=OppositeAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5390,8 +5540,10 @@ procedure TAnchorDockHostSite.UpdateHeaderShowing; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=DockMaster.DockSitesCanBeMinimized; + end else Header.Parent:=nil; end; @@ -5476,6 +5628,7 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5569,6 +5722,13 @@ end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +begin + if Parent is TAnchorDockHostSite then begin + TAnchorDockHostSite(Parent).MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +5800,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +5895,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5742,11 +5916,15 @@ procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +5965,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,6 +5977,16 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; @@ -5844,6 +6032,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMDIMinButtonNormal; + if not IsEnabled then + Result := twMDIMinButtonDisabled + else + if FState in [bsDown, bsExclusive] then + Result := twMDIMinButtonPushed + else + if FState = bsHot then + Result := twMDIMinButtonHot + else + Result := twMDIMinButtonNormal; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails(twMinButtonNormal)) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6505,32 +6731,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59377) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59377) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59377) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation |
|
anchordocking_minimize_docksite3.patch can be applied for tests |
|
anchordocking_minimize_docksite4.patch (39,872 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -123,6 +123,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +141,11 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -154,6 +164,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -262,7 +273,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +333,8 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -431,6 +447,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +465,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +484,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +521,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -561,6 +581,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -680,6 +701,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -970,6 +992,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1404,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1431,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1458,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1481,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1503,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1526,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1549,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2193,7 +2249,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2514,6 +2570,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2698,14 +2772,13 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2800,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -3323,6 +3402,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3423,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3680,6 +3761,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4201,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4317,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4398,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4564,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4676,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5265,71 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + Application.QueueAsyncCall(@AsyncMinimizeSite,0); + //AsyncMinimizeSite,0 +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + Splitter.SetBoundsPercentually; + end; + end; + fMinimization:=false; +end; + + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5471,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5526,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5390,8 +5578,11 @@ procedure TAnchorDockHostSite.UpdateHeaderShowing; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=DockMaster.DockSitesCanBeMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5476,6 +5667,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5684,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5569,6 +5763,13 @@ end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +begin + if Parent is TAnchorDockHostSite then begin + TAnchorDockHostSite(Parent).MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +5841,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +5936,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5742,11 +5957,15 @@ procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6006,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,6 +6018,16 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; @@ -5844,6 +6073,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMDIMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMDIMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMDIMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMDIMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMDIMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6505,32 +6772,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation |
|
Please test anchordocking_minimize_docksite4.patch it work with gtk,win and qt -ugly minimize button (for gtk2 i use twMDIRestoreButton instead twMDIMinButtonNormal) -minimize state not saved -overlap show not implemented |
|
anchordocking_minimize_docksite5.patch (56,037 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -92,9 +92,9 @@ {$mode objfpc}{$H+} { $DEFINE VerboseAnchorDockRestore} -{ $DEFINE VerboseADCustomSite} -{ $DEFINE VerboseAnchorDockPages} -{ $DEFINE VerboseAnchorDocking} +{$DEFINE VerboseADCustomSite} +{$DEFINE VerboseAnchorDockPages} +{$DEFINE VerboseAnchorDocking} interface @@ -123,6 +123,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +141,11 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -154,6 +164,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -262,7 +273,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +333,8 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -431,6 +447,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +465,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +484,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +521,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -541,6 +561,8 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +583,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -680,6 +703,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -970,6 +994,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1406,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1433,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1460,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1483,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1505,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1528,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1551,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2079,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2100,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2272,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2437,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2447,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2514,6 +2594,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2698,14 +2796,13 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2824,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -3088,12 +3191,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3227,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3235,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3260,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3355,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3365,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3427,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3448,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3680,6 +3786,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4226,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4342,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4423,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4589,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4701,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5290,71 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + Splitter.SetBoundsPercentually; + end; + end; + fMinimization:=false; +end; + + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5496,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5551,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5390,8 +5603,11 @@ procedure TAnchorDockHostSite.UpdateHeaderShowing; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=DockMaster.DockSitesCanBeMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5432,7 +5648,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5666,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5677,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5692,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5709,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5569,6 +5788,13 @@ end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +begin + if Parent is TAnchorDockHostSite then begin + TAnchorDockHostSite(Parent).MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +5866,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +5961,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5742,11 +5982,15 @@ procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6031,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,6 +6043,16 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; @@ -5844,6 +6098,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6505,32 +6797,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6562,12 +6880,39 @@ procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + + if not Enabled then begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + LayoutNode.BoundsRect:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
anchordocking_minimize_docksite5.patch - now minimized sites can be saved\restored. Please test |
|
anchordocking_minimize_docksite6.patch (64,863 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -92,9 +92,9 @@ {$mode objfpc}{$H+} { $DEFINE VerboseAnchorDockRestore} -{ $DEFINE VerboseADCustomSite} -{ $DEFINE VerboseAnchorDockPages} -{ $DEFINE VerboseAnchorDocking} +{$DEFINE VerboseADCustomSite} +{$DEFINE VerboseAnchorDockPages} +{$DEFINE VerboseAnchorDocking} interface @@ -109,6 +109,10 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + type TAnchorDockHostSite = class; @@ -123,6 +127,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +145,12 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +162,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +174,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +211,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +263,15 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + protected + procedure MouseLeave; override; + public + AnchorDockHostSite:TAnchorDockHostSite; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +293,11 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; + //OverlappingForm:TAnchorDockOverlappingForm; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +354,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -431,6 +470,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +488,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +507,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +544,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +574,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +585,8 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +607,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -586,6 +633,8 @@ procedure OnIdle(Sender: TObject; var Done: Boolean); procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm; constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +729,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,6 +748,7 @@ var DockMaster: TAnchorDockMaster = nil; + MouseNoMoveTimer: TTimer = nil; const ADHeaderStyleNames: array[TADHeaderStyle] of string = ( @@ -970,6 +1021,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1433,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1460,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1487,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1510,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1532,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1555,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1578,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2106,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2127,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2299,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2464,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2474,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2423,10 +2530,22 @@ end; procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not PtInRect(Bounds,MousePos) then begin + HideOverlappingForm; + end; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2633,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2668,6 +2805,19 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm; +begin + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2848,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2877,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -3018,7 +3174,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3219,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3236,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3260,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3296,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3304,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3329,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3424,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3434,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3496,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3517,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3680,6 +3855,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4295,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4411,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4492,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4658,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4770,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5359,102 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + Splitter.SetBoundsPercentually; + end; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5596,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5651,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5390,8 +5703,11 @@ procedure TAnchorDockHostSite.UpdateHeaderShowing; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=DockMaster.DockSitesCanBeMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5432,7 +5748,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5766,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5777,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5792,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5809,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5569,6 +5888,13 @@ end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +begin + if Parent is TAnchorDockHostSite then begin + TAnchorDockHostSite(Parent).MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +5966,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +6061,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5739,14 +6079,63 @@ DragManager.DragStart(Parent,false,DockMaster.DragTreshold); end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if MouseNoMoveTimer.Enabled then MouseNoMoveTimer.Enabled:=false; + MouseNoMoveTimer.Interval:=MouseNoMoveTime; + MouseNoMoveTimer.OnTimer:=@DoMouseNoMoveTimer; + MouseNoMoveTimer.Enabled:=true; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + MouseNoMoveTimer.OnTimer:=nil; + MouseNoMoveTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6176,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6188,22 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; end; { TAnchorDockCloseButton } @@ -5844,6 +6244,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6505,32 +6943,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7024,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6782,6 +7279,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; +end; + +procedure TAnchorDockOverlappingForm.MouseLeave; +begin + inherited; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7346,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + MouseNoMoveTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(MouseNoMoveTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
anchordocking_minimize_docksite6.patch In the first approximation everything works. Please test! -Need a timer, for not close overlapping form immediately after the loss of the mouse |
|
anchordocking_minimize_docksite7.patch (67,286 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -109,6 +109,11 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + HideOverlappingFormByMouseLoseTime=500; + type TAnchorDockHostSite = class; @@ -123,6 +128,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +146,12 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +163,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +175,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +212,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +264,15 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + protected + procedure MouseLeave; override; + public + AnchorDockHostSite:TAnchorDockHostSite; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +294,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +354,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -431,6 +470,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +488,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +507,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +544,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +574,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +585,8 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +607,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -584,8 +631,12 @@ procedure SetHideHeaderCaptionFloatingControl(const AValue: boolean); procedure SetSplitterWidth(const AValue: integer); procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure StartHideOverlappingTimer; + procedure StopHideOverlappingTimer; procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm(Sender: TObject); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +731,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,6 +750,7 @@ var DockMaster: TAnchorDockMaster = nil; + DockTimer: TTimer = nil; const ADHeaderStyleNames: array[TADHeaderStyle] of string = ( @@ -970,6 +1023,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1435,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1462,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1489,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1512,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1534,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1557,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1580,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2108,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2129,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2301,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2466,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2476,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2422,11 +2531,40 @@ OptionsChanged; end; +procedure TAnchorDockMaster.StartHideOverlappingTimer; +begin + if not DockTimer.Enabled then begin + DockTimer.Interval:=HideOverlappingFormByMouseLoseTime; + DockTimer.OnTimer:=@HideOverlappingForm; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockMaster.StopHideOverlappingTimer; +begin + DockTimer.Enabled:=False; + DockTimer.Interval:=0; + DockTimer.OnTimer:=nil; +end; + procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not PtInRect(Bounds,MousePos) then + StartHideOverlappingTimer + else + StopHideOverlappingTimer; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2652,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2668,6 +2824,20 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm(Sender: TObject); +begin + StopHideOverlappingTimer; + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2868,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2897,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -3018,7 +3194,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3239,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3256,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3280,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3316,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3324,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3349,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3444,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3454,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3516,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3537,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3680,6 +3875,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4315,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4431,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4512,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4678,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4790,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5379,105 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + Splitter.SetBoundsPercentually; + end; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + header.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + header.Parent:=self; + header.UpdateHeaderControls; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5619,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5674,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5390,8 +5726,11 @@ procedure TAnchorDockHostSite.UpdateHeaderShowing; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=DockMaster.DockSitesCanBeMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5432,7 +5771,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5789,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5800,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5815,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5832,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5562,13 +5904,34 @@ end; procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; begin - if Parent is TAnchorDockHostSite then begin - DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(Parent),true); - TAnchorDockHostSite(Parent).CloseSite; + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; end; + if HeaderParent is TAnchorDockHostSite then begin + DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent),true); + HeaderParent.CloseSite; + end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; +begin + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; + end; + if HeaderParent is TAnchorDockHostSite then begin + HeaderParent.MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +6003,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,7 +6098,14 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; @@ -5735,18 +6112,67 @@ X, Y: Integer); begin inherited MouseDown(Button, Shift, X, Y); - if (Button=mbLeft) and DockMaster.AllowDragging then + if (Button=mbLeft) and (DockMaster.AllowDragging) and (DockMaster.FOverlappingForm=nil) then DragManager.DragStart(Parent,false,DockMaster.DragTreshold); end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if DockTimer.Enabled then DockTimer.Enabled:=false; + DockTimer.Interval:=MouseNoMoveTime; + DockTimer.OnTimer:=@DoMouseNoMoveTimer; + DockTimer.Enabled:=true; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + DockTimer.OnTimer:=nil; + DockTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6213,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6225,22 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; end; { TAnchorDockCloseButton } @@ -5844,6 +6281,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6213,6 +6688,9 @@ ClientRectChanged:=(WidthDiff<>0) or (HeightDiff<>0); if ClientRectChanged or PreferredSiteSizeAsSiteMinimum then AlignChilds; + if ClientRectChanged then + if DockMaster.FOverlappingForm<>nil then + DockMaster.HideOverlappingForm(nil); end; procedure TAnchorDockManager.SaveToStream(Stream: TStream); @@ -6505,32 +6983,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7064,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6645,7 +7182,7 @@ begin inherited MouseDown(Button, Shift, X, Y); ATabIndex := IndexOfPageAt(X, Y); - if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) then + if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) and (DockMaster.FOverlappingForm=nil) then begin APage:=Page[ATabIndex]; if (APage.ControlCount>0) and (APage.Controls[0] is TAnchorDockHostSite) then @@ -6782,6 +7319,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; +end; + +procedure TAnchorDockOverlappingForm.MouseLeave; +begin + inherited; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7386,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + DockTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(DockTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
anchordocking_minimize_docksite7.patch That's about what I wanted to do)) Problems: -ugly minimize button; -perhaps need add to settings MouseNoMoveDelta=5 MouseNoMoveTime=500 HideOverlappingFormByMouseLoseTime=500 consts; -perhaps need add animation to show\hide overlaping window; -perhaps need add small border to overlaping window; Not tested in linux! Please review and test! |
|
Demo https://imgur.com/a/q5owCHp |
|
anchordocking_minimize_docksite8.patch (67,938 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -109,6 +109,11 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + HideOverlappingFormByMouseLoseTime=500; + type TAnchorDockHostSite = class; @@ -123,6 +128,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +146,12 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +163,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +175,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +212,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +264,15 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + protected + procedure MouseLeave; override; + public + AnchorDockHostSite:TAnchorDockHostSite; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +294,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +354,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -431,6 +470,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +488,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +507,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +544,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +574,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +585,8 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +607,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -584,8 +631,12 @@ procedure SetHideHeaderCaptionFloatingControl(const AValue: boolean); procedure SetSplitterWidth(const AValue: integer); procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure StartHideOverlappingTimer; + procedure StopHideOverlappingTimer; procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm(Sender: TObject); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +731,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,6 +750,7 @@ var DockMaster: TAnchorDockMaster = nil; + DockTimer: TTimer = nil; const ADHeaderStyleNames: array[TADHeaderStyle] of string = ( @@ -970,6 +1023,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1435,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1462,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1489,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1512,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1534,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1557,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1580,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2108,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2129,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2301,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2466,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2476,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2422,11 +2531,54 @@ OptionsChanged; end; +procedure TAnchorDockMaster.StartHideOverlappingTimer; +begin + if not DockTimer.Enabled then begin + DockTimer.Interval:=HideOverlappingFormByMouseLoseTime; + DockTimer.OnTimer:=@HideOverlappingForm; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockMaster.StopHideOverlappingTimer; +begin + DockTimer.Enabled:=False; + DockTimer.Interval:=0; + DockTimer.OnTimer:=nil; +end; + +function IsParentControl(aParent, aControl: TControl): boolean; +begin + while (aControl <> nil) and (aControl.Parent <> nil) do + begin + if (aControl=aParent) then + exit(true); + aControl := aControl.Parent; + end; + result:=aControl=aParent; +end; + + procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not IsParentControl(FOverlappingForm, GetCaptureControl) then begin + if not PtInRect(Bounds,MousePos) then + StartHideOverlappingTimer + else + StopHideOverlappingTimer; + end; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2666,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2668,6 +2838,20 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm(Sender: TObject); +begin + StopHideOverlappingTimer; + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2882,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2911,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -3018,7 +3208,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3253,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3270,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3294,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3330,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3338,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3363,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3458,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3468,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3530,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3551,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3680,6 +3889,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4329,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4445,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4526,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4692,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4804,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5393,105 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + Splitter.SetBoundsPercentually; + end; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + header.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + header.Parent:=self; + header.UpdateHeaderControls; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5306,9 +5633,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm))and(Pages=nil); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5362,9 +5688,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5390,8 +5740,11 @@ procedure TAnchorDockHostSite.UpdateHeaderShowing; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=DockMaster.DockSitesCanBeMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5432,7 +5785,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5803,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5814,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5829,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5846,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5562,13 +5918,34 @@ end; procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; begin - if Parent is TAnchorDockHostSite then begin - DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(Parent),true); - TAnchorDockHostSite(Parent).CloseSite; + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; end; + if HeaderParent is TAnchorDockHostSite then begin + DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent),true); + HeaderParent.CloseSite; + end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; +begin + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; + end; + if HeaderParent is TAnchorDockHostSite then begin + HeaderParent.MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +6017,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,25 +6112,89 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + SiteMinimized:Boolean; begin inherited MouseDown(Button, Shift, X, Y); - if (Button=mbLeft) and DockMaster.AllowDragging then - DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + SiteMinimized:=False; + if Parent is TAnchorDockHostSite then + SiteMinimized:=(Parent as TAnchorDockHostSite).FMinimized; + if SiteMinimized then begin + DoMouseNoMoveTimer(nil); + end else + if (Button=mbLeft) and (DockMaster.AllowDragging) and (DockMaster.FOverlappingForm=nil) then + DragManager.DragStart(Parent,false,DockMaster.DragTreshold); end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if DockTimer.Enabled then DockTimer.Enabled:=false; + DockTimer.Interval:=MouseNoMoveTime; + DockTimer.OnTimer:=@DoMouseNoMoveTimer; + DockTimer.Enabled:=true; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + DockTimer.OnTimer:=nil; + DockTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6235,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6247,22 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; end; { TAnchorDockCloseButton } @@ -5844,6 +6303,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6213,6 +6710,9 @@ ClientRectChanged:=(WidthDiff<>0) or (HeightDiff<>0); if ClientRectChanged or PreferredSiteSizeAsSiteMinimum then AlignChilds; + if ClientRectChanged then + if DockMaster.FOverlappingForm<>nil then + DockMaster.HideOverlappingForm(nil); end; procedure TAnchorDockManager.SaveToStream(Stream: TStream); @@ -6505,32 +7005,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7086,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6645,7 +7204,7 @@ begin inherited MouseDown(Button, Shift, X, Y); ATabIndex := IndexOfPageAt(X, Y); - if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) then + if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) and (DockMaster.FOverlappingForm=nil) then begin APage:=Page[ATabIndex]; if (APage.ControlCount>0) and (APage.Controls[0] is TAnchorDockHostSite) then @@ -6782,6 +7341,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; +end; + +procedure TAnchorDockOverlappingForm.MouseLeave; +begin + inherited; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7408,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + DockTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(DockTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
anchordocking_minimize_docksite8.patch - no hide overlaping window if mouse captured - disable drag minimized headers Works in linux, but not tested! Please review and test! |
|
Thank you for your work! I like this feature very much and I don't think, this has to be optional. However it is implemented, so it can be optional. I tested Windows 7 (Classic and Aero theme), Linux Mint KDE GTK2, Linux Mint KDE Qt. Now my list of issues/suggestions: 1. A little one. In the options, this option is not correct aligned, it overlap option "header align top". 2. The caption of a form isn't shown, when it is minimized. 3. If a docked form is minimized and "show headers" are unchecked, the space for the header is further blocked, but nothing (just the background) is shown there. 4. It would be nice, if a second click on a closed form will close the form again, so it is not necessary to move the mouse out the form. 5. If you try to dock a form on a minimized form, Lazarus is crashed. 6. If you try to dock a form before a minimized form, it is docked after the minimized form and the layout is destroyed (the splitter get lost, the maximize button doesn't react anymore). 7. The preview window need a border and/or at least a background (maybe a TPanel). On Qt the tabs of a page control are shown with alpha channel. Without a background, they are not readable. Hope you can manage the issues?! I'm looking forward for a new patch. |
|
anchordocking_minimize_docksite9.patch (72,496 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -109,6 +109,11 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + HideOverlappingFormByMouseLoseTime=500; + type TAnchorDockHostSite = class; @@ -123,6 +128,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +146,13 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + fUseTimer:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +164,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +176,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +213,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +265,14 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + public + AnchorDockHostSite:TAnchorDockHostSite; + Panel:TPanel; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +294,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +354,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -329,6 +368,7 @@ procedure UpdateDockCaption(Exclude: TControl = nil); override; procedure UpdateHeaderAlign; procedure UpdateHeaderShowing; + function CanBeMinimized(out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; procedure BeginUpdateLayout; procedure EndUpdateLayout; function UpdatingLayout: boolean; @@ -431,6 +471,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +489,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +508,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +545,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +575,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +586,9 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure UpdateHeaders; + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +609,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -584,8 +633,12 @@ procedure SetHideHeaderCaptionFloatingControl(const AValue: boolean); procedure SetSplitterWidth(const AValue: integer); procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure StartHideOverlappingTimer; + procedure StopHideOverlappingTimer; procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm(Sender: TObject); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +733,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,6 +752,7 @@ var DockMaster: TAnchorDockMaster = nil; + DockTimer: TTimer = nil; const ADHeaderStyleNames: array[TADHeaderStyle] of string = ( @@ -970,6 +1025,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1437,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1464,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1491,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1514,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1536,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1559,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1582,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2110,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2131,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2303,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2468,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2478,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2422,11 +2533,54 @@ OptionsChanged; end; +procedure TAnchorDockMaster.StartHideOverlappingTimer; +begin + if not DockTimer.Enabled then begin + DockTimer.Interval:=HideOverlappingFormByMouseLoseTime; + DockTimer.OnTimer:=@HideOverlappingForm; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockMaster.StopHideOverlappingTimer; +begin + DockTimer.Enabled:=False; + DockTimer.Interval:=0; + DockTimer.OnTimer:=nil; +end; + +function IsParentControl(aParent, aControl: TControl): boolean; +begin + while (aControl <> nil) and (aControl.Parent <> nil) do + begin + if (aControl=aParent) then + exit(true); + aControl := aControl.Parent; + end; + result:=aControl=aParent; +end; + + procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not IsParentControl(FOverlappingForm, GetCaptureControl) then begin + if not PtInRect(Bounds,MousePos) then + StartHideOverlappingTimer + else + StopHideOverlappingTimer; + end; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2668,24 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + for i:=0 to ComponentCount-1 do begin + Site:=TAnchorDockHostSite(Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if (Site.Header<>nil) then begin + DisableControlAutoSizing(Site); + Site.UpdateHeaderShowing; + end; + end; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2598,6 +2770,9 @@ if (Site.Header<>nil) then begin DisableControlAutoSizing(Site); Site.UpdateHeaderShowing; + if Site.fminimized then + if not AValue then + site.MinimizeSite; end; end; EnableAllAutoSizing; @@ -2668,6 +2843,20 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm(Sender: TObject); +begin + StopHideOverlappingTimer; + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2887,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2916,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -3018,7 +3213,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3258,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3275,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3299,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3335,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3343,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3368,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3463,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3473,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3535,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3556,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3664,6 +3878,24 @@ LUIncreaseChangeStamp64(FOptionsChangeStamp); end; +procedure TAnchorDockMaster.UpdateHeaders; +var + i: Integer; + AControl: TControl; + AHostSite: TAnchorDockHostSite; +begin + for i:=0 to ControlCount-1 do begin + AControl:=Controls[i]; + if not DockedControlIsVisible(AControl) then continue; + while Assigned(AControl) do + begin + if AControl is TAnchorDockHostSite then + TAnchorDockHostSite(AControl).UpdateHeaderShowing; + AControl:=AControl.parent; + end; + end; +end; + { TAnchorDockHostSite } procedure TAnchorDockHostSite.SetHeaderSide(const AValue: TAnchorKind); @@ -3680,6 +3912,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4352,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4468,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4549,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4715,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4827,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5416,117 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +function TAnchorDockHostSite.CanBeMinimized(out Splitter: TAnchorDockSplitter; + out SplitterAnchorKind:TAnchorKind):boolean; +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; +begin + result:=false; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) then + result:=true; + end +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if CanBeMinimized(Splitter,SplitterAnchorKind) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + dockmaster.UpdateHeaders; + Splitter.SetBoundsPercentually; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + header.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm.Panel; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + header.Parent:=self; + header.UpdateHeaderControls; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5281,21 +5643,24 @@ begin if csDestroying in ComponentState then exit; NewCaption:=''; - for i:=0 to ControlCount-1 do begin - Child:=Controls[i]; - if Child=Exclude then continue; - if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) - or (Child is TAnchorDockPageControl) then begin - if NewCaption<>'' then - NewCaption:=NewCaption+','; - NewCaption:=NewCaption+Child.Caption; + if FMinimized then + NewCaption:=FMinimizedControl.Caption + else + for i:=0 to ControlCount-1 do begin + Child:=Controls[i]; + if Child=Exclude then continue; + if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) + or (Child is TAnchorDockPageControl) then begin + if NewCaption<>'' then + NewCaption:=NewCaption+','; + NewCaption:=NewCaption+Child.Caption; + end; end; - end; OldCaption:=Caption; Caption:=NewCaption; //debugln(['TAnchorDockHostSite.UpdateDockCaption Caption="',Caption,'" NewCaption="',NewCaption,'" HasParent=',Parent<>nil,' ',DbgSName(Header)]); - if ((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) - or (not DockMaster.ShowHeaderCaption) then + if {((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) + or (not DockMaster.ShowHeaderCaption)}false then Header.Caption:='' else Header.Caption:=Caption; @@ -5306,9 +5671,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm)); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5339,7 +5703,8 @@ end; CanDock:=(Client is TAnchorDockHostSite) - and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client); + and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client) + and not FMinimized; //debugln(['TAnchorDockHostSite.GetSiteInfo ',DbgSName(Self),' ',dbgs(BoundsRect),' ',Caption,' CanDock=',CanDock,' PtIn=',PtInRect(InfluenceRect,MousePos)]); if Assigned(OnGetSiteInfo) then @@ -5362,9 +5727,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5388,10 +5777,16 @@ end; procedure TAnchorDockHostSite.UpdateHeaderShowing; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=(DockMaster.DockSitesCanBeMinimized and CanBeMinimized(Splitter,SplitterAnchorKind))or FMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5432,7 +5827,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5845,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5856,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5871,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5888,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5562,13 +5960,34 @@ end; procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; begin - if Parent is TAnchorDockHostSite then begin - DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(Parent),true); - TAnchorDockHostSite(Parent).CloseSite; + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; end; + if HeaderParent is TAnchorDockHostSite then begin + DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent),true); + HeaderParent.CloseSite; + end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; +begin + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; + end; + if HeaderParent is TAnchorDockHostSite then begin + HeaderParent.MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5640,6 +6059,13 @@ r.Right:=CloseButton.Left-1; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+1 + else + r.Right:=MinimizeButton.Left-1; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,25 +6154,102 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + SiteMinimized:Boolean; begin inherited MouseDown(Button, Shift, X, Y); - if (Button=mbLeft) and DockMaster.AllowDragging then - DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + SiteMinimized:=False; + fUseTimer:=false; + StopMouseNoMoveTimer; + if Parent is TAnchorDockHostSite then + SiteMinimized:=(Parent as TAnchorDockHostSite).FMinimized; + if SiteMinimized then begin + DoMouseNoMoveTimer(nil); + end else + begin + if parent<>nil then + if DockMaster.FOverlappingForm<>nil then + //if parent=DockMaster.FOverlappingForm.Panel then + DockMaster.HideOverlappingForm(nil); + if (Button=mbLeft) and (DockMaster.AllowDragging) and (DockMaster.FOverlappingForm=nil) then + DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + end; end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; + if (parent is TAnchorDockHostSite)and(DockMaster.FOverlappingForm=nil)then + fUseTimer:=true; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if fUseTimer then begin + if DockTimer.Enabled then DockTimer.Enabled:=false; + DockTimer.Interval:=MouseNoMoveTime; + DockTimer.OnTimer:=@DoMouseNoMoveTimer; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + DockTimer.OnTimer:=nil; + DockTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + //if fUseTimer then + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alTop; CloseButton.Align:=alTop; + end; end else begin - if CloseButton<>nil then + if CloseButton<>nil then begin + MinimizeButton.Align:=alRight; CloseButton.Align:=alRight; + end; end; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6290,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6302,23 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; + fUseTimer:=true; end; { TAnchorDockCloseButton } @@ -5844,6 +6359,44 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6213,6 +6766,9 @@ ClientRectChanged:=(WidthDiff<>0) or (HeightDiff<>0); if ClientRectChanged or PreferredSiteSizeAsSiteMinimum then AlignChilds; + if ClientRectChanged then + if DockMaster.FOverlappingForm<>nil then + DockMaster.HideOverlappingForm(nil); end; procedure TAnchorDockManager.SaveToStream(Stream: TStream); @@ -6505,32 +7061,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7142,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6645,7 +7260,7 @@ begin inherited MouseDown(Button, Shift, X, Y); ATabIndex := IndexOfPageAt(X, Y); - if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) then + if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) and (DockMaster.FOverlappingForm=nil) then begin APage:=Page[ATabIndex]; if (APage.ControlCount>0) and (APage.Controls[0] is TAnchorDockHostSite) then @@ -6782,6 +7397,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; + Panel:=TPanel.Create(self); + Panel.BorderStyle:=bsSingle; + Panel.Align:=alClient; + Panel.Parent:=self; + Panel.Visible:=true; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7464,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + DockTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(DockTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -202,7 +203,7 @@ HeaderAlignTopSpinEdit.Visible:=true; HeaderAlignTopTrackBar.Visible:=false; - HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,HighlightFocusedCheckBox); + HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,DockSitesCanBeMinimized); HeaderAlignTopLabel.AnchorVerticalCenterTo(HeaderAlignTopSpinEdit); UpdateHeaderAlignTopLabel; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
anchordocking_minimize_docksite9.patch 1,2,3,4,5,7 - fixed, please test 6 - please give layout for components\anchordocking\minide\ example, and screenshot how to do for crash |
|
test.xml (1,379 bytes)
<?xml version="1.0" encoding="utf-8"?> <CONFIG> <MainConfig> <Nodes ChildCount="2"> <Item1 Name="MainIDE" Type="CustomSite" ChildCount="1"> <Bounds Top="50" Left="100" Width="600" Height="434"> <WorkArea> <Rect Right="1920" Bottom="1036"/> </WorkArea> </Bounds> <Item1 Name="AnchorDockSite3" Type="Layout" ChildCount="3"> <Bounds Top="60" Width="600" Height="350" SplitterPos="55"/> <Anchors Align="Bottom"/> <Item1 Name="ObjectInspector" Type="Control"> <Bounds Width="296" Height="350"/> <Anchors Right="AnchorDockSplitter2"/> </Item1> <Item2 Name="AnchorDockSplitter2" Type="SplitterVertical"> <Bounds Left="296" Width="4" Height="350"/> </Item2> <Item3 Name="SourceEditor1" Type="Control"> <Bounds Left="300" Width="300" Height="350"/> <Anchors Left="AnchorDockSplitter2"/> </Item3> </Item1> </Item1> <Item2 Name="Messages" Type="Control"> <Bounds Top="548" Left="208" Width="350" Height="100"> <WorkArea> <Rect Right="1920" Bottom="1036"/> </WorkArea> </Bounds> </Item2> </Nodes> </MainConfig> <Settings DockSitecCanBeMinimized="True"/> </CONFIG> |
|
|
|
1. For issue 6, see test.xml: - after loading of layout, minimize Source Editor 1 - dock messages after (right) of minimized Source Editor 1 - Splitter between Object Inspector and Source Editor 1 get lost 2. If you do this, there you can see a new bug. The minimize button of Object Inspector is lost. This always happens, when a form is docked to a new place. 3. The size of the minimize button and therefore the size of the header is wrong calculated. It is nearly the double size. See test.png: Left: wrong size (Source Editor 1); Right: correct size (Messages) 4. In MiniIDE: - load layout test.xml - dock Messages right of Source Editor 1 - minimize Source Editor 1 - maximize Source Editor 1 - minimize Messages - maximize Messages - see the minimize button and close button changed (see test2.png) |
|
|
|
1 - maybe unminimize all sites if user start drag site? |
|
Imagine as user, you have some minimized sites left, right and on the bottom. Now you dock a site on the right and all your minimized sites are unminimized. For user it would be annyoing when his layout is changed this way. If it is possible, I wouldn't do it. |
|
anchordocking_minimize_docksite10.patch (77,237 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -109,6 +109,12 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + HideOverlappingFormByMouseLoseTime=500; + ButtonBorderSpacingAround=4; + type TAnchorDockHostSite = class; @@ -123,6 +129,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +147,13 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + fUseTimer:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +165,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +177,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +214,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +266,14 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + public + AnchorDockHostSite:TAnchorDockHostSite; + Panel:TPanel; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +295,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +355,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -329,6 +369,7 @@ procedure UpdateDockCaption(Exclude: TControl = nil); override; procedure UpdateHeaderAlign; procedure UpdateHeaderShowing; + function CanBeMinimized(out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; procedure BeginUpdateLayout; procedure EndUpdateLayout; function UpdatingLayout: boolean; @@ -431,6 +472,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +490,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +509,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +546,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +576,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +587,9 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure UpdateHeaders; + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +610,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -584,8 +634,12 @@ procedure SetHideHeaderCaptionFloatingControl(const AValue: boolean); procedure SetSplitterWidth(const AValue: integer); procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure StartHideOverlappingTimer; + procedure StopHideOverlappingTimer; procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm(Sender: TObject); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +734,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,8 +753,14 @@ var DockMaster: TAnchorDockMaster = nil; + DockTimer: TTimer = nil; + PreferredButtonWidth:integer=-1; + PreferredButtonHeight:integer=-1; + + const + HardcodedButtonSize:integer=13; ADHeaderStyleNames: array[TADHeaderStyle] of string = ( 'Frame3D', 'Line', @@ -970,6 +1031,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1443,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1470,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1497,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1520,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1542,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1565,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1588,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2116,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2137,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2309,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2474,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2484,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2422,11 +2539,54 @@ OptionsChanged; end; +procedure TAnchorDockMaster.StartHideOverlappingTimer; +begin + if not DockTimer.Enabled then begin + DockTimer.Interval:=HideOverlappingFormByMouseLoseTime; + DockTimer.OnTimer:=@HideOverlappingForm; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockMaster.StopHideOverlappingTimer; +begin + DockTimer.Enabled:=False; + DockTimer.Interval:=0; + DockTimer.OnTimer:=nil; +end; + +function IsParentControl(aParent, aControl: TControl): boolean; +begin + while (aControl <> nil) and (aControl.Parent <> nil) do + begin + if (aControl=aParent) then + exit(true); + aControl := aControl.Parent; + end; + result:=aControl=aParent; +end; + + procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not IsParentControl(FOverlappingForm, GetCaptureControl) then begin + if not PtInRect(Bounds,MousePos) then + StartHideOverlappingTimer + else + StopHideOverlappingTimer; + end; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2674,18 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + UpdateHeaders; + InvalidateHeaders; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2598,6 +2770,9 @@ if (Site.Header<>nil) then begin DisableControlAutoSizing(Site); Site.UpdateHeaderShowing; + if Site.fminimized then + if not AValue then + site.MinimizeSite; end; end; EnableAllAutoSizing; @@ -2668,6 +2843,20 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm(Sender: TObject); +begin + StopHideOverlappingTimer; + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2887,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2916,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -2914,6 +3109,7 @@ raise Exception.Create('TAnchorDockMaster.MakeDockable '+Format( adrsNotSupportedHasParent, [DbgSName(AControl), DbgSName(AControl)])); end; + site.UpdateHeaderShowing; if (Site<>nil) and Show then MakeVisible(Site,BringToFront); finally @@ -3018,7 +3214,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3259,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3276,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3300,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3336,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3344,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3369,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3464,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3474,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3536,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3557,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3436,8 +3651,11 @@ if fUpdateCount<=0 then RaiseGDBException(''); dec(fUpdateCount); - if fUpdateCount=0 then + if fUpdateCount=0 then begin SimplifyPendingLayouts; + UpdateHeaders; + InvalidateHeaders; + end; end; function TAnchorDockMaster.IsReleasing(AControl: TControl): Boolean; @@ -3664,6 +3882,24 @@ LUIncreaseChangeStamp64(FOptionsChangeStamp); end; +procedure TAnchorDockMaster.UpdateHeaders; +var + i: Integer; + AControl: TControl; + AHostSite: TAnchorDockHostSite; +begin + for i:=0 to ControlCount-1 do begin + AControl:=Controls[i]; + if not DockedControlIsVisible(AControl) then continue; + while Assigned(AControl) do + begin + if AControl is TAnchorDockHostSite then + TAnchorDockHostSite(AControl).UpdateHeaderShowing; + AControl:=AControl.parent; + end; + end; +end; + { TAnchorDockHostSite } procedure TAnchorDockHostSite.SetHeaderSide(const AValue: TAnchorKind); @@ -3680,6 +3916,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4356,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4472,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4553,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4719,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4831,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5420,119 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +function TAnchorDockHostSite.CanBeMinimized(out Splitter: TAnchorDockSplitter; + out SplitterAnchorKind:TAnchorKind):boolean; +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; +begin + result:=false; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) then + result:=true; + end +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + //OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if CanBeMinimized(Splitter,SplitterAnchorKind) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + //self.DoDockOver(); OnDockOver; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + dockmaster.UpdateHeaders; + dockmaster.InvalidateHeaders; + Splitter.SetBoundsPercentually; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + header.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm.Panel; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + header.Parent:=self; + header.UpdateHeaderControls; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5281,21 +5649,24 @@ begin if csDestroying in ComponentState then exit; NewCaption:=''; - for i:=0 to ControlCount-1 do begin - Child:=Controls[i]; - if Child=Exclude then continue; - if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) - or (Child is TAnchorDockPageControl) then begin - if NewCaption<>'' then - NewCaption:=NewCaption+','; - NewCaption:=NewCaption+Child.Caption; + if FMinimized then + NewCaption:=FMinimizedControl.Caption + else + for i:=0 to ControlCount-1 do begin + Child:=Controls[i]; + if Child=Exclude then continue; + if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) + or (Child is TAnchorDockPageControl) then begin + if NewCaption<>'' then + NewCaption:=NewCaption+','; + NewCaption:=NewCaption+Child.Caption; + end; end; - end; OldCaption:=Caption; Caption:=NewCaption; //debugln(['TAnchorDockHostSite.UpdateDockCaption Caption="',Caption,'" NewCaption="',NewCaption,'" HasParent=',Parent<>nil,' ',DbgSName(Header)]); - if ((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) - or (not DockMaster.ShowHeaderCaption) then + if {((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) + or (not DockMaster.ShowHeaderCaption)}false then Header.Caption:='' else Header.Caption:=Caption; @@ -5306,9 +5677,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm)); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5339,7 +5709,8 @@ end; CanDock:=(Client is TAnchorDockHostSite) - and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client); + and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client) + and not FMinimized; //debugln(['TAnchorDockHostSite.GetSiteInfo ',DbgSName(Self),' ',dbgs(BoundsRect),' ',Caption,' CanDock=',CanDock,' PtIn=',PtInRect(InfluenceRect,MousePos)]); if Assigned(OnGetSiteInfo) then @@ -5362,9 +5733,33 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +const +OppositeAlign: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); +OppositeAnchorKindAlign: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKindAlign[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5388,10 +5783,16 @@ end; procedure TAnchorDockHostSite.UpdateHeaderShowing; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=(DockMaster.DockSitesCanBeMinimized and CanBeMinimized(Splitter,SplitterAnchorKind))or FMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5432,7 +5833,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5851,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5862,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5877,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5894,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5562,13 +5966,34 @@ end; procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; begin - if Parent is TAnchorDockHostSite then begin - DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(Parent),true); - TAnchorDockHostSite(Parent).CloseSite; + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; end; + if HeaderParent is TAnchorDockHostSite then begin + DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent),true); + HeaderParent.CloseSite; + end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; +begin + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; + end; + if HeaderParent is TAnchorDockHostSite then begin + HeaderParent.MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5635,11 +6060,18 @@ if CloseButton.IsControlVisible and (CloseButton.Parent=Self) then begin if Align in [alLeft,alRight] then - r.Top:=CloseButton.Top+CloseButton.Height+1 + r.Top:=CloseButton.Top+CloseButton.Height+ButtonBorderSpacingAround else - r.Right:=CloseButton.Left-1; + r.Right:=CloseButton.Left-ButtonBorderSpacingAround; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+ButtonBorderSpacingAround + else + r.Right:=MinimizeButton.Left-ButtonBorderSpacingAround; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,26 +6160,127 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + SiteMinimized:Boolean; begin inherited MouseDown(Button, Shift, X, Y); - if (Button=mbLeft) and DockMaster.AllowDragging then - DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + SiteMinimized:=False; + fUseTimer:=false; + StopMouseNoMoveTimer; + if Parent is TAnchorDockHostSite then + SiteMinimized:=(Parent as TAnchorDockHostSite).FMinimized; + if SiteMinimized then begin + DoMouseNoMoveTimer(nil); + end else + begin + if parent<>nil then + if DockMaster.FOverlappingForm<>nil then + //if parent=DockMaster.FOverlappingForm.Panel then + DockMaster.HideOverlappingForm(nil); + if (Button=mbLeft) and (DockMaster.AllowDragging) and (DockMaster.FOverlappingForm=nil) then + DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + end; end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; + if (parent is TAnchorDockHostSite)and(DockMaster.FOverlappingForm=nil)then + fUseTimer:=true; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if fUseTimer then begin + if DockTimer.Enabled then DockTimer.Enabled:=false; + DockTimer.Interval:=MouseNoMoveTime; + DockTimer.OnTimer:=@DoMouseNoMoveTimer; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + DockTimer.OnTimer:=nil; + DockTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + //if fUseTimer then + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then - CloseButton.Align:=alTop; + if CloseButton<>nil then begin + //MinimizeButton.Align:=alTop; + //CloseButton.Align:=alTop; + CloseButton.AnchorSide[akRight].Side := asrCenter; + CloseButton.AnchorSide[akRight].Control := self; + CloseButton.AnchorSide[akTop].Side := asrTop; + CloseButton.AnchorSide[akTop].Control := self; + CloseButton.Anchors := CloseButton.Anchors + [akTop] + [akRight]; + + MinimizeButton.AnchorSide[akRight].Side := asrCenter; + MinimizeButton.AnchorSide[akRight].Control := CloseButton; + MinimizeButton.AnchorSide[akTop].Side := asrBottom; + MinimizeButton.AnchorSide[akTop].Control := CloseButton; + MinimizeButton.Anchors := MinimizeButton.Anchors + [akTop] + [akRight]; + end; end else begin - if CloseButton<>nil then - CloseButton.Align:=alRight; + if CloseButton<>nil then begin + //MinimizeButton.Align:=alRight; + //CloseButton.Align:=alRight; + CloseButton.AnchorSide[akRight].Side := asrRight; + CloseButton.AnchorSide[akRight].Control := self; + CloseButton.AnchorSide[akTop].Side := asrCenter; + CloseButton.AnchorSide[akTop].Control := self; + CloseButton.Anchors := CloseButton.Anchors - [akLeft] + [akRight]; + + MinimizeButton.AnchorSide[akRight].Side := asrLeft; + MinimizeButton.AnchorSide[akRight].Control := CloseButton; + MinimizeButton.AnchorSide[akTop].Side := asrCenter; + MinimizeButton.AnchorSide[akTop].Control := CloseButton; + MinimizeButton.Anchors := MinimizeButton.Anchors - [akLeft] + [akRight]; + end; end; + CloseButton.BorderSpacing.Around:=ButtonBorderSpacingAround; + MinimizeButton.BorderSpacing.Around:=ButtonBorderSpacingAround; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6320,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6332,23 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; + fUseTimer:=true; end; { TAnchorDockCloseButton } @@ -5830,6 +6375,31 @@ Result := ThemeServices.GetElementDetails(WindowPart); end; +procedure SizeCorrector(var current,recomend:integer); +begin + if recomend<0 then begin + if current>0 then + recomend:=current + else + current:=HardcodedButtonSize; + end else begin + if current>recomend then + current:=recomend + else begin + if current>0 then + recomend:=current + else + current:=recomend; + end; + end; +end; + +procedure ButtonSizeCorrector(var w,h:integer); +begin + SizeCorrector(w,PreferredButtonWidth); + SizeCorrector(h,PreferredButtonHeight); +end; + procedure TAnchorDockCloseButton.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); begin @@ -5837,6 +6407,7 @@ begin PreferredWidth:=cx; PreferredHeight:=cy; + ButtonSizeCorrector(PreferredWidth,PreferredHeight); {$IF defined(LCLGtk2) or defined(Carbon)} inc(PreferredWidth,2); inc(PreferredHeight,2); @@ -5844,6 +6415,45 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + ButtonSizeCorrector(PreferredWidth,PreferredHeight); + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6213,6 +6823,9 @@ ClientRectChanged:=(WidthDiff<>0) or (HeightDiff<>0); if ClientRectChanged or PreferredSiteSizeAsSiteMinimum then AlignChilds; + if ClientRectChanged then + if DockMaster.FOverlappingForm<>nil then + DockMaster.HideOverlappingForm(nil); end; procedure TAnchorDockManager.SaveToStream(Stream: TStream); @@ -6234,6 +6847,27 @@ BestDistance:=CurDistance; end; + procedure UnMinimizeSitesAt; + var + i:integer; + Site: TAnchorDockHostSite; + ARect:trect; + begin + for i:=0 to DockMaster.ComponentCount-1 do begin + Site:=TAnchorDockHostSite(DockMaster.Components[i]); + if not (Site is TAnchorDockHostSite) then continue; + if not Site.Showing then continue; + if not Site.Enabled then continue; + if not Site.IsVisible then continue; + ARect.TopLeft:=Site.ClientToScreen(point(0,0)); + ARect.BottomRight:=Site.ClientToScreen(point(Site.Width,Site.Height)); + InflateRect(ARect,DockMaster.DragTreshold+10,DockMaster.DragTreshold+10); + if PtInRect(ARect, ADockObject.DragPos) then + if Site.FMinimized then + Application.QueueAsyncCall(@Site.AsyncMinimizeSite,0); + end; + end; + var p: TPoint; LastTabRect: TRect; @@ -6245,6 +6879,8 @@ exit(false); end; + UnMinimizeSitesAt; + p:=Site.ScreenToClient(ADockObject.DragPos); //debugln(['TAnchorDockManager.GetDockEdge ',dbgs(p),' ',dbgs(Site.BoundsRect),' ',DbgSName(Site)]); if (DockSite<>nil) and (DockSite.Pages<>nil) then begin @@ -6505,32 +7141,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7222,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6645,7 +7340,7 @@ begin inherited MouseDown(Button, Shift, X, Y); ATabIndex := IndexOfPageAt(X, Y); - if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) then + if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) and (DockMaster.FOverlappingForm=nil) then begin APage:=Page[ATabIndex]; if (APage.ControlCount>0) and (APage.Controls[0] is TAnchorDockHostSite) then @@ -6782,6 +7477,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; + Panel:=TPanel.Create(self); + Panel.BorderStyle:=bsSingle; + Panel.Align:=alClient; + Panel.Parent:=self; + Panel.Visible:=true; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7544,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + DockTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(DockTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -202,7 +203,7 @@ HeaderAlignTopSpinEdit.Visible:=true; HeaderAlignTopTrackBar.Visible:=false; - HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,HighlightFocusedCheckBox); + HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,DockSitesCanBeMinimized); HeaderAlignTopLabel.AnchorVerticalCenterTo(HeaderAlignTopSpinEdit); UpdateHeaderAlignTopLabel; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
See anchordocking_minimize_docksite10.patch 1. I unminimize sites which came the mouse, it's not a very good solution, but so far I haven't been able to do better 2,3,4 Fixed |
|
|
|
Thank you! A lot is working, but I found some things: 1. See picture Test3.png. It seems, the space for the buttons is correct but the buttons itself is half the size. 2. - load layout test.xml (don't maximize MiniIDE) - minimize Source Editor 1 - move Messages right of minimized Source Editor 1, but don't dock it - move Messages out of MiniIDE and release mouse --> Messages is further activated as docking site, with no mouse pressed - pressing ESC, Messages is moved to coordinates 0, 0 3. - load layout test2.xml - minimize Messages - move Project Inspector on Messages --> Project Inspector is docked right from Messages without releasing of mouse 4. (do the same steps as in 3.) - load layout test2.xml - minimize Messages - move Project Inspector on Messages - move Project Inspector back to FPDoc Editor --> Messages has no minimize button anymore |
|
test2.xml (2,636 bytes)
<?xml version="1.0" encoding="utf-8"?> <CONFIG> <MainConfig> <Nodes ChildCount="1"> <Item1 Name="MainIDE" Type="CustomSite" ChildCount="1" WindowState="Maximized"> <Bounds Top="-4" Left="-4" Width="1920" Height="1012"> <WorkArea> <Rect Right="1920" Bottom="1036"/> </WorkArea> </Bounds> <Item1 Name="AnchorDockSite3" Type="Layout" ChildCount="7" WindowState="Maximized"> <Bounds Top="80" Width="1920" Height="908" SplitterPos="75"/> <Anchors Align="Bottom"/> <Item1 Name="ObjectInspector" Type="Control" WindowState="Maximized"> <Bounds Width="644" Height="908"/> <Anchors Right="AnchorDockSplitter2"/> </Item1> <Item2 Name="AnchorDockSplitter2" Type="SplitterVertical" WindowState="Maximized"> <Bounds Left="644" Width="4" Height="908"/> </Item2> <Item3 Name="SourceEditor1" Type="Control" WindowState="Maximized"> <Bounds Left="648" Width="779" Height="638"/> <Anchors Left="AnchorDockSplitter2" Right="AnchorDockSplitter4" Bottom="AnchorDockSplitter3"/> </Item3> <Item4 Name="AnchorDockSplitter3" Type="SplitterHorizontal" WindowState="Maximized"> <Bounds Top="638" Left="648" Width="779" Height="4"/> <Anchors Left="AnchorDockSplitter2" Right="AnchorDockSplitter4"/> </Item4> <Item5 Name="AnchorDockSite4" Type="Pages" ChildCount="2" WindowState="Maximized"> <Bounds Top="642" Left="648" Width="779" Height="266"/> <Anchors Top="AnchorDockSplitter3" Left="AnchorDockSplitter2" Right="AnchorDockSplitter4"/> <Item1 Name="FPDocEditor" Type="Control" WindowState="Maximized"> <Bounds Width="320" Height="240"/> <Anchors Align="Client"/> </Item1> <Item2 Name="ProjectInspector" Type="Control" WindowState="Maximized"> <Bounds Width="762" Height="240"/> <Anchors Align="Client"/> </Item2> </Item5> <Item6 Name="AnchorDockSplitter4" Type="SplitterVertical" WindowState="Maximized"> <Bounds Left="1427" Width="4" Height="908"/> </Item6> <Item7 Name="Messages" Type="Control" WindowState="Maximized"> <Bounds Left="1431" Width="489" Height="908"/> <Anchors Left="AnchorDockSplitter4"/> </Item7> </Item1> </Item1> </Nodes> </MainConfig> <Settings DockSitecCanBeMinimized="True"/> </CONFIG> |
|
1. Themes.GetDetailSize without aero return 11,11 for twSmallClose (13,13 with aero). Therefore the screenshot is correct. I refused buttons.align and buttons became square. 2. This is separate DragManager issue 3. Yes, I will fix it soon 4. Because mouse capture changed >>1. I unminimize sites which came the mouse, it's not a very good solution, but so far I haven't been able to do better I will look for another solution |
|
anchordocking_minimize_docksite11.patch (78,809 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -109,6 +109,31 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + HideOverlappingFormByMouseLoseTime=500; + ButtonBorderSpacingAround=4; + OppositeAnchorKind2Align: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); + {AnchorKind2Align: array[TAnchorKind] of TAlign = ( + alTop, // akTop, + alLeft, // akLeft, + alRight,// akRight, + alBottom// akBottom + );} + OppositeAnchorKind2TADLHeaderPosition: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); + + type TAnchorDockHostSite = class; @@ -123,6 +148,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +166,13 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + fUseTimer:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +184,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +196,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +233,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +285,14 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + public + AnchorDockHostSite:TAnchorDockHostSite; + Panel:TPanel; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +314,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +374,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -329,6 +388,7 @@ procedure UpdateDockCaption(Exclude: TControl = nil); override; procedure UpdateHeaderAlign; procedure UpdateHeaderShowing; + function CanBeMinimized(out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; procedure BeginUpdateLayout; procedure EndUpdateLayout; function UpdatingLayout: boolean; @@ -337,6 +397,7 @@ procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode); property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; + function GetDockEdge(const MousePos: TPoint): TAlign; override; property HeaderSide: TAnchorKind read FHeaderSide write SetHeaderSide; property Header: TAnchorDockHeader read FHeader; @@ -431,6 +492,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +510,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +529,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +566,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +596,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +607,9 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure UpdateHeaders; + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +630,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -584,8 +654,12 @@ procedure SetHideHeaderCaptionFloatingControl(const AValue: boolean); procedure SetSplitterWidth(const AValue: integer); procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure StartHideOverlappingTimer; + procedure StopHideOverlappingTimer; procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm(Sender: TObject); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +754,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,8 +773,14 @@ var DockMaster: TAnchorDockMaster = nil; + DockTimer: TTimer = nil; + PreferredButtonWidth:integer=-1; + PreferredButtonHeight:integer=-1; + + const + HardcodedButtonSize:integer=13; ADHeaderStyleNames: array[TADHeaderStyle] of string = ( 'Frame3D', 'Line', @@ -970,6 +1051,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1463,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1490,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1517,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1540,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1562,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1585,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1608,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2136,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2157,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2329,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2494,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2504,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2422,11 +2559,54 @@ OptionsChanged; end; +procedure TAnchorDockMaster.StartHideOverlappingTimer; +begin + if not DockTimer.Enabled then begin + DockTimer.Interval:=HideOverlappingFormByMouseLoseTime; + DockTimer.OnTimer:=@HideOverlappingForm; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockMaster.StopHideOverlappingTimer; +begin + DockTimer.Enabled:=False; + DockTimer.Interval:=0; + DockTimer.OnTimer:=nil; +end; + +function IsParentControl(aParent, aControl: TControl): boolean; +begin + while (aControl <> nil) and (aControl.Parent <> nil) do + begin + if (aControl=aParent) then + exit(true); + aControl := aControl.Parent; + end; + result:=aControl=aParent; +end; + + procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not IsParentControl(FOverlappingForm, GetCaptureControl) then begin + if not PtInRect(Bounds,MousePos) then + StartHideOverlappingTimer + else + StopHideOverlappingTimer; + end; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2694,18 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + UpdateHeaders; + InvalidateHeaders; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2598,6 +2790,9 @@ if (Site.Header<>nil) then begin DisableControlAutoSizing(Site); Site.UpdateHeaderShowing; + if Site.fminimized then + if not AValue then + site.MinimizeSite; end; end; EnableAllAutoSizing; @@ -2668,6 +2863,20 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm(Sender: TObject); +begin + StopHideOverlappingTimer; + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2907,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2936,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -2914,6 +3129,7 @@ raise Exception.Create('TAnchorDockMaster.MakeDockable '+Format( adrsNotSupportedHasParent, [DbgSName(AControl), DbgSName(AControl)])); end; + site.UpdateHeaderShowing; if (Site<>nil) and Show then MakeVisible(Site,BringToFront); finally @@ -3018,7 +3234,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3279,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3296,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3320,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3356,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3364,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3389,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3484,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3494,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3556,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3577,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3436,8 +3671,11 @@ if fUpdateCount<=0 then RaiseGDBException(''); dec(fUpdateCount); - if fUpdateCount=0 then + if fUpdateCount=0 then begin SimplifyPendingLayouts; + UpdateHeaders; + InvalidateHeaders; + end; end; function TAnchorDockMaster.IsReleasing(AControl: TControl): Boolean; @@ -3664,6 +3902,24 @@ LUIncreaseChangeStamp64(FOptionsChangeStamp); end; +procedure TAnchorDockMaster.UpdateHeaders; +var + i: Integer; + AControl: TControl; + AHostSite: TAnchorDockHostSite; +begin + for i:=0 to ControlCount-1 do begin + AControl:=Controls[i]; + if not DockedControlIsVisible(AControl) then continue; + while Assigned(AControl) do + begin + if AControl is TAnchorDockHostSite then + TAnchorDockHostSite(AControl).UpdateHeaderShowing; + AControl:=AControl.parent; + end; + end; +end; + { TAnchorDockHostSite } procedure TAnchorDockHostSite.SetHeaderSide(const AValue: TAnchorKind); @@ -3680,6 +3936,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4376,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4492,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4573,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4739,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4851,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5440,119 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;var AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +function TAnchorDockHostSite.CanBeMinimized(out Splitter: TAnchorDockSplitter; + out SplitterAnchorKind:TAnchorKind):boolean; +var + AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; +begin + result:=false; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) then + result:=true; + end +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + //OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if CanBeMinimized(Splitter,SplitterAnchorKind) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + //self.DoDockOver(); OnDockOver; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + dockmaster.UpdateHeaders; + dockmaster.InvalidateHeaders; + Splitter.SetBoundsPercentually; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + header.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm.Panel; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + header.Parent:=self; + header.UpdateHeaderControls; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5281,21 +5669,24 @@ begin if csDestroying in ComponentState then exit; NewCaption:=''; - for i:=0 to ControlCount-1 do begin - Child:=Controls[i]; - if Child=Exclude then continue; - if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) - or (Child is TAnchorDockPageControl) then begin - if NewCaption<>'' then - NewCaption:=NewCaption+','; - NewCaption:=NewCaption+Child.Caption; + if FMinimized then + NewCaption:=FMinimizedControl.Caption + else + for i:=0 to ControlCount-1 do begin + Child:=Controls[i]; + if Child=Exclude then continue; + if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) + or (Child is TAnchorDockPageControl) then begin + if NewCaption<>'' then + NewCaption:=NewCaption+','; + NewCaption:=NewCaption+Child.Caption; + end; end; - end; OldCaption:=Caption; Caption:=NewCaption; //debugln(['TAnchorDockHostSite.UpdateDockCaption Caption="',Caption,'" NewCaption="',NewCaption,'" HasParent=',Parent<>nil,' ',DbgSName(Header)]); - if ((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) - or (not DockMaster.ShowHeaderCaption) then + if {((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) + or (not DockMaster.ShowHeaderCaption)}false then Header.Caption:='' else Header.Caption:=Caption; @@ -5306,9 +5697,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm)); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5339,7 +5729,8 @@ end; CanDock:=(Client is TAnchorDockHostSite) - and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client); + and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client) + and not FMinimized; //debugln(['TAnchorDockHostSite.GetSiteInfo ',DbgSName(Self),' ',dbgs(BoundsRect),' ',Caption,' CanDock=',CanDock,' PtIn=',PtInRect(InfluenceRect,MousePos)]); if Assigned(OnGetSiteInfo) then @@ -5362,9 +5753,20 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKind2TADLHeaderPosition[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5388,10 +5790,16 @@ end; procedure TAnchorDockHostSite.UpdateHeaderShowing; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=(DockMaster.DockSitesCanBeMinimized and CanBeMinimized(Splitter,SplitterAnchorKind))or FMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5415,6 +5823,31 @@ Result:=(fUpdateLayout>0) or (csDestroying in ComponentState); end; +function AcceptAlign(Site:TAnchorDockHostSite; AlignCandidate:TAlign):TAlign; +var + i:integer; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + MinimizedSiteAlign:TAlign; +begin + for i:=0 to Site.ControlCount-1 do + if Site.Controls[i] is TAnchorDockHostSite then + if (Site.Controls[i] as TAnchorDockHostSite).FMinimized then begin + if FindNearestSpliter(Site.Controls[i] as TAnchorDockHostSite,Splitter,SplitterAnchorKind) then begin + MinimizedSiteAlign:=OppositeAnchorKind2Align[SplitterAnchorKind]; + if AlignCandidate=MinimizedSiteAlign then + exit(alNone); + end + end; + result:=AlignCandidate; +end; + +function TAnchorDockHostSite.GetDockEdge(const MousePos: TPoint): TAlign; +begin + result:=inherited; + result:=AcceptAlign(self,result); +end; + procedure TAnchorDockHostSite.SaveLayout( LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode); var @@ -5432,7 +5865,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5883,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5894,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5909,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5926,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5562,13 +5998,34 @@ end; procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; begin - if Parent is TAnchorDockHostSite then begin - DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(Parent),true); - TAnchorDockHostSite(Parent).CloseSite; + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; end; + if HeaderParent is TAnchorDockHostSite then begin + DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent),true); + HeaderParent.CloseSite; + end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; +begin + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; + end; + if HeaderParent is TAnchorDockHostSite then begin + HeaderParent.MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5635,11 +6092,18 @@ if CloseButton.IsControlVisible and (CloseButton.Parent=Self) then begin if Align in [alLeft,alRight] then - r.Top:=CloseButton.Top+CloseButton.Height+1 + r.Top:=CloseButton.Top+CloseButton.Height+ButtonBorderSpacingAround else - r.Right:=CloseButton.Left-1; + r.Right:=CloseButton.Left-ButtonBorderSpacingAround; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+ButtonBorderSpacingAround + else + r.Right:=MinimizeButton.Left-ButtonBorderSpacingAround; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,26 +6192,127 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + SiteMinimized:Boolean; begin inherited MouseDown(Button, Shift, X, Y); - if (Button=mbLeft) and DockMaster.AllowDragging then - DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + SiteMinimized:=False; + fUseTimer:=false; + StopMouseNoMoveTimer; + if Parent is TAnchorDockHostSite then + SiteMinimized:=(Parent as TAnchorDockHostSite).FMinimized; + if SiteMinimized then begin + DoMouseNoMoveTimer(nil); + end else + begin + if parent<>nil then + if DockMaster.FOverlappingForm<>nil then + //if parent=DockMaster.FOverlappingForm.Panel then + DockMaster.HideOverlappingForm(nil); + if (Button=mbLeft) and (DockMaster.AllowDragging) and (DockMaster.FOverlappingForm=nil) then + DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + end; end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; + if (parent is TAnchorDockHostSite)and(DockMaster.FOverlappingForm=nil)then + fUseTimer:=true; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if fUseTimer then begin + if DockTimer.Enabled then DockTimer.Enabled:=false; + DockTimer.Interval:=MouseNoMoveTime; + DockTimer.OnTimer:=@DoMouseNoMoveTimer; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + DockTimer.OnTimer:=nil; + DockTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + //if fUseTimer then + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then - CloseButton.Align:=alTop; + if CloseButton<>nil then begin + //MinimizeButton.Align:=alTop; + //CloseButton.Align:=alTop; + CloseButton.AnchorSide[akRight].Side := asrCenter; + CloseButton.AnchorSide[akRight].Control := self; + CloseButton.AnchorSide[akTop].Side := asrTop; + CloseButton.AnchorSide[akTop].Control := self; + CloseButton.Anchors := CloseButton.Anchors + [akTop] + [akRight]; + + MinimizeButton.AnchorSide[akRight].Side := asrCenter; + MinimizeButton.AnchorSide[akRight].Control := CloseButton; + MinimizeButton.AnchorSide[akTop].Side := asrBottom; + MinimizeButton.AnchorSide[akTop].Control := CloseButton; + MinimizeButton.Anchors := MinimizeButton.Anchors + [akTop] + [akRight]; + end; end else begin - if CloseButton<>nil then - CloseButton.Align:=alRight; + if CloseButton<>nil then begin + //MinimizeButton.Align:=alRight; + //CloseButton.Align:=alRight; + CloseButton.AnchorSide[akRight].Side := asrRight; + CloseButton.AnchorSide[akRight].Control := self; + CloseButton.AnchorSide[akTop].Side := asrCenter; + CloseButton.AnchorSide[akTop].Control := self; + CloseButton.Anchors := CloseButton.Anchors - [akLeft] + [akRight]; + + MinimizeButton.AnchorSide[akRight].Side := asrLeft; + MinimizeButton.AnchorSide[akRight].Control := CloseButton; + MinimizeButton.AnchorSide[akTop].Side := asrCenter; + MinimizeButton.AnchorSide[akTop].Control := CloseButton; + MinimizeButton.Anchors := MinimizeButton.Anchors - [akLeft] + [akRight]; + end; end; + CloseButton.BorderSpacing.Around:=ButtonBorderSpacingAround; + MinimizeButton.BorderSpacing.Around:=ButtonBorderSpacingAround; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6352,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6364,23 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; + fUseTimer:=true; end; { TAnchorDockCloseButton } @@ -5830,6 +6407,31 @@ Result := ThemeServices.GetElementDetails(WindowPart); end; +procedure SizeCorrector(var current,recomend:integer); +begin + if recomend<0 then begin + if current>0 then + recomend:=current + else + current:=HardcodedButtonSize; + end else begin + if current>recomend then + current:=recomend + else begin + if current>0 then + recomend:=current + else + current:=recomend; + end; + end; +end; + +procedure ButtonSizeCorrector(var w,h:integer); +begin + SizeCorrector(w,PreferredButtonWidth); + SizeCorrector(h,PreferredButtonHeight); +end; + procedure TAnchorDockCloseButton.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); begin @@ -5837,6 +6439,7 @@ begin PreferredWidth:=cx; PreferredHeight:=cy; + ButtonSizeCorrector(PreferredWidth,PreferredHeight); {$IF defined(LCLGtk2) or defined(Carbon)} inc(PreferredWidth,2); inc(PreferredHeight,2); @@ -5844,6 +6447,45 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + ButtonSizeCorrector(PreferredWidth,PreferredHeight); + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6213,6 +6855,9 @@ ClientRectChanged:=(WidthDiff<>0) or (HeightDiff<>0); if ClientRectChanged or PreferredSiteSizeAsSiteMinimum then AlignChilds; + if ClientRectChanged then + if DockMaster.FOverlappingForm<>nil then + DockMaster.HideOverlappingForm(nil); end; procedure TAnchorDockManager.SaveToStream(Stream: TStream); @@ -6287,6 +6932,11 @@ ADockObject.DropOnControl:=Site else ADockObject.DropOnControl:=nil; + if Site is TAnchorDockHostSite then begin + ADockObject.DropAlign:=AcceptAlign(Site as TAnchorDockHostSite,ADockObject.DropAlign); + if ADockObject.DropAlign=alNone then + exit(false); + end; end; //debugln(['TAnchorDockManager.GetDockEdge ADockObject.DropAlign=',dbgs(ADockObject.DropAlign),' DropOnControl=',DbgSName(ADockObject.DropOnControl)]); Result:=true; @@ -6505,32 +7155,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7236,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6645,7 +7354,7 @@ begin inherited MouseDown(Button, Shift, X, Y); ATabIndex := IndexOfPageAt(X, Y); - if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) then + if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) and (DockMaster.FOverlappingForm=nil) then begin APage:=Page[ATabIndex]; if (APage.ControlCount>0) and (APage.Controls[0] is TAnchorDockHostSite) then @@ -6782,6 +7491,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; + Panel:=TPanel.Create(self); + Panel.BorderStyle:=bsSingle; + Panel.Align:=alClient; + Panel.Parent:=self; + Panel.Visible:=true; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7558,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + DockTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(DockTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -202,7 +203,7 @@ HeaderAlignTopSpinEdit.Visible:=true; HeaderAlignTopTrackBar.Visible:=false; - HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,HighlightFocusedCheckBox); + HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,DockSitesCanBeMinimized); HeaderAlignTopLabel.AnchorVerticalCenterTo(HeaderAlignTopSpinEdit); UpdateHeaderAlignTopLabel; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; Index: lcl/include/dragmanager.inc =================================================================== --- lcl/include/dragmanager.inc (revision 59428) +++ lcl/include/dragmanager.inc (working copy) @@ -484,6 +484,8 @@ else DropAlign := DropOnControl.GetDockEdge(DropOnControl.ScreenToClient(APosition)); end; + if DropAlign=alNone then + ATarget:=nil; end; if ATarget <> FDockObject.DragTarget then |
|
anchordocking_minimize_docksite11.patch Dock to minimized sites disabled. But it need smal changes to lcl - dragmanager.inc |
|
test3.xml (2,232 bytes)
<?xml version="1.0" encoding="utf-8"?> <CONFIG> <MainConfig> <Nodes ChildCount="1"> <Item1 Name="MainIDE" Type="CustomSite" ChildCount="1"> <Bounds Top="50" Left="100" Width="722" Height="502"> <WorkArea> <Rect Right="1920" Bottom="1036"/> </WorkArea> </Bounds> <Item1 Name="AnchorDockSite6" Type="Layout" ChildCount="9"> <Bounds Top="58" Width="722" Height="420" SplitterPos="53"/> <Anchors Align="Bottom"/> <Item1 Name="ObjectInspector" Type="Control"> <Bounds Width="177" Height="420"/> <Anchors Right="AnchorDockSplitter2"/> </Item1> <Item2 Name="AnchorDockSplitter2" Type="SplitterVertical"> <Bounds Left="177" Width="4" Height="420"/> </Item2> <Item3 Name="SourceEditor1" Type="Control"> <Bounds Left="181" Width="160" Height="420"/> <Anchors Left="AnchorDockSplitter2" Right="AnchorDockSplitter4"/> </Item3> <Item4 Name="FPDocEditor" Type="Control"> <Bounds Left="632" Width="90" Height="420"/> <Anchors Left="AnchorDockSplitter3"/> </Item4> <Item5 Name="AnchorDockSplitter4" Type="SplitterVertical"> <Bounds Left="341" Width="4" Height="420"/> </Item5> <Item6 Name="Messages" Type="Control" Minimized="True"> <Bounds Left="345" Width="15" Height="420"/> <Anchors Left="AnchorDockSplitter4" Right="AnchorDockSplitter5"/> </Item6> <Item7 Name="AnchorDockSplitter5" Type="SplitterVertical"> <Bounds Left="522" Width="4" Height="420"/> </Item7> <Item8 Name="ProjectInspector" Type="Control"> <Bounds Left="364" Width="264" Height="420"/> <Anchors Left="AnchorDockSplitter5" Right="AnchorDockSplitter3"/> </Item8> <Item9 Name="AnchorDockSplitter3" Type="SplitterVertical"> <Bounds Left="628" Width="4" Height="420"/> </Item9> </Item1> </Item1> </Nodes> </MainConfig> <Settings DockSitecCanBeMinimized="True"/> </CONFIG> |
|
Sorry for the delay, currently I have very low spare time and I want test the issue before I commit the patch. Please load test3.xml. There are two issues. 1. The minimize button of Source Editor 1 is missing. This is maybe per design but if someone will use this feature, he might minimize more then one site at one place. 2.Minimize Project Inspector, then you have some space. Maybe thatswhile you don't show the minimize button?! I get a Range Error in Lazarus-IDE with Qt, maybe because of 2. ?! A further minor issue I see. The background of the form caption in Qt is further transparent for the popup. |
|
1.2. Yes, it by design. Project Inspector also should not have a minimize button. if the adjacent window is minimized, this window should not have a minimize button I'll fix it soon. too there were of free time problems >>I get a Range Error in Lazarus-IDE with Qt, maybe because of 2. ?! I have not encountered this. >>A further minor issue I see. The background of the form caption in Qt is further transparent for the popup. there is still an incorrect getting of popup window borders if it popup on paged site. I think it's a qt issue. |
|
anchordocking_minimize_docksite12.patch (78,825 bytes)
Index: components/anchordocking/anchordocking.pas =================================================================== --- components/anchordocking/anchordocking.pas (revision 59428) +++ components/anchordocking/anchordocking.pas (working copy) @@ -109,6 +109,37 @@ const ADAutoSizingReason = 'TAnchorDockMaster Delayed'; {$ENDIF} +const EmptyMouseTimeStartX=low(Integer); + MouseNoMoveDelta=5; + MouseNoMoveTime=500; + HideOverlappingFormByMouseLoseTime=500; + ButtonBorderSpacingAround=4; + OppositeAnchorKind2Align: array[TAnchorKind] of TAlign = ( + alBottom, // akTop, + alRight, // akLeft, + alLeft, // akRight, + alTop // akBottom + ); + OppositeAnchorKind: array[TAnchorKind] of TAnchorKind = ( + akBottom, // akTop, + akRight, // akLeft, + akLeft, // akRight, + akTop // akBottom + ); + {AnchorKind2Align: array[TAnchorKind] of TAlign = ( + alTop, // akTop, + alLeft, // akLeft, + alRight,// akRight, + alBottom// akBottom + );} + OppositeAnchorKind2TADLHeaderPosition: array[TAnchorKind] of TADLHeaderPosition = ( + adlhpBottom, // akTop, + adlhpRight, // akLeft, + adlhpLeft, // akRight, + adlhpTop // akBottom + ); + + type TAnchorDockHostSite = class; @@ -123,6 +154,14 @@ PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; end; + TAnchorDockMinimizeButton = class(TCustomSpeedButton) + protected + function GetDrawDetails: TThemedElementDetails; override; + procedure CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; {%H-}WithThemeSpace: Boolean); override; + end; + + { TAnchorDockHeader The panel of a TAnchorDockHostSite containing the close button and the caption when the form is docked. The header can be shown at any of the four @@ -133,9 +172,13 @@ TAnchorDockHeader = class(TCustomPanel) private FCloseButton: TCustomSpeedButton; + FMinimizeButton: TCustomSpeedButton; FHeaderPosition: TADLHeaderPosition; fFocused:Boolean; + fUseTimer:Boolean; + FMouseTimeStartX,FMouseTimeStartY:Integer; procedure CloseButtonClick(Sender: TObject); + procedure MinimizeButtonClick(Sender: TObject); procedure HeaderPositionItemClick(Sender: TObject); procedure UndockButtonClick(Sender: TObject); procedure MergeButtonClick(Sender: TObject); @@ -147,6 +190,11 @@ PreferredHeight: integer; WithThemeSpace: Boolean); override; procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseMove(Shift: TShiftState; X,Y: Integer); override; + procedure MouseLeave; override; + procedure StartMouseNoMoveTimer(X, Y: Integer); + procedure StopMouseNoMoveTimer; + procedure DoMouseNoMoveTimer(Sender: TObject); procedure UpdateHeaderControls; procedure SetAlign(Value: TAlign); override; procedure DoOnShowHint(HintInfo: PHintInfo); override; @@ -154,6 +202,7 @@ public constructor Create(TheOwner: TComponent); override; property CloseButton: TCustomSpeedButton read FCloseButton; + property MinimizeButton: TCustomSpeedButton read FMinimizeButton; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property BevelOuter default bvNone; end; @@ -190,6 +239,7 @@ procedure SetBoundsKeepDockBounds(ALeft, ATop, AWidth, AHeight: integer); // movement for scaling keeps the DockBounds function SideAnchoredControlCount(Side: TAnchorKind): integer; function HasAnchoredControls: boolean; + function GetSpliterBoundsWithUnminimizedDockSites:TRect; procedure SaveLayout(LayoutNode: TAnchorDockLayoutTreeNode); function HasOnlyOneSibling(Side: TAnchorKind; MinPos, MaxPos: integer): TControl; property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; @@ -241,6 +291,14 @@ end; TAnchorDockPageControlClass = class of TAnchorDockPageControl; + + TAnchorDockOverlappingForm = class(TCustomForm) + public + AnchorDockHostSite:TAnchorDockHostSite; + Panel:TPanel; + constructor CreateNew(AOwner: TComponent; Num: Integer = 0); override; + end; + { TAnchorDockHostSite This form is the dockhostsite for all controls. When docked together they build a tree structure with the docked controls @@ -262,7 +320,10 @@ FPages: TAnchorDockPageControl; FSiteType: TAnchorDockHostSiteType; FBoundSplitter: TAnchorDockSplitter; - fUpdateLayout: integer; + fUpdateLayout: Integer; + FMinimized: Boolean; + fMinimization: Boolean; + FMinimizedControl: TControl; procedure SetHeaderSide(const AValue: TAnchorKind); protected procedure DoEnter; override; @@ -319,6 +380,10 @@ destructor Destroy; override; function CloseQuery: boolean; override; function CloseSite: boolean; virtual; + procedure MinimizeSite; virtual; + procedure AsyncMinimizeSite(Data: PtrInt); + procedure ShowMinimizedControl; + procedure HideMinimizedControl; procedure RemoveControl(AControl: TControl); override; procedure InsertControl(AControl: TControl; Index: integer); override; procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect; @@ -329,6 +394,7 @@ procedure UpdateDockCaption(Exclude: TControl = nil); override; procedure UpdateHeaderAlign; procedure UpdateHeaderShowing; + function CanBeMinimized(out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; procedure BeginUpdateLayout; procedure EndUpdateLayout; function UpdatingLayout: boolean; @@ -337,6 +403,7 @@ procedure SaveLayout(LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode); property DockRestoreBounds: TRect read FDockRestoreBounds write FDockRestoreBounds; + function GetDockEdge(const MousePos: TPoint): TAlign; override; property HeaderSide: TAnchorKind read FHeaderSide write SetHeaderSide; property Header: TAnchorDockHeader read FHeader; @@ -431,6 +498,7 @@ FShowHeader: boolean; FShowHeaderCaption: boolean; FSplitterWidth: integer; + FDockSitecCanBeMinimized: boolean; procedure SetAllowDragging(AValue: boolean); procedure SetDockOutsideMargin(AValue: integer); procedure SetDockParentMargin(AValue: integer); @@ -448,6 +516,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitecCanBeMinimized(AValue: boolean); public property DragTreshold: integer read FDragTreshold write SetDragTreshold; property DockOutsideMargin: integer read FDockOutsideMargin write SetDockOutsideMargin; @@ -466,6 +535,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused; + property DockSitesCanBeMinimized: boolean read FDockSitecCanBeMinimized write SetDockSitecCanBeMinimized; procedure IncreaseChangeStamp; inline; property ChangeStamp: integer read FChangeStamp; procedure LoadFromConfig(Config: TConfigStorage); overload; @@ -502,6 +572,7 @@ FHeaderFlatten: boolean; FHeaderFilled: boolean; FHeaderHighlightFocused: boolean; + FDockSitesCanBeMinimized: boolean; FIdleConnected: Boolean; FManagerClass: TAnchorDockManagerClass; FOnCreateControl: TADCreateControlEvent; @@ -531,6 +602,7 @@ fPopupMenu: TPopupMenu; // Used by RestoreLayout: WorkArea, SrcWorkArea: TRect; + FOverlappingForm:TAnchorDockOverlappingForm; function GetControls(Index: integer): TControl; function GetLocalizedHeaderHint: string; @@ -541,6 +613,9 @@ function GetNodeSite(Node: TAnchorDockLayoutTreeNode): TAnchorDockHostSite; procedure MapTreeToControls(Tree: TAnchorDockLayoutTree); function RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; + procedure SetMinimizedState(Tree: TAnchorDockLayoutTree); + procedure UpdateHeaders; + procedure SetnodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); procedure EnableAllAutoSizing; procedure ClearLayoutProperties(AControl: TControl; NewAlign: TAlign = alClient); procedure PopupMenuPopup(Sender: TObject); @@ -561,6 +636,7 @@ procedure SetHeaderFlatten(AValue: boolean); procedure SetHeaderFilled(AValue: boolean); procedure SetHeaderHighlightFocused(AValue: boolean); + procedure SetDockSitesCanBeMinimized(AValue: boolean); procedure SetShowMenuItemShowHeader(AValue: boolean); procedure SetupSite(Site: TWinControl; ANode: TAnchorDockLayoutTreeNode; @@ -584,8 +660,12 @@ procedure SetHideHeaderCaptionFloatingControl(const AValue: boolean); procedure SetSplitterWidth(const AValue: integer); procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure StartHideOverlappingTimer; + procedure StopHideOverlappingTimer; procedure AsyncSimplify({%H-}Data: PtrInt); public + procedure ShowOverlappingForm; + procedure HideOverlappingForm(Sender: TObject); constructor Create(AOwner: TComponent); override; destructor Destroy; override; function FullRestoreLayout(Tree: TAnchorDockLayoutTree; Scale: Boolean): Boolean; @@ -680,6 +760,7 @@ property HeaderFlatten: boolean read FHeaderFlatten write SetHeaderFlatten default true; property HeaderFilled: boolean read FHeaderFilled write SetHeaderFilled default true; property HeaderHighlightFocused: boolean read FHeaderHighlightFocused write SetHeaderHighlightFocused default false; + property DockSitesCanBeMinimized: boolean read FDockSitesCanBeMinimized write SetDockSitesCanBeMinimized default false; property SplitterWidth: integer read FSplitterWidth write SetSplitterWidth default 4; property ScaleOnResize: boolean read FScaleOnResize write SetScaleOnResize default true; // scale children when resizing a site @@ -698,8 +779,14 @@ var DockMaster: TAnchorDockMaster = nil; + DockTimer: TTimer = nil; + PreferredButtonWidth:integer=-1; + PreferredButtonHeight:integer=-1; + + const + HardcodedButtonSize:integer=13; ADHeaderStyleNames: array[TADHeaderStyle] of string = ( 'Frame3D', 'Line', @@ -970,6 +1057,27 @@ end; end; +function CountAndReturnOnlyOneMinimizedAnchoredControls(Control: TControl; Side: TAnchorKind): TAnchorDockHostSite; +var + i,Counter: Integer; + Neighbour: TControl; +begin + Counter:=0; + for i:=0 to Control.AnchoredControlCount-1 do begin + Neighbour:=Control.AnchoredControls[i]; + if Neighbour.Visible then + if Neighbour is TAnchorDockHostSite then + if (OppositeAnchor[Side] in Neighbour.Anchors) + and (Neighbour.AnchorSide[OppositeAnchor[Side]].Control=Control) then begin + inc(Counter); + result:=TAnchorDockHostSite(Neighbour); + end; + end; + if (Counter=1)and(result is TAnchorDockHostSite)and((result as TAnchorDockHostSite).FMinimized) then + else + result:=Nil; +end; + function NeighbourCanBeShrinked(EnlargeControl, Neighbour: TControl; Side: TAnchorKind): boolean; { returns true if Neighbour can be shrinked on the opposite side of Side @@ -1361,6 +1469,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockSettings.SetDockSitecCanBeMinimized(AValue: boolean); +begin + if FDockSitecCanBeMinimized=AValue then Exit; + FDockSitecCanBeMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockSettings.Assign(Source: TAnchorDockSettings); begin FAllowDragging := Source.FAllowDragging; @@ -1381,6 +1496,7 @@ FShowHeaderCaption := Source.FShowHeaderCaption; FSplitterWidth := Source.FSplitterWidth; FHeaderHighlightFocused:=Source.FHeaderHighlightFocused; + FDockSitecCanBeMinimized:=Source.FDockSitecCanBeMinimized; end; procedure TAnchorDockSettings.IncreaseChangeStamp; @@ -1407,6 +1523,7 @@ HeaderFlatten:=Config.GetValue('HeaderFlatten',true); HeaderFilled:=Config.GetValue('HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue('HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue('DockSitecCanBeMinimized',False); Config.UndoAppendBasePath; end; @@ -1429,6 +1546,7 @@ Config.SetDeleteValue(Path+'HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue(Path+'HeaderFilled',HeaderFilled,true); Config.SetDeleteValue(Path+'HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue(Path+'DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); end; procedure TAnchorDockSettings.SaveToConfig(Config: TConfigStorage); @@ -1450,6 +1568,7 @@ Config.SetDeleteValue('HeaderFlatten',HeaderFlatten,true); Config.SetDeleteValue('HeaderFilled',HeaderFilled,true); Config.SetDeleteValue('HeaderHighlightFocused',HeaderHighlightFocused,False); + Config.SetDeleteValue('DockSitecCanBeMinimized',DockSitesCanBeMinimized,False); Config.UndoAppendBasePath; end; @@ -1472,6 +1591,7 @@ and (HeaderFlatten=Settings.HeaderFlatten) and (HeaderFilled=Settings.HeaderFilled) and (HeaderHighlightFocused=Settings.HeaderHighlightFocused) + and (DockSitesCanBeMinimized=Settings.DockSitesCanBeMinimized) ; end; @@ -1494,6 +1614,7 @@ HeaderFlatten:=Config.GetValue(Path+'HeaderFlatten',true); HeaderFilled:=Config.GetValue(Path+'HeaderFilled',true); HeaderHighlightFocused:=Config.GetValue(Path+'HeaderHighlightFocused',False); + DockSitesCanBeMinimized:=Config.GetValue(Path+'DockSitecCanBeMinimized',False); end; { TAnchorDockMaster } @@ -2021,6 +2142,8 @@ aHostSite:=TAnchorDockHostSite(Site); aHostSite.Header.HeaderPosition:=ANode.HeaderPosition; aHostSite.DockRestoreBounds:=NewBounds; + //aHostSite.FMinimized:=ANode.Minimized; + //we update aHostSite.FMinimized in TAnchorDockMaster.SetMinimizedState if (ANode.NodeType<>adltnPages) and (aHostSite.Pages<>nil) then aHostSite.FreePages; end; @@ -2040,6 +2163,25 @@ fTreeNameToDocker[Node.Name]:=Result; end; +procedure TAnchorDockMaster.SetNodeMinimizedState(ANode: TAnchorDockLayoutTreeNode); +var + HostSite:TAnchorDockHostSite; + i:integer; +begin + HostSite:=GetNodeSite(ANode); + if Assigned(HostSite) then + if HostSite.FMinimized<>ANode.Minimized then + Application.QueueAsyncCall(@HostSite.AsyncMinimizeSite,0); + //HostSite.MinimizeSite; + for i:=0 to ANode.Count-1 do + SetnodeMinimizedState(ANode.Nodes[i]); +end; + +procedure TAnchorDockMaster.SetMinimizedState(Tree: TAnchorDockLayoutTree); +begin + SetnodeMinimizedState(Tree.Root); +end; + function TAnchorDockMaster.RestoreLayout(Tree: TAnchorDockLayoutTree; Scale: boolean): boolean; @@ -2193,7 +2335,7 @@ try SetupSite(Site,ANode,AParent); Site.FSiteType:=adhstPages; - Site.Header.Parent:=nil; + //Site.Header.Parent:=nil; if Site.Pages=nil then Site.CreatePages; for i:=0 to ANode.Count-1 do begin @@ -2358,7 +2500,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -2368,6 +2510,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -2422,11 +2565,54 @@ OptionsChanged; end; +procedure TAnchorDockMaster.StartHideOverlappingTimer; +begin + if not DockTimer.Enabled then begin + DockTimer.Interval:=HideOverlappingFormByMouseLoseTime; + DockTimer.OnTimer:=@HideOverlappingForm; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockMaster.StopHideOverlappingTimer; +begin + DockTimer.Enabled:=False; + DockTimer.Interval:=0; + DockTimer.OnTimer:=nil; +end; + +function IsParentControl(aParent, aControl: TControl): boolean; +begin + while (aControl <> nil) and (aControl.Parent <> nil) do + begin + if (aControl=aParent) then + exit(true); + aControl := aControl.Parent; + end; + result:=aControl=aParent; +end; + + procedure TAnchorDockMaster.OnIdle(Sender: TObject; var Done: Boolean); +var + MousePos: TPoint; + Bounds:Trect; begin if Done then ; - IdleConnected:=false; Restoring:=false; + if FOverlappingForm=nil then + IdleConnected:=false + else begin + GetCursorPos(MousePos); + Bounds.TopLeft:=FOverlappingForm.ClientToScreen(point(0,0)); + Bounds.BottomRight:=FOverlappingForm.ClientToScreen(point(FOverlappingForm.Width,FOverlappingForm.Height)); + if not IsParentControl(FOverlappingForm, GetCaptureControl) then begin + if not PtInRect(Bounds,MousePos) then + StartHideOverlappingTimer + else + StopHideOverlappingTimer; + end; + end; end; procedure TAnchorDockMaster.AsyncSimplify(Data: PtrInt); @@ -2514,6 +2700,18 @@ InvalidateHeaders; end; +procedure TAnchorDockMaster.SetDockSitesCanBeMinimized(AValue: boolean); +var + i:integer; + Site: TAnchorDockHostSite; +begin + if FDockSitesCanBeMinimized=AValue then Exit; + FDockSitesCanBeMinimized:=AValue; + UpdateHeaders; + InvalidateHeaders; + EnableAllAutoSizing; + OptionsChanged; +end; procedure TAnchorDockMaster.SetScaleOnResize(AValue: boolean); begin if FScaleOnResize=AValue then Exit; @@ -2598,6 +2796,9 @@ if (Site.Header<>nil) then begin DisableControlAutoSizing(Site); Site.UpdateHeaderShowing; + if Site.fminimized then + if not AValue then + site.MinimizeSite; end; end; EnableAllAutoSizing; @@ -2668,6 +2869,20 @@ EnableAllAutoSizing; end; +procedure TAnchorDockMaster.ShowOverlappingForm; +begin + FOverlappingForm.Show; + IdleConnected:=true; +end; + +procedure TAnchorDockMaster.HideOverlappingForm(Sender: TObject); +begin + StopHideOverlappingTimer; + FOverlappingForm.Hide; + FOverlappingForm.AnchorDockHostSite.HideMinimizedControl; + IdleConnected:=false; +end; + constructor TAnchorDockMaster.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -2698,14 +2913,14 @@ FPageClass:=TAnchorDockPage; FRestoreLayouts:=TAnchorDockRestoreLayouts.Create; FHeaderHighlightFocused:=false; + FDockSitesCanBeMinimized:=false; + FOverlappingForm:=nil; end; destructor TAnchorDockMaster.Destroy; var AControl: TControl; - {$IFDEF VerboseAnchorDocking} - i: Integer; - {$ENDIF} + i, j: Integer; begin QueueSimplify:=false; FreeAndNil(FRestoreLayouts); @@ -2727,6 +2942,12 @@ debugln(['TAnchorDockMaster.Destroy ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); end; {$ENDIF} + for i:=0 to ComponentCount-1 do begin + for j:=0 to ComponentCount-1 do begin + if i<>j then + TControl(Components[i]).RemoveAllHandlersOfObject(TControl(Components[j])); + end; + end; inherited Destroy; end; @@ -2914,6 +3135,7 @@ raise Exception.Create('TAnchorDockMaster.MakeDockable '+Format( adrsNotSupportedHasParent, [DbgSName(AControl), DbgSName(AControl)])); end; + site.UpdateHeaderShowing; if (Site<>nil) and Show then MakeVisible(Site,BringToFront); finally @@ -3018,7 +3240,8 @@ i:=Screen.CustomFormCount-1; while i>=0 do begin AForm:=GetParentForm(Screen.CustomForms[i]); - AForm.Hide; + if Assigned(AForm)then + AForm.Hide; i:=Min(i,Screen.CustomFormCount)-1; end; @@ -3062,8 +3285,11 @@ end; end; -function GetParentFormOrDockPanel(Control: TControl): TCustomForm; +function GetParentFormOrDockPanel(Control: TControl; TopForm:Boolean=true): TCustomForm; +var + oldControl: TControl; begin + oldControl:=Control; while (Control <> nil) and (Control.Parent <> nil) do begin if (Control is TAnchorDockPanel) then @@ -3076,6 +3302,18 @@ Result := TCustomForm(Control) else Result := nil; + if not TopForm then begin + if Control is TAnchorDockPanel then + exit; + Control:=oldControl; + while (Control <> nil) and (Control.Parent <> nil) do + begin + Control := Control.Parent; + if (Control is TCustomForm) then + Break; + end; + Result := TCustomForm(Control); + end; end; procedure TAnchorDockMaster.SaveMainLayoutToTree(LayoutTree: TAnchorDockLayoutTree); @@ -3088,12 +3326,12 @@ AFormOrDockPanel: TWinControl; VisibleControls: TStringList; - procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean); + procedure SaveFormOrDockPanel(theFormOrDockPanel: TWinControl; SaveChildren: boolean; AMinimized:boolean); begin // custom dock site LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel); + LayoutNode.Assign(theFormOrDockPanel,theFormOrDockPanel is TAnchorDockPanel,AMinimized); // can have one normal dock site if SaveChildren then begin @@ -3124,7 +3362,7 @@ debugln(['TAnchorDockMaster.SaveMainLayoutToTree AForm=',DbgSName(AFormOrDockPanel)]); DebugWriteChildAnchors(AFormOrDockPanel,true,true); if AFormOrDockPanel is TAnchorDockPanel then begin - SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),{false}true); + SaveFormOrDockPanel(GetParentFormOrDockPanel(AFormOrDockPanel),true,false); //LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); //TAnchorDockPanel(AFormOrDockPanel).SaveLayout(LayoutTree,LayoutNode); end else if AFormOrDockPanel is TAnchorDockHostSite then begin @@ -3132,12 +3370,12 @@ LayoutNode:=LayoutTree.NewNode(LayoutTree.Root); Site.SaveLayout(LayoutTree,LayoutNode); end else if IsCustomSite(AFormOrDockPanel) then begin - SaveFormOrDockPanel(AFormOrDockPanel,true); + SaveFormOrDockPanel(AFormOrDockPanel,true,false); end else raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - LayoutTree.Root.Simplify(VisibleControls); + LayoutTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; @@ -3157,7 +3395,7 @@ (AControl as TAnchorDockPanel).SaveLayout(LayoutTree,LayoutTree.Root); end else if IsCustomSite(AControl) then begin LayoutTree.Root.NodeType:=adltnCustomSite; - LayoutTree.Root.Assign(AControl); + LayoutTree.Root.Assign(AControl,false,false); // can have one normal dock site Site:=TAnchorDockManager(AControl.DockManager).GetChildSite; if Site<>nil then begin @@ -3252,7 +3490,7 @@ debugln(ControlNames.Text); {$ENDIF} // if some forms/controls could not be created the layout needs to be adapted - Tree.Root.Simplify(ControlNames); + Tree.Root.Simplify(ControlNames,false); // reuse existing sites to reduce flickering MapTreeToControls(Tree); @@ -3262,6 +3500,7 @@ // create sites, move controls RestoreLayout(Tree,Scale); + SetMinimizedState(Tree); finally EndUpdate; end; @@ -3323,6 +3562,7 @@ HeaderFlatten := Settings.HeaderFlatten; HeaderFilled := Settings.HeaderFilled; HeaderHighlightFocused := Settings.HeaderHighlightFocused; + DockSitesCanBeMinimized := Settings.DockSitesCanBeMinimized; end; procedure TAnchorDockMaster.SaveSettings(Settings: TAnchorDockSettings); @@ -3343,6 +3583,7 @@ Settings.HeaderFlatten:=HeaderFlatten; Settings.HeaderFilled:=HeaderFilled; Settings.HeaderHighlightFocused:=HeaderHighlightFocused; + Settings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized; end; function TAnchorDockMaster.SettingsAreEqual(Settings: TAnchorDockSettings @@ -3436,8 +3677,11 @@ if fUpdateCount<=0 then RaiseGDBException(''); dec(fUpdateCount); - if fUpdateCount=0 then + if fUpdateCount=0 then begin SimplifyPendingLayouts; + UpdateHeaders; + InvalidateHeaders; + end; end; function TAnchorDockMaster.IsReleasing(AControl: TControl): Boolean; @@ -3664,6 +3908,24 @@ LUIncreaseChangeStamp64(FOptionsChangeStamp); end; +procedure TAnchorDockMaster.UpdateHeaders; +var + i: Integer; + AControl: TControl; + AHostSite: TAnchorDockHostSite; +begin + for i:=0 to ControlCount-1 do begin + AControl:=Controls[i]; + if not DockedControlIsVisible(AControl) then continue; + while Assigned(AControl) do + begin + if AControl is TAnchorDockHostSite then + TAnchorDockHostSite(AControl).UpdateHeaderShowing; + AControl:=AControl.parent; + end; + end; +end; + { TAnchorDockHostSite } procedure TAnchorDockHostSite.SetHeaderSide(const AValue: TAnchorKind); @@ -3680,6 +3942,7 @@ AControl:=TControl(Sender); if not (csDestroying in ComponentState) then begin if (not AControl.Visible) + and (not FMinimized) and (not ((AControl is TAnchorDockHeader) or (AControl is TAnchorDockSplitter) or (AControl is TAnchorDockHostSite))) @@ -4119,6 +4382,8 @@ end; procedure TAnchorDockHostSite.FreePages; +var + i:Integer; begin FreeAndNil(FPages); end; @@ -4233,6 +4498,14 @@ akRight: NewBounds.Right:=AControl.Left+AControl.Width; akBottom: NewBounds.Bottom:=AControl.Top+AControl.Height; end; + if (sibling is TAnchorDockHostSite) then + if (sibling as TAnchorDockHostSite).FMinimized then begin + (sibling as TAnchorDockHostSite).FMinimized:=false; + (sibling as TAnchorDockHostSite).FMinimizedControl.Parent:=(sibling as TAnchorDockHostSite); + (sibling as TAnchorDockHostSite).FMinimizedControl.Visible:=True; + (sibling as TAnchorDockHostSite).FMinimizedControl:=nil; + (sibling as TAnchorDockHostSite).UpdateHeaderAlign; + end; Sibling.BoundsRect:=NewBounds; end; end; @@ -4306,6 +4579,13 @@ FSiteType:=adhstOneControl; OnlySiteLeft.Align:=alClient; Header.Parent:=Self; + if OnlySiteLeft.FMinimized then begin + OnlySiteLeft.FMinimized:=false; + OnlySiteLeft.FMinimizedControl.Parent:=OnlySiteLeft; + OnlySiteLeft.FMinimizedControl.Visible:=True; + OnlySiteLeft.FMinimizedControl:=nil; + UpdateHeaderAlign; + end; UpdateHeaderAlign; //debugln(['TAnchorDockHostSite.RemoveControlFromLayout.ConvertToOneControlType AFTER CONVERT "',Caption,'" to onecontrol OnlySiteLeft="',OnlySiteLeft.Caption,'"']); @@ -4465,7 +4745,7 @@ debugln(['TAnchorDockHostSite.Simplify ',DbgSName(Self),' ',DbgSName(AControl)]); if AControl is TAnchorDockHostSite then SimplifyOneControl - else if (AControl=nil) or (csDestroying in AControl.ComponentState) then + else if ((AControl=nil) or (csDestroying in AControl.ComponentState)) then DockMaster.NeedFree(Self); end; end; @@ -4577,7 +4857,8 @@ Result:=Controls[i]; if Result.Owner<>Self then exit; end; - Result:=nil; + result:=FMinimizedControl; + //Result:=nil; end; function TAnchorDockHostSite.GetSiteCount: integer; @@ -5165,6 +5446,125 @@ Result:=Check(Self); end; +function CheckOposite(Side:TAnchorKind;AControl: TControl;out Splitter: TAnchorDockSplitter; out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=GetDockSplitter(AControl,Side,Splitter); + if result then begin + if CountAnchoredControls(Splitter,OppositeAnchor[Side])=1 then begin + SplitterAnchorKind:=Side; + exit; + end; + end; + result:=false +end; + +function FindNearestSpliter(AControl: TControl;out Splitter: TAnchorDockSplitter;out SplitterAnchorKind:TAnchorKind):boolean; +begin + result:=CheckOposite(akTop,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akRight,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akBottom,AControl,Splitter,SplitterAnchorKind); + if result then exit; + result:=CheckOposite(akLeft,AControl,Splitter,SplitterAnchorKind); +end; + +function TAnchorDockHostSite.CanBeMinimized(out Splitter: TAnchorDockSplitter; + out SplitterAnchorKind:TAnchorKind):boolean; +var + //AControl: TControl; + OpositeDockHostSite:TAnchorDockHostSite; + OpositeSplitter: TAnchorDockSplitter; +begin + result:=false; + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + OpositeDockHostSite:=CountAndReturnOnlyOneMinimizedAnchoredControls(Splitter,SplitterAnchorKind); + if (Splitter.Enabled and (OpositeDockHostSite=nil)) then begin + result:=true; + if CheckOposite(OppositeAnchorKind[SplitterAnchorKind],self,OpositeSplitter,SplitterAnchorKind) then + if Assigned(OpositeSplitter) then + if not OpositeSplitter.Enabled then + result:=false; + end; + end; +end; + +procedure TAnchorDockHostSite.MinimizeSite; +begin + //Application.QueueAsyncCall(@AsyncMinimizeSite,0); + AsyncMinimizeSite(0); +end; + +procedure TAnchorDockHostSite.AsyncMinimizeSite(Data: PtrInt); +var + AControl: TControl; + //OpositeDockHostSite:TAnchorDockHostSite; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + //SpliterPercentPosition:Single; +begin + fMinimization:=true; + debugln(['TAnchorDockHostSite.MinimizeSite ',DbgSName(Self),' SiteType=',dbgs(SiteType)]); + if FMinimized then + AControl:=FMinimizedControl + else + AControl:=GetOneControl; + if CanBeMinimized(Splitter,SplitterAnchorKind) or FMinimized then begin + FMinimized:=not FMinimized; + if FMinimized then begin + FMinimizedControl:=AControl; + AControl.Visible:=False; + AControl.Parent:=nil; + //self.DoDockOver(); OnDockOver; + end else begin + AControl.Parent:=self; + AControl.Visible:=True; + FMinimizedControl:=nil; + end; + Splitter.Enabled:=AControl.Visible; + UpdateHeaderAlign; + dockmaster.UpdateHeaders; + dockmaster.InvalidateHeaders; + Splitter.SetBoundsPercentually; + end; + fMinimization:=false; +end; + +procedure TAnchorDockHostSite.ShowMinimizedControl; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + SpliterRect,OverlappingFormRect:TRect; +begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + SpliterRect:=Splitter.GetSpliterBoundsWithUnminimizedDockSites; + OverlappingFormRect:=BoundsRect; + case SplitterAnchorKind of + akTop:OverlappingFormRect.Top:=SpliterRect.Bottom; + akLeft:OverlappingFormRect.Left:=SpliterRect.Right; + akRight:OverlappingFormRect.Right:=SpliterRect.Left; + akBottom:OverlappingFormRect.Bottom:=SpliterRect.Top; + end; + DockMaster.FOverlappingForm:=TAnchorDockOverlappingForm.CreateNew(self); + DockMaster.FOverlappingForm.BoundsRect:=OverlappingFormRect; + DockMaster.FOverlappingForm.Parent:=GetParentFormOrDockPanel(self,false); + DockMaster.FOverlappingForm.AnchorDockHostSite:=self; + header.Parent:=DockMaster.FOverlappingForm; + FMinimizedControl.Parent:=DockMaster.FOverlappingForm.Panel; + FMinimizedControl.Show; + DockMaster.ShowOverlappingForm; + end; +end; + +procedure TAnchorDockHostSite.HideMinimizedControl; +begin + FMinimizedControl.Hide; + header.Parent:=self; + header.UpdateHeaderControls; + FMinimizedControl.Parent:=nil; + FreeAndNil(DockMaster.FOverlappingForm); +end; + function TAnchorDockHostSite.CloseSite: boolean; var AControl: TControl; @@ -5281,21 +5681,24 @@ begin if csDestroying in ComponentState then exit; NewCaption:=''; - for i:=0 to ControlCount-1 do begin - Child:=Controls[i]; - if Child=Exclude then continue; - if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) - or (Child is TAnchorDockPageControl) then begin - if NewCaption<>'' then - NewCaption:=NewCaption+','; - NewCaption:=NewCaption+Child.Caption; + if FMinimized then + NewCaption:=FMinimizedControl.Caption + else + for i:=0 to ControlCount-1 do begin + Child:=Controls[i]; + if Child=Exclude then continue; + if (Child.HostDockSite=Self) or (Child is TAnchorDockHostSite) + or (Child is TAnchorDockPageControl) then begin + if NewCaption<>'' then + NewCaption:=NewCaption+','; + NewCaption:=NewCaption+Child.Caption; + end; end; - end; OldCaption:=Caption; Caption:=NewCaption; //debugln(['TAnchorDockHostSite.UpdateDockCaption Caption="',Caption,'" NewCaption="',NewCaption,'" HasParent=',Parent<>nil,' ',DbgSName(Header)]); - if ((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) - or (not DockMaster.ShowHeaderCaption) then + if {((Parent=nil) and DockMaster.HideHeaderCaptionFloatingControl) + or (not DockMaster.ShowHeaderCaption)}false then Header.Caption:='' else Header.Caption:=Caption; @@ -5306,9 +5709,8 @@ if Parent is TAnchorDockPage then TAnchorDockPage(Parent).UpdateDockCaption; end; - // do not show close button for mainform - Header.CloseButton.Visible:=not IsParentOf(Application.MainForm); + Header.CloseButton.Visible:=(not IsParentOf(Application.MainForm)); end; procedure TAnchorDockHostSite.GetSiteInfo(Client: TControl; @@ -5339,7 +5741,8 @@ end; CanDock:=(Client is TAnchorDockHostSite) - and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client); + and not DockMaster.AutoFreedIfControlIsRemoved(Self,Client) + and not FMinimized; //debugln(['TAnchorDockHostSite.GetSiteInfo ',DbgSName(Self),' ',dbgs(BoundsRect),' ',Caption,' CanDock=',CanDock,' PtIn=',PtInRect(InfluenceRect,MousePos)]); if Assigned(OnGetSiteInfo) then @@ -5362,9 +5765,20 @@ end; procedure TAnchorDockHostSite.UpdateHeaderAlign; +var + NeededHeaderPosition:TADLHeaderPosition; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - case Header.HeaderPosition of + if FMinimized then begin + if FindNearestSpliter(self,Splitter,SplitterAnchorKind) then begin + NeededHeaderPosition:=OppositeAnchorKind2TADLHeaderPosition[SplitterAnchorKind]; + end else + NeededHeaderPosition:=Header.HeaderPosition; + end else + NeededHeaderPosition:=Header.HeaderPosition; + case NeededHeaderPosition of adlhpAuto: if Header.Align in [alLeft,alRight] then begin if (ClientHeight>0) @@ -5388,10 +5802,16 @@ end; procedure TAnchorDockHostSite.UpdateHeaderShowing; +var + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; begin if Header=nil then exit; - if HeaderNeedsShowing then - Header.Parent:=Self + if HeaderNeedsShowing then begin + Header.Parent:=Self; + Header.MinimizeButton.Visible:=(DockMaster.DockSitesCanBeMinimized and CanBeMinimized(Splitter,SplitterAnchorKind))or FMinimized; + Header.MinimizeButton.Parent:=Header; + end else Header.Parent:=nil; end; @@ -5415,6 +5835,31 @@ Result:=(fUpdateLayout>0) or (csDestroying in ComponentState); end; +function AcceptAlign(Site:TAnchorDockHostSite; AlignCandidate:TAlign):TAlign; +var + i:integer; + Splitter: TAnchorDockSplitter; + SplitterAnchorKind:TAnchorKind; + MinimizedSiteAlign:TAlign; +begin + for i:=0 to Site.ControlCount-1 do + if Site.Controls[i] is TAnchorDockHostSite then + if (Site.Controls[i] as TAnchorDockHostSite).FMinimized then begin + if FindNearestSpliter(Site.Controls[i] as TAnchorDockHostSite,Splitter,SplitterAnchorKind) then begin + MinimizedSiteAlign:=OppositeAnchorKind2Align[SplitterAnchorKind]; + if AlignCandidate=MinimizedSiteAlign then + exit(alNone); + end + end; + result:=AlignCandidate; +end; + +function TAnchorDockHostSite.GetDockEdge(const MousePos: TPoint): TAlign; +begin + result:=inherited; + result:=AcceptAlign(self,result); +end; + procedure TAnchorDockHostSite.SaveLayout( LayoutTree: TAnchorDockLayoutTree; LayoutNode: TAnchorDockLayoutTreeNode); var @@ -5432,7 +5877,7 @@ if (SiteType=adhstOneControl) and (OneControl<>nil) and (not (OneControl is TAnchorDockHostSite)) then begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.Name:=OneControl.Name; LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if (SiteType in [adhstLayout,adhstOneControl]) then begin @@ -5450,7 +5895,7 @@ Splitter.SaveLayout(ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else if SiteType=adhstPages then begin LayoutNode.NodeType:=adltnPages; @@ -5461,7 +5906,7 @@ Site.SaveLayout(LayoutTree,ChildNode); end; end; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,FMinimized); LayoutNode.HeaderPosition:=Header.HeaderPosition; end else LayoutNode.NodeType:=adltnNone; @@ -5476,6 +5921,9 @@ constructor TAnchorDockHostSite.CreateNew(AOwner: TComponent; Num: Integer); begin inherited CreateNew(AOwner,Num); + FMinimized:=false; + fMinimization:=false; + FMinimizedControl:=Nil; Visible:=false; FHeaderSide:=akTop; FHeader:=DockMaster.HeaderClass.Create(Self); @@ -5490,13 +5938,13 @@ end; destructor TAnchorDockHostSite.Destroy; -//var i: Integer; +var i: Integer; begin - //debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); - {for i:=0 to ComponentCount-1 do + debugln(['TAnchorDockHostSite.Destroy ',DbgSName(Self),' Caption="',Caption,'" Self=',dbgs(Pointer(Self)),' ComponentCount=',ComponentCount,' ControlCount=',ControlCount]); + for i:=0 to ComponentCount-1 do debugln(['TAnchorDockHostSite.Destroy Component ',i,'/',ComponentCount,' ',DbgSName(Components[i])]); for i:=0 to ControlCount-1 do - debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]);} + debugln(['TAnchorDockHostSite.Destroy Control ',i,'/',ControlCount,' ',DbgSName(Controls[i])]); FreePages; inherited Destroy; end; @@ -5562,13 +6010,34 @@ end; procedure TAnchorDockHeader.CloseButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; begin - if Parent is TAnchorDockHostSite then begin - DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(Parent),true); - TAnchorDockHostSite(Parent).CloseSite; + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; end; + if HeaderParent is TAnchorDockHostSite then begin + DockMaster.RestoreLayouts.Add(DockMaster.CreateRestoreLayout(HeaderParent),true); + HeaderParent.CloseSite; + end; end; +procedure TAnchorDockHeader.MinimizeButtonClick(Sender: TObject); +var + HeaderParent:TAnchorDockHostSite; +begin + TWinControl(HeaderParent):=Parent; + if HeaderParent=TWinControl(DockMaster.FOverlappingForm) then begin + HeaderParent:=DockMaster.FOverlappingForm.AnchorDockHostSite; + HeaderParent.HideMinimizedControl; + end; + if HeaderParent is TAnchorDockHostSite then begin + HeaderParent.MinimizeSite; + end; +end; + procedure TAnchorDockHeader.HeaderPositionItemClick(Sender: TObject); var Item: TMenuItem; @@ -5635,11 +6104,18 @@ if CloseButton.IsControlVisible and (CloseButton.Parent=Self) then begin if Align in [alLeft,alRight] then - r.Top:=CloseButton.Top+CloseButton.Height+1 + r.Top:=CloseButton.Top+CloseButton.Height+ButtonBorderSpacingAround else - r.Right:=CloseButton.Left-1; + r.Right:=CloseButton.Left-ButtonBorderSpacingAround; end; + if MinimizeButton.IsControlVisible and (MinimizeButton.Parent=Self) then begin + if Align in [alLeft,alRight] then + r.Top:=MinimizeButton.Top+MinimizeButton.Height+ButtonBorderSpacingAround + else + r.Right:=MinimizeButton.Left-ButtonBorderSpacingAround; + end; + // caption if Caption<>'' then begin if fFocused and DockMaster.HeaderHighlightFocused and NeedHighlightText then @@ -5728,26 +6204,127 @@ end else begin PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end else begin + NeededHeight:=CloseButton.Height; + if Align in [alLeft,alRight] then begin + PreferredWidth:=Max(NeededHeight,PreferredWidth); + end else begin + PreferredHeight:=Max(NeededHeight,PreferredHeight); end; + end; end; procedure TAnchorDockHeader.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var + SiteMinimized:Boolean; begin inherited MouseDown(Button, Shift, X, Y); - if (Button=mbLeft) and DockMaster.AllowDragging then - DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + SiteMinimized:=False; + fUseTimer:=false; + StopMouseNoMoveTimer; + if Parent is TAnchorDockHostSite then + SiteMinimized:=(Parent as TAnchorDockHostSite).FMinimized; + if SiteMinimized then begin + DoMouseNoMoveTimer(nil); + end else + begin + if parent<>nil then + if DockMaster.FOverlappingForm<>nil then + //if parent=DockMaster.FOverlappingForm.Panel then + DockMaster.HideOverlappingForm(nil); + if (Button=mbLeft) and (DockMaster.AllowDragging) and (DockMaster.FOverlappingForm=nil) then + DragManager.DragStart(Parent,false,DockMaster.DragTreshold); + end; end; +procedure TAnchorDockHeader.MouseMove(Shift: TShiftState; X,Y: Integer); +begin + inherited MouseMove(Shift, X, Y); + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + if DockMaster.FOverlappingForm=nil then + if FMouseTimeStartX=EmptyMouseTimeStartX then + StartMouseNoMoveTimer(X, Y) + else begin + if (abs(FMouseTimeStartX-X)>MouseNoMoveDelta)or(abs(FMouseTimeStartY-Y)>MouseNoMoveDelta)then + StopMouseNoMoveTimer; + end; + if (parent is TAnchorDockHostSite)and(DockMaster.FOverlappingForm=nil)then + fUseTimer:=true; +end; + +procedure TAnchorDockHeader.MouseLeave; +begin + inherited; + StopMouseNoMoveTimer; +end; + +procedure TAnchorDockHeader.StartMouseNoMoveTimer(X, Y: Integer); +begin + if fUseTimer then begin + if DockTimer.Enabled then DockTimer.Enabled:=false; + DockTimer.Interval:=MouseNoMoveTime; + DockTimer.OnTimer:=@DoMouseNoMoveTimer; + DockTimer.Enabled:=true; + end; +end; + +procedure TAnchorDockHeader.StopMouseNoMoveTimer; +begin + FMouseTimeStartX:=EmptyMouseTimeStartX; + DockTimer.OnTimer:=nil; + DockTimer.Enabled:=false; +end; + +procedure TAnchorDockHeader.DoMouseNoMoveTimer(Sender: TObject); +begin + StopMouseNoMoveTimer; + //if fUseTimer then + if parent<>nil then + if parent is TAnchorDockHostSite then + if (parent as TAnchorDockHostSite).FMinimized then + (parent as TAnchorDockHostSite).ShowMinimizedControl; +end; + procedure TAnchorDockHeader.UpdateHeaderControls; begin if Align in [alLeft,alRight] then begin - if CloseButton<>nil then - CloseButton.Align:=alTop; + if CloseButton<>nil then begin + //MinimizeButton.Align:=alTop; + //CloseButton.Align:=alTop; + CloseButton.AnchorSide[akRight].Side := asrCenter; + CloseButton.AnchorSide[akRight].Control := self; + CloseButton.AnchorSide[akTop].Side := asrTop; + CloseButton.AnchorSide[akTop].Control := self; + CloseButton.Anchors := CloseButton.Anchors + [akTop] + [akRight]; + + MinimizeButton.AnchorSide[akRight].Side := asrCenter; + MinimizeButton.AnchorSide[akRight].Control := CloseButton; + MinimizeButton.AnchorSide[akTop].Side := asrBottom; + MinimizeButton.AnchorSide[akTop].Control := CloseButton; + MinimizeButton.Anchors := MinimizeButton.Anchors + [akTop] + [akRight]; + end; end else begin - if CloseButton<>nil then - CloseButton.Align:=alRight; + if CloseButton<>nil then begin + //MinimizeButton.Align:=alRight; + //CloseButton.Align:=alRight; + CloseButton.AnchorSide[akRight].Side := asrRight; + CloseButton.AnchorSide[akRight].Control := self; + CloseButton.AnchorSide[akTop].Side := asrCenter; + CloseButton.AnchorSide[akTop].Control := self; + CloseButton.Anchors := CloseButton.Anchors - [akLeft] + [akRight]; + + MinimizeButton.AnchorSide[akRight].Side := asrLeft; + MinimizeButton.AnchorSide[akRight].Control := CloseButton; + MinimizeButton.AnchorSide[akTop].Side := asrCenter; + MinimizeButton.AnchorSide[akTop].Control := CloseButton; + MinimizeButton.Anchors := MinimizeButton.Anchors - [akLeft] + [akRight]; + end; end; + CloseButton.BorderSpacing.Around:=ButtonBorderSpacingAround; + MinimizeButton.BorderSpacing.Around:=ButtonBorderSpacingAround; //debugln(['TAnchorDockHeader.UpdateHeaderControls ',dbgs(Align),' ',dbgs(CloseButton.Align)]); end; @@ -5787,9 +6364,9 @@ begin inherited Create(TheOwner); FHeaderPosition:=adlhpAuto; - FCloseButton:=TAnchorDockCloseButton.Create(Self); BevelOuter:=bvNone; BorderWidth:=0; + FCloseButton:=TAnchorDockCloseButton.Create(Self); with FCloseButton do begin Name:='CloseButton'; Parent:=Self; @@ -5799,11 +6376,23 @@ OnClick:=@CloseButtonClick; AutoSize:=true; end; + FMinimizeButton:=TAnchorDockMinimizeButton.Create(Self); + with FMinimizeButton do begin + Name:='MinimizeButton'; + Parent:=Self; + Flat:=true; + ShowHint:=true; + Hint:=adrsMinimize; + OnClick:=@MinimizeButtonClick; + AutoSize:=true; + end; Align:=alTop; AutoSize:=true; ShowHint:=true; PopupMenu:=DockMaster.GetPopupMenu; fFocused:=false; + FMouseTimeStartX:=EmptyMouseTimeStartX; + fUseTimer:=true; end; { TAnchorDockCloseButton } @@ -5830,6 +6419,31 @@ Result := ThemeServices.GetElementDetails(WindowPart); end; +procedure SizeCorrector(var current,recomend:integer); +begin + if recomend<0 then begin + if current>0 then + recomend:=current + else + current:=HardcodedButtonSize; + end else begin + if current>recomend then + current:=recomend + else begin + if current>0 then + recomend:=current + else + current:=recomend; + end; + end; +end; + +procedure ButtonSizeCorrector(var w,h:integer); +begin + SizeCorrector(w,PreferredButtonWidth); + SizeCorrector(h,PreferredButtonHeight); +end; + procedure TAnchorDockCloseButton.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; WithThemeSpace: Boolean); begin @@ -5837,6 +6451,7 @@ begin PreferredWidth:=cx; PreferredHeight:=cy; + ButtonSizeCorrector(PreferredWidth,PreferredHeight); {$IF defined(LCLGtk2) or defined(Carbon)} inc(PreferredWidth,2); inc(PreferredHeight,2); @@ -5844,6 +6459,45 @@ end; end; +{ TAnchorDockMinimizeButton } + +function TAnchorDockMinimizeButton.GetDrawDetails: TThemedElementDetails; + +function WindowPart: TThemedWindow; + begin + // no check states available + Result := twMinButtonNormal; + if not IsEnabled then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonDisabled{$ELSE}twMinButtonDisabled{$ENDIF} + else + if FState in [bsDown, bsExclusive] then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonPushed{$ELSE}twMinButtonPushed{$ENDIF} + else + if FState = bsHot then + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonHot{$ELSE}twMinButtonHot{$ENDIF} + else + Result := {$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF}; + end; + +begin + Result := ThemeServices.GetElementDetails(WindowPart); +end; + +procedure TAnchorDockMinimizeButton.CalculatePreferredSize(var PreferredWidth, + PreferredHeight: integer; WithThemeSpace: Boolean); +begin + with ThemeServices.GetDetailSize(ThemeServices.GetElementDetails({$IFDEF LCLGtk2}twMDIRestoreButtonNormal{$ELSE}twMinButtonNormal{$ENDIF})) do + begin + PreferredWidth:=cx; + PreferredHeight:=cy; + ButtonSizeCorrector(PreferredWidth,PreferredHeight); + {$IF defined(LCLGtk2) or defined(Carbon)} + inc(PreferredWidth,2); + inc(PreferredHeight,2); + {$ENDIF} + end; +end; + { TAnchorDockManager } procedure TAnchorDockManager.SetPreferredSiteSizeAsSiteMinimum( @@ -6213,6 +6867,9 @@ ClientRectChanged:=(WidthDiff<>0) or (HeightDiff<>0); if ClientRectChanged or PreferredSiteSizeAsSiteMinimum then AlignChilds; + if ClientRectChanged then + if DockMaster.FOverlappingForm<>nil then + DockMaster.HideOverlappingForm(nil); end; procedure TAnchorDockManager.SaveToStream(Stream: TStream); @@ -6287,6 +6944,11 @@ ADockObject.DropOnControl:=Site else ADockObject.DropOnControl:=nil; + if Site is TAnchorDockHostSite then begin + ADockObject.DropAlign:=AcceptAlign(Site as TAnchorDockHostSite,ADockObject.DropAlign); + if ADockObject.DropAlign=alNone then + exit(false); + end; end; //debugln(['TAnchorDockManager.GetDockEdge ADockObject.DropAlign=',dbgs(ADockObject.DropAlign),' DropOnControl=',DbgSName(ADockObject.DropOnControl)]); Result:=true; @@ -6505,32 +7167,58 @@ procedure TAnchorDockSplitter.SetBoundsPercentually; var NewLeft, NewTop: Integer; + AControl: TControl; + SplitterAnchorKind:TAnchorKind; begin - if ResizeAnchor in [akLeft,akRight] then - begin - if DockParentClientSize.cx> 0 then + if Enabled then begin + if ResizeAnchor in [akLeft,akRight] then begin - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewLeft := Round(FPercentPosition*Parent.ClientWidth) - else - NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; - NewTop := Top; - SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); + end; end; - end else - begin - if DockParentClientSize.cy> 0 then - begin - NewLeft := Left; - if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then - NewTop := Round(FPercentPosition*Parent.ClientHeight) - else - NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + if FPercentPosition < 0 then + UpdatePercentPosition; + end else begin + SplitterAnchorKind:=akTop; + AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind); + if AControl=nil then begin SplitterAnchorKind:=akRight;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akBottom;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + if AControl=nil then begin SplitterAnchorKind:=akLeft;AControl:=CountAndReturnOnlyOneMinimizedAnchoredControls(self,SplitterAnchorKind);end; + + if AControl is TAnchorDockHostSite then begin + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + NewTop := (AControl as TAnchorDockHostSite).Header.Left; + NewTop := (AControl as TAnchorDockHostSite).Header.Height; + NewLeft := left; + NewTop := top; + (AControl as TAnchorDockHostSite).UpdateHeaderAlign; + case SplitterAnchorKind of + akTop: NewTop := AControl.Top+(AControl as TAnchorDockHostSite).Header.Height; + akBottom: NewTop := AControl.Top+AControl.Height-(AControl as TAnchorDockHostSite).Header.Height-Height; + akLeft: NewLeft := AControl.Left+(AControl as TAnchorDockHostSite).Header.Width; + akRight: NewLeft := AControl.Left+AControl.Width-(AControl as TAnchorDockHostSite).Header.Width-Width; + end; SetBoundsKeepDockBounds(NewLeft,NewTop,Width,Height); end; end; - if FPercentPosition < 0 then - UpdatePercentPosition; end; function TAnchorDockSplitter.SideAnchoredControlCount(Side: TAnchorKind): integer; @@ -6560,14 +7248,47 @@ end; end; +function TAnchorDockSplitter.GetSpliterBoundsWithUnminimizedDockSites:TRect; +var + NewLeft, NewTop: Integer; +begin + if ResizeAnchor in [akLeft,akRight] then + begin + if DockParentClientSize.cx> 0 then + begin + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewLeft := Round(FPercentPosition*Parent.ClientWidth) + else + NewLeft := (DockBounds.Left*Parent.ClientWidth) div DockParentClientSize.cx; + NewTop := Top; + end; + end else + begin + if DockParentClientSize.cy> 0 then + begin + NewLeft := Left; + if (FPercentPosition > 0) or SameValue(FPercentPosition, 0) then + NewTop := Round(FPercentPosition*Parent.ClientHeight) + else + NewTop := (DockBounds.Top*Parent.ClientHeight) div DockParentClientSize.cy; + end; + end; + result:=Rect(NewLeft,NewTop,NewLeft+Width,NewTop+Height); +end; + procedure TAnchorDockSplitter.SaveLayout( LayoutNode: TAnchorDockLayoutTreeNode); +var + NewLeft, NewTop: Integer; begin if ResizeAnchor in [akLeft,akRight] then LayoutNode.NodeType:=adltnSplitterVertical else LayoutNode.NodeType:=adltnSplitterHorizontal; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); + if not Enabled then begin + LayoutNode.BoundsRect:=GetSpliterBoundsWithUnminimizedDockSites; + end end; function TAnchorDockSplitter.HasOnlyOneSibling(Side: TAnchorKind; MinPos, @@ -6645,7 +7366,7 @@ begin inherited MouseDown(Button, Shift, X, Y); ATabIndex := IndexOfPageAt(X, Y); - if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) then + if (Button = mbLeft) and DockMaster.AllowDragging and (ATabIndex >= 0) and (DockMaster.FOverlappingForm=nil) then begin APage:=Page[ATabIndex]; if (APage.ControlCount>0) and (APage.Controls[0] is TAnchorDockHostSite) then @@ -6782,6 +7503,20 @@ PopupMenu:=DockMaster.GetPopupMenu; end; +{ TAnchorDockOverlappingForm } + +constructor TAnchorDockOverlappingForm.CreateNew(AOwner: TComponent; Num: Integer = 0); +begin + inherited; + BorderStyle:=bsNone; + AnchorDockHostSite:=nil; + Panel:=TPanel.Create(self); + Panel.BorderStyle:=bsSingle; + Panel.Align:=alClient; + Panel.Parent:=self; + Panel.Visible:=true; +end; + { TAnchorDockPage } procedure TAnchorDockPage.UpdateDockCaption(Exclude: TControl); @@ -6835,9 +7570,11 @@ initialization DockMaster:=TAnchorDockMaster.Create(nil); + DockTimer:=TTimer.Create(nil); finalization FreeAndNil(DockMaster); + FreeAndNil(DockTimer); end. Index: components/anchordocking/anchordockoptionsdlg.lfm =================================================================== --- components/anchordocking/anchordockoptionsdlg.lfm (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.lfm (working copy) @@ -1,11 +1,13 @@ object AnchorDockOptionsFrame: TAnchorDockOptionsFrame Left = 0 - Height = 482 + Height = 567 Top = 0 - Width = 416 - ClientHeight = 482 - ClientWidth = 416 + Width = 490 + ClientHeight = 567 + ClientWidth = 490 + DesignTimePPI = 113 OnClick = FrameClick + ParentFont = False TabOrder = 0 DesignLeft = 513 DesignTop = 189 @@ -12,14 +14,15 @@ object DragThresholdLabel: TLabel AnchorSideLeft.Control = Owner AnchorSideTop.Control = Owner - Left = 10 - Height = 13 - Top = 10 - Width = 111 - BorderSpacing.Left = 10 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 12 + Width = 122 + BorderSpacing.Left = 12 + BorderSpacing.Top = 12 Caption = 'DragThresholdLabel' ParentColor = False + ParentFont = False end object DragThresholdTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdLabel @@ -27,15 +30,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 23 - Width = 396 + Left = 12 + Height = 54 + Top = 31 + Width = 466 Max = 20 OnChange = DragThresholdTrackBarChange Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Right = 10 + BorderSpacing.Right = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 1 @@ -46,12 +50,13 @@ AnchorSideTop.Control = DragThresholdLabel AnchorSideTop.Side = asrCenter AnchorSideRight.Control = Owner - Left = 127 - Height = 23 - Top = 5 - Width = 50 - BorderSpacing.Left = 6 + Left = 141 + Height = 27 + Top = 8 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 20 + ParentFont = False TabOrder = 0 Visible = False end @@ -59,13 +64,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = DragThresholdTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 79 - Width = 103 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 97 + Width = 112 + BorderSpacing.Top = 12 Caption = 'SplitterWidthLabel' ParentColor = False + ParentFont = False end object SplitterWidthTrackBar: TTrackBar AnchorSideLeft.Control = DragThresholdTrackBar @@ -73,14 +79,15 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 46 - Top = 92 - Width = 396 + Left = 12 + Height = 54 + Top = 116 + Width = 466 Min = 1 OnChange = SplitterWidthTrackBarChange Position = 1 Anchors = [akTop, akLeft, akRight] + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 3 @@ -89,12 +96,13 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = SplitterWidthTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 142 - Width = 160 - BorderSpacing.Top = 4 + Left = 12 + Height = 23 + Top = 175 + Width = 169 + BorderSpacing.Top = 5 Caption = 'ScaleOnResizeCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 4 @@ -103,12 +111,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ScaleOnResizeCheckBox AnchorSideTop.Side = asrBottom - Left = 10 - Height = 24 - Top = 166 - Width = 149 + Left = 12 + Height = 23 + Top = 198 + Width = 160 Caption = 'ShowHeaderCheckBox' OnChange = ShowHeaderCheckBoxChange + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 5 @@ -117,12 +126,13 @@ AnchorSideLeft.Control = ScaleOnResizeCheckBox AnchorSideTop.Control = ShowHeaderCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 190 - Width = 191 - BorderSpacing.Left = 15 + Left = 30 + Height = 23 + Top = 221 + Width = 208 + BorderSpacing.Left = 18 Caption = 'ShowHeaderCaptionCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 6 @@ -131,11 +141,12 @@ AnchorSideLeft.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Control = ShowHeaderCaptionCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 214 - Width = 249 + Left = 30 + Height = 23 + Top = 244 + Width = 272 Caption = 'HideHeaderCaptionForFloatingCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 7 @@ -147,15 +158,16 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = Owner AnchorSideRight.Side = asrBottom - Left = 122 + Left = 136 Height = 27 - Top = 286 - Width = 284 + Top = 313 + Width = 342 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 6 - BorderSpacing.Right = 10 - ItemHeight = 0 + BorderSpacing.Left = 7 + BorderSpacing.Right = 12 + ItemHeight = 19 OnDrawItem = HeaderStyleComboBoxDrawItem + ParentFont = False Style = csDropDownList TabOrder = 10 end @@ -163,23 +175,25 @@ AnchorSideLeft.Control = ShowHeaderCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrCenter - Left = 20 - Height = 13 - Top = 293 - Width = 96 - BorderSpacing.Left = 10 + Left = 24 + Height = 19 + Top = 317 + Width = 105 + BorderSpacing.Left = 12 Caption = 'HeaderStyleLabel' ParentColor = False + ParentFont = False end object FlattenHeadersCheckBox: TCheckBox AnchorSideLeft.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Control = HideHeaderCaptionForFloatingCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 238 - Width = 164 + Left = 30 + Height = 23 + Top = 267 + Width = 175 Caption = 'FlattenHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 8 @@ -188,11 +202,12 @@ AnchorSideLeft.Control = FlattenHeadersCheckBox AnchorSideTop.Control = FlattenHeadersCheckBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 262 - Width = 154 + Left = 30 + Height = 23 + Top = 290 + Width = 164 Caption = 'FilledHeadersCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 9 @@ -201,11 +216,12 @@ AnchorSideLeft.Control = FilledHeadersCheckBox AnchorSideTop.Control = HeaderStyleComboBox AnchorSideTop.Side = asrBottom - Left = 25 - Height = 24 - Top = 313 - Width = 175 + Left = 30 + Height = 23 + Top = 340 + Width = 189 Caption = 'HighlightFocusedCheckBox' + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 11 @@ -215,13 +231,14 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = SplitterWidthLabel AnchorSideTop.Side = asrCenter - Left = 119 - Height = 23 - Top = 74 - Width = 50 - BorderSpacing.Left = 6 + Left = 131 + Height = 27 + Top = 93 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 10 MinValue = 1 + ParentFont = False TabOrder = 2 Value = 1 Visible = False @@ -228,15 +245,16 @@ end object HeaderAlignTopLabel: TLabel AnchorSideLeft.Control = DragThresholdLabel - AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Control = DockSitesCanBeMinimized AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 347 - Width = 117 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 398 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignTopLabel' ParentColor = False + ParentFont = False end object HeaderAlignTopTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -244,10 +262,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 360 - Width = 396 + Left = 12 + Height = 55 + Top = 417 + Width = 466 Frequency = 10 Max = 150 OnChange = HeaderAlignTopTrackBarChange @@ -254,7 +272,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 13 @@ -264,12 +283,13 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignTopLabel AnchorSideTop.Side = asrCenter - Left = 133 - Height = 23 - Top = 342 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 394 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 150 + ParentFont = False TabOrder = 12 Visible = False end @@ -277,13 +297,14 @@ AnchorSideLeft.Control = DragThresholdLabel AnchorSideTop.Control = HeaderAlignTopTrackBar AnchorSideTop.Side = asrBottom - Left = 10 - Height = 13 - Top = 417 - Width = 120 - BorderSpacing.Top = 10 + Left = 12 + Height = 19 + Top = 484 + Width = 130 + BorderSpacing.Top = 12 Caption = 'HeaderAlignLeftLabel' ParentColor = False + ParentFont = False end object HeaderAlignLeftTrackBar: TTrackBar AnchorSideLeft.Control = Owner @@ -291,10 +312,10 @@ AnchorSideTop.Side = asrBottom AnchorSideRight.Control = DragThresholdTrackBar AnchorSideRight.Side = asrBottom - Left = 10 - Height = 47 - Top = 430 - Width = 396 + Left = 12 + Height = 55 + Top = 503 + Width = 466 Frequency = 10 Max = 200 OnChange = HeaderAlignLeftTrackBarChange @@ -301,7 +322,8 @@ PageSize = 10 Position = 0 Anchors = [akTop, akLeft, akRight] - BorderSpacing.Left = 10 + BorderSpacing.Left = 12 + ParentFont = False ParentShowHint = False ShowHint = True TabOrder = 15 @@ -311,13 +333,28 @@ AnchorSideLeft.Side = asrBottom AnchorSideTop.Control = HeaderAlignLeftLabel AnchorSideTop.Side = asrCenter - Left = 136 - Height = 23 - Top = 412 - Width = 50 - BorderSpacing.Left = 6 + Left = 149 + Height = 27 + Top = 480 + Width = 59 + BorderSpacing.Left = 7 MaxValue = 200 + ParentFont = False TabOrder = 14 Visible = False end + object DockSitesCanBeMinimized: TCheckBox + AnchorSideLeft.Control = FilledHeadersCheckBox + AnchorSideTop.Control = HighlightFocusedCheckBox + AnchorSideTop.Side = asrBottom + Left = 30 + Height = 23 + Top = 363 + Width = 185 + Caption = 'DockSitesCanBeMinimized' + ParentFont = False + ParentShowHint = False + ShowHint = True + TabOrder = 16 + end end Index: components/anchordocking/anchordockoptionsdlg.pas =================================================================== --- components/anchordocking/anchordockoptionsdlg.pas (revision 59428) +++ components/anchordocking/anchordockoptionsdlg.pas (working copy) @@ -37,6 +37,7 @@ HeaderStyleLabel: TLabel; HideHeaderCaptionForFloatingCheckBox: TCheckBox; HighlightFocusedCheckBox: TCheckBox; + DockSitesCanBeMinimized: TCheckBox; ScaleOnResizeCheckBox: TCheckBox; ShowHeaderCaptionCheckBox: TCheckBox; ShowHeaderCheckBox: TCheckBox; @@ -202,7 +203,7 @@ HeaderAlignTopSpinEdit.Visible:=true; HeaderAlignTopTrackBar.Visible:=false; - HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,HighlightFocusedCheckBox); + HeaderAlignTopSpinEdit.AnchorToNeighbour(akTop,6,DockSitesCanBeMinimized); HeaderAlignTopLabel.AnchorVerticalCenterTo(HeaderAlignTopSpinEdit); UpdateHeaderAlignTopLabel; @@ -299,6 +300,7 @@ HeaderStyleLabel.Enabled:=HasHeaders; HeaderStyleComboBox.Enabled:=HasHeaders; HighlightFocusedCheckBox.Enabled:=HasHeaders; + DockSitesCanBeMinimized.Enabled:=HasHeaders; end; constructor TAnchorDockOptionsFrame.Create(TheOwner: TComponent); @@ -356,6 +358,7 @@ TheSettings.HeaderFilled:=FilledHeadersCheckBox.Checked; TheSettings.HeaderStyle:=TADHeaderStyle(HeaderStyleComboBox.ItemIndex); TheSettings.HeaderHighlightFocused:=HighlightFocusedCheckBox.Checked; + TheSettings.DockSitesCanBeMinimized:=DockSitesCanBeMinimized.Checked; end; procedure TAnchorDockOptionsFrame.LoadFromSettings( @@ -429,6 +432,10 @@ HighlightFocusedCheckBox.Checked:=TheSettings.HeaderHighlightFocused; HighlightFocusedCheckBox.Caption:=adrsHighlightFocused; HighlightFocusedCheckBox.Hint:=adrsHighlightFocusedHint; + + DockSitesCanBeMinimized.Checked:=TheSettings.DockSitesCanBeMinimized; + DockSitesCanBeMinimized.Caption:=adrsDockSitesCanBeMinimized; + DockSitesCanBeMinimized.Hint:=adrsDockSitesCanBeMinimizedHint; end; end. Index: components/anchordocking/anchordockpanel.pas =================================================================== --- components/anchordocking/anchordockpanel.pas (revision 59428) +++ components/anchordocking/anchordockpanel.pas (working copy) @@ -55,7 +55,7 @@ begin LayoutNode.NodeType:=adltnControl; - LayoutNode.Assign(Self); + LayoutNode.Assign(Self,false,false); LayoutNode.Name:={OneControl.}Name; TAnchorDockHostSite(OneControl).SaveLayout(LayoutTree,LayoutNode); Index: components/anchordocking/anchordockstorage.pas =================================================================== --- components/anchordocking/anchordockstorage.pas (revision 59428) +++ components/anchordocking/anchordockstorage.pas (working copy) @@ -64,6 +64,7 @@ FTabPosition: TTabPosition; FWindowState: TWindowState; FControlLocation: TADLControlLocation; + FMinimized: Boolean; function GetAnchors(Site: TAnchorKind): string; function GetBottom: integer; function GetHeight: integer; @@ -90,6 +91,7 @@ procedure SetTop(const AValue: integer); procedure SetWidth(const AValue: integer); procedure SetWindowState(const AValue: TWindowState); + procedure SetMinimized(const AValue: boolean); public constructor Create; destructor Destroy; override; @@ -96,7 +98,7 @@ procedure Clear; function IsEqual(Node: TAnchorDockLayoutTreeNode): boolean; procedure Assign(Node: TAnchorDockLayoutTreeNode); overload; - procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); overload; + procedure Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); overload; procedure LoadFromConfig(Config: TConfigStorage); overload; procedure LoadFromConfig(Path: string; Config: TRttiXMLConfig); overload; procedure SaveToConfig(Config: TConfigStorage); overload; @@ -106,7 +108,7 @@ procedure CheckConsistency; virtual; // simplifying - procedure Simplify(ExistingNames: TStrings); + procedure Simplify(ExistingNames: TStrings; ParentMinimized:boolean); procedure DeleteNode(ChildNode: TAnchorDockLayoutTreeNode); function FindNodeBoundSplitter(ChildNode: TAnchorDockLayoutTreeNode; Side: TAnchorKind): TAnchorDockLayoutTreeNode; @@ -135,6 +137,7 @@ property Monitor: integer read FMonitor write SetMonitor; property HeaderPosition: TADLHeaderPosition read FHeaderPosition write SetHeaderPosition; property TabPosition: TTabPosition read FTabPosition write SetTabPosition; + property Minimized: Boolean read FMinimized write SetMinimized; function Count: integer; function IsSplitter: boolean; function IsRootWindow: boolean; @@ -988,6 +991,13 @@ IncreaseChangeStamp; end; +procedure TAnchorDockLayoutTreeNode.SetMinimized(const AValue: boolean); +begin + if FMinimized=AValue then exit; + FMinimized:=AValue; + IncreaseChangeStamp; +end; + procedure TAnchorDockLayoutTreeNode.SetTop(const AValue: integer); begin if Top=AValue then exit; @@ -1084,6 +1094,7 @@ BoundSplitterPos:=Node.BoundSplitterPos; WorkAreaRect:=Node.WorkAreaRect; Monitor:=Node.Monitor; + Minimized:=Node.Minimized; for a:=low(TAnchorKind) to high(TAnchorKind) do Anchors[a]:=Node.Anchors[a]; while Count>Node.Count do Nodes[Count-1].Free; @@ -1098,9 +1109,10 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean=false); +procedure TAnchorDockLayoutTreeNode.Assign(AControl: TControl; OverrideBoundsRect: Boolean; AMinimized: Boolean); var AnchorControl: TControl; + ParentForm:TCustomForm; a: TAnchorKind; begin Name:=AControl.Name; @@ -1109,12 +1121,18 @@ else BoundsRect:=AControl.BoundsRect; Align:=AControl.Align; + Minimized:=AMinimized; if (AControl.Parent=nil) and (AControl is TCustomForm) then begin WindowState:=TCustomForm(AControl).WindowState; Monitor:=TCustomForm(AControl).Monitor.MonitorNum; WorkAreaRect:=TCustomForm(AControl).Monitor.WorkareaRect; - end else - WindowState:=GetParentForm(AControl).WindowState; + end else begin + ParentForm:=GetParentForm(AControl); + if assigned(ParentForm) then + WindowState:=ParentForm.WindowState + else + WindowState:=wsNormal; + end; if AControl is TCustomTabControl then TabPosition:=TCustomTabControl(AControl).TabPosition else @@ -1137,6 +1155,7 @@ Clear; Name:=Config.GetValue('Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue('Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue('Minimized',false); Left:=Config.GetValue('Bounds/Left',0); Top:=Config.GetValue('Bounds/Top',0); Width:=Config.GetValue('Bounds/Width',0); @@ -1171,6 +1190,7 @@ Clear; Name:=Config.GetValue(Path+'Name',''); NodeType:=NameToADLTreeNodeType(Config.GetValue(Path+'Type',ADLTreeNodeTypeNames[adltnNone])); + Minimized:=Config.GetValue(Path+'Minimized',false); Left:=Config.GetValue(Path+'Bounds/Left',0); Top:=Config.GetValue(Path+'Bounds/Top',0); Width:=Config.GetValue(Path+'Bounds/Width',0); @@ -1219,6 +1239,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue('Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue('Minimized',Minimized,False); Config.SetDeleteValue('Monitor',Monitor,0); Config.SetDeleteValue('ChildCount',Count,0); for i:=1 to Count do begin @@ -1252,6 +1273,7 @@ ADLHeaderPositionNames[adlhpAuto]); Config.SetDeleteValue(Path+'Header/TabPosition',ADLTabPostionNames[TabPosition], ADLTabPostionNames[tpTop]); + Config.SetDeleteValue(Path+'Minimized',Minimized,False); Config.SetDeleteValue(Path+'Monitor',Monitor,0); Config.SetDeleteValue(Path+'ChildCount',Count,0); for i:=1 to Count do @@ -1397,7 +1419,7 @@ end; end; -procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings); +procedure TAnchorDockLayoutTreeNode.Simplify(ExistingNames: TStrings; ParentMinimized:boolean); { Simplification rules: 1. Control nodes without existing name are deleted. 2. Empty layouts and pages are deleted @@ -1406,16 +1428,18 @@ var i: Integer; ChildNode: TAnchorDockLayoutTreeNode; + NodeMinimized:boolean; begin // simplify children i:=Count-1; while i>=0 do begin ChildNode:=Nodes[i]; - ChildNode.Simplify(ExistingNames); + NodeMinimized:=ParentMinimized or ChildNode.Minimized; + ChildNode.Simplify(ExistingNames,NodeMinimized); if (ChildNode.NodeType=adltnControl) then begin // leaf node => check if there is a control - if (ChildNode.Name='') or (ExistingNames.IndexOf(ChildNode.Name)<0) then + if (ChildNode.Name='') or ((ExistingNames.IndexOf(ChildNode.Name)<0) and (not NodeMinimized)) then DeleteNode(ChildNode); end else if ChildNode.IsSplitter then begin // splitter @@ -1424,7 +1448,7 @@ ChildNode[0].Free; end else if ChildNode.NodeType=adltnCustomSite then begin // custom dock site - end else if ChildNode.Count=0 then begin + end else if (ChildNode.Count=0)and(not NodeMinimized) then begin // inner node without child => delete DeleteNode(ChildNode); end else if (ChildNode.Count=1) Index: components/anchordocking/anchordockstr.pas =================================================================== --- components/anchordocking/anchordockstr.pas (revision 59428) +++ components/anchordocking/anchordockstr.pas (working copy) @@ -8,6 +8,7 @@ resourcestring adrsClose = 'Close'; + adrsMinimize = 'Minimize'; adrsQuit = 'Quit %s'; adrsTabPosition = 'Tab position'; adrsMovePageRight = 'Move page right'; @@ -82,6 +83,8 @@ adrsFilledHeadersHint = 'Fill headers of docked controls'; adrsHighlightFocused = 'Highlight focused'; adrsHighlightFocusedHint = 'Highlight header of focused docked control'; + adrsDockSitesCanBeMinimized = 'Dock sites can be minimized'; + adrsDockSitesCanBeMinimizedHint = 'Dock sites can be minimized'; implementation Index: components/anchordocking/design/anchordesktopoptions.pas =================================================================== --- components/anchordocking/design/anchordesktopoptions.pas (revision 59428) +++ components/anchordocking/design/anchordesktopoptions.pas (working copy) @@ -272,7 +272,7 @@ // custom dock site LayoutNode:=FTree.NewNode(FTree.Root); LayoutNode.NodeType:=adltnCustomSite; - LayoutNode.Assign(AForm); + LayoutNode.Assign(AForm,false,false); // can have one normal dock site Site:=TAnchorDockManager(AForm.DockManager).GetChildSite; if Site<>nil then begin @@ -287,7 +287,7 @@ raise EAnchorDockLayoutError.Create('invalid root control for save: '+DbgSName(AControl)); end; // remove invisible controls - FTree.Root.Simplify(VisibleControls); + FTree.Root.Simplify(VisibleControls,false); finally VisibleControls.Free; SavedSites.Free; |
|
anchordocking_minimize_docksite12.patch Last 1,2 issues fixed: >>Project Inspector also should not have a minimize button. >>if the adjacent window is minimized, this window should not have a minimize button Now I see a few small problems, and two big ones: 1) Bugs with double loading layout with minimized sites 2) Problem with unminimize site after dock a window nearby. When free space became less than the original width unminimized site I will solve it, but please add the current patch. I'm already bad at navigating my changes, it makes it difficult to work |
|
I commited the patch with minor formatting changes. Thank you! |
|
I've seen, you are not listed in the contributors list. You have posted a lot of patches for bugs and features. I'll add you to that list. Is Andrey Zubarev your correct name and can I add you to the list? |
|
Yes, Andrey Zubarev my correct name. You can add. Thanks! |
|
Done. I hope of more good patches from you ;) |
|
Thanks! |
|
Found small bug. If load layout for visible=false forms minimize button not show. To fix need modify DockedControlIsVisible function. Modifed function: function DockedControlIsVisible(Control: TControl): boolean; begin while Control<>nil do begin if (not Control.IsControlVisible) and (not (Control is TAnchorDockPage))//exclude pages and (Control.parent<>nil )then //exclude top level forms exit(false); Control:=Control.Parent; end; Result:=true; end; Unfortunately I can not give the patch, I have accumulated too many changes |
|
Applied. Thank you! |
|
Thanks! |
|
> Found small bug. If load layout for visible=false forms minimize button not show. > To fix need modify DockedControlIsVisible function. Modifed function: As I can't see the problem, can you please add a layout for this bug?! I reverted the last patch in revision 60233. With it, a closed site was wrongly reopened after loading layout. |
|
The problem occurs if you load layout on starting program, before show mainform. Try attached layout.xml with minidewithdockpanel example, it will be loaded before the form is shown, in Application.Createform, And minimize button not shown, although he enabled in attached layout.xml |
|
layout.xml (1,060 bytes)
<?xml version="1.0" encoding="utf-8"?> <CONFIG> <MainConfig> <Nodes ChildCount="1"> <Item1 Name="AnchorDockPanel1" Type="CustomSite" ChildCount="1"> <Bounds Top="43" Left="45" Width="568" Height="418"/> <Anchors Align="Client"/> <Item1 Name="AnchorDockSite3" Type="Layout" ChildCount="3"> <Bounds Top="1" Left="1" Width="524" Height="325"/> <Anchors Align="Client"/> <Item1 Name="SourceEditor1" Type="Control"> <Bounds Width="524" Height="171"/> <Anchors Bottom="AnchorDockSplitter1"/> </Item1> <Item2 Name="AnchorDockSplitter1" Type="SplitterHorizontal"> <Bounds Top="171" Width="524" Height="4"/> </Item2> <Item3 Name="DebugOutput" Type="Control"> <Bounds Top="175" Width="524" Height="150"/> <Anchors Top="AnchorDockSplitter1"/> </Item3> </Item1> </Item1> </Nodes> </MainConfig> <Settings DockSitesCanBeMinimized="True"/> </CONFIG> |
|
I removed the check DockedControlIsVisible in UpdateHeaders. At least your patch does the same. This is IMHO not the best solution. Maybe a loading (and simelar) state for DockMaster could be inserted, whith it, there were a chance to detect this special case to call UpdateHeaderShowing. For now, I'll not insert such a new state property. |
|
Thanks! |
Date Modified | Username | Field | Change |
---|---|---|---|
2018-09-27 12:04 | Andrey Zubarev | New Issue | |
2018-09-27 12:04 | Andrey Zubarev | File Added: button.png | |
2018-09-27 15:16 | Juha Manninen | Note Added: 0111054 | |
2018-09-28 07:16 | Andrey Zubarev | Note Added: 0111059 | |
2018-09-28 09:17 | Juha Manninen | Note Added: 0111060 | |
2018-10-19 18:41 | Juha Manninen | Relationship added | related to 0034363 |
2018-10-30 11:48 | Andrey Zubarev | Note Added: 0111677 | |
2018-10-30 11:49 | Andrey Zubarev | File Added: anchordocking_minimize_docksite1.patch | |
2018-10-30 22:34 | Juha Manninen | Note Added: 0111697 | |
2018-10-30 23:34 | Andrey Zubarev | Note Added: 0111699 | |
2018-10-30 23:35 | Andrey Zubarev | File Added: anchordocking_minimize_docksite2.patch | |
2018-10-31 18:57 | Juha Manninen | Note Added: 0111710 | |
2018-10-31 19:10 | Andrey Zubarev | Note Added: 0111711 | |
2018-10-31 19:19 | Andrey Zubarev | Note Added: 0111712 | |
2018-10-31 21:00 | Michl | Assigned To | => Michl |
2018-10-31 21:00 | Michl | Status | new => assigned |
2018-10-31 21:04 | Michl | LazTarget | => - |
2018-10-31 21:04 | Michl | Summary | AnchorDocing feature (new button: size reduction of the panel) => AnchorDocking feature (new button: size reduction of the panel) |
2018-10-31 22:36 | Andrey Zubarev | File Added: anchordocking_minimize_docksite3.patch | |
2018-10-31 22:37 | Andrey Zubarev | Note Added: 0111717 | |
2018-11-04 13:22 | Andrey Zubarev | File Added: anchordocking_minimize_docksite4.patch | |
2018-11-04 13:26 | Andrey Zubarev | Note Added: 0111784 | |
2018-11-06 07:16 | Andrey Zubarev | File Added: anchordocking_minimize_docksite5.patch | |
2018-11-06 07:18 | Andrey Zubarev | Note Added: 0111804 | |
2018-11-07 11:26 | Andrey Zubarev | File Added: anchordocking_minimize_docksite6.patch | |
2018-11-07 11:30 | Andrey Zubarev | Note Added: 0111824 | |
2018-11-07 14:16 | Andrey Zubarev | File Added: anchordocking_minimize_docksite7.patch | |
2018-11-07 14:16 | Andrey Zubarev | Note Edited: 0111824 | View Revisions |
2018-11-07 14:22 | Andrey Zubarev | Note Added: 0111831 | |
2018-11-08 21:37 | Andrey Zubarev | Note Added: 0111872 | |
2018-11-11 00:19 | Andrey Zubarev | File Added: anchordocking_minimize_docksite8.patch | |
2018-11-11 00:21 | Andrey Zubarev | Note Added: 0111897 | |
2018-11-11 00:23 | Andrey Zubarev | Note Edited: 0111897 | View Revisions |
2018-11-11 21:49 | Michl | Note Added: 0111912 | |
2018-11-11 21:50 | Michl | Note Edited: 0111912 | View Revisions |
2018-11-12 00:08 | Andrey Zubarev | File Added: anchordocking_minimize_docksite9.patch | |
2018-11-12 00:12 | Andrey Zubarev | Note Added: 0111917 | |
2018-11-12 21:01 | Michl | File Added: test.xml | |
2018-11-12 21:12 | Michl | File Added: test.png | |
2018-11-12 21:14 | Michl | Note Added: 0111942 | |
2018-11-12 21:25 | Michl | File Added: Test2.png | |
2018-11-12 21:30 | Michl | Note Edited: 0111942 | View Revisions |
2018-11-12 21:31 | Michl | Note Edited: 0111942 | View Revisions |
2018-11-12 23:11 | Andrey Zubarev | Note Added: 0111945 | |
2018-11-13 07:21 | Michl | Note Added: 0111946 | |
2018-11-14 21:16 | Andrey Zubarev | File Added: anchordocking_minimize_docksite10.patch | |
2018-11-14 21:21 | Andrey Zubarev | Note Added: 0111977 | |
2018-11-14 22:26 | Michl | File Added: Test3.png | |
2018-11-14 22:44 | Michl | Note Added: 0111981 | |
2018-11-14 22:44 | Michl | Note Edited: 0111981 | View Revisions |
2018-11-14 22:48 | Michl | File Added: test2.xml | |
2018-11-14 22:53 | Michl | Note Edited: 0111981 | View Revisions |
2018-11-15 13:48 | Andrey Zubarev | Note Added: 0111984 | |
2018-11-18 19:09 | Andrey Zubarev | File Added: anchordocking_minimize_docksite11.patch | |
2018-11-18 19:12 | Andrey Zubarev | Note Added: 0112050 | |
2018-11-25 15:31 | Juha Manninen | Relationship added | related to 0034508 |
2018-11-27 09:34 | Michl | File Added: test3.xml | |
2018-11-27 09:50 | Michl | Note Added: 0112225 | |
2018-11-27 11:48 | Andrey Zubarev | Note Added: 0112229 | |
2018-11-27 11:50 | Andrey Zubarev | Note Edited: 0112229 | View Revisions |
2018-11-27 20:15 | Andrey Zubarev | File Added: anchordocking_minimize_docksite12.patch | |
2018-11-27 20:25 | Andrey Zubarev | Note Added: 0112235 | |
2018-11-27 21:35 | Michl | Fixed in Revision | => 59681 |
2018-11-27 21:35 | Michl | Note Added: 0112237 | |
2018-11-27 21:35 | Michl | Status | assigned => resolved |
2018-11-27 21:35 | Michl | Fixed in Version | => 2.1 (SVN) |
2018-11-27 21:35 | Michl | Resolution | open => fixed |
2018-11-27 21:35 | Michl | Target Version | => 2.2 |
2018-11-27 21:52 | Michl | Note Added: 0112238 | |
2018-11-27 21:52 | Michl | Status | resolved => feedback |
2018-11-27 22:24 | Andrey Zubarev | Note Added: 0112239 | |
2018-11-27 22:24 | Andrey Zubarev | Status | feedback => assigned |
2018-11-27 23:09 | Michl | Note Added: 0112240 | |
2018-11-27 23:09 | Michl | Status | assigned => resolved |
2018-11-28 11:17 | Andrey Zubarev | Note Added: 0112244 | |
2018-11-28 11:17 | Andrey Zubarev | Status | resolved => closed |
2018-12-12 22:09 | Michl | Relationship added | related to 0034614 |
2018-12-12 22:10 | Michl | Relationship added | related to 0034612 |
2019-01-17 20:51 | Andrey Zubarev | Note Added: 0113452 | |
2019-01-17 20:51 | Andrey Zubarev | Status | closed => assigned |
2019-01-17 20:51 | Andrey Zubarev | Resolution | fixed => reopened |
2019-01-17 23:46 | Michl | Fixed in Revision | 59681 => 59681, 60099 |
2019-01-17 23:46 | Michl | Note Added: 0113456 | |
2019-01-17 23:46 | Michl | Status | assigned => resolved |
2019-01-17 23:46 | Michl | Resolution | reopened => fixed |
2019-01-18 07:46 | Andrey Zubarev | Note Added: 0113458 | |
2019-01-18 07:46 | Andrey Zubarev | Status | resolved => closed |
2019-01-27 17:54 | Michl | Status | closed => assigned |
2019-01-27 17:54 | Michl | Resolution | fixed => reopened |
2019-01-27 17:58 | Michl | Note Added: 0113675 | |
2019-01-27 17:58 | Michl | Status | assigned => feedback |
2019-01-27 20:07 | Andrey Zubarev | Note Added: 0113677 | |
2019-01-27 20:07 | Andrey Zubarev | Status | feedback => assigned |
2019-01-27 20:07 | Andrey Zubarev | File Added: layout.xml | |
2019-01-27 23:24 | Michl | Fixed in Revision | 59681, 60099 => 59681, 60099, 60233, 60234 |
2019-01-27 23:24 | Michl | Note Added: 0113682 | |
2019-01-27 23:24 | Michl | Status | assigned => resolved |
2019-01-27 23:24 | Michl | Resolution | reopened => fixed |
2019-01-28 06:32 | Andrey Zubarev | Note Added: 0113684 | |
2019-01-28 06:32 | Andrey Zubarev | Status | resolved => closed |