1
0
Fork 0

Added real keyboard shortcut support for menu items

This commit is contained in:
TheFGFSEagle 2023-01-08 15:35:46 +01:00 committed by James Turner
parent 66fcfce8af
commit 2cf388e674
6 changed files with 77 additions and 35 deletions

View file

@ -16,10 +16,35 @@ var Element = {
var obj = {
parents: [Element, PropertyElement, ghost],
_node: props.wrapNode(ghost._node_ghost),
_bindings: [],
};
return obj;
},
bindShortcut: func(s, f) {
if (!isa(s, keyboard.Shortcut)) {
s = keyboard.Shortcut.new(s);
}
foreach (var b; me._bindings) {
if (b.shortcut.equals(s)) {
b.f = f;
return;
}
}
append(me._bindings, keyboard.Binding.new(s, f));
if (size(me._bindings) == 1) {
obj.addEventListener("keydown", func(e) obj.onKeyPressed(e));
}
},
onKeyPressed: func(e) {
foreach (var b; me._bindings) {
if (b.shortcut.match(keyboard.findKeyName(e.keyCode), e.shiftKey, e.ctrlKey, e.altKey, e.metaKey)) {
b.fire(e);
}
}
},
getType: func () {
return me._node.getName();
},

View file

@ -16,7 +16,7 @@
gui.MenuItem = {
# @description Create a new menu item widget
# @cfg_field text: str Text of the new menu item
# @cfg_field shortcut: str String representation of the keyboard shortcut for the item
# @cfg_field shortcut: str String representation of the keyboard shortcut for the item
# @cfg_field cb: callable Function / method to call when the item is clicked
# @cfg_field icon: str Path of an icon to be displayed (relative to the path in `canvas.style._dir_widgets`)
# @cfg_field enabled: bool Initial state of the menu item: enabled (1) or disabled (0)
@ -24,7 +24,7 @@ gui.MenuItem = {
var cfg = Config.new(cfg);
var m = gui.Widget.new(gui.MenuItem);
m._text = cfg.get("text", "Menu item");
m._shortcut = cfg.get("shortcut", "");
m._shortcut = cfg.get("shortcut", nil);
m._cb = cfg.get("cb", nil);
m._icon = cfg.get("icon", nil);
m._enabled = cfg.get("enabled", 1);
@ -38,9 +38,9 @@ gui.MenuItem = {
m.setLayoutSizeHint([64, 24]);
m.setLayoutMaximumSize([1024, 24]);
m._view.setText(m, m._text);
m._view.setIcon(m._icon);
m._view.setShortcut(m, m._shortcut);
m.setText(m._text);
m.setIcon(m._icon);
m.setShortcut(m._shortcut);
return m;
},
@ -110,11 +110,21 @@ gui.MenuItem = {
},
setShortcut: func(shortcut) {
me._shortcut = shortcut;
me._view.setShortcut(me, shortcut);
me._shortcut = keyboard.Shortcut.new(shortcut);
if (me._parent_menu != nil and me._parent_menu._canvas_item != nil and me._cb != nil) {
me._parent_menu._canvas_item.bindShortcut(me._shortcut, me._cb);
}
me._view.setShortcut(me, me._shortcut);
return me.update();
},
_setParentMenu: func(m) {
me._parent_menu = m;
if (me._parent_menu != nil and me._parent_menu._canvas_item != nil and me._cb != nil) {
me._parent_menu._canvas_item.bindShortcut(me._shortcut, me._cb);
}
},
setIcon: func(icon) {
me._icon = icon;
me._view.setIcon(icon);
@ -153,16 +163,24 @@ gui.Menu = {
m._root = m._canvas.createGroup();
m._layout = VBoxLayout.new();
m._layout.setSpacing(0);
m._canvas_item = nil;
m.setLayout(m._layout);
m.hide();
return m;
},
setCanvasItem: func(item) {
me._canvas_item = item;
for (var i = 0; i < me._layout.count(); i += 1) {
me._layout.itemAt(i)._setParentMenu(me);
}
},
# @description Add the given menu item to the menu (normally a `canvas.gui.MenuItem`, but can be any `canvas.gui.Widget` in theory)
# @return canvas.gui.Menu Return me to enable method chaining
addItem: func(item) {
item._parent_menu = me;
item._setParentMenu(me);
me._layout.addItem(item);
me.setSize(me._layout.minimumSize()[0], me._layout.minimumSize()[1]);
return me;
@ -175,7 +193,7 @@ gui.Menu = {
# @param icon: str optional Path to the icon (relative to canvas.style._dir_widgets) or nil if none should be displayed
# @param enabled: bool optional Whether the item should be enabled (1) or disabled (0)
# @return canvas.gui.MenuItem The item that was created
createItem: func(text = nil, cb = nil, shortcut = "", icon = nil, enabled = 1) {
createItem: func(text = nil, cb = nil, shortcut = nil, icon = nil, enabled = 1) {
if (text == nil) {
die("cannot create a menu item without text");
}
@ -198,7 +216,7 @@ gui.Menu = {
if (menu == nil) {
die("cannot create a submenu item without submenu");
}
var item = gui.MenuItem.new(me._root, me.style, {text: text, cb: nil, shortcut: "", icon: icon, enabled: enabled});
var item = gui.MenuItem.new(me._root, me.style, {text: text, cb: nil, shortcut: nil, icon: icon, enabled: enabled});
item.setMenu(menu);
me.addItem(item);
return item;

View file

@ -141,6 +141,9 @@ gui.Widget = {
{
me._view._root.setVisible(visible);
},
bindShortcut: func(s, f) {
me._view._root.bindShortcut(s, f);
},
_setView: func(view)
{
me._view = view;
@ -170,6 +173,11 @@ gui.Widget = {
me._trigger("mouse-leave");
me._onStateChange();
});
root.addEventListener("keypress", func(e) {
if (me._focused) {
root.onKeyPressed(e);
}
});
},
_trigger: func(type, data = nil)
{

View file

@ -900,7 +900,7 @@ DefaultStyle.widgets["menu-item"] = {
},
setShortcut: func(model, shortcut) {
me._shortcut.setText(shortcut);
me._shortcut.setText(shortcut.repr());
return me._updateLayoutSizes(model);
},

View file

@ -16,11 +16,12 @@ gui.widgets.LineEdit = {
m._selection_end = 0;
m.context_menu = gui.Menu.new();
m.context_menu.createItem(text: "Copy", cb: func() { m.copy(); }, shortcut: "Ctrl+C");
m.context_menu.createItem(text: "Cut", cb: func() { m.cut(); }, shortcut: "Ctrl+X");
m.context_menu.createItem(text: "Paste", cb: func() { m.paste(); }, shortcut: "Ctrl+V");
m.context_menu.createItem(text: "Clear", cb: func() { m.clear(); }, shortcut: "Ctrl+D");
m.context_menu.createItem(text: "Select all", cb: func() { m.selectAll(); }, shortcut: "Ctrl+A");
m.context_menu.createItem(text: "Copy", cb: func() { m.copy(); }, shortcut: "<Ctrl>+C");
m.context_menu.createItem(text: "Cut", cb: func() { m.cut(); }, shortcut: "<Ctrl>+X");
m.context_menu.createItem(text: "Paste", cb: func() { m.paste(); }, shortcut: "<Ctrl>+V");
m.context_menu.createItem(text: "Clear", cb: func() { m.clear(); }, shortcut: "<Ctrl>+D");
m.context_menu.createItem(text: "Select all", cb: func() { m.selectAll(); }, shortcut: "<Ctrl>+A");
m.context_menu.setCanvasItem(m);
return m;
},
@ -182,7 +183,11 @@ gui.widgets.LineEdit = {
call(gui.Widget._setView, [view], me);
var el = view._root;
el.addEventListener("keypress", func (e) me.insert(e.key));
el.addEventListener("keypress", func (e) {
if (!e.ctrlKey and !e.altKey and !e.metaKey) {
me.insert(e.key);
}
});
el.addEventListener("keydown", func (e)
{
if( me._view == nil )
@ -202,19 +207,6 @@ gui.widgets.LineEdit = {
me.home();
else if( e.key == "End" )
me.end();
else if (e.ctrlKey) {
if (e.keyCode == `c`) {
me.copy();
} elsif (e.keyCode == `v`) {
me.paste();
} elsif (e.keyCode == `x`) {
me.cut();
} elsif (e.keyCode == `d`) {
me.clear();
} elsif (e.keyCode == `a`) {
me.selectAll();
}
}
});
el.addEventListener("click", func(e) {
if (e.button == 2) {

View file

@ -357,10 +357,10 @@ var Shortcut = {
return 0;
}
var match = 1;
match &= veccontains(me.modifiers, ModifierKeys["Shift"]) == shift;
match &= veccontains(me.modifiers, ModifierKeys["Ctrl"]) == ctrl;
match &= veccontains(me.modifiers, ModifierKeys["Alt"]) == alt;
match &= veccontains(me.modifiers, ModifierKeys["Meta"]) == meta;
match &= contains(me.modifiers, ModifierKeys["Shift"]) == shift;
match &= contains(me.modifiers, ModifierKeys["Ctrl"]) == ctrl;
match &= contains(me.modifiers, ModifierKeys["Alt"]) == alt;
match &= contains(me.modifiers, ModifierKeys["Meta"]) == meta;
match &= size(keys) == size(me.keys);
if (!match) {
return 0;
@ -376,7 +376,6 @@ var Shortcut = {
return "";
}
var names = [];
debug.dump(me.modifiers);
foreach (var mod; me.modifiers) {
append(names, findKeyName(mod));
}