configurable shortcuts - issue #59

This commit is contained in:
Vadim Lopatin 2015-02-16 12:06:43 +03:00
parent 009e0ec21c
commit 8208f43049
4 changed files with 78 additions and 35 deletions

View File

@ -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")

View File

@ -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);

View File

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

View File

@ -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);