From 0eda8d5b38dbd57cdf80c91318c7ddc117f4faad Mon Sep 17 00:00:00 2001 From: mattias Date: Sat, 5 Jan 2008 16:39:32 +0000 Subject: [PATCH] LCL: improved painting dock frame e.g. TLazDockTree.PaintDockFrame from Paul git-svn-id: trunk@13632 - --- lcl/include/wincontrol.inc | 14 ++- lcl/ldocktree.pas | 188 ++++++++++++++++++++++++++++++++----- 2 files changed, 175 insertions(+), 27 deletions(-) diff --git a/lcl/include/wincontrol.inc b/lcl/include/wincontrol.inc index eca5e886fb..29afa87b3a 100644 --- a/lcl/include/wincontrol.inc +++ b/lcl/include/wincontrol.inc @@ -2328,8 +2328,10 @@ var CurAnchorSide:=Control.AnchorSide[Kind]; //if CheckPosition(Control) and (Kind=akLeft) then debugln(['GetAnchorSidePosition A Self=',DbgSName(Self),' Control=',DbgSName(Control),' CurAnchorSide.Control=',DbgSName(CurAnchorSide.Control),' Spacing=',Control.BorderSpacing.GetSpace(Kind)]); CurAnchorSide.GetSidePosition(ReferenceControl,ReferenceSide,Position); - if ReferenceControl<>nil then + if ReferenceControl<>nil then begin + //DebugLn(['GetAnchorSidePosition ',DbgSName(Control),' ReferenceControl=',DbgSName(ReferenceControl)]); Result:=Position; + end; //if CheckPosition(Control) and (Kind=akLeft) then begin //debugln('GetAnchorSidePosition B Self=',DbgSName(Self),' Control=',DbgSName(Control),' Result=',dbgs(Result),' ReferenceControl=',dbgsName(ReferenceControl)); //if ReferenceControl<>nil then DebugLn(['GetAnchorSidePosition ReferenceControl.BoundsRect=',dbgs(ReferenceControl.BoundsRect)]); @@ -4184,7 +4186,12 @@ begin Assert(False, Format('Trace:> [TWinControl.PaintHandler] %s --> Msg.DC: 0x%x', [ClassName, TheMessage.DC])); DC := TheMessage.DC; - if DC = 0 then DC := BeginPaint(Handle, PS); + if DC = 0 then + DC := BeginPaint(Handle, PS); + + if FDockSite and FUseDockManager then + FDockManager.PaintSite(DC); + try // check if child controls need clipping //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' B'); @@ -4221,7 +4228,8 @@ begin //DebugLn('[TWinControl.PaintHandler] ',DbgSName(Self),' PaintControls ...'); PaintControls(DC, nil); finally - if TheMessage.DC = 0 then EndPaint(Handle, PS); + if TheMessage.DC = 0 then + EndPaint(Handle, PS); end; Assert(False, Format('Trace:< [TWinControl.PaintHandler] %s', [ClassName])); //DebugLn('[TWinControl.PaintHandler] END ',Name,':',ClassName,' DC=',DbgS(Message.DC,8)); diff --git a/lcl/ldocktree.pas b/lcl/ldocktree.pas index 4947f7ac99..9f9cb46add 100644 --- a/lcl/ldocktree.pas +++ b/lcl/ldocktree.pas @@ -31,8 +31,8 @@ unit LDockTree; interface uses - Classes, SysUtils, LCLProc, LCLType, Forms, Controls, ExtCtrls, Menus, - LCLStrConsts; + Types, Classes, SysUtils, LCLProc, LCLType, LCLStrConsts, + Graphics, Controls, ExtCtrls, Forms, Menus, Themes; type TLazDockPages = class; @@ -61,10 +61,13 @@ type private FAutoFreeDockSite: boolean; protected - procedure UndockControlForDocking(AControl: TControl); - procedure BreakAnchors(Zone: TDockZone); - procedure CreateDockLayoutHelperControls(Zone: TLazDockZone); + procedure AdjustDockRect(AControl: TControl; var ARect: TRect); override; procedure AnchorDockLayout(Zone: TLazDockZone); + procedure CreateDockLayoutHelperControls(Zone: TLazDockZone); + procedure BreakAnchors(Zone: TDockZone); + procedure PaintDockFrame(ACanvas: TCanvas; AControl: TControl; + const ARect: TRect); override; + procedure UndockControlForDocking(AControl: TControl); public constructor Create(TheDockSite: TWinControl); override; destructor Destroy; override; @@ -76,6 +79,7 @@ type function FindBorderControl(Zone: TLazDockZone; Side: TAnchorKind): TControl; function GetAnchorControl(Zone: TLazDockZone; Side: TAnchorKind; OutSide: boolean): TControl; + procedure PaintSite(DC: HDC); override; public property AutoFreeDockSite: boolean read FAutoFreeDockSite write FAutoFreeDockSite; end; @@ -196,6 +200,7 @@ type const + DefaultDockGrabberSize = 15; DockAlignOrientations: array[TAlign] of TDockOrientation = ( doPages, //alNone, doVertical, //alTop, @@ -602,6 +607,79 @@ begin BreakAnchors(Zone.NextSibling); end; +procedure TLazDockTree.PaintDockFrame(ACanvas: TCanvas; AControl: TControl; + const ARect: TRect); +var + Details: TThemedElementDetails; + BtnRect: TRect; + DrawRect: TRect; + d: integer; +begin + DrawRect := ARect; + InflateRect(DrawRect, -1, -1); + ACanvas.Brush.Color := clBtnShadow; + ACanvas.FrameRect(DrawRect); + InflateRect(DrawRect, -1, -1); + case AControl.DockOrientation of + doHorizontal: + begin + d := DrawRect.Bottom - DrawRect.Top; + BtnRect := DrawRect; + Dec(BtnRect.Right); + BtnRect.Left := BtnRect.Right - d; + Details := ThemeServices.GetElementDetails(twCloseButtonNormal); + ThemeServices.DrawElement(ACanvas.Handle, Details, BtnRect); + + DrawRect.Right := BtnRect.Left; + BtnRect := DrawRect; + Dec(BtnRect.Right); + BtnRect.Left := BtnRect.Right - d; + Details := ThemeServices.GetElementDetails(twRestoreButtonNormal); + ThemeServices.DrawElement(ACanvas.Handle, Details, BtnRect); + + DrawRect.Right := BtnRect.Left; + InflateRect(DrawRect, -4, 0); + d := (DrawRect.Bottom + DrawRect.Top) div 2; + + ACanvas.Pen.Color := clBtnHighlight; + ACanvas.MoveTo(DrawRect.Left, d - 1); + ACanvas.LineTo(DrawRect.Right, d - 1); + + ACanvas.Pen.Color := clBtnShadow; + ACanvas.MoveTo(DrawRect.Left, d); + ACanvas.LineTo(DrawRect.Right, d); + end; + doVertical: + begin + d := DrawRect.Right - DrawRect.Left; + BtnRect := DrawRect; + Inc(BtnRect.Top); + BtnRect.Bottom := BtnRect.Top + d; + Details := ThemeServices.GetElementDetails(twCloseButtonNormal); + ThemeServices.DrawElement(ACanvas.Handle, Details, BtnRect); + + DrawRect.Top := BtnRect.Bottom; + BtnRect := DrawRect; + Inc(BtnRect.Top); + BtnRect.Bottom := BtnRect.Top + d; + Details := ThemeServices.GetElementDetails(twRestoreButtonNormal); + ThemeServices.DrawElement(ACanvas.Handle, Details, BtnRect); + + DrawRect.Top := BtnRect.Bottom; + InflateRect(DrawRect, 0, -4); + d := (DrawRect.Right + DrawRect.Left) div 2; + + ACanvas.Pen.Color := clBtnHighlight; + ACanvas.MoveTo(d - 1, DrawRect.Top); + ACanvas.LineTo(d - 1, DrawRect.Bottom); + + ACanvas.Pen.Color := clBtnShadow; + ACanvas.MoveTo(d, DrawRect.Top); + ACanvas.LineTo(d, DrawRect.Bottom); + end; + end; +end; + procedure TLazDockTree.CreateDockLayoutHelperControls(Zone: TLazDockZone); var ParentPages: TLazDockPages; @@ -658,6 +736,15 @@ begin CreateDockLayoutHelperControls(Zone.NextSibling as TLazDockZone); end; +procedure TLazDockTree.AdjustDockRect(AControl: TControl; var ARect: TRect); +begin + // offset one of the borders of control rect in order to get space for frame + case AControl.DockOrientation of + doHorizontal: Inc(ARect.Top, DefaultDockGrabberSize); + doVertical : Inc(ARect.Left, DefaultDockGrabberSize); + end; +end; + procedure TLazDockTree.AnchorDockLayout(Zone: TLazDockZone); // setup all anchors between all docked controls and helper controls var @@ -771,6 +858,16 @@ procedure TLazDockTree.InsertControl(AControl: TControl; InsertAt: TAlign; +-Zone2 (Form1,doNoOrient) +-Zone3 (Form2,doNoOrient) } + + procedure PrepareControlForResize(AControl: TControl); inline; + begin + AControl.Align := alNone; + AControl.Anchors := [akLeft, akTop]; + AControl.AnchorSide[akLeft].Control := nil; + AControl.AnchorSide[akTop].Control := nil; + AControl.AutoSize := False; + end; + const SplitterWidth = 5; SplitterHeight = 5; @@ -803,14 +900,22 @@ begin if (DropZone=RootZone) and (RootZone.FirstChild=nil) then begin // this is the first child debugln('TLazDockTree.InsertControl First Child'); - RootZone.Orientation:=NewOrientation; + RootZone.Orientation := NewOrientation; RootZone.AddAsFirstChild(NewZone); + AControl.DockOrientation := NewOrientation; if not AControl.Visible then - DockSite.Visible:=false; - DockSite.BoundsRect:=AControl.BoundsRect; - AControl.Parent:=DockSite; + DockSite.Visible := False; + + NewBounds := AControl.BoundsRect; + AdjustDockRect(AControl, NewBounds); + DockSite.BoundsRect := NewBounds; + + PrepareControlForResize(AControl); + AControl.BoundsRect := NewBounds; + AControl.Parent := DockSite; + if AControl.Visible then - DockSite.Visible:=true; + DockSite.Visible := True; end else begin // there are already other childs @@ -862,24 +967,20 @@ begin // break anchors and resize DockSite BreakAnchors(RootZone); - NewBounds:=DockSite.BoundsRect; + NewBounds := DockSite.BoundsRect; case InsertAt of - alLeft: dec(NewBounds.Left,SplitterWidth+AControl.Width); - alRight: inc(NewBounds.Right,SplitterWidth+AControl.Width); - alTop: dec(NewBounds.Top,SplitterHeight+AControl.Height); - alBottom:inc(NewBounds.Bottom,SplitterHeight+AControl.Height); + alLeft: dec(NewBounds.Left,SplitterWidth+AControl.Width); + alRight: inc(NewBounds.Right,SplitterWidth+AControl.Width); + alTop: dec(NewBounds.Top,SplitterHeight+AControl.Height); + alBottom:inc(NewBounds.Bottom,SplitterHeight+AControl.Height); else // no change end; - DockSite.BoundsRect:=NewBounds; + DockSite.BoundsRect := NewBounds; // add AControl to DockSite - AControl.Visible:=false; - AControl.Parent:=nil; - AControl.Align:=alNone; - AControl.Anchors:=[akLeft,akTop]; - AControl.AnchorSide[akLeft].Control:=nil; - AControl.AnchorSide[akTop].Control:=nil; - AControl.AutoSize:=false; + AControl.Visible := False; + AControl.Parent := nil; + PrepareControlForResize(AControl); // resize control RaiseGDBException('TLazDockTree.InsertControl TODO resize control'); if NewOrientation in [doHorizontal,doVertical] then begin @@ -892,7 +993,8 @@ begin AControl.Width:=ASibling.Width; end; end; - AControl.Parent:=NewZone.GetParentControl; + AControl.DockOrientation := NewOrientation; + AControl.Parent := NewZone.GetParentControl; // Build dock layout (anchors, splitters, pages) BuildDockLayout(RootZone as TLazDockZone); @@ -1022,6 +1124,41 @@ begin end; end; +procedure TLazDockTree.PaintSite(DC: HDC); +var + ACanvas: TCanvas; + ARect: TRect; + i: integer; +begin + // paint bounds for each control and close button + if DockSite.ControlCount > 0 then + begin + ACanvas := TCanvas.Create; + ACanvas.Handle := DC; + try + for i := 0 to DockSite.ControlCount - 1 do + begin + ARect := DockSite.Controls[i].BoundsRect; + case DockSite.Controls[i].DockOrientation of + doHorizontal: + begin + ARect.Bottom := ARect.Top; + Dec(ARect.Top, DefaultDockGrabberSize); + end; + doVertical: + begin + ARect.Right := ARect.Left; + Dec(ARect.Left, DefaultDockGrabberSize); + end; + end; + PaintDockFrame(ACanvas, DockSite.Controls[i], ARect); + end; + finally + ACanvas.Free; + end; + end; +end; + { TLazDockZone } destructor TLazDockZone.Destroy; @@ -2219,4 +2356,7 @@ begin FindCandidate(Self,0); end; +initialization + DefaultDockTreeClass := TLazDockTree; + end.