diff --git a/icons/other/splitter.png b/icons/other/splitter.png
new file mode 100644
index 00000000..1aacb081
Binary files /dev/null and b/icons/other/splitter.png differ
diff --git a/lazproj/test/pagecontrol/pagecontrol.lpi b/lazproj/test/pagecontrol/pagecontrol.lpi
index d6cbb4dc..b20c9d17 100644
--- a/lazproj/test/pagecontrol/pagecontrol.lpi
+++ b/lazproj/test/pagecontrol/pagecontrol.lpi
@@ -55,6 +55,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lazproj/test/pagecontrol/pagecontroltester.pas b/lazproj/test/pagecontrol/pagecontroltester.pas
index 0f1c50c3..82ac37ca 100644
--- a/lazproj/test/pagecontrol/pagecontroltester.pas
+++ b/lazproj/test/pagecontrol/pagecontroltester.pas
@@ -36,6 +36,7 @@ begin
AssignPng(fPageControl.addButton.Glyph, 'document_add');
AssignPng(fPageControl.moveLeftButton.Glyph, 'document_back');
AssignPng(fPageControl.moveRightButton.Glyph, 'document_next');
+ AssignPng(fPageControl.splitButton.Glyph, 'splitter');
end;
procedure TForm1.pageControlChanged(sender: TObject);
diff --git a/src/ce_controls.pas b/src/ce_controls.pas
index 573f022e..90b08bc9 100644
--- a/src/ce_controls.pas
+++ b/src/ce_controls.pas
@@ -8,11 +8,11 @@ uses
Classes, SysUtils, Forms, Controls, ComCtrls, ExtCtrls, buttons;
type
- TCEPageControlButton = (pbClose, pbMoveLeft, pbMoveRight, pbAdd);
+ TCEPageControlButton = (pbClose, pbMoveLeft, pbMoveRight, pbAdd, pbSplit);
TCEPageControlButtons = set of TCEPageControlButton;
const
- CEPageControlDefaultButtons = [pbClose, pbMoveLeft, pbMoveRight, pbAdd];
+ CEPageControlDefaultButtons = [pbClose, pbMoveLeft, pbMoveRight, pbAdd, pbSplit];
type
@@ -30,8 +30,9 @@ type
* Minimalist page-control dedicated to Coedit
*
* - get rid of the framed aspect of the default LCL one
- * - no published props, since CE has to be compilable w/o extra IDE comps
+ * - no published props, no need for design time support
* - add/close/move left and right speed buttons
+ * - a particular tab can be set to reside on a split view
*)
TCEPageControl = class(TWinControl)
private
@@ -41,17 +42,22 @@ type
fMoveLeftBtn: TSpeedButton;
fMoveRightBtn: TSpeedButton;
fAddBtn: TSpeedButton;
+ fSplitBtn: TSpeedButton;
fContent: TPanel;
fPages: TFPList;
fPageIndex: integer;
+ fSplittedPageIndex: integer;
fButtons: TCEPageControlButtons;
fOnChanged: TNotifyEvent;
fOnChanging: TTabChangingEvent;
+ fSplitter: TSplitter;
+ fOldSplitPos: integer;
procedure btnCloseClick(sender: TObject);
procedure btnMoveLeftClick(sender: TObject);
procedure btnMoveRightClick(sender: TObject);
procedure btnAddClick(sender: TObject);
+ procedure btnSplitClick(sender: TObject);
procedure tabsChanging(Sender: TObject; var AllowChange: Boolean);
procedure tabsChanged(sender: TObject);
@@ -87,6 +93,7 @@ type
property moveLeftButton: TSpeedButton read fMoveLeftBtn;
property moveRightButton: TSpeedButton read fMoveRightBtn;
property addButton: TSpeedButton read fAddBtn;
+ property splitButton: TSpeedButton read fSplitBtn;
property onChanged: TNotifyEvent read fOnChanged write fOnChanged;
property onChanging: TTabChangingEvent read fOnChanging write fOnChanging;
@@ -126,6 +133,8 @@ begin
fHeader.Align := alTop;
fHeader.Height:= 32;
+ fSplittedPageIndex:=-1;
+
fTabs := TTabControl.Create(self);
fTabs.Parent:= fHeader;
fTabs.Align := alClient;
@@ -169,6 +178,15 @@ begin
fCloseBtn.OnClick:=@btnCloseClick;
fCloseBtn.Hint:='close current page';
+ fSplitBtn := TSpeedButton.Create(self);
+ fSplitBtn.Parent := fHeader;
+ fSplitBtn.Align:= alRight;
+ fSplitBtn.Width:= 28;
+ fSplitBtn.BorderSpacing.Around:= 2;
+ fSplitBtn.ShowCaption:=false;
+ fSplitBtn.OnClick:=@btnSplitClick;
+ fSplitBtn.Hint:= 'pin or un-pin the page to the right';
+
fContent := TPanel.Create(self);
fContent.Parent := self;
fContent.Align := alClient;
@@ -177,6 +195,12 @@ begin
fContent.BorderStyle:=bsNone;
fContent.BorderSpacing.Top:=3;
+ fSplitter := TSplitter.Create(self);
+ fSplitter.Parent := fContent;
+ fSplitter.Visible:= false;
+ fSplitter.Align := alLeft;
+ fSplitter.Width := 6;
+
fPages := TFPList.Create;
fPageIndex := -1;
@@ -201,7 +225,8 @@ end;
procedure TCEPageControl.tabsChanged(sender: TObject);
begin
- setPageIndex(fTabs.TabIndex);
+ if fTabs.TabIndex < fPages.Count then
+ setPageIndex(fTabs.TabIndex);
end;
procedure TCEPageControl.tabsChanging(Sender: TObject; var AllowChange: Boolean);
@@ -229,6 +254,8 @@ begin
exit;
pge := TCEPage(fPages.Items[index]);
+ if (fSplittedPageIndex = -1) or (index = fSplittedPageIndex) then
+ pge.Align:=alClient;
pge.Visible:=true;
pge.Repaint;
for ctl in pge.GetEnumeratorControls do
@@ -236,15 +263,42 @@ begin
end;
procedure TCEPageControl.setPageIndex(index: integer);
+var
+ leftp, rightp: TCEPage;
begin
+ if (fPageIndex <> fSplittedPageIndex) then
+ fOldSplitPos := fSplitter.Left;
if (index > fPages.Count-1) then
index := fPages.Count-1;
if (index < 0) then
exit;
- hidePage(fPageIndex);
- fPageIndex := index;
- showPage(fPageIndex);
+ if (fSplittedPageIndex = -1) or (index = fSplittedPageIndex) then
+ begin
+ hidePage(fPageIndex);
+ fPageIndex := index;
+ showPage(fPageIndex);
+ fSplitter.Visible:= false;
+ end
+ else if (fSplittedPageIndex <> -1) then
+ begin
+ hidePage(fPageIndex);
+ fPageIndex := index;
+
+ fSplitter.Visible:= true;
+
+ leftp := getPage(fPageIndex);
+ leftp.Align := alLeft;
+ if fOldSplitPos = 0 then
+ leftp.Width:= (fContent.Width - fSplitter.Width) div 2
+ else
+ leftp.Width:= fOldSplitPos;
+ showPage(fPageIndex);
+
+ rightp := getPage(fSplittedPageIndex);
+ rightp.Align := alClient;
+ showPage(fSplittedPageIndex);
+ end;
if fTabs.TabIndex <> fPageIndex then
fTabs.TabIndex:= fPageIndex;
@@ -272,12 +326,18 @@ begin
if (index > fPages.Count-1) or (index < 0) then
exit;
+ if index = fSplittedPageIndex then
+ fSplittedPageIndex := -1
+ else if index < fSplittedPageIndex then
+ fSplittedPageIndex -= 1;
+
TCEPage(fPages.Items[index]).Free;
+ if fPageIndex >= fPages.Count then
+ fPageIndex -= 1;
+
fPages.Delete(index);
fTabs.Tabs.Delete(index);
- if fPageIndex >= fPages.Count then
- fPageIndex -= 1;
updateButtonsState;
if fPages.Count = 0 then
exit;
@@ -320,6 +380,8 @@ begin
fPages.Exchange(fPageIndex, fPageIndex + 1);
fTabs.Tabs.Exchange(fPageIndex, fPageIndex + 1);
+ if fPageIndex = fSplittedPageIndex then
+ fSplittedPageIndex += 1;
setPageIndex(fPageIndex+1);
end;
@@ -330,6 +392,8 @@ begin
fPages.Exchange(fPageIndex, fPageIndex - 1);
fTabs.Tabs.Exchange(fPageIndex, fPageIndex - 1);
+ if fPageIndex = fSplittedPageIndex then
+ fSplittedPageIndex -= 1;
setPageIndex(fPageIndex-1);
end;
@@ -353,6 +417,19 @@ begin
addPage;
end;
+procedure TCEPageControl.btnSplitClick(sender: TObject);
+begin
+ if fPageIndex = fSplittedPageIndex then
+ fSplittedPageIndex := -1
+ else
+ begin
+ if (fSplittedPageIndex <> -1) then
+ hidePage(fSplittedPageIndex);
+ fSplittedPageIndex:= fPageIndex;
+ end;
+ setPageIndex(fPageIndex);
+end;
+
procedure TCEPageControl.setButtons(value: TCEPageControlButtons);
begin
if fButtons = value then
@@ -370,6 +447,7 @@ begin
fMoveLeftBtn.Visible:= pbMoveLeft in fButtons;
fCloseBtn.Visible:= pbMoveRight in fButtons;
fAddBtn.Visible:= pbAdd in fButtons;
+ fSplitBtn.Visible:= pbSplit in fButtons;
fHeader.EnableAlign;
fCloseBtn.Enabled := fPageIndex <> -1;
fMoveLeftBtn.Enabled := fPageIndex > 0;
diff --git a/src/ce_editor.pas b/src/ce_editor.pas
index 6afac642..3d74408f 100644
--- a/src/ce_editor.pas
+++ b/src/ce_editor.pas
@@ -77,6 +77,7 @@ type
function findDocument(aFilename: string): TCESynMemo;
procedure openDocument(aFilename: string);
function closeDocument(index: Integer): boolean;
+ function closeDocument(doc: TCESynMemo): boolean;
public
constructor create(aOwner: TComponent); override;
destructor destroy; override;
@@ -102,6 +103,7 @@ begin
AssignPng(pageControl.moveRightButton, 'go_next');
AssignPng(pageControl.addButton, 'document_add');
AssignPng(pageControl.closeButton, 'document_delete');
+ AssignPng(pageControl.splitButton, 'splitter');
fTokList := TLexTokenList.Create;
fErrList := TLexErrorList.Create;
@@ -245,6 +247,16 @@ begin
doc.Free;
result := true;
end;
+
+function TCEEditorWidget.closeDocument(doc: TCESynMemo): boolean;
+var
+ page: TCEPage = nil;
+begin
+ page := TCEPage(doc.Parent);
+ if not assigned(page) then
+ exit(false);
+ exit(closeDocument(page.index));
+end;
{$ENDREGION}
{$REGION PageControl/Editor things ---------------------------------------------}
diff --git a/src/ce_icons.inc b/src/ce_icons.inc
index 2f651bb5..6022543c 100644
--- a/src/ce_icons.inc
+++ b/src/ce_icons.inc
@@ -1879,6 +1879,22 @@ LazarusResources.Add('script_bricks','PNG',[
+#208#201#143'>'#252#244#1#12#220#156#248'7'#240'qB'#160'$'#2#254#184#240'?'
+#248'.'#192#0#5#181#10'l'#246#0'3S'#0#0#0#0'IEND'#174'B`'#130
]);
+LazarusResources.Add('splitter','PNG',[
+ #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#16#0#0#0#16#8#4#0#0#0#181#250'7'
+ +#234#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0' cHRM'#0#0'z&'#0#0#128#132#0
+ +#0#250#0#0#0#128#232#0#0'u0'#0#0#234'`'#0#0':'#152#0#0#23'p'#156#186'Q<'#0#0
+ +#0#2'bKGD'#0#255#135#143#204#191#0#0#0#158'IDAT('#207#133#145'A'#10#194'0'#16
+ +'E_'#146#174#4'!'#189#137#160#135#240#2#30'F'#196#149'G'#17#234#29#188#131
+ +#224'M*'#212#173#254'.'#146#198'&'#218':'#217#204#252#188#201#12'?F'#132'0'#0
+ +'\Z'#239#159#143']'#13#16'n,Y'#188#253#150#133#31'+'#5' Z'#196#12#0'U'#28'6'
+ +#9#216'B*'#0'C5'#13#236#5#138'/'#28#244#5#28#163#228#176#128'Iu'#2'N'#155'a'
+ +#136#0#165#26#197#3#172#225','#233#170#144#7'}'#188#209'mh'#249#228'?'#140
+ +#226#159'Q'#204#251'`'#1'W8'#155#27#213'5Ku'#153#146#127'7+'#28'/'#238'iYz'
+ +#241#246'-'#217#139'7'#147#144#0#0#0'%tEXtdate:create'#0'2014-03-13T04:26:36'
+ +'+02:00'#249'}l'#149#0#0#0'%tEXtdate:modify'#0'2013-01-08T13:07:58+02:00'#133
+ +#178'Km'#0#0#0#25'tEXtSoftware'#0'Adobe ImageReadyq'#201'e<'#0#0#0#0'IEND'
+ +#174'B`'#130
+]);
LazarusResources.Add('application','PNG',[
#137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#16#0#0#0#16#8#6#0#0#0#31#243#255'a'
+#0#0#0#25'tEXtSoftware'#0'Adobe ImageReadyq'#201'e<'#0#0#1#175'IDATx'#218#156
diff --git a/src/ce_interfaces.pas b/src/ce_interfaces.pas
index e5ac445c..fdd48bed 100644
--- a/src/ce_interfaces.pas
+++ b/src/ce_interfaces.pas
@@ -289,14 +289,16 @@ type
ICEMultiDocHandler = interface(ICESingleService)
// returns the count of opened document
function documentCount: Integer;
- // returns the index-th document
+ // returns the nth document
function getDocument(index: Integer): TCESynMemo;
// returns true if the document matching aFielanme is already opened.
function findDocument(aFilename: string): TCESynMemo;
// open or set the focus on the document matching aFilename
procedure openDocument(aFilename: string);
- // close the index-th document
+ // close the nth document
function closeDocument(index: Integer): boolean;
+ // close a particular document
+ function closeDocument(doc: TCESynMemo): boolean;
// conveniance property
property document[index: integer]: TCESynMemo read getDocument;
end;
diff --git a/src/ce_main.lfm b/src/ce_main.lfm
index 7faea280..2065616f 100644
--- a/src/ce_main.lfm
+++ b/src/ce_main.lfm
@@ -1,7 +1,7 @@
object CEMainForm: TCEMainForm
- Left = 480
+ Left = 485
Height = 49
- Top = 238
+ Top = 239
Width = 745
AllowDropFiles = True
Caption = 'Coedit'
diff --git a/src/ce_main.pas b/src/ce_main.pas
index 45d41540..d2fa54bc 100644
--- a/src/ce_main.pas
+++ b/src/ce_main.pas
@@ -1575,7 +1575,7 @@ begin
if fDoc = nil then exit;
if (fDoc.modified or(fDoc.fileName = fDoc.tempFilename))
and (dlgFileChangeClose(fDoc.fileName) = mrCancel) then exit;
- fDoc.Free;
+ getMultiDocHandler.closeDocument(fDoc);
end;
procedure TCEMainForm.actFileSaveAllExecute(Sender: TObject);
diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas
index d16d043f..2dcdb22a 100644
--- a/src/ce_synmemo.pas
+++ b/src/ce_synmemo.pas
@@ -8,7 +8,7 @@ uses
Classes, SysUtils, controls,lcltype, Forms, graphics, ExtCtrls, crc,
SynEdit, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText,
SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView,
- SynEditMarks, SynEditMarkup, SynEditTypes,
+ SynEditMarks, SynEditMarkup, SynEditTypes, Messages, LMessages,
ce_common, ce_observer, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs,
ce_sharedres;
@@ -103,6 +103,7 @@ type
fIsDSource: boolean;
fIsTxtFile: boolean;
fIsConfig: boolean;
+ fFocusForInput: boolean;
fIdentifier: string;
fTempFileName: string;
fMultiDocSubject: TCECustomSubject;
@@ -154,6 +155,8 @@ type
procedure removeBreakPoint(line: integer);
function findBreakPoint(line: integer): boolean;
protected
+ procedure DoEnter; override;
+ procedure DoExit; override;
procedure DoOnProcessCommand(var Command: TSynEditorCommand; var AChar: TUTF8Char;
Data: pointer); override;
procedure MouseLeave; override;
@@ -556,6 +559,25 @@ begin
subjDocFocused(TCEMultiDocSubject(fMultiDocSubject), self);
end;
+procedure TCESynMemo.DoEnter;
+begin
+ inherited;
+ checkFileDate;
+ if not fFocusForInput then
+ subjDocFocused(TCEMultiDocSubject(fMultiDocSubject), self);
+ fFocusForInput := true;
+end;
+
+procedure TCESynMemo.DoExit;
+begin
+ inherited;
+ fFocusForInput := false;
+ fDDocWin.Hide;
+ fCallTipWin.Hide;
+ if fCompletion.IsActive then
+ fCompletion.Deactivate;
+end;
+
procedure TCESynMemo.SetVisible(Value: Boolean);
begin
inherited;
@@ -569,7 +591,7 @@ begin
else begin
fDDocWin.Hide;
fCallTipWin.Hide;
- if fCompletion.IsActive then
+ if fCompletion.IsActive then
fCompletion.Deactivate;
end;
end;
@@ -1091,6 +1113,7 @@ end;
procedure TCESynMemo.MouseLeave;
begin
+ inherited;
fDDocWin.Hide;
fCallTipWin.Hide;
end;