test new page control

This commit is contained in:
Basile Burg 2015-12-07 10:05:04 +01:00
parent 8ad5eaa025
commit b45d01c308
5 changed files with 370 additions and 66 deletions

View File

@ -137,7 +137,7 @@
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item6> </Item6>
</RequiredPackages> </RequiredPackages>
<Units Count="43"> <Units Count="44">
<Unit0> <Unit0>
<Filename Value="coedit.lpr"/> <Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -365,6 +365,10 @@
<HasResources Value="True"/> <HasResources Value="True"/>
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
</Unit42> </Unit42>
<Unit43>
<Filename Value="..\src\ce_controls.pas"/>
<IsPartOfProject Value="True"/>
</Unit43>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -10,7 +10,7 @@ uses
ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent, ce_observer, ce_libman, ce_tools, ce_dcd, ce_main, ce_writableComponent,
ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions, ce_symstring, ce_staticmacro, ce_inspectors, ce_editoroptions, ce_dockoptions,
ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs, ce_shortcutseditor, ce_mru, ce_processes, ce_dubproject, ce_dialogs,
ce_dubprojeditor, ce_gdb; ce_dubprojeditor, ce_gdb, ce_controls;
{$R *.res} {$R *.res}

338
src/ce_controls.pas Normal file
View File

@ -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.

View File

@ -14,28 +14,14 @@ inherited CEEditorWidget: TCEEditorWidget
inherited Content: TPanel inherited Content: TPanel
Height = 406 Height = 406
Width = 465 Width = 465
BevelOuter = bvRaised
ClientHeight = 406 ClientHeight = 406
ClientWidth = 465 ClientWidth = 465
object PageControl: TExtendedNotebook[0] object editorStatus: TStatusBar[0]
Left = 3 Left = 2
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
Height = 18 Height = 18
Top = 385 Top = 386
Width = 459 Width = 461
AutoSize = False
BorderSpacing.Around = 2 BorderSpacing.Around = 2
Panels = < Panels = <
item item

View File

@ -9,18 +9,10 @@ uses
Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus, Graphics, SynEditKeyCmds, ComCtrls, SynEditHighlighter, ExtCtrls, Menus,
SynMacroRecorder, SynPluginSyncroEdit, SynEdit, SynHighlighterMulti, ce_dialogs, SynMacroRecorder, SynPluginSyncroEdit, SynEdit, SynHighlighterMulti, ce_dialogs,
ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer, ce_widget, ce_interfaces, ce_synmemo, ce_dlang, ce_common, ce_dcd, ce_observer,
ce_sharedres; ce_sharedres, ce_controls;
type 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 //TODO-crefact: moves the macro recorded to TCESynMemo, + add visual feedback + declare shortcuts ecXXXX
{ TCEEditorWidget } { TCEEditorWidget }
@ -36,7 +28,6 @@ type
mnuedRedo: TMenuItem; mnuedRedo: TMenuItem;
MenuItem7: TMenuItem; MenuItem7: TMenuItem;
mnuedJum2Decl: TMenuItem; mnuedJum2Decl: TMenuItem;
PageControl: TExtendedNotebook;
macRecorder: TSynMacroRecorder; macRecorder: TSynMacroRecorder;
editorStatus: TStatusBar; editorStatus: TStatusBar;
mnuEditor: TPopupMenu; mnuEditor: TPopupMenu;
@ -55,15 +46,14 @@ type
procedure updateDelayed; override; procedure updateDelayed; override;
procedure updateImperative; override; procedure updateImperative; override;
private private
pageControl: TCEPageControl;
fKeyChanged: boolean; fKeyChanged: boolean;
fDoc: TCESynMemo; fDoc: TCESynMemo;
fTokList: TLexTokenList; fTokList: TLexTokenList;
fErrList: TLexErrorList; fErrList: TLexErrorList;
fModStart: boolean; fModStart: boolean;
fLastCommand: TSynEditorCommand; fLastCommand: TSynEditorCommand;
{$IFDEF LINUX}
procedure pageCloseBtnClick(Sender: TObject); procedure pageCloseBtnClick(Sender: TObject);
{$ENDIF}
procedure lexFindToken(const aToken: PLexToken; out doStop: boolean); procedure lexFindToken(const aToken: PLexToken; out doStop: boolean);
procedure memoKeyPress(Sender: TObject; var Key: char); procedure memoKeyPress(Sender: TObject; var Key: char);
procedure memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure memoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@ -95,25 +85,19 @@ type
implementation implementation
{$R *.lfm} {$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------------------------------------------------------} {$REGION Standard Comp/Obj------------------------------------------------------}
constructor TCEEditorWidget.create(aOwner: TComponent); constructor TCEEditorWidget.create(aOwner: TComponent);
begin begin
inherited; inherited;
// //
pageControl := TCEPageControl.Create(self);
pageControl.Parent := Content;
pageControl.align := alClient;
pageControl.onChanged:= @PageControlChange;
pageControl.closeButton.OnClick:=@pageCloseBtnClick;
fTokList := TLexTokenList.Create; fTokList := TLexTokenList.Create;
fErrList := TLexErrorList.Create; fErrList := TLexErrorList.Create;
{$IFDEF LINUX}
PageControl.OnCloseTabClicked := @pageCloseBtnClick;
{$ENDIF}
// //
AssignPng(mnuedCopy.Bitmap, 'copy'); AssignPng(mnuedCopy.Bitmap, 'copy');
AssignPng(mnuedCut.Bitmap, 'cut'); AssignPng(mnuedCut.Bitmap, 'cut');
@ -133,9 +117,9 @@ var
begin begin
EntitiesConnector.removeObserver(self); EntitiesConnector.removeObserver(self);
for i := PageControl.PageCount-1 downto 0 do for i := PageControl.PageCount-1 downto 0 do
if PageControl.Page[i].ControlCount > 0 then if PageControl.Pages[i].ControlCount > 0 then
if (PageControl.Page[i].Controls[0] is TCESynMemo) then if (PageControl.Pages[i].Controls[0] is TCESynMemo) then
PageControl.Page[i].Controls[0].Free; PageControl.Pages[i].Controls[0].Free;
fTokList.Free; fTokList.Free;
fErrList.Free; fErrList.Free;
inherited; inherited;
@ -150,13 +134,12 @@ end;
{$REGION ICEMultiDocObserver ---------------------------------------------------} {$REGION ICEMultiDocObserver ---------------------------------------------------}
procedure TCEEditorWidget.docNew(aDoc: TCESynMemo); procedure TCEEditorWidget.docNew(aDoc: TCESynMemo);
var var
sheet: TCEEditorPage; pge: TCEPage;
begin begin
sheet := TCEEditorPage.Create(self); pge := pageControl.addPage;
sheet.PageControl := PageControl;
// //
aDoc.Align := alClient; aDoc.Align := alClient;
aDoc.Parent := sheet; aDoc.Parent := pge;
// //
aDoc.OnKeyDown := @memoKeyDown; aDoc.OnKeyDown := @memoKeyDown;
aDoc.OnKeyUp := @memoKeyUp; aDoc.OnKeyUp := @memoKeyUp;
@ -167,24 +150,20 @@ begin
aDoc.OnCommandProcessed:= @memoCmdProcessed; aDoc.OnCommandProcessed:= @memoCmdProcessed;
// //
fDoc := aDoc; fDoc := aDoc;
pageControl.ActivePage := sheet;
focusedEditorChanged; focusedEditorChanged;
beginDelayedUpdate; beginDelayedUpdate;
updateImperative; updateImperative;
end; end;
procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo); procedure TCEEditorWidget.docClosing(aDoc: TCESynMemo);
var
sheet: TWinControl;
begin begin
if aDoc = nil then if aDoc = nil then
exit; exit;
sheet := aDoc.Parent;
aDoc.Parent := nil; aDoc.Parent := nil;
if aDoc = fDoc then if aDoc = fDoc then
fDoc := nil; fDoc := nil;
if sheet <> nil then sheet.Free;
updateImperative; updateImperative;
pageControl.deletePage(pageControl.pageIndex);
end; end;
procedure TCEEditorWidget.docFocused(aDoc: TCESynMemo); procedure TCEEditorWidget.docFocused(aDoc: TCESynMemo);
@ -240,7 +219,7 @@ var
begin begin
doc := findDocument(aFilename); doc := findDocument(aFilename);
if doc <> nil then begin if doc <> nil then begin
PageControl.ActivePage := TTabSheet(doc.Parent); PageControl.currentPage := TCEPage(doc.Parent);
exit; exit;
end; end;
doc := TCESynMemo.Create(nil); doc := TCESynMemo.Create(nil);
@ -261,13 +240,10 @@ end;
{$ENDREGION} {$ENDREGION}
{$REGION PageControl/Editor things ---------------------------------------------} {$REGION PageControl/Editor things ---------------------------------------------}
{$IFDEF LINUX}
procedure TCEEditorWidget.pageCloseBtnClick(Sender: TObject); procedure TCEEditorWidget.pageCloseBtnClick(Sender: TObject);
begin begin
PageControl.PageIndex := TTabSheet(sender).PageIndex;
closeDocument(PageControl.PageIndex); closeDocument(PageControl.PageIndex);
end; end;
{$ENDIF}
procedure TCEEditorWidget.focusedEditorChanged; procedure TCEEditorWidget.focusedEditorChanged;
begin begin
@ -276,7 +252,7 @@ begin
// //
macRecorder.Editor:= fDoc; macRecorder.Editor:= fDoc;
fDoc.PopupMenu := mnuEditor; fDoc.PopupMenu := mnuEditor;
if (pageControl.ActivePage.Caption = '') then if (pageControl.currentPage.Caption = '') then
begin begin
fKeyChanged := true; fKeyChanged := true;
beginDelayedUpdate; beginDelayedUpdate;
@ -389,8 +365,8 @@ begin
editorStatus.Panels[0].Text := format('%d : %d | %d', [fDoc.CaretY, fDoc.CaretX, fDoc.SelEnd - fDoc.SelStart]); 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[1].Text := modstr[fDoc.modified];
editorStatus.Panels[2].Text := fDoc.fileName; editorStatus.Panels[2].Text := fDoc.fileName;
if Visible and (pageControl.ActivePage <> nil) and ((pageControl.ActivePage.Caption = '') or if Visible and (pageControl.currentPage <> nil) and ((pageControl.currentPage.Caption = '') or
(pageControl.ActivePage.Caption = '<new document>')) then (pageControl.currentPage.Caption = '<new document>')) then
begin begin
if fDoc.isDSource then if fDoc.isDSource then
begin begin
@ -400,7 +376,7 @@ begin
fErrList.Clear; fErrList.Clear;
end; end;
if md = '' then md := extractFileName(fDoc.fileName); if md = '' then md := extractFileName(fDoc.fileName);
pageControl.ActivePage.Caption := md; pageControl.currentPage.Caption := md;
end; end;
end; end;
end; end;
@ -437,7 +413,7 @@ begin
fErrList.Clear; fErrList.Clear;
end; end;
if md = '' then md := extractFileName(fDoc.fileName); 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 // note: not true anymore vecause cesyms use send the doc in stdin
// when a widget saves a temp file & syncro mode is on: // when a widget saves a temp file & syncro mode is on: