dockmanager example: new notebook

git-svn-id: trunk@20204 -
This commit is contained in:
dodi 2009-05-25 13:31:44 +00:00
parent 56d71374e0
commit 08179bd3a2
6 changed files with 180 additions and 192 deletions

View File

@ -74,10 +74,10 @@
</Unit5>
<Unit6>
<Filename Value="fdockbook.pas"/>
<ComponentName Value="DockBook"/>
<ComponentName Value="EasyDockBook"/>
<IsPartOfProject Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="fdockbook"/>
<UnitName Value="fDockBook"/>
</Unit6>
</Units>
</ProjectOptions>

View File

@ -19,6 +19,7 @@ begin
Application.Initialize;
Application.CreateForm(TEasyDockMain, EasyDockMain);
Application.CreateForm(TDumpBox, DumpBox);
Application.CreateForm(TEasyDockBook, EasyDockBook);
Application.Run;
end.

View File

@ -201,26 +201,6 @@ type
procedure PaintSite(DC: HDC); override;
end;
(* Docking into a notebook
Notebook base class is TCustomPageControl (TPageControl?)
Dockable control is either the notebook or a form with a notebook.
TEasyPages is the page control itself, for docking clients.
TEasyBook is the dockable control or wrapper form.
*)
(* Notebook for alCustom docking.
Added behaviour: free self on undock of the last client/page.
The behaviour of TPageControl sucks :-(
*)
TEasyPages = class(TPageControl)
protected
procedure DoDock(NewDockSite: TWinControl; var ARect: TRect); override;
procedure DoRemoveDockClient(Client: TControl); override;
function GetDefaultDockCaption: string; override;
public
constructor Create(TheOwner: TComponent); override;
end;
const
AlignNames: array[TAlign] of string = (
'alNone', 'alTop', 'alBottom', 'alLeft', 'alRight', 'alClient', 'alCustom'
@ -235,11 +215,8 @@ implementation
uses
SysUtils, Types,
math,
fDockBook,
Themes, LResources,
{$IFDEF bookform}
//fDockBook,
{$ELSE}
{$ENDIF}
LCLproc; //debugging
const
@ -250,58 +227,16 @@ const
{$ENDIF}
type
{$IFDEF bookform}
//use a notebook in it's own form
TEasyBook = class(TCustomForm) // TDockBook;
protected
Pages: TPageControl;
//function GetDockCaption(AControl: TControl): String; override;
public
property DragMode;
property DragKind;
end;
{$ELSE}
TEasyBook = TEasyPages;
{$ENDIF}
TEasyBook = TEasyDockBook;
function NoteBookCreate(AOwner: TWinControl): TEasyBook;
{$IFDEF bookform}
(* Create a form, containing a page control.
The form must be dockable.
The page control must be a dock site. (is?)
*)
var
Pages: TEasyPages;
function NoteBookCreate(AOwner: TWinControl): TEasyBook; inline;
begin
Result := TEasyBook.Create(AOwner);
Result.Visible := True;
Result.DragMode := dmAutomatic;
Result.DragKind := dkDock;
Pages := TEasyPages.Create(Result);
Result.Pages := Pages;
Pages.Parent := Result;
Pages.Visible := True;
Pages.Align := alClient;
Pages.DockSite := True; //default?
{$ELSE}
begin
Result := TEasyPages.Create(AOwner);
//Result.Align := alNone; //doesn't help :-(
{$ENDIF}
Result := TEasyDockBook.Create(AOwner);
end;
procedure NoteBookAdd(ABook: TEasyBook; AItem: TControl);
procedure NoteBookAdd(ABook: TEasyBook; AItem: TControl); inline;
begin
{$IFDEF bookform}
//dock into client
AItem.Align := alClient;
AItem.ManualDock(ABook.Pages);
ABook.Pages.ActivePageIndex := ABook.Pages.PageCount - 1;
{$ELSE}
//dock into control
AItem.ManualDock(ABook);
ABook.ActivePageIndex := ABook.PageCount - 1;
{$ENDIF}
AItem.ManualDock(ABook.pnlDock);
end;
//from CustomFormEditor.pp
@ -349,7 +284,7 @@ begin
FDockSite := ADockSite;
//reset inappropriate docking defaults - should be fixed in Controls/DragManager!
DragManager.DragImmediate := False;
DragManager.DragThreshold:=5;
//DragManager.DragThreshold:=5;
//workaround: check for already assigned docking manager
//FreeAndNil(DockSite.DockManager); - seems to be fixed
DockSite.DockManager := self;
@ -393,7 +328,7 @@ procedure TEasyTree.EndUpdate;
begin
dec(FUpdateCount);
if (FUpdateCount = 0) and (FTopZone.FirstChild <> nil) then begin
DebugLn('EndUpdate---');
//DebugLn('EndUpdate---');
UpdateTree;
end;
end;
@ -411,7 +346,7 @@ begin
else if zone.FirstChild <> nil then
zone := zone.FirstChild
else begin
break; //here?
break; //found it
end;
end;
Result := zone;
@ -425,14 +360,7 @@ end;
procedure TEasyTree.AdjustDockRect(Control: TControl; var ARect: TRect);
begin
//get the client area within the given zone rectangle
{$IFDEF old}
if Control.DockOrientation = doVertical then
inc(ARect.Top, DockHeaderSize)
else
inc(ARect.Left, DockHeaderSize);
{$ELSE}
ARect := FHeader.GetRectOfPart(ARect, Control.DockOrientation, zpClient, true);
{$ENDIF}
end;
function TEasyTree.FindControlZone(zone: TEasyZone; Control: TControl): TEasyZone;
@ -461,8 +389,7 @@ begin
if zone = nil then
CtlBounds := Rect(0,0,0,0)
else begin
{ TODO -cdocking : zpClient }
CtlBounds := zone.GetBounds;
CtlBounds := zone.GetPartRect(zpClient);
end;
end;
@ -616,7 +543,6 @@ var
i: integer;
zone: TEasyZone;
//function DetectAlign(ZoneSize, MousePos: TPoint): TAlign;
function DetectAlign(ZoneRect: TRect; MousePos: TPoint): TAlign;
var
w, h, zphi: integer;
@ -1434,57 +1360,6 @@ begin
end; //else empty root zone?
end;
{ TEasyPages }
constructor TEasyPages.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
{ this does not help :-(
DragKind := dkDock;
DragMode := dmAutomatic;
}
end;
procedure TEasyPages.DoDock(NewDockSite: TWinControl; var ARect: TRect);
begin
//test: do nothing
//inherited DoDock(NewDockSite, ARect);
//DebugLn('NoteBook as (%d,%d)-(%d,%d)', [ARect.Top, ARect.Left, ARect.Bottom, ARect.Right]);
//BoundsRect := ARect;
//DebugLn('NoteBook is (%d,%d)-(%d,%d)', [Top, Left, Height, Width]);
end;
procedure TEasyPages.DoRemoveDockClient(Client: TControl);
begin
(* Destroy notebook when it becomes empty.
Notebook clients are organized in pages, not in dock clients.
Hence we have to test for PageCount, instead of DockClientCount.
*)
inherited;
//DebugLn('TEasyBook.DoRemoveDockClient: remaining ' + IntToStr(PageCount));
if PageCount = 0 then begin
{ TODO -cdocking : When standalone and docked, undock from HostDockSite.
When wrapped into a dockable form, undock the form? }
Application.ReleaseComponent(self);
end;
end;
function TEasyPages.GetDefaultDockCaption: string;
var
i: integer;
pg: TTabSheet;
begin
Result := '';
for i := 0 to PageCount - 1 do begin
pg := Pages[i];
if Result = '' then
Result := pg.Caption
else
Result := Result + ', ' + pg.Caption;
end;
end;
//implement various headers
{$I zoneheader.inc}

View File

@ -1,22 +1,47 @@
object DockBook: TDockBook
Left = 298
object EasyDockBook: TEasyDockBook
Left = 263
Height = 300
Top = 151
Top = 146
Width = 400
Caption = 'DockBook'
Caption = 'EasyDockBook'
ClientHeight = 300
ClientWidth = 400
DragKind = dkDock
DragMode = dmAutomatic
LCLVersion = '0.9.27'
Visible = True
object Pages: TPageControl
Left = 0
Height = 300
Top = 0
Width = 400
Align = alClient
DockSite = True
object Tabs: TToolBar
Left = 1
Height = 26
Top = 1
Width = 398
AutoSize = True
BorderSpacing.Around = 1
BorderWidth = 1
Caption = 'Tabs'
ChildSizing.HorizontalSpacing = 2
ChildSizing.EnlargeHorizontal = crsHomogenousSpaceResize
ChildSizing.Layout = cclLeftToRightThenTopToBottom
Color = clBtnFace
EdgeBorders = [ebTop, ebBottom]
Flat = False
Font.Style = [fsBold]
List = True
ParentColor = False
ParentFont = False
ShowCaptions = True
TabOrder = 0
end
object pnlDock: TPanel
Left = 0
Height = 272
Top = 28
Width = 400
Align = alClient
Caption = 'pnlDock'
DockSite = True
TabOrder = 1
OnDockDrop = pnlDockDockDrop
OnUnDock = pnlDockUnDock
end
end

View File

@ -1,10 +1,35 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TDockBook','FORMDATA',[
'TPF0'#9'TDockBook'#8'DockBook'#4'Left'#3'*'#1#6'Height'#3','#1#3'Top'#3#151#0
'TPF0'#9'TDockBook'#8'DockBook'#4'Left'#3#10#1#6'Height'#3','#1#3'Top'#3#150#0
+#5'Width'#3#144#1#7'Caption'#6#8'DockBook'#12'ClientHeight'#3','#1#11'Client'
+'Width'#3#144#1#8'DragKind'#7#6'dkDock'#8'DragMode'#7#11'dmAutomatic'#10'LCL'
+'Version'#6#6'0.9.27'#7'Visible'#9#0#12'TPageControl'#5'Pages'#4'Left'#2#0#6
+'Height'#3','#1#3'Top'#2#0#5'Width'#3#144#1#5'Align'#7#8'alClient'#8'DockSit'
+'e'#9#8'TabOrder'#2#0#0#0#0
+'Width'#3#144#1#8'DockSite'#9#8'DragKind'#7#6'dkDock'#8'DragMode'#7#11'dmAut'
+'omatic'#10'OnDockOver'#7#12'FormDockOver'#10'LCLVersion'#6#6'0.9.27'#7'Visi'
+'ble'#9#0#6'TPanel'#7'pnlDock'#4'Left'#2#0#6'Height'#3#254#0#3'Top'#2#26#5'W'
+'idth'#3#144#1#5'Align'#7#8'alClient'#7'Caption'#6#7'pnlDock'#8'DockSite'#9#8
+'TabOrder'#2#0#8'OnUnDock'#7#13'pnlDockUnDock'#0#0#10'TStatusBar'#2'sb'#4'Le'
+'ft'#2#0#6'Height'#2#20#3'Top'#3#24#1#5'Width'#3#144#1#6'Panels'#14#0#0#0#8
+'TToolBar'#4'Tabs'#4'Left'#2#0#6'Height'#2#26#3'Top'#2#0#5'Width'#3#144#1#8
+'AutoSize'#9#7'Caption'#6#4'Tabs'#18'ChildSizing.Layout'#7#29'cclLeftToRight'
+'ThenTopToBottom'#11'EdgeBorders'#11#5'ebTop'#8'ebBottom'#0#4'Flat'#8#4'List'
+#9#12'ShowCaptions'#9#8'TabOrder'#2#2#0#11'TToolButton'#11'ToolButton1'#4'Le'
+'ft'#2#1#3'Top'#2#2#7'Caption'#6#11'ToolButton1'#5'Style'#7#8'tbsCheck'#7'On'
+'Click'#7#16'ToolButton1Click'#0#0#0#0
]);
LazarusResources.Add('TEasyDockBook','FORMDATA',[
'TPF0'#13'TEasyDockBook'#12'EasyDockBook'#4'Left'#3#7#1#6'Height'#3','#1#3'To'
+'p'#3#146#0#5'Width'#3#144#1#7'Caption'#6#12'EasyDockBook'#12'ClientHeight'#3
+','#1#11'ClientWidth'#3#144#1#8'DragKind'#7#6'dkDock'#8'DragMode'#7#11'dmAut'
+'omatic'#10'LCLVersion'#6#6'0.9.27'#7'Visible'#9#0#8'TToolBar'#4'Tabs'#4'Lef'
+'t'#2#1#6'Height'#2#26#3'Top'#2#1#5'Width'#3#142#1#8'AutoSize'#9#20'BorderSp'
+'acing.Around'#2#1#11'BorderWidth'#2#1#7'Caption'#6#4'Tabs'#29'ChildSizing.H'
+'orizontalSpacing'#2#2#29'ChildSizing.EnlargeHorizontal'#7#24'crsHomogenousS'
+'paceResize'#18'ChildSizing.Layout'#7#29'cclLeftToRightThenTopToBottom'#5'Co'
+'lor'#7#9'clBtnFace'#11'EdgeBorders'#11#5'ebTop'#8'ebBottom'#0#4'Flat'#8#10
+'Font.Style'#11#6'fsBold'#0#4'List'#9#11'ParentColor'#8#10'ParentFont'#8#12
+'ShowCaptions'#9#8'TabOrder'#2#0#0#0#6'TPanel'#7'pnlDock'#4'Left'#2#0#6'Heig'
+'ht'#3#16#1#3'Top'#2#28#5'Width'#3#144#1#5'Align'#7#8'alClient'#7'Caption'#6
+#7'pnlDock'#8'DockSite'#9#8'TabOrder'#2#1#10'OnDockDrop'#7#15'pnlDockDockDro'
+'p'#8'OnUnDock'#7#13'pnlDockUnDock'#0#0#0
]);

View File

@ -1,4 +1,4 @@
unit fdockbook;
unit fDockBook;
{$mode objfpc}{$H+}
@ -6,61 +6,123 @@ interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
ComCtrls;
ComCtrls, ExtCtrls;
type
TDockBook = class(TForm)
private
Pages: TPageControl;
procedure FormCreate(Sender: TObject);
TTabButton = class(TToolButton)
protected
{$IFDEF new}
procedure DoRemoveDockClient(Client: TControl); override;
function GetDefaultDockCaption: string; override;
{$ELSE}
{$ENDIF}
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
public
{ public declarations }
end;
constructor Create(TheOwner: TComponent); override;
Control: TControl;
end;
TEasyDockBook = class(TForm)
pnlDock: TPanel;
Tabs: TToolBar;
procedure pnlDockDockDrop(Sender: TObject; Source: TDragDockObject;
X, Y: Integer);
procedure pnlDockUnDock(Sender: TObject; Client: TControl;
NewTarget: TWinControl; var Allow: Boolean);
procedure ToolButton1Click(Sender: TObject);
private
CurTab: TTabButton;
protected
function GetDefaultDockCaption: string; override;
end;
var
EasyDockBook: TEasyDockBook;
implementation
{ TDockBook }
{ TEasyDockBook }
procedure TDockBook.FormCreate(Sender: TObject);
begin
//nop?
end;
{$IFDEF new}
procedure TDockBook.DoRemoveDockClient(Client: TControl);
begin
(* Destroy notebook when it becomes empty.
Notebook clients are organized in pages, not in dock clients.
Hence we have to test for PageCount, instead of DockClientCount.
*)
inherited;
//DebugLn('TEasyBook.DoRemoveDockClient: remaining ' + IntToStr(PageCount));
if PageCount = 0 then
Application.ReleaseComponent(self);
end;
function TDockBook.GetDefaultDockCaption: string;
function TEasyDockBook.GetDefaultDockCaption: string;
var
i: integer;
pg: TTabSheet;
pg: TToolButton;
begin
Result := '';
for i := 0 to PageCount - 1 do begin
pg := Pages[i];
for i := 0 to Tabs.ButtonCount - 1 do begin
pg := Tabs.Buttons[i];
if Result = '' then
Result := pg.Caption
else
Result := Result + ' ' + pg.Caption;
Result := Result + ', ' + pg.Caption;
end;
end;
procedure TEasyDockBook.pnlDockDockDrop(Sender: TObject; Source: TDragDockObject;
X, Y: Integer);
var
btn: TTabButton;
begin
btn := TTabButton.Create(Tabs);
btn.Control := Source.Control;
btn.Control.Align := alClient;
btn.Caption := GetDockCaption(btn.Control);
//btn.Caption := ' ' + GetDockCaption(btn.Control) + ' ';
btn.OnClick := @ToolButton1Click;
btn.Down := True;
btn.Click;
end;
procedure TEasyDockBook.pnlDockUnDock(Sender: TObject; Client: TControl;
NewTarget: TWinControl; var Allow: Boolean);
var
i: integer;
begin
Allow := true;
//assert(CurTab.Control = Client, 'diff client');
i := CurTab.Index;
Tabs.ButtonList.Delete(i);
CurTab.Free; //seems to work
//Tabs.removebutton
CurTab := nil;
if i >= Tabs.ButtonCount then
dec(i);
if Tabs.ButtonCount > 0 then begin
CurTab := Tabs.Buttons[i] as TTabButton;
CurTab.Down := True;
CurTab.Click;
end else
close;
end;
procedure TEasyDockBook.ToolButton1Click(Sender: TObject);
var
btn: TTabButton absolute Sender;
begin
if CurTab <> nil then begin
CurTab.Control.Visible := false;
end;
if btn.Control <> nil then
btn.Control.Visible := True;
CurTab := btn;
end;
{ TTabButton }
constructor TTabButton.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
Parent := TWinControl(TheOwner);
Grouped := True;
AllowAllUp := False;
Style := tbsCheck;
AutoSize := True;
end;
procedure TTabButton.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited MouseMove(Shift, X, Y);
if ssLeft in Shift then begin
if Control <> nil then begin
Control.BeginDrag(False); //delayed docking
end;
end;
end;
{$ELSE}
{$ENDIF}
initialization
{$I fdockbook.lrs}