diff --git a/phpgwapi/js/egw_action/egw_action.js b/phpgwapi/js/egw_action/egw_action.js index a936df9a10..af5892f5a5 100644 --- a/phpgwapi/js/egw_action/egw_action.js +++ b/phpgwapi/js/egw_action/egw_action.js @@ -1162,57 +1162,61 @@ egwActionObject.prototype.handleKeyPress = function(_keyCode, _shift, _ctrl, _al case EGW_KEY_ARROW_DOWN: case EGW_KEY_PAGE_UP: case EGW_KEY_PAGE_DOWN: - var intval = - (_keyCode == EGW_KEY_ARROW_UP || _keyCode == EGW_KEY_ARROW_DOWN) ? - 1 : 10; - if (this.children.length > 0) + if (!_shift && !_ctrl && !_alt) { - // Get the focused object - var focused = this.getFocusedObject(); + var intval = + (_keyCode == EGW_KEY_ARROW_UP || _keyCode == EGW_KEY_ARROW_DOWN) ? + 1 : 10; - // Determine the object which should get selected - var selObj = null; - if (!focused) + if (this.children.length > 0) { - selObj = this.children[0]; - } - else - { - selObj = (_keyCode == EGW_KEY_ARROW_UP || _keyCode == EGW_KEY_PAGE_UP) ? - focused.getPrevious(intval) : focused.getNext(intval); - } + // Get the focused object + var focused = this.getFocusedObject(); - if (selObj != null) - { - if (!_shift) + // Determine the object which should get selected + var selObj = null; + if (!focused) { - this.setAllSelected(false); + selObj = this.children[0]; } else { - var objs = focused.traversePath(selObj); - for (var i = 0; i < objs.length; i++) - { - objs[i].setSelected(true); - } + selObj = (_keyCode == EGW_KEY_ARROW_UP || _keyCode == EGW_KEY_PAGE_UP) ? + focused.getPrevious(intval) : focused.getNext(intval); } - selObj.setSelected(true); - selObj.setFocused(true); + if (selObj != null) + { + if (!_shift) + { + this.setAllSelected(false); + } + else + { + var objs = focused.traversePath(selObj); + for (var i = 0; i < objs.length; i++) + { + objs[i].setSelected(true); + } + } - // Tell the aoi of the object to make it visible - selObj.makeVisible(); + selObj.setSelected(true); + selObj.setFocused(true); + + // Tell the aoi of the object to make it visible + selObj.makeVisible(); + } + + return true; } - - return true; } break; // Handle CTRL-A to select all elements in the current container case EGW_KEY_A: - if (_ctrl) + if (_ctrl && !_shift && !_alt) { this.toggleAllSelected(); return true; diff --git a/phpgwapi/js/egw_action/egw_action_popup.js b/phpgwapi/js/egw_action/egw_action_popup.js index a49f3ce791..4518fd8ca1 100644 --- a/phpgwapi/js/egw_action/egw_action_popup.js +++ b/phpgwapi/js/egw_action/egw_action_popup.js @@ -62,27 +62,34 @@ function egwPopupAction(_id, _handler, _caption, _icon, _onExecute, _allowOnMult } action.set_shortcut = function(_value) { - var sc = { - "keyCode": -1, - "shift": false, - "ctrl": false, - "alt": false - } - - if (typeof _value == "number") + if (_value) { - sc.keyCode = _value; - } + var sc = { + "keyCode": -1, + "shift": false, + "ctrl": false, + "alt": false + } - if (typeof _value == "object" && _value.keyCode != "undefined") + if (typeof _value == "number") + { + sc.keyCode = _value; + } + + if (typeof _value == "object" && _value.keyCode != "undefined") + { + sc.keyCode = _value.keyCode; + sc.shift = (typeof _value.shift == "undefined") ? false : _value.shift; + sc.ctrl = (typeof _value.ctrl == "undefined") ? false : _value.ctrl; + sc.alt = (typeof _value.alt == "undefined") ? false : _value.alt; + } + + this.shortcut = sc; + } + else { - sc.keyCode = _value.keyCode; - sc.shift = (typeof _value.shift == "undefined") ? false : _value.shift; - sc.ctrl = (typeof _value.ctrl == "undefined") ? false : _value.ctrl; - sc.alt = (typeof _value.shift == "undefined") ? false : _value.alt; + this.shortcut = false; } - - this.shortcut = null; } return action; @@ -147,18 +154,61 @@ function egwPopupActionImplementation() return defaultAction; } + ai._searchShortcut = function (_key, _objs, _links) { + for (var i = 0; i < _objs.length; i++) + { + var sc = _objs[i].shortcut; + if (sc && sc.keyCode == _key.keyCode && sc.shift == _key.shift && + sc.ctrl == _key.ctrl && sc.alt == _key.alt && + _objs[i].type == "popup" && (typeof _links[_objs[i].id] == "undefined" || + _links[_objs[i].id].enabled)) + { + return _objs[i]; + } + + var obj = this._searchShortcut(_key, _objs[i].children, _links); + if (obj) { + return obj; + } + } + } + + ai._searchShortcutInLinks = function(_key, _links) { + var objs = []; + for (var k in _links) + { + if (_links[k].enabled) + { + objs.push(_links[k].actionObj); + } + } + + return ai._searchShortcut(_key, objs, _links); + } + /** * Handles a key press */ ai._handleKeyPress = function(_key, _selected, _links, _target) { + // Handle the default if (_key.keyCode == EGW_KEY_ENTER && !_key.ctrl && !_key.shift && !_key.alt) { var defaultAction = this._getDefaultLink(_links); if (defaultAction) { defaultAction.execute(_selected); - return false; + return true; } } + + // Check whether the given shortcut exists + var obj = this._searchShortcutInLinks(_key, _links); + if (obj) + { + obj.execute(_selected); + return true; + } + + return false; } /** @@ -386,6 +436,13 @@ function egwPopupActionImplementation() item.set_checkbox(link.actionObj.checkbox); item.set_checked(link.actionObj.checked); item.set_groupIndex(link.actionObj.radioGroup); + + if (link.actionObj.shortcut) + { + var sc = link.actionObj.shortcut; + item.set_shortcutCaption(egw_shortcutCaption( + sc.keyCode, sc.shift, sc.ctrl, sc.alt)); + } } item.set_data(link.actionObj); diff --git a/phpgwapi/js/egw_action/egw_keymanager.js b/phpgwapi/js/egw_action/egw_keymanager.js index 2f2d66f163..77f2679b22 100644 --- a/phpgwapi/js/egw_action/egw_keymanager.js +++ b/phpgwapi/js/egw_action/egw_keymanager.js @@ -173,7 +173,94 @@ $(document).ready(function() { }); /** - * Creates the shortcut structure + * Default key tranlation table - do not override this variable when doing + * an translation, but set the EGW_LANG_KEYS assoc array! + */ +var _egw_lang_keys_default = { + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift" +} + +_egw_lang_keys_default[EGW_KEY_DELETE] = "Del"; +_egw_lang_keys_default[EGW_KEY_TAB] = "Tab"; +_egw_lang_keys_default[EGW_KEY_ESCAPE] = "Esc"; +_egw_lang_keys_default[EGW_KEY_BACKSPACE] = "Back"; +_egw_lang_keys_default[EGW_KEY_PAGE_UP] = "Pg Up"; +_egw_lang_keys_default[EGW_KEY_PAGE_DOWN] = "Pg Down"; +_egw_lang_keys_default[EGW_KEY_ARROW_LEFT] = "Left"; +_egw_lang_keys_default[EGW_KEY_ARROW_RIGHT] = "Right"; +_egw_lang_keys_default[EGW_KEY_ARROW_DOWN] = "Down"; +_egw_lang_keys_default[EGW_KEY_ARROW_UP] = "Up"; + +function egw_lang_keys_lookup(_keyCode) { + // Special keys - search for the key translation table - if not found, + // return default names + if (typeof EGW_LANG_KEYS != "undefined") + { + return EGW_LANG_KEYS[_keyCode]; + } + + return _egw_lang_keys_default[_keyCode]; +} + +/** + * Tranlates the given key into the an string + */ +function egw_keyName(_keyCode) +{ + // Force the keyCode to be valid + _keyCode = egw_keycode_makeValid(_keyCode); + if (_keyCode == -1) + { + return ""; + } + + // Keys which can be directly translated into ASCII chars + if ((_keyCode >= EGW_KEY_0 && _keyCode <= EGW_KEY_9) || + (_keyCode >= EGW_KEY_A && _keyCode <= EGW_KEY_Z)) + { + return String.fromCharCode(_keyCode); + } + + // Function keys + if (_keyCode >= EGW_KEY_F1 && _keyCode <= EGW_KEY_F12) + { + return "F" + (_keyCode - EGW_KEY_F1 + 1); + } + + return egw_lang_keys_lookup(_keyCode); +} + +/** + * Assembles the caption of a shortcut and returns it + */ +function egw_shortcutCaption(_keyCode, _shift, _ctrl, _alt) +{ + var elems = []; + + if (_shift) + { + elems.push(egw_lang_keys_lookup("shift")); + } + + if (_ctrl) + { + elems.push(egw_lang_keys_lookup("ctrl")); + } + + if (_alt) + { + elems.push(egw_lang_keys_lookup("alt")); + } + + elems.push(egw_keyName(_keyCode)); + + return elems.join(" + "); +} + +/** + * Creates an unique key for the given shortcut */ function egw_shortcutIdx(_keyCode, _shift, _ctrl, _alt) { @@ -293,12 +380,15 @@ function egw_keyHandler(_keyCode, _shift, _ctrl, _alt) { // Execute the egw_popup key handler of the focused object if (!handled) { - !focusedObject.executeActionImplementation({"keyEvent": { - "keyCode": _keyCode, - "shift": _shift, - "ctrl": _ctrl, - "alt": _alt - }}, "popup", EGW_AO_EXEC_SELECTED); + return focusedObject.executeActionImplementation( + { + "keyEvent": { + "keyCode": _keyCode, + "shift": _shift, + "ctrl": _ctrl, + "alt": _alt + } + }, "popup", EGW_AO_EXEC_SELECTED); } return handled; diff --git a/phpgwapi/js/egw_action/egw_menu.js b/phpgwapi/js/egw_action/egw_menu.js index 52f6ac749d..fb06f5d182 100644 --- a/phpgwapi/js/egw_action/egw_menu.js +++ b/phpgwapi/js/egw_action/egw_menu.js @@ -69,7 +69,8 @@ function _egwGenMenuStructure(_elements, _parent) //TODO Implement menu item getters? if (key == "id" || key == "caption" || key == "iconUrl" || key == "checkbox" || key == "checked" || key == "groupIndex" || - key == "enabled" || key == "default" || key == "onClick") + key == "enabled" || key == "default" || key == "onClick" || + key == "hint" || key == "shortcutCaption") { item['set_' + key](obj[key]); } @@ -289,6 +290,7 @@ function egwMenuItem(_parent, _id) this.onClick = null; this["default"] = false; this.data = null; + this.shortcutCaption = null; this.children = []; this.parent = _parent; @@ -411,3 +413,8 @@ egwMenuItem.prototype.set_hint = function(_value) this.hint = _value; } +egwMenuItem.prototype.set_shortcutCaption = function(_value) +{ + this.shortcutCaption = _value; +} + diff --git a/phpgwapi/js/egw_action/egw_menu_dhtmlx.js b/phpgwapi/js/egw_action/egw_menu_dhtmlx.js index 4cae2718a0..5f3c8ac16f 100644 --- a/phpgwapi/js/egw_action/egw_menu_dhtmlx.js +++ b/phpgwapi/js/egw_action/egw_menu_dhtmlx.js @@ -126,6 +126,11 @@ egwMenuImpl.prototype._translateStructure = function(_structure, _parentId, _idC elem.iconUrl, elem.iconUrl); } + if (elem.shortcutCaption != null) + { + this.dhtmlxmenu.setHotKey(id, elem.shortcutCaption); + } + if (elem.children.length > 0) { counter += this._translateStructure(elem.children, id, (_idCnt + counter)); diff --git a/phpgwapi/js/egw_action/test/test_menu.html b/phpgwapi/js/egw_action/test/test_menu.html index 4c8a629321..11458adc8a 100644 --- a/phpgwapi/js/egw_action/test/test_menu.html +++ b/phpgwapi/js/egw_action/test/test_menu.html @@ -23,7 +23,8 @@ menu.loadStructure( "id": "file_open", "caption": "Open file...", "iconUrl": "imgs/folder.png", - "default": true + "default": true, + "shortcutCaption": "CTRL + A" }, { "caption": "-"