mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-13 21:39:21 +02:00
dockmanager example: new notebook
git-svn-id: trunk@20204 -
This commit is contained in:
parent
56d71374e0
commit
08179bd3a2
@ -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>
|
||||
|
@ -19,6 +19,7 @@ begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TEasyDockMain, EasyDockMain);
|
||||
Application.CreateForm(TDumpBox, DumpBox);
|
||||
Application.CreateForm(TEasyDockBook, EasyDockBook);
|
||||
Application.Run;
|
||||
end.
|
||||
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
]);
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user