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;
|
return cast(dstring)buf;
|
||||||
}
|
}
|
||||||
/// Serializes accelerator text description
|
/// Serializes accelerator text description
|
||||||
@property string toString() {
|
@property string toString() const {
|
||||||
char[] buf;
|
char[] buf;
|
||||||
if (keyFlags & KeyFlag.Control)
|
if (keyFlags & KeyFlag.Control)
|
||||||
buf ~= "Ctrl+";
|
buf ~= "Ctrl+";
|
||||||
|
@ -246,13 +246,21 @@ class Action {
|
||||||
@property Accelerator[] accelerators() {
|
@property Accelerator[] accelerators() {
|
||||||
// check for accelerators override in settings
|
// check for accelerators override in settings
|
||||||
Accelerator[] res = findActionAccelerators(_id);
|
Accelerator[] res = findActionAccelerators(_id);
|
||||||
if (res)
|
if (res) {
|
||||||
|
//Log.d("Found accelerators ", res);
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
// return this action accelerators
|
// return this action accelerators
|
||||||
return _accelerators;
|
return _accelerators;
|
||||||
}
|
}
|
||||||
/// returs const array of accelerators
|
/// returs const array of accelerators
|
||||||
@property const(Accelerator)[] accelerators() const {
|
@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;
|
return _accelerators;
|
||||||
}
|
}
|
||||||
/// returns text description for first accelerator of action; null if no 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 "Down": return KeyCode.DOWN;
|
||||||
case "Ins": return KeyCode.DEL;
|
case "Ins": return KeyCode.DEL;
|
||||||
case "Del": return KeyCode.INS;
|
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:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1241,6 +1254,14 @@ string keyName(uint keyCode) {
|
||||||
return "Ins";
|
return "Ins";
|
||||||
case KeyCode.DEL:
|
case KeyCode.DEL:
|
||||||
return "Del";
|
return "Del";
|
||||||
|
case KeyCode.KEY_BRACKETOPEN:
|
||||||
|
return "[";
|
||||||
|
case KeyCode.KEY_BRACKETCLOSE:
|
||||||
|
return "]";
|
||||||
|
case KeyCode.BACK:
|
||||||
|
return "Backspace";
|
||||||
|
case KeyCode.RETURN:
|
||||||
|
return "Enter";
|
||||||
default:
|
default:
|
||||||
return format("0x%08x", keyCode);
|
return format("0x%08x", keyCode);
|
||||||
}
|
}
|
||||||
|
@ -1313,8 +1334,8 @@ void setActionAccelerators(int actionId, Accelerator[] accelerators) {
|
||||||
}
|
}
|
||||||
/// lookup accelerators override for action by id
|
/// lookup accelerators override for action by id
|
||||||
Accelerator[] findActionAccelerators(int actionId) {
|
Accelerator[] findActionAccelerators(int actionId) {
|
||||||
if (auto found = actionAcceleratorsMap[actionId])
|
if (auto found = actionId in actionAcceleratorsMap)
|
||||||
return found;
|
return *found;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/// lookup accelerators override for action by name (e.g. "EditorActions.ToggleLineComment")
|
/// lookup accelerators override for action by name (e.g. "EditorActions.ToggleLineComment")
|
||||||
|
|
|
@ -64,7 +64,7 @@ class SettingsFile {
|
||||||
_setting = new Setting();
|
_setting = new Setting();
|
||||||
_filename = filename;
|
_filename = filename;
|
||||||
if (_filename) {
|
if (_filename) {
|
||||||
string dir = baseName(_filename);
|
string dir = dirName(_filename);
|
||||||
if (load()) {
|
if (load()) {
|
||||||
// loaded ok
|
// loaded ok
|
||||||
} else {
|
} else {
|
||||||
|
@ -114,7 +114,7 @@ class SettingsFile {
|
||||||
if (filename !is null)
|
if (filename !is null)
|
||||||
_filename = filename;
|
_filename = filename;
|
||||||
assert(_filename);
|
assert(_filename);
|
||||||
string dir = baseName(_filename);
|
string dir = dirName(_filename);
|
||||||
if (!dir.exists) {
|
if (!dir.exists) {
|
||||||
try {
|
try {
|
||||||
mkdirRecurse(dir);
|
mkdirRecurse(dir);
|
||||||
|
@ -170,6 +170,16 @@ final class Setting {
|
||||||
_store.array.list = v;
|
_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
|
/// returns true if setting has been changed
|
||||||
@property bool changed() {
|
@property bool changed() {
|
||||||
return _changed;
|
return _changed;
|
||||||
|
@ -920,10 +930,6 @@ final class Setting {
|
||||||
double opAssign(double value) {
|
double opAssign(double value) {
|
||||||
return (floating = value);
|
return (floating = value);
|
||||||
}
|
}
|
||||||
// assign string[] value
|
|
||||||
string[] opAssign(string[] value) {
|
|
||||||
return (strArray = value);
|
|
||||||
}
|
|
||||||
// assign int[] value
|
// assign int[] value
|
||||||
int[] opAssign(int[] value) {
|
int[] opAssign(int[] value) {
|
||||||
return (intArray = value);
|
return (intArray = value);
|
||||||
|
@ -932,6 +938,10 @@ final class Setting {
|
||||||
string[string] opAssign(string[string] value) {
|
string[string] opAssign(string[string] value) {
|
||||||
return (strMap = value);
|
return (strMap = value);
|
||||||
}
|
}
|
||||||
|
// assign string[] value
|
||||||
|
string[] opAssign(string[] value) {
|
||||||
|
return (strArray = value);
|
||||||
|
}
|
||||||
// assign int[string] value
|
// assign int[string] value
|
||||||
int[string] opAssign(int[string] value) {
|
int[string] opAssign(int[string] value) {
|
||||||
return (intMap = 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
|
/// override to return some identifier for app, e.g. to use as settings directory name
|
||||||
@property string appCodeName() {
|
@property string appCodeName() {
|
||||||
return _appName;
|
return _appName;
|
||||||
|
@ -121,18 +121,20 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
|
||||||
for (int i = 0; i < value.length; i++) {
|
for (int i = 0; i < value.length; i++) {
|
||||||
string v = value[i].str;
|
string v = value[i].str;
|
||||||
Accelerator a;
|
Accelerator a;
|
||||||
if (a.parse(v))
|
if (a.parse(v)) {
|
||||||
|
//Log.d("Read accelerator for action ", key, " : ", a.toString);
|
||||||
accelerators ~= a;
|
accelerators ~= a;
|
||||||
else
|
} else
|
||||||
Log.e("cannot parse accelerator: ", v);
|
Log.e("applyShortcutsSettings: cannot parse accelerator: ", v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
string v = value.str;
|
string v = value.str;
|
||||||
Accelerator a;
|
Accelerator a;
|
||||||
if (a.parse(v))
|
if (a.parse(v)) {
|
||||||
|
//Log.d("Read accelerator for action ", key, " : ", a.toString);
|
||||||
accelerators ~= a;
|
accelerators ~= a;
|
||||||
else
|
} else
|
||||||
Log.e("cannot parse accelerator: ", v);
|
Log.e("applyShortcutsSettings: cannot parse accelerator: ", v);
|
||||||
}
|
}
|
||||||
setActionAccelerators(actionId, accelerators);
|
setActionAccelerators(actionId, accelerators);
|
||||||
}
|
}
|
||||||
|
@ -148,7 +150,7 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
|
||||||
foreach(a; actions) {
|
foreach(a; actions) {
|
||||||
string name = actionIdToName(a.id);
|
string name = actionIdToName(a.id);
|
||||||
if (name) {
|
if (name) {
|
||||||
Accelerator[] acc = findActionAccelerators(a.id);
|
const(Accelerator)[] acc = a.accelerators;
|
||||||
if (acc.length > 0) {
|
if (acc.length > 0) {
|
||||||
if (acc.length == 1) {
|
if (acc.length == 1) {
|
||||||
_shortcutSettings[name] = acc[0].toString;
|
_shortcutSettings[name] = acc[0].toString;
|
||||||
|
@ -212,6 +214,7 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
|
||||||
super("APP_FRAME");
|
super("APP_FRAME");
|
||||||
layoutWidth = FILL_PARENT;
|
layoutWidth = FILL_PARENT;
|
||||||
layoutHeight = FILL_PARENT;
|
layoutHeight = FILL_PARENT;
|
||||||
|
_appName = "dlangui";
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +243,11 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler {
|
||||||
addChild(_body);
|
addChild(_body);
|
||||||
if (_statusLine)
|
if (_statusLine)
|
||||||
addChild(_statusLine);
|
addChild(_statusLine);
|
||||||
|
updateShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// override it
|
||||||
|
protected void updateShortcuts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// override to handle main menu commands
|
/// override to handle main menu commands
|
||||||
|
|
|
@ -113,9 +113,11 @@ enum EditorActions : int {
|
||||||
|
|
||||||
/// insert new line (Enter)
|
/// insert new line (Enter)
|
||||||
InsertNewLine,
|
InsertNewLine,
|
||||||
/// insert new line after current position (Ctrl+Enter)
|
/// insert new line before current position (Ctrl+Enter)
|
||||||
PrependNewLine,
|
PrependNewLine,
|
||||||
|
/// insert new line after current position (Ctrl+Enter)
|
||||||
|
AppendNewLine,
|
||||||
|
|
||||||
/// Turn On/Off replace mode
|
/// Turn On/Off replace mode
|
||||||
ToggleReplaceMode,
|
ToggleReplaceMode,
|
||||||
|
|
||||||
|
@ -178,6 +180,19 @@ __gshared static this() {
|
||||||
registerActionEnum!EditorActions();
|
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
|
/// base for all editor widgets
|
||||||
class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemActionHandler {
|
class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemActionHandler {
|
||||||
protected EditableContent _content;
|
protected EditableContent _content;
|
||||||
|
@ -348,10 +363,6 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction
|
||||||
new Action(EditorActions.ScrollLineUp, KeyCode.UP, KeyFlag.Control),
|
new Action(EditorActions.ScrollLineUp, KeyCode.UP, KeyFlag.Control),
|
||||||
new Action(EditorActions.ScrollLineDown, KeyCode.DOWN, 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
|
// Backspace/Del
|
||||||
new Action(EditorActions.DelPrevChar, KeyCode.BACK, 0),
|
new Action(EditorActions.DelPrevChar, KeyCode.BACK, 0),
|
||||||
new Action(EditorActions.DelNextChar, KeyCode.DEL, 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.Tab, KeyCode.TAB, 0),
|
||||||
new Action(EditorActions.BackTab, KeyCode.TAB, KeyFlag.Shift),
|
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;
|
protected MenuItem _popupMenu;
|
||||||
|
@ -1515,6 +1518,7 @@ class EditLine : EditWidgetBase {
|
||||||
switch (a.id) {
|
switch (a.id) {
|
||||||
case EditorActions.InsertNewLine:
|
case EditorActions.InsertNewLine:
|
||||||
case EditorActions.PrependNewLine:
|
case EditorActions.PrependNewLine:
|
||||||
|
case EditorActions.AppendNewLine:
|
||||||
if (editorActionListener.assigned) {
|
if (editorActionListener.assigned) {
|
||||||
return editorActionListener(a);
|
return editorActionListener(a);
|
||||||
}
|
}
|
||||||
|
@ -2071,7 +2075,7 @@ class EditBox : EditWidgetBase {
|
||||||
if (_content.syntaxHighlighter && _content.syntaxHighlighter.supportsToggleLineComment && _content.syntaxHighlighter.canToggleLineComment(_selectionRange))
|
if (_content.syntaxHighlighter && _content.syntaxHighlighter.supportsToggleLineComment && _content.syntaxHighlighter.canToggleLineComment(_selectionRange))
|
||||||
_content.syntaxHighlighter.toggleLineComment(_selectionRange, this);
|
_content.syntaxHighlighter.toggleLineComment(_selectionRange, this);
|
||||||
return true;
|
return true;
|
||||||
case EditorActions.InsertLine:
|
case EditorActions.AppendNewLine:
|
||||||
{
|
{
|
||||||
correctCaretPos();
|
correctCaretPos();
|
||||||
TextPosition p = _content.lineEnd(_caretPos.line);
|
TextPosition p = _content.lineEnd(_caretPos.line);
|
||||||
|
|
Loading…
Reference in New Issue