Issue #136: Replace the standard memo on the grid cell text editor with a TSynMemo. And provide all supported highlighters in a drop-down, remembering the previously selected highlighter.

This commit is contained in:
Ansgar Becker
2021-03-14 20:46:30 +01:00
parent 5b86687f2c
commit 9dcd446a47
4 changed files with 103 additions and 18 deletions

View File

@ -149,7 +149,7 @@ type
asMainWinHeight, asMainWinOnMonitor, asCoolBandIndex, asCoolBandBreak, asCoolBandWidth, asToolbarShowCaptions, asQuerymemoheight, asDbtreewidth, asMainWinHeight, asMainWinOnMonitor, asCoolBandIndex, asCoolBandBreak, asCoolBandWidth, asToolbarShowCaptions, asQuerymemoheight, asDbtreewidth,
asDataPreviewHeight, asDataPreviewEnabled, asLogHeight, asQueryhelperswidth, asStopOnErrorsInBatchMode, asDataPreviewHeight, asDataPreviewEnabled, asLogHeight, asQueryhelperswidth, asStopOnErrorsInBatchMode,
asWrapLongLines, asCodeFolding, asDisplayBLOBsAsText, asSingleQueries, asMemoEditorWidth, asMemoEditorHeight, asMemoEditorMaximized, asWrapLongLines, asCodeFolding, asDisplayBLOBsAsText, asSingleQueries, asMemoEditorWidth, asMemoEditorHeight, asMemoEditorMaximized,
asMemoEditorWrap, asDelimiter, asSQLHelpWindowLeft, asSQLHelpWindowTop, asSQLHelpWindowWidth, asMemoEditorWrap, asMemoEditorHighlighter, asDelimiter, asSQLHelpWindowLeft, asSQLHelpWindowTop, asSQLHelpWindowWidth,
asSQLHelpWindowHeight, asSQLHelpPnlLeftWidth, asSQLHelpPnlRightTopHeight, asHost, asSQLHelpWindowHeight, asSQLHelpPnlLeftWidth, asSQLHelpPnlRightTopHeight, asHost,
asUser, asPassword, asCleartextPluginEnabled, asWindowsAuth, asLoginPrompt, asPort, asLibrary, asAllProviders, asUser, asPassword, asCleartextPluginEnabled, asWindowsAuth, asLoginPrompt, asPort, asLibrary, asAllProviders,
asPlinkExecutable, asSSHtunnelHost, asSSHtunnelHostPort, asSSHtunnelPort, asSSHtunnelUser, asPlinkExecutable, asSSHtunnelHost, asSSHtunnelHostPort, asSSHtunnelPort, asSSHtunnelUser,
@ -3451,6 +3451,7 @@ begin
InitSetting(asMemoEditorHeight, 'MemoEditorHeight', 100); InitSetting(asMemoEditorHeight, 'MemoEditorHeight', 100);
InitSetting(asMemoEditorMaximized, 'MemoEditorMaximized', 0, False); InitSetting(asMemoEditorMaximized, 'MemoEditorMaximized', 0, False);
InitSetting(asMemoEditorWrap, 'MemoEditorWrap', 0, False); InitSetting(asMemoEditorWrap, 'MemoEditorWrap', 0, False);
InitSetting(asMemoEditorHighlighter, 'MemoEditorHighlighter_%s', 0, False, 'General', True);
InitSetting(asDelimiter, 'Delimiter', 0, False, ';'); InitSetting(asDelimiter, 'Delimiter', 0, False, ';');
InitSetting(asSQLHelpWindowLeft, 'SQLHelp_WindowLeft', 0); InitSetting(asSQLHelpWindowLeft, 'SQLHelp_WindowLeft', 0);
InitSetting(asSQLHelpWindowTop, 'SQLHelp_WindowTop', 0); InitSetting(asSQLHelpWindowTop, 'SQLHelp_WindowTop', 0);

View File

@ -1203,11 +1203,12 @@ procedure TInplaceEditorLink.ButtonClick(Sender: TObject);
begin begin
if not FButton.Visible then Exit; // Button was invisible, but hotkey was pressed if not FButton.Visible then Exit; // Button was invisible, but hotkey was pressed
FTextEditor := TfrmTextEditor.Create(FTree); FTextEditor := TfrmTextEditor.Create(FTree);
FTextEditor.SetFont(FEdit.Font); FTextEditor.SetFont(MainForm.SynMemoQuery.Font);
FTextEditor.SetText(FEdit.Text); FTextEditor.SetText(FEdit.Text);
FTextEditor.SetTitleText(TitleText); FTextEditor.SetTitleText(TitleText);
FTextEditor.Modified := FEdit.Modified; FTextEditor.Modified := FEdit.Modified;
FTextEditor.SetMaxLength(Self.FMaxLength); FTextEditor.SetMaxLength(Self.FMaxLength);
FTextEditor.TableColumn := FTableColumn;
FTextEditor.memoText.ReadOnly := not FAllowEdit; FTextEditor.memoText.ReadOnly := not FAllowEdit;
FTextEditor.ShowModal; FTextEditor.ShowModal;
end; end;

View File

@ -3,7 +3,7 @@ object frmTextEditor: TfrmTextEditor
Top = 0 Top = 0
Caption = 'Text editor' Caption = 'Text editor'
ClientHeight = 104 ClientHeight = 104
ClientWidth = 332 ClientWidth = 571
Color = clBtnFace Color = clBtnFace
Constraints.MinHeight = 100 Constraints.MinHeight = 100
Constraints.MinWidth = 130 Constraints.MinWidth = 130
@ -24,7 +24,7 @@ object frmTextEditor: TfrmTextEditor
AlignWithMargins = True AlignWithMargins = True
Left = 0 Left = 0
Top = 82 Top = 82
Width = 322 Width = 561
Height = 22 Height = 22
Margins.Left = 0 Margins.Left = 0
Margins.Top = 0 Margins.Top = 0
@ -37,7 +37,7 @@ object frmTextEditor: TfrmTextEditor
TabOrder = 0 TabOrder = 0
object lblTextLength: TLabel object lblTextLength: TLabel
AlignWithMargins = True AlignWithMargins = True
Left = 210 Left = 355
Top = 3 Top = 3
Width = 65 Width = 65
Height = 16 Height = 16
@ -130,6 +130,17 @@ object frmTextEditor: TfrmTextEditor
Action = actSearchReplace Action = actSearchReplace
end end
end end
object comboHighlighter: TComboBox
Left = 207
Top = 0
Width = 145
Height = 21
Align = alLeft
Style = csDropDownList
Sorted = True
TabOrder = 1
OnSelect = comboHighlighterSelect
end
end end
object popupLinebreaks: TPopupMenu object popupLinebreaks: TPopupMenu
Images = MainForm.VirtualImageListMain Images = MainForm.VirtualImageListMain

View File

@ -6,7 +6,24 @@ uses
Windows, Classes, Graphics, Forms, Controls, StdCtrls, VirtualTrees, Windows, Classes, Graphics, Forms, Controls, StdCtrls, VirtualTrees,
ComCtrls, ToolWin, Dialogs, SysUtils, Menus, ExtDlgs, ComCtrls, ToolWin, Dialogs, SysUtils, Menus, ExtDlgs,
apphelpers, gnugettext, ActnList, StdActns, extra_controls, System.Actions, apphelpers, gnugettext, ActnList, StdActns, extra_controls, System.Actions,
Vcl.ExtCtrls; Vcl.ExtCtrls, dbconnection, SynEdit, SynMemo, SynEditHighlighter,
SynHighlighterADSP21xx, SynHighlighterAWK, SynHighlighterAsm, SynHighlighterAsmMASM,
SynHighlighterBaan, SynHighlighterBat, SynHighlighterCAC, SynHighlighterCPM, SynHighlighterCS,
SynHighlighterCache, SynHighlighterCobol, SynHighlighterCpp, SynHighlighterCss, SynHighlighterDOT,
SynHighlighterDWS, SynHighlighterDfm, SynHighlighterDml, SynHighlighterEiffel,
SynHighlighterFortran, SynHighlighterFoxpro, SynHighlighterGLSL, SynHighlighterGWS,
SynHighlighterGalaxy, SynHighlighterGeneral, SynHighlighterGo, SynHighlighterHC11,
SynHighlighterHP48, SynHighlighterHashEntries, SynHighlighterHaskell, SynHighlighterHtml,
SynHighlighterIDL, SynHighlighterIni, SynHighlighterInno, SynHighlighterJSON, SynHighlighterJScript,
SynHighlighterJava, SynHighlighterKix, SynHighlighterLDraw, SynHighlighterLLVM, SynHighlighterM3,
SynHighlighterModelica, SynHighlighterMsg, SynHighlighterPHP, SynHighlighterPas, SynHighlighterPerl,
SynHighlighterProgress, SynHighlighterPython, SynHighlighterRC, SynHighlighterRexx,
SynHighlighterRuby, SynHighlighterSDD, SynHighlighterSQL, SynHighlighterST, SynHighlighterSml,
SynHighlighterTclTk, SynHighlighterTeX, SynHighlighterUNIXShellScript, SynHighlighterURI,
SynHighlighterUnreal, SynHighlighterVB, SynHighlighterVBScript, SynHighlighterVrml97,
SynHighlighterWebIDL, SynHighlighterXML, SynHighlighterZPL
;
{$I const.inc} {$I const.inc}
@ -35,6 +52,7 @@ type
btnSearchFindNext: TToolButton; btnSearchFindNext: TToolButton;
btnSeparator1: TToolButton; btnSeparator1: TToolButton;
TimerMemoChange: TTimer; TimerMemoChange: TTimer;
comboHighlighter: TComboBox;
procedure btnApplyClick(Sender: TObject); procedure btnApplyClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject); procedure btnCancelClick(Sender: TObject);
procedure btnLoadTextClick(Sender: TObject); procedure btnLoadTextClick(Sender: TObject);
@ -52,14 +70,18 @@ type
procedure actSearchFindFindDialogClose(Sender: TObject); procedure actSearchFindFindDialogClose(Sender: TObject);
procedure actSearchReplaceReplaceDialogShow(Sender: TObject); procedure actSearchReplaceReplaceDialogShow(Sender: TObject);
procedure actSearchReplaceReplaceDialogClose(Sender: TObject); procedure actSearchReplaceReplaceDialogClose(Sender: TObject);
procedure comboHighlighterSelect(Sender: TObject);
private private
{ Private declarations } { Private declarations }
FModified: Boolean; FModified: Boolean;
FStopping: Boolean; FStopping: Boolean;
FDetectedLineBreaks, FDetectedLineBreaks,
FSelectedLineBreaks: TLineBreaks; FSelectedLineBreaks: TLineBreaks;
FmemoText: TLineNormalizingMemo; FmemoText: TSynMemo;
FFindDialogActive, FReplaceDialogActive: Boolean; FFindDialogActive, FReplaceDialogActive: Boolean;
FMaxLength: Integer;
FTableColumn: TTableColumn;
FHighlighter: TSynCustomHighlighter;
procedure SetModified(NewVal: Boolean); procedure SetModified(NewVal: Boolean);
public public
function GetText: String; function GetText: String;
@ -68,7 +90,8 @@ type
procedure SetMaxLength(len: integer); procedure SetMaxLength(len: integer);
procedure SetFont(font: TFont); procedure SetFont(font: TFont);
property Modified: Boolean read FModified write SetModified; property Modified: Boolean read FModified write SetModified;
property memoText: TLineNormalizingMemo read FmemoText; property memoText: TSynMemo read FmemoText;
property TableColumn: TTableColumn read FTableColumn write FTableColumn;
end; end;
@ -135,15 +158,15 @@ begin
// Timer based onchange handler, so we don't scan the whole text on every typed character // Timer based onchange handler, so we don't scan the whole text on every typed character
TimerMemoChange.Enabled := False; TimerMemoChange.Enabled := False;
TextLen := Length(FmemoText.Text); TextLen := Length(FmemoText.Text);
if FmemoText.MaxLength = 0 then if FMaxLength = 0 then
MaxLen := '?' MaxLen := '?'
else else
MaxLen := FormatNumber(FmemoText.MaxLength); MaxLen := FormatNumber(FMaxLength);
if TextLen = 0 then if TextLen = 0 then
Lines := 0 Lines := 0
else else
Lines := CountLineBreaks(FmemoText.Text) + 1; Lines := CountLineBreaks(FmemoText.Text) + 1;
CursorPos := FormatNumber(FmemoText.CaretPos.Y+1) + ' : ' + FormatNumber(FmemoText.CaretPos.X+1); CursorPos := 'x:z'; //FormatNumber(FmemoText.CaretPos.Y+1) + ' : ' + FormatNumber(FmemoText.CaretPos.X+1);
lblTextLength.Caption := f_('%s characters (max: %s), %s lines, cursor at %s', [FormatNumber(TextLen), MaxLen, FormatNumber(Lines), CursorPos]); lblTextLength.Caption := f_('%s characters (max: %s), %s lines, cursor at %s', [FormatNumber(TextLen), MaxLen, FormatNumber(Lines), CursorPos]);
end; end;
@ -175,7 +198,7 @@ end;
procedure TfrmTextEditor.SetMaxLength(len: integer); procedure TfrmTextEditor.SetMaxLength(len: integer);
begin begin
// Input: Length in number of bytes. // Input: Length in number of bytes.
FmemoText.MaxLength := len; FMaxLength := len;
end; end;
procedure TfrmTextEditor.SetFont(font: TFont); procedure TfrmTextEditor.SetFont(font: TFont);
@ -185,9 +208,12 @@ begin
end; end;
procedure TfrmTextEditor.FormCreate(Sender: TObject); procedure TfrmTextEditor.FormCreate(Sender: TObject);
var
Highlighters: TSynHighlighterList;
i: Integer;
begin begin
HasSizeGrip := True; HasSizeGrip := True;
FmemoText := TLineNormalizingMemo.Create(Self); FmemoText := TSynMemo.Create(Self);
FmemoText.Parent := Self; FmemoText.Parent := Self;
FmemoText.Align := alClient; FmemoText.Align := alClient;
FmemoText.ScrollBars := ssBoth; FmemoText.ScrollBars := ssBoth;
@ -196,6 +222,9 @@ begin
FmemoText.OnKeyDown := memoTextKeyDown; FmemoText.OnKeyDown := memoTextKeyDown;
FmemoText.OnClick := memoTextClick; FmemoText.OnClick := memoTextClick;
FmemoText.HideSelection := False; // Make found text visible when find dialog has focus FmemoText.HideSelection := False; // Make found text visible when find dialog has focus
FmemoText.Options := FmemoText.Options - [eoScrollPastEol];
FmemoText.RightEdge := 0;
FmemoText.Gutter.ShowLineNumbers := True;
// Use same text properties as in query/find/replace actions // Use same text properties as in query/find/replace actions
actSearchFind.Caption := MainForm.actQueryFind.Caption; actSearchFind.Caption := MainForm.actQueryFind.Caption;
actSearchFind.Hint := MainForm.actQueryFind.Hint; actSearchFind.Hint := MainForm.actQueryFind.Hint;
@ -214,8 +243,17 @@ begin
Height := AppSettings.ReadInt(asMemoEditorHeight); Height := AppSettings.ReadInt(asMemoEditorHeight);
if AppSettings.ReadBool(asMemoEditorMaximized) then if AppSettings.ReadBool(asMemoEditorMaximized) then
WindowState := wsMaximized; WindowState := wsMaximized;
if AppSettings.ReadBool(asMemoEditorWrap) then if AppSettings.ReadBool(asMemoEditorWrap) then
btnWrap.Click; btnWrap.Click;
Highlighters := SynEditHighlighter.GetPlaceableHighlighters;
for i:=0 to Highlighters.Count-1 do begin
comboHighlighter.Items.Add(Highlighters[i].GetFriendlyLanguageName);
end;
FTableColumn := nil;
// Fix label position: // Fix label position:
lblTextLength.Top := tlbStandard.Top + (tlbStandard.Height-lblTextLength.Height) div 2; lblTextLength.Top := tlbStandard.Top + (tlbStandard.Height-lblTextLength.Height) div 2;
end; end;
@ -229,11 +267,25 @@ begin
end; end;
AppSettings.WriteBool(asMemoEditorMaximized, WindowState=wsMaximized); AppSettings.WriteBool(asMemoEditorMaximized, WindowState=wsMaximized);
AppSettings.WriteBool(asMemoEditorWrap, btnWrap.Down); AppSettings.WriteBool(asMemoEditorWrap, btnWrap.Down);
if Assigned(FTableColumn) and (comboHighlighter.Text <> AppSettings.GetDefaultString(asMemoEditorHighlighter)) then begin
AppSettings.SessionPath := MainForm.GetRegKeyTable;
AppSettings.WriteString(asMemoEditorHighlighter, comboHighlighter.Text, FTableColumn.Name);
end;
end; end;
procedure TfrmTextEditor.FormShow(Sender: TObject); procedure TfrmTextEditor.FormShow(Sender: TObject);
var
HighlighterName: String;
begin begin
// Select previously used highlighter
HighlighterName := AppSettings.GetDefaultString(asMemoEditorHighlighter);
if Assigned(FTableColumn) then begin
AppSettings.SessionPath := MainForm.GetRegKeyTable;
HighlighterName := AppSettings.ReadString(asMemoEditorHighlighter, FTableColumn.Name, HighlighterName);
end;
comboHighlighter.ItemIndex := comboHighlighter.Items.IndexOf(HighlighterName);
comboHighlighter.OnSelect(comboHighlighter);
// Trigger change event, which is not fired when text is empty. See #132. // Trigger change event, which is not fired when text is empty. See #132.
TimerMemoChangeTimer(Self); TimerMemoChangeTimer(Self);
FmemoText.SetFocus; FmemoText.SetFocus;
@ -274,16 +326,36 @@ begin
Screen.Cursor := crHourglass; Screen.Cursor := crHourglass;
// Changing the scrollbars invoke the OnChange event. We avoid thinking the text was really modified. // Changing the scrollbars invoke the OnChange event. We avoid thinking the text was really modified.
WasModified := Modified; WasModified := Modified;
if FmemoText.ScrollBars = ssBoth then if FmemoText.ScrollBars = ssBoth then begin
FmemoText.ScrollBars := ssVertical FmemoText.ScrollBars := ssVertical;
else FmemoText.WordWrap := True;
end else begin
FmemoText.ScrollBars := ssBoth; FmemoText.ScrollBars := ssBoth;
FmemoText.WordWrap := False;
end;
TToolbutton(Sender).Down := FmemoText.ScrollBars = ssVertical; TToolbutton(Sender).Down := FmemoText.ScrollBars = ssVertical;
Modified := WasModified; Modified := WasModified;
Screen.Cursor := crDefault; Screen.Cursor := crDefault;
end; end;
procedure TfrmTextEditor.comboHighlighterSelect(Sender: TObject);
var
Highlighters: TSynHighlighterList;
i: Integer;
begin
// Code highlighter selected
FmemoText.Highlighter := nil;
FHighlighter.Free;
Highlighters := SynEditHighlighter.GetPlaceableHighlighters;
for i:=0 to Highlighters.Count-1 do begin
if comboHighlighter.Text = Highlighters[i].GetFriendlyLanguageName then begin
FHighlighter := Highlighters[i].Create(Self);
FmemoText.Highlighter := FHighlighter;
end;
end;
end;
procedure TfrmTextEditor.btnLoadTextClick(Sender: TObject); procedure TfrmTextEditor.btnLoadTextClick(Sender: TObject);
var var
d: TOpenTextFileDialog; d: TOpenTextFileDialog;
@ -297,8 +369,8 @@ begin
if d.Execute then try if d.Execute then try
Screen.Cursor := crHourglass; Screen.Cursor := crHourglass;
FmemoText.Text := ReadTextFile(d.FileName, MainForm.GetEncodingByName(d.Encodings[d.EncodingIndex])); FmemoText.Text := ReadTextFile(d.FileName, MainForm.GetEncodingByName(d.Encodings[d.EncodingIndex]));
if (FmemoText.MaxLength > 0) and (Length(FmemoText.Text) > FmemoText.MaxLength) then if (FMaxLength > 0) and (Length(FmemoText.Text) > FMaxLength) then
FmemoText.Text := copy(FmemoText.Text, 0, FmemoText.MaxLength); FmemoText.Text := copy(FmemoText.Text, 0, FMaxLength);
AppSettings.WriteInt(asFileDialogEncoding, d.EncodingIndex, Self.Name); AppSettings.WriteInt(asFileDialogEncoding, d.EncodingIndex, Self.Name);
finally finally
Screen.Cursor := crDefault; Screen.Cursor := crDefault;