Componentes.Terceros.DevExp.../internal/x.42/1/ExpressDocking Library/Sources/dxDockPanel.pas
2009-03-03 12:07:07 +00:00

540 lines
17 KiB
ObjectPascal

{*******************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressDocking }
{ }
{ Copyright (c) 2002-2009 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSDOCKING AND ALL ACCOMPANYING }
{ VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{*******************************************************************}
unit dxDockPanel;
{$I cxVer.inc}
interface
uses
Menus, Windows, Graphics, Classes, Controls, ExtCtrls, Messages, Forms,
dxCore, dxDockConsts, dxDockControl;
type
TdxDockPanel = class(TdxCustomDockControl)
private
FShowSingleTab: Boolean;
FTabIsDown: Boolean;
FTabPosition: TdxTabContainerTabsPosition;
FTabsRect: TRect;
FTabRect: TRect;
procedure SetShowSingleTab(const Value: Boolean);
procedure SetTabPosition(const Value: TdxTabContainerTabsPosition);
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
protected
function GetClientRect: TRect; override;
procedure SetParent(AParent: TWinControl); override;
procedure ValidateInsert(AComponent: TComponent); override;
function IsDockPanel: Boolean; override;
// Activation
procedure CheckActiveDockControl; override;
procedure DoActivate; override;
// Docking
procedure UpdateControlDockZones(AControl: TdxCustomDockControl; AZoneWidth: Integer); override;
// Site layout
procedure CreateLayout(AControl: TdxCustomDockControl; AType: TdxDockingType; Index: Integer); override;
// SideContainer site
function CanAcceptSideContainerItems(AContainer: TdxSideContainerDockSite): Boolean; override;
// TabContainer site
procedure AssignTabContainerSiteProperies(ASite: TdxTabContainerDockSite); override;
function CanAcceptTabContainerItems(AContainer: TdxTabContainerDockSite): Boolean; override;
// Painting
procedure CalculateNC(var ARect: TRect); override;
procedure InvalidateCaptionArea; override;
procedure NCPaint(ACanvas: TCanvas); override;
function NeedInvalidateCaptionArea: Boolean; override;
function IsTabPoint(pt: TPoint): Boolean;
function GetTabPosition: TdxTabContainerTabsPosition;
function HasBorder: Boolean; override;
function HasCaption: Boolean; override;
function HasTabs: Boolean; override;
property TabRect: TRect read FTabRect;
property TabsRect: TRect read FTabsRect;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function CanActive: Boolean; override;
function CanAutoHide: Boolean; override;
function CanDock: Boolean; override;
function CanDockHost(AControl: TdxCustomDockControl; AType: TdxDockingType): Boolean; override;
function CanMaximize: Boolean; override;
published
property AllowDockClients;
property AllowFloating;
property AllowDock;
property AutoHide;
property Caption;
property CaptionButtons;
property Dockable;
property ImageIndex;
property ShowCaption;
property ShowSingleTab: Boolean read FShowSingleTab write SetShowSingleTab default False;
property TabPosition: TdxTabContainerTabsPosition read FTabPosition write SetTabPosition default tctpBottom;
property OnActivate;
property OnAutoHideChanged;
property OnAutoHideChanging;
property OnCanResize;
property OnClose;
property OnCloseQuery;
property OnCreateFloatSite;
property OnCreateSideContainer;
property OnCreateTabContainer;
property OnCustomDrawDockingSelection;
property OnCustomDrawResizingSelection;
property OnDock;
property OnDocking;
property OnEndDocking;
property OnEndResizing;
property OnGetAutoHidePosition;
property OnLayoutChanged;
property OnMakeFloating;
property OnResize;
property OnResizing;
property OnRestoreDockPosition;
property OnStartDocking;
property OnStartResizing;
property OnStoreDockPosition;
property OnUnDock;
property OnUpdateDockZones;
property OnUpdateResizeZones;
end;
implementation
uses
Types, SysUtils, dxDockZones, cxGraphics, cxGeometry;
type
TdxCustomDockControlAccess = class(TdxCustomDockControl);
TdxDockingControllerAccess = class(TdxDockingController);
{ TdxDockPanel }
constructor TdxDockPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ShowSingleTab := False;
TabPosition := tctpBottom;
UseDoubleBuffer := True;
SetBounds(0, 0, 185, 140);
end;
destructor TdxDockPanel.Destroy;
begin
inherited;
end;
function TdxDockPanel.CanActive: Boolean;
begin
Result := True;
end;
function TdxDockPanel.CanAutoHide: Boolean;
begin
Result := IsLoading or
((AutoHideHostSite <> nil) and ((AutoHideControl = nil) or (AutoHideControl = Self)));
end;
function TdxDockPanel.CanDock: Boolean;
begin
Result := True;
end;
function TdxDockPanel.CanDockHost(AControl: TdxCustomDockControl; AType: TdxDockingType): Boolean;
var
ACanDockHost: Boolean;
begin
if Container <> nil then
begin
ACanDockHost := Container.CanContainerDockHost(AType);
if Container is TdxTabContainerDockSite then
begin
if doSideContainerCanInTabContainer in ControllerOptions then
ACanDockHost := ACanDockHost or (AType in [dtLeft, dtRight, dtTop, dtBottom]);
end;
if Container is TdxSideContainerDockSite then
begin
if doTabContainerCanInSideContainer in ControllerOptions then
ACanDockHost := ACanDockHost or (AType in [dtClient]);
if doSideContainerCanInSideContainer in ControllerOptions then
ACanDockHost := ACanDockHost or (AType in [dtLeft, dtRight, dtTop, dtBottom]);
end;
end
else
ACanDockHost := (AType in [dtClient, dtLeft, dtRight, dtTop, dtBottom]);
Result := inherited CanDockHost(AControl, AType) and ACanDockHost;;
end;
function TdxDockPanel.CanMaximize: Boolean;
begin
Result := not AutoHide and (SideContainer <> nil) and (SideContainer.ValidChildCount > 1);
end;
procedure TdxDockPanel.CheckActiveDockControl;
begin
if Active and not IsDesigning and CanFocusEx and not dxDockingController.IsDockControlFocusedEx(Self) then
DoActivate;
end;
procedure TdxDockPanel.DoActivate;
var
AParentForm: TCustomForm;
begin
AParentForm := Forms.GetParentForm(Self);
if (AParentForm <> nil) then
begin
AParentForm.ActiveControl := Self;
if AParentForm.ActiveControl = Self then
SelectFirst;
end
else
SetFocus;
end;
function TdxDockPanel.GetClientRect: TRect;
begin
if HandleAllocated then
Result := inherited GetClientRect
else
Result := cxEmptyRect;
if TdxDockingControllerAccess(Controller).IsUpdateNCLocked and
((Height = 0) or (Width = 0) or (cxRectWidth(Result) = 0) or (cxRectHeight(Result) = 0)) then
Result := Rect(0, 0, OriginalWidth, OriginalHeight);
end;
procedure TdxDockPanel.SetParent(AParent: TWinControl);
var
ALeft, ATop: Integer;
APrevParent: TWinControl;
I: TdxDockingType;
begin
if (UpdateLayoutLock = 0) and not IsDestroying and
((AParent = nil) or not (csLoading in AParent.ComponentState)) then
begin
if IsDesigning and (AParent <> nil) then
ValidateContainer(AParent);
if AParent is TdxCustomDockControl then
for I := Low(TdxDockingType) to High(TdxDockingType) do
begin
if TdxCustomDockControl(AParent).CanDockHost(Self, I) then
begin
DockTo(AParent as TdxCustomDockControl, I, -1);
Exit;
end;
end;
// else Make Float
APrevParent := Parent;
ALeft := Left;
ATop := Top;
if AParent = nil then
AParent := APrevParent;
if AParent <> nil then
begin
ALeft := AParent.ClientOrigin.X + ALeft;
ATop := AParent.ClientOrigin.Y + ATop;
end;
MakeFloating(ALeft, ATop);
end
else
begin
if (AParent <> nil) and
not ((AParent is TdxCustomDockControl) or (AutoHide and (AParent is TdxDockSiteAutoHideContainer))) then
raise EdxException.CreateFmt(sdxInvalidParent, [ClassName])
else
inherited SetParent(AParent);
end
end;
procedure TdxDockPanel.ValidateInsert(AComponent: TComponent);
begin
if AComponent is TdxCustomDockControl then
raise EdxException.CreateFmt(sdxInvalidPanelChild, [AComponent.ClassName]);
end;
function TdxDockPanel.IsDockPanel: Boolean;
begin
Result := True;
end;
procedure TdxDockPanel.UpdateControlDockZones(AControl: TdxCustomDockControl; AZoneWidth: Integer);
begin
if not (doUseCaptionAreaToClientDocking in ControllerOptions) then
begin
if (TabContainer <> nil) and TdxTabContainerZone.ValidateDockZone(Self, AControl) then
DockZones.Insert(0, TdxTabContainerZone.Create(TabContainer))
else
if TdxDockPanelClientZone.ValidateDockZone(Self, AControl) then
DockZones.Insert(0, TdxDockPanelClientZone.Create(Self));
end;
inherited;
if doUseCaptionAreaToClientDocking in ControllerOptions then
begin
if (TabContainer <> nil) and TdxTabContainerCaptionZone.ValidateDockZone(Self, AControl) then
DockZones.Insert(0, TdxTabContainerCaptionZone.Create(TabContainer))
else
if TdxDockPanelCaptionClientZone.ValidateDockZone(Self, AControl) then
DockZones.Insert(0, TdxDockPanelCaptionClientZone.Create(Self));
end;
end;
procedure TdxDockPanel.CreateLayout(AControl: TdxCustomDockControl;
AType: TdxDockingType; Index: Integer);
begin
if (Container <> nil) and Container.CanContainerDockHost(AType) then
CreateContainerLayout(Container, AControl, AType, DockIndex)
else
case AType of
dtClient:
CreateTabContainerLayout(AControl, AType, Index);
dtLeft, dtRight, dtTop, dtBottom:
CreateSideContainerLayout(AControl, AType, Index);
else
Assert(False, Format(sdxInternalErrorCreateLayout, [TdxContainerDockSite.ClassName]));
end;
end;
function TdxDockPanel.CanAcceptSideContainerItems(AContainer: TdxSideContainerDockSite): Boolean;
begin
Result := True;
end;
procedure TdxDockPanel.AssignTabContainerSiteProperies(ASite: TdxTabContainerDockSite);
begin
inherited;
if ShowSingleTab then
ASite.TabsPosition := TabPosition;
end;
function TdxDockPanel.CanAcceptTabContainerItems(AContainer: TdxTabContainerDockSite): Boolean;
begin
Result := True;
end;
procedure TdxDockPanel.CalculateNC(var ARect: TRect);
begin
inherited;
FTabsRect.Left := ARect.Left;
FTabsRect.Right := ARect.Right;
if GetTabPosition = tctpTop then
begin
FTabsRect.Top := ARect.Top;
FTabsRect.Bottom := FTabsRect.Top + Painter.GetTabsHeight;
if HasTabs then
ARect.Top := FTabsRect.Bottom;
end
else
begin
FTabsRect.Bottom := ARect.Bottom;
FTabsRect.Top := FTabsRect.Bottom - Painter.GetTabsHeight;
if FTabsRect.Top < ARect.Top then
begin
FTabsRect.Top := ARect.Top;
FTabsRect.Bottom := FTabsRect.Top + Painter.GetTabsHeight;
end;
if HasTabs then
ARect.Bottom := FTabsRect.Top;
end;
FTabRect.Left := FTabsRect.Left + Painter.GetTabHorizInterval;
FTabRect.Top := FTabsRect.Top + Painter.GetTabVertInterval;
if GetTabPosition = tctpBottom then
Inc(FTabRect.Top, Painter.GetTabVertInterval);
FTabRect.Bottom := FTabsRect.Bottom - Painter.GetTabVertInterval;
if GetTabPosition = tctpTop then
Dec(FTabRect.Bottom, Painter.GetTabVertInterval);
FTabRect.Right := FTabRect.Left + GetTabWidth(Canvas);
if FTabRect.Right > FTabsRect.Right - Painter.GetTabHorizInterval then
FTabRect.Right := FTabsRect.Right - Painter.GetTabHorizInterval;
end;
procedure TdxDockPanel.InvalidateCaptionArea;
begin
if HasTabs then
InvalidateNC(True)
else
inherited;
end;
procedure TdxDockPanel.NCPaint(ACanvas: TCanvas);
begin
inherited;
if HasTabs then
begin
Painter.DrawTabs(ACanvas, TabsRect, TabRect, TabPosition);
Painter.DrawTab(ACanvas, Self, TabRect, True, TabPosition);
end;
end;
function TdxDockPanel.NeedInvalidateCaptionArea: Boolean;
begin
Result := inherited NeedInvalidateCaptionArea or HasTabs;
end;
function TdxDockPanel.IsTabPoint(pt: TPoint): Boolean;
begin
Result := HasTabs and PtInRect(TabRect, ClientToWindow(pt));
end;
function TdxDockPanel.GetTabPosition: TdxTabContainerTabsPosition;
begin
if ShowSingleTab then
Result := TabPosition
else
if Controller.DefaultTabContainerSiteProperties(ParentForm) <> nil then
Result := Controller.DefaultTabContainerSiteProperties(ParentForm).TabsPosition
else
Result := tctpBottom;
end;
function TdxDockPanel.HasBorder: Boolean;
begin
Result := (FloatDockSite = nil) and
(AutoHide or
((TabContainer = nil) or ((TabContainer.ValidChildCount < 2) and not TabContainer.AutoHide)) and
((ParentDockControl = nil) or TdxCustomDockControlAccess(ParentDockControl).CanUndock(Self))
);
end;
function TdxDockPanel.HasCaption: Boolean;
begin
Result := ShowCaption and HasBorder;
end;
function TdxDockPanel.HasTabs: Boolean;
begin
Result := ShowSingleTab and ((TabContainer = nil) or (TabContainer.ValidChildCount = 1));
end;
procedure TdxDockPanel.SetShowSingleTab(const Value: Boolean);
begin
if FShowSingleTab <> Value then
begin
FShowSingleTab := Value;
NCChanged;
end;
end;
procedure TdxDockPanel.SetTabPosition(const Value: TdxTabContainerTabsPosition);
begin
if FTabPosition <> Value then
begin
FTabPosition := Value;
NCChanged;
end;
end;
procedure TdxDockPanel.WMLButtonDblClk(var Message: TWMLButtonDblClk);
var
pt: TPoint;
begin
inherited;
if Message.Result = 0 then
begin
if not IsDesigning and (doDblClickDocking in ControllerOptions) and
not AutoHide and IsTabPoint(CursorPoint) then
begin
pt := ClientToScreen(CursorPoint);
DoStartDocking(pt);
if FloatDockSite = nil then
MakeFloating
else
RestoreDockPosition(ClientToWindow(pt));
DoEndDocking(pt);
Message.Result := 1;
end;
end;
end;
procedure TdxDockPanel.WMLButtonDown(var Message: TWMLButtonDown);
begin
inherited;
if Message.Result = 0 then
begin
FTabIsDown := IsTabPoint(SourcePoint);
if FTabIsDown then
CaptureMouse;
Message.Result := 1;
end;
end;
procedure TdxDockPanel.WMLButtonUp(var Message: TWMLButtonUp);
begin
inherited;
if Message.Result = 0 then
begin
if FTabIsDown then
begin
ReleaseMouse;
FTabIsDown := False;
Message.Result := 1;
end;
end;
end;
procedure TdxDockPanel.WMMouseMove(var Message: TWMMouseMove);
begin
inherited;
if (Message.Result = 0) and (FloatFormActive or ParentFormActive or IsDesigning) then
begin
if FTabIsDown and ((IsDesigning and
((Abs(CursorPoint.X - SourcePoint.X) > 3) or
(Abs(CursorPoint.Y - SourcePoint.Y) > 3))) or
not IsTabPoint(CursorPoint)) then
begin
ReleaseMouse;
FTabIsDown := False;
StartDocking(ClientToScreen(SourcePoint));
Message.Result := 1;
end;
end;
end;
initialization
RegisterClasses([TdxDockPanel]);
end.