diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi
index efd69c2c..b85c391c 100644
--- a/lazproj/coedit.lpi
+++ b/lazproj/coedit.lpi
@@ -137,7 +137,7 @@
-
+
@@ -365,6 +365,10 @@
+
+
+
+
diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr
index 3a5d7c55..700f4047 100644
--- a/lazproj/coedit.lpr
+++ b/lazproj/coedit.lpr
@@ -10,7 +10,7 @@ uses
ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent,
ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions,
ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs,
-ce_dubprojeditor, ce_gdb;
+ce_dubprojeditor, ce_gdb, ce_controls;
{$R *.res}
diff --git a/src/ce_controls.pas b/src/ce_controls.pas
new file mode 100644
index 00000000..7674e229
--- /dev/null
+++ b/src/ce_controls.pas
@@ -0,0 +1,338 @@
+unit ce_controls;
+
+{$I ce_defines.inc}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
+ ExtCtrls, buttons;
+
+type
+ TCEPageControlButton = (pbClose, pbMoveLeft, pbMoveRight, pbAdd);
+ TCEPageControlButtons = set of TCEPageControlButton;
+
+const
+ CEPageControlDefaultButtons = [pbClose, pbMoveLeft, pbMoveRight, pbAdd];
+
+type
+
+ TCEPage = class(TCustomControl)
+ protected
+ procedure RealSetText(const Value: TCaption); override;
+ end;
+
+ TCEPageControl = class(TWinControl)
+ private
+ fHeader: TWinControl;
+ fTabs: TTabControl;
+ fCloseBtn: TSpeedButton;
+ fMoveLeftBtn: TSpeedButton;
+ fMoveRightBtn: TSpeedButton;
+ fAddBtn: TSpeedButton;
+ fContent: TPanel;
+ fPages: TFPList;
+ fPageIndex: integer;
+ fButtons: TCEPageControlButtons;
+ fOnChanged: TNotifyEvent;
+
+ procedure btnCloseClick(sender: TObject);
+ procedure btnMoveLeftClick(sender: TObject);
+ procedure btnMoveRightClick(sender: TObject);
+ procedure btnAddClick(sender: TObject);
+
+ procedure tabsChanged(sender: TObject);
+ procedure hidePage(index: integer);
+ procedure showPage(index: integer);
+ procedure setPageIndex(index: integer);
+ procedure setButtons(value: TCEPageControlButtons);
+ procedure setCurrentPage(value: TCEPage);
+ function getCurrentPage: TCEPage;
+ function getPageCount: integer;
+ function getPage(index: integer): TCEPage;
+
+ procedure changedNotify;
+
+ public
+ constructor Create(aowner: TComponent); override;
+ destructor Destroy; override;
+
+ function addPage: TCEPage;
+ procedure deletePage(index: integer);
+ function getPageIndex(page: TCEPage): integer;
+ procedure movePageRight;
+ procedure movePageLeft;
+
+ property currentPage: TCEPage read getCurrentPage write setCurrentPage;
+ property pageIndex: integer read fPageIndex write setPageIndex;
+ property pageCount: integer read getPageCount;
+ property pages[index: integer]: TCEPage read getPage; default;
+
+ property buttons: TCEPageControlButtons read fButtons write setButtons;
+ property closeButton: TSpeedButton read fCloseBtn;
+ property moveLeftButton: TSpeedButton read fMoveLeftBtn;
+ property moveRightButton: TSpeedButton read fMoveRightBtn;
+ property addButton: TSpeedButton read fAddBtn;
+
+ property onChanged: TNotifyEvent read fOnChanged write fOnChanged;
+ end;
+
+implementation
+
+
+procedure TCEPage.RealSetText(const Value: TCaption);
+var
+ i: integer;
+ ctrl: TCEPageControl;
+begin
+ inherited;
+ ctrl := TCEPageControl(Owner);
+ i := ctrl.getPageIndex(self);
+ if i <> -1 then ctrl.fTabs.Tabs.Strings[i] := caption;
+end;
+
+constructor TCEPageControl.Create(aowner: TComponent);
+begin
+ inherited;
+
+ fHeader := TWinControl.Create(self);
+ fHeader.Parent:= self;
+ fHeader.Align := alTop;
+ fHeader.Height:= 32;
+
+ fTabs := TTabControl.Create(self);
+ fTabs.Parent:= fHeader;
+ fTabs.Align := alClient;
+ fTabs.Options:=[];
+ fTabs.OnChange:=@tabsChanged;
+
+ fMoveLeftBtn:= TSpeedButton.Create(self);
+ fMoveLeftBtn.Parent := fHeader;
+ fMoveLeftBtn.Align:= alRight;
+ fMoveLeftBtn.Width:= 28;
+ fMoveLeftBtn.BorderSpacing.Around:= 2;
+ fMoveLeftBtn.ShowCaption:=false;
+ fMoveLeftBtn.OnClick:=@btnMoveLeftClick;
+ fMoveLeftBtn.Hint:='move page to the left';
+
+ fMoveRightBtn:= TSpeedButton.Create(self);
+ fMoveRightBtn.Parent := fHeader;
+ fMoveRightBtn.Align:= alRight;
+ fMoveRightBtn.Width:= 28;
+ fMoveRightBtn.BorderSpacing.Around:= 2;
+ fMoveRightBtn.ShowCaption:=false;
+ fMoveRightBtn.OnClick:=@btnMoveRightClick;
+ fMoveRightBtn.Hint:='move page to the right';
+
+ fAddBtn:= TSpeedButton.Create(self);
+ fAddBtn.Parent := fHeader;
+ fAddBtn.Align:= alRight;
+ fAddBtn.Width:= 28;
+ fAddBtn.BorderSpacing.Around:= 2;
+ fAddBtn.ShowCaption:=false;
+ fAddBtn.OnClick:=@btnAddClick;
+
+ fCloseBtn := TSpeedButton.Create(self);
+ fCloseBtn.Parent := fHeader;
+ fCloseBtn.Align:= alRight;
+ fCloseBtn.Width:= 28;
+ fCloseBtn.BorderSpacing.Around:= 2;
+ fCloseBtn.ShowCaption:=false;
+ fCloseBtn.OnClick:=@btnCloseClick;
+ fCloseBtn.Hint:='close page';
+
+ fContent := TPanel.Create(self);
+ fContent.Parent := self;
+ fContent.Align := alClient;
+ fContent.BevelInner:= bvNone;
+ fContent.BevelOuter:= bvNone;
+ fContent.BorderStyle:=bsNone;
+ fContent.BorderSpacing.Around:=2;
+
+ fPages := TFPList.Create;
+ fPageIndex := -1;
+
+ fButtons:= CEPageControlDefaultButtons;
+end;
+
+destructor TCEPageControl.Destroy;
+begin
+ while fPages.Count > 0 do
+ deletePage(fPages.Count-1);
+ fPages.Free;
+ inherited;
+end;
+
+procedure TCEPageControl.changedNotify;
+begin
+ if assigned(fOnChanged) then
+ fOnChanged(self);
+end;
+
+procedure TCEPageControl.tabsChanged(sender: TObject);
+begin
+ setPageIndex(fTabs.TabIndex);
+end;
+
+procedure TCEPageControl.hidePage(index: integer);
+var
+ pge: TCEPage;
+ ctl: TControl;
+begin
+ if (index < 0) or (index > fPages.Count-1) then
+ exit;
+
+ pge := TCEPage(fPages.Items[index]);
+ pge.Visible:=false;
+ for ctl in pge.GetEnumeratorControls do
+ ctl.Visible:=false;
+end;
+
+procedure TCEPageControl.showPage(index: integer);
+var
+ pge: TCEPage;
+ ctl: TControl;
+begin
+ if (index < 0) or (index > fPages.Count-1) then
+ exit;
+
+ pge := TCEPage(fPages.Items[index]);
+ pge.Visible:=true;
+ pge.Repaint;
+ for ctl in pge.GetEnumeratorControls do
+ ctl.Visible:=true;
+end;
+
+procedure TCEPageControl.setPageIndex(index: integer);
+begin
+ if (index > fPages.Count-1) then
+ index := fPages.Count-1;
+ if (index < 0) then
+ exit;
+
+ hidePage(fPageIndex);
+ fPageIndex := index;
+ showPage(fPageIndex);
+ fTabs.TabIndex:= fPageIndex;
+
+ changedNotify;
+end;
+
+function TCEPageControl.addPage: TCEPage;
+var
+ pge: TCEPage;
+begin
+ pge := TCEPage.Create(self);
+ pge.Parent := fContent;
+ pge.Align:= alClient;
+
+ fPages.Add(pge);
+ fTabs.Tabs.Add(format('', [fPages.Count]));
+ setPageIndex(fTabs.Tabs.Count-1);
+
+ result := pge;
+end;
+
+procedure TCEPageControl.deletePage(index: integer);
+begin
+ if (index > fPages.Count-1) or (index < 0) then
+ exit;
+
+ TCEPage(fPages.Items[index]).Free;
+ fPages.Delete(index);
+ fTabs.Tabs.Delete(index);
+
+ if fPageIndex >= fPages.Count then
+ fPageIndex -= 1;
+ if fPages.Count = 0 then exit;
+
+ showPage(fPageIndex);
+ changedNotify;
+end;
+
+function TCEPageControl.getPageIndex(page: TCEPage): integer;
+begin
+ exit(fPages.IndexOf(page));
+end;
+
+function TCEPageControl.getCurrentPage: TCEPage;
+begin
+ if (fPageIndex < 0) or (fPageIndex > fPages.Count-1) then
+ exit(nil)
+ else
+ exit(TCEPage(fPages.Items[fPageIndex]));
+end;
+
+procedure TCEPageControl.setCurrentPage(value: TCEPage);
+begin
+ setPageIndex(getPageIndex(value));
+end;
+
+function TCEPageControl.getPageCount: integer;
+begin
+ exit(fPages.Count);
+end;
+
+function TCEPageControl.getPage(index: integer): TCEPage;
+begin
+ exit(TCEPage(fPages.Items[index]));
+end;
+
+procedure TCEPageControl.movePageRight;
+begin
+ if fPageIndex = fPages.Count-1 then
+ exit;
+
+ fPages.Exchange(fPageIndex, fPageIndex + 1);
+ fTabs.Tabs.Exchange(fPageIndex, fPageIndex + 1);
+ setPageIndex(fPageIndex+1);
+end;
+
+procedure TCEPageControl.movePageLeft;
+begin
+ if fPageIndex <= 0 then
+ exit;
+
+ fPages.Exchange(fPageIndex, fPageIndex - 1);
+ fTabs.Tabs.Exchange(fPageIndex, fPageIndex - 1);
+ setPageIndex(fPageIndex-1);
+end;
+
+
+
+procedure TCEPageControl.btnCloseClick(sender: TObject);
+begin
+ deletePage(fPageIndex);
+end;
+
+procedure TCEPageControl.btnMoveLeftClick(sender: TObject);
+begin
+ movePageLeft;
+end;
+
+procedure TCEPageControl.btnMoveRightClick(sender: TObject);
+begin
+ movePageRight;
+end;
+
+procedure TCEPageControl.btnAddClick(sender: TObject);
+begin
+ addPage;
+end;
+
+procedure TCEPageControl.setButtons(value: TCEPageControlButtons);
+begin
+ fButtons:= value;
+ fHeader.DisableAlign;
+
+ fCloseBtn.Visible:= pbClose in fButtons;
+ fMoveLeftBtn.Visible:= pbMoveLeft in fButtons;
+ fCloseBtn.Visible:= pbMoveRight in fButtons;
+ fAddBtn.Visible:= pbAdd in fButtons;
+
+ fHeader.EnableAlign;
+ fHeader.ReAlign;
+end;
+
+end.
+
diff --git a/src/ce_editor.lfm b/src/ce_editor.lfm
index 2d98ace8..80303710 100644
--- a/src/ce_editor.lfm
+++ b/src/ce_editor.lfm
@@ -14,28 +14,14 @@ inherited CEEditorWidget: TCEEditorWidget
inherited Content: TPanel
Height = 406
Width = 465
- BevelOuter = bvRaised
ClientHeight = 406
ClientWidth = 465
- object PageControl: TExtendedNotebook[0]
- Left = 3
- Height = 380
- Top = 3
- Width = 459
- Align = alClient
- BorderSpacing.Around = 2
- TabOrder = 0
- OnChange = PageControlChange
- OnChanging = PageControlChanging
- Options = [nboShowCloseButtons, nboShowAddTabButton]
- TabDragMode = dmAutomatic
- TabDragAcceptMode = dmAutomatic
- end
- object editorStatus: TStatusBar[1]
- Left = 3
+ object editorStatus: TStatusBar[0]
+ Left = 2
Height = 18
- Top = 385
- Width = 459
+ Top = 386
+ Width = 461
+ AutoSize = False
BorderSpacing.Around = 2
Panels = <
item
diff --git a/src/ce_editor.pas b/src/ce_editor.pas
index eecc849c..03519c78 100644
--- a/src/ce_editor.pas
+++ b/src/ce_editor.pas
@@ -9,18 +9,10 @@ uses
Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus,
SynMacroRecorder, SynPluginSyncroEdit, SynEdit, SynHighlighterMulti, ce_dialogs,
ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer,
- ce_sharedres;
+ ce_sharedres, ce_controls;
type
- // this descendant propagates the Visible property to the children.
- // this fix the bug described in commit c1a0ed2799390d788b1d1e435eb8dc1ed3369ce7
- TCEEditorPage = class(TTabSheet)
- protected
- procedure SetVisible(Value: Boolean); override;
- end;
-
-
//TODO-crefact: moves the macro recorded to TCESynMemo, + add visual feedback + declare shortcuts ecXXXX
{ TCEEditorWidget }
@@ -36,7 +28,6 @@ type
mnuedRedo: TMenuItem;
MenuItem7: TMenuItem;
mnuedJum2Decl: TMenuItem;
- PageControl: TExtendedNotebook;
macRecorder: TSynMacroRecorder;
editorStatus: TStatusBar;
mnuEditor: TPopupMenu;
@@ -55,15 +46,14 @@ type
procedure updateDelayed; override;
procedure updateImperative; override;
private
+ pageControl: TCEPageControl;
fKeyChanged: boolean;
fDoc: TCESynMemo;
fTokList: TLexTokenList;
fErrList: TLexErrorList;
fModStart: boolean;
fLastCommand: TSynEditorCommand;
- {$IFDEF LINUX}
procedure pageCloseBtnClick(Sender: TObject);
- {$ENDIF}
procedure lexFindToken(const aToken: PLexToken; out doStop: boolean);
procedure memoKeyPress(Sender: TObject; var Key: char);
procedure memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -95,25 +85,19 @@ type
implementation
{$R *.lfm}
-procedure TCEEditorPage.SetVisible(Value: Boolean);
-var
- i: integer;
-begin
- inherited;
- for i := 0 to ControlCount-1 do
- Controls[i].Visible:= Value;
-end;
-
{$REGION Standard Comp/Obj------------------------------------------------------}
constructor TCEEditorWidget.create(aOwner: TComponent);
begin
inherited;
//
+ pageControl := TCEPageControl.Create(self);
+ pageControl.Parent := Content;
+ pageControl.align := alClient;
+ pageControl.onChanged:= @PageControlChange;
+ pageControl.closeButton.OnClick:=@pageCloseBtnClick;
+
fTokList := TLexTokenList.Create;
fErrList := TLexErrorList.Create;
- {$IFDEF LINUX}
- PageControl.OnCloseTabClicked := @pageCloseBtnClick;
- {$ENDIF}
//
AssignPng(mnuedCopy.Bitmap, 'copy');
AssignPng(mnuedCut.Bitmap, 'cut');
@@ -133,9 +117,9 @@ var
begin
EntitiesConnector.removeObserver(self);
for i := PageControl.PageCount-1 downto 0 do
- if PageControl.Page[i].ControlCount > 0 then
- if (PageControl.Page[i].Controls[0] is TCESynMemo) then
- PageControl.Page[i].Controls[0].Free;
+ if PageControl.Pages[i].ControlCount > 0 then
+ if (PageControl.Pages[i].Controls[0] is TCESynMemo) then
+ PageControl.Pages[i].Controls[0].Free;
fTokList.Free;
fErrList.Free;
inherited;
@@ -150,13 +134,12 @@ end;
{$REGION ICEMultiDocObserver ---------------------------------------------------}
procedure TCEEditorWidget.docNew(aDoc: TCESynMemo);
var
- sheet: TCEEditorPage;
+ pge: TCEPage;
begin
- sheet := TCEEditorPage.Create(self);
- sheet.PageControl := PageControl;
+ pge := pageControl.addPage;
//
aDoc.Align := alClient;
- aDoc.Parent := sheet;
+ aDoc.Parent := pge;
//
aDoc.OnKeyDown := @memoKeyDown;
aDoc.OnKeyUp := @memoKeyUp;
@@ -167,24 +150,20 @@ begin
aDoc.OnCommandProcessed:= @memoCmdProcessed;
//
fDoc := aDoc;
- pageControl.ActivePage := sheet;
focusedEditorChanged;
beginDelayedUpdate;
updateImperative;
end;
procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo);
-var
- sheet: TWinControl;
begin
if aDoc = nil then
exit;
- sheet := aDoc.Parent;
aDoc.Parent := nil;
if aDoc = fDoc then
fDoc := nil;
- if sheet <> nil then sheet.Free;
updateImperative;
+ pageControl.deletePage(pageControl.pageIndex);
end;
procedure TCEEditorWidget.docFocused(aDoc: TCESynMemo);
@@ -240,7 +219,7 @@ var
begin
doc := findDocument(aFilename);
if doc <> nil then begin
- PageControl.ActivePage := TTabSheet(doc.Parent);
+ PageControl.currentPage := TCEPage(doc.Parent);
exit;
end;
doc := TCESynMemo.Create(nil);
@@ -261,13 +240,10 @@ end;
{$ENDREGION}
{$REGION PageControl/Editor things ---------------------------------------------}
-{$IFDEF LINUX}
procedure TCEEditorWidget.pageCloseBtnClick(Sender: TObject);
begin
- PageControl.PageIndex := TTabSheet(sender).PageIndex;
closeDocument(PageControl.PageIndex);
end;
-{$ENDIF}
procedure TCEEditorWidget.focusedEditorChanged;
begin
@@ -276,7 +252,7 @@ begin
//
macRecorder.Editor:= fDoc;
fDoc.PopupMenu := mnuEditor;
- if (pageControl.ActivePage.Caption = '') then
+ if (pageControl.currentPage.Caption = '') then
begin
fKeyChanged := true;
beginDelayedUpdate;
@@ -389,8 +365,8 @@ begin
editorStatus.Panels[0].Text := format('%d : %d | %d', [fDoc.CaretY, fDoc.CaretX, fDoc.SelEnd - fDoc.SelStart]);
editorStatus.Panels[1].Text := modstr[fDoc.modified];
editorStatus.Panels[2].Text := fDoc.fileName;
- if Visible and (pageControl.ActivePage <> nil) and ((pageControl.ActivePage.Caption = '') or
- (pageControl.ActivePage.Caption = '')) then
+ if Visible and (pageControl.currentPage <> nil) and ((pageControl.currentPage.Caption = '') or
+ (pageControl.currentPage.Caption = '')) then
begin
if fDoc.isDSource then
begin
@@ -400,7 +376,7 @@ begin
fErrList.Clear;
end;
if md = '' then md := extractFileName(fDoc.fileName);
- pageControl.ActivePage.Caption := md;
+ pageControl.currentPage.Caption := md;
end;
end;
end;
@@ -437,7 +413,7 @@ begin
fErrList.Clear;
end;
if md = '' then md := extractFileName(fDoc.fileName);
- pageControl.ActivePage.Caption := md;
+ pageControl.currentPage.Caption := md;
// note: not true anymore vecause cesyms use send the doc in stdin
// when a widget saves a temp file & syncro mode is on: