From d9a59440fd64e26921970dda308388979579a43b Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Mon, 10 Sep 2012 03:02:34 +0400 Subject: [PATCH] made the keyhandler mode-aware... Signed-off-by: Alex A. Naanou --- ui/TODO.otl | 7 +- ui/gallery-prototype.js | 162 ++++++++++++++++------------- ui/keybindings.js | 218 ++++++++++++++++++++++------------------ 3 files changed, 218 insertions(+), 169 deletions(-) diff --git a/ui/TODO.otl b/ui/TODO.otl index 01252ea4..5f739047 100755 --- a/ui/TODO.otl +++ b/ui/TODO.otl @@ -177,9 +177,9 @@ Priority work [X] 100% actions [X] bug: shifting up to new ribbon pushes the current row down... | before starting on a fix, need to cleanup the code from old hacks and workarounds... - [_] 37% Preview II (optional features) - [_] 0% make things modular and reusable - [_] make the keyboard handler local to selector (mode-aware) + [_] 39% Preview II (optional features) + [_] 14% make things modular and reusable + [X] make the keyboard handler local to selector (mode-aware) [_] prefix an ID to all selectors to make their actions "local" [_] avoid use of id html attr [_] avoid use of globals @@ -204,7 +204,6 @@ Priority work [_] .dblclick(...) does not work... [_] .dragable(...) does not work... [_] slideshow... - [_] make keyboard handler mode-aware... | this is needed to disable navigation keys in setup-mode, for example... [X] 100% serialization/deserialization [X] JSON loader/unloader diff --git a/ui/gallery-prototype.js b/ui/gallery-prototype.js index ac6d1175..873352cd 100755 --- a/ui/gallery-prototype.js +++ b/ui/gallery-prototype.js @@ -10,6 +10,7 @@ // - are the benefits worth the code bloat? // + var ImageGrid = { // this can be serialized... // NOTE: to load a serialized set of options use ImageGrid.set(options)... @@ -524,6 +525,8 @@ function toKeyName(code){ // XXX this must create it's own overlay... function showInOverlay(obj){ obj.click(function(){ return false }) + // XXX + $('.viewer').addClass('overlay-mode') // clean things up... $('.overlay .content').children().remove() // put it in the overlay... @@ -536,6 +539,7 @@ function showInOverlay(obj){ $('.overlay .content') .children() .remove() + $('.overlay-mode').removeClass('overlay-mode') }) }) .fadeIn() @@ -1113,10 +1117,10 @@ function setupEvents(){ // keyboard... if(DEBUG){ $(document) - .keydown(makeKeyboardHandler(keybindings, ignorekeys, function(k){alert(k)})) + .keydown(makeKeyboardHandler(keybindings, function(k){alert(k)})) } else { $(document) - .keydown(makeKeyboardHandler(keybindings, ignorekeys)) + .keydown(makeKeyboardHandler(keybindings)) } // swipe... $('.viewer') @@ -1474,52 +1478,58 @@ var KEYBOARD_HANDLER_PROPAGATE = false * * XXX might need to add meta information to generate sensible help... */ -function makeKeyboardHandler(keybindings, ignore, unhandled){ +function makeKeyboardHandler(keybindings, unhandled){ if(unhandled == null){ unhandled = function(){return false} } return function(evt){ - var key = evt.keyCode - if(ignore != null && ignore.indexOf(key) != -1){ - return true - } - // XXX ugly... - var modifers = evt.ctrlKey ? 'ctrl' : '' - modifers += evt.altKey ? (modifers != '' ? '+alt' : 'alt') : '' - modifers += evt.shiftKey ? (modifers != '' ? '+shift' : 'shift') : '' + for(var mode in keybindings){ + if($(mode).length > 0){ + var bindings = keybindings[mode] - var handler = keybindings[key] + var key = evt.keyCode + if(bindings.ignore != null && bindings.ignore.indexOf(key) != -1){ + return true + } + // XXX ugly... + var modifers = evt.ctrlKey ? 'ctrl' : '' + modifers += evt.altKey ? (modifers != '' ? '+alt' : 'alt') : '' + modifers += evt.shiftKey ? (modifers != '' ? '+shift' : 'shift') : '' - // alias... - while (typeof(handler) == typeof(123)) { - handler = keybindings[handler] - } - // no handler... - if(handler == null){ - return unhandled(key) - } - // Array, lisp style with docs... - // XXX for some odd reason in chrome typeof([]) == typeof({})!!! - if(typeof(handler) == typeof([]) && handler.constructor.name == 'Array'){ - // we do not care about docs here, so just get the handler... - handler = handler[0] - } - // complex handler... - if(typeof(handler) == typeof({})){ - var callback = handler[modifers] - if(callback == null){ - callback = handler['default'] + var handler = bindings[key] + + // alias... + while (typeof(handler) == typeof(123)) { + handler = bindings[handler] + } + // no handler... + if(handler == null){ + return unhandled(key) + } + // Array, lisp style with docs... + // XXX for some odd reason in chrome typeof([]) == typeof({})!!! + if(typeof(handler) == typeof([]) && handler.constructor.name == 'Array'){ + // we do not care about docs here, so just get the handler... + handler = handler[0] + } + // complex handler... + if(typeof(handler) == typeof({})){ + var callback = handler[modifers] + if(callback == null){ + callback = handler['default'] + } + if(callback != null){ + var res = callback() + return KEYBOARD_HANDLER_PROPAGATE&&res?true:false + } + } else { + // simple callback... + var res = handler() + return KEYBOARD_HANDLER_PROPAGATE&&res?true:false + } + return unhandled(key) } - if(callback != null){ - var res = callback() - return KEYBOARD_HANDLER_PROPAGATE&&res?true:false - } - } else { - // simple callback... - var res = handler() - return KEYBOARD_HANDLER_PROPAGATE&&res?true:false } - return unhandled(key) } } @@ -1642,6 +1652,7 @@ ImageGrid.GROUP('Configuration and Help', }, function(e){return e.click_handler}) }), + // XXX do not use global keybindings... ImageGrid.ACTION({ title: 'Keyboard configuration', doc: 'Show keyboard configuration interface.', @@ -1649,39 +1660,52 @@ ImageGrid.GROUP('Configuration and Help', function showKeyboardBindings(){ // build reverse key index... var bindings = {} - for(var k in keybindings){ - var id - var v = keybindings[k] + for(var m in keybindings){ + var mode_bindings = keybindings[m] - // alias... - while (typeof(v) == typeof(123)) { - v = keybindings[v] - } - // Array, lisp style with docs... - if(typeof(v) == typeof([]) && v.constructor.name == 'Array'){ - // XXX what do we do here??? - } - // function... - if(typeof(v) == typeof(function(){})){ - id = v.id != null ? v.id : v.name - } - // complex handler... - // NOTE: this can contain several key bindings... - if(typeof(v) == typeof({})){ - for(var m in v){ - id = v[m].id != null ? v[m].id : v[m].name - if(bindings[id] == null){ - bindings[id] = [] - } - bindings[id].push((m=='default'?'':m+'+') + toKeyName(k)) + // XXX do the doc for the mode... + // XXX + + for(var k in mode_bindings){ + // XXX skip doc attrs... + if(k == 'title' || k == 'doc' || k == 'ignore'){ + continue } - continue + + var id + var v = mode_bindings[k] + + // alias... + while (typeof(v) == typeof(123)) { + v = mode_bindings[v] + } + // Array, lisp style with docs... + if(typeof(v) == typeof([]) && v.constructor.name == 'Array'){ + // XXX what do we do here??? + } + // function... + if(typeof(v) == typeof(function(){})){ + id = v.id != null ? v.id : v.name + } + // complex handler... + // NOTE: this can contain several key bindings... + if(typeof(v) == typeof({})){ + for(var m in v){ + id = v[m].id != null ? v[m].id : v[m].name + if(bindings[id] == null){ + bindings[id] = [] + } + bindings[id].push((m=='default'?'':m+'+') + toKeyName(k)) + } + continue + } + + if(bindings[id] == null){ + bindings[id] = [] + } + bindings[id].push(toKeyName(k)) } - if(bindings[id] == null){ - bindings[id] = [] - } - bindings[id].push(toKeyName(k)) } showOptionsUI(ImageGrid.actions, function(e){ diff --git a/ui/keybindings.js b/ui/keybindings.js index cb4f359f..23fe8387 100755 --- a/ui/keybindings.js +++ b/ui/keybindings.js @@ -1,110 +1,136 @@ /*********************************************************************/ // NOTE: use String.fromCharCode(code)... // list of keys to be ignored by handler but still handled by the browser... -var ignorekeys = [ - 116, // F5 - 123, // F12 -] var keybindings = { - // togglable modes and options... - 191: { - 'default': ImageGrid.showKeyboardBindings, // ? - 'ctrl': ImageGrid.showSetup, // ctrl+? + '.overlay-mode': { + title: 'Overlay mode', + doc: 'overlay mode key bindings.', + + ignore: [ + 37, // Left + 39, // Right + 36, // Home + 32, // Space + 35, // End + 38, // Up + 40, // Down + ], + + 27: ImageGrid.closeOverlay, // Esc }, - 80: ImageGrid.showSetup, // p - 70: ImageGrid.toggleSingleImageMode, // f - 13: 70, // Enter - 83: ImageGrid.toggleSingleRibbonMode, // s - 84: ImageGrid.toggleSingleImageModeTransitions, // t - 65: ImageGrid.toggleTransitions, // a - 9: ImageGrid.toggleControls, // tab - 66: ImageGrid.toggleBackgroundModes, // b - 73: ImageGrid.toggleCurrentRibbonOpacity, // i - 77: toggleMarkers, // m - 87: ImageGrid.saveState, // w - 27: ImageGrid.closeOverlay, // Esc + //'*': { + // everything except overlays... + '.viewer *:not(.overlay-mode *)': { + title: 'ALL', + doc: 'global key bindings.', - // zooming... - 187: ImageGrid.scaleContainerUp, // + - 189: ImageGrid.scaleContainerDown, // - - // zoom presets... - 48: { - 'default': ImageGrid.centerCurrentImage, // 0 + ignore: [ + 116, // F5 + 123, // F12 + ], + + // togglable modes and options... + 191: { + 'default': ImageGrid.showKeyboardBindings, // ? + 'ctrl': ImageGrid.showSetup, // ctrl+? + }, + 80: ImageGrid.showSetup, // p + 70: ImageGrid.toggleSingleImageMode, // f + 13: 70, // Enter + 83: ImageGrid.toggleSingleRibbonMode, // s + 84: ImageGrid.toggleSingleImageModeTransitions, // t + 65: ImageGrid.toggleTransitions, // a + 9: ImageGrid.toggleControls, // tab + 66: ImageGrid.toggleBackgroundModes, // b + 73: ImageGrid.toggleCurrentRibbonOpacity, // i + 77: toggleMarkers, // m + + 87: ImageGrid.saveState, // w + + 27: ImageGrid.closeOverlay, // Esc + + // zooming... + 187: ImageGrid.scaleContainerUp, // + + 189: ImageGrid.scaleContainerDown, // - + // zoom presets... + 48: { + 'default': ImageGrid.centerCurrentImage, // 0 + // XXX make this into a real action... + 'ctrl': ImageGrid.fitImage, // ctrl+0 + }, + 49: ImageGrid.fitImage, // 1 + 50: ImageGrid.fitTwoImages, // 2 + 51: ImageGrid.fitThreeImages, // 3 + 52: ImageGrid.fitFourImages, // 4 + 53: ImageGrid.fitFiveImages, // 5 + 54: ImageGrid.fitSixImages, // 6 + 55: ImageGrid.fitSevenImages, // 7 + 56: ImageGrid.fitEightImages, // 8 + 57: ImageGrid.fitNineImages, // 9 + + + // navigation... + 36: ImageGrid.firstImage, // Home + 219: 36, // [ + 35: ImageGrid.lastImage, // End + 221: 35, // ] + 37: { + 'default': ImageGrid.prevImage, // Right + 'ctrl': ImageGrid.prevScreenImages, // ctrl-Right + 'alt': ImageGrid.prevScreenImages, // alt-Right + }, + 8: 37, // BkSp + 188: 37, // < + 39: { + 'default': ImageGrid.nextImage, // Left + 'ctrl': ImageGrid.nextScreenImages, // ctrl-Left + 'alt': ImageGrid.nextScreenImages, // alt-Left + }, + 32: 39, // Space + 190: 39, // > + 186: ImageGrid.prevScreenImages, // ; + 222: ImageGrid.nextScreenImages, // ' + // move view... + // XXX should these be s-up, s-down, ... ?? + 75: ImageGrid.moveViewUp, // k + 74: ImageGrid.moveViewDown, // j + 72: ImageGrid.moveViewLeft, // h + 76: ImageGrid.moveViewRight, // l + // XXX use this to open... + //79: ImageGrid.centerCurrentImage, // o + + + // combined navigation with actions.. + 38: { + 'default': ImageGrid.focusAboveRibbon, // Up + 'shift': ImageGrid.shiftImageUp, // shift-Up + 'ctrl+shift': ImageGrid.shiftImageUpNewRibbon // ctrl-shift-Up + }, + 40: { + 'default': ImageGrid.focusBelowRibbon, // Down + 'shift': ImageGrid.shiftImageDown, // shift-Down + 'ctrl+shift': ImageGrid.shiftImageDownNewRibbon // ctrl-shift-Down + }, + + // misc actions... + 82: ImageGrid.reverseImageOrder, // r + + + // ignore the modifiers (shift, alt, ctrl, caps)... + 16: function(){}, + 17: 16, + 18: 16, + 20: 16, // Caps Lock + + // refresh... // XXX make this into a real action... - 'ctrl': ImageGrid.fitImage, // ctrl+0 - }, - 49: ImageGrid.fitImage, // 1 - 50: ImageGrid.fitTwoImages, // 2 - 51: ImageGrid.fitThreeImages, // 3 - 52: ImageGrid.fitFourImages, // 4 - 53: ImageGrid.fitFiveImages, // 5 - 54: ImageGrid.fitSixImages, // 6 - 55: ImageGrid.fitSevenImages, // 7 - 56: ImageGrid.fitEightImages, // 8 - 57: ImageGrid.fitNineImages, // 9 - - - // navigation... - 36: ImageGrid.firstImage, // Home - 219: 36, // [ - 35: ImageGrid.lastImage, // End - 221: 35, // ] - 37: { - 'default': ImageGrid.prevImage, // Right - 'ctrl': ImageGrid.prevScreenImages, // ctrl-Right - 'alt': ImageGrid.prevScreenImages, // alt-Right - }, - 8: 37, // BkSp - 188: 37, // < - 39: { - 'default': ImageGrid.nextImage, // Left - 'ctrl': ImageGrid.nextScreenImages, // ctrl-Left - 'alt': ImageGrid.nextScreenImages, // alt-Left - }, - 32: 39, // Space - 190: 39, // > - 186: ImageGrid.prevScreenImages, // ; - 222: ImageGrid.nextScreenImages, // ' - // move view... - // XXX should these be s-up, s-down, ... ?? - 75: ImageGrid.moveViewUp, // k - 74: ImageGrid.moveViewDown, // j - 72: ImageGrid.moveViewLeft, // h - 76: ImageGrid.moveViewRight, // l - // XXX use this to open... - //79: ImageGrid.centerCurrentImage, // o - - - // combined navigation with actions.. - 40: { - 'default': ImageGrid.focusBelowRibbon, // Down - 'shift': ImageGrid.shiftImageDown, // shift-Down - 'ctrl+shift': ImageGrid.shiftImageDownNewRibbon // ctrl-shift-Down - }, - 38: { - 'default': ImageGrid.focusAboveRibbon, // Up - 'shift': ImageGrid.shiftImageUp, // shift-Up - 'ctrl+shift': ImageGrid.shiftImageUpNewRibbon // ctrl-shift-Up - }, - - // misc actions... - 82: ImageGrid.reverseImageOrder, // r - - - // ignore the modifiers (shift, alt, ctrl, caps)... - 16: function(){}, - 17: 16, - 18: 16, - 20: 16, // Caps Lock - - // refresh... - // XXX make this into a real action... - 116: function(){ return DEBUG?true:false }, // F5 - 112: 116, // F12 + 116: function(){ return DEBUG?true:false }, // F5 + 112: 116, // F12 + } }