mirror of https://gitlab.com/basile.b/dexed.git
526 lines
15 KiB
Plaintext
526 lines
15 KiB
Plaintext
unit ce_editoroptions;
|
|
|
|
{$I ce_defines.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, SynEdit, SynEditMouseCmds, SynEditMiscClasses,
|
|
SynEditKeyCmds, Menus, LCLProc,
|
|
ce_interfaces, ce_observer, ce_common, ce_writableComponent, ce_synmemo,
|
|
ce_d2syn, ce_txtsyn;
|
|
|
|
type
|
|
|
|
(**
|
|
* Container for the editor and highlither options.
|
|
* The base class is also used to backup the settings
|
|
* to allow a to preview and restore the settings when rejected.
|
|
*
|
|
* note: when adding a new property, the default value must be set in
|
|
* the constructor according to the default value of the member binded
|
|
* to the property.
|
|
*)
|
|
TCEEditorOptionsBase = class(TWritableLfmTextComponent)
|
|
private
|
|
// note this is how a TComponent can be edited in
|
|
// a basic TTIGrid: in the ctor create the component
|
|
// but expose it as a published TPersistent.
|
|
fD2Syn: TPersistent;
|
|
fTxtSyn: TPersistent;
|
|
//
|
|
fShortCuts: TCollection;
|
|
//
|
|
fSelCol: TSynSelectedColor;
|
|
fFoldedColor: TSynSelectedColor;
|
|
fMouseLinkColor: TSynSelectedColor;
|
|
fBracketMatchColor: TSynSelectedColor;
|
|
fFont: TFont;
|
|
//
|
|
fDDocDelay: Integer;
|
|
fAutoDotDelay: Integer;
|
|
fTabWidth: Integer;
|
|
fBlockIdent: Integer;
|
|
fLineSpacing: Integer;
|
|
fCharSpacing: Integer;
|
|
fRightEdge: Integer;
|
|
fBackground: TColor;
|
|
fRightEdgeColor: TColor;
|
|
fOptions1: TSynEditorOptions;
|
|
fOptions2: TSynEditorOptions2;
|
|
fMouseOptions: TSynEditorMouseOptions;
|
|
fCompletionMenuCaseCare: boolean;
|
|
//
|
|
procedure setFont(aValue: TFont);
|
|
procedure setSelCol(aValue: TSynSelectedColor);
|
|
procedure setFoldedColor(aValue: TSynSelectedColor);
|
|
procedure setMouseLinkColor(aValue: TSynSelectedColor);
|
|
procedure setBracketMatchColor(aValue: TSynSelectedColor);
|
|
procedure setD2Syn(aValue: TPersistent);
|
|
procedure setTxtSyn(aValue: TPersistent);
|
|
procedure setShortcuts(aValue: TCollection);
|
|
procedure setDDocDelay(aValue: Integer);
|
|
procedure setAutoDotDelay(aValue: Integer);
|
|
published
|
|
property completionMenuCaseCare: boolean read fCompletionMenuCaseCare write fCompletionMenuCaseCare;
|
|
property autoDotDelay: integer read fAutoDotDelay write SetautoDotDelay;
|
|
property hintDelay: Integer read fDDocDelay write setDDocDelay stored false; deprecated;
|
|
property ddocDelay: Integer read fDDocDelay write setDDocDelay;
|
|
property bracketMatchColor: TSynSelectedColor read fBracketMatchColor write setBracketMatchColor;
|
|
property mouseLinkColor: TSynSelectedColor read fMouseLinkColor write setMouseLinkColor;
|
|
property selectedColor: TSynSelectedColor read fSelCol write setSelCol;
|
|
property foldedColor: TSynSelectedColor read fFoldedColor write setFoldedColor;
|
|
property background: TColor read fBackground write fBackground default clWhite;
|
|
property tabulationWidth: Integer read fTabWidth write fTabWidth default 4;
|
|
property blockIdentation: Integer read fBlockIdent write fBlockIdent default 4;
|
|
property lineSpacing: Integer read fLineSpacing write fLineSpacing default 0;
|
|
property characterSpacing: Integer read fCharSpacing write fCharSpacing default 0;
|
|
property rightEdge: Integer read fRightEdge write fRightEdge default 80;
|
|
property rightEdgeColor: TColor read fRightEdgeColor write fRightEdgeColor default clSilver;
|
|
property font: TFont read fFont write setFont;
|
|
property options1: TSynEditorOptions read fOptions1 write fOptions1;
|
|
property options2: TSynEditorOptions2 read fOptions2 write fOptions2;
|
|
property mouseOptions: TSynEditorMouseOptions read fMouseOptions write fMouseOptions;
|
|
property D2Highlighter: TPersistent read fD2Syn write setD2Syn;
|
|
property TxtHighlighter: TPersistent read fTxtSyn write setTxtSyn;
|
|
property shortcuts: TCollection read fShortCuts write setShortcuts;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
//
|
|
procedure Assign(src: TPersistent); override;
|
|
end;
|
|
|
|
(**
|
|
* Manages and exposes all the editor and highligther options to an TCEOptionsEditor.
|
|
* It's also responsible to give the current options to a new editor.
|
|
*)
|
|
TCEEditorOptions = class(TCEEditorOptionsBase, ICEEditableOptions, ICEMultiDocObserver, ICEEDitableShortcut)
|
|
private
|
|
fBackup: TCEEditorOptionsBase;
|
|
fShortcutCount: Integer;
|
|
//
|
|
function optionedWantCategory(): string;
|
|
function optionedWantEditorKind: TOptionEditorKind;
|
|
function optionedWantContainer: TPersistent;
|
|
procedure optionedEvent(anEvent: TOptionEditorEvent);
|
|
function optionedOptionsModified: boolean;
|
|
//
|
|
procedure docNew(aDoc: TCESynMemo);
|
|
procedure docFocused(aDoc: TCESynMemo);
|
|
procedure docChanged(aDoc: TCESynMemo);
|
|
procedure docClosing(aDoc: TCESynMemo);
|
|
//
|
|
function scedWantFirst: boolean;
|
|
function scedWantNext(out category, identifier: string; out aShortcut: TShortcut): boolean;
|
|
procedure scedSendItem(const category, identifier: string; aShortcut: TShortcut);
|
|
//
|
|
procedure applyChangesFromSelf;
|
|
procedure applyChangeToEditor(anEditor: TCESynMemo);
|
|
protected
|
|
procedure afterLoad; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
const
|
|
edoptFname = 'editor.txt';
|
|
|
|
var
|
|
EditorOptions: TCEEditorOptions;
|
|
|
|
{$REGION Standard Comp/Obj -----------------------------------------------------}
|
|
constructor TCEEditorOptionsBase.Create(AOwner: TComponent);
|
|
var
|
|
i: integer;
|
|
shc: TCEPersistentShortcut;
|
|
ed: TSynEdit;
|
|
begin
|
|
inherited;
|
|
//
|
|
fFont := TFont.Create;
|
|
fFont.Name := 'Courier New';
|
|
fFont.Quality := fqProof;
|
|
fFont.Pitch := fpFixed;
|
|
fFont.Size := 10;
|
|
//
|
|
fD2Syn := TSynD2Syn.Create(self);
|
|
fD2Syn.Assign(D2Syn);
|
|
fTxtSyn := TSynTxtSyn.Create(self);
|
|
fTxtSyn.Assign(TxtSyn);
|
|
//
|
|
fDDocDelay:=200;
|
|
fAutoDotDelay:=200;
|
|
fSelCol := TSynSelectedColor.Create;
|
|
fFoldedColor := TSynSelectedColor.Create;
|
|
fMouseLinkColor := TSynSelectedColor.Create;
|
|
fBracketMatchColor := TSynSelectedColor.Create;
|
|
//
|
|
// note: default values come from TSynEditFoldedView ctor.
|
|
fFoldedColor.Background := clNone;
|
|
fFoldedColor.Foreground := clDkGray;
|
|
fFoldedColor.FrameColor := clDkGray;
|
|
//
|
|
fMouseLinkColor.Style := [fsUnderline, fsBold];
|
|
fMouseLinkColor.StyleMask := [];
|
|
fMouseLinkColor.Foreground := clNone;
|
|
fMouseLinkColor.Background := clNone;
|
|
//
|
|
fBracketMatchColor.Foreground := clRed;
|
|
fBracketMatchColor.Background := clNone;
|
|
//
|
|
rightEdge := 80;
|
|
tabulationWidth := 4;
|
|
blockIdentation := 4;
|
|
fBackground := clWhite;
|
|
fRightEdgeColor := clSilver;
|
|
//
|
|
options1 :=
|
|
[eoAutoIndent, eoBracketHighlight, eoGroupUndo, eoTabsToSpaces,
|
|
eoDragDropEditing, eoShowCtrlMouseLinks, eoEnhanceHomeKey, eoTabIndent];
|
|
options2 :=
|
|
[eoEnhanceEndKey, eoFoldedCopyPaste, eoOverwriteBlock];
|
|
//
|
|
mouseOptions := MouseOptions +
|
|
[emAltSetsColumnMode, emDragDropEditing, emCtrlWheelZoom, emShowCtrlMouseLinks];
|
|
//
|
|
fShortCuts := TCollection.Create(TCEPersistentShortcut);
|
|
ed := TSynEdit.Create(nil);
|
|
try
|
|
// note: cant use a TCESynMemo because it'd be added to the EntitiesConnector
|
|
SetDefaultCoeditKeystrokes(ed);
|
|
for i:= 0 to ed.Keystrokes.Count-1 do
|
|
begin
|
|
shc := TCEPersistentShortcut(fShortCuts.Add);
|
|
shc.actionName:= EditorCommandToCodeString(ed.Keystrokes.Items[i].Command);
|
|
shc.shortcut := ed.Keystrokes.Items[i].ShortCut;
|
|
end;
|
|
finally
|
|
ed.free;
|
|
end;
|
|
end;
|
|
|
|
destructor TCEEditorOptionsBase.Destroy;
|
|
begin
|
|
fFont.Free;
|
|
fSelCol.Free;
|
|
fShortCuts.Free;
|
|
fFoldedColor.Free;
|
|
fMouseLinkColor.Free;
|
|
fBracketMatchColor.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.Assign(src: TPersistent);
|
|
var
|
|
srcopt: TCEEditorOptionsBase;
|
|
begin
|
|
if (src is TCEEditorOptionsBase) then
|
|
begin
|
|
srcopt := TCEEditorOptionsBase(src);
|
|
//
|
|
fCompletionMenuCaseCare:=srcopt.fCompletionMenuCaseCare;
|
|
fAutoDotDelay:=srcopt.fAutoDotDelay;
|
|
fDDocDelay:=srcopt.fDDocDelay;
|
|
fFont.Assign(srcopt.fFont);
|
|
fSelCol.Assign(srcopt.fSelCol);
|
|
fFoldedColor.Assign(srcopt.fFoldedColor);
|
|
fMouseLinkColor.Assign(srcopt.fMouseLinkColor);
|
|
fBracketMatchColor.Assign(srcopt.fBracketMatchColor);
|
|
fD2Syn.Assign(srcopt.fD2Syn);
|
|
fTxtSyn.Assign(srcopt.fTxtSyn);
|
|
background := srcopt.background;
|
|
tabulationWidth := srcopt.tabulationWidth;
|
|
blockIdentation := srcopt.blockIdentation;
|
|
lineSpacing := srcopt.lineSpacing;
|
|
characterSpacing := srcopt.characterSpacing;
|
|
options1 := srcopt.options1;
|
|
options2 := srcopt.options2;
|
|
mouseOptions := srcopt.mouseOptions;
|
|
rightEdge := srcopt.rightEdge;
|
|
rightEdgeColor := srcopt.rightEdgeColor;
|
|
fShortCuts.Assign(srcopt.fShortCuts);
|
|
end
|
|
else
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setDDocDelay(aValue: Integer);
|
|
begin
|
|
if aValue > 2000 then aValue := 2000
|
|
else if aValue < 20 then aValue := 20;
|
|
fDDocDelay:=aValue;
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setAutoDotDelay(aValue: Integer);
|
|
begin
|
|
if aValue > 2000 then aValue := 2000
|
|
else if aValue < 0 then aValue := 0;
|
|
fAutoDotDelay:=aValue;
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setShortcuts(aValue: TCollection);
|
|
begin
|
|
fShortCuts.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setFont(aValue: TFont);
|
|
begin
|
|
fFont.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setSelCol(aValue: TSynSelectedColor);
|
|
begin
|
|
fSelCol.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setFoldedColor(aValue: TSynSelectedColor);
|
|
begin
|
|
fFoldedColor.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setMouseLinkColor(aValue: TSynSelectedColor);
|
|
begin
|
|
fMouseLinkColor.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setBracketMatchColor(aValue: TSynSelectedColor);
|
|
begin
|
|
fBracketMatchColor.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setD2Syn(aValue: TPersistent);
|
|
begin
|
|
D2Syn.Assign(aValue);
|
|
end;
|
|
|
|
procedure TCEEditorOptionsBase.setTxtSyn(aValue: TPersistent);
|
|
begin
|
|
TxtSyn.Assign(aValue);
|
|
end;
|
|
|
|
constructor TCEEditorOptions.Create(AOwner: TComponent);
|
|
var
|
|
fname: string;
|
|
begin
|
|
inherited;
|
|
fBackup := TCEEditorOptionsBase.Create(self);
|
|
EntitiesConnector.addObserver(self);
|
|
//
|
|
fname := getCoeditDocPath + edoptFname;
|
|
if fileExists(fname) then
|
|
loadFromFile(fname);
|
|
end;
|
|
|
|
destructor TCEEditorOptions.Destroy;
|
|
begin
|
|
saveToFile(getCoeditDocPath + edoptFname);
|
|
//
|
|
EntitiesConnector.removeObserver(self);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TCEEditorOptions.afterLoad;
|
|
begin
|
|
inherited;
|
|
D2Syn.Assign(fD2Syn);
|
|
TxtSyn.Assign(fTxtSyn);
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEMultiDocObserver ----------------------------------------------------}
|
|
procedure TCEEditorOptions.docNew(aDoc: TCESynMemo);
|
|
begin
|
|
applyChangeToEditor(aDoc);
|
|
end;
|
|
|
|
procedure TCEEditorOptions.docFocused(aDoc: TCESynMemo);
|
|
begin
|
|
end;
|
|
|
|
procedure TCEEditorOptions.docChanged(aDoc: TCESynMemo);
|
|
begin
|
|
end;
|
|
|
|
procedure TCEEditorOptions.docClosing(aDoc: TCESynMemo);
|
|
begin
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEEDitableShortcut ---------------------------------------------------}
|
|
function TCEEditorOptions.scedWantFirst: boolean;
|
|
begin
|
|
result := fShortCuts.Count > 0;
|
|
fShortcutCount := 0;
|
|
end;
|
|
|
|
function TCEEditorOptions.scedWantNext(out category, identifier: string; out aShortcut: TShortcut): boolean;
|
|
var
|
|
shrct: TCEPersistentShortcut;
|
|
begin
|
|
shrct := TCEPersistentShortcut(fShortCuts.Items[fShortcutCount]);
|
|
category := 'Code editor';
|
|
identifier:= shrct.actionName;
|
|
// SynEdit shortcuts start with 'ec'
|
|
if length(identifier) > 2 then
|
|
identifier := identifier[3..length(identifier)];
|
|
aShortcut := shrct.shortcut;
|
|
//
|
|
fShortcutCount += 1;
|
|
result := fShortcutCount < fShortCuts.Count;
|
|
end;
|
|
|
|
procedure TCEEditorOptions.scedSendItem(const category, identifier: string; aShortcut: TShortcut);
|
|
var
|
|
i: Integer;
|
|
shc: TCEPersistentShortcut;
|
|
begin
|
|
if category <> 'Code editor' then exit;
|
|
//
|
|
for i:= 0 to fShortCuts.Count-1 do
|
|
begin
|
|
shc := TCEPersistentShortcut(fShortCuts.Items[i]);
|
|
if length(shc.actionName) > 2 then
|
|
begin
|
|
if shc.actionName[3..length(shc.actionName)] <> identifier then
|
|
continue;
|
|
end else if shc.actionName <> identifier then
|
|
continue;
|
|
shc.shortcut:= aShortcut;
|
|
break;
|
|
end;
|
|
// note: shortcut modifications are not reversible,
|
|
// they are sent from another option editor.
|
|
applyChangesFromSelf;
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEEditableOptions ----------------------------------------------------}
|
|
function TCEEditorOptions.optionedWantCategory(): string;
|
|
begin
|
|
exit('Editor');
|
|
end;
|
|
|
|
function TCEEditorOptions.optionedWantEditorKind: TOptionEditorKind;
|
|
begin
|
|
exit(oekGeneric);
|
|
end;
|
|
|
|
function TCEEditorOptions.optionedWantContainer: TPersistent;
|
|
begin
|
|
fD2Syn := D2Syn;
|
|
fTxtSyn := TxtSyn;
|
|
fBackup.Assign(self);
|
|
fBackup.fD2Syn.Assign(D2Syn);
|
|
fBackup.fTxtSyn.Assign(TxtSyn);
|
|
exit(self);
|
|
end;
|
|
|
|
procedure TCEEditorOptions.optionedEvent(anEvent: TOptionEditorEvent);
|
|
begin
|
|
// restores
|
|
if anEvent = oeeCancel then
|
|
begin
|
|
self.Assign(fBackup);
|
|
D2Syn.Assign(fBackup.fD2Syn);
|
|
TxtSyn.Assign(fBackup.fTxtSyn);
|
|
end;
|
|
// apply, if change/accept event
|
|
// to get a live preview
|
|
if anEvent <> oeeSelectCat then
|
|
applyChangesFromSelf;
|
|
// new backup values based on accepted values.
|
|
if anEvent = oeeAccept then
|
|
begin
|
|
fBackup.Assign(self);
|
|
fBackup.fD2Syn.Assign(D2Syn);
|
|
fBackup.fTxtSyn.Assign(TxtSyn);
|
|
end;
|
|
end;
|
|
|
|
function TCEEditorOptions.optionedOptionsModified: boolean;
|
|
begin
|
|
exit(false);
|
|
end;
|
|
{$ENDREGION}
|
|
|
|
{$REGION ICEEditableOptions ----------------------------------------------------}
|
|
procedure TCEEditorOptions.applyChangesFromSelf;
|
|
var
|
|
multied: ICEMultiDocHandler;
|
|
i: Integer;
|
|
begin
|
|
multied := getMultiDocHandler;
|
|
for i := 0 to multied.documentCount - 1 do
|
|
applyChangeToEditor(multied.document[i]);
|
|
end;
|
|
|
|
procedure TCEEditorOptions.applyChangeToEditor(anEditor: TCESynMemo);
|
|
var
|
|
i, j, k: Integer;
|
|
shc: TCEPersistentShortcut;
|
|
kst: TSynEditKeyStroke;
|
|
dup: boolean;
|
|
begin
|
|
anEditor.D2Highlighter.Assign(D2Syn);
|
|
anEditor.TxtHighlighter.Assign(TxtSyn);
|
|
|
|
anEditor.completionMenuCaseCare:=fCompletionMenuCaseCare;
|
|
anEditor.autoDotDelay:=fAutoDotDelay;
|
|
anEditor.ddocDelay:=fDDocDelay;
|
|
anEditor.defaultFontSize := font.Size;
|
|
anEditor.Font.Assign(font);
|
|
anEditor.SelectedColor.Assign(fSelCol);
|
|
anEditor.FoldedCodeColor.Assign(fFoldedColor);
|
|
anEditor.MouseLinkColor.Assign(fMouseLinkColor);
|
|
anEditor.BracketMatchColor.Assign(fBracketMatchColor);
|
|
anEditor.TabWidth := tabulationWidth;
|
|
anEditor.BlockIndent := blockIdentation;
|
|
anEditor.ExtraLineSpacing := lineSpacing;
|
|
anEditor.ExtraCharSpacing := characterSpacing;
|
|
anEditor.Options := options1;
|
|
anEditor.Options2 := options2;
|
|
anEditor.MouseOptions := mouseOptions;
|
|
anEditor.Color := background;
|
|
anEditor.RightEdge := rightEdge;
|
|
anEditor.RightEdgeColor := rightEdgeColor;
|
|
for i := 0 to anEditor.Keystrokes.Count-1 do
|
|
begin
|
|
kst := anEditor.Keystrokes.Items[i];
|
|
for j := 0 to fShortCuts.Count-1 do
|
|
begin
|
|
dup := false;
|
|
shc := TCEPersistentShortcut(fShortCuts.Items[j]);
|
|
if shc.actionName = EditorCommandToCodeString(kst.Command) then
|
|
begin
|
|
try
|
|
for k := 0 to i-1 do
|
|
if anEditor.Keystrokes.Items[k].shortCut = shc.shortcut then
|
|
if shc.shortCut <> 0 then
|
|
dup := true;
|
|
if not dup then
|
|
kst.shortCut := shc.shortcut;
|
|
except
|
|
kst.shortCut := 0;
|
|
shc.shortcut := 0;
|
|
// in case of conflict synedit raises an exception.
|
|
end;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$ENDREGION}
|
|
|
|
|
|
initialization
|
|
EditorOptions := TCEEditorOptions.Create(nil);
|
|
|
|
finalization
|
|
EditorOptions.Free;
|
|
end.
|