git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jvcl@19 7f62d464-2af8-f54e-996c-e91b33f51cbe
5145 lines
166 KiB
ObjectPascal
5145 lines
166 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvDockControlForm.pas, released on 2003-12-31.
|
|
|
|
The Initial Developer of the Original Code is luxiaoban.
|
|
Portions created by luxiaoban are Copyright (C) 2002,2003 luxiaoban.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
2005-02-08 - Warren Postma - TJvDockServer.CustomPanel.
|
|
|
|
Last Modified: 2005-02-08
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.delphi-jedi.org
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvDockControlForm.pas 12579 2009-10-26 19:59:53Z ahuser $
|
|
|
|
{ Changes:
|
|
|
|
2005-02-08 WP: Added TJvDockServer.CustomDock panel (new property),
|
|
and new event TJvDockServer.OnCustomPanel to get
|
|
a custom parent control (such as the form's center area) for the
|
|
CustomPanel. Previously you could only dock at the edges. Created a
|
|
splitter object (to avoid possible access violations) but the splitter
|
|
control is hidden and never used for this custom panel. Several
|
|
changes were made to the VID dock style also to make this custom
|
|
panel more useful,allowing an "tabbed MDI" style application.
|
|
}
|
|
|
|
unit JvDockControlForm;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
Windows, Messages, Classes, Graphics, Controls, Forms, Menus,
|
|
ExtCtrls, ComCtrls,
|
|
JvComponentBase, JvComponent, JvAppStorage, JvConsts,
|
|
JvDockTree, JvDockSupportClass, JvDockSupportControl, JvDockAdvTree;
|
|
|
|
const
|
|
JvDockPositionCount = 5;
|
|
|
|
JvDockState_Unknown = 0;
|
|
JvDockState_Docking = 1;
|
|
JvDockState_Floating = 2;
|
|
|
|
type
|
|
TJvDockSplitterSize = 0..32767;
|
|
|
|
TJvDockBaseControl = class;
|
|
TJvDockServer = class;
|
|
TJvDockClient = class;
|
|
TJvDockConjoinPanel = class;
|
|
TJvDockTabPageControl = class;
|
|
TJvDockConjoinHostForm = class;
|
|
TJvDockTabHostForm = class;
|
|
|
|
TJvDockSplitter = class(TJvDockCustomPanelSplitter)
|
|
private
|
|
FDockServer: TJvDockServer;
|
|
function GetSplitterIndex: Integer;
|
|
protected
|
|
function FindControl: TControl; override;
|
|
property DockServer: TJvDockServer read FDockServer write FDockServer;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
property SplitterIndex: Integer read GetSplitterIndex;
|
|
end;
|
|
|
|
TJvDockSetDockPanelSizeFrom = (sdfDockPanel, sdfClient);
|
|
|
|
TJvDockPanel = class(TJvDockCustomPanel)
|
|
private
|
|
FDockServer: TJvDockServer;
|
|
FCustomFlag: Boolean; // Set only if custom area! {NEW}
|
|
function GetPanelIndex: Integer;
|
|
procedure SetDockServer(ADockServer: TJvDockServer);
|
|
protected
|
|
function CreateDockManager: IDockManager; override;
|
|
procedure AddDockServer(ADockServer: TJvDockServer); virtual;
|
|
procedure RemoveDockServer(ADockServer: TJvDockServer); virtual;
|
|
procedure ReloadDockedControl(const AControlName: string;
|
|
var AControl: TControl); override;
|
|
procedure CustomStartDock(var Source: TJvDockDragDockObject); override;
|
|
procedure CustomGetSiteInfo(Source: TJvDockDragDockObject; Client: TControl; var InfluenceRect: TRect;
|
|
MousePos: TPoint; var CanDock: Boolean); override;
|
|
procedure CustomDockOver(Source: TJvDockDragDockObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean); override;
|
|
procedure CustomPositionDockRect(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
procedure CustomDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
procedure CustomEndDock(Target: TObject; X, Y: Integer); override;
|
|
function CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
procedure Resize; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
|
|
|
|
procedure ShowDockPanel(MakeVisible: Boolean; Client: TControl;
|
|
PanelSizeFrom: TJvDockSetDockPanelSizeFrom = sdfClient); virtual;
|
|
procedure ResetPosition;
|
|
// GetDockedControls: NEW! -WPostma.
|
|
// base class doesn't have this capability.
|
|
// see TJvDockAdvPanel for override that implements this!
|
|
procedure GetDockedControls(WinControls: TList); virtual;
|
|
|
|
property PanelIndex: Integer read GetPanelIndex;
|
|
property DockServer: TJvDockServer read FDockServer write SetDockServer;
|
|
property CustomFlag: Boolean read FCustomFlag write FCustomFlag; // Set only if custom area! {NEW}
|
|
end;
|
|
|
|
TJvDockAdvPanel = class(TJvDockPanel)
|
|
private
|
|
procedure CMUnDockClient(var Msg: TCMUnDockClient); message CM_UNDOCKCLIENT;
|
|
protected
|
|
procedure CustomDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
function CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
public
|
|
procedure GetDockedControls(WinControls: TList); override;
|
|
procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
|
|
end;
|
|
|
|
TJvDockPanelClass = class of TJvDockPanel;
|
|
TJvDockSplitterClass = class of TJvDockSplitter;
|
|
TJvDockConjoinPanelClass = class of TJvDockConjoinPanel;
|
|
TJvDockTabClass = class of TJvDockTabPageControl;
|
|
|
|
{ Maintained by a TJvDockServer; TJvDockServer ensures that FDockServer is
|
|
assigned. FSplitter may be nil }
|
|
TJvDockSplitterStyle = class(TPersistent)
|
|
private
|
|
FSplitter: TJvDockSplitter;
|
|
FDockServer: TJvDockServer;
|
|
FColor: TColor;
|
|
FCursor: TCursor;
|
|
FParentColor: Boolean;
|
|
FResizeStyle: TResizeStyle;
|
|
FSize: TJvDockSplitterSize;
|
|
FMinSize: TJvDockSplitterSize;
|
|
procedure SetColor(const Value: TColor);
|
|
procedure SetCursor(const Value: TCursor);
|
|
procedure SetParentColor(const Value: Boolean);
|
|
procedure SetResizeStyle(const Value: TResizeStyle);
|
|
procedure SetSize(const Value: TJvDockSplitterSize);
|
|
procedure SetMinSize(const Value: TJvDockSplitterSize);
|
|
protected
|
|
procedure AssignTo(Dest: TPersistent); override;
|
|
procedure AssignToSplitter(Dest: TJvDockSplitter);
|
|
procedure SetSplitterStyle;
|
|
property Splitter: TJvDockSplitter read FSplitter write FSplitter;
|
|
public
|
|
constructor Create(ASplitter: TJvDockSplitter; ACursor: TCursor); virtual;
|
|
procedure Assign(Source: TPersistent); override;
|
|
published
|
|
property Color: TColor read FColor write SetColor default clBtnFace;
|
|
property Cursor: TCursor read FCursor write SetCursor;
|
|
property ParentColor: Boolean read FParentColor write SetParentColor default True;
|
|
property ResizeStyle: TResizeStyle read FResizeStyle write SetResizeStyle default rsPattern;
|
|
property Size: TJvDockSplitterSize read FSize write SetSize default 3;
|
|
property MinSize: TJvDockSplitterSize read FMinSize write SetMinSize default 30;
|
|
end;
|
|
|
|
TJvDockBasicStyle = class;
|
|
|
|
TJvDockBasicStyle = class(TJvDockObservableStyle)
|
|
private
|
|
FDockPanelClass: TJvDockPanelClass;
|
|
FDockSplitterClass: TJvDockSplitterClass;
|
|
FConjoinPanelClass: TJvDockConjoinPanelClass;
|
|
FTabDockClass: TJvDockTabClass;
|
|
FDockPanelTreeClass: TJvDockTreeClass;
|
|
FDockPanelZoneClass: TJvDockZoneClass;
|
|
FConjoinPanelTreeClass: TJvDockTreeClass;
|
|
FConjoinPanelZoneClass: TJvDockZoneClass;
|
|
FDockBaseControls: TList;
|
|
function GetDockBaseControlCount: Integer;
|
|
function GetDockBaseControl(Index: Integer): TJvDockBaseControl;
|
|
protected
|
|
procedure FormStartDock(DockClient: TJvDockClient; var Source: TJvDockDragDockObject); virtual;
|
|
procedure FormGetSiteInfo(Source: TJvDockDragDockObject; DockClient: TJvDockClient; Client: TControl;
|
|
var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean); virtual;
|
|
procedure FormDockOver(DockClient: TJvDockClient; Source: TJvDockDragDockObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean); virtual;
|
|
procedure FormPositionDockRect(DockClient: TJvDockClient; Source: TJvDockDragDockObject); virtual;
|
|
procedure FormDockDrop(DockClient: TJvDockClient; Source: TJvDockDragDockObject; X, Y: Integer); virtual;
|
|
procedure FormEndDock(DockClient: TJvDockClient; Target: TObject; X, Y: Integer); virtual;
|
|
function FormUnDock(DockClient: TJvDockClient; NewTarget: TWinControl; Client: TControl): Boolean; virtual;
|
|
procedure FormGetDockEdge(DockClient: TJvDockClient; Source: TJvDockDragDockObject;
|
|
MousePos: TPoint; var DropAlign: TAlign); virtual;
|
|
|
|
procedure SetDockBaseControl(IsCreate: Boolean; DockBaseControl: TJvDockBaseControl); virtual;
|
|
function DockServerWindowProc(DockServer: TJvDockServer; var Msg: TMessage): Boolean; virtual;
|
|
function DockClientWindowProc(DockClient: TJvDockClient; var Msg: TMessage): Boolean; virtual;
|
|
procedure AddDockBaseControl(ADockBaseControl: TJvDockBaseControl); virtual;
|
|
procedure RemoveDockBaseControl(ADockBaseControl: TJvDockBaseControl); virtual;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
function CanSetEnableDocked(ADockBaseControl: TJvDockBaseControl): Boolean; virtual;
|
|
function CanSetLeftDocked(ADockBaseControl: TJvDockBaseControl): Boolean; virtual;
|
|
function CanSetRightDocked(ADockBaseControl: TJvDockBaseControl): Boolean; virtual;
|
|
function CanSetTopDocked(ADockBaseControl: TJvDockBaseControl): Boolean; virtual;
|
|
function CanSetBottomDocked(ADockBaseControl: TJvDockBaseControl): Boolean; virtual;
|
|
function CanSetEachOtherDocked(ADockBaseControl: TJvDockBaseControl): Boolean; virtual;
|
|
|
|
procedure ResetCursor(Source: TJvDockDragDockObject); virtual;
|
|
|
|
function GetDockState(DockClient: TJvDockClient): Integer; virtual;
|
|
|
|
procedure DoShowDockForm(DockWindow: TWinControl); virtual;
|
|
procedure DoHideDockForm(DockWindow: TWinControl); virtual;
|
|
|
|
procedure ShowDockForm(ADockClient: TJvDockClient); virtual;
|
|
procedure HideDockForm(ADockClient: TJvDockClient); virtual;
|
|
function GetDockFormVisible(ADockClient: TJvDockClient): Boolean; virtual;
|
|
|
|
property DockBaseControlCount: Integer read GetDockBaseControlCount;
|
|
property DockBaseControl[Index: Integer]: TJvDockBaseControl read GetDockBaseControl;
|
|
|
|
procedure RestoreClient(DockClient: TJvDockClient); virtual;
|
|
property DockPanelClass: TJvDockPanelClass read FDockPanelClass write FDockPanelClass;
|
|
property DockSplitterClass: TJvDockSplitterClass read FDockSplitterClass write FDockSplitterClass;
|
|
property ConjoinPanelClass: TJvDockConjoinPanelClass read FConjoinPanelClass write FConjoinPanelClass;
|
|
property TabDockClass: TJvDockTabClass read FTabDockClass write FTabDockClass;
|
|
property DockPanelTreeClass: TJvDockTreeClass read FDockPanelTreeClass write FDockPanelTreeClass;
|
|
property DockPanelZoneClass: TJvDockZoneClass read FDockPanelZoneClass write FDockPanelZoneClass;
|
|
property ConjoinPanelTreeClass: TJvDockTreeClass read FConjoinPanelTreeClass write FConjoinPanelTreeClass;
|
|
property ConjoinPanelZoneClass: TJvDockZoneClass read FConjoinPanelZoneClass write FConjoinPanelZoneClass;
|
|
end;
|
|
|
|
TJvDockAdvStyle = class(TJvDockBasicStyle)
|
|
protected
|
|
function DockClientWindowProc(DockClient: TJvDockClient; var Msg: TMessage): Boolean; override;
|
|
end;
|
|
|
|
TJvDockBaseControl = class(TJvComponent)
|
|
private
|
|
FEnableDock: Boolean;
|
|
FLeftDock: Boolean; { Can the parent form be docked into the Left dock? }
|
|
FTopDock: Boolean; { Can the parent form be docked into the Top dock? }
|
|
FRightDock: Boolean; { Can the parent form be docked into the Right dock? }
|
|
FBottomDock: Boolean; { Can the parent form be docked into the Bottom dock? }
|
|
FCustomDock: Boolean; {NEW! Can the parent form be docked into the Custom (center window) dock area? }
|
|
FEachOtherDock: Boolean;
|
|
FDockStyle: TJvDockBasicStyle;
|
|
FOldOnClose: TCloseEvent;
|
|
FOldOnCreate: TNotifyEvent;
|
|
FParentForm: TForm;
|
|
FOldWindowProc: TWndMethod;
|
|
procedure SetDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
protected
|
|
procedure SetParentComponent(Value: TComponent); override;
|
|
|
|
function CanSetEnableDocked: Boolean; virtual;
|
|
function CanSetLeftDocked: Boolean; virtual;
|
|
function CanSetRightDocked: Boolean; virtual;
|
|
function CanSetTopDocked: Boolean; virtual;
|
|
function CanSetBottomDocked: Boolean; virtual;
|
|
function CanSetEachOtherDocked: Boolean; virtual;
|
|
|
|
procedure DoFormOnClose(Sender: TObject; var Action: TCloseAction); virtual;
|
|
procedure DoFormOnCreate(Sender: TObject); virtual;
|
|
|
|
procedure SetBottomDock(const Value: Boolean); virtual;
|
|
procedure SetEachOtherDock(const Value: Boolean); virtual;
|
|
procedure SetEnableDock(const Value: Boolean); virtual;
|
|
procedure SetLeftDock(const Value: Boolean); virtual;
|
|
procedure SetRightDock(const Value: Boolean); virtual;
|
|
procedure SetTopDock(const Value: Boolean); virtual;
|
|
|
|
procedure AddDockStyle(ADockStyle: TJvDockBasicStyle); virtual;
|
|
procedure RemoveDockStyle(ADockStyle: TJvDockBasicStyle); virtual;
|
|
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure WindowProc(var Msg: TMessage); virtual;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
{ Owner of this component }
|
|
property ParentForm: TForm read FParentForm;
|
|
property EnableDock: Boolean read FEnableDock write SetEnableDock default True;
|
|
property LeftDock: Boolean read FLeftDock write SetLeftDock default True;
|
|
property TopDock: Boolean read FTopDock write SetTopDock default True;
|
|
property RightDock: Boolean read FRightDock write SetRightDock default True;
|
|
property BottomDock: Boolean read FBottomDock write SetBottomDock default True;
|
|
property EachOtherDock: Boolean read FEachOtherDock write SetEachOtherDock default True;
|
|
property CustomDock: Boolean read FCustomDock write FCustomDock default True; {NEW!}
|
|
property DockStyle: TJvDockBasicStyle read FDockStyle write SetDockStyle;
|
|
end;
|
|
|
|
TJvDockCustomPanelEvent = procedure(Sender: TJvDockServer;
|
|
var AParent: TWinControl; var Align: TAlign) of object; {NEW!}
|
|
TJvDockCheckDockableEvent = procedure(DockClient: TJvDockClient; DockForm: TForm;
|
|
DockServer: TJvDockServer; DockPanel: TJvDockPanel; var CanDock: Boolean) of object; {NEW!}
|
|
TJvDockTabHostFormCreatedEvent = procedure(DockClient: TJvDockClient;
|
|
TabHost: TJvDockTabHostForm) of object;
|
|
|
|
TJvDockGetClientAlignSizeEvent = procedure(Align: TAlign; var Value: Integer) of object;
|
|
TJvDockFinishSetDockPanelSizeEvent = procedure(DockPanel: TJvDockPanel) of object;
|
|
|
|
{
|
|
|
|
TJvDockServer is the Creator of 4 panels and 4 splitters that are placed on
|
|
the form that contains the TJvDockServer. The type of the panels and splitters
|
|
is determined by the DockStyle.
|
|
|
|
o TJvDockServer maintains the panels and splitters. If the dock server is
|
|
destroyed then the panels and splitters are destroyed.
|
|
o If the DockStyle is changed then the panels+splitters are destroyed and
|
|
recreated.
|
|
o If DockStyle is set to nil then the panels+splitters are nil.
|
|
}
|
|
|
|
TJvDockPosition = (dpLeft, dpRight, dpTop, dpBottom, dpCustom); {dpCustom NEW!}
|
|
|
|
TJvDockServer = class(TJvDockBaseControl)
|
|
private
|
|
FDockPanelClass: TJvDockPanelClass;
|
|
FDockPanels: array [TJvDockPosition] of TJvDockPanel;
|
|
FDockSplitterClass: TJvDockSplitterClass;
|
|
FSplitters: array [TJvDockPosition] of TJvDockSplitter;
|
|
FSplitterStyles: array [TJvDockPosition] of TJvDockSplitterStyle;
|
|
FOnCustomPanel: TJvDockCustomPanelEvent; // Self, AParent, Align
|
|
FOnGetClientAlignSize: TJvDockGetClientAlignSizeEvent;
|
|
FOnFinishSetDockPanelSize: TJvDockFinishSetDockPanelSizeEvent;
|
|
FAutoFocusDockedForm: Boolean;
|
|
procedure CreateDockPanelAndSplitter;
|
|
procedure DestroyDockPanelAndSplitter;
|
|
procedure CreateSplitterStyle;
|
|
procedure DestroySplitterStyle;
|
|
procedure SetSplitterStyles;
|
|
procedure DoGetClientAlignControl(Align: TAlign; var Value: Integer);
|
|
function GetDockPanel(DockPosition: TJvDockPosition): TJvDockPanel;
|
|
function GetDockPanelIndex(const Index: Integer): TJvDockPanel;
|
|
function GetDockPanelWithAlign(Index: TAlign): TJvDockPanel;
|
|
function GetDockSplitterWithAlign(Index: TAlign): TJvDockSplitter;
|
|
function GetSplitter(DockPosition: TJvDockPosition): TJvDockSplitter;
|
|
function GetSplitterIndex(const Index: Integer): TJvDockSplitter;
|
|
function GetSplitterStyle(DockPosition: TJvDockPosition): TJvDockSplitterStyle;
|
|
function GetSplitterStyleIndex(const Index: Integer): TJvDockSplitterStyle;
|
|
procedure SetSplitterStyle(DockPosition: TJvDockPosition; ASplitterStyle: TJvDockSplitterStyle);
|
|
procedure SetSplitterStyleIndex(const Index: Integer; ASplitterStyle: TJvDockSplitterStyle);
|
|
protected
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure DoFinishSetDockPanelSize(DockPanel: TJvDockPanel);
|
|
procedure DoFloatDockClients(DockPanel: TJvDockPanel);
|
|
procedure SetBottomDock(const Value: Boolean); override;
|
|
procedure SetEnableDock(const Value: Boolean); override;
|
|
procedure SetLeftDock(const Value: Boolean); override;
|
|
procedure SetRightDock(const Value: Boolean); override;
|
|
procedure SetTopDock(const Value: Boolean); override;
|
|
|
|
procedure AddDockStyle(ADockStyle: TJvDockBasicStyle); override;
|
|
procedure RemoveDockStyle(ADockStyle: TJvDockBasicStyle); override;
|
|
|
|
procedure WMActivate(var Msg: TWMActivate);
|
|
procedure WindowProc(var Msg: TMessage); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function GetClientAlignControl(Align: TAlign): Integer;
|
|
|
|
property DockPanel[DockPosition: TJvDockPosition]: TJvDockPanel read GetDockPanel;
|
|
property Splitter[DockPosition: TJvDockPosition]: TJvDockSplitter read GetSplitter;
|
|
property SplitterStyle[DockPosition: TJvDockPosition]: TJvDockSplitterStyle read GetSplitterStyle write
|
|
SetSplitterStyle;
|
|
|
|
property LeftDockPanel: TJvDockPanel index 0 read GetDockPanelIndex;
|
|
property RightDockPanel: TJvDockPanel index 1 read GetDockPanelIndex;
|
|
property TopDockPanel: TJvDockPanel index 2 read GetDockPanelIndex;
|
|
property BottomDockPanel: TJvDockPanel index 3 read GetDockPanelIndex;
|
|
property CustomDockPanel: TJvDockPanel index 4 read GetDockPanelIndex;
|
|
|
|
property LeftSplitter: TJvDockSplitter index 0 read GetSplitterIndex;
|
|
property RightSplitter: TJvDockSplitter index 1 read GetSplitterIndex;
|
|
property TopSplitter: TJvDockSplitter index 2 read GetSplitterIndex;
|
|
property BottomSplitter: TJvDockSplitter index 3 read GetSplitterIndex;
|
|
|
|
property DockPanelWithAlign[Index: TAlign]: TJvDockPanel read GetDockPanelWithAlign;
|
|
property DockSplitterWithAlign[Index: TAlign]: TJvDockSplitter read GetDockSplitterWithAlign;
|
|
published
|
|
property LeftSplitterStyle: TJvDockSplitterStyle index 0 read GetSplitterStyleIndex write SetSplitterStyleIndex;
|
|
property RightSplitterStyle: TJvDockSplitterStyle index 1 read GetSplitterStyleIndex write SetSplitterStyleIndex;
|
|
property TopSplitterStyle: TJvDockSplitterStyle index 2 read GetSplitterStyleIndex write SetSplitterStyleIndex;
|
|
property BottomSplitterStyle: TJvDockSplitterStyle index 3 read GetSplitterStyleIndex write SetSplitterStyleIndex;
|
|
property AutoFocusDockedForm: Boolean read FAutoFocusDockedForm write FAutoFocusDockedForm default True;
|
|
property EnableDock;
|
|
property LeftDock;
|
|
property TopDock;
|
|
property RightDock;
|
|
property BottomDock;
|
|
property DockStyle;
|
|
property CustomDock;
|
|
property OnGetClientAlignSize: TJvDockGetClientAlignSizeEvent read FOnGetClientAlignSize
|
|
write FOnGetClientAlignSize;
|
|
property OnFinishSetDockPanelSize: TJvDockFinishSetDockPanelSizeEvent read FOnFinishSetDockPanelSize
|
|
write FOnFinishSetDockPanelSize;
|
|
property OnCustomPanel: TJvDockCustomPanelEvent read FOnCustomPanel write FOnCustomPanel; {NEW!}
|
|
end;
|
|
|
|
TJvDockMouseStation = (msFloat, msConjoin, msTabPage);
|
|
|
|
TJvDockNCButtonEvent = procedure(DockClient: TJvDockClient; Button: TMouseButton;
|
|
X, Y: Smallint; HitTest: Longint; MouseStation: TJvDockMouseStation) of object;
|
|
TJvDockNCButtonDownEvent = TJvDockNCButtonEvent;
|
|
TJvDockNCButtonUpEvent = TJvDockNCButtonEvent;
|
|
TJvDockNCButtonDblClkEvent = TJvDockNCButtonEvent;
|
|
TJvDockNCMouseMoveEvent = procedure(DockClient: TJvDockClient;
|
|
X, Y: Smallint; HitTest: Longint; MouseStation: TJvDockMouseStation) of object;
|
|
TJvDockPaintDockEvent = procedure(Canvas: TCanvas;
|
|
Control: TControl; const ARect: TRect) of object;
|
|
TJvDockPaintDockGrabberEvent = TJvDockPaintDockEvent;
|
|
TJvDockPaintDockSplitterEvent = TJvDockPaintDockEvent;
|
|
TJvDockFormHintEvent = procedure(HTFlag: Integer; var HintStr: string; var CanShow: Boolean) of object;
|
|
|
|
TJvDockClient = class(TJvDockBaseControl)
|
|
private
|
|
FConjoinPanelClass: TJvDockConjoinPanelClass;
|
|
FTabDockClass: TJvDockTabClass;
|
|
FParentVisible: Boolean;
|
|
FNCPopupMenu: TPopupMenu;
|
|
FDirectDrag: Boolean;
|
|
FShowHint: Boolean;
|
|
FCanFloat: Boolean;
|
|
FDockLevel: Integer;
|
|
FEnableCloseButton: Boolean;
|
|
FOnNCButtonDown: TJvDockNCButtonDownEvent;
|
|
FOnNCButtonUp: TJvDockNCButtonUpEvent;
|
|
FOnNCMouseMove: TJvDockNCMouseMoveEvent;
|
|
FOnNCButtonDblClk: TJvDockNCButtonDblClkEvent;
|
|
FOnPaintDockGrabber: TJvDockPaintDockGrabberEvent;
|
|
FOnPaintDockSplitter: TJvDockPaintDockSplitterEvent;
|
|
FOnFormShowHint: TJvDockFormHintEvent;
|
|
FOnFormShow: TNotifyEvent;
|
|
FOnFormHide: TNotifyEvent;
|
|
FOnCheckIsDockable: TJvDockCheckDockableEvent; {NEW!}
|
|
FOnTabHostFormCreated: TJvDockTabHostFormCreatedEvent; {NEW!}
|
|
FCurrentDockSite: TWinControl;
|
|
FLastDockSite: TWinControl;
|
|
FUnDockLeft: Integer;
|
|
FUnDockTop: Integer;
|
|
FVSPaneWidth: Integer;
|
|
procedure SetParentVisible(const Value: Boolean);
|
|
function GetLRDockWidth: Integer;
|
|
function GetTBDockHeight: Integer;
|
|
procedure SetLRDockWidth(const Value: Integer);
|
|
procedure SetTBDockHeight(const Value: Integer);
|
|
procedure SetNCPopupMenu(Value: TPopupMenu);
|
|
procedure WMNCLButtonDown(var Msg: TWMNCHitMessage);
|
|
procedure WMNCLButtonUp(var Msg: TWMNCHitMessage);
|
|
procedure WMNCLButtonDblClk(var Msg: TWMNCHitMessage);
|
|
procedure WMNCMButtonDown(var Msg: TWMNCHitMessage);
|
|
procedure WMNCMButtonUp(var Msg: TWMNCHitMessage);
|
|
procedure WMNCMButtonDblClk(var Msg: TWMNCHitMessage);
|
|
procedure WMNCRButtonDown(var Msg: TWMNCHitMessage);
|
|
procedure WMNCRButtonUp(var Msg: TWMNCHitMessage);
|
|
procedure WMNCRButtonDblClk(var Msg: TWMNCHitMessage);
|
|
procedure WMNCMouseMove(var Msg: TWMNCHitMessage);
|
|
procedure CMVisibleChanged(var Msg: TMessage);
|
|
procedure SetCurrentDockSite(const Value: TWinControl);
|
|
procedure SetLastDockSite(ALastDockSite: TWinControl);
|
|
procedure SetVSPaneWidth(const Value: Integer);
|
|
procedure SetUnDockLeft(const Value: Integer);
|
|
procedure SetUnDockTop(const Value: Integer);
|
|
function GetDockState: Integer;
|
|
procedure SetCanFloat(const Value: Boolean);
|
|
procedure SetDockLevel(const Value: Integer);
|
|
procedure SetEnableCloseButton(const Value: Boolean);
|
|
protected
|
|
procedure DoMenuPopup(X, Y: Integer); virtual;
|
|
procedure Deactivate; virtual;
|
|
procedure Activate; virtual;
|
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
|
procedure DoFloatDockClients(PanelAlign: TAlign);
|
|
procedure DoFloatDockEachOther;
|
|
procedure SetBottomDock(const Value: Boolean); override;
|
|
procedure SetEachOtherDock(const Value: Boolean); override;
|
|
procedure SetEnableDock(const Value: Boolean); override;
|
|
procedure SetLeftDock(const Value: Boolean); override;
|
|
procedure SetRightDock(const Value: Boolean); override;
|
|
procedure SetTopDock(const Value: Boolean); override;
|
|
procedure DoFormOnClose(Sender: TObject; var Action: TCloseAction); override;
|
|
procedure AddDockStyle(ADockStyle: TJvDockBasicStyle); override;
|
|
procedure RemoveDockStyle(ADockStyle: TJvDockBasicStyle); override;
|
|
procedure WMSize(var Msg: TWMSize);
|
|
procedure WMActivate(var Msg: TWMActivate);
|
|
procedure WindowProc(var Msg: TMessage); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure FormStartDock(var Source: TJvDockDragDockObject); virtual;
|
|
procedure FormPositionDockRect(Source: TJvDockDragDockObject); virtual;
|
|
procedure FormDockOver(Source: TJvDockDragDockObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean); virtual;
|
|
procedure FormDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); virtual;
|
|
procedure FormEndDock(Target: TObject; X, Y: Integer); virtual;
|
|
function FormUnDock(NewTarget: TWinControl; Client: TControl): Boolean; virtual;
|
|
procedure FormGetSiteInfo(Source: TJvDockDragDockObject;
|
|
Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
|
|
var CanDock: Boolean); virtual;
|
|
procedure FormGetDockEdge(Source: TJvDockDragDockObject; MousePos: TPoint; var DropAlign: TAlign); virtual;
|
|
procedure Assign(Source: TPersistent); override;
|
|
procedure MakeShowEvent;
|
|
procedure MakeHideEvent;
|
|
function CreateConjoinPanelClass(ConjoinHost: TForm): TJvDockConjoinPanel;
|
|
function CreateTabDockClass(TabHost: TForm): TJvDockTabPageControl;
|
|
function CreateConjoinHostAndDockControl(Control1, Control2: TControl;
|
|
DockType: TAlign): TJvDockConjoinHostForm; virtual;
|
|
function CreateTabHostAndDockControl(Control1, Control2: TControl): TJvDockTabHostForm; virtual;
|
|
|
|
function FindTabHostForm: TForm;
|
|
// return nil if not found, otherwise, get currently docked parent tabhost form if there is one.
|
|
|
|
procedure DoNCButtonDown(Msg: TWMNCHitMessage; Button: TMouseButton;
|
|
MouseStation: TJvDockMouseStation); virtual;
|
|
procedure DoNCButtonUp(Msg: TWMNCHitMessage; Button: TMouseButton;
|
|
MouseStation: TJvDockMouseStation); virtual;
|
|
procedure DoNCMouseMove(Msg: TWMNCHitMessage;
|
|
MouseStation: TJvDockMouseStation); virtual;
|
|
procedure DoNCButtonDblClk(Msg: TWMNCHitMessage; Button: TMouseButton;
|
|
MouseStation: TJvDockMouseStation); virtual;
|
|
|
|
procedure DoPaintDockGrabber(Canvas: TCanvas;
|
|
Control: TControl; const ARect: TRect);
|
|
procedure DoPaintDockSplitter(Canvas: TCanvas;
|
|
Control: TControl; const ARect: TRect);
|
|
procedure DoFormShowHint(HTFlag: Integer; var HintStr: string; var CanShow: Boolean);
|
|
procedure ShowParentForm;
|
|
procedure HideParentForm;
|
|
procedure RestoreChild;
|
|
property VSPaneWidth: Integer read FVSPaneWidth write SetVSPaneWidth;
|
|
property ParentVisible: Boolean read FParentVisible write SetParentVisible;
|
|
{ (rb) not used? }
|
|
property CurrentDockSite: TWinControl read FCurrentDockSite write SetCurrentDockSite;
|
|
property LastDockSite: TWinControl read FLastDockSite write SetLastDockSite;
|
|
property UnDockLeft: Integer read FUnDockLeft write SetUnDockLeft;
|
|
property UnDockTop: Integer read FUnDockTop write SetUnDockTop;
|
|
property DockState: Integer read GetDockState;
|
|
published
|
|
property LRDockWidth: Integer read GetLRDockWidth write SetLRDockWidth default 100;
|
|
property TBDockHeight: Integer read GetTBDockHeight write SetTBDockHeight default 100;
|
|
property NCPopupMenu: TPopupMenu read FNCPopupMenu write SetNCPopupMenu;
|
|
property DirectDrag: Boolean read FDirectDrag write FDirectDrag;
|
|
property ShowHint: Boolean read FShowHint write FShowHint default True;
|
|
property CanFloat: Boolean read FCanFloat write SetCanFloat default True;
|
|
{ Not implemented; intention: only forms with the same DockLevel could be docked together }
|
|
property DockLevel: Integer read FDockLevel write SetDockLevel default 0;
|
|
property EnableCloseButton: Boolean read FEnableCloseButton write SetEnableCloseButton default True;
|
|
property EnableDock;
|
|
property LeftDock;
|
|
property TopDock;
|
|
property RightDock;
|
|
property BottomDock;
|
|
property EachOtherDock;
|
|
property DockStyle;
|
|
property CustomDock;
|
|
property OnFormShow: TNotifyEvent read FOnFormShow write FOnFormShow;
|
|
property OnFormHide: TNotifyEvent read FOnFormHide write FOnFormHide;
|
|
property OnCheckIsDockable: TJvDockCheckDockableEvent read FOnCheckIsDockable write FOnCheckIsDockable; {NEW!}
|
|
property OnTabHostFormCreated: TJvDockTabHostFormCreatedEvent read FOnTabHostFormCreated
|
|
write FOnTabHostFormCreated; {NEW!}
|
|
property OnNCButtonDown: TJvDockNCButtonDownEvent read FOnNCButtonDown write FOnNCButtonDown;
|
|
property OnNCButtonUp: TJvDockNCButtonUpEvent read FOnNCButtonUp write FOnNCButtonUp;
|
|
property OnNCMouseMove: TJvDockNCMouseMoveEvent read FOnNCMouseMove write FOnNCMouseMove;
|
|
property OnNCButtonDblClk: TJvDockNCButtonDblClkEvent read FOnNCButtonDblClk write FOnNCButtonDblClk;
|
|
property OnPaintDockGrabber: TJvDockPaintDockGrabberEvent read FOnPaintDockGrabber write FOnPaintDockGrabber;
|
|
property OnPaintDockSplitter: TJvDockPaintDockSplitterEvent read FOnPaintDockSplitter write FOnPaintDockSplitter;
|
|
property OnFormShowHint: TJvDockFormHintEvent read FOnFormShowHint write FOnFormShowHint;
|
|
end;
|
|
|
|
{ Maintained by a TJvDockConjoinHostForm; That is (always) the owner, ie.
|
|
that is assumed on multiple places in the code) }
|
|
TJvDockConjoinPanel = class(TJvDockCustomPanel)
|
|
private
|
|
function GetDockClient: TJvDockClient;
|
|
function GetParentForm: TJvDockConjoinHostForm;
|
|
procedure CMUnDockClient(var Msg: TCMUnDockClient); message CM_UNDOCKCLIENT;
|
|
protected
|
|
function CreateDockManager: IDockManager; override;
|
|
procedure ReloadDockedControl(const AControlName: string; var AControl: TControl); override;
|
|
procedure CustomStartDock(var Source: TJvDockDragDockObject); override;
|
|
procedure CustomGetSiteInfo(Source: TJvDockDragDockObject;
|
|
Client: TControl; var InfluenceRect: TRect; MousePos: TPoint;
|
|
var CanDock: Boolean); override;
|
|
procedure CustomDockOver(Source: TJvDockDragDockObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean); override;
|
|
procedure CustomPositionDockRect(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
procedure CustomDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
procedure CustomEndDock(Target: TObject; X, Y: Integer); override;
|
|
function CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl;
|
|
Client: TControl): Boolean; override;
|
|
procedure DoDockOver(Source: TDragDockObject; X, Y: Integer; State: TDragState;
|
|
var Accept: Boolean); override;
|
|
procedure GetSiteInfo(Client: TControl; var InfluenceRect: TRect;
|
|
MousePos: TPoint; var CanDock: Boolean); override;
|
|
function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
|
|
{ DockClient of the Owner }
|
|
property DockClient: TJvDockClient read GetDockClient;
|
|
{ ParentForm is the Owner }
|
|
property ParentForm: TJvDockConjoinHostForm read GetParentForm;
|
|
end;
|
|
|
|
TJvDockAdvConjoinPanel = class(TJvDockConjoinPanel)
|
|
private
|
|
procedure CMUnDockClient(var Msg: TCMUnDockClient); message CM_UNDOCKCLIENT;
|
|
protected
|
|
procedure CustomDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
function CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl;
|
|
Client: TControl): Boolean; override;
|
|
function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
public
|
|
procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
|
|
end;
|
|
|
|
{ Maintained by a TJvDockTabHostForm; That is (always) the owner, ie.
|
|
that is assumed on multiple places in the code) }
|
|
TJvDockTabPageControl = class(TJvDockPageControl)
|
|
private
|
|
FVersion: Integer;
|
|
FStyleLink: TJvDockStyleLink;
|
|
function GetParentForm: TJvDockTabHostForm;
|
|
procedure DockStyleChanged(Sender: TObject);
|
|
function GetDockStyle: TJvDockObservableStyle;
|
|
function GetActiveDockForm: TCustomForm;
|
|
function GetDockForm(Index: Integer): TCustomForm;
|
|
protected
|
|
procedure AdjustClientRect(var Rect: TRect); override;
|
|
procedure ReloadDockedControl(const AControlName: string;
|
|
var AControl: TControl); override;
|
|
procedure CustomStartDock(var Source: TJvDockDragDockObject); override;
|
|
procedure CustomGetSiteInfo(Source: TJvDockDragDockObject; Client: TControl;
|
|
var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean); override;
|
|
procedure CustomDockOver(Source: TJvDockDragDockObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean); override;
|
|
procedure CustomPositionDockRect(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
procedure CustomDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
procedure CustomEndDock(Target: TObject; X, Y: Integer); override;
|
|
function CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl;
|
|
Client: TControl): Boolean; override;
|
|
procedure CustomGetDockEdge(Source: TJvDockDragDockObject; MousePos: TPoint;
|
|
var DropAlign: TAlign); override;
|
|
function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
|
|
procedure SyncWithStyle; virtual;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure AfterConstruction; override;
|
|
procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
|
|
procedure LoadFromStream(Stream: TStream); virtual;
|
|
procedure SaveToStream(Stream: TStream); virtual;
|
|
|
|
property ActiveDockForm: TCustomForm read GetActiveDockForm;
|
|
property DockForm[Index: Integer]: TCustomForm read GetDockForm;
|
|
{ ParentForm is the Owner }
|
|
property ParentForm: TJvDockTabHostForm read GetParentForm;
|
|
property TabPosition;
|
|
property DockStyle: TJvDockObservableStyle read GetDockStyle;
|
|
end;
|
|
|
|
TJvDockAdvTabPageControl = class(TJvDockTabPageControl)
|
|
private
|
|
procedure CMUnDockClient(var Msg: TCMUnDockClient); message CM_UNDOCKCLIENT;
|
|
protected
|
|
procedure CustomDockDrop(Source: TJvDockDragDockObject; X, Y: Integer); override;
|
|
function CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl;
|
|
Client: TControl): Boolean; override;
|
|
function DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean; override;
|
|
public
|
|
destructor Destroy; override;
|
|
procedure DockDrop(Source: TDragDockObject; X, Y: Integer); override;
|
|
end;
|
|
|
|
{ A TJvDockableForm is a base class for TJvDockConjoinHostForm
|
|
and TJvDockTabHostForm which are the base classes for the two kinds of
|
|
docked-views possible for handling multiple controls docked to the same
|
|
dock site. }
|
|
TJvDockableForm = class(TJvForm)
|
|
private
|
|
FDockClient: TJvDockClient;
|
|
FDockableControl: TWinControl;
|
|
FUnDockControl: TControl;
|
|
FFloatingChild: TControl;
|
|
function GetDockableControl: TWinControl;
|
|
procedure SetDockableControl(const Value: TWinControl);
|
|
procedure SetUnDockControl(const Value: TControl);
|
|
protected
|
|
procedure DoClose(var Action: TCloseAction); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
{ Fixed DockClient owned by the component }
|
|
property DockClient: TJvDockClient read FDockClient;
|
|
{ Either a TJvDockTabPageControl or a TJvDockConjoinPanel, assigned on
|
|
construction of the dockable form }
|
|
property DockableControl: TWinControl read GetDockableControl write SetDockableControl;
|
|
{ ?? Probably needs notification }
|
|
property UnDockControl: TControl read FUnDockControl write SetUnDockControl;
|
|
{ ?? Probably needs notification }
|
|
property FloatingChild: TControl read FFloatingChild;
|
|
end;
|
|
|
|
TJvDockConjoinHostForm = class(TJvDockableForm)
|
|
private
|
|
FPanel: TJvDockConjoinPanel;
|
|
protected
|
|
procedure DoClose(var Action: TCloseAction); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
property DockClient;
|
|
{ Constructed in TJvDockClient.CreateConjoinPanelClass }
|
|
property Panel: TJvDockConjoinPanel read FPanel write FPanel;
|
|
end;
|
|
|
|
TJvDockTabHostForm = class(TJvDockableForm)
|
|
private
|
|
FPageControl: TJvDockTabPageControl;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure ShowDockedControl(AControl:TWinControl); virtual; // If aControl is docked in PageControl, change PageControl to that page. NEW! WPostma.
|
|
procedure UpdateCaption(AControl:TWinControl); virtual; // update tab host's tabs and title bar when page caption changes.
|
|
|
|
// backwards compatibility: Mantis 4100
|
|
function GetActiveDockForm: TForm;
|
|
property DockClient;
|
|
{ Constructed in TJvDockClient.CreateTabDockClass }
|
|
property PageControl: TJvDockTabPageControl read FPageControl write FPageControl;
|
|
end;
|
|
|
|
TJvGlobalDockManager = class(TJvDockManager)
|
|
private
|
|
FDockServers: TList;
|
|
FDockClients: TList;
|
|
FDockableForms: TList;
|
|
function GetDockClient(const Index: Integer): TJvDockClient;
|
|
function GetDockClientCount: Integer;
|
|
function GetDockServer(const Index: Integer): TJvDockServer;
|
|
function GetDockServerCount: Integer;
|
|
function GetDockableForm(const Index: Integer): TJvDockableForm;
|
|
function GetDockableFormCount: Integer;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
procedure RegisterDockServer(ADockServer: TJvDockServer);
|
|
procedure RegisterDockClient(ADockClient: TJvDockClient);
|
|
procedure RegisterDockableForm(ADockableForm: TJvDockableForm);
|
|
procedure UnRegisterDockServer(ADockServer: TJvDockServer);
|
|
procedure UnRegisterDockClient(ADockClient: TJvDockClient);
|
|
procedure UnRegisterDockableForm(ADockableForm: TJvDockableForm);
|
|
function FindDockServerForm(const AName: string): TControl;
|
|
function FindDockClientForm(const AName: string): TControl;
|
|
function FindDockControlForm(const AName: string): TControl;
|
|
|
|
property DockServer[const Index: Integer]: TJvDockServer read GetDockServer;
|
|
property DockClient[const Index: Integer]: TJvDockClient read GetDockClient;
|
|
property DockableForm[const Index: Integer]: TJvDockableForm read GetDockableForm;
|
|
property DockServerCount: Integer read GetDockServerCount;
|
|
property DockClientCount: Integer read GetDockClientCount;
|
|
property DockableFormCount: Integer read GetDockableFormCount;
|
|
end;
|
|
|
|
var
|
|
DefaultDockPanelClass: TJvDockPanelClass = TJvDockPanel;
|
|
DefaultDockSplitterClass: TJvDockSplitterClass = TJvDockSplitter;
|
|
DefaultConjoinPanelClass: TJvDockConjoinPanelClass = TJvDockConjoinPanel;
|
|
DefaultTabDockClass: TJvDockTabClass = TJvDockTabPageControl;
|
|
DefaultDockZoneClass: TJvDockZoneClass = TJvDockZone;
|
|
DefaultDockTreeClass: TJvDockTreeClass = TJvDockTree;
|
|
|
|
procedure ShowDockForm(DockWindow: TWinControl);
|
|
procedure HideDockForm(DockWindow: TWinControl);
|
|
procedure MakeDockClientEvent(Host: TControl; Visible: Boolean);
|
|
function GetFormVisible(DockWindow: TWinControl): Boolean;
|
|
procedure SetDockPageControlPopupMenu(Value: TPopupMenu);
|
|
procedure SetDockPageControlHotTrack(Value: Boolean);
|
|
procedure SetTabDockHostBorderStyle(Value: TFormBorderStyle);
|
|
procedure SetConjoinDockHostBorderStyle(Value: TFormBorderStyle);
|
|
|
|
// Save Layout to JvAppStorage:
|
|
procedure SaveDockTreeToAppStorage(AppStorage: TJvCustomAppStorage; AppStoragePath: string = '');
|
|
// Load Layout from JvAppStorage:
|
|
procedure LoadDockTreeFromAppStorage(AppStorage: TJvCustomAppStorage; AppStoragePath: string = '');
|
|
|
|
procedure SaveDockTreeToFile(FileName: string);
|
|
procedure LoadDockTreeFromFile(FileName: string);
|
|
procedure SaveDockTreeToReg(ARootKey: DWORD; RegPatch: string);
|
|
procedure LoadDockTreeFromReg(ARootKey: DWORD; RegPatch: string);
|
|
|
|
function FindDockBaseControl(Client: TControl): TJvDockBaseControl;
|
|
function FindDockClient(Client: TControl): TJvDockClient;
|
|
function FindDockServer(Client: TControl): TJvDockServer;
|
|
|
|
function IsDockable(Sender: TWinControl; Client: TControl;
|
|
DropCtl: TControl = nil; DockAlign: TAlign = alNone): Boolean;
|
|
function ComputeDockingRect(AControl: TControl;
|
|
var DockRect: TRect; MousePos: TPoint): TAlign;
|
|
|
|
{ Undocks AControl from Sender; Sender is used to calculate the rectangle in
|
|
which AControl is displayed when it starts floating. }
|
|
procedure DoFloat(Sender, AControl: TControl);
|
|
procedure SetDockSite(Control: TWinControl; SiteValue: Boolean);
|
|
procedure DoFloatForm(DockForm: TControl);
|
|
procedure FreeAllDockableForm;
|
|
procedure DoFloatAllForm;
|
|
|
|
function GetClientAlignControlArea(AControl: TWinControl; Align: TAlign; Exclude: TControl = nil): Integer;
|
|
procedure ResetDockClient(Control: TControl; NewTarget: TControl); overload;
|
|
procedure ResetDockClient(DockClient: TJvDockClient; NewTarget: TControl); overload;
|
|
|
|
{ Quick way to do tabbed docking programmatically - Added by Warren }
|
|
function ManualTabDock(DockSite: TWinControl; Form1, Form2: TForm): TJvDockTabHostForm;
|
|
{ Must create the initial tab dock with two pages, using ManualTabDock,
|
|
then you can add more pages with this:}
|
|
procedure ManualTabDockAddPage(TabHost: TJvDockTabHostForm; AForm: TForm);
|
|
function ManualConjoinDock(DockSite: TWinControl; Form1, Form2: TForm): TJvDockConjoinHostForm;
|
|
|
|
function DockStateStr(DockState: Integer): string; {return string for a dock state}
|
|
|
|
procedure BeginDockLoading;
|
|
procedure EndDockLoading;
|
|
function JvGlobalDockIsLoading: Boolean;
|
|
|
|
{$IFNDEF COMPILER9_UP}
|
|
procedure InvalidateDockHostSiteOfControl(Control: TControl; FocusLost: Boolean);
|
|
{$ENDIF !COMPILER9_UP}
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_39/run/JvDockControlForm.pas $';
|
|
Revision: '$Revision: 12579 $';
|
|
Date: '$Date: 2009-10-26 20:59:53 +0100 (lun., 26 oct. 2009) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils,
|
|
JvAppRegistryStorage, JvAppIniStorage, JvTypes,
|
|
JvDockSupportProc, JvDockGlobals, JvDockInfo, JvDockVSNetStyle, JvJVCLUtils;
|
|
|
|
{$R JvDockableForm.dfm}
|
|
{$R JvDockConjoinHost.dfm}
|
|
{$R JvDockTabHost.dfm}
|
|
|
|
type
|
|
TControlAccessProtected = class(TControl);
|
|
TWinControlAccessProtected = class(TWinControl);
|
|
|
|
var
|
|
DockPageControlPopupMenu: TPopupMenu = nil;
|
|
DockPageControlHotTrack: Boolean = False;
|
|
TabDockHostBorderStyle: TFormBorderStyle = bsSizeToolWin;
|
|
ConjoinDockHostBorderStyle: TFormBorderStyle = bsSizeToolWin;
|
|
|
|
GDockLoadCount: Integer = 0;
|
|
GShowingChanged: TList;
|
|
|
|
//=== Local procedures =======================================================
|
|
|
|
function IsWinXP_UP: Boolean;
|
|
begin
|
|
Result := (Win32Platform = VER_PLATFORM_WIN32_NT) and
|
|
((Win32MajorVersion > 5) or
|
|
(Win32MajorVersion = 5) and (Win32MinorVersion >= 1));
|
|
end;
|
|
|
|
procedure ApplyShowingChanged;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if IsWinXP_UP and (GShowingChanged <> nil) then
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
if GShowingChanged.IndexOf(Screen.Forms[I]) >= 0 then
|
|
Screen.Forms[i].Perform(CM_SHOWINGCHANGED, 0, 0);
|
|
FreeAndNil(GShowingChanged);
|
|
end;
|
|
|
|
procedure UpdateCaption(Source: TWinControl; Exclude: TControl);
|
|
var
|
|
I: Integer;
|
|
Host: TJvDockableForm;
|
|
begin
|
|
if (Source <> nil) and (Source.Parent is TJvDockableForm) then
|
|
begin
|
|
Host := TJvDockableForm(Source.Parent);
|
|
Host.Caption := '';
|
|
|
|
for I := 0 to Source.DockClientCount - 1 do
|
|
if Source.DockClients[I].Visible and (Source.DockClients[I] <> Exclude) then
|
|
Host.Caption := Host.Caption + TCustomForm(Source.DockClients[I]).Caption + RsDockStringSplitter;
|
|
|
|
if Host.HostDockSite is TJvDockTabPageControl then
|
|
with TJvDockTabPageControl(Host.HostDockSite) do
|
|
if (ActivePage <> nil) and (ActivePage.Controls[0] = Source) then
|
|
ActivePage.Caption := Host.Caption;
|
|
UpdateCaption(Host.HostDockSite, nil);
|
|
end;
|
|
end;
|
|
|
|
//=== Global procedures ======================================================
|
|
|
|
procedure BeginDockLoading;
|
|
begin
|
|
if GDockLoadCount = 0 then
|
|
begin
|
|
JvDockLockWindow(nil);
|
|
end;
|
|
Inc(GDockLoadCount);
|
|
end;
|
|
|
|
procedure EndDockLoading;
|
|
begin
|
|
Dec(GDockLoadCount);
|
|
if GDockLoadCount = 0 then
|
|
begin
|
|
ApplyShowingChanged;
|
|
JvDockUnLockWindow;
|
|
end;
|
|
end;
|
|
|
|
function JvGlobalDockIsLoading: Boolean;
|
|
begin
|
|
Result := GDockLoadCount > 0;
|
|
end;
|
|
|
|
{ ahuser: These functions are not call anywhere
|
|
|
|
function GetActiveControl(AForm: TCustomForm): TWinControl;
|
|
var
|
|
AControl: TWinControl;
|
|
begin
|
|
Result := nil;
|
|
AControl := AForm.ActiveControl;
|
|
while AControl <> nil do
|
|
begin
|
|
if AControl.HostDockSite <> nil then
|
|
begin
|
|
Result := AControl;
|
|
Break;
|
|
end;
|
|
AControl := AControl.Parent;
|
|
end;
|
|
end;
|
|
|
|
function GetHostDockParent(AControl: TWinControl): TWinControl;
|
|
begin
|
|
Result := nil;
|
|
while AControl <> nil do
|
|
begin
|
|
if AControl.HostDockSite <> nil then
|
|
begin
|
|
Result := AControl.HostDockSite;
|
|
Break;
|
|
end;
|
|
AControl := AControl.Parent;
|
|
end;
|
|
end;}
|
|
|
|
function ComputeDockingRect(AControl: TControl; var DockRect: TRect; MousePos: TPoint): TAlign;
|
|
var
|
|
DockTopRect, DockLeftRect, DockBottomRect, DockRightRect, DockCenterRect: TRect;
|
|
begin
|
|
Result := alNone;
|
|
|
|
if AControl = nil then
|
|
Exit;
|
|
with AControl do
|
|
begin
|
|
DockLeftRect.TopLeft := Point(0, 0);
|
|
DockLeftRect.BottomRight := Point(ClientWidth div 5, ClientHeight);
|
|
|
|
DockTopRect.TopLeft := Point(ClientWidth div 5, 0);
|
|
DockTopRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5);
|
|
|
|
DockRightRect.TopLeft := Point(ClientWidth div 5 * 4, 0);
|
|
DockRightRect.BottomRight := Point(ClientWidth, ClientHeight);
|
|
|
|
DockBottomRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5 * 4);
|
|
DockBottomRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight);
|
|
|
|
DockCenterRect.TopLeft := Point(ClientWidth div 5, ClientHeight div 5);
|
|
DockCenterRect.BottomRight := Point(ClientWidth div 5 * 4, ClientHeight div 5 * 4);
|
|
|
|
if PtInRect(DockLeftRect, MousePos) then
|
|
begin
|
|
Result := alLeft;
|
|
DockRect := DockLeftRect;
|
|
DockRect.Right := ClientWidth div 2;
|
|
end
|
|
else
|
|
if PtInRect(DockTopRect, MousePos) then
|
|
begin
|
|
Result := alTop;
|
|
DockRect := DockTopRect;
|
|
DockRect.Left := 0;
|
|
DockRect.Right := ClientWidth;
|
|
DockRect.Bottom := ClientHeight div 2;
|
|
end
|
|
else
|
|
if PtInRect(DockRightRect, MousePos) then
|
|
begin
|
|
Result := alRight;
|
|
DockRect := DockRightRect;
|
|
DockRect.Left := ClientWidth div 2;
|
|
end
|
|
else
|
|
if PtInRect(DockBottomRect, MousePos) then
|
|
begin
|
|
Result := alBottom;
|
|
DockRect := DockBottomRect;
|
|
DockRect.Left := 0;
|
|
DockRect.Right := ClientWidth;
|
|
DockRect.Top := ClientHeight div 2;
|
|
end
|
|
else
|
|
if PtInRect(DockCenterRect, MousePos) then
|
|
begin
|
|
Result := alClient;
|
|
DockRect := DockCenterRect;
|
|
end;
|
|
if Result = alNone then
|
|
Exit;
|
|
|
|
DockRect.TopLeft := ClientToScreen(DockRect.TopLeft);
|
|
DockRect.BottomRight := ClientToScreen(DockRect.BottomRight);
|
|
end;
|
|
end;
|
|
|
|
function DockStateStr(DockState: Integer): string;
|
|
begin
|
|
// (rom) XML strings do not localize
|
|
case DockState of
|
|
JvDockState_Unknown:
|
|
Result := 'Unknown';
|
|
JvDockState_Docking:
|
|
Result := 'Docking';
|
|
JvDockState_Floating:
|
|
Result := 'Floating';
|
|
else
|
|
Result := IntToStr(DockState);
|
|
end;
|
|
end;
|
|
|
|
procedure DoFloat(Sender, AControl: TControl);
|
|
var
|
|
ARect: TRect;
|
|
CH, BW: Integer;
|
|
begin
|
|
BW := JvDockGetSysBorderWidth;
|
|
CH := JvDockGetSysCaptionHeight;
|
|
|
|
ARect.TopLeft := Sender.ClientToScreen(Point(-(BW + 3), -(CH + BW + 1)));
|
|
ARect.BottomRight := Sender.ClientToScreen(
|
|
Point(Sender.UndockWidth - (BW + 3), Sender.UndockHeight - (BW + CH + 1)));
|
|
AControl.ManualFloat(ARect);
|
|
if (AControl.Left <> ARect.Left) or (AControl.Top <> ARect.Top) then
|
|
begin
|
|
AControl.Left := ARect.Left;
|
|
AControl.Top := ARect.Top;
|
|
end;
|
|
end;
|
|
|
|
procedure DoFloatAllForm;
|
|
var
|
|
I: Integer;
|
|
TempList: TList;
|
|
begin
|
|
TempList := TList.Create;
|
|
try
|
|
for I := 0 to Screen.CustomFormCount - 1 do
|
|
if not (Screen.CustomForms[I] is TJvDockableForm) and
|
|
(Assigned(FinddockClient(Screen.CustomForms[I])) or
|
|
Assigned(FinddockServer(Screen.CustomForms[I]))) then
|
|
TempList.Add(Screen.CustomForms[I]);
|
|
|
|
for I := 0 to TempList.Count - 1 do
|
|
DoFloatForm(TempList[I]);
|
|
finally
|
|
TempList.Free;
|
|
end;
|
|
FreeAllDockableForm;
|
|
end;
|
|
|
|
procedure DoFloatForm(DockForm: TControl);
|
|
var
|
|
I: TAlign;
|
|
J: Integer;
|
|
ADockServer: TJvDockServer;
|
|
// ARect: TRect;
|
|
Channel: TJvDockVSChannel;
|
|
begin
|
|
if DockForm is TJvDockableForm then
|
|
begin
|
|
with TJvDockableForm(DockForm).DockableControl do
|
|
begin
|
|
for J := DockClientCount - 1 downto 0 do
|
|
DoFloatForm(DockClients[J]);
|
|
|
|
DockForm.ManualDock(nil);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
ADockServer := FindDockServer(DockForm);
|
|
if ADockServer <> nil then
|
|
begin
|
|
// (rom) better use a Count or introduce one
|
|
// (p3) this is due to the fact that DockPanel returns a dockpanel based on the indices 0 to 3
|
|
// DockPanelWithAlign uses the TAlign enumeration, however
|
|
for I := alTop to alRight do
|
|
if Assigned(ADockServer.DockPanelWithAlign[I]) then
|
|
begin
|
|
for J := ADockServer.DockPanelWithAlign[I].DockClientCount - 1 downto 0 do
|
|
DoFloatForm(ADockServer.DockPanelWithAlign[I].DockClients[J]);
|
|
if ADockServer.DockPanelWithAlign[I] is TJvDockVSNETPanel then
|
|
with TJvDockVSNETPanel(ADockServer.DockPanelWithAlign[I]).VSChannel do
|
|
begin
|
|
RemoveAllBlock;
|
|
HidePopupPanel(ActiveDockForm);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if DockForm.HostDockSite <> nil then
|
|
begin
|
|
if (DockForm.HostDockSite.Parent is TJvDockableForm) and
|
|
(DockForm.HostDockSite.DockClientCount <= 2) then
|
|
PostMessage(DockForm.HostDockSite.Parent.Handle, WM_CLOSE, 0, 0);
|
|
end;
|
|
// else
|
|
// ARect := DockForm.BoundsRect;
|
|
|
|
Channel := RetrieveChannel(DockForm.HostDockSite);
|
|
if Assigned(Channel) then
|
|
begin
|
|
Channel.RemoveDockControl(TWinControl(DockForm));
|
|
DockForm.Dock(nil, Bounds(DockForm.Left, DockForm.Top, DockForm.UndockWidth, DockForm.UndockHeight));
|
|
end
|
|
else
|
|
DockForm.ManualDock(nil);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function FindDockBaseControl(Client: TControl): TJvDockBaseControl;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := nil;
|
|
if Client <> nil then
|
|
for I := 0 to Client.ComponentCount - 1 do
|
|
if Client.Components[I] is TJvDockBaseControl then
|
|
begin
|
|
Result := TJvDockBaseControl(Client.Components[I]);
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function FindDockClient(Client: TControl): TJvDockClient;
|
|
var
|
|
ADockControl: TJvDockBaseControl;
|
|
begin
|
|
ADockControl := FindDockBaseControl(Client);
|
|
if ADockControl is TJvDockClient then
|
|
Result := TJvDockClient(ADockControl)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function FindDockServer(Client: TControl): TJvDockServer;
|
|
var
|
|
ADockControl: TJvDockBaseControl;
|
|
begin
|
|
ADockControl := FindDockBaseControl(Client);
|
|
if ADockControl is TJvDockServer then
|
|
Result := TJvDockServer(ADockControl)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure FreeAllDockableForm;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Assert(JvGlobalDockManager <> nil);
|
|
for I := JvGlobalDockManager.DockableFormCount - 1 downto 0 do
|
|
if JvGlobalDockManager.DockableForm[I].DockableControl.DockClientCount = 0 then
|
|
JvGlobalDockManager.DockableForm[I].Free;
|
|
end;
|
|
|
|
function GetClientAlignControlArea(AControl: TWinControl; Align: TAlign; Exclude: TControl): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := 0 to AControl.ControlCount - 1 do
|
|
if (AControl.Controls[I].Align = Align) and AControl.Controls[I].Visible and
|
|
(AControl.Controls[I] <> Exclude) and
|
|
not ((AControl.Controls[I] is TJvDockSplitter) or (AControl.Controls[I] is TJvDockPanel)) then
|
|
if Align in [alLeft, alRight] then
|
|
Inc(Result, AControl.Controls[I].Width)
|
|
else
|
|
Inc(Result, AControl.Controls[I].Height);
|
|
end;
|
|
|
|
function GetFormVisible(DockWindow: TWinControl): Boolean;
|
|
var
|
|
ADockClient: TJvDockClient;
|
|
begin
|
|
Result := True;
|
|
ADockClient := FindDockClient(DockWindow);
|
|
if ADockClient <> nil then
|
|
Result := ADockClient.DockStyle.GetDockFormVisible(ADockClient);
|
|
end;
|
|
|
|
procedure HideDockForm(DockWindow: TWinControl);
|
|
var
|
|
ADockClient: TJvDockClient;
|
|
begin
|
|
// delegate to style
|
|
ADockClient := FindDockClient(DockWindow);
|
|
if Assigned(ADockClient) and Assigned(ADockClient.DockStyle) then
|
|
ADockClient.DockStyle.DoHideDockForm(DockWindow);
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.DoHideDockForm(DockWindow: TWinControl);
|
|
|
|
procedure HideDockChild(DockWindow: TWinControl);
|
|
var
|
|
I: Integer;
|
|
DockClient: TJvDockClient;
|
|
begin
|
|
if DockWindow = nil then
|
|
Exit;
|
|
if (DockWindow is TJvDockableForm) and (DockWindow.Visible) then
|
|
with TJvDockableForm(DockWindow).DockableControl do
|
|
for I := 0 to DockClientCount - 1 do
|
|
HideDockChild(TWinControl(DockClients[I]));
|
|
DockClient := FindDockClient(DockWindow);
|
|
if (DockWindow is TForm) and (TForm(DockWindow).FormStyle <> fsMDIChild) and
|
|
(DockClient.DockStyle <> nil) then
|
|
DockClient.DockStyle.HideDockForm(DockClient);
|
|
end;
|
|
|
|
procedure HideDockParent(DockWindow: TWinControl);
|
|
var
|
|
Host: TWinControl;
|
|
DockClient: TJvDockClient;
|
|
begin
|
|
if (DockWindow <> nil) and (DockWindow.HostDockSite <> nil) then
|
|
begin
|
|
Host := DockWindow.HostDockSite;
|
|
if Host.VisibleDockClientCount = 0 then
|
|
if Host is TJvDockPanel then
|
|
TJvDockPanel(Host).ShowDockPanel(False, nil)
|
|
else
|
|
begin
|
|
if Host.Parent <> nil then
|
|
begin
|
|
DockClient := FindDockClient(Host.Parent);
|
|
if (DockClient <> nil) and (DockClient.DockStyle <> nil) then
|
|
DockClient.DockStyle.HideDockForm(DockClient);
|
|
HideDockParent(Host.Parent);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
HideDockChild(DockWindow);
|
|
HideDockParent(DockWindow);
|
|
if (DockWindow.HostDockSite is TJvDockCustomControl) then
|
|
TJvDockCustomControl(DockWindow.HostDockSite).UpdateCaption(DockWindow);
|
|
end;
|
|
|
|
{$IFNDEF COMPILER9_UP}
|
|
procedure InvalidateDockHostSiteOfControl(Control: TControl; FocusLost: Boolean);
|
|
var
|
|
ChildDockSite: TControl;
|
|
ParentWalk: TWinControl;
|
|
begin
|
|
{ Invalidate the first dock site we come across; its ui may
|
|
need updating to reflect which control has focus. }
|
|
if Control = nil then
|
|
Exit;
|
|
ChildDockSite := Control;
|
|
ParentWalk := Control.Parent;
|
|
while (ChildDockSite.HostDockSite = nil) and (ParentWalk <> nil) do
|
|
begin
|
|
ChildDockSite := ParentWalk;
|
|
ParentWalk := ParentWalk.Parent;
|
|
end;
|
|
if ChildDockSite <> nil then
|
|
TWinControlAccessProtected(ChildDockSite).SendDockNotification(CM_INVALIDATEDOCKHOST,
|
|
Integer(Control), Integer(FocusLost));
|
|
end;
|
|
{$ENDIF !COMPILER9_UP}
|
|
|
|
function IsDockable(Sender: TWinControl; Client: TControl; DropCtl: TControl = nil;
|
|
DockAlign: TAlign = alNone): Boolean;
|
|
var
|
|
I: Integer;
|
|
ADockClient: TJvDockClient;
|
|
SenderDockStyle, ClientDockStyle: TJvDockBasicStyle;
|
|
SenderStyleName, ClientStyleName: string;
|
|
SenderDocPanel: TJvDockPanel;
|
|
//s:String;
|
|
// (rom) disabled unused
|
|
//label
|
|
// JudgeRelation;
|
|
begin
|
|
ADockClient := FindDockClient(Client);
|
|
Result := False;
|
|
if (ADockClient <> nil) and (ADockClient.EnableDock) then
|
|
begin
|
|
if Sender is TJvDockPanel then
|
|
begin
|
|
SenderDocPanel := TJvDockPanel(Sender);
|
|
with SenderDocPanel do
|
|
begin
|
|
{$IFDEF JVDOCK_DEBUG}
|
|
if CustomFlag and (not ADockClient.CustomDock) then
|
|
begin
|
|
OutputDebugString('IsDockable() - Debugging Dock-to-custom-panel problem.');
|
|
ADockClient.CustomDock := True; // BUG WORKAROUND. WPostma.
|
|
end;
|
|
{$ENDIF JVDOCK_DEBUG}
|
|
Result := DockServer.EnableDock and
|
|
(((Align = alLeft) and DockServer.LeftDock and (ADockClient.LeftDock)) or
|
|
((Align = alTop) and DockServer.TopDock and (ADockClient.TopDock)) or
|
|
((Align = alRight) and DockServer.RightDock and (ADockClient.RightDock)) or
|
|
((Align = alBottom) and DockServer.BottomDock and (ADockClient.BottomDock)) or
|
|
((CustomFlag) and Assigned(DockServer.CustomDockPanel) and (ADockClient.CustomDock))
|
|
);
|
|
|
|
//{$IFDEF JVDOCK_DEBUG}
|
|
// XXXXXX very noisy during drag operations:
|
|
//if Result then begin
|
|
// if Assigned(DropCtl) then
|
|
// s := DropCtl.Name
|
|
// else
|
|
// s := 'nil';
|
|
// OutputDebugString(PChar( 'JvDockControlForm.pas IsDockable: '+Sender.Name+ ': Dockable. DropCtl='+s ));
|
|
//end;
|
|
//{$ENDIF JVDOCK_DEBUG}
|
|
SenderDockStyle := DockServer.DockStyle;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (Sender <> nil) and (Sender.Parent is TJvDockableForm) then
|
|
with TJvDockableForm(Sender.Parent).DockableControl do
|
|
for I := 0 to DockClientCount - 1 do
|
|
if DockClients[I] = Client then
|
|
Exit;
|
|
Result := ADockClient.EachOtherDock;
|
|
if Sender <> nil then
|
|
ADockClient := FindDockClient(Sender.Parent);
|
|
if ADockClient <> nil then
|
|
Result := Result and ADockClient.EachOtherDock;
|
|
|
|
if ADockClient <> nil then
|
|
SenderDockStyle := ADockClient.DockStyle
|
|
else
|
|
Exit;
|
|
end;
|
|
|
|
ADockClient := FindDockClient(Client);
|
|
if ADockClient <> nil then
|
|
ClientDockStyle := ADockClient.DockStyle
|
|
else
|
|
Exit;
|
|
|
|
if SenderDockStyle = nil then
|
|
SenderStyleName := ''
|
|
else
|
|
SenderStyleName := SenderDockStyle.ClassName;
|
|
|
|
if ClientDockStyle = nil then
|
|
ClientStyleName := ''
|
|
else
|
|
ClientStyleName := ClientDockStyle.ClassName;
|
|
|
|
Result := Result and (SenderStyleName = ClientStyleName);
|
|
|
|
//JudgeRelation:
|
|
end;
|
|
end;
|
|
|
|
procedure LoadDockTreeFromAppStorage(AppStorage: TJvCustomAppStorage; AppStoragePath: string = '');
|
|
var
|
|
JvDockInfoTree: TJvDockInfoTree;
|
|
begin
|
|
AppStorage.BeginUpdate;
|
|
try
|
|
HideAllPopupPanel(nil); {This is in JvDockVSNetStyle.pas }
|
|
|
|
JvDockInfoTree := TJvDockInfoTree.Create(TJvDockInfoZone);
|
|
try
|
|
BeginDockLoading;
|
|
try
|
|
JvDockInfoTree.AppStorage := AppStorage;
|
|
JvDockInfoTree.AppStoragePath := AppStoragePath;
|
|
JvDockInfoTree.ReadInfoFromAppStorage;
|
|
finally
|
|
EndDockLoading;
|
|
end;
|
|
finally
|
|
JvDockInfoTree.Free;
|
|
end;
|
|
finally
|
|
AppStorage.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure LoadDockTreeFromFile(FileName: string);
|
|
var
|
|
JvAppStorage: TJvAppIniFileStorage;
|
|
begin
|
|
JvAppStorage := TJvAppIniFileStorage.Create(nil);
|
|
try
|
|
JvAppStorage.Location := flCustom;
|
|
JvAppStorage.FileName := FileName;
|
|
JvAppStorage.Reload;
|
|
LoadDockTreeFromAppStorage(JvAppStorage);
|
|
finally
|
|
JvAppStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure LoadDockTreeFromReg(ARootKey: DWORD; RegPatch: string);
|
|
var
|
|
JvAppStorage: TJvAppRegistryStorage;
|
|
begin
|
|
JvAppStorage := TJvAppRegistryStorage.Create(nil);
|
|
try
|
|
// (p3) this seems dangerous but it's the same method as used by TJvAppRegistryStorage
|
|
JvAppStorage.RegRoot := TJvRegKey(HKEY_CLASSES_ROOT + ARootKey);
|
|
JvAppStorage.Path := RegPatch;
|
|
LoadDockTreeFromAppStorage(JvAppStorage);
|
|
finally
|
|
JvAppStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure MakeDockClientEvent(Host: TControl; Visible: Boolean);
|
|
var
|
|
I: Integer;
|
|
DC: TJvDockClient;
|
|
begin
|
|
DC := FindDockClient(Host);
|
|
if DC <> nil then
|
|
begin
|
|
if Visible then
|
|
DC.MakeShowEvent
|
|
else
|
|
DC.MakeHideEvent;
|
|
if (Host is TJvDockableForm) and Host.Visible then
|
|
with TJvDockableForm(Host).DockableControl do
|
|
for I := 0 to DockClientCount - 1 do
|
|
MakeDockClientEvent(DockClients[I], Visible);
|
|
end;
|
|
end;
|
|
|
|
{ Quick way to do conjoined docking programmatically - Added by Warren }
|
|
|
|
function ManualConjoinDock(DockSite: TWinControl; Form1, Form2: TForm): TJvDockConjoinHostForm;
|
|
var
|
|
ConjoinHost: TJvDockConjoinHostForm;
|
|
DockClient1, DockCLient2: TJvDockClient;
|
|
begin
|
|
Form1.Show;
|
|
Form2.Show;
|
|
DockClient1 := FindDockClient(Form1);
|
|
Assert(Assigned(DockClient1));
|
|
DockClient2 := FindDockClient(Form2);
|
|
Assert(Assigned(DockClient2));
|
|
ConjoinHost := DockClient1.CreateConjoinHostAndDockControl(DockClient1.ParentForm, Form2, alTop);
|
|
ShowDockForm(Form2);
|
|
ConjoinHost.ManualDock(DockSite);
|
|
Result := ConjoinHost;
|
|
end;
|
|
|
|
{ Quick way to do tabbed docking programmatically - Added by Warren }
|
|
|
|
function ManualTabDock(DockSite: TWinControl; Form1, Form2: TForm): TJvDockTabHostForm;
|
|
var
|
|
TabHost: TJvDockTabHostForm;
|
|
// wasVisible1,wasVisible2:Boolean;
|
|
DockClient1, DockCLient2: TJvDockClient;
|
|
ScreenPos: TRect;
|
|
begin
|
|
//Form1.Show;
|
|
//Form2.Show;
|
|
|
|
DockClient1 := FindDockClient(Form1);
|
|
//wasVisible1 := Form1.Visible;
|
|
Form1.Hide;
|
|
Assert(Assigned(DockClient1));
|
|
if DockClient1.DockState = JvDockState_Docking then
|
|
begin
|
|
ScreenPos := Application.MainForm.ClientRect; // Just making it float temporarily.
|
|
Form1.ManualFloat(ScreenPos);
|
|
end;
|
|
DockClient2 := FindDockClient(Form2);
|
|
//wasVisible2 := Form2.Visible;
|
|
Form2.Hide;
|
|
|
|
Assert(Assigned(DockClient2));
|
|
if DockClient2.DockState = JvDockState_Docking then
|
|
begin
|
|
ScreenPos := Application.MainForm.ClientRect; // Just making it float temporarily.
|
|
Form2.ManualFloat(ScreenPos);
|
|
end;
|
|
|
|
TabHost := DockClient1.CreateTabHostAndDockControl(Form1, Form2);
|
|
{DockClient1.ParentForm, DockClient2.ParentForm}
|
|
TabHost.Hide;
|
|
|
|
TabHost.ManualDock(DockSite);
|
|
if not Form1.Visible then
|
|
Form1.Show;
|
|
if not Form2.Visible then
|
|
Form2.Show;
|
|
|
|
TabHost.Show;
|
|
ShowDockForm(Form2);
|
|
Result := TabHost;
|
|
end;
|
|
|
|
{ Must create the initial tab dock with two pages, using ManualTabDock,
|
|
then you can add more pages with this:}
|
|
|
|
procedure ManualTabDockAddPage(TabHost: TJvDockTabHostForm; AForm: TForm);
|
|
begin
|
|
Assert(Assigned(TabHost));
|
|
Assert(Assigned(TabHost.PageControl));
|
|
//AForm.Show;
|
|
AForm.ManualDock(TabHost.PageControl);
|
|
AForm.Show;
|
|
end;
|
|
|
|
procedure ResetDockClient(DockClient: TJvDockClient; NewTarget: TControl);
|
|
var
|
|
Pt: TPoint;
|
|
begin
|
|
if (DockClient <> nil) and not (csDestroying in DockClient.ParentForm.ComponentState) then
|
|
begin
|
|
if not ((DockClient.ParentForm.HostDockSite is TJvDockPanel) and (NewTarget is TJvDockPanel)) then
|
|
begin
|
|
if (DockClient.LastDockSite is TJvDockPanel) and (NewTarget is TJvDockPanel) and
|
|
(DockClient.LastDockSite <> NewTarget) then
|
|
with TJvDockPanel(DockClient.LastDockSite) do
|
|
if UseDockManager and (JvDockManager <> nil) then
|
|
JvDockManager.RemoveControl(DockClient.ParentForm);
|
|
|
|
if DockClient.ParentForm.HostDockSite is TJvDockPanel then
|
|
DockClient.LastDockSite := DockClient.ParentForm.HostDockSite
|
|
else
|
|
DockClient.LastDockSite := nil;
|
|
|
|
if DockClient.ParentForm.HostDockSite = nil then
|
|
begin
|
|
DockClient.UnDockLeft := DockClient.ParentForm.BoundsRect.TopLeft.X;
|
|
DockClient.UnDockTop := DockClient.ParentForm.BoundsRect.TopLeft.Y;
|
|
end
|
|
else
|
|
begin
|
|
Pt := DockClient.ParentForm.BoundsRect.TopLeft;
|
|
Pt := DockClient.ParentForm.HostDockSite.ClientToScreen(Pt);
|
|
DockClient.UnDockLeft := Pt.X;
|
|
DockClient.UnDockTop := Pt.Y;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure ResetDockClient(Control: TControl; NewTarget: TControl);
|
|
begin
|
|
ResetDockClient(FindDockClient(Control), NewTarget);
|
|
end;
|
|
|
|
// Save Layout to JvAppStorage:
|
|
//
|
|
// Uses Global VCL object Screens to go through all forms, and save layout for
|
|
// all the forms. Use any JvCustomAppStorage descendant to store to, such
|
|
// as registry, ini files, etc.
|
|
|
|
procedure SaveDockTreeToAppStorage(AppStorage: TJvCustomAppStorage; AppStoragePath: string = '');
|
|
var
|
|
JvDockInfoTree: TJvDockInfoTree;
|
|
I: Integer;
|
|
begin
|
|
AppStorage.BeginUpdate;
|
|
try
|
|
HideAllPopupPanel(nil); {This is in JvDockVSNetStyle.pas }
|
|
JvDockInfoTree := TJvDockInfoTree.Create(TJvDockInfoZone);
|
|
try
|
|
for I := 0 to Screen.CustomFormCount - 1 do
|
|
if (Screen.CustomForms[I].Parent = nil) and
|
|
((FindDockClient(Screen.CustomForms[I]) <> nil) or
|
|
(FindDockServer(Screen.CustomForms[I]) <> nil)) then
|
|
begin
|
|
{$IFDEF JVDOCK_DEBUG}
|
|
OutputDebugString(PChar('SaveDockTreeToAppStorage : Form ' + Screen.CustomForms[I].Name));
|
|
{$ENDIF JVDOCK_DEBUG}
|
|
JvDockInfoTree.CreateZoneAndAddInfoFromApp(Screen.CustomForms[I]);
|
|
end;
|
|
|
|
JvDockInfoTree.AppStorage := AppStorage;
|
|
JvDockInfoTree.AppStoragePath := AppStoragePath;
|
|
JvDockInfoTree.WriteInfoToAppStorage;
|
|
finally
|
|
JvDockInfoTree.Free;
|
|
end;
|
|
finally
|
|
AppStorage.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure SaveDockTreeToFile(FileName: string);
|
|
var
|
|
JvAppStorage: TJvAppIniFileStorage;
|
|
begin
|
|
JvAppStorage := TJvAppIniFileStorage.Create(nil);
|
|
try
|
|
JvAppStorage.Location := flCustom;
|
|
JvAppStorage.FileName := FileName;
|
|
JvAppStorage.Reload;
|
|
SaveDockTreeToAppStorage(JvAppStorage);
|
|
finally
|
|
JvAppStorage.Flush;
|
|
JvAppStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure SaveDockTreeToReg(ARootKey: DWORD; RegPatch: string);
|
|
var
|
|
JvAppStorage: TJvAppRegistryStorage;
|
|
begin
|
|
JvAppStorage := TJvAppRegistryStorage.Create(nil);
|
|
try
|
|
// (p3) this seems dangerous but it's the same method as used by TJvAppRegistryStorage
|
|
JvAppStorage.RegRoot := TJvRegKey(HKEY_CLASSES_ROOT + ARootKey);
|
|
JvAppStorage.Path := RegPatch;
|
|
SaveDockTreeToAppStorage(JvAppStorage);
|
|
finally
|
|
JvAppStorage.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure SetConjoinDockHostBorderStyle(Value: TFormBorderStyle);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
ConjoinDockHostBorderStyle := Value;
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
if (Screen.CustomForms[I] is TJvDockConjoinHostForm) and (Screen.CustomForms[I].HostDockSite = nil) then
|
|
TJvDockConjoinHostForm(Screen.CustomForms[I]).BorderStyle := Value;
|
|
end;
|
|
|
|
procedure SetDockPageControlHotTrack(Value: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
DockPageControlHotTrack := Value;
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
if Screen.CustomForms[I] is TJvDockTabHostForm then
|
|
TJvDockTabHostForm(Screen.CustomForms[I]).PageControl.HotTrack := Value;
|
|
end;
|
|
|
|
procedure SetDockPageControlPopupMenu(Value: TPopupMenu);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
DockPageControlPopupMenu := Value;
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
if Screen.CustomForms[I] is TJvDockTabHostForm then
|
|
TJvDockTabHostForm(Screen.CustomForms[I]).PageControl.PopupMenu := Value;
|
|
end;
|
|
|
|
procedure SetDockSite(Control: TWinControl; SiteValue: Boolean);
|
|
begin
|
|
TWinControlAccessProtected(Control).DockSite := SiteValue;
|
|
if (not (csDesigning in Control.ComponentState)) and (JvGlobalDockManager <> nil) then
|
|
JvGlobalDockManager.RegisterDockSite(Control, SiteValue);
|
|
end;
|
|
|
|
procedure SetTabDockHostBorderStyle(Value: TFormBorderStyle);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
TabDockHostBorderStyle := Value;
|
|
for I := 0 to Screen.FormCount - 1 do
|
|
if (Screen.CustomForms[I] is TJvDockTabHostForm) and (Screen.CustomForms[I].HostDockSite = nil) then
|
|
TJvDockTabHostForm(Screen.CustomForms[I]).BorderStyle := Value;
|
|
end;
|
|
|
|
procedure ShowDockForm(DockWindow: TWinControl);
|
|
var
|
|
ADockClient: TJvDockClient;
|
|
begin
|
|
// delegate to style
|
|
ADockClient := FindDockClient(DockWindow);
|
|
if Assigned(ADockClient) and Assigned(ADockClient.DockStyle) then
|
|
ADockClient.DockStyle.DoShowDockForm(DockWindow);
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.DoShowDockForm(DockWindow: TWinControl);
|
|
|
|
procedure ShowClient(Client, DockParent: TWinControl);
|
|
var
|
|
ADockClient: TJvDockClient;
|
|
ADockServer: TJvDockServer;
|
|
I: Integer;
|
|
begin
|
|
if (DockParent is TJvDockableForm) and (Client <> nil) then
|
|
begin
|
|
with TJvDockableForm(DockParent).DockableControl do
|
|
for I := 0 to DockClientCount - 1 do
|
|
if DockClients[I] <> Client then
|
|
MakeDockClientEvent(DockClients[I], True);
|
|
if Client.HostDockSite is TJvDockCustomControl then
|
|
TJvDockCustomControl(Client.HostDockSite).UpdateCaption(nil);
|
|
end
|
|
else
|
|
begin
|
|
ADockClient := FindDockClient(DockParent);
|
|
if (ADockClient <> nil) and (ADockClient.DockStyle <> nil) then
|
|
begin
|
|
ADockClient.DockStyle.ShowDockForm(ADockClient);
|
|
ADockServer := FindDockServer(GetParentForm(DockParent));
|
|
if (not Assigned(ADockServer) or ADockServer.AutoFocusDockedForm) and
|
|
DockParent.CanFocus then
|
|
DockParent.SetFocus;
|
|
end;
|
|
end;
|
|
if DockParent.Parent = nil then
|
|
SetForegroundWindow(DockParent.Handle);
|
|
end;
|
|
|
|
function ShowDockPanel(Client: TWinControl): TWinControl;
|
|
begin
|
|
Result := Client;
|
|
if Assigned(Client) and (Client.HostDockSite is TJvDockPanel) then
|
|
begin
|
|
ShowClient(nil, Client);
|
|
TJvDockPanel(Client.HostDockSite).ShowDockPanel(True, Client, sdfDockPanel);
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
function ShowTabDockHost(Client: TWinControl): TWinControl;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := Client;
|
|
if Assigned(Client) and (Client.HostDockSite is TJvDockTabPageControl) then
|
|
begin
|
|
ShowClient(nil, Client);
|
|
|
|
with TJvDockTabPageControl(Client.HostDockSite) do
|
|
for I := 0 to Count - 1 do
|
|
if Pages[I].Controls[0] = Client then
|
|
begin
|
|
Pages[I].Show;
|
|
Break;
|
|
end;
|
|
if (Client.HostDockSite <> nil) and not (Client.HostDockSite is TJvDockPanel) then
|
|
begin
|
|
Result := Client.HostDockSite.Parent;
|
|
ShowClient(Client, Result);
|
|
if (Result <> nil) and (Result.HostDockSite is TJvDockTabPageControl) then
|
|
{ (rb) never called AFAICS }
|
|
Result := ShowTabDockHost(Result)
|
|
else
|
|
ShowClient(nil, Result);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function ShowConjoinDockHost(Client: TWinControl): TWinControl;
|
|
begin
|
|
Result := Client;
|
|
if Assigned(Client) and Assigned(Client.HostDockSite) and not (Client.HostDockSite is TJvDockPanel) then
|
|
begin
|
|
ShowClient(nil, Client);
|
|
if Client.HostDockSite.Parent <> nil then
|
|
begin
|
|
Result := Client.HostDockSite.Parent;
|
|
ShowClient(Client, Result);
|
|
if (Result <> nil) and (Result.HostDockSite is TJvDockConjoinPanel) then
|
|
{ (rb) never called AFAICS }
|
|
Result := ShowConjoinDockHost(Result)
|
|
else
|
|
ShowClient(nil, Result);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
repeat
|
|
{ Show single floating window }
|
|
if Assigned(DockWindow) and (DockWindow.HostDockSite = nil) then
|
|
ShowClient(nil, DockWindow);
|
|
DockWindow := ShowTabDockHost(DockWindow);
|
|
DockWindow := ShowConjoinDockHost(DockWindow);
|
|
{ Show docked window }
|
|
DockWindow := ShowDockPanel(DockWindow);
|
|
until (DockWindow = nil) or (DockWindow.Parent = nil);
|
|
end;
|
|
|
|
//=== { TJvDockableForm } ====================================================
|
|
|
|
constructor TJvDockableForm.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
DragKind := dkDock;
|
|
FDockClient := TJvDockClient.Create(Self);
|
|
JvGlobalDockManager.RegisterDockableForm(Self);
|
|
FFloatingChild := nil;
|
|
TBDockHeight := FDockClient.TBDockHeight;
|
|
LRDockWidth := FDockClient.LRDockWidth;
|
|
end;
|
|
|
|
destructor TJvDockableForm.Destroy;
|
|
begin
|
|
if JvGlobalDockManager <> nil then
|
|
JvGlobalDockManager.UnRegisterDockableForm(Self);
|
|
{ Now handled in destroy of DockClient via TJvDockClient.SetLastDockSite }
|
|
//if DockClient.LastDockSite is TJvDockPanel then
|
|
// if Assigned(TJvDockPanel(DockClient.LastDockSite).JvDockManager) then
|
|
// TJvDockPanel(DockClient.LastDockSite).JvDockManager.RemoveControl(Self);
|
|
inherited Destroy;
|
|
// (rom) better comment this
|
|
FFloatingChild := nil;
|
|
end;
|
|
|
|
procedure TJvDockableForm.DoClose(var Action: TCloseAction);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if DockableControl.DockClientCount = 1 then
|
|
begin
|
|
FFloatingChild := DockableControl.DockClients[0];
|
|
|
|
if HostDockSite <> nil then
|
|
FFloatingChild.Visible := False;
|
|
|
|
DoFloat(Self, DockableControl.DockClients[0]);
|
|
Action := caFree;
|
|
end
|
|
else
|
|
if DockableControl.DockClientCount = 0 then
|
|
Action := caFree
|
|
else
|
|
begin
|
|
Action := caHide;
|
|
if (FUnDockControl <> nil) and (DockableControl.DockClientCount = 2) then
|
|
for I := 0 to DockableControl.DockClientCount - 1 do
|
|
if FUnDockControl = DockableControl.DockClients[I] then
|
|
begin
|
|
Action := caNone;
|
|
Break;
|
|
end;
|
|
end;
|
|
if (HostDockSite is TJvDockPanel) and (HostDockSite.VisibleDockClientCount = 1) and
|
|
(FFloatingChild = nil) then
|
|
TJvDockPanel(HostDockSite).ShowDockPanel(False, Self);
|
|
|
|
inherited DoClose(Action);
|
|
FUnDockControl := nil;
|
|
end;
|
|
|
|
function TJvDockableForm.GetDockableControl: TWinControl;
|
|
begin
|
|
Result := FDockableControl;
|
|
end;
|
|
|
|
procedure TJvDockableForm.SetDockableControl(const Value: TWinControl);
|
|
begin
|
|
FDockableControl := Value;
|
|
end;
|
|
|
|
procedure TJvDockableForm.SetUnDockControl(const Value: TControl);
|
|
begin
|
|
FUnDockControl := Value;
|
|
end;
|
|
|
|
//=== { TJvDockAdvConjoinPanel } =============================================
|
|
|
|
procedure TJvDockAdvConjoinPanel.CMUnDockClient(var Msg: TCMUnDockClient);
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
procedure TJvDockAdvConjoinPanel.CustomDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, Source.TargetControl);
|
|
inherited CustomDockDrop(Source, X, Y);
|
|
end;
|
|
|
|
function TJvDockAdvConjoinPanel.CustomUnDock(Source: TJvDockDragDockObject;
|
|
NewTarget: TWinControl; Client: TControl): Boolean;
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, NewTarget);
|
|
Result := inherited CustomUnDock(Source, NewTarget, Client);
|
|
end;
|
|
|
|
procedure TJvDockAdvConjoinPanel.DockDrop(Source: TDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, TControl(Source.DragTarget));
|
|
inherited DockDrop(Source, X, Y);
|
|
end;
|
|
|
|
function TJvDockAdvConjoinPanel.DoUnDock(NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Client, NewTarget);
|
|
Result := inherited DoUnDock(NewTarget, Client);
|
|
end;
|
|
|
|
//=== { TJvDockAdvPanel } ====================================================
|
|
|
|
procedure TJvDockAdvPanel.CMUnDockClient(var Msg: TCMUnDockClient);
|
|
var
|
|
DockClient: TJvDockClient;
|
|
begin
|
|
if JvGlobalDockIsLoading then
|
|
Exit;
|
|
with Msg do
|
|
begin
|
|
Result := 0;
|
|
if UseDockManager and (JvDockManager <> nil) then
|
|
begin
|
|
DockClient := FindDockClient(Client);
|
|
if (NewTarget <> nil) or
|
|
((Client <> nil) and (csDestroying in Client.ComponentState)) then
|
|
begin
|
|
if DockClient <> nil then
|
|
DockClient.LastDockSite := nil;
|
|
JvDockManager.RemoveControl(Client);
|
|
end
|
|
else
|
|
begin
|
|
if DockClient <> nil then
|
|
DockClient.LastDockSite := Self;
|
|
JvDockManager.HideControl(Client);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockAdvPanel.CustomDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, Source.TargetControl);
|
|
inherited CustomDockDrop(Source, X, Y);
|
|
end;
|
|
|
|
function TJvDockAdvPanel.CustomUnDock(Source: TJvDockDragDockObject;
|
|
NewTarget: TWinControl; Client: TControl): Boolean;
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, NewTarget);
|
|
Result := inherited CustomUnDock(Source, NewTarget, Client)
|
|
end;
|
|
|
|
procedure TJvDockAdvPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, TControl(Source.DragTarget));
|
|
inherited DockDrop(Source, X, Y);
|
|
end;
|
|
|
|
function TJvDockAdvPanel.DoUnDock(NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Client, NewTarget);
|
|
Result := inherited DoUnDock(NewTarget, Client);
|
|
end;
|
|
|
|
// NEW! -WPostma.
|
|
// Calls FADVTree.QueryControls which finds forms containing JvDockClient
|
|
// objects that are directly or indirectly docked to this panel.
|
|
|
|
procedure TJvDockAdvPanel.GetDockedControls(WinControls: TList); //override;
|
|
begin
|
|
{ (rb) Same result could be get via iterating property TWinControl.DockClients }
|
|
Assert(Assigned(WinControls));
|
|
if Assigned(JvDockManager) then
|
|
begin
|
|
WinControls.Clear;
|
|
{$IFDEF JVDOCK_QUERY}
|
|
JvDockManager.ControlQuery({Docked to self}Self, WinControls);
|
|
{$ENDIF JVDOCK_QUERY}
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDockAdvStyle } ====================================================
|
|
|
|
function TJvDockAdvStyle.DockClientWindowProc(DockClient: TJvDockClient;
|
|
var Msg: TMessage): Boolean;
|
|
begin
|
|
if (DockClient <> nil) and (Msg.Msg = WM_NCLBUTTONDBLCLK) then
|
|
if DockClient.CanFloat then
|
|
DockClient.RestoreChild;
|
|
Result := inherited DockClientWindowProc(DockClient, Msg);
|
|
end;
|
|
|
|
//=== { TJvDockAdvTabPageControl } ===========================================
|
|
|
|
destructor TJvDockAdvTabPageControl.Destroy;
|
|
//var
|
|
// DockClient: TJvDockClient;
|
|
begin
|
|
{ Now handled in TJvDockClient.SetLastDockSite }
|
|
// { Parent is always nil? Self is maintained by TJvDockTabHostForm (=Parent),
|
|
// Self is destroyed only if TJvDockTabHostForm is destroyed (thus is nil at
|
|
// this point }
|
|
// DockClient := FindDockClient(Parent);
|
|
// if (DockClient <> nil) and (DockClient.LastDockSite is TJvDockPanel) then
|
|
// with TJvDockPanel(DockClient.LastDockSite) do
|
|
// if UseDockManager and (JvDockManager <> nil) then
|
|
// JvDockManager.RemoveControl(Self.Parent);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDockAdvTabPageControl.CMUnDockClient(var Msg: TCMUnDockClient);
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
procedure TJvDockAdvTabPageControl.CustomDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, Source.TargetControl);
|
|
inherited CustomDockDrop(Source, X, Y);
|
|
end;
|
|
|
|
function TJvDockAdvTabPageControl.CustomUnDock(Source: TJvDockDragDockObject;
|
|
NewTarget: TWinControl; Client: TControl): Boolean;
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, NewTarget);
|
|
Result := inherited CustomUnDock(Source, NewTarget, Client)
|
|
end;
|
|
|
|
procedure TJvDockAdvTabPageControl.DockDrop(Source: TDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Source.Control, TControl(Source.DragTarget));
|
|
inherited DockDrop(Source, X, Y);
|
|
end;
|
|
|
|
function TJvDockAdvTabPageControl.DoUnDock(NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
if not JvGlobalDockIsLoading then
|
|
ResetDockClient(Client, NewTarget);
|
|
Result := inherited DoUnDock(NewTarget, Client);
|
|
end;
|
|
|
|
//=== { TJvDockBaseControl } =================================================
|
|
|
|
constructor TJvDockBaseControl.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
{ Dangerous/Dirty }
|
|
FParentForm := TForm(AOwner);
|
|
FEnableDock := True;
|
|
FLeftDock := True;
|
|
FTopDock := True;
|
|
FCustomDock := True; {Allowed to dock in custom area!}
|
|
FRightDock := True;
|
|
FBottomDock := True;
|
|
FEachOtherDock := True;
|
|
FDockStyle := nil;
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
FOldOnClose := FParentForm.OnClose;
|
|
ParentForm.OnClose := DoFormOnClose;
|
|
FOldOnCreate := FParentForm.OnCreate;
|
|
ParentForm.OnCreate := DoFormOnCreate;
|
|
FOldWindowProc := FParentForm.WindowProc;
|
|
FParentForm.WindowProc := WindowProc;
|
|
end;
|
|
end;
|
|
|
|
destructor TJvDockBaseControl.Destroy;
|
|
begin
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
if Assigned(FOldWindowProc) then
|
|
FParentForm.WindowProc := FOldWindowProc;
|
|
FOldWindowProc := nil;
|
|
{ ?? FDockStyle is always a TJvDockBasicStyle }
|
|
if Assigned(FDockStyle) {and not (FDockStyle is TJvDockBasicStyle)} then
|
|
FDockStyle.SetDockBaseControl(False, Self);
|
|
end;
|
|
DockStyle := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.AddDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
{ Notification }
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TJvDockBaseControl then
|
|
begin
|
|
EnableDock := TJvDockBaseControl(Source).EnableDock;
|
|
LeftDock := TJvDockBaseControl(Source).LeftDock;
|
|
TopDock := TJvDockBaseControl(Source).TopDock;
|
|
RightDock := TJvDockBaseControl(Source).RightDock;
|
|
BottomDock := TJvDockBaseControl(Source).BottomDock;
|
|
CustomDock := TJvDockBaseControl(Source).CustomDock; {NEW!}
|
|
EachOtherDock := TJvDockBaseControl(Source).EachOtherDock;
|
|
DockStyle := TJvDockBaseControl(Source).DockStyle;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
function TJvDockBaseControl.CanSetBottomDocked: Boolean;
|
|
begin
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.CanSetBottomDocked(Self)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBaseControl.CanSetEachOtherDocked: Boolean;
|
|
begin
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.CanSetEachOtherDocked(Self)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBaseControl.CanSetEnableDocked: Boolean;
|
|
begin
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.CanSetEnableDocked(Self)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBaseControl.CanSetLeftDocked: Boolean;
|
|
begin
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.CanSetLeftDocked(Self)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBaseControl.CanSetRightDocked: Boolean;
|
|
begin
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.CanSetRightDocked(Self)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBaseControl.CanSetTopDocked: Boolean;
|
|
begin
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.CanSetTopDocked(Self)
|
|
else
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.DoFormOnClose(Sender: TObject;
|
|
var Action: TCloseAction);
|
|
begin
|
|
{ Code is moved to AddDockStyle, RemoveDockStyle; if a user assigns OnClose,
|
|
OnCreate handlers things would go wrong.
|
|
}
|
|
if Assigned(FOldOnClose) then
|
|
FOldOnClose(Sender, Action);
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.DoFormOnCreate(Sender: TObject);
|
|
begin
|
|
{ Code is moved to AddDockStyle, RemoveDockStyle; if a user assigns OnClose,
|
|
OnCreate handlers things would go wrong.
|
|
}
|
|
if Assigned(FOldOnCreate) then
|
|
FOldOnCreate(Sender);
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if Operation = opRemove then
|
|
if AComponent = FDockStyle then
|
|
DockStyle := nil;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.RemoveDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
{ Notification }
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetBottomDock(const Value: Boolean);
|
|
begin
|
|
if CanSetBottomDocked then
|
|
FBottomDock := Value;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
{$IFDEF JVDOCK_DEBUG}
|
|
OutputDebugString('TJvDockBaseControl.SetDockStyle');
|
|
{$ENDIF JVDOCK_DEBUG}
|
|
if ADockStyle <> FDockStyle then
|
|
begin
|
|
ParentForm.DisableAlign;
|
|
try
|
|
if FDockStyle <> nil then
|
|
begin
|
|
{ Remove Self from the internal list of the dock style component }
|
|
FDockStyle.RemoveDockBaseControl(Self);
|
|
|
|
{ Give the ancestors a change to respond }
|
|
RemoveDockStyle(FDockStyle);
|
|
end;
|
|
|
|
ReplaceComponentReference (Self, ADockStyle, TComponent(FDockStyle));
|
|
|
|
if FDockStyle <> nil then
|
|
begin
|
|
{ Let the style initialize the TJvDockClient/TJvDockServer }
|
|
FDockStyle.SetDockBaseControl([csLoading, csDesigning] * ComponentState <> [], Self);
|
|
|
|
{ Add Self to the internal list of the dock style component }
|
|
FDockStyle.AddDockBaseControl(Self);
|
|
|
|
{ Give the ancestors a change to respond }
|
|
AddDockStyle(FDockStyle);
|
|
|
|
end;
|
|
finally
|
|
ParentForm.EnableAlign;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetEachOtherDock(const Value: Boolean);
|
|
begin
|
|
if CanSetEachOtherDocked then
|
|
FEachOtherDock := Value;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetEnableDock(const Value: Boolean);
|
|
begin
|
|
if CanSetEnableDocked then
|
|
FEnableDock := Value;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetLeftDock(const Value: Boolean);
|
|
begin
|
|
if CanSetLeftDocked then
|
|
FLeftDock := Value;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetParentComponent(Value: TComponent);
|
|
var
|
|
DockBaseControl: TJvDockBaseControl;
|
|
begin
|
|
DockBaseControl := FindDockBaseControl(ParentForm);
|
|
if Assigned(DockBaseControl) and (DockBaseControl <> Self) then
|
|
raise EInvalidOperation.CreateResFmt(@RsEDockCannotLayAnother, [DockBaseControl.ClassName, ClassName]);
|
|
inherited SetParentComponent(Value);
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetRightDock(const Value: Boolean);
|
|
begin
|
|
if CanSetRightDocked then
|
|
FRightDock := Value;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.SetTopDock(const Value: Boolean);
|
|
begin
|
|
if CanSetTopDocked then
|
|
FTopDock := Value;
|
|
end;
|
|
|
|
procedure TJvDockBaseControl.WindowProc(var Msg: TMessage);
|
|
begin
|
|
if not (csDesigning in ComponentState) then
|
|
if Assigned(FOldWindowProc) then
|
|
FOldWindowProc(Msg);
|
|
end;
|
|
|
|
//=== { TJvDockBasicStyle } ==================================================
|
|
|
|
constructor TJvDockBasicStyle.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
|
|
DockPanelClass := DefaultDockPanelClass;
|
|
DockSplitterClass := DefaultDockSplitterClass;
|
|
ConjoinPanelClass := DefaultConjoinPanelClass;
|
|
TabDockClass := DefaultTabDockClass;
|
|
DockPanelTreeClass := DefaultDockTreeClass;
|
|
DockPanelZoneClass := DefaultDockZoneClass;
|
|
ConjoinPanelTreeClass := DefaultDockTreeClass;
|
|
ConjoinPanelZoneClass := DefaultDockZoneClass;
|
|
FDockBaseControls := TList.Create;
|
|
end;
|
|
|
|
destructor TJvDockBasicStyle.Destroy;
|
|
begin
|
|
FDockBaseControls.Free;
|
|
FreeServerOption;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.AddDockBaseControl(ADockBaseControl: TJvDockBaseControl);
|
|
begin
|
|
{$IFDEF JVDOCK_DEBUG}
|
|
OutputDebugString('TJvDockBasicStyle.AddDockBaseControl');
|
|
{$ENDIF JVDOCK_DEBUG}
|
|
if ADockBaseControl = nil then
|
|
Exit;
|
|
FDockBaseControls.Add(ADockBaseControl);
|
|
end;
|
|
|
|
function TJvDockBasicStyle.CanSetBottomDocked(ADockBaseControl: TJvDockBaseControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.CanSetEachOtherDocked(ADockBaseControl: TJvDockBaseControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.CanSetEnableDocked(ADockBaseControl: TJvDockBaseControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.CanSetLeftDocked(ADockBaseControl: TJvDockBaseControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.CanSetRightDocked(ADockBaseControl: TJvDockBaseControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.CanSetTopDocked(ADockBaseControl: TJvDockBaseControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.DockClientWindowProc(DockClient: TJvDockClient; var Msg: TMessage): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.DockServerWindowProc(DockServer: TJvDockServer;
|
|
var Msg: TMessage): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormDockDrop(DockClient: TJvDockClient;
|
|
Source: TJvDockDragDockObject; X, Y: Integer);
|
|
var
|
|
ARect, DRect: TRect;
|
|
DockType: TAlign;
|
|
Host: TCustomForm;
|
|
APanelDock: TWinControl;
|
|
begin
|
|
if IsDockable(DockClient.ParentForm, Source.Control, Source.DropOnControl, Source.DropAlign) then
|
|
begin
|
|
Host := nil;
|
|
|
|
if not JvGlobalDockIsLoading then
|
|
JvDockLockWindow(nil);
|
|
try
|
|
with DockClient do
|
|
begin
|
|
DockType := ComputeDockingRect(DockClient.ParentForm, ARect, Point(X, Y));
|
|
|
|
if ParentForm.HostDockSite is TJvDockPanel then
|
|
begin
|
|
if DockType = alClient then
|
|
begin
|
|
if Source.Control is TJvDockTabHostForm then
|
|
begin
|
|
APanelDock := ParentForm.HostDockSite;
|
|
ARect := ParentForm.BoundsRect;
|
|
ParentForm.ManualDock(TJvDockTabHostForm(Source.Control).PageControl, nil, alClient);
|
|
TJvDockTabHostForm(Source.Control).PageControl.ActivePage.PageIndex := 0;
|
|
Source.Control.BoundsRect := ARect;
|
|
Source.Control.ManualDock(APanelDock, nil, alClient);
|
|
if ParentForm.FormStyle = fsStayOnTop then
|
|
TForm(Source.Control).FormStyle := fsStayOnTop;
|
|
end
|
|
else
|
|
begin
|
|
APanelDock := ParentForm.HostDockSite;
|
|
DRect.TopLeft := ParentForm.HostDockSite.ClientToScreen(Point(0, 0));
|
|
Host := CreateTabHostAndDockControl(ParentForm, Source.Control);
|
|
SetDockSite(ParentForm, False);
|
|
SetDockSite(TWinControl(Source.Control), False);
|
|
Host.Top := DRect.Top;
|
|
Host.Left := DRect.Left;
|
|
Host.ManualDock(APanelDock, nil, alClient);
|
|
Host.Visible := True;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
DRect := ParentForm.HostDockSite.BoundsRect;
|
|
Source.Control.ManualDock(ParentForm.HostDockSite, nil, DockType);
|
|
ParentForm.HostDockSite.BoundsRect := DRect;
|
|
end;
|
|
Exit;
|
|
end;
|
|
|
|
if DockType = alClient then
|
|
begin
|
|
Host := CreateTabHostAndDockControl(ParentForm, Source.Control);
|
|
SetDockSite(ParentForm, False);
|
|
SetDockSite(TWinControl(Source.Control), False);
|
|
Host.Visible := True;
|
|
end
|
|
else
|
|
if DockType <> alNone then
|
|
begin
|
|
Host := CreateConjoinHostAndDockControl(ParentForm, Source.Control, DockType);
|
|
SetDockSite(ParentForm, False);
|
|
SetDockSite(TWinControl(Source.Control), False);
|
|
Host.Visible := True;
|
|
end;
|
|
|
|
if Host <> nil then
|
|
begin
|
|
Host.LRDockWidth := Source.Control.LRDockWidth;
|
|
Host.TBDockHeight := Source.Control.TBDockHeight;
|
|
end;
|
|
end;
|
|
finally
|
|
if not JvGlobalDockIsLoading then
|
|
JvDockUnLockWindow;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormDockOver(DockClient: TJvDockClient;
|
|
Source: TJvDockDragDockObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
with DockClient do
|
|
begin
|
|
Accept := EnableDock and EachOtherDock and
|
|
IsDockable(ParentForm.HostDockSite, Source.Control, Source.DropOnControl, Source.DropAlign);
|
|
if Accept and (State = dsDragMove) and
|
|
(ComputeDockingRect(ParentForm, ARect, Point(X, Y)) <> alNone) then
|
|
Source.DockRect := ARect;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormEndDock(DockClient: TJvDockClient;
|
|
Target: TObject; X, Y: Integer);
|
|
begin
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormGetDockEdge(DockClient: TJvDockClient;
|
|
Source: TJvDockDragDockObject; MousePos: TPoint; var DropAlign: TAlign);
|
|
begin
|
|
DropAlign := TControlAccessProtected(DockClient.ParentForm).GetDockEdge(MousePos);
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormGetSiteInfo(Source: TJvDockDragDockObject;
|
|
DockClient: TJvDockClient; Client: TControl; var InfluenceRect: TRect;
|
|
MousePos: TPoint; var CanDock: Boolean);
|
|
begin
|
|
with DockClient do
|
|
CanDock := EnableDock and EachOtherDock and
|
|
IsDockable(ParentForm, Client, Source.DropOnControl, Source.DropAlign);
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormPositionDockRect(DockClient: TJvDockClient;
|
|
Source: TJvDockDragDockObject);
|
|
var
|
|
NewWidth, NewHeight: Integer;
|
|
TempX, TempY: Double;
|
|
R, TempDockRect: TRect;
|
|
begin
|
|
with Source do
|
|
begin
|
|
if (DragTarget = nil) or (not TWinControlAccessProtected(DragTarget).UseDockManager) then
|
|
begin
|
|
NewWidth := Control.UndockWidth;
|
|
NewHeight := Control.UndockHeight;
|
|
|
|
TempX := DragPos.X - ((NewWidth) * MouseDeltaX);
|
|
TempY := DragPos.Y - ((NewHeight) * MouseDeltaY);
|
|
TempDockRect := DockRect;
|
|
with TempDockRect do
|
|
begin
|
|
Left := Round(TempX);
|
|
Top := Round(TempY);
|
|
Right := Left + NewWidth;
|
|
Bottom := Top + NewHeight;
|
|
end;
|
|
DockRect := TempDockRect;
|
|
|
|
AdjustDockRect(DockRect);
|
|
end
|
|
else
|
|
begin
|
|
GetWindowRect(TargetControl.Handle, R);
|
|
DockRect := R;
|
|
if TWinControlAccessProtected(DragTarget).UseDockManager then
|
|
if TargetControl is TJvDockCustomPanel then
|
|
if (TJvDockCustomPanel(DragTarget).JvDockManager <> nil) then
|
|
begin
|
|
R := DockRect;
|
|
TJvDockCustomPanel(DragTarget).JvDockManager.PositionDockRect(Control,
|
|
DropOnControl, DropAlign, R);
|
|
DockRect := R;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.FormStartDock(DockClient: TJvDockClient;
|
|
var Source: TJvDockDragDockObject);
|
|
begin
|
|
end;
|
|
|
|
function TJvDockBasicStyle.FormUnDock(DockClient: TJvDockClient; NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.GetDockBaseControlCount: Integer;
|
|
begin
|
|
Result := FDockBaseControls.Count;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.GetDockBaseControl(Index: Integer): TJvDockBaseControl;
|
|
begin
|
|
Result := TJvDockBaseControl(FDockBaseControls[Index]);
|
|
end;
|
|
|
|
function TJvDockBasicStyle.GetDockFormVisible(ADockClient: TJvDockClient): Boolean;
|
|
begin
|
|
Result := True;
|
|
if ADockClient <> nil then
|
|
begin
|
|
if ADockClient.ParentForm.Visible then
|
|
begin
|
|
if ADockClient.ParentForm.HostDockSite <> nil then
|
|
begin
|
|
if ADockClient.ParentForm.HostDockSite is TJvDockPanel then
|
|
Result := ADockClient.ParentForm.HostDockSite.Width * ADockClient.ParentForm.HostDockSite.Height > 0
|
|
else
|
|
Result := GetFormVisible(ADockClient.ParentForm.HostDockSite.Parent);
|
|
end;
|
|
end
|
|
else
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function TJvDockBasicStyle.GetDockState(DockClient: TJvDockClient): Integer;
|
|
begin
|
|
Result := JvDockState_Unknown;
|
|
if (DockClient <> nil) and (DockClient.ParentForm <> nil) then
|
|
if DockClient.ParentForm.Floating then
|
|
Result := JvDockState_Floating
|
|
else
|
|
Result := JvDockState_Docking;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.HideDockForm(ADockClient: TJvDockClient);
|
|
begin
|
|
if ADockClient <> nil then
|
|
begin
|
|
ADockClient.ParentForm.Visible := False;
|
|
ADockClient.MakeHideEvent;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.RemoveDockBaseControl(ADockBaseControl: TJvDockBaseControl);
|
|
begin
|
|
FDockBaseControls.Remove(ADockBaseControl);
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.ResetCursor(Source: TJvDockDragDockObject);
|
|
begin
|
|
if (Source.TargetControl = nil) and (Source.Control <> nil) and (Source.Control.Floating) then
|
|
Windows.SetCursor(Screen.Cursors[crDefault])
|
|
else
|
|
if (Source.TargetControl = nil) and (not JvGlobalDockClient.CanFloat) then
|
|
Windows.SetCursor(Screen.Cursors[crNo])
|
|
else
|
|
Windows.SetCursor(Screen.Cursors[crDefault]);
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.RestoreClient(DockClient: TJvDockClient);
|
|
var
|
|
TmpLastDockSite: TWinControl;
|
|
TmpUnDockLeft, TmpUnDockTop: Integer;
|
|
I: Integer;
|
|
ADockClient: TJvDockClient;
|
|
ADockServer: TJvDockServer;
|
|
ARect: TRect;
|
|
|
|
procedure DoFloatParentForm;
|
|
begin
|
|
with DockClient do
|
|
if (ParentForm.HostDockSite <> nil) then
|
|
begin
|
|
ARect := Bounds(TmpUnDockLeft, TmpUnDockTop, ParentForm.UndockWidth, ParentForm.UndockHeight);
|
|
ParentForm.ManualFloat(ARect);
|
|
if (ParentForm.Left <> ARect.Left) or (ParentForm.Top <> ARect.Top) then
|
|
begin
|
|
ParentForm.Left := ARect.Left;
|
|
ParentForm.Top := ARect.Top;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if DockClient = nil then
|
|
Exit;
|
|
if not DockClient.CanFloat then
|
|
Exit;
|
|
with DockClient do
|
|
begin
|
|
if not EnableDock then
|
|
Exit;
|
|
if LastDockSite is TJvDockPanel then
|
|
begin
|
|
with TJvDockPanel(LastDockSite) do
|
|
begin
|
|
if ((not LeftDock) and (Align = alLeft)) or
|
|
((not RightDock) and (Align = alRight)) or
|
|
((not TopDock) and (Align = alTop)) or
|
|
((not BottomDock) and (Align = alBottom)) then
|
|
begin
|
|
DoFloatParentForm;
|
|
Exit;
|
|
end;
|
|
|
|
ADockServer := DockServer;
|
|
if ADockServer <> nil then
|
|
if (not ADockServer.EnableDock) or
|
|
((not ADockServer.LeftDock) and (Align = alLeft)) or
|
|
((not ADockServer.RightDock) and (Align = alRight)) or
|
|
((not ADockServer.TopDock) and (Align = alTop)) or
|
|
((not ADockServer.BottomDock) and (Align = alBottom)) then
|
|
begin
|
|
DoFloatParentForm;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if ParentForm is TJvDockConjoinHostForm then
|
|
begin
|
|
with TJvDockConjoinHostForm(ParentForm).Panel do
|
|
for I := DockClientCount - 1 downto 0 do
|
|
begin
|
|
ADockClient := FindDockClient(DockClients[I]);
|
|
if (ADockClient <> nil) and (ADockClient.LastDockSite is TJvDockPanel) then
|
|
ADockClient.RestoreChild;
|
|
end;
|
|
Exit;
|
|
end;
|
|
|
|
TmpLastDockSite := LastDockSite;
|
|
TmpUnDockLeft := UnDockLeft;
|
|
TmpUnDockTop := UnDockTop;
|
|
|
|
ResetDockClient(DockClient, nil);
|
|
|
|
DoFloatParentForm;
|
|
|
|
if TmpLastDockSite is TJvDockPanel then
|
|
begin
|
|
with TJvDockPanel(TmpLastDockSite) do
|
|
begin
|
|
if UseDockManager and (JvDockManager <> nil) then
|
|
begin
|
|
if not JvDockManager.HasZoneWithControl(ParentForm) then
|
|
Exit;
|
|
DisableAlign;
|
|
try
|
|
ParentForm.Dock(TmpLastDockSite, Rect(0, 0, 0, 0));
|
|
|
|
JvDockManager.ShowControl(ParentForm);
|
|
|
|
ParentForm.ActiveControl := nil;
|
|
SetDockSite(ParentForm, False);
|
|
|
|
if ParentForm.Visible and ParentForm.CanFocus then
|
|
ParentForm.SetFocus;
|
|
ShowDockPanel(True, ParentForm, sdfDockPanel);
|
|
finally
|
|
EnableAlign;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.SetDockBaseControl(IsCreate: Boolean;
|
|
DockBaseControl: TJvDockBaseControl);
|
|
begin
|
|
end;
|
|
|
|
procedure TJvDockBasicStyle.ShowDockForm(ADockClient: TJvDockClient);
|
|
begin
|
|
if ADockClient <> nil then
|
|
begin
|
|
ADockClient.ParentForm.Visible := True;
|
|
ADockClient.MakeShowEvent;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDockClient } ======================================================
|
|
|
|
constructor TJvDockClient.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FParentVisible := ParentForm.Visible;
|
|
ParentForm.DragKind := dkDock;
|
|
ParentForm.DragMode := dmAutomatic;
|
|
ParentForm.UseDockManager := False;
|
|
if not (ParentForm is TJvDockableForm) then
|
|
SetDockSite(ParentForm, True);
|
|
LRDockWidth := 100;
|
|
TBDockHeight := 100;
|
|
if JvGlobalDockClient = nil then
|
|
JvGlobalDockClient := Self;
|
|
FDirectDrag := False;
|
|
FShowHint := True;
|
|
FCanFloat := True;
|
|
FDockLevel := 0;
|
|
EnableCloseButton := True;
|
|
end;
|
|
|
|
destructor TJvDockClient.Destroy;
|
|
begin
|
|
if not (ParentForm is TJvDockableForm) then
|
|
SetDockSite(ParentForm, False);
|
|
ParentForm.DragKind := dkDrag;
|
|
ParentForm.DragMode := dmManual;
|
|
LastDockSite := nil;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDockClient.Activate;
|
|
begin
|
|
{$IFNDEF COMPILER9_UP}
|
|
if ParentForm.HostDockSite is TJvDockCustomPanel then
|
|
InvalidateDockHostSiteOfControl(ParentForm, False);
|
|
{$ENDIF !COMPILER9_UP}
|
|
end;
|
|
|
|
procedure TJvDockClient.AddDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
JvGlobalDockManager.RegisterDockClient(Self);
|
|
|
|
if Assigned(ADockStyle) and Assigned(ADockStyle.ConjoinPanelClass) then
|
|
FConjoinPanelClass := ADockStyle.ConjoinPanelClass
|
|
else
|
|
FConjoinPanelClass := DefaultConjoinPanelClass;
|
|
|
|
if Assigned(ADockStyle) and Assigned(ADockStyle.TabDockClass) then
|
|
FTabDockClass := ADockStyle.TabDockClass
|
|
else
|
|
FTabDockClass := DefaultTabDockClass;
|
|
end;
|
|
|
|
procedure TJvDockClient.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TJvDockClient then
|
|
begin
|
|
FConjoinPanelClass := TJvDockClient(Source).FConjoinPanelClass;
|
|
FTabDockClass := TJvDockClient(Source).FTabDockClass;
|
|
ParentVisible := TJvDockClient(Source).ParentVisible;
|
|
NCPopupMenu := TJvDockClient(Source).NCPopupMenu;
|
|
DirectDrag := TJvDockClient(Source).DirectDrag;
|
|
ShowHint := TJvDockClient(Source).ShowHint;
|
|
CanFloat := TJvDockClient(Source).CanFloat;
|
|
// (rom) either bug or needs comment
|
|
FDockLevel := TJvDockClient(Source).DockLevel;
|
|
CustomDock := TJvDockClient(Source).CustomDock; {NEW!}
|
|
DockStyle := TJvDockClient(Source).DockStyle;
|
|
end;
|
|
inherited Assign(Source); // Also copy base class properties!
|
|
end;
|
|
|
|
procedure TJvDockClient.CMVisibleChanged(var Msg: TMessage);
|
|
begin
|
|
end;
|
|
|
|
function TJvDockClient.CreateConjoinHostAndDockControl(Control1, Control2: TControl;
|
|
DockType: TAlign): TJvDockConjoinHostForm;
|
|
var
|
|
APanel: TJvDockConjoinPanel;
|
|
OldDockWidth, OldDockHeight: Integer;
|
|
begin
|
|
Result := TJvDockConjoinHostForm.Create(Application);
|
|
|
|
{ CreateConjoinPanelClass implicitly sets Result.DockClient.DockStyle via the
|
|
assign in that function }
|
|
APanel := CreateConjoinPanelClass(Result);
|
|
|
|
Result.BoundsRect := Control1.BoundsRect;
|
|
|
|
Result.Width := Control1.UndockWidth;
|
|
Result.Height := Control1.UndockHeight;
|
|
|
|
OldDockWidth := Control1.LRDockWidth;
|
|
OldDockHeight := Control1.TBDockHeight;
|
|
Control1.ManualDock(APanel, nil, alNone);
|
|
Control1.LRDockWidth := OldDockWidth;
|
|
Control1.TBDockHeight := OldDockHeight;
|
|
|
|
OldDockWidth := Control2.LRDockWidth;
|
|
OldDockHeight := Control2.TBDockHeight;
|
|
Control2.ManualDock(APanel, nil, DockType);
|
|
Control2.LRDockWidth := OldDockWidth;
|
|
Control2.TBDockHeight := OldDockHeight;
|
|
|
|
SetDockSite(Result, False);
|
|
end;
|
|
|
|
function TJvDockClient.CreateConjoinPanelClass(ConjoinHost: TForm): TJvDockConjoinPanel;
|
|
begin
|
|
Result := nil;
|
|
TJvDockConjoinHostForm(ConjoinHost).DockClient.Assign(Self);
|
|
if (FConjoinPanelClass <> nil) and
|
|
(FConjoinPanelClass <> TJvDockConjoinPanelClass(ClassType)) then
|
|
begin
|
|
Result := FConjoinPanelClass.Create(ConjoinHost);
|
|
Result.Align := alClient;
|
|
TJvDockConjoinHostForm(ConjoinHost).DockableControl := Result;
|
|
TJvDockConjoinHostForm(ConjoinHost).Panel := Result;
|
|
SetDockSite(Result, True);
|
|
end;
|
|
end;
|
|
|
|
{ CreateTabDockClass creates a TJvDockTabPageControl subclass. The actual subclass
|
|
used is stored in FTabDockClass which is assigned by the Docking Style object,
|
|
so this is truly polymorphic.
|
|
|
|
We need a TJvDockTabPageControl to do tabbed-docking inside a container form.
|
|
The typical container this is placed inside of is either a
|
|
TJvDockConjoinHostForm or TJvDockTabHostForm.
|
|
}
|
|
|
|
function TJvDockClient.CreateTabDockClass(TabHost: TForm): TJvDockTabPageControl;
|
|
begin
|
|
Result := nil;
|
|
{ copy properties of the JvTabDockPageControl's DockClient
|
|
from the form it contains. }
|
|
TJvDockTabHostForm(TabHost).DockClient.Assign(Self);
|
|
|
|
// Next line commented out, it seems it is useless. See Mantis 3900.
|
|
// Assert(TJvDockTabHostForm(TabHost).DockClient.CustomDock, 'DEBUG HELPER: Not working!');
|
|
|
|
if (FTabDockClass <> nil) and (FTabDockClass <> TJvDockTabClass(ClassType)) then
|
|
begin
|
|
Result := FTabDockClass.Create(TabHost);
|
|
Result.Align := alClient;
|
|
TJvDockTabHostForm(TabHost).DockableControl := Result;
|
|
TJvDockTabHostForm(TabHost).PageControl := Result;
|
|
SetDockSite(Result, True);
|
|
end;
|
|
end;
|
|
|
|
{ This is the main function for creating a tabbed dock, given two non-tab-docked
|
|
controls (usually these are actually Forms), we create a TJvDockTabHostForm,
|
|
and then inside it we create a TabDock container. A TJvDockTabHostForm is
|
|
an empty TForm containing a DockClient object, and then it contains a set of
|
|
tabbed pages inside the TJvDockTabPageControl object (Page). }
|
|
|
|
function TJvDockClient.CreateTabHostAndDockControl(Control1, Control2: TControl): TJvDockTabHostForm;
|
|
var
|
|
Page: TJvDockTabPageControl;
|
|
OldDockWidth, OldDockHeight: Integer;
|
|
begin
|
|
Result := TJvDockTabHostForm.Create(Application);
|
|
Result.Name := 'TJvDockTabHostForm_' + Control1.Name + '_' + Control2.Name + '_' +
|
|
IntToHex(Integer(Result), 8);
|
|
|
|
{ CreateTabDockClass implicitly sets Result.DockClient.DockStyle via the
|
|
assign in that function }
|
|
Page := CreateTabDockClass(Result);
|
|
Page.Name := Page.ClassName + '_' + Control1.Name + '_' + Control2.Name; // debug!
|
|
|
|
Result.BoundsRect := Control1.BoundsRect;
|
|
|
|
Result.Width := Control1.UndockWidth;
|
|
Result.Height := Control1.UndockHeight;
|
|
|
|
OldDockWidth := Control1.LRDockWidth;
|
|
OldDockHeight := Control1.TBDockHeight;
|
|
Control1.ManualDock(Page, nil, alClient);
|
|
Control1.LRDockWidth := OldDockWidth;
|
|
Control1.TBDockHeight := OldDockHeight;
|
|
|
|
OldDockWidth := Control2.LRDockWidth;
|
|
OldDockHeight := Control2.TBDockHeight;
|
|
Control2.ManualDock(Page, nil, alClient);
|
|
Control2.LRDockWidth := OldDockWidth;
|
|
Control2.TBDockHeight := OldDockHeight;
|
|
|
|
SetDockSite(Result, False);
|
|
//TJvDockTabHostFormCreatedEvent:
|
|
if Assigned(FOnTabHostFormCreated) then
|
|
FOnTabHostFormCreated(Self, {TabHost:TJvDockTabHostForm} Result);
|
|
end;
|
|
|
|
procedure TJvDockClient.Deactivate;
|
|
begin
|
|
{$IFNDEF COMPILER9_UP}
|
|
if ParentForm.HostDockSite is TJvDockCustomPanel then
|
|
InvalidateDockHostSiteOfControl(ParentForm, True);
|
|
{$ENDIF !COMPILER9_UP}
|
|
end;
|
|
|
|
procedure TJvDockClient.DoFloatDockClients(PanelAlign: TAlign);
|
|
begin
|
|
if not (csDestroying in ParentForm.ComponentState) and
|
|
(ParentForm.HostDockSite is TJvDockPanel) and
|
|
(PanelAlign = ParentForm.HostDockSite.Align) then
|
|
RestoreChild;
|
|
end;
|
|
|
|
procedure TJvDockClient.DoFloatDockEachOther;
|
|
begin
|
|
if not (csDestroying in ParentForm.ComponentState) and
|
|
(ParentForm.HostDockSite <> nil) and
|
|
(ParentForm.HostDockSite.Parent is TJvDockableForm) then
|
|
RestoreChild;
|
|
end;
|
|
|
|
procedure TJvDockClient.DoFormOnClose(Sender: TObject; var Action: TCloseAction);
|
|
begin
|
|
if Action = caHide then
|
|
begin
|
|
HideDockForm(ParentForm);
|
|
FParentVisible := True;
|
|
end;
|
|
inherited DoFormOnClose(Sender, Action);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoFormShowHint(HTFlag: Integer; var HintStr: string;
|
|
var CanShow: Boolean);
|
|
begin
|
|
if Assigned(FOnFormShowHint) then
|
|
FOnFormShowHint(HTFlag, HintStr, CanShow);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoMenuPopup(X, Y: Integer);
|
|
begin
|
|
if FNCPopupMenu <> nil then
|
|
begin
|
|
FNCPopupMenu.PopupComponent := ParentForm;
|
|
FNCPopupMenu.Popup(X, Y);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockClient.DoNCButtonDblClk(Msg: TWMNCHitMessage; Button: TMouseButton;
|
|
MouseStation: TJvDockMouseStation);
|
|
begin
|
|
if Assigned(FOnNCButtonDblClk) then
|
|
FOnNCButtonDblClk(Self, Button, Msg.XCursor, Msg.YCursor,
|
|
Msg.HitTest, MouseStation);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoNCButtonDown(Msg: TWMNCHitMessage;
|
|
Button: TMouseButton; MouseStation: TJvDockMouseStation);
|
|
begin
|
|
if Assigned(FOnNCButtonDown) then
|
|
FOnNCButtonDown(Self, Button, Msg.XCursor, Msg.YCursor,
|
|
Msg.HitTest, MouseStation);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoNCButtonUp(Msg: TWMNCHitMessage;
|
|
Button: TMouseButton; MouseStation: TJvDockMouseStation);
|
|
begin
|
|
if Assigned(FOnNCButtonUp) then
|
|
FOnNCButtonUp(Self, Button, Msg.XCursor, Msg.YCursor,
|
|
Msg.HitTest, MouseStation);
|
|
if Button = mbRight then
|
|
DoMenuPopup(Msg.XCursor, Msg.YCursor);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoNCMouseMove(Msg: TWMNCHitMessage;
|
|
MouseStation: TJvDockMouseStation);
|
|
begin
|
|
if Assigned(FOnNCMouseMove) then
|
|
FOnNCMouseMove(Self, Msg.XCursor, Msg.YCursor,
|
|
Msg.HitTest, MouseStation);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoPaintDockGrabber(Canvas: TCanvas;
|
|
Control: TControl; const ARect: TRect);
|
|
begin
|
|
if Assigned(FOnPaintDockGrabber) then
|
|
FOnPaintDockGrabber(Canvas, Control, ARect);
|
|
end;
|
|
|
|
procedure TJvDockClient.DoPaintDockSplitter(Canvas: TCanvas;
|
|
Control: TControl; const ARect: TRect);
|
|
begin
|
|
if Assigned(FOnPaintDockSplitter) then
|
|
FOnPaintDockSplitter(Canvas, Control, ARect);
|
|
end;
|
|
|
|
// return nil if not found, otherwise, get currently docked parent tabhost form if there is one.
|
|
|
|
function TJvDockClient.FindTabHostForm: TForm;
|
|
var
|
|
OwnerWin: TWinControl;
|
|
TabSheet: TJvDockTabSheet;
|
|
CheckForm: TComponent;
|
|
begin
|
|
Result := nil;
|
|
if not Assigned(Owner) then
|
|
Exit;
|
|
if not (Owner is TWinControl) then
|
|
Exit;
|
|
OwnerWin := TWinControl(Owner);
|
|
if Self.DockState <> JvDockState_Docking then
|
|
Exit;
|
|
if not Assigned(OwnerWin.Parent) then
|
|
Exit;
|
|
if OwnerWin.Parent is TJvDockTabSheet then
|
|
begin
|
|
TabSheet := TJvDockTabSheet(OwnerWin.Parent);
|
|
if TabSheet.Owner is TJvDockPageControl then
|
|
begin
|
|
CheckForm := TJvDockPageControl(TabSheet.Owner).Owner;
|
|
if CheckForm is TJvDockTabHostForm then
|
|
Result := TForm(CheckForm);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockClient.FormDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormDockDrop(Self, Source, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockClient.FormDockOver(Source: TJvDockDragDockObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
begin
|
|
FormPositionDockRect(Source);
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormDockOver(Self, Source, X, Y, State, Accept);
|
|
end;
|
|
|
|
procedure TJvDockClient.FormEndDock(Target: TObject; X, Y: Integer);
|
|
begin
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormEndDock(Self, Target, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockClient.FormGetDockEdge(Source: TJvDockDragDockObject;
|
|
MousePos: TPoint; var DropAlign: TAlign);
|
|
begin
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormGetDockEdge(Self, Source, MousePos, DropAlign)
|
|
else
|
|
DropAlign := alNone;
|
|
end;
|
|
|
|
procedure TJvDockClient.FormGetSiteInfo(Source: TJvDockDragDockObject; Client: TControl;
|
|
var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
|
|
begin
|
|
GetWindowRect(ParentForm.Handle, InfluenceRect);
|
|
InflateRect(InfluenceRect, -4, -4);
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormGetSiteInfo(Source, Self, Client, InfluenceRect, MousePos, CanDock);
|
|
end;
|
|
|
|
procedure TJvDockClient.FormPositionDockRect(Source: TJvDockDragDockObject);
|
|
begin
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormPositionDockRect(Self, Source);
|
|
end;
|
|
|
|
procedure TJvDockClient.FormStartDock(var Source: TJvDockDragDockObject);
|
|
begin
|
|
if Assigned(DockStyle) then
|
|
DockStyle.FormStartDock(Self, Source);
|
|
end;
|
|
|
|
function TJvDockClient.FormUnDock(NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
if Assigned(DockStyle) then
|
|
Result := DockStyle.FormUnDock(Self, NewTarget, Client)
|
|
else
|
|
Result := False;
|
|
end;
|
|
|
|
function TJvDockClient.GetDockState: Integer;
|
|
begin
|
|
Result := JvDockState_Unknown;
|
|
if DockStyle <> nil then
|
|
Result := DockStyle.GetDockState(Self);
|
|
end;
|
|
|
|
function TJvDockClient.GetLRDockWidth: Integer;
|
|
begin
|
|
Result := ParentForm.LRDockWidth;
|
|
end;
|
|
|
|
function TJvDockClient.GetTBDockHeight: Integer;
|
|
begin
|
|
Result := ParentForm.TBDockHeight;
|
|
end;
|
|
|
|
procedure TJvDockClient.HideParentForm;
|
|
begin
|
|
HideDockForm(ParentForm);
|
|
end;
|
|
|
|
procedure TJvDockClient.MakeHideEvent;
|
|
begin
|
|
ParentVisible := False;
|
|
if Assigned(FOnFormHide) then
|
|
FOnFormHide(Self);
|
|
end;
|
|
|
|
procedure TJvDockClient.MakeShowEvent;
|
|
begin
|
|
if ParentForm.Visible then
|
|
begin
|
|
if Assigned(FOnFormShow) then
|
|
FOnFormShow(Self);
|
|
ParentVisible := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockClient.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if Operation = opRemove then
|
|
begin
|
|
if AComponent = FLastDockSite then
|
|
LastDockSite := nil
|
|
else
|
|
if AComponent = NCPopupMenu then
|
|
NCPopupMenu := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockClient.RemoveDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
DoFloatDockClients(alTop);
|
|
DoFloatDockClients(alBottom);
|
|
DoFloatDockClients(alLeft);
|
|
DoFloatDockClients(alRight);
|
|
DoFloatDockEachOther;
|
|
|
|
FConjoinPanelClass := nil;
|
|
FTabDockClass := nil;
|
|
|
|
if JvGlobalDockManager <> nil then
|
|
JvGlobalDockManager.UnRegisterDockClient(Self);
|
|
end;
|
|
|
|
procedure TJvDockClient.RestoreChild;
|
|
begin
|
|
DockStyle.RestoreClient(Self);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetBottomDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(alBottom);
|
|
inherited SetBottomDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetCanFloat(const Value: Boolean);
|
|
begin
|
|
FCanFloat := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetCurrentDockSite(const Value: TWinControl);
|
|
begin
|
|
FCurrentDockSite := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetDockLevel(const Value: Integer);
|
|
begin
|
|
if not ParentForm.Floating then
|
|
if FDockLevel <> Value then
|
|
DoFloatForm(ParentForm);
|
|
FDockLevel := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetEachOtherDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockEachOther;
|
|
inherited SetEachOtherDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetEnableCloseButton(const Value: Boolean);
|
|
begin
|
|
FEnableCloseButton := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetEnableDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
begin
|
|
DoFloatDockClients(alTop);
|
|
DoFloatDockClients(alBottom);
|
|
DoFloatDockClients(alLeft);
|
|
DoFloatDockClients(alRight);
|
|
DoFloatDockEachOther;
|
|
end;
|
|
if ParentForm <> nil then
|
|
if Value then
|
|
ParentForm.DragKind := dkDock
|
|
else
|
|
ParentForm.DragKind := dkDrag;
|
|
inherited SetEnableDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetLastDockSite(ALastDockSite: TWinControl);
|
|
var
|
|
JvDockManager: IJvDockManager;
|
|
begin
|
|
if ALastDockSite <> FLastDockSite then
|
|
begin
|
|
if FLastDockSite <> nil then
|
|
begin
|
|
if TWinControlAccessProtected(FLastDockSite).UseDockManager and
|
|
Supports(TWinControlAccessProtected(FLastDockSite).DockManager, IJvDockManager, JvDockManager) then
|
|
JvDockManager.RemoveControl(Self.ParentForm);
|
|
end;
|
|
ReplaceComponentReference (Self, ALastDockSite, TComponent(FLastDockSite));
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetLeftDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(alLeft);
|
|
inherited SetLeftDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetLRDockWidth(const Value: Integer);
|
|
begin
|
|
if ParentForm.LRDockWidth <> Value then
|
|
ParentForm.LRDockWidth := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetNCPopupMenu(Value: TPopupMenu);
|
|
begin
|
|
ReplaceComponentReference (Self, Value, TComponent(FNCPopupMenu));
|
|
end;
|
|
|
|
procedure TJvDockClient.SetParentVisible(const Value: Boolean);
|
|
begin
|
|
FParentVisible := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetRightDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(alRight);
|
|
inherited SetRightDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetTBDockHeight(const Value: Integer);
|
|
begin
|
|
if ParentForm.TBDockHeight <> Value then
|
|
ParentForm.TBDockHeight := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetTopDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(alTop);
|
|
inherited SetTopDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockClient.SetUnDockLeft(const Value: Integer);
|
|
begin
|
|
FUnDockLeft := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetUnDockTop(const Value: Integer);
|
|
begin
|
|
FUnDockTop := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.SetVSPaneWidth(const Value: Integer);
|
|
begin
|
|
FVSPaneWidth := Value;
|
|
end;
|
|
|
|
procedure TJvDockClient.ShowParentForm;
|
|
begin
|
|
ShowDockForm(ParentForm);
|
|
end;
|
|
|
|
procedure TJvDockClient.WindowProc(var Msg: TMessage);
|
|
var
|
|
OldOrient: TDockOrientation;
|
|
begin
|
|
if Assigned(FDockStyle) then
|
|
if FDockStyle.DockClientWindowProc(Self, Msg) then
|
|
Exit;
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
case Msg.Msg of
|
|
CM_SHOWINGCHANGED:
|
|
if IsWinXP_UP and JvGlobalDockIsLoading then
|
|
begin
|
|
if GShowingChanged = nil then
|
|
GShowingChanged := TList.Create;
|
|
GShowingChanged.Add(ParentForm);
|
|
Exit;
|
|
end;
|
|
WM_NCLBUTTONDOWN:
|
|
begin
|
|
WMNCLButtonDown(TWMNCHitMessage(Msg));
|
|
if Msg.Result = 1 then
|
|
Exit;
|
|
end;
|
|
WM_NCLBUTTONUP:
|
|
WMNCLButtonUp(TWMNCHitMessage(Msg));
|
|
WM_NCLBUTTONDBLCLK:
|
|
WMNCLButtonDblClk(TWMNCHitMessage(Msg));
|
|
WM_NCMBUTTONDOWN:
|
|
WMNCMButtonDown(TWMNCHitMessage(Msg));
|
|
WM_NCMBUTTONUP:
|
|
WMNCMButtonUp(TWMNCHitMessage(Msg));
|
|
WM_NCMBUTTONDBLCLK:
|
|
WMNCMButtonDblClk(TWMNCHitMessage(Msg));
|
|
WM_NCRBUTTONDOWN:
|
|
begin
|
|
WMNCRButtonDown(TWMNCHitMessage(Msg));
|
|
if FNCPopupMenu <> nil then
|
|
Exit;
|
|
end;
|
|
WM_NCRBUTTONUP:
|
|
WMNCRButtonUp(TWMNCHitMessage(Msg));
|
|
WM_NCRBUTTONDBLCLK:
|
|
WMNCRButtonDblClk(TWMNCHitMessage(Msg));
|
|
WM_NCMOUSEMOVE:
|
|
WMNCMouseMove(TWMNCHitMessage(Msg));
|
|
WM_SIZE:
|
|
WMSize(TWMSize(Msg));
|
|
WM_ACTIVATE:
|
|
WMActivate(TWMActivate(Msg));
|
|
WM_WINDOWPOSCHANGED:
|
|
begin
|
|
ParentForm.ControlState := ParentForm.ControlState + [csDocking];
|
|
OldOrient := ParentForm.DockOrientation;
|
|
ParentForm.DockOrientation := doNoOrient;
|
|
try
|
|
inherited WindowProc(Msg);
|
|
finally
|
|
ParentForm.ControlState := ParentForm.ControlState - [csDocking];
|
|
ParentForm.DockOrientation := OldOrient;
|
|
end;
|
|
Exit;
|
|
end;
|
|
CM_ENTER:
|
|
Activate;
|
|
CM_EXIT:
|
|
Deactivate;
|
|
CM_VISIBLECHANGED:
|
|
CMVisibleChanged(Msg);
|
|
end;
|
|
end;
|
|
|
|
inherited WindowProc(Msg);
|
|
|
|
if Msg.Msg = WM_SETTEXT then
|
|
if ParentForm.HostDockSite is TJvDockCustomControl then
|
|
TJvDockCustomControl(ParentForm.HostDockSite).UpdateCaption(ParentForm);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMActivate(var Msg: TWMActivate);
|
|
begin
|
|
{$IFNDEF COMPILER9_UP}
|
|
InvalidateDockHostSiteOfControl(ParentForm.ActiveControl, Msg.Active = WA_INACTIVE);
|
|
{$ENDIF !COMPILER9_UP}
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCLButtonDblClk(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonDblClk(Msg, mbLeft, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCLButtonDown(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonDown(Msg, mbLeft, msFloat);
|
|
|
|
JvGlobalDockClient := Self;
|
|
|
|
if (Msg.HitTest = HTCAPTION) and (ParentForm.DragKind = dkDock) and not
|
|
(csDesigning in ComponentState) and not IsIconic(ParentForm.Handle) then
|
|
begin
|
|
SetWindowPos(ParentForm.Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE);
|
|
PostMessage(ParentForm.Handle, WM_NCLBUTTONUP, TMessage(Msg).WParam, TMessage(Msg).LParam);
|
|
if ParentForm.Active then
|
|
JvGlobalDockManager.BeginDrag(ParentForm, DirectDrag, Integer(DirectDrag) * 2 - 1);
|
|
Msg.Result := 1;
|
|
end
|
|
else
|
|
Msg.Result := 0;
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCLButtonUp(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonUp(Msg, mbLeft, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCMButtonDblClk(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonDblClk(Msg, mbMiddle, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCMButtonDown(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonDown(Msg, mbMiddle, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCMButtonUp(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonUp(Msg, mbMiddle, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCMouseMove(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCMouseMove(Msg, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCRButtonDblClk(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonDblClk(Msg, mbRight, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCRButtonDown(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonDown(Msg, mbRight, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMNCRButtonUp(var Msg: TWMNCHitMessage);
|
|
begin
|
|
DoNCButtonUp(Msg, mbRight, msFloat);
|
|
end;
|
|
|
|
procedure TJvDockClient.WMSize(var Msg: TWMSize);
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
//=== { TJvDockConjoinHostForm } =============================================
|
|
|
|
constructor TJvDockConjoinHostForm.Create(AOwner: TComponent);
|
|
begin
|
|
{$IFDEF JVDOCK_DEBUG}
|
|
OutputDebugString('TJvDockConjoinHostForm.Create');
|
|
{$ENDIF JVDOCK_DEBUG}
|
|
inherited Create(AOwner);
|
|
BorderStyle := ConjoinDockHostBorderStyle;
|
|
end;
|
|
|
|
procedure TJvDockConjoinHostForm.DoClose(var Action: TCloseAction);
|
|
begin
|
|
inherited DoClose(Action);
|
|
end;
|
|
|
|
//=== { TJvDockConjoinPanel } ================================================
|
|
|
|
constructor TJvDockConjoinPanel.Create(AOwner: TComponent);
|
|
begin
|
|
{$IFDEF JVDOCK_DEBUG}
|
|
OutputDebugString('TJvDockConjoinPanel.Create');
|
|
{$ENDIF JVDOCK_DEBUG}
|
|
inherited Create(AOwner);
|
|
Parent := TWinControl(AOwner);
|
|
Align := alClient;
|
|
BevelOuter := bvNone;
|
|
DoubleBuffered := True;
|
|
ParentFont := False;
|
|
Caption := '';
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CMUnDockClient(var Msg: TCMUnDockClient);
|
|
begin
|
|
inherited;
|
|
{ Panel can be closed when
|
|
* DockClientCount <= 1:
|
|
One hidden form left that is freed. Call originates from TControl.Destroy
|
|
* DockClientCount=2 and VisibleDockClientCount=1
|
|
Two forms left, one is freed. Call originates from TControl.Destroy or
|
|
TJvDockManager.DoUnDock etc.
|
|
}
|
|
if (DockClientCount <= 1) or ((DockClientCount = 2) and (VisibleDockClientCount = 1)) then
|
|
PostMessage(ParentForm.Handle, WM_CLOSE, 0, 0);
|
|
if VisibleDockClientCount <= 2 then
|
|
JvDockControlForm.UpdateCaption(Self, Msg.Client);
|
|
if UseDockManager and (JvDockManager <> nil) then
|
|
JvDockManager.ResetBounds(True);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CustomDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited CustomDockDrop(Source, X, Y);
|
|
if Source.Control is TForm then
|
|
begin
|
|
ParentForm.ActiveControl := nil;
|
|
if TForm(Source.Control).FormStyle = fsStayOnTop then
|
|
TForm(Parent).FormStyle := fsStayOnTop;
|
|
end;
|
|
UpdateCaption(nil);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CustomDockOver(Source: TJvDockDragDockObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
begin
|
|
inherited CustomDockOver(Source, X, Y, State, Accept);
|
|
Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CustomEndDock(Target: TObject; X, Y: Integer);
|
|
begin
|
|
inherited CustomEndDock(Target, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CustomGetSiteInfo(Source: TJvDockDragDockObject;
|
|
Client: TControl; var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
|
|
begin
|
|
CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
|
|
inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CustomPositionDockRect(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited CustomPositionDockRect(Source, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.CustomStartDock(var Source: TJvDockDragDockObject);
|
|
begin
|
|
ParentForm.FUnDockControl := nil;
|
|
inherited CustomStartDock(Source);
|
|
end;
|
|
|
|
function TJvDockConjoinPanel.CustomUnDock(Source: TJvDockDragDockObject;
|
|
NewTarget: TWinControl; Client: TControl): Boolean;
|
|
begin
|
|
ParentForm.FUnDockControl := Client;
|
|
|
|
if not (Client is TJvDockableForm) then
|
|
SetDockSite(TForm(Client), True);
|
|
if ((VisibleDockClientCount = 1) or
|
|
(DockClientCount <= 2)) and (NewTarget <> ParentForm.DockableControl) then
|
|
PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
|
|
UpdateCaption(Client);
|
|
Result := inherited CustomUnDock(Source, NewTarget, Client);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
|
|
begin
|
|
if Perform(CM_DOCKCLIENT, WPARAM(Source), LPARAM(SmallPoint(X, Y))) >= 0 then
|
|
begin
|
|
if Source.Control is TForm then
|
|
begin
|
|
ParentForm.ActiveControl := nil;
|
|
TForm(Source.Control).ActiveControl := nil;
|
|
|
|
SetDockSite(TForm(Source.Control), False);
|
|
if TForm(Source.Control).FormStyle = fsStayOnTop then
|
|
TForm(Parent).FormStyle := fsStayOnTop;
|
|
end;
|
|
UpdateCaption(nil);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.DoDockOver(Source: TDragDockObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
begin
|
|
Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
|
|
end;
|
|
|
|
function TJvDockConjoinPanel.DoUnDock(NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
ParentForm.FUnDockControl := Client;
|
|
|
|
if not (Client is TJvDockableForm) then
|
|
SetDockSite(TForm(Client), True);
|
|
if (VisibleDockClientCount = 1) or
|
|
(DockClientCount <= 2) then
|
|
{ It's possible that 2 WM_CLOSE are send to the parent form }
|
|
PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
|
|
UpdateCaption(Client);
|
|
Result := Perform(CM_UNDOCKCLIENT, WPARAM(NewTarget), LPARAM(Client)) = 0;
|
|
end;
|
|
|
|
function TJvDockConjoinPanel.GetDockClient: TJvDockClient;
|
|
begin
|
|
if Assigned(ParentForm) then
|
|
Result := ParentForm.FDockClient
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJvDockConjoinPanel.GetParentForm: TJvDockConjoinHostForm;
|
|
begin
|
|
{ Dirty }
|
|
Result := TJvDockConjoinHostForm(Parent);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.GetSiteInfo(Client: TControl;
|
|
var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
|
|
begin
|
|
CanDock := IsDockable(Self, Client);
|
|
if CanDock then
|
|
GetWindowRect(Handle, InfluenceRect);
|
|
end;
|
|
|
|
procedure TJvDockConjoinPanel.ReloadDockedControl(const AControlName: string;
|
|
var AControl: TControl);
|
|
begin
|
|
AControl := JvDockFindDockFormWithName(AControlName);
|
|
end;
|
|
|
|
function TJvDockConjoinPanel.CreateDockManager: IDockManager;
|
|
var
|
|
TreeClass: TJvDockTreeClass;
|
|
ADockStyle: TJvDockBasicStyle;
|
|
begin
|
|
Result := nil;
|
|
|
|
if (DockManager = nil) and DockSite and UseDockManager then
|
|
begin
|
|
if Assigned(DockClient) then
|
|
begin
|
|
ADockStyle := DockClient.DockStyle;
|
|
if Assigned(ADockStyle) then
|
|
begin
|
|
TreeClass := ADockStyle.ConjoinPanelTreeClass;
|
|
if Assigned(TreeClass) and (TreeClass <> TJvDockTree) then
|
|
Result := TreeClass.Create(Self, ADockStyle.ConjoinPanelZoneClass, ADockStyle) as IJvDockManager;
|
|
end;
|
|
end;
|
|
end;
|
|
if Result = nil then
|
|
Result := DockManager;
|
|
DoubleBuffered := DoubleBuffered or (Result <> nil);
|
|
end;
|
|
|
|
//=== { TJvDockPanel } =======================================================
|
|
|
|
constructor TJvDockPanel.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
DoubleBuffered := True;
|
|
BevelOuter := bvNone;
|
|
Width := 10;
|
|
Height := 10;
|
|
end;
|
|
|
|
procedure TJvDockPanel.AddDockServer(ADockServer: TJvDockServer);
|
|
begin
|
|
{ Notification }
|
|
end;
|
|
|
|
procedure TJvDockPanel.CustomDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited CustomDockDrop(Source, X, Y);
|
|
|
|
if Source.Control <> nil then
|
|
ShowDockPanel(True, Source.Control);
|
|
end;
|
|
|
|
procedure TJvDockPanel.CustomDockOver(Source: TJvDockDragDockObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
begin
|
|
Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
|
|
if Accept then
|
|
inherited CustomDockOver(Source, X, Y, State, Accept);
|
|
end;
|
|
|
|
procedure TJvDockPanel.CustomEndDock(Target: TObject; X, Y: Integer);
|
|
begin
|
|
inherited CustomEndDock(Target, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockPanel.CustomGetSiteInfo(Source: TJvDockDragDockObject; Client: TControl;
|
|
var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
|
|
begin
|
|
inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock);
|
|
CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
|
|
end;
|
|
|
|
procedure TJvDockPanel.CustomPositionDockRect(Source: TJvDockDragDockObject; X, Y: Integer);
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
inherited CustomPositionDockRect(Source, X, Y);
|
|
if (VisibleDockClientCount = 0) and (JvGlobalDockClient <> nil) then
|
|
begin
|
|
case Align of
|
|
alTop:
|
|
begin
|
|
ARect.TopLeft := ClientToScreen(Point(0, 0));
|
|
ARect.BottomRight := ClientToScreen(Point(Width, Source.Control.TBDockHeight));
|
|
end;
|
|
alBottom:
|
|
begin
|
|
ARect.TopLeft := ClientToScreen(Point(0, -Source.Control.TBDockHeight));
|
|
ARect.BottomRight := ClientToScreen(Point(Width, 0));
|
|
end;
|
|
alLeft:
|
|
begin
|
|
ARect.TopLeft := ClientToScreen(Point(0, 0));
|
|
ARect.BottomRight := ClientToScreen(Point(Source.Control.LRDockWidth, Height));
|
|
end;
|
|
alRight:
|
|
begin
|
|
ARect.TopLeft := ClientToScreen(Point(-Source.Control.LRDockWidth, 0));
|
|
ARect.BottomRight := ClientToScreen(Point(Width, Height));
|
|
end;
|
|
alClient:
|
|
begin
|
|
ARect.TopLeft := ClientToScreen(Point(0, 0));
|
|
ARect.BottomRight := ClientToScreen(Point(Width, Height));
|
|
end;
|
|
end;
|
|
Source.DockRect := ARect;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockPanel.CustomStartDock(var Source: TJvDockDragDockObject);
|
|
begin
|
|
inherited CustomStartDock(Source);
|
|
end;
|
|
|
|
function TJvDockPanel.CustomUnDock(Source: TJvDockDragDockObject; NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
ShowDockPanel(False, nil);
|
|
Result := inherited CustomUnDock(Source, NewTarget, Client);
|
|
if not (Client is TJvDockableForm) and (Client is TWinControl) then
|
|
SetDockSite(TWinControl(Client), True);
|
|
end;
|
|
|
|
procedure TJvDockPanel.DockDrop(Source: TDragDockObject; X, Y: Integer);
|
|
begin
|
|
if Perform(CM_DOCKCLIENT, WPARAM(Source), LPARAM(SmallPoint(X, Y))) >= 0 then
|
|
begin
|
|
if Source.Control is TForm then
|
|
begin
|
|
TForm(Source.Control).ActiveControl := nil;
|
|
SetDockSite(TForm(Source.Control), False);
|
|
end;
|
|
UpdateCaption(nil);
|
|
end;
|
|
ShowDockPanel(TWinControl(Source.DragTarget).VisibleDockClientCount > 0, Source.Control);
|
|
end;
|
|
|
|
function TJvDockPanel.DoUnDock(NewTarget: TWinControl; Client: TControl): Boolean;
|
|
begin
|
|
Result := IsDockable(Self, Client);
|
|
ShowDockPanel(False, nil);
|
|
Result := Result and (Perform(CM_UNDOCKCLIENT, WPARAM(NewTarget), LPARAM(Client)) = 0);
|
|
if Result then
|
|
if not (Client is TJvDockableForm) then
|
|
SetDockSite(TForm(Client), True);
|
|
end;
|
|
|
|
procedure TJvDockPanel.GetDockedControls(WinControls: TList);
|
|
begin
|
|
// THE BASE CLASS DOESN'T SUPPORT THIS. JUST RETURN QUIETLY.
|
|
// See TJvDockAdvPanel.GetDockedControls for the actual implementation.
|
|
end;
|
|
|
|
function TJvDockPanel.GetPanelIndex: Integer;
|
|
begin
|
|
case Align of
|
|
alTop:
|
|
Result := 0;
|
|
alBottom:
|
|
Result := 1;
|
|
alLeft:
|
|
Result := 2;
|
|
alRight:
|
|
Result := 3;
|
|
else
|
|
if FCustomFlag then
|
|
Result := 4 {NEW!}
|
|
else
|
|
Result := -1; {unknown.}
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockPanel.ReloadDockedControl(const AControlName: string;
|
|
var AControl: TControl);
|
|
begin
|
|
AControl := JvDockFindDockFormWithName(AControlName);
|
|
end;
|
|
|
|
procedure TJvDockPanel.RemoveDockServer(ADockServer: TJvDockServer);
|
|
begin
|
|
{ Notification }
|
|
end;
|
|
|
|
procedure TJvDockPanel.ResetPosition;
|
|
begin
|
|
case Align of
|
|
alLeft:
|
|
Left := GetClientAlignControlArea(Parent, Align) + 1;
|
|
alRight:
|
|
Left := Parent.ClientWidth - GetClientAlignControlArea(Parent, Align) - Width - 1;
|
|
alTop:
|
|
Top := GetClientAlignControlArea(Parent, Align) + 1;
|
|
alBottom:
|
|
Top := Parent.ClientHeight - GetClientAlignControlArea(Parent, Align) - Height - 1;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockPanel.Resize;
|
|
begin
|
|
inherited Resize;
|
|
end;
|
|
|
|
procedure TJvDockPanel.SetDockServer(ADockServer: TJvDockServer);
|
|
begin
|
|
if ADockServer <> FDockServer then
|
|
begin
|
|
if FDockServer <> nil then
|
|
RemoveDockServer(FDockServer);
|
|
|
|
FDockServer := ADockServer;
|
|
|
|
if FDockServer <> nil then
|
|
AddDockServer(FDockServer);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockPanel.ShowDockPanel(MakeVisible: Boolean;
|
|
Client: TControl; PanelSizeFrom: TJvDockSetDockPanelSizeFrom);
|
|
const
|
|
DefaultDockSize = 100;
|
|
var
|
|
DockHeight, DockWidth: Integer;
|
|
begin
|
|
if (not MakeVisible and (VisibleDockClientCount > 1)) or
|
|
(JvGlobalDockClient = nil) then
|
|
Exit;
|
|
|
|
if Assigned(DockServer.DockSplitterWithAlign[Align]) then
|
|
DockServer.DockSplitterWithAlign[Align].Visible := MakeVisible;
|
|
|
|
if MakeVisible and (Client <> nil) then
|
|
begin
|
|
if Width * Height = 0 then
|
|
begin
|
|
if (PanelSizeFrom = sdfDockPanel) or (Client = nil) then
|
|
begin
|
|
DockHeight := TBDockHeight;
|
|
DockWidth := LRDockWidth;
|
|
end
|
|
else
|
|
begin
|
|
DockHeight := Client.TBDockHeight;
|
|
DockWidth := Client.LRDockWidth;
|
|
end;
|
|
|
|
if DockHeight = 0 then
|
|
DockHeight := DefaultDockSize;
|
|
if DockWidth = 0 then
|
|
DockWidth := DefaultDockSize;
|
|
|
|
Parent.DisableAlign;
|
|
try
|
|
case Align of
|
|
alTop:
|
|
begin
|
|
Top := DockServer.GetClientAlignControl(alTop);
|
|
Height := DockHeight;
|
|
DockServer.TopSplitter.Top := Top + Height;
|
|
end;
|
|
alBottom:
|
|
begin
|
|
Top := Parent.ClientHeight - DockServer.GetClientAlignControl(alBottom) - DockHeight + 1;
|
|
Height := DockHeight;
|
|
DockServer.BottomSplitter.Top := Top + DockServer.BottomSplitter.Height;
|
|
end;
|
|
alLeft:
|
|
begin
|
|
Left := DockServer.GetClientAlignControl(alLeft);
|
|
Width := DockWidth;
|
|
DockServer.LeftSplitter.Left := Left + Width;
|
|
end;
|
|
alRight:
|
|
begin
|
|
Width := DockWidth;
|
|
Left := Parent.ClientWidth - DockServer.GetClientAlignControl(alRight) - DockWidth + 1;
|
|
DockServer.RightSplitter.Left := Left - DockServer.RightSplitter.Width;
|
|
end;
|
|
end;
|
|
finally
|
|
Parent.EnableAlign;
|
|
if UseDockManager and (JvDockManager <> nil) then
|
|
JvDockManager.ResetBounds(True);
|
|
end;
|
|
DockServer.DoFinishSetDockPanelSize(Self);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if (PanelSizeFrom = sdfDockPanel) or (Client = nil) then
|
|
begin
|
|
if Height > 0 then
|
|
TBDockHeight := Height;
|
|
if Width > 0 then
|
|
LRDockWidth := Width;
|
|
end
|
|
else
|
|
begin
|
|
if Height > 0 then
|
|
Client.TBDockHeight := Height;
|
|
if Width > 0 then
|
|
Client.LRDockWidth := Width;
|
|
end;
|
|
if Align in [alLeft, alRight] then
|
|
Width := 0
|
|
else
|
|
Height := 0;
|
|
|
|
ResetPosition;
|
|
end;
|
|
|
|
if MakeVisible and (Client <> nil) then
|
|
begin
|
|
if not Client.Visible then
|
|
Client.Show;
|
|
|
|
if DockServer.AutoFocusDockedForm and (Client is TWinControl) and
|
|
not TWinControl(Client).Focused and TWinControl(Client).CanFocus then
|
|
TWinControl(Client).SetFocus;
|
|
end;
|
|
end;
|
|
|
|
function TJvDockPanel.CreateDockManager: IDockManager;
|
|
var
|
|
ADockStyle: TJvDockBasicStyle;
|
|
TreeClass: TJvDockTreeClass;
|
|
begin
|
|
Result := nil;
|
|
if (DockManager = nil) and DockSite and UseDockManager then
|
|
begin
|
|
if Assigned(DockServer) then
|
|
begin
|
|
ADockStyle := DockServer.DockStyle;
|
|
if Assigned(ADockStyle) then
|
|
begin
|
|
TreeClass := ADockStyle.DockPanelTreeClass;
|
|
if Assigned(TreeClass) and (TreeClass <> TJvDockTree) then
|
|
Result := TreeClass.Create(Self, ADockStyle.DockPanelZoneClass, ADockStyle) as IJvDockManager;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if Result = nil then
|
|
Result := DockManager;
|
|
DoubleBuffered := DoubleBuffered or (Result <> nil);
|
|
end;
|
|
|
|
//=== { TJvDockServer } ======================================================
|
|
|
|
constructor TJvDockServer.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FAutoFocusDockedForm := True;
|
|
CreateSplitterStyle;
|
|
end;
|
|
|
|
destructor TJvDockServer.Destroy;
|
|
begin
|
|
DestroySplitterStyle;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDockServer.AddDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
JvGlobalDockManager.RegisterDockServer(Self);
|
|
|
|
if Assigned(ADockStyle) and Assigned(ADockStyle.DockPanelClass) then
|
|
FDockPanelClass := ADockStyle.DockPanelClass
|
|
else
|
|
FDockPanelClass := DefaultDockPanelClass;
|
|
|
|
if Assigned(ADockStyle) and Assigned(ADockStyle.DockSplitterClass) then
|
|
FDockSplitterClass := ADockStyle.DockSplitterClass
|
|
else
|
|
FDockSplitterClass := DefaultDockSplitterClass;
|
|
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
CreateDockPanelAndSplitter;
|
|
SetSplitterStyles;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockServer.CreateDockPanelAndSplitter;
|
|
//var
|
|
// ControlList: TList;
|
|
|
|
function CreatePanel(AParent: TWinControl; Align: TAlign; Name: string): TJvDockPanel;
|
|
begin
|
|
if (FDockPanelClass <> nil) and
|
|
(FDockPanelClass <> TJvDockPanelClass(ClassType)) then
|
|
begin
|
|
Result := FDockPanelClass.Create({Owner} Self);
|
|
// (ahuser) Delphi 5's TComponent.Notification() will fail if Owner=Self.Owner
|
|
Result.Parent := AParent; {ParentForm;}
|
|
Result.Name := Name;
|
|
Result.Caption := '';
|
|
Result.Align := Align;
|
|
Result.DockServer := Self;
|
|
Result.ResetPosition;
|
|
if Align in [alTop, alBottom] then
|
|
Result.Height := 0
|
|
else
|
|
if Align in [alLeft, alRight] then
|
|
Result.Width := 0;
|
|
SetDockSite(Result, True);
|
|
|
|
Result.FreeNotification(Self);
|
|
end
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
function CreateSplitter(AParent: TWinControl; Align: TAlign; Name: string): TJvDockSplitter;
|
|
begin
|
|
if (FDockSplitterClass <> nil) and
|
|
(FDockSplitterClass <> TJvDockSplitterClass(ClassType)) then
|
|
begin
|
|
Result := FDockSplitterClass.Create({Owner}Self);
|
|
// (ahuser) Delphi 5's TComponent.Notification() will fail if Owner=Self.Owner
|
|
Result.Parent := AParent; {ParentForm;}
|
|
Result.Name := Name;
|
|
Result.Visible := False;
|
|
Result.Align := Align;
|
|
Result.DockServer := Self;
|
|
Result.FreeNotification(Self);
|
|
end
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
{NEW! Docking panel in center area, or other part of form than the built in left/top/right/bottom panels! }
|
|
|
|
procedure CustomDockPanel;
|
|
var
|
|
AParent: TWinControl;
|
|
LAlign: TAlign;
|
|
begin
|
|
AParent := PArentForm;
|
|
LAlign := alClient;
|
|
if Assigned(FOnCustomPanel) then
|
|
//TJvDockCustomPanelEvent:
|
|
FOnCustomPanel(Self, AParent, LAlign)
|
|
else
|
|
begin
|
|
FDockPanels[dpCustom] := nil;
|
|
FSplitters[dpCustom] := nil;
|
|
Exit;
|
|
end;
|
|
if (LAlign <> alNone) and Assigned(AParent) then
|
|
begin // Don't create if align is alNone or parent is NIL.
|
|
FDockPanels[dpCustom] := CreatePanel(AParent, LAlign, {NOTRANSLATE} 'CustomDockPanel');
|
|
FDockPanels[dpCustom].CustomFlag := True;
|
|
if AParent is TPanel then
|
|
FDockPanels[dpCustom].Color := TPanel(AParent).Color;
|
|
FSplitters[dpCustom] := nil; //CreateSplitter(ParentForm, alTop, 'CustomSplitter' + cDefaultNameSuffix);
|
|
//FSplitters[dpCustom].Visible := False;
|
|
end
|
|
else
|
|
FDockPanels[dpCustom] := nil;
|
|
FSplitters[dpCustom] := nil;
|
|
end;
|
|
|
|
begin
|
|
// ControlList := TList.Create;
|
|
// try
|
|
FDockPanels[dpLeft] := CreatePanel(ParentForm, alLeft, {NOTRANSLATE} 'LeftDockPanel');
|
|
FSplitters[dpLeft] := CreateSplitter(ParentForm, alLeft, {NOTRANSLATE} 'LeftSplitter');
|
|
FDockPanels[dpRight] := CreatePanel(ParentForm, alRight, {NOTRANSLATE} 'RightDockPanel');
|
|
FSplitters[dpRight] := CreateSplitter(ParentForm, alRight, {NOTRANSLATE} 'RightSplitter');
|
|
FDockPanels[dpTop] := CreatePanel(ParentForm, alTop, {NOTRANSLATE} 'TopDockPanel');
|
|
FSplitters[dpTop] := CreateSplitter(ParentForm, alTop, {NOTRANSLATE} 'TopSplitter');
|
|
FDockPanels[dpBottom] := CreatePanel(ParentForm, alBottom, {NOTRANSLATE} 'BottomDockPanel');
|
|
FSplitters[dpBottom] := CreateSplitter(ParentForm, alBottom, {NOTRANSLATE} 'BottomSplitter');
|
|
|
|
CustomDockPanel;
|
|
|
|
// FSplitters[dpCustom] := nil; // NOT USED!
|
|
// finally
|
|
// ControlList.Free;
|
|
// end;
|
|
end;
|
|
|
|
procedure TJvDockServer.CreateSplitterStyle;
|
|
const
|
|
cCursor: array [TJvDockPosition] of TCursor =
|
|
(crHSplit, crHSplit, crVSplit, crVSplit, crNone);
|
|
var
|
|
Position: TJvDockPosition;
|
|
begin
|
|
for Position := Low(TJvDockPosition) to High(TJvDockPosition) do
|
|
begin
|
|
FSplitterStyles[Position] := TJvDockSplitterStyle.Create(Splitter[Position], cCursor[Position]);
|
|
FSplitterStyles[Position].FDockServer := Self;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockServer.DestroyDockPanelAndSplitter;
|
|
var
|
|
Position: TJvDockPosition;
|
|
begin
|
|
for Position := Low(TJvDockPosition) to High(TJvDockPosition) do
|
|
begin
|
|
{ SplitterStyles may already be destroyed }
|
|
if Assigned(SplitterStyle[Position]) then
|
|
SplitterStyle[Position].Splitter := nil;
|
|
FreeAndNil(FDockPanels[Position]);
|
|
FreeAndNil(FSplitters[Position]);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockServer.DestroySplitterStyle;
|
|
var
|
|
Position: TJvDockPosition;
|
|
begin
|
|
for Position := Low(TJvDockPosition) to High(TJvDockPosition) do
|
|
FreeAndNil(FSplitterStyles[Position]);
|
|
end;
|
|
|
|
procedure TJvDockServer.DoFinishSetDockPanelSize(DockPanel: TJvDockPanel);
|
|
begin
|
|
if Assigned(FOnFinishSetDockPanelSize) then
|
|
FOnFinishSetDockPanelSize(DockPanel);
|
|
end;
|
|
|
|
procedure TJvDockServer.DoFloatDockClients(DockPanel: TJvDockPanel);
|
|
var
|
|
I: Integer;
|
|
DC: TJvDockClient;
|
|
begin
|
|
if not (csDesigning in ComponentState) and (DockPanel <> nil) then
|
|
for I := DockPanel.DockClientCount - 1 downto 0 do
|
|
begin
|
|
DC := FindDockClient(DockPanel.DockClients[I]);
|
|
if DC <> nil then
|
|
DC.RestoreChild;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockServer.DoGetClientAlignControl(Align: TAlign; var Value: Integer);
|
|
begin
|
|
if Assigned(FOnGetClientAlignSize) then
|
|
FOnGetClientAlignSize(Align, Value);
|
|
end;
|
|
|
|
function TJvDockServer.GetClientAlignControl(Align: TAlign): Integer;
|
|
begin
|
|
Result := GetClientAlignControlArea(ParentForm, Align);
|
|
DoGetClientAlignControl(Align, Result);
|
|
end;
|
|
|
|
function TJvDockServer.GetDockPanel(DockPosition: TJvDockPosition): TJvDockPanel;
|
|
begin
|
|
Result := FDockPanels[DockPosition];
|
|
end;
|
|
|
|
function TJvDockServer.GetDockPanelIndex(const Index: Integer): TJvDockPanel;
|
|
begin
|
|
Result := FDockPanels[TJvDockPosition(Index)];
|
|
end;
|
|
|
|
function TJvDockServer.GetDockPanelWithAlign(Index: TAlign): TJvDockPanel;
|
|
begin
|
|
Result := nil;
|
|
case Index of
|
|
alLeft:
|
|
Result := LeftDockPanel;
|
|
alRight:
|
|
Result := RightDockPanel;
|
|
alTop:
|
|
Result := TopDockPanel;
|
|
alBottom:
|
|
Result := BottomDockPanel;
|
|
end;
|
|
end;
|
|
|
|
function TJvDockServer.GetDockSplitterWithAlign(Index: TAlign): TJvDockSplitter;
|
|
begin
|
|
Result := nil;
|
|
case Index of
|
|
alLeft:
|
|
Result := LeftSplitter;
|
|
alRight:
|
|
Result := RightSplitter;
|
|
alTop:
|
|
Result := TopSplitter;
|
|
alBottom:
|
|
Result := BottomSplitter;
|
|
end;
|
|
end;
|
|
|
|
function TJvDockServer.GetSplitter(DockPosition: TJvDockPosition): TJvDockSplitter;
|
|
begin
|
|
Result := FSplitters[DockPosition];
|
|
end;
|
|
|
|
function TJvDockServer.GetSplitterIndex(const Index: Integer): TJvDockSplitter;
|
|
begin
|
|
Result := FSplitters[TJvDockPosition(Index)];
|
|
end;
|
|
|
|
function TJvDockServer.GetSplitterStyle(DockPosition: TJvDockPosition): TJvDockSplitterStyle;
|
|
begin
|
|
Result := FSplitterStyles[DockPosition];
|
|
end;
|
|
|
|
function TJvDockServer.GetSplitterStyleIndex(const Index: Integer): TJvDockSplitterStyle;
|
|
begin
|
|
Result := FSplitterStyles[TJvDockPosition(Index)];
|
|
end;
|
|
|
|
procedure TJvDockServer.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
var
|
|
Position: TJvDockPosition;
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
|
|
if Operation = opRemove then
|
|
begin
|
|
for Position := Low(TJvDockPosition) to High(TJvDockPosition) do
|
|
if AComponent = DockPanel[Position] then
|
|
begin
|
|
FDockPanels[Position] := nil;
|
|
DestroyDockPanelAndSplitter;
|
|
end
|
|
else
|
|
if AComponent = Splitter[Position] then
|
|
begin
|
|
FSplitters[Position] := nil;
|
|
if Assigned(SplitterStyle[Position]) then
|
|
SplitterStyle[Position].Splitter := nil;
|
|
DestroyDockPanelAndSplitter;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockServer.RemoveDockStyle(ADockStyle: TJvDockBasicStyle);
|
|
begin
|
|
DoFloatDockClients(TopDockPanel);
|
|
DoFloatDockClients(BottomDockPanel);
|
|
DoFloatDockClients(LeftDockPanel);
|
|
DoFloatDockClients(RightDockPanel);
|
|
|
|
DestroyDockPanelAndSplitter;
|
|
|
|
FDockPanelClass := nil;
|
|
FDockSplitterClass := nil;
|
|
|
|
{ !! can be nil }
|
|
if JvGlobalDockManager <> nil then
|
|
JvGlobalDockManager.UnRegisterDockServer(Self);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetBottomDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(BottomDockPanel);
|
|
inherited SetBottomDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetEnableDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
begin
|
|
DoFloatDockClients(TopDockPanel);
|
|
DoFloatDockClients(BottomDockPanel);
|
|
DoFloatDockClients(LeftDockPanel);
|
|
DoFloatDockClients(RightDockPanel);
|
|
end;
|
|
inherited SetEnableDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetLeftDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(LeftDockPanel);
|
|
inherited SetLeftDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetRightDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(RightDockPanel);
|
|
inherited SetRightDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetSplitterStyle(DockPosition: TJvDockPosition;
|
|
ASplitterStyle: TJvDockSplitterStyle);
|
|
begin
|
|
FSplitterStyles[DockPosition].Assign(ASplitterStyle);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetSplitterStyleIndex(const Index: Integer;
|
|
ASplitterStyle: TJvDockSplitterStyle);
|
|
begin
|
|
FSplitterStyles[TJvDockPosition(Index)].Assign(ASplitterStyle);
|
|
end;
|
|
|
|
procedure TJvDockServer.SetSplitterStyles;
|
|
var
|
|
Position: TJvDockPosition;
|
|
begin
|
|
for Position := Low(TJvDockPosition) to High(TJvDockPosition) do
|
|
begin
|
|
SplitterStyle[Position].Splitter := Splitter[Position];
|
|
SplitterStyle[Position].SetSplitterStyle;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockServer.SetTopDock(const Value: Boolean);
|
|
begin
|
|
if not Value then
|
|
DoFloatDockClients(TopDockPanel);
|
|
inherited SetTopDock(Value);
|
|
end;
|
|
|
|
procedure TJvDockServer.WindowProc(var Msg: TMessage);
|
|
begin
|
|
if Assigned(FDockStyle) then
|
|
if FDockStyle.DockServerWindowProc(Self, Msg) then
|
|
Exit;
|
|
if not (csDesigning in ComponentState) then
|
|
if Msg.Msg = WM_ACTIVATE then
|
|
WMActivate(TWMActivate(Msg));
|
|
inherited WindowProc(Msg);
|
|
end;
|
|
|
|
procedure TJvDockServer.WMActivate(var Msg: TWMActivate);
|
|
{$IFNDEF COMPILER9_UP}
|
|
var
|
|
Control: TWinControl;
|
|
{$ENDIF !COMPILER9_UP}
|
|
begin
|
|
{$IFNDEF COMPILER9_UP}
|
|
if Msg.Active = WA_INACTIVE then
|
|
begin
|
|
Control := ParentForm.ActiveControl;
|
|
if Assigned(Control) then
|
|
InvalidateDockHostSiteOfControl(Control, True);
|
|
end
|
|
else
|
|
begin
|
|
Control := ParentForm.ActiveControl;
|
|
if Assigned(Control) then
|
|
begin
|
|
// { ?? }
|
|
// if AutoFocusDockedForm and Control.CanFocus then
|
|
// Control.SetFocus;
|
|
InvalidateDockHostSiteOfControl(Control, False);
|
|
end;
|
|
end;
|
|
{$ENDIF !COMPILER9_UP}
|
|
end;
|
|
|
|
//=== { TJvDockSplitter } ====================================================
|
|
|
|
constructor TJvDockSplitter.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
AutoSnap := False;
|
|
end;
|
|
|
|
function TJvDockSplitter.FindControl: TControl;
|
|
begin
|
|
if DockServer <> nil then
|
|
Result := DockServer.GetDockPanelWithAlign(Align)
|
|
else
|
|
Result := inherited FindControl;
|
|
end;
|
|
|
|
function TJvDockSplitter.GetSplitterIndex: Integer;
|
|
begin
|
|
case Align of
|
|
alTop:
|
|
Result := 0;
|
|
alBottom:
|
|
Result := 1;
|
|
alLeft:
|
|
Result := 2;
|
|
alRight:
|
|
Result := 3;
|
|
else
|
|
Result := -1;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDockSplitterStyle } ===============================================
|
|
|
|
constructor TJvDockSplitterStyle.Create(ASplitter: TJvDockSplitter; ACursor: TCursor);
|
|
begin
|
|
inherited Create;
|
|
FSplitter := ASplitter;
|
|
Color := clBtnFace;
|
|
Cursor := ACursor;
|
|
ParentColor := False;
|
|
ResizeStyle := rsPattern;
|
|
FSize := 3;
|
|
FMinSize := 30;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TJvDockSplitterStyle then
|
|
begin
|
|
Color := TJvDockSplitterStyle(Source).Color;
|
|
Cursor := TJvDockSplitterStyle(Source).Cursor;
|
|
ParentColor := TJvDockSplitterStyle(Source).ParentColor;
|
|
ResizeStyle := TJvDockSplitterStyle(Source).ResizeStyle;
|
|
Size := TJvDockSplitterStyle(Source).Size;
|
|
end
|
|
else
|
|
inherited Assign(Source);
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.AssignTo(Dest: TPersistent);
|
|
begin
|
|
if Dest is TJvDockSplitterStyle then
|
|
with TJvDockSplitterStyle(Dest) do
|
|
begin
|
|
Color := Self.Color;
|
|
Cursor := Self.Cursor;
|
|
ParentColor := Self.ParentColor;
|
|
ResizeStyle := Self.ResizeStyle;
|
|
Size := Self.Size;
|
|
end
|
|
else
|
|
inherited AssignTo(Dest);
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.AssignToSplitter(Dest: TJvDockSplitter);
|
|
begin
|
|
Dest.Color := Color;
|
|
Dest.Cursor := Cursor;
|
|
Dest.ParentColor := ParentColor;
|
|
Dest.ResizeStyle := ResizeStyle;
|
|
if Dest.Align in [alTop, alBottom] then
|
|
Dest.Height := Size
|
|
else
|
|
Dest.Width := Size;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetColor(const Value: TColor);
|
|
begin
|
|
if FColor <> Value then
|
|
begin
|
|
FColor := Value;
|
|
ParentColor := False;
|
|
if Assigned(FSplitter) then
|
|
FSplitter.Color := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetCursor(const Value: TCursor);
|
|
begin
|
|
FCursor := Value;
|
|
if Assigned(FSplitter) then
|
|
FSplitter.Cursor := Value;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetMinSize(const Value: TJvDockSplitterSize);
|
|
begin
|
|
FMinSize := Value;
|
|
if Assigned(FSplitter) then
|
|
FSplitter.MinSize := Value;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetParentColor(const Value: Boolean);
|
|
begin
|
|
if FParentColor <> Value then
|
|
begin
|
|
FParentColor := Value;
|
|
if Value then
|
|
FColor := FDockServer.ParentForm.Color;
|
|
if Assigned(FSplitter) then
|
|
FSplitter.ParentColor := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetResizeStyle(const Value: TResizeStyle);
|
|
begin
|
|
FResizeStyle := Value;
|
|
if Assigned(FSplitter) then
|
|
FSplitter.ResizeStyle := Value;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetSize(const Value: TJvDockSplitterSize);
|
|
begin
|
|
FSize := Value;
|
|
if Assigned(FSplitter) then
|
|
begin
|
|
if FSplitter.Align in [alTop, alBottom] then
|
|
FSplitter.Height := Value
|
|
else
|
|
FSplitter.Width := Value;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockSplitterStyle.SetSplitterStyle;
|
|
begin
|
|
if Assigned(FSplitter) then
|
|
AssignToSplitter(FSplitter);
|
|
end;
|
|
|
|
//=== { TJvDockTabHostForm } =================================================
|
|
|
|
constructor TJvDockTabHostForm.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
BorderStyle := TabDockHostBorderStyle;
|
|
end;
|
|
|
|
function TJvDockTabHostForm.GetActiveDockForm: TForm;
|
|
begin
|
|
if PageControl.ActiveDockForm is TForm then
|
|
Result := TForm(PageControl.ActiveDockForm)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
//------------------------------------------------------------------------
|
|
// ShowDockedControl:
|
|
//
|
|
// If under program control you need a tabdock to switch pages to show
|
|
// a particular docked form, you call DockTabHostForm.ShowControl(aForm):
|
|
//
|
|
// If aControl is docked in DockTabhostForm.PageControl, this will
|
|
// change the PageControl.ActivePage to that page.
|
|
//------------------------------------------------------------------------
|
|
|
|
procedure TJvDockTabHostForm.ShowDockedControl(AControl: TWinControl); // NEW! WPostma.
|
|
var
|
|
t: Integer;
|
|
TabSheet: TJvDockTabSheet;
|
|
begin
|
|
Assert(Assigned(AControl));
|
|
if not Assigned(AControl.Parent) then
|
|
exit;
|
|
if not (AControl.Parent is TJvDockTabSheet) then
|
|
exit;
|
|
TabSheet := TJvDockTabSheet(AControl.Parent);
|
|
// Now go through the pages and find it!
|
|
for t := 0 to FPageControl.Count - 1 do
|
|
begin
|
|
if FPageControl.Pages[t] = TabSheet then
|
|
begin
|
|
FPageControl.ActivePage := TabSheet; { set page!}
|
|
if AControl is TForm then
|
|
TabSheet.Caption := TForm(AControl).Caption;
|
|
Self.Caption := TabSheet.Caption;
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// If while docked, you need a docked form's caption to update,
|
|
// and this update needs to be shown on the tabs on the screen,
|
|
// and possibly also the title bar of the docktabhost form needs
|
|
// updating also, then you need to call this function, like this:
|
|
// DockTabHostForm.UpdateCaption(MyForm)
|
|
|
|
procedure TJvDockTabHostForm.UpdateCaption(AControl: TWinControl); //virtual;
|
|
var
|
|
t: Integer;
|
|
TabSheet: TJvDockTabSheet;
|
|
begin
|
|
Assert(Assigned(AControl));
|
|
if not Assigned(AControl.Parent) then
|
|
exit;
|
|
if not (AControl.Parent is TJvDockTabSheet) then
|
|
exit;
|
|
TabSheet := TJvDockTabSheet(AControl.Parent);
|
|
// Now go through the pages and find the one page that needs
|
|
// its caption updated.
|
|
for t := 0 to FPageControl.Count - 1 do
|
|
begin
|
|
if FPageControl.Pages[t] = TabSheet then
|
|
begin
|
|
if AControl is TForm then
|
|
TabSheet.Caption := TForm(AControl).Caption;
|
|
if FPageControl.ActivePage = TabSheet then
|
|
Self.Caption := TabSheet.Caption; // tabhost's form caption needs updating.
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvDockTabPageControl } ==============================================
|
|
|
|
constructor TJvDockTabPageControl.Create(AOwner: TComponent);
|
|
var
|
|
ADockClient: TJvDockClient;
|
|
begin
|
|
inherited Create(AOwner);
|
|
if AOwner is TWinControl then
|
|
Parent := TWinControl(AOwner);
|
|
FStyleLink := TJvDockStyleLink.Create;
|
|
{ First set DockStyle then OnStyleChanged so no OnStyleChanged is fired;
|
|
we do it ourself in AfterContruction }
|
|
ADockClient := FindDockClient(Parent);
|
|
if Assigned(ADockClient) then
|
|
FStyleLink.DockStyle := ADockClient.DockStyle;
|
|
FStyleLink.OnStyleChanged := DockStyleChanged;
|
|
SetDockSite(Self, True);
|
|
PopupMenu := DockPageControlPopupMenu;
|
|
HotTrack := DockPageControlHotTrack;
|
|
DoubleBuffered := True;
|
|
Caption := '';
|
|
FVersion := $00040000;
|
|
end;
|
|
|
|
destructor TJvDockTabPageControl.Destroy;
|
|
begin
|
|
FStyleLink.Free;
|
|
SetDockSite(Self, False);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.AdjustClientRect(var Rect: TRect);
|
|
begin
|
|
inherited AdjustClientRect(Rect);
|
|
case TabPosition of
|
|
tpLeft:
|
|
Inc(Rect.Left, 2);
|
|
tpRight:
|
|
Dec(Rect.Right, 2);
|
|
tpBottom:
|
|
begin
|
|
Dec(Rect.Top, 1);
|
|
Dec(Rect.Bottom, 2);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.AfterConstruction;
|
|
begin
|
|
inherited AfterConstruction;
|
|
FStyleLink.StyleChanged;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomDockDrop(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
var
|
|
DragDockObject: TDragDockObject;
|
|
begin
|
|
if Source.DropAlign in [alClient, alNone] then
|
|
begin
|
|
DragDockObject := TDragDockObject.Create(Source.Control);
|
|
try
|
|
DragDockObject.DockRect := Source.DockRect;
|
|
DragDockObject.Control := Source.Control;
|
|
Perform(CM_DOCKCLIENT, WPARAM(DragDockObject), LPARAM(SmallPoint(X, Y)));
|
|
UpdateCaption(nil);
|
|
finally
|
|
DragDockObject.Free;
|
|
end;
|
|
end
|
|
else
|
|
inherited CustomDockDrop(Source, X, Y);
|
|
if Source.Control is TForm then
|
|
begin
|
|
TForm(Source.Control).ActiveControl := nil;
|
|
SetDockSite(TForm(Source.Control), False);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomDockOver(Source: TJvDockDragDockObject;
|
|
X, Y: Integer; State: TDragState; var Accept: Boolean);
|
|
var
|
|
Rect: TRect;
|
|
begin
|
|
inherited CustomDockOver(Source, X, Y, State, Accept);
|
|
|
|
Accept := IsDockable(Self, Source.Control, Source.DropOnControl, Source.DropAlign);
|
|
|
|
if Accept then
|
|
begin
|
|
ComputeDockingRect(Self, Rect, Point(ClientWidth div 2, ClientHeight div 2));
|
|
Source.DockRect := Rect;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomEndDock(Target: TObject; X, Y: Integer);
|
|
begin
|
|
inherited CustomEndDock(Target, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomGetDockEdge(Source: TJvDockDragDockObject;
|
|
MousePos: TPoint; var DropAlign: TAlign);
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
ARect := Source.DockRect;
|
|
DropAlign := ComputeDockingRect(Source.Control, ARect, MousePos);
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomGetSiteInfo(Source: TJvDockDragDockObject;
|
|
Client: TControl; var InfluenceRect: TRect; MousePos: TPoint; var CanDock: Boolean);
|
|
begin
|
|
inherited CustomGetSiteInfo(Source, Client, InfluenceRect, MousePos, CanDock);
|
|
CanDock := IsDockable(Self, Client, Source.DropOnControl, Source.DropAlign);
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomPositionDockRect(Source: TJvDockDragDockObject;
|
|
X, Y: Integer);
|
|
begin
|
|
inherited CustomPositionDockRect(Source, X, Y);
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.CustomStartDock(var Source: TJvDockDragDockObject);
|
|
begin
|
|
inherited CustomStartDock(Source);
|
|
end;
|
|
|
|
function TJvDockTabPageControl.CustomUnDock(Source: TJvDockDragDockObject;
|
|
NewTarget: TWinControl; Client: TControl): Boolean;
|
|
begin
|
|
if not (Client is TJvDockableForm) then
|
|
SetDockSite(TForm(Client), True);
|
|
if (VisibleDockClientCount = 1) or (DockClientCount <= 2) then
|
|
PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
|
|
UpdateCaption(Client);
|
|
Result := Perform(CM_UNDOCKCLIENT, WPARAM(NewTarget), LPARAM(Client)) = 0;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.DockDrop(Source: TDragDockObject; X,
|
|
Y: Integer);
|
|
begin
|
|
if Perform(CM_DOCKCLIENT, WPARAM(Source), LPARAM(SmallPoint(X, Y))) >= 0 then
|
|
begin
|
|
if Source.Control is TForm then
|
|
begin
|
|
TForm(Source.Control).ActiveControl := nil;
|
|
SetDockSite(TWinControl(Source.Control), False);
|
|
if TForm(Source.Control).FormStyle = fsStayOnTop then
|
|
TForm(Parent).FormStyle := fsStayOnTop;
|
|
end;
|
|
UpdateCaption(nil);
|
|
end;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.DockStyleChanged(Sender: TObject);
|
|
begin
|
|
SyncWithStyle;
|
|
end;
|
|
|
|
function TJvDockTabPageControl.DoUnDock(NewTarget: TWinControl;
|
|
Client: TControl): Boolean;
|
|
begin
|
|
if not (Client is TJvDockableForm) then
|
|
SetDockSite(TForm(Client), True);
|
|
if (VisibleDockClientCount = 1) or
|
|
(DockClientCount <= 2) then
|
|
PostMessage(Parent.Handle, WM_CLOSE, 0, 0);
|
|
UpdateCaption(Client);
|
|
Result := Perform(CM_UNDOCKCLIENT, WPARAM(NewTarget), LPARAM(Client)) = 0;
|
|
end;
|
|
|
|
function TJvDockTabPageControl.GetActiveDockForm: TCustomForm;
|
|
begin
|
|
Result := DockForm[ActivePageIndex];
|
|
end;
|
|
|
|
function TJvDockTabPageControl.GetDockForm(Index: Integer): TCustomForm;
|
|
var
|
|
Page: TJvDockTabSheet;
|
|
begin
|
|
Result := nil;
|
|
|
|
if (Index > -1) and (Index < Count) then
|
|
begin
|
|
Page := Pages[Index];
|
|
if Assigned(Page) and (Page.ControlCount = 1) and (Page.Controls[0] is TCustomForm) then
|
|
begin
|
|
Result := TCustomForm(Page.Controls[0]);
|
|
end
|
|
end;
|
|
end;
|
|
|
|
function TJvDockTabPageControl.GetDockStyle: TJvDockObservableStyle;
|
|
begin
|
|
Result := FStyleLink.DockStyle;
|
|
end;
|
|
|
|
function TJvDockTabPageControl.GetParentForm: TJvDockTabHostForm;
|
|
begin
|
|
if Parent is TJvDockTabHostForm then
|
|
Result := TJvDockTabHostForm(Parent)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.LoadFromStream(Stream: TStream);
|
|
var
|
|
I, ACount, NameLen, SheetVisible, ActiveSheetIndex: Integer;
|
|
ControlName: UTF8String;
|
|
AControl: TControl;
|
|
Index: Integer;
|
|
begin
|
|
Stream.Read(I, SizeOf(I));
|
|
|
|
Stream.Read(ACount, SizeOf(ACount));
|
|
Index := 0;
|
|
for I := 0 to ACount - 1 do
|
|
begin
|
|
ControlName := '';
|
|
|
|
Stream.Read(NameLen, SizeOf(NameLen));
|
|
if NameLen > 0 then
|
|
begin
|
|
SetLength(ControlName, NameLen);
|
|
Stream.Read(ControlName[1], NameLen);
|
|
end;
|
|
|
|
Stream.Read(SheetVisible, SizeOf(SheetVisible));
|
|
|
|
if ControlName <> '' then
|
|
begin
|
|
ReloadDockedControl({$IFDEF UNICODE}UTF8ToString{$ELSE}UTF8Decode{$ENDIF}(ControlName), AControl);
|
|
if AControl <> nil then
|
|
begin
|
|
AControl.ManualDock(Self, nil, alClient);
|
|
{ DockClients[Index] is always AControl? }
|
|
DockClients[Index].Visible := Boolean(SheetVisible);
|
|
if (Self is TJvDockVSNETTabPageControl) and (Index = Count - 1) then
|
|
TJvDockVSNETTabSheet(Pages[Index]).OldVisible := Boolean(SheetVisible);
|
|
Inc(Index);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Stream.Read(ActiveSheetIndex, SizeOf(ActiveSheetIndex));
|
|
ActivePageIndex := ActiveSheetIndex;
|
|
Change;
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.ReloadDockedControl(const AControlName: string;
|
|
var AControl: TControl);
|
|
begin
|
|
AControl := JvDockFindDockFormWithName(AControlName);
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.SaveToStream(Stream: TStream);
|
|
var
|
|
I, ACount, NameLen, SheetVisible, ActiveSheetIndex: Integer;
|
|
ControlName: UTF8String;
|
|
CurrentControl: TControl;
|
|
TabPageStreamEndFlag: Integer;
|
|
begin
|
|
Stream.Write(FVersion, SizeOf(FVersion));
|
|
ACount := Count;
|
|
|
|
Stream.Write(ACount, SizeOf(ACount));
|
|
for I := 0 to ACount - 1 do
|
|
begin
|
|
if Pages[I].ControlCount > 0 then
|
|
begin
|
|
CurrentControl := Pages[I].Controls[0];
|
|
|
|
ControlName := UTF8Encode(CurrentControl.Name);
|
|
NameLen := Length(ControlName);
|
|
Stream.Write(NameLen, SizeOf(NameLen));
|
|
if NameLen > 0 then
|
|
Stream.Write(ControlName[1], NameLen);
|
|
|
|
SheetVisible := 0;
|
|
if (Self is TJvDockVSNETTabPageControl) and (ParentForm.HostDockSite is TJvDockPanel) then
|
|
SheetVisible := Integer(TJvDockVSNETTabSheet(Pages[I]).OldVisible)
|
|
else
|
|
SheetVisible := SheetVisible + Integer(CurrentControl.Visible);
|
|
|
|
Stream.Write(SheetVisible, SizeOf(SheetVisible));
|
|
end;
|
|
end;
|
|
ActiveSheetIndex := ActivePageIndex;
|
|
|
|
Stream.Write(ActiveSheetIndex, SizeOf(ActiveSheetIndex));
|
|
|
|
TabPageStreamEndFlag := -10;
|
|
Stream.Write(TabPageStreamEndFlag, SizeOf(TabPageStreamEndFlag));
|
|
end;
|
|
|
|
procedure TJvDockTabPageControl.SyncWithStyle;
|
|
begin
|
|
HotTrack := DockStyle.TabServerOption.HotTrack;
|
|
TabPosition := DockStyle.TabServerOption.TabPosition;
|
|
end;
|
|
|
|
//=== { TJvGlobalDockManager } ===============================================
|
|
|
|
constructor TJvGlobalDockManager.Create;
|
|
begin
|
|
inherited Create;
|
|
FDockServers := TList.Create;
|
|
FDockClients := TList.Create;
|
|
FDockableForms := TList.Create;
|
|
end;
|
|
|
|
destructor TJvGlobalDockManager.Destroy;
|
|
begin
|
|
FDockableForms.Free;
|
|
FDockServers.Free;
|
|
FDockClients.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvGlobalDockManager.FindDockClientForm(
|
|
const AName: string): TControl;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to DockClientCount - 1 do
|
|
begin
|
|
Result := DockClient[I].ParentForm;
|
|
if Result.Name = AName then
|
|
Exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJvGlobalDockManager.FindDockControlForm(
|
|
const AName: string): TControl;
|
|
begin
|
|
Result := FindDockServerForm(AName);
|
|
if Result = nil then
|
|
FindDockClientForm(AName);
|
|
end;
|
|
|
|
function TJvGlobalDockManager.FindDockServerForm(
|
|
const AName: string): TControl;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to DockServerCount - 1 do
|
|
begin
|
|
Result := DockServer[I].ParentForm;
|
|
if Result.Name = AName then
|
|
Exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
function TJvGlobalDockManager.GetDockableForm(
|
|
const Index: Integer): TJvDockableForm;
|
|
begin
|
|
Result := TJvDockableForm(FDockableForms[Index]);
|
|
end;
|
|
|
|
function TJvGlobalDockManager.GetDockableFormCount: Integer;
|
|
begin
|
|
Result := FDockableForms.Count;
|
|
end;
|
|
|
|
function TJvGlobalDockManager.GetDockClient(
|
|
const Index: Integer): TJvDockClient;
|
|
begin
|
|
Result := TJvDockClient(FDockClients[Index]);
|
|
end;
|
|
|
|
function TJvGlobalDockManager.GetDockClientCount: Integer;
|
|
begin
|
|
Result := FDockClients.Count;
|
|
end;
|
|
|
|
function TJvGlobalDockManager.GetDockServer(
|
|
const Index: Integer): TJvDockServer;
|
|
begin
|
|
Result := TJvDockServer(FDockServers[Index]);
|
|
end;
|
|
|
|
function TJvGlobalDockManager.GetDockServerCount: Integer;
|
|
begin
|
|
Result := FDockServers.Count;
|
|
end;
|
|
|
|
procedure TJvGlobalDockManager.RegisterDockableForm(
|
|
ADockableForm: TJvDockableForm);
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
Index := FDockableForms.IndexOf(ADockableForm);
|
|
if Index < 0 then
|
|
FDockableForms.Add(ADockableForm);
|
|
end;
|
|
|
|
procedure TJvGlobalDockManager.RegisterDockClient(
|
|
ADockClient: TJvDockClient);
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
Index := FDockClients.IndexOf(ADockClient);
|
|
if Index < 0 then
|
|
FDockClients.Add(ADockClient);
|
|
end;
|
|
|
|
procedure TJvGlobalDockManager.RegisterDockServer(
|
|
ADockServer: TJvDockServer);
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
Index := FDockServers.IndexOf(ADockServer);
|
|
if Index < 0 then
|
|
FDockServers.Add(ADockServer);
|
|
end;
|
|
|
|
procedure TJvGlobalDockManager.UnRegisterDockableForm(
|
|
ADockableForm: TJvDockableForm);
|
|
begin
|
|
FDockableForms.Remove(ADockableForm);
|
|
end;
|
|
|
|
procedure TJvGlobalDockManager.UnRegisterDockClient(
|
|
ADockClient: TJvDockClient);
|
|
begin
|
|
FDockClients.Remove(ADockClient);
|
|
end;
|
|
|
|
procedure TJvGlobalDockManager.UnRegisterDockServer(
|
|
ADockServer: TJvDockServer);
|
|
begin
|
|
FDockServers.Remove(ADockServer);
|
|
end;
|
|
|
|
procedure InitDockManager;
|
|
begin
|
|
try
|
|
JvGlobalDockManager.Free;
|
|
JvGlobalDockManager := nil;
|
|
JvGlobalDockManager := TJvGlobalDockManager.Create;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
procedure DoneDockManager;
|
|
begin
|
|
JvGlobalDockManager.Free;
|
|
JvGlobalDockManager := nil;
|
|
end;
|
|
|
|
initialization
|
|
{$IFDEF UNITVERSIONING}
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
{$ENDIF UNITVERSIONING}
|
|
InitDockManager;
|
|
|
|
finalization
|
|
DoneDockManager;
|
|
{$IFDEF UNITVERSIONING}
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|