Moved drag-able notebook

git-svn-id: trunk@26257 -
This commit is contained in:
martin 2010-06-22 17:31:08 +00:00
parent 2b652bd86c
commit afbdf3e742
7 changed files with 510 additions and 361 deletions

3
.gitattributes vendored
View File

@ -1223,7 +1223,10 @@ components/lazcontrols/Makefile svneol=native#text/plain
components/lazcontrols/Makefile.fpc svneol=native#text/plain components/lazcontrols/Makefile.fpc svneol=native#text/plain
components/lazcontrols/dividerbevel.pas svneol=native#text/pascal components/lazcontrols/dividerbevel.pas svneol=native#text/pascal
components/lazcontrols/dividerbevel_icon.lrs svneol=native#text/pascal components/lazcontrols/dividerbevel_icon.lrs svneol=native#text/pascal
components/lazcontrols/extendednotebook.pas svneol=native#text/pascal
components/lazcontrols/extendednotebook_icon.lrs svneol=native#text/pascal
components/lazcontrols/images/tdividerbevel.png -text components/lazcontrols/images/tdividerbevel.png -text
components/lazcontrols/images/textnotebook.png -text
components/lazcontrols/lazcontrols.lpk svneol=native#text/xml components/lazcontrols/lazcontrols.lpk svneol=native#text/xml
components/lazcontrols/lazcontrols.pas svneol=native#text/pascal components/lazcontrols/lazcontrols.pas svneol=native#text/pascal
components/lazreport/doc/contributors.txt svneol=native#text/plain components/lazreport/doc/contributors.txt svneol=native#text/plain

View File

@ -0,0 +1,448 @@
{ DividerBevel
Copyright (C) 2010 <name of author> <contact>
This library is free software; you can redistribute it and/or modify it
under the same terms as the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the copyright.
}
unit ExtendedNotebook;
{$mode objfpc}{$H+}
interface
uses
Classes, sysutils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
LCLIntf, LCLType, math;
type
TNotebookTabDragDropEvent = procedure(Sender, Source: TObject;
OldIndex, NewIndex: Integer;
CopyDrag: Boolean;
var Done: Boolean) of object;
TNotebookTabDragOverEvent = procedure(Sender, Source: TObject;
OldIndex, NewIndex: Integer;
CopyDrag: Boolean;
var Accept: Boolean) of object;
{ TExtendedNotebook }
TExtendedNotebook = class(TNotebook)
private
FDraggingTabIndex: Integer;
FOnTabDragDrop: TDragDropEvent;
FOnTabDragOver: TDragOverEvent;
FOnTabDragOverEx: TNotebookTabDragOverEvent;
FOnTabDragDropEx: TNotebookTabDragDropEvent;
FOnTabEndDrag: TEndDragEvent;
FOnTabStartDrag: TStartDragEvent;
FTabDragMode: TDragMode;
FTabDragAcceptMode: TDragMode;
FTabDragged: boolean;
FDragOverIndex: Integer;
FDragToRightSide: Boolean;
FDragOverTabRect, FDragNextToTabRect: TRect;
procedure InitDrag;
procedure InvalidateRect(ARect: TRect);
function TabIndexForDrag(x, y: Integer): Integer;
function TabRectEx(AIndex, X, Y: Integer; out IsRightHalf: Boolean): TRect;
protected
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer); override;
procedure DoStartDrag(var DragObject: TDragObject); override;
procedure DoEndDrag(Target: TObject; X,Y: Integer); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); override;
procedure DragCanceled; override;
procedure PaintWindow(DC: HDC); override;
public
constructor Create(TheOwner: TComponent); override;
procedure DragDrop(Source: TObject; X, Y: Integer); override;
procedure BeginDragTab(ATabIndex: Integer; Immediate: Boolean; Threshold: Integer = -1);
property DraggingTabIndex: Integer read FDraggingTabIndex;
published
property OnTabDragOver: TDragOverEvent read FOnTabDragOver write FOnTabDragOver;
property OnTabDragOverEx: TNotebookTabDragOverEvent read FOnTabDragOverEx write FOnTabDragOverEx;
property OnTabDragDrop: TDragDropEvent read FOnTabDragDrop write FOnTabDragDrop;
property OnTabDragDropEx: TNotebookTabDragDropEvent read FOnTabDragDropEx write FOnTabDragDropEx;
property OnTabEndDrag: TEndDragEvent read FOnTabEndDrag write FOnTabEndDrag;
property OnTabStartDrag: TStartDragEvent read FOnTabStartDrag write FOnTabStartDrag;
property TabDragMode: TDragMode read FTabDragMode write FTabDragMode
default dmManual;
property TabDragAcceptMode: TDragMode read FTabDragAcceptMode write FTabDragAcceptMode
default dmManual;
end;
procedure Register;
implementation
procedure Register;
begin
{$I extendednotebook_icon.lrs}
RegisterComponents('LazControls',[TExtendedNotebook]);
end;
{ TExtendedNotebook }
procedure TExtendedNotebook.InitDrag;
begin
DragCursor := crDrag;
FDragOverIndex := -1;
FDragOverTabRect := Rect(0, 0, 0, 0);
FDragNextToTabRect := Rect(0, 0, 0, 0);
end;
procedure TExtendedNotebook.InvalidateRect(ARect: TRect);
begin
LCLIntf.InvalidateRect(Handle, @ARect, false);
end;
function TExtendedNotebook.TabIndexForDrag(x, y: Integer): Integer;
var
TabPos: TRect;
begin
Result := TabIndexAtClientPos(Point(X,Y));
if Result < 0 then begin
TabPos := TabRect(PageCount-1);
// Check empty space after last tab
if (TabPos.Right > 1) and (X > TabPos.Left) and
(Y >= TabPos.Top) and (Y <= TabPos.Bottom)
then
Result := PageCount - 1;
end;
end;
function TExtendedNotebook.TabRectEx(AIndex, X, Y: Integer; out IsRightHalf: Boolean): TRect;
begin
Result := TabRect(AIndex);
if (TabPosition in [tpLeft, tpRight]) then // Drag-To-Bottom/Lower
IsRightHalf := Y > (Result.Top + Result.Bottom) div 2
else
IsRightHalf := X > (Result.Left + Result.Right) div 2;
end;
procedure TExtendedNotebook.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var
t: Integer;
begin
InitDrag;
FTabDragged:=false;
inherited MouseDown(Button, Shift, X, Y);
t := TabIndexAtClientPos(Point(X,Y));
if (fTabDragMode = dmAutomatic) and (Button = mbLeft) and (t >= 0) then
BeginDragTab(t, False);
end;
procedure TExtendedNotebook.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
MouseUpTabIndex: LongInt;
begin
InitDrag;
inherited MouseUp(Button, Shift, X, Y);
if not FTabDragged then begin
// no drag => check for normal click and activate page
MouseUpTabIndex := TabIndexAtClientPos(Point(X,Y));
if (Button = mbLeft) and (FDraggingTabIndex = MouseUpTabIndex) and
(FDraggingTabIndex >= 0)
then
PageIndex:=MouseUpTabIndex;
end;
end;
procedure TExtendedNotebook.DoStartDrag(var DragObject: TDragObject);
begin
if FDraggingTabIndex < 0 then
inherited DoStartDrag(DragObject)
else
if Assigned(FOnTabStartDrag) then FOnTabStartDrag(Self, DragObject);
end;
procedure TExtendedNotebook.DoEndDrag(Target: TObject; X, Y: Integer);
begin
if FDraggingTabIndex < 0 then
inherited DoEndDrag(Target, X, Y)
else
if Assigned(FOnTabEndDrag) then FOnTabEndDrag(Self, Target, x, Y);
end;
procedure TExtendedNotebook.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
var
TabIndex: Integer;
LastRect, LastNRect: TRect;
LastIndex: Integer;
LastRight, NeedInvalidate: Boolean;
Ctrl: Boolean;
Src: TExtendedNotebook;
begin
if (not (Source is TExtendedNotebook)) or
(TExtendedNotebook(Source).FDraggingTabIndex < 0)
then begin
// normal DragOver
inherited DragOver(Source, X, Y, State, Accept);
exit;
end;
// Tab drag over
TabIndex := TabIndexForDrag(X,Y);
Accept := (FTabDragAcceptMode = dmAutomatic) and (Source = Self) and
(TabIndex >= 0) and (TabIndex <> FDraggingTabIndex);
if Assigned(FOnTabDragOver) then
FOnTabDragOver(Self,Source,X,Y,State,Accept);
if ((state = dsDragLeave) or (TabIndex < 0)) and
(FDragOverIndex >= 0)
then begin
InvalidateRect(FDragOverTabRect);
InvalidateRect(FDragNextToTabRect);
FDragOverIndex := -1;
end;
if (TabIndex < 0) then
exit;
Ctrl := (GetKeyState(VK_CONTROL) and $8000)<>0;
if Ctrl then
DragCursor := crMultiDrag
else
DragCursor := crDrag;
LastIndex := FDragOverIndex;
LastRight := FDragToRightSide;
LastRect := FDragOverTabRect;
LastNRect := FDragNextToTabRect;
FDragOverIndex := TabIndex;
FDragOverTabRect := TabRectEx(TabIndex, X, Y, FDragToRightSide);
if (Source = Self) and (TabIndex = FDraggingTabIndex - 1) then
FDragToRightSide := False;
if (Source = Self) and (TabIndex = FDraggingTabIndex + 1) then
FDragToRightSide := True;
NeedInvalidate := (FDragOverIndex <> LastIndex) or (FDragToRightSide <> LastRight);
if NeedInvalidate then begin
InvalidateRect(LastRect);
InvalidateRect(LastNRect);
InvalidateRect(FDragOverTabRect);
InvalidateRect(FDragNextToTabRect);
end;
if FDragToRightSide then begin
inc(TabIndex);
if TabIndex < PageCount then
FDragNextToTabRect := TabRect(TabIndex);
end else begin
if TabIndex > 0 then
FDragNextToTabRect := TabRect(TabIndex - 1);
end;
if NeedInvalidate then
InvalidateRect(FDragNextToTabRect);
Src := TExtendedNotebook(Source);
if (Source = self) and (TabIndex > Src.DraggingTabIndex) then
dec(TabIndex);
if Assigned(FOnTabDragOverEx) then
FOnTabDragOverEx(Self, Source, Src.DraggingTabIndex, TabIndex, Ctrl, Accept);
if (not Accept) or (state = dsDragLeave) then begin
InvalidateRect(FDragOverTabRect);
InvalidateRect(FDragNextToTabRect);
FDragOverIndex := -1;
end;
end;
procedure TExtendedNotebook.DragCanceled;
begin
inherited DragCanceled;
if (FDragOverIndex >= 0) then begin
InvalidateRect(FDragOverTabRect);
InvalidateRect(FDragNextToTabRect);
end;
FDragOverIndex := -1;
DragCursor := crDrag;
end;
procedure TExtendedNotebook.PaintWindow(DC: HDC);
var
Points: Array [0..3] of TPoint;
procedure DrawLeftArrow(ARect: TRect);
var y, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
y := (ARect.Top + ARect.Bottom) div 2;
Points[0].X := ARect.Left + 2 + h;
Points[0].y := y - h;
Points[1].X := ARect.Left + 2 + h;
Points[1].y := y + h;
Points[2].X := ARect.Left + 2;
Points[2].y := y;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
procedure DrawRightArrow(ARect: TRect);
var y, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
y := (ARect.Top + ARect.Bottom) div 2;
Points[0].X := ARect.Right - 2 - h;
Points[0].y := y - h;
Points[1].X := ARect.Right - 2 - h;
Points[1].y := y + h;
Points[2].X := ARect.Right - 2;
Points[2].y := y;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
procedure DrawTopArrow(ARect: TRect);
var x, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
x := (ARect.Left + ARect.Right) div 2;
Points[0].Y := ARect.Top + 2 + h;
Points[0].X := x - h;
Points[1].Y := ARect.Top + 2 + h;
Points[1].X := x + h;
Points[2].Y := ARect.Top + 2;
Points[2].X := x;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
procedure DrawBottomArrow(ARect: TRect);
var x, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
x := (ARect.Left + ARect.Right) div 2;
Points[0].Y := ARect.Bottom - 2 - h;
Points[0].X := X - h;
Points[1].Y := ARect.Bottom - 2 - h;
Points[1].X := X + h;
Points[2].Y := ARect.Bottom - 2;
Points[2].X := X;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
begin
inherited PaintWindow(DC);
if FDragOverIndex < 0 then exit;
if (TabPosition in [tpLeft, tpRight]) then begin
if FDragToRightSide then begin
DrawBottomArrow(FDragOverTabRect);
if (FDragOverIndex < PageCount - 1) then
DrawTopArrow(FDragNextToTabRect);
end else begin
DrawTopArrow(FDragOverTabRect);
if (FDragOverIndex > 0) then
DrawBottomArrow(FDragNextToTabRect);
end;
end
else
begin
if FDragToRightSide then begin
DrawRightArrow(FDragOverTabRect);
if (FDragOverIndex < PageCount - 1) then
DrawLeftArrow(FDragNextToTabRect);
end else begin
DrawLeftArrow(FDragOverTabRect);
if (FDragOverIndex > 0) then
DrawRightArrow(FDragNextToTabRect);
end;
end;
end;
constructor TExtendedNotebook.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
InitDrag;
fTabDragMode := dmManual;
end;
procedure TExtendedNotebook.DragDrop(Source: TObject; X, Y: Integer);
var
TabIndex, TabIndex2: Integer;
ToRight: Boolean;
Ctrl: Boolean;
Src: TExtendedNotebook;
Accept: Boolean;
begin
if (not (Source is TExtendedNotebook)) or
(TExtendedNotebook(Source).FDraggingTabIndex < 0)
then begin
// normal DragDrop
inherited DragDrop(Source, X, Y);
exit;
end;
// Tab DragDrop
If Assigned(FOnTabDragDrop) then FOnTabDragDrop(Self, Source,X,Y);
if (FDragOverIndex >= 0) then begin
InvalidateRect(FDragOverTabRect);
InvalidateRect(FDragNextToTabRect);
end;
FDragOverIndex := -1;
DragCursor := crDrag;
TabIndex := TabIndexForDrag(X,Y);
TabRectEx(TabIndex, X, Y, ToRight);
if (Source = Self) and (TabIndex = FDraggingTabIndex - 1) then
ToRight := False;
if (Source = Self) and (TabIndex = FDraggingTabIndex + 1) then
ToRight := True;
if ToRight then
inc(TabIndex);
Src := TExtendedNotebook(Source);
TabIndex2 := TabIndex;
if (Source = self) and (TabIndex > Src.DraggingTabIndex) then
dec(TabIndex);
if assigned(FOnTabDragDropEx) then begin
Ctrl := (GetKeyState(VK_CONTROL) and $8000)<>0;
Accept := True;
if Assigned(FOnTabDragOverEx) then
FOnTabDragOverEx(Self, Source, Src.DraggingTabIndex, TabIndex, Ctrl, Accept);
if Accept then
FOnTabDragDropEx(Self, Source, Src.DraggingTabIndex, TabIndex, Ctrl, FTabDragged);
end;
if (not FTabDragged) and (FTabDragAcceptMode = dmAutomatic) and
(Source = Self) and (TabIndex2 >= 0) and (TabIndex2 <> FDraggingTabIndex)
then begin
Pages.Move(Src.DraggingTabIndex, TabIndex);
FTabDragged := True;
end;
end;
procedure TExtendedNotebook.BeginDragTab(ATabIndex: Integer; Immediate: Boolean;
Threshold: Integer = -1);
begin
if (ATabIndex < 0) or (ATabIndex >= PageCount) then
raise Exception.Create('Bad index');
FDraggingTabIndex := ATabIndex;
BeginDrag(Immediate, Threshold);
end;
end.

View File

@ -0,0 +1,19 @@
LazarusResources.Add('textnotebook','PNG',[
#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#6#0#0#0#224'w='#248#0
+#0#0#1'sRGB'#0#174#206#28#233#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0#9
+'pHYs'#0#0#14#195#0#0#14#195#1#199'o'#168'd'#0#0#1'CIDATHKc'#252#15#4#12'4'#4
+'L44'#27'l4#6'#31#236'>'#255#129#161'i'#193'v'#178#237#174'K'#240'dp5'#20#128
+#232#7'Y'#128#14'l'#242#150#253#255#248#233'7'#6#198'&'#142'K'#12'f&'#206' '
+#186#127#239#9#3':'#6'9'#136'X'#177#195#7#15'a'#6'Qy'#249'd'#178#131#5']'#163
+#143#151'>'#131#173#189#29'j'#16#149#149'M'#194#22'b$'#139#129#204'9t'#224' '
+'X'#31#206' z'#240#224#14#3'2'#6#185#144#24'1X'#208#192'|'#4#182#0#20'4'#176
+#224'AW'#0#146'WPP'#193#25't'#248#228'@'#154#192#22'tv'#230'2'#128#194#12#4
+#182'l'#187#8#183#12#217'p'#144#235#209#1'L'#12#175'%'#200#1#140#28#7#247#239
+#223'&9'#236'Az@a'#143#17#7#132#130#136#146#164#5#207#201#160#176#7#5#15#12
+'dfz'#130#153'0'#239'c'#11'"l'#242#143#31'>'#3#155#3'K'#166#240'T'#4'N'#179
+#208#248#0#197#9#12#224#11'gB'#150#195'#'#153'P'#16#225'r=,'#233#226#11'B'
+#130#169#8#221''''#200#134#225#179#24#166#142'`'#16'Q'#18#193'D'#7#17'%'#150
+#16#29'D'#228'ZB'#159' '#194#230':Pz&'#7#163#155#133'Re'#210#162'>'#192#168
+#147#177#149#166#228#134'?('#243'b'#173#244#201'5'#16#155'>'#0'F'#185#255#147
+#18#219#213#163#0#0#0#0'IEND'#174'B`'#130
]);

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

View File

@ -11,15 +11,22 @@
</SearchPaths> </SearchPaths>
<Other> <Other>
<CompilerPath Value="$(CompPath)"/> <CompilerPath Value="$(CompPath)"/>
<CreateMakefileOnBuild Value="True"/>
</Other> </Other>
</CompilerOptions> </CompilerOptions>
<Files Count="1"> <Files Count="2">
<Item1> <Item1>
<Filename Value="dividerbevel.pas"/> <Filename Value="dividerbevel.pas"/>
<HasRegisterProc Value="True"/> <HasRegisterProc Value="True"/>
<UnitName Value="dividerbevel"/> <UnitName Value="DividerBevel"/>
</Item1> </Item1>
<Item2>
<Filename Value="extendednotebook.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="ExtendedNotebook"/>
</Item2>
</Files> </Files>
<LazDoc Paths="docs\"/>
<Type Value="RunAndDesignTime"/> <Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="2"> <RequiredPkgs Count="2">
<Item1> <Item1>

View File

@ -7,13 +7,14 @@ unit lazcontrols;
interface interface
uses uses
DividerBevel, LazarusPackageIntf; DividerBevel, ExtendedNotebook, LazarusPackageIntf;
implementation implementation
procedure Register; procedure Register;
begin begin
RegisterUnit('DividerBevel', @DividerBevel.Register); RegisterUnit('DividerBevel', @DividerBevel.Register);
RegisterUnit('ExtendedNotebook', @ExtendedNotebook.Register);
end; end;
initialization initialization

View File

@ -40,7 +40,7 @@ uses
{$IFDEF IDE_MEM_CHECK} {$IFDEF IDE_MEM_CHECK}
MemCheck, MemCheck,
{$ENDIF} {$ENDIF}
Classes, SysUtils, Math, Controls, LCLProc, LCLType, LResources, Classes, SysUtils, Math, Controls, ExtendedNotebook, LCLProc, LCLType, LResources,
LCLIntf, FileUtil, Forms, ComCtrls, Dialogs, StdCtrls, Graphics, Translations, LCLIntf, FileUtil, Forms, ComCtrls, Dialogs, StdCtrls, Graphics, Translations,
ClipBrd, types, Extctrls, Menus, HelpIntfs, LConvEncoding, ClipBrd, types, Extctrls, Menus, HelpIntfs, LConvEncoding,
// codetools // codetools
@ -49,7 +49,7 @@ uses
SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, SynRegExpr, SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, SynRegExpr,
SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion, SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion,
SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks, SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks,
SynBeautifier, SynEditTextBase, SynPluginTemplateEdit, SynPluginSyncroEdit, SynBeautifier, SynEditTextBase,
SynPluginSyncronizedEditBase, SourceSynEditor, SynPluginSyncronizedEditBase, SourceSynEditor,
// Intf // Intf
SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, IDEHelpIntf, IDEImagesIntf, SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, IDEHelpIntf, IDEImagesIntf,
@ -524,39 +524,6 @@ type
); );
TSourceNotebookStates = set of TSourceNotebookState; TSourceNotebookStates = set of TSourceNotebookState;
TDragMoveTabEvent = procedure(Sender, Source: TObject; OldIndex, NewIndex: Integer; CopyDrag: Boolean) of object;
TDragMoveTabQuery = function(Sender, Source: TObject; OldIndex, NewIndex: Integer; CopyDrag: Boolean): Boolean of object;
{ TSourceDragableNotebook }
TSourceDragableNotebook = class(TNoteBook)
private
FMouseDownTabIndex: Integer;
FOnCanDragMoveTab: TDragMoveTabQuery;
FOnDragMoveTab: TDragMoveTabEvent;
FTabDragged: boolean;
FDragOverIndex: Integer;
FDragToRightSide: Boolean;
FDragOverTabRect, FDragNextToTabRect: TRect;
protected
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); override;
procedure DragCanceled; override;
property MouseDownTabIndex: Integer read FMouseDownTabIndex;
procedure PaintWindow(DC: HDC); override;
procedure InitDrag;
public
constructor Create(TheOwner: TComponent); override;
procedure DragDrop(Source: TObject; X, Y: Integer); override;
property OnDragMoveTab: TDragMoveTabEvent read FOnDragMoveTab write FOnDragMoveTab;
property OnCanDragMoveTab: TDragMoveTabQuery read FOnCanDragMoveTab write FOnCanDragMoveTab;
end;
{ TSourceNotebook } { TSourceNotebook }
TSourceNotebook = class(TSourceEditorWindowInterface) TSourceNotebook = class(TSourceEditorWindowInterface)
@ -565,7 +532,7 @@ type
Shift: TShiftState; X, Y: Integer); Shift: TShiftState; X, Y: Integer);
procedure StatusBarDblClick(Sender: TObject); procedure StatusBarDblClick(Sender: TObject);
private private
FNotebook: TSourceDragableNotebook; FNotebook: TExtendedNotebook;
FBaseCaption: String; FBaseCaption: String;
FIsClosing: Boolean; FIsClosing: Boolean;
SrcPopUpMenu: TPopupMenu; SrcPopUpMenu: TPopupMenu;
@ -711,9 +678,11 @@ type
procedure NotebookMouseDown(Sender: TObject; Button: TMouseButton; procedure NotebookMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X,Y: Integer); Shift: TShiftState; X,Y: Integer);
procedure NotebookDragTabMove(Sender, Source: TObject; procedure NotebookDragTabMove(Sender, Source: TObject;
OldIndex, NewIndex: Integer; CopyDrag: Boolean); OldIndex, NewIndex: Integer; CopyDrag: Boolean;
function NotebookCanDragTabMove(Sender, Source: TObject; var Done: Boolean);
OldIndex, NewIndex: Integer; CopyDrag: Boolean): Boolean; procedure NotebookCanDragTabMove(Sender, Source: TObject;
OldIndex, NewIndex: Integer; CopyDrag: Boolean;
var Accept: Boolean);
procedure NotebookDragOver(Sender, Source: TObject; procedure NotebookDragOver(Sender, Source: TObject;
X,Y: Integer; State: TDragState; var Accept: Boolean); X,Y: Integer; State: TDragState; var Accept: Boolean);
procedure NotebookEndDrag(Sender, Target: TObject; X,Y: Integer); procedure NotebookEndDrag(Sender, Target: TObject; X,Y: Integer);
@ -4913,7 +4882,7 @@ Begin
{$IFDEF IDE_MEM_CHECK} {$IFDEF IDE_MEM_CHECK}
CheckHeapWrtMemCnt('[TSourceNotebook.CreateNotebook] A '); CheckHeapWrtMemCnt('[TSourceNotebook.CreateNotebook] A ');
{$ENDIF} {$ENDIF}
FNotebook := TSourceDragableNotebook.Create(self); FNotebook := TExtendedNotebook.Create(self);
{$IFDEF IDE_DEBUG} {$IFDEF IDE_DEBUG}
writeln('[TSourceNotebook.CreateNotebook] B'); writeln('[TSourceNotebook.CreateNotebook] B');
{$ENDIF} {$ENDIF}
@ -4942,10 +4911,11 @@ Begin
OnPageChanged := @NotebookPageChanged; OnPageChanged := @NotebookPageChanged;
OnCloseTabClicked:=@CloseTabClicked; OnCloseTabClicked:=@CloseTabClicked;
OnMouseDown:=@NotebookMouseDown; OnMouseDown:=@NotebookMouseDown;
OnCanDragMoveTab := @NotebookCanDragTabMove; TabDragMode := dmAutomatic;
OnDragOver := @NotebookDragOver; OnTabDragOverEx := @NotebookCanDragTabMove;
OnEndDrag := @NotebookEndDrag; OnTabDragDropEx := @NotebookDragTabMove;
OnDragMoveTab := @NotebookDragTabMove; OnTabDragOver := @NotebookDragOver;
OnTabEndDrag := @NotebookEndDrag;
ShowHint:=true; ShowHint:=true;
OnShowHint:=@NotebookShowTabHint; OnShowHint:=@NotebookShowTabHint;
{$IFDEF IDE_DEBUG} {$IFDEF IDE_DEBUG}
@ -5927,7 +5897,7 @@ begin
inherited DragOver(Source, X, Y, State, Accept); inherited DragOver(Source, X, Y, State, Accept);
if State = dsDragLeave then if State = dsDragLeave then
FUpdateTabAndPageTimer.Enabled := True FUpdateTabAndPageTimer.Enabled := True
else if Source is TSourceDragableNotebook then else if Source is TExtendedNotebook then
FNotebook.ShowTabs := True; FNotebook.ShowTabs := True;
end; end;
@ -6892,7 +6862,7 @@ begin
end; end;
procedure TSourceNotebook.NotebookDragTabMove(Sender, Source: TObject; OldIndex, procedure TSourceNotebook.NotebookDragTabMove(Sender, Source: TObject; OldIndex,
NewIndex: Integer; CopyDrag: Boolean); NewIndex: Integer; CopyDrag: Boolean; var Done: Boolean);
function SourceIndex: Integer; function SourceIndex: Integer;
begin begin
Result := Manager.SourceWindowCount - 1; Result := Manager.SourceWindowCount - 1;
@ -6902,24 +6872,30 @@ procedure TSourceNotebook.NotebookDragTabMove(Sender, Source: TObject; OldIndex,
end; end;
end; end;
begin begin
{$IFnDEF SingleSrcWindow}
If CopyDrag then begin If CopyDrag then begin
Manager.SourceWindows[SourceIndex].CopyEditor Manager.SourceWindows[SourceIndex].CopyEditor
(OldIndex, Manager.IndexOfSourceWindow(self), NewIndex); (OldIndex, Manager.IndexOfSourceWindow(self), NewIndex);
end end
else begin else begin
{$ENDIF}
if (Source = FNotebook) then if (Source = FNotebook) then
MoveEditor(OldIndex, NewIndex) MoveEditor(OldIndex, NewIndex)
else begin else begin
Manager.SourceWindows[SourceIndex].MoveEditor Manager.SourceWindows[SourceIndex].MoveEditor
(OldIndex, Manager.IndexOfSourceWindow(self), NewIndex); (OldIndex, Manager.IndexOfSourceWindow(self), NewIndex);
end; end;
{$IFnDEF SingleSrcWindow}
end; end;
{$ENDIF}
Manager.ActiveSourceWindow := self; Manager.ActiveSourceWindow := self;
Manager.ShowActiveWindowOnTop(True); Manager.ShowActiveWindowOnTop(True);
Done := True;
end; end;
function TSourceNotebook.NotebookCanDragTabMove(Sender, Source: TObject; procedure TSourceNotebook.NotebookCanDragTabMove(Sender, Source: TObject;
OldIndex, NewIndex: Integer; CopyDrag: Boolean): Boolean; OldIndex, NewIndex: Integer; CopyDrag: Boolean; var Accept: Boolean);
function SourceIndex: Integer; function SourceIndex: Integer;
begin begin
Result := Manager.SourceWindowCount - 1; Result := Manager.SourceWindowCount - 1;
@ -6935,10 +6911,12 @@ begin
Src := Manager.SourceWindows[SourceIndex]; Src := Manager.SourceWindows[SourceIndex];
NBHasSharedEditor := IndexOfEditorInShareWith NBHasSharedEditor := IndexOfEditorInShareWith
(Src.FindSourceEditorWithPageIndex(OldIndex)) >= 0; (Src.FindSourceEditorWithPageIndex(OldIndex)) >= 0;
{$IFnDEF SingleSrcWindow}
if CopyDrag then if CopyDrag then
Result := (NewIndex >= 0) and (Source <> Sender) and (not NBHasSharedEditor) Accept := (NewIndex >= 0) and (Source <> Sender) and (not NBHasSharedEditor)
else else
Result := (NewIndex >= 0) and {$ENDIF}
Accept := (NewIndex >= 0) and
((Source <> Sender) or (OldIndex <> NewIndex)) and ((Source <> Sender) or (OldIndex <> NewIndex)) and
((Source = Sender) or (not NBHasSharedEditor)); ((Source = Sender) or (not NBHasSharedEditor));
end; end;
@ -6949,7 +6927,7 @@ begin
FUpdateTabAndPageTimer.Enabled := False; FUpdateTabAndPageTimer.Enabled := False;
if State = dsDragLeave then if State = dsDragLeave then
FUpdateTabAndPageTimer.Enabled := True FUpdateTabAndPageTimer.Enabled := True
else if Source is TSourceDragableNotebook then else if Source is TExtendedNotebook then
FNotebook.ShowTabs := True; FNotebook.ShowTabs := True;
end; end;
@ -7562,313 +7540,6 @@ begin
FreeThenNil(aWordCompletion); FreeThenNil(aWordCompletion);
end; end;
{ TSourceDragableNotebook }
procedure TSourceDragableNotebook.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
InitDrag;
FTabDragged:=false;
inherited MouseDown(Button, Shift, X, Y);
FMouseDownTabIndex := TabIndexAtClientPos(Point(X,Y));
if (Button = mbLeft) and (FMouseDownTabIndex >= 0) then
BeginDrag(False);
end;
procedure TSourceDragableNotebook.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
var
MouseUpTabIndex: LongInt;
begin
InitDrag;
inherited MouseUp(Button, Shift, X, Y);
if not FTabDragged then begin
// no drag => check for normal click and activate page
MouseUpTabIndex := TabIndexAtClientPos(Point(X,Y));
if (Button = mbLeft) and (FMouseDownTabIndex = MouseUpTabIndex) and
(FMouseDownTabIndex >= 0)
then
PageIndex:=MouseUpTabIndex;
end;
end;
procedure TSourceDragableNotebook.DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
var
TabIndex: Integer;
TabPos, LastRect, LastNRect, tmp: TRect;
LastIndex: Integer;
LastRight, NeedInvalidate: Boolean;
Ctrl: Boolean;
Src: TSourceDragableNotebook;
begin
inherited DragOver(Source, X, Y, State, Accept);
if (state = dsDragLeave) and (FDragOverIndex >= 0) then begin
tmp := FDragOverTabRect;
InvalidateRect(Handle, @tmp, false);
tmp := FDragNextToTabRect;
InvalidateRect(Handle, @tmp, false);
FDragOverIndex := -1;
end;
// currently limited to source=self => extendable to allow dragging tabs from other notebooks
if (Source is TSourceDragableNotebook) and
(TSourceDragableNotebook(Source).FMouseDownTabIndex >= 0)
then begin
{$IFnDEF SingleSrcWindow}
Ctrl := (GetKeyState(VK_CONTROL) and $8000)<>0;
{$ELSE}
Ctrl := false;
{$ENDIF}
if Ctrl then
DragCursor := crMultiDrag
else
DragCursor := crDrag;
TabIndex := TabIndexAtClientPos(Point(X,Y));
if TabIndex < 0 then begin
TabPos := TabRect(PageCount-1);
if (TabPos.Right > 1) and (X > TabPos.Left) then
TabIndex := PageCount - 1;
end;
if TabIndex < 0 then begin
Accept := False;
exit;
end;
LastIndex := FDragOverIndex;
LastRight := FDragToRightSide;
LastRect := FDragOverTabRect;
LastNRect := FDragNextToTabRect;
FDragOverIndex := TabIndex;
FDragOverTabRect := TabRect(TabIndex);
if (TabPosition in [tpLeft, tpRight]) then
// Drag-To-Bottom/Lower
FDragToRightSide := Y > (FDragOverTabRect.Top + FDragOverTabRect.Bottom) div 2
else
FDragToRightSide := X > (FDragOverTabRect.Left + FDragOverTabRect.Right) div 2;
if (Source = Self) and (TabIndex = FMouseDownTabIndex - 1) then
FDragToRightSide := False;
if (Source = Self) and (TabIndex = FMouseDownTabIndex + 1) then
FDragToRightSide := True;
NeedInvalidate := (FDragOverIndex <> LastIndex) or (FDragToRightSide <> LastRight);
if NeedInvalidate then begin
InvalidateRect(Handle, @LastRect, false);
InvalidateRect(Handle, @LastNRect, false);
tmp := FDragOverTabRect;
InvalidateRect(Handle, @tmp, false);
tmp := FDragNextToTabRect;
InvalidateRect(Handle, @tmp, false);
end;
if FDragToRightSide then begin
inc(TabIndex);
if TabIndex < PageCount then
FDragNextToTabRect := TabRect(TabIndex);
end else begin
if TabIndex > 0 then
FDragNextToTabRect := TabRect(TabIndex - 1);
end;
if NeedInvalidate then begin
tmp := FDragNextToTabRect;
InvalidateRect(Handle, @tmp, false);
end;
Src := TSourceDragableNotebook(Source);
if (Source = self) and (TabIndex > Src.MouseDownTabIndex) then
dec(TabIndex);
Accept := OnCanDragMoveTab(Self, Source, Src.MouseDownTabIndex, TabIndex, Ctrl);
end
else
FDragOverIndex := -1;
if (not Accept) or (state = dsDragLeave) then
FDragOverIndex := -1;
end;
procedure TSourceDragableNotebook.DragCanceled;
var
tmp: TRect;
begin
inherited DragCanceled;
if (FDragOverIndex >= 0) then begin
tmp := FDragOverTabRect;
InvalidateRect(Handle, @tmp, false);
tmp := FDragNextToTabRect;
InvalidateRect(Handle, @tmp, false);
end;
FDragOverIndex := -1;
DragCursor := crDrag;
end;
procedure TSourceDragableNotebook.PaintWindow(DC: HDC);
var
Points: Array [0..3] of TPoint;
procedure DrawLeftArrow(ARect: TRect);
var y, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
y := (ARect.Top + ARect.Bottom) div 2;
Points[0].X := ARect.Left + 2 + h;
Points[0].y := y - h;
Points[1].X := ARect.Left + 2 + h;
Points[1].y := y + h;
Points[2].X := ARect.Left + 2;
Points[2].y := y;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
procedure DrawRightArrow(ARect: TRect);
var y, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
y := (ARect.Top + ARect.Bottom) div 2;
Points[0].X := ARect.Right - 2 - h;
Points[0].y := y - h;
Points[1].X := ARect.Right - 2 - h;
Points[1].y := y + h;
Points[2].X := ARect.Right - 2;
Points[2].y := y;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
procedure DrawTopArrow(ARect: TRect);
var x, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
x := (ARect.Left + ARect.Right) div 2;
Points[0].Y := ARect.Top + 2 + h;
Points[0].X := x - h;
Points[1].Y := ARect.Top + 2 + h;
Points[1].X := x + h;
Points[2].Y := ARect.Top + 2;
Points[2].X := x;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
procedure DrawBottomArrow(ARect: TRect);
var x, h: Integer;
begin
h := Min( (Abs(ARect.Bottom - ARect.Top) - 4) div 2,
(Abs(ARect.Left - ARect.Right) - 4) div 2 );
x := (ARect.Left + ARect.Right) div 2;
Points[0].Y := ARect.Bottom - 2 - h;
Points[0].X := X - h;
Points[1].Y := ARect.Bottom - 2 - h;
Points[1].X := X + h;
Points[2].Y := ARect.Bottom - 2;
Points[2].X := X;
Points[3] := Points[0];
Polygon(DC, @Points, 4, False);
end;
begin
inherited PaintWindow(DC);
if FDragOverIndex < 0 then exit;
if (TabPosition in [tpLeft, tpRight]) then begin
if FDragToRightSide then begin
DrawBottomArrow(FDragOverTabRect);
if (FDragOverIndex < PageCount - 1) then
DrawTopArrow(FDragNextToTabRect);
end else begin
DrawTopArrow(FDragOverTabRect);
if (FDragOverIndex > 0) then
DrawBottomArrow(FDragNextToTabRect);
end;
end
else
begin
if FDragToRightSide then begin
DrawRightArrow(FDragOverTabRect);
if (FDragOverIndex < PageCount - 1) then
DrawLeftArrow(FDragNextToTabRect);
end else begin
DrawLeftArrow(FDragOverTabRect);
if (FDragOverIndex > 0) then
DrawRightArrow(FDragNextToTabRect);
end;
end;
end;
procedure TSourceDragableNotebook.InitDrag;
begin
DragCursor := crDrag;
FDragOverIndex := -1;
FDragOverTabRect := Rect(0, 0, 0, 0);
FDragNextToTabRect := Rect(0, 0, 0, 0);
end;
constructor TSourceDragableNotebook.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
InitDrag;
end;
procedure TSourceDragableNotebook.DragDrop(Source: TObject; X, Y: Integer);
var
TabIndex: Integer;
TabPos, tmp: TRect;
ToRight: Boolean;
Ctrl: Boolean;
Src: TSourceDragableNotebook;
begin
inherited DragDrop(Source, X, Y);
if (FDragOverIndex >= 0) then begin
tmp := FDragOverTabRect;
InvalidateRect(Handle, @tmp, false);
tmp := FDragNextToTabRect;
InvalidateRect(Handle, @tmp, false);
end;
FDragOverIndex := -1;
DragCursor := crDrag;
if assigned(FOnDragMoveTab) and (Source is TSourceDragableNotebook) and
(TSourceDragableNotebook(Source).MouseDownTabIndex >= 0)
then begin
{$IFnDEF SingleSrcWindow}
Ctrl := (GetKeyState(VK_CONTROL) and $8000)<>0;
{$ELSE}
Ctrl := false;
{$ENDIF}
TabIndex := TabIndexAtClientPos(Point(X,Y));
if TabIndex < 0 then begin
TabPos := TabRect(PageCount-1);
if (TabPos.Right > 1) and (X > TabPos.Left) then
TabIndex := PageCount - 1;
end;
TabPos := TabRect(TabIndex);
ToRight := X > (TabPos.Left + TabPos.Right) div 2;
if (Source = Self) and (TabIndex = FMouseDownTabIndex - 1) then
ToRight := False;
if (Source = Self) and (TabIndex = FMouseDownTabIndex + 1) then
ToRight := True;
if ToRight then
inc(TabIndex);
Src := TSourceDragableNotebook(Source);
// includes unknown
if (Source = self) and (TabIndex > Src.MouseDownTabIndex) then
dec(TabIndex);
if OnCanDragMoveTab(Self, Source, Src.MouseDownTabIndex, TabIndex, Ctrl) then
begin
FTabDragged:=true;
FOnDragMoveTab(Self, Source, Src.MouseDownTabIndex, TabIndex, Ctrl);
end;
end;
end;
{ TSourceEditorManagerBase } { TSourceEditorManagerBase }
procedure TSourceEditorManagerBase.FreeSourceWindows; procedure TSourceEditorManagerBase.FreeSourceWindows;