mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-19 12:29:30 +02:00
dockmanager example: attempt to improve notebook docking
git-svn-id: trunk@20145 -
This commit is contained in:
parent
fafb745f2d
commit
db48255126
@ -22,7 +22,7 @@ Inconsistent DockRect
|
||||
=====================
|
||||
1. The DockRect should be drawn as an outline, as is on Windows.
|
||||
Using gtk, a filled rectangle is drawn instead.
|
||||
[acknowledged by Paul]
|
||||
[fixed]
|
||||
|
||||
2. The DockRect should reflect the possible placement of the dragged control on a
|
||||
dock site, as is on Windows.
|
||||
@ -96,10 +96,11 @@ TPageControl
|
||||
Controls can be docked into a notebook (with tabs).
|
||||
|
||||
1. A docked TPageControl rejects an initial placement (set BoundsRect).
|
||||
[fixed]
|
||||
|
||||
2. TPageControl does not always allow to undock individual pages.
|
||||
TControls can be undocked, but not forms.
|
||||
|
||||
3. A TPageControl does not resize properly (retains initial place).
|
||||
(Okay when wrapped into a form, and the form is docked)
|
||||
|
||||
[fixed]
|
@ -48,6 +48,7 @@ done? (unclear whether this is really fixed in the trunk)
|
||||
|
||||
{$H+}
|
||||
|
||||
{.$DEFINE handle_existing} //dock controls existing in the dock site?
|
||||
{.$DEFINE splitter_color} //use colored splitter, for debugging?
|
||||
{.$DEFINE NoDrop} //patched dragobject?
|
||||
{.$DEFINE visibility} //handling of invisible clients deserves dock manager notification!
|
||||
@ -200,13 +201,18 @@ type
|
||||
procedure PaintSite(DC: HDC); override;
|
||||
end;
|
||||
|
||||
{$IFDEF bookform}
|
||||
{$ELSE}
|
||||
(* 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 :-(
|
||||
*)
|
||||
TEasyBook = class(TPageControl)
|
||||
TEasyPages = class(TPageControl)
|
||||
protected
|
||||
procedure DoDock(NewDockSite: TWinControl; var ARect: TRect); override;
|
||||
procedure DoRemoveDockClient(Client: TControl); override;
|
||||
@ -214,7 +220,6 @@ type
|
||||
public
|
||||
constructor Create(TheOwner: TComponent); override;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
const
|
||||
AlignNames: array[TAlign] of string = (
|
||||
@ -247,50 +252,53 @@ const
|
||||
type
|
||||
{$IFDEF bookform}
|
||||
//use a notebook in it's own form
|
||||
TEasyPages = class(TCustomForm) // TDockBook;
|
||||
TEasyBook = class(TCustomForm) // TDockBook;
|
||||
protected
|
||||
Pages: TPageControl;
|
||||
//function GetDockCaption(AControl: TControl): String; override;
|
||||
public
|
||||
property DragMode;
|
||||
property DragKind;
|
||||
end;
|
||||
{$ELSE}
|
||||
TEasyPages = TEasyBook;
|
||||
TEasyBook = TEasyPages;
|
||||
{$ENDIF}
|
||||
|
||||
function NoteBookCreate(AOwner: TWinControl): TEasyPages;
|
||||
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: TPageControl;
|
||||
Pages: TEasyPages;
|
||||
begin
|
||||
Result := TEasyPages.Create(AOwner);
|
||||
Result := TEasyBook.Create(AOwner);
|
||||
Result.Visible := True;
|
||||
Result.DragMode := dmAutomatic;
|
||||
Result.DragKind := dkDock;
|
||||
Pages := TPageControl.Create(Result);
|
||||
Pages := TEasyPages.Create(Result);
|
||||
Result.Pages := Pages;
|
||||
Pages.Parent := Result;
|
||||
Pages.Visible := True;
|
||||
Pages.Align := alClient; //doesn't work? minimal values too large?
|
||||
Pages.DockSite := True; //problem?
|
||||
Pages.Align := alClient;
|
||||
Pages.DockSite := True; //default?
|
||||
{$ELSE}
|
||||
begin
|
||||
Result := TEasyPages.Create(AOwner);
|
||||
Result.Align := alNone; //doesn't help :-(
|
||||
//Result.Align := alNone; //doesn't help :-(
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure NoteBookAdd(ABook: TEasyPages; AItem: TControl);
|
||||
procedure NoteBookAdd(ABook: TEasyBook; AItem: TControl);
|
||||
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}
|
||||
@ -330,9 +338,10 @@ constructor TEasyTree.Create(ADockSite: TWinControl);
|
||||
i: integer;
|
||||
ctl: TControl;
|
||||
begin
|
||||
for i := 0 to DockSite.ControlCount - 1 do begin
|
||||
for i := DockSite.ControlCount - 1 downto 0 do begin
|
||||
ctl := DockSite.Controls[i];
|
||||
InsertControl(ctl, ctl.Align, nil);
|
||||
//InsertControl(ctl, ctl.Align, nil); //this is what Delphi does
|
||||
ctl.ManualDock(FDockSite, nil, ctl.Align); //this is what should be done
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -360,10 +369,11 @@ begin
|
||||
FSplitter.ResizeStyle := rsLine;
|
||||
{$IFDEF splitter_color}
|
||||
FSplitter.Color := clPurple; //test!!!
|
||||
{$ELSE}
|
||||
{$ENDIF}
|
||||
{$IFDEF handle_existing}
|
||||
//handle controls, already residing in the site
|
||||
//DockExisting; //doesn't work in the current LCL :-(
|
||||
DockExisting; //doesn't work in the current LCL :-(
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
destructor TEasyTree.Destroy;
|
||||
@ -461,7 +471,7 @@ procedure TEasyTree.InsertControl(Control: TControl; InsertAt: TAlign;
|
||||
var
|
||||
DropZone, OldZone, NewZone, OldParent, NewParent: TEasyZone;
|
||||
r: TRect;
|
||||
NoteBook: TEasyPages;
|
||||
NoteBook: TEasyBook;
|
||||
(* special cases:
|
||||
1) first child in top zone - no orientation
|
||||
2) second child in top zone - determines orientation
|
||||
@ -506,18 +516,12 @@ begin
|
||||
*)
|
||||
if (InsertAt = alCustom) and (FTopZone.FirstChild <> nil) then begin
|
||||
//dock into book
|
||||
if (DropCtl is TEasyPages) then begin
|
||||
NoteBook := DropCtl as TEasyPages;
|
||||
if (DropCtl is TEasyBook) then begin
|
||||
NoteBook := DropCtl as TEasyBook;
|
||||
end else begin
|
||||
//create new book
|
||||
NoteBook := NoteBookCreate(FDockSite); // TEasyBook.Create(FDockSite);
|
||||
{$IFDEF old}
|
||||
NoteBook.Align := alNone;
|
||||
NoteBook.DragKind := dkDock;
|
||||
NoteBook.DragMode := dmAutomatic;
|
||||
{$ELSE}
|
||||
NoteBook := NoteBookCreate(FDockSite); // TEasyPages.Create(FDockSite);
|
||||
NoteBook.ManualDock(nil, nil);
|
||||
{$ENDIF}
|
||||
//hack: manually dock the notebook
|
||||
FReplacingControl := NoteBook; //ignore insert (see above)
|
||||
NoteBook.ManualDock(FDockSite); //move into DockClients[]
|
||||
@ -539,12 +543,7 @@ begin
|
||||
NoteBook.BoundsRect := r;
|
||||
{$ENDIF}
|
||||
end; //else use existing control
|
||||
{$IFDEF old}
|
||||
Control.ManualDock(NoteBook);
|
||||
NoteBook.ActivePageIndex:=NoteBook.PageCount - 1;
|
||||
{$ELSE}
|
||||
NoteBookAdd(NoteBook, Control);
|
||||
{$ENDIF}
|
||||
//FDockSite.Invalidate;
|
||||
exit;
|
||||
end;
|
||||
@ -648,7 +647,7 @@ var
|
||||
//zone := zInnermost;
|
||||
dir := alCustom; //pages
|
||||
end else begin
|
||||
{
|
||||
{ not yet: outer zones, meaning docking into parent zone
|
||||
if izone >= k-1 then
|
||||
zone := zOuter
|
||||
else //if izone > 0 then
|
||||
@ -1435,12 +1434,10 @@ begin
|
||||
end; //else empty root zone?
|
||||
end;
|
||||
|
||||
{$IFDEF bookform}
|
||||
//notebook is a form
|
||||
{$ELSE}
|
||||
{ TEasyBook }
|
||||
|
||||
constructor TEasyBook.Create(TheOwner: TComponent);
|
||||
{ TEasyPages }
|
||||
|
||||
constructor TEasyPages.Create(TheOwner: TComponent);
|
||||
begin
|
||||
inherited Create(TheOwner);
|
||||
{ this does not help :-(
|
||||
@ -1449,7 +1446,7 @@ begin
|
||||
}
|
||||
end;
|
||||
|
||||
procedure TEasyBook.DoDock(NewDockSite: TWinControl; var ARect: TRect);
|
||||
procedure TEasyPages.DoDock(NewDockSite: TWinControl; var ARect: TRect);
|
||||
begin
|
||||
//test: do nothing
|
||||
//inherited DoDock(NewDockSite, ARect);
|
||||
@ -1458,7 +1455,7 @@ begin
|
||||
//DebugLn('NoteBook is (%d,%d)-(%d,%d)', [Top, Left, Height, Width]);
|
||||
end;
|
||||
|
||||
procedure TEasyBook.DoRemoveDockClient(Client: TControl);
|
||||
procedure TEasyPages.DoRemoveDockClient(Client: TControl);
|
||||
begin
|
||||
(* Destroy notebook when it becomes empty.
|
||||
Notebook clients are organized in pages, not in dock clients.
|
||||
@ -1473,7 +1470,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEasyBook.GetDefaultDockCaption: string;
|
||||
function TEasyPages.GetDefaultDockCaption: string;
|
||||
var
|
||||
i: integer;
|
||||
pg: TTabSheet;
|
||||
@ -1487,7 +1484,6 @@ begin
|
||||
Result := Result + ', ' + pg.Caption;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
//implement various headers
|
||||
{$I zoneheader.inc}
|
||||
|
@ -87,6 +87,15 @@ object EasyDockMain: TEasyDockMain
|
||||
TabOrder = 1
|
||||
Text = 'Drag Me!'
|
||||
end
|
||||
object buManDock: TButton
|
||||
Left = 329
|
||||
Height = 22
|
||||
Top = 2
|
||||
Width = 75
|
||||
Caption = 'buManDock'
|
||||
OnClick = buManDockClick
|
||||
TabOrder = 2
|
||||
end
|
||||
end
|
||||
object pnlDocker: TPanel
|
||||
Left = 0
|
||||
|
@ -22,7 +22,9 @@ LazarusResources.Add('TEasyDockMain','FORMDATA',[
|
||||
+'Top'#2#2#5'Width'#2':'#7'Caption'#6#4'Dump'#7'OnClick'#7#11'buDumpClick'#8
|
||||
+'TabOrder'#2#0#0#0#5'TEdit'#6'edDock'#4'Left'#3#249#0#6'Height'#2#22#3'Top'#2
|
||||
+#2#5'Width'#2'P'#8'DragKind'#7#6'dkDock'#8'TabOrder'#2#1#4'Text'#6#8'Drag Me'
|
||||
+'!'#0#0#0#6'TPanel'#9'pnlDocker'#4'Left'#2#0#6'Height'#3#236#0#3'Top'#2#29#5
|
||||
+'Width'#3#205#1#5'Align'#7#8'alClient'#7'Caption'#6#10'Dock here!'#8'TabOrde'
|
||||
+'r'#2#2#14'UseDockManager'#8#10'OnDockOver'#7#14'DockerDockOver'#0#0#0
|
||||
+'!'#0#0#7'TButton'#9'buManDock'#4'Left'#3'I'#1#6'Height'#2#22#3'Top'#2#2#5'W'
|
||||
+'idth'#2'K'#7'Caption'#6#9'buManDock'#7'OnClick'#7#14'buManDockClick'#8'TabO'
|
||||
+'rder'#2#2#0#0#0#6'TPanel'#9'pnlDocker'#4'Left'#2#0#6'Height'#3#236#0#3'Top'
|
||||
+#2#29#5'Width'#3#205#1#5'Align'#7#8'alClient'#7'Caption'#6#10'Dock here!'#8
|
||||
+'TabOrder'#2#2#14'UseDockManager'#8#10'OnDockOver'#7#14'DockerDockOver'#0#0#0
|
||||
]);
|
||||
|
@ -15,7 +15,7 @@ unit fMain;
|
||||
//some defines, to demonstrate LCL flaws
|
||||
{$DEFINE Docker} //using control (undef: entire form) as dock site
|
||||
{$DEFINE easy} //using EasyDockSite (undef: default LDockTree)
|
||||
{.$DEFINE dragForm} //create a form from the draggable images (or drag images)
|
||||
{$DEFINE dragForm} //create a form from the draggable images (or drag images)
|
||||
//dragging forms is not supported on all platforms!
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@ type
|
||||
{ TEasyDockMain }
|
||||
|
||||
TEasyDockMain = class(TForm)
|
||||
buManDock: TButton;
|
||||
pnlDocker: TPanel;
|
||||
edDock: TEdit;
|
||||
lbDock: TLabel;
|
||||
@ -46,6 +47,7 @@ type
|
||||
Shape3: TShape;
|
||||
Shape4: TShape;
|
||||
buDump: TButton;
|
||||
procedure buManDockClick(Sender: TObject);
|
||||
procedure DockerUnDock(Sender: TObject; Client: TControl;
|
||||
NewTarget: TWinControl; var Allow: Boolean);
|
||||
procedure Shape1MouseUp(Sender: TObject; Button: TMouseButton;
|
||||
@ -99,6 +101,8 @@ begin
|
||||
shp := Sender as TShape;
|
||||
{$IFDEF dragForm}
|
||||
df := TDockable.Create(self);
|
||||
df.Name := 'test' + IntToStr(ShapeCount);
|
||||
inc(ShapeCount);
|
||||
sb.SimpleText := df.Name;
|
||||
c := shp.Brush.Color;
|
||||
//df.Color := c; - not all widgetsets support TForm.Color!?
|
||||
@ -243,6 +247,12 @@ begin
|
||||
sb.SimpleText := lbDock.Name;
|
||||
end;
|
||||
|
||||
procedure TEasyDockMain.buManDockClick(Sender: TObject);
|
||||
begin
|
||||
if buManDock.HostDockSite = nil then
|
||||
buManDock.ManualDock(Docker);
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$i fMain.lrs}
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user