mirror of https://github.com/buggins/dlangui.git
configurable shortcuts - issue #59
This commit is contained in:
parent
009e0ec21c
commit
8208f43049
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue