From 8208f4304905085f7779666a9d15682e316de63f Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 16 Feb 2015 12:06:43 +0300 Subject: [PATCH] configurable shortcuts - issue #59 --- src/dlangui/core/events.d | 31 ++++++++++++++++++++++++----- src/dlangui/core/settings.d | 22 +++++++++++++++------ src/dlangui/widgets/appframe.d | 24 +++++++++++++++-------- src/dlangui/widgets/editors.d | 36 +++++++++++++++++++--------------- 4 files changed, 78 insertions(+), 35 deletions(-) diff --git a/src/dlangui/core/events.d b/src/dlangui/core/events.d index bc2aa33d..4320fed5 100644 --- a/src/dlangui/core/events.d +++ b/src/dlangui/core/events.d @@ -43,7 +43,7 @@ struct Accelerator { return cast(dstring)buf; } /// Serializes accelerator text description - @property string toString() { + @property string toString() const { char[] buf; if (keyFlags & KeyFlag.Control) buf ~= "Ctrl+"; @@ -246,13 +246,21 @@ class Action { @property Accelerator[] accelerators() { // check for accelerators override in settings Accelerator[] res = findActionAccelerators(_id); - if (res) + if (res) { + //Log.d("Found accelerators ", res); return res; + } // return this action accelerators return _accelerators; } /// returs const array of accelerators @property const(Accelerator)[] accelerators() const { + // check for accelerators override in settings + Accelerator[] res = findActionAccelerators(_id); + if (res) { + //Log.d("Found accelerators ", res); + return res; + } return _accelerators; } /// returns text description for first accelerator of action; null if no accelerators @@ -1082,7 +1090,12 @@ uint parseKeyName(string name) { case "Down": return KeyCode.DOWN; case "Ins": return KeyCode.DEL; case "Del": return KeyCode.INS; - // TODO: add more keys here + case "[": return KeyCode.KEY_BRACKETOPEN; + case "]": return KeyCode.KEY_BRACKETCLOSE; + case ",": return KeyCode.KEY_COMMA; + case ".": return KeyCode.KEY_PERIOD; + case "Backspace": return KeyCode.BACK; + case "Enter": return KeyCode.RETURN; default: return 0; } @@ -1241,6 +1254,14 @@ string keyName(uint keyCode) { return "Ins"; case KeyCode.DEL: return "Del"; + case KeyCode.KEY_BRACKETOPEN: + return "["; + case KeyCode.KEY_BRACKETCLOSE: + return "]"; + case KeyCode.BACK: + return "Backspace"; + case KeyCode.RETURN: + return "Enter"; default: return format("0x%08x", keyCode); } @@ -1313,8 +1334,8 @@ void setActionAccelerators(int actionId, Accelerator[] accelerators) { } /// lookup accelerators override for action by id Accelerator[] findActionAccelerators(int actionId) { - if (auto found = actionAcceleratorsMap[actionId]) - return found; + if (auto found = actionId in actionAcceleratorsMap) + return *found; return null; } /// lookup accelerators override for action by name (e.g. "EditorActions.ToggleLineComment") diff --git a/src/dlangui/core/settings.d b/src/dlangui/core/settings.d index ad905d04..ad4fd2b0 100644 --- a/src/dlangui/core/settings.d +++ b/src/dlangui/core/settings.d @@ -64,7 +64,7 @@ class SettingsFile { _setting = new Setting(); _filename = filename; if (_filename) { - string dir = baseName(_filename); + string dir = dirName(_filename); if (load()) { // loaded ok } else { @@ -114,7 +114,7 @@ class SettingsFile { if (filename !is null) _filename = filename; assert(_filename); - string dir = baseName(_filename); + string dir = dirName(_filename); if (!dir.exists) { try { mkdirRecurse(dir); @@ -170,6 +170,16 @@ final class Setting { _store.array.list = v; } + this(string[] v) { + clear(SettingType.ARRAY); + this.strArray = v; + } + + this(string[string] v) { + clear(SettingType.ARRAY); + this.strMap = v; + } + /// returns true if setting has been changed @property bool changed() { return _changed; @@ -920,10 +930,6 @@ final class Setting { double opAssign(double value) { return (floating = value); } - // assign string[] value - string[] opAssign(string[] value) { - return (strArray = value); - } // assign int[] value int[] opAssign(int[] value) { return (intArray = value); @@ -932,6 +938,10 @@ final class Setting { string[string] opAssign(string[string] value) { return (strMap = value); } + // assign string[] value + string[] opAssign(string[] value) { + return (strArray = value); + } // assign int[string] value int[string] opAssign(int[string] value) { return (intMap = value); diff --git a/src/dlangui/widgets/appframe.d b/src/dlangui/widgets/appframe.d index 6d0c8815..5b688069 100644 --- a/src/dlangui/widgets/appframe.d +++ b/src/dlangui/widgets/appframe.d @@ -81,7 +81,7 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler { - protected string _appName = "dlangui"; + protected string _appName; /// override to return some identifier for app, e.g. to use as settings directory name @property string appCodeName() { return _appName; @@ -121,18 +121,20 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler { for (int i = 0; i < value.length; i++) { string v = value[i].str; Accelerator a; - if (a.parse(v)) + if (a.parse(v)) { + //Log.d("Read accelerator for action ", key, " : ", a.toString); accelerators ~= a; - else - Log.e("cannot parse accelerator: ", v); + } else + Log.e("applyShortcutsSettings: cannot parse accelerator: ", v); } } else { string v = value.str; Accelerator a; - if (a.parse(v)) + if (a.parse(v)) { + //Log.d("Read accelerator for action ", key, " : ", a.toString); accelerators ~= a; - else - Log.e("cannot parse accelerator: ", v); + } else + Log.e("applyShortcutsSettings: cannot parse accelerator: ", v); } setActionAccelerators(actionId, accelerators); } @@ -148,7 +150,7 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler { foreach(a; actions) { string name = actionIdToName(a.id); if (name) { - Accelerator[] acc = findActionAccelerators(a.id); + const(Accelerator)[] acc = a.accelerators; if (acc.length > 0) { if (acc.length == 1) { _shortcutSettings[name] = acc[0].toString; @@ -212,6 +214,7 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler { super("APP_FRAME"); layoutWidth = FILL_PARENT; layoutHeight = FILL_PARENT; + _appName = "dlangui"; init(); } @@ -240,6 +243,11 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler { addChild(_body); if (_statusLine) addChild(_statusLine); + updateShortcuts(); + } + + /// override it + protected void updateShortcuts() { } /// override to handle main menu commands diff --git a/src/dlangui/widgets/editors.d b/src/dlangui/widgets/editors.d index 15fb2b61..d99d5aee 100644 --- a/src/dlangui/widgets/editors.d +++ b/src/dlangui/widgets/editors.d @@ -113,9 +113,11 @@ enum EditorActions : int { /// insert new line (Enter) InsertNewLine, - /// insert new line after current position (Ctrl+Enter) + /// insert new line before current position (Ctrl+Enter) PrependNewLine, - + /// insert new line after current position (Ctrl+Enter) + AppendNewLine, + /// Turn On/Off replace mode ToggleReplaceMode, @@ -178,6 +180,19 @@ __gshared static this() { registerActionEnum!EditorActions(); } +const Action ACTION_EDITOR_INSERT_NEW_LINE = (new Action(EditorActions.InsertNewLine, KeyCode.RETURN, 0)).addAccelerator(KeyCode.RETURN, KeyFlag.Shift); +const Action ACTION_EDITOR_PREPEND_NEW_LINE = (new Action(EditorActions.PrependNewLine, KeyCode.RETURN, KeyFlag.Control|KeyFlag.Shift)); +const Action ACTION_EDITOR_APPEND_NEW_LINE = (new Action(EditorActions.AppendNewLine, KeyCode.RETURN, KeyFlag.Control)); +const Action ACTION_EDITOR_DELETE_LINE = (new Action(EditorActions.DeleteLine, KeyCode.KEY_D, KeyFlag.Control)).addAccelerator(KeyCode.KEY_L, KeyFlag.Control); +const Action ACTION_EDITOR_TOGGLE_REPLACE_MODE = (new Action(EditorActions.ToggleReplaceMode, KeyCode.INS, 0)); +const Action ACTION_EDITOR_SELECT_ALL = (new Action(EditorActions.SelectAll, KeyCode.KEY_A, KeyFlag.Control)); +const Action ACTION_EDITOR_TOGGLE_LINE_COMMENT = (new Action(EditorActions.ToggleLineComment, KeyCode.KEY_DIVIDE, KeyFlag.Control)); +const Action ACTION_EDITOR_TOGGLE_BLOCK_COMMENT = (new Action(EditorActions.ToggleBlockComment, KeyCode.KEY_DIVIDE, KeyFlag.Control | KeyFlag.Shift)); + +const Action[] STD_EDITOR_ACTIONS = [ACTION_EDITOR_INSERT_NEW_LINE, ACTION_EDITOR_PREPEND_NEW_LINE, + ACTION_EDITOR_APPEND_NEW_LINE, ACTION_EDITOR_DELETE_LINE, ACTION_EDITOR_TOGGLE_REPLACE_MODE, + ACTION_EDITOR_SELECT_ALL, ACTION_EDITOR_TOGGLE_LINE_COMMENT, ACTION_EDITOR_TOGGLE_BLOCK_COMMENT]; + /// base for all editor widgets class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemActionHandler { protected EditableContent _content; @@ -348,10 +363,6 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction new Action(EditorActions.ScrollLineUp, KeyCode.UP, KeyFlag.Control), new Action(EditorActions.ScrollLineDown, KeyCode.DOWN, KeyFlag.Control), - new Action(EditorActions.InsertNewLine, KeyCode.RETURN, 0), - new Action(EditorActions.InsertNewLine, KeyCode.RETURN, KeyFlag.Shift), - new Action(EditorActions.PrependNewLine, KeyCode.RETURN, KeyFlag.Control), - // Backspace/Del new Action(EditorActions.DelPrevChar, KeyCode.BACK, 0), new Action(EditorActions.DelNextChar, KeyCode.DEL, 0), @@ -376,16 +387,8 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction new Action(EditorActions.Tab, KeyCode.TAB, 0), new Action(EditorActions.BackTab, KeyCode.TAB, KeyFlag.Shift), - - new Action(EditorActions.ToggleReplaceMode, KeyCode.INS, 0), - new Action(EditorActions.SelectAll, KeyCode.KEY_A, KeyFlag.Control), - - new Action(EditorActions.ToggleLineComment, KeyCode.KEY_DIVIDE, KeyFlag.Control), - new Action(EditorActions.ToggleBlockComment, KeyCode.KEY_DIVIDE, KeyFlag.Control | KeyFlag.Shift), - new Action(EditorActions.DeleteLine, KeyCode.KEY_D, KeyFlag.Control), - new Action(EditorActions.DeleteLine, KeyCode.KEY_L, KeyFlag.Control), - new Action(EditorActions.InsertLine, KeyCode.RETURN, KeyFlag.Control), ]); + acceleratorMap.add(STD_EDITOR_ACTIONS); } protected MenuItem _popupMenu; @@ -1515,6 +1518,7 @@ class EditLine : EditWidgetBase { switch (a.id) { case EditorActions.InsertNewLine: case EditorActions.PrependNewLine: + case EditorActions.AppendNewLine: if (editorActionListener.assigned) { return editorActionListener(a); } @@ -2071,7 +2075,7 @@ class EditBox : EditWidgetBase { if (_content.syntaxHighlighter && _content.syntaxHighlighter.supportsToggleLineComment && _content.syntaxHighlighter.canToggleLineComment(_selectionRange)) _content.syntaxHighlighter.toggleLineComment(_selectionRange, this); return true; - case EditorActions.InsertLine: + case EditorActions.AppendNewLine: { correctCaretPos(); TextPosition p = _content.lineEnd(_caretPos.line);