📄 jvdocktree.pas
字号:
// a tabbed set of other forms, so we have to check for that and
// go down into those container forms. DoQuery calls itself and other
// helper routines, recursively, and together this set of routines
// descends through the Zones, Controls (Forms), etc, finding all
// the Controls inside those zones.
DoControlQuery(TopZone, FoundItems);
end;
//XXX Helper routines for DoQuery: XXX
procedure TJvDockTree._ParentQuery(LevelsLeft: Integer; AParent: TWinControl; FoundItems: TList );
var
DockServer: TJvDockServer;
LClassName, LName: string;
begin
if Assigned(AParent) then
begin
LClassName := AParent.ClassName;
LName := AParent.Name;
//Write(Indent + ' <parent>');
//Write(Indent + ' <class>' + LClassName + '</class>');
//Write(Indent + ' <name>' + LName + '@' + IntToHex(Integer(AParent), 8) + '</name>');
if AParent is TJvDockPanel then
begin
DockServer := TJvDockPanel(AParent).DockServer;
if Assigned(DockServer) then
begin
//Write(Indent + ' <dockserver>' + DockServer.Name + '</dockserver>');
end
else
begin
//Write(Indent + ' <error>TJvDockPanel has no DockServer</name>');
end;
end;
// recurse down:
if LevelsLeft > 0 then
if AParent.Parent <> AParent then // don't show controls where they are their own parent!
_ParentQuery(LevelsLeft - 1, AParent.Parent, FoundItems);
//Write(Indent + ' </parent>');
end;
end;
procedure TJvDockTree._PageControlQuery(PageControl: TWinControl; FoundItems: TList); {actually TJvDockTabPageControl}
var
I, J, Count: Integer;
PageID: string;
LPageControl: TJvDockTabPageControl;
LClassName, LName: string;
begin
if Assigned(PageControl) then
begin
LPageControl := PageControl as TJvDockTabPageControl;
LClassName := LPageControl.ClassName;
LName := LPageControl.Name;
Count := LPageControl.Count;
//Write(Indent + ' <pageControl>');
//Write(Indent + ' <class>' + LClassName + '</class>');
//Write(Indent + ' <name>' + LName + '</name>');
for I := 0 to Count - 1 do
begin
PageID := 'Page' + IntToStr(I + 1);
//Write(Indent + ' <' + PageID + '>');
//Write(Indent + ' <class>' + LPageControl.Pages[I].ClassName + '</class>');
//Write(Indent + ' <name>' + LPageControl.Pages[I].Name + '</name>');
//Write(Indent + ' <pageCaption>' + LPageControl.Pages[I].Caption + '</pageCaption>');
//Write('');
for J := 0 to LPageControl.Pages[I].ControlCount - 1 do
_ControlQuery(LPageControl.Pages[I].Controls[J] as TWinControl, FoundItems);
//Write(Indent + ' </' + PageID + '>');
end;
//Write(Indent + ' </pageControl>');
//Write('');
end;
end;
procedure TJvDockTree._ControlQuery(AControl: TWinControl; FoundItems: TList);
var
LClassName, LName: string;
LForm: TForm;
DockClient: TJvDockClient;
begin
//Write(Indent + ' <Control>');
LClassName := AControl.ClassName;
LName := AControl.Name;
//Write(Indent + ' <class>' + LClassName + '</class>');
//Write(Indent + ' <name>' + LName + '</name>');
//Write(Indent + ' <visible>' + BoolToStr(AControl.Visible, True) + '</visible>');
//Write(Indent + ' <enabled>' + BoolToStr(AControl.Enabled, True) + '</enabled>');
if AControl is TForm then
begin
LForm := TForm(AControl);
//Write(Indent + ' <caption>' + LForm.Caption + '</caption>');
DockClient := FindDockClient(AControl);
if Assigned(DockClient) then
begin
LClassName := DockClient.ClassName;
LName := DockClient.Name;
// FOUND A CONTROL WHICH IS A FORM AND HAS A JVDOCK CLIENT.
// Add it to FoundItems:
if DockClient.DockState = JvDockState_Docking then
begin
Assert(Assigned(FoundItems));
FoundItems.Add(AControl);
end;
//Write(Indent + ' <dockclient>');
//Write(Indent + ' <class>' + LClassName + '</class>');
//Write(Indent + ' <name>' + LName + '</name>');
//Write(Indent + ' <customdock>' + BoolToStr(DockClient.CustomDock, True) + '</customdock>');
// uses DockStateStr - utility function in JvDockControlForm.pas:
//Write(Indent + ' <dockstate>' + DockStateStr(DockClient.DockState) + '</dockstate>');
//Write(Indent + ' </dockclient>');
end
else
begin
//Write(Indent + ' <WARNING>No dockclient found in this form.</WARNING>');
end;
if LForm is TJvDockTabHostForm then
_PageControlQuery(TJvDockTabHostForm(LForm).PageControl, FoundItems);
end;
{ LAST for each control, recursively query the TWinControl.Parent
tree, but limit to only a few levels
so we can avoid information overload. Oops. Too late. :-) }
_ParentQuery(3, AControl.Parent, FoundItems);
//Write(Indent + ' </Control>');
end;
// DoQuery:
// This is a recursive function called from top level function Query().
// This helps us to find particular Controls, that are docked to a particular
// dock panel, or are floating, etc.
procedure TJvDockTree.DoControlQuery(TreeZone: TJvDockZone; FoundItems: TList);
var
Zone: TJvDockZone;
begin
Zone := TreeZone;
{ while loop over siblings at this level...}
while Assigned(Zone) do
begin
{ Dump controls recursively }
if Assigned( Zone.ChildControl) then
_ControlQuery(Zone.ChildControl, FoundItems);
{ query children, descends recursively }
DoControlQuery(Zone.ChildZones, FoundItems);
{query all siblings at this level immediately after current item }
Zone := Zone.NextSibling;
end;
end;
{$ENDIF JVDOCK_QUERY}
{$IFDEF JVCL_DOCKING_NOTIFYLISTENERS}
// properties in Dock Style (FDockStyle) have changed.
procedure TJvDockTree.NotifyDockStyleChange;
var
Changed: Boolean;
LDockStyle: TJvDockBasicStyle;
begin
if not Assigned(FDockStyle) then
Exit;
LDockStyle := FDockStyle as TJvDockBasicStyle;
Changed := False;
{ change in grabber size: }
if LDockStyle.ConjoinServerOption.GrabbersSize > 0 then
if FGrabberSize <> LDockStyle.ConjoinServerOption.GrabbersSize then
begin
Changed := True;
// we purposely DON'T use the TJvDockTree.SetGrabberSize function or
// access the GrabberSize as a Property, instead we assign FGrabberSize
// directly, because doing otherwise would cause TWO calls to UpdateAll
// and DockSite.Invalidate.
FGrabberSize := LDockStyle.ConjoinServerOption.GrabbersSize;
end;
// This now happens only when NotifyDockStyleChange is invoked, because
// multiple properties might be updated, and we only want to update the whole
// deal once, for less flickering, and more efficiency: Wpostma.
if Changed then
begin
UpdateAll; // Update once with each change.
DockSite.Invalidate;
end;
end;
{$ENDIF JVCL_DOCKING_NOTIFYLISTENERS}
procedure TJvDockTree.AdjustDockRect(Control: TControl; var ARect: TRect);
begin
InflateRect(ARect, -BorderWidth, -BorderWidth);
case GrabbersPosition of
gpTop:
Inc(ARect.Top, GrabberSize);
gpBottom:
Dec(ARect.Bottom, GrabberSize);
gpLeft:
Inc(ARect.Left, GrabberSize);
gpRight:
Dec(ARect.Right, GrabberSize);
end;
end;
procedure TJvDockTree.BeginUpdate;
begin
Inc(FUpdateCount);
end;
procedure TJvDockTree.EndUpdate;
begin
Dec(FUpdateCount);
if FUpdateCount <= 0 then
begin
FUpdateCount := 0;
UpdateAll;
end;
end;
function TJvDockTree.FindControlZone(Control: TControl; IncludeHide: Boolean): TJvDockZone;
var
CtlZone: TJvDockZone;
procedure DoFindControlZone(StartZone: TJvDockZone);
begin
if (StartZone.ChildControl = Control) and (StartZone.Visibled or IncludeHide) then
CtlZone := StartZone
else
begin
if (CtlZone = nil) and (StartZone.NextSibling <> nil) then
DoFindControlZone(StartZone.NextSibling);
if (CtlZone = nil) and (StartZone.ChildZones <> nil) then
DoFindControlZone(StartZone.ChildZones);
end;
end;
begin
CtlZone := nil;
if (Control <> nil) and (FTopZone <> nil) then
DoFindControlZone(FTopZone);
Result := CtlZone;
end;
procedure TJvDockTree.ForEachAt(Zone: TJvDockZone; Proc: TJvDockForEachZoneProc;
ScanKind: TJvDockTreeScanKind; ScanPriority: TJvDockTreeScanPriority);
procedure DoForwardForEach(Zone: TJvDockZone);
begin
Proc(Zone);
if ScanPriority = tspSibling then
begin
if Zone.NextSibling <> nil then
DoForwardForEach(Zone.NextSibling);
if Zone.ChildZones <> nil then
DoForwardForEach(Zone.ChildZones);
end
else
begin
if Zone.ChildZones <> nil then
DoForwardForEach(Zone.ChildZones);
if Zone.NextSibling <> nil then
DoForwardForEach(Zone.NextSibling);
end;
end;
procedure DoMiddleForEach(Zone: TJvDockZone);
begin
if ScanPriority = tspSibling then
begin
if Zone.NextSibling <> nil then
DoMiddleForEach(Zone.NextSibling);
end
else
begin
if Zone.ChildZones <> nil then
DoMiddleForEach(Zone.ChildZones);
end;
Proc(Zone);
if ScanPriority = tspSibling then
begin
if Zone.ChildZones <> nil then
DoMiddleForEach(Zone.ChildZones);
end
else
if Zone.NextSibling <> nil then
DoMiddleForEach(Zone.NextSibling);
end;
procedure DoBackwardForEach(Zone: TJvDockZone);
begin
if ScanPriority = tspSibling then
begin
if Zone.NextSibling <> nil then
DoBackwardForEach(Zone.NextSibling);
if Zone.ChildZones <> nil then
DoBackwardForEach(Zone.ChildZones);
end
else
begin
if Zone.ChildZones <> nil then
DoForwardForEach(Zone.ChildZones);
if Zone.NextSibling <> nil then
DoForwardForEach(Zone.NextSibling);
end;
Proc(Zone);
end;
begin
if Zone = nil then
begin
if FTopZone = nil then
FTopZone := FDockZoneClass.Create(Self);
Zone := FTopZone;
end;
case ScanKind of
tskForward:
DoForwardForEach(Zone);
tskMiddle:
DoMiddleForEach(Zone);
tskBackward:
DoBackwardForEach(Zone);
end;
end;
procedure TJvDockTree.GetControlBounds(Control: TControl; out CtlBounds: TRect);
var
Z: TJvDockZone;
begin
Z := FindControlZone(Control);
if Z = nil then
FillChar(CtlBounds, SizeOf(CtlBounds), 0)
else
with Z do
CtlBounds := Bounds(Left, Top, Width, Height);
end;
function TJvDockTree.HitTest(const MousePos: TPoint; out HTFlag: Integer): TControl;
var
Zone: TJvDockZone;
begin
Zone := InternalHitTest(MousePos, HTFlag);
if Zone <> nil then
Result := Zone.ChildControl
else
Result := nil;
end;
procedure TJvDockTree.InsertControl(Control: TControl; InsertAt: TAlign;
DropCtl: TControl);
const
{$IFDEF COMPILER6_UP}
Orients: array [TAlign] of TDockOrientation =
(doNoOrient, doHorizontal, doHorizontal, doVertical, doVertical, doNoOrient, doNoOrient);
MakeLast: array [TAlign] of Boolean =
(False, False, True, False, True, False, False);
{$ELSE}
Orients: array [TAlign] of TDockOrientation =
(doNoOrient, doHorizontal, doHorizontal, doVertical, doVertical, doNoOrient);
MakeLast: array [TAlign] of Boolean =
(False, False, True, False, True, False);
{$ENDIF COMPILER6_UP}
var
Sibling: TJvDockZone;
Me: TJvDockZone;
Inser
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -