From 664743a975555f82d9fc55d32f42c507bc066ac4 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 11 Jan 2017 01:32:42 +0300 Subject: [PATCH] started leanup... Signed-off-by: Alex A. Naanou --- ui (gen4)/features/keyboard.js | 410 ++------------------------------- ui (gen4)/lib/keyboard2.js | 139 +++++++---- 2 files changed, 107 insertions(+), 442 deletions(-) diff --git a/ui (gen4)/features/keyboard.js b/ui (gen4)/features/keyboard.js index 55796e9d..e595e764 100755 --- a/ui (gen4)/features/keyboard.js +++ b/ui (gen4)/features/keyboard.js @@ -10,7 +10,8 @@ var actions = require('lib/actions') var features = require('lib/features') var toggler = require('lib/toggler') -var keyboard = require('lib/keyboard') +// XXX +var keyboard = require('lib/keyboard2') var core = require('features/core') var widgets = require('features/ui-widgets') @@ -24,393 +25,7 @@ var drawer = require('lib/widget/drawer') /*********************************************************************/ -// helper... -function customScale(n){ - return { - default: 'fitCustom: '+n+' -- Set cutom image size', - 'alt': 'setCustomSize: '+n+' -- Set current image size as custom', - 'ctrl+shift': 'setCustomSize: '+n+' null -- Clear custom image size', - } -} - - -// XXX might be a good idea to be able ignore actions rather than keys... -// XXX add this to the global doc... var GLOBAL_KEYBOARD = -window.GLOBAL_KEYBOARD = -module.GLOBAL_KEYBOARD = { - 'Global': { - doc: 'Global bindings that take priority over other sections.', - pattern: '*', - - }, - - 'Slideshow': { - pattern: '.slideshow-running', - ignore: [ - 'Esc', - 'Up', 'Down', 'Enter', - 'R', 'L', 'G', 'T', - ], - - Esc: 'toggleSlideshow: "off" -- Exit slideshow', - Enter: 'slideshowDialog', - - Left: 'resetSlideshowTimer', - Right: 'resetSlideshowTimer', - Home: 'resetSlideshowTimer', - End: 'resetSlideshowTimer', - - T: 'slideshowIntervalDialog', - R: 'toggleSlideshowDirection', - L: 'toggleSlideshowLooping', - }, - - // XXX do we need to prevent up/down navigation here, it may get confusing? - // XXX do we need to disable fast sorting here??? - 'Single Image': { - pattern: '.single-image-mode', - ignore: [ - 'Esc', - - // do not crop in single image mode... - 'C', 'F2', - - // zooming... - '#0', '#1', '#2', '#3', '#4', '#5', '#6', '#7', '#8', '#9', - ], - - - // NOTE: these are here so as to enable handling via the next - // block, i.e. the Viewer - // ...if not given, then the ignore above will shadow the - // keys... - // NOTE: the 'nop' action does not exist, this it will get ignored - '(': 'nop', - ')': 'nop', - - // zooming... - '#1': 'fitScreen', - // XXX should these also be implemented in the same way as 4-9??? - '#2': { - default: 'fitNormal', - 'alt': 'setNormalScale -- Set current image size as normal', - 'ctrl+shift': 'setNormalScale: null -- Reset normal image size to default', - }, - '#3': { - default: 'fitSmall', - 'alt': 'setSmallScale -- Set current image size as small', - 'ctrl+shift': 'setSmallScale: null -- Reset small image size to default', - }, - '#4': customScale(4), - '#5': customScale(5), - '#6': customScale(6), - '#7': customScale(7), - '#8': customScale(8), - '#9': customScale(9), - '#0': customScale(0), - - - Esc: 'toggleSingleImage: "off" -- Exit single image view', - - // ignore sorting and reversing... - // XXX not sure about these yet, especially reversing... - R: { - shift: 'IGNORE', - }, - S: { - shift: 'IGNORE', - }, - }, - - // XXX add "save as collection..." - 'Cropped': { - pattern: '.crop-mode', - - Esc: { - default: 'uncrop', - ctrl: 'uncropAll', - }, - }, - - 'Range': { - doc: 'Range editing', - pattern: '.brace', - - // XXX add: - // - range navigation - // - range manipulation - - Esc: 'clearRange', - }, - - // XXX add "save as collection..." (???) - // XXX cleanup... - 'Viewer': { - doc: 'NOTE: binding priority is the same as the order of sections '+ - 'on this page.', - pattern: '*', - - X: { - alt: 'close', - }, - - F4: { - alt: 'close', - }, - Q: { - meta: 'close', - }, - // XXX - F5: keyboard.doc('Full reload viewer', - function(){ - //a.stop() - /* - killAllWorkers() - .done(function(){ - reload() - }) - */ - location.reload() - return false - }), - F12: 'showDevTools', - // NOTE: these are for systems where F** keys are not available - // or do other stuff... - R: { - default: 'rotateCW', - shift: 'reverseImages', - ctrl: 'loadNewImages!', - alt: 'browseActions: "/Ribbon/" -- Open ribbon menu', - 'ctrl+alt': 'reload!', - 'ctrl+shift': 'F5', - }, - L: 'rotateCCW', - H: { - default: 'flipHorizontal', - ctrl: 'listURLHistory', - 'ctrl+shift': 'listSaveHistory', - alt: 'browseActions: "/History/" -- Open history menu', - }, - V: 'flipVertical', - - // tilt... - // XXX experimental, not sure if wee need this with a keyboard... - T: { - default: 'rotateRibbonCCW -- Tilt ribbons counter clock wise', - shift: 'rotateRibbonCW -- Tilt ribbons clock wise', - - alt: 'resetRibbonRotation -- Reset ribbon tilt', - }, - - P: { - 'ctrl+shift': 'F12', - }, - - // NOTE: this is handled by the wrapper at this point, so we do - // not have to do anything here... - F11: 'toggleFullScreen', - F: { - ctrl: 'F11', - meta: 'F11', - }, - - // XXX testing... - - Enter: 'toggleSingleImage', - - Home: { - default: 'firstImage', - ctrl: 'firstGlobalImage', - shift: 'firstRibbon', - }, - End: { - default: 'lastImage', - ctrl: 'lastGlobalImage', - shift: 'lastRibbon', - }, - Left: { - default: 'prevImage', - alt: 'shiftImageLeft!', - ctrl: 'prevScreen', - // XXX need to prevent default on mac + browser... - meta: 'prevScreen', - }, - PgUp: 'prevScreen', - PgDown: 'nextScreen', - Right: { - default: 'nextImage', - alt: 'shiftImageRight!', - ctrl: 'nextScreen', - // XXX need to prevent default on mac + browser... - meta: 'nextScreen', - }, - Space: 'Right', - Backspace: 'Left', - '(': 'prevImageInOrder', - ')': 'nextImageInOrder', - ',': 'prevMarked', - '.': 'nextMarked', - '[': { - default: 'prevBookmarked', - // XXX experimental - shift: 'openRange', - }, - ']': { - default: 'nextBookmarked', - // XXX experimental - shift: 'closeRange', - }, - Up: { - default: 'prevRibbon', - shift: 'shiftImageUp', - 'alt+shift': 'travelImageUp', - 'ctrl+shift': 'shiftImageUpNewRibbon', - }, - Down: { - default: 'nextRibbon', - shift: 'shiftImageDown', - 'alt+shift': 'travelImageDown', - 'ctrl+shift': 'shiftImageDownNewRibbon', - }, - - '#0': 'fitMax', - '#1': { - default: 'fitImage', - shift: 'fitRibbon', - ctrl: 'fitOrig!', - }, - '#2': 'fitImage: 2 -- Fit 2 Images', - '#3': { - default: 'fitImage: 3 -- Fit 3 images', - shift: 'fitRibbon: 3.5 -- Fit 3.5 ribbons', - }, - '#4': 'fitImage: 4 -- Fit 4 images', - '#5': { - default: 'fitImage: 5 -- Fit 5 images', - shift: 'fitRibbon: 5.5 -- Fit 5.5 ribbons', - }, - '#6': 'fitImage: 6 -- Fit 6 images', - '#7': 'fitImage: 7 -- Fit 7 images', - '#8':'fitImage: 8 -- Fit 8 images', - '#9': 'fitImage: 9 -- Fit 9 images', - - '+': { - default: 'zoomIn', - ctrl: 'lighterTheme!', - }, - '=': '+', - '-': { - default: 'zoomOut', - ctrl: 'darkerTheme!', - }, - - F2: { - default: 'cropRibbon', - shift: 'cropRibbonAndAbove', - ctrl: 'cropMarked', - alt: 'cropBookmarked', - }, - - // marking... - M: { - default: 'toggleMark', - alt: 'browseActions: "/Mark/" -- Show mark menu', - }, - A: { - alt: 'browseActions', - 'alt+shift': 'listActions', - - ctrl: 'toggleMark!: "ribbon" "on" -- Mark all images in ribbon', - }, - D: { - ctrl: 'toggleMark!: "ribbon" "off" -- Unmark all images in ribbon', - }, - I: { - default: 'showMetadata', - alt: 'browseActions: "/Image/" -- Show image menu', - shift: 'toggleStatusBar', - - ctrl: 'toggleMark!: "ribbon" -- Invert marks in ribbon', - 'ctrl+shift': 'showMetadata: "current" "full" -- Show full metadata', - - 'meta+alt': 'showDevTools', - }, - // XXX experimental... - '*': 'setRangeBorder', - - B: { - default: 'toggleBookmark', - ctrl: 'toggleTheme!', - 'ctrl+shift': 'toggleTheme!: "prev"', - - alt: 'browseActions: "/Bookmark/" -- Show bookmark menu', - - // XXX not sure if this is the right way to go... - shift: 'setBaseRibbon', - }, - E: { - default: 'openInExtenalEditor', - shift: 'openInExtenalEditor: 1 -- Open in alternative editor', - alt: 'listExtenalEditors', - }, - C: { - default: 'browseActions: "/Crop/" -- Show crop menu', - // do the default copy thing... - // NOTE: this stops the default: handler from getting the ctrl: - // key case... - ctrl: '', - }, - O: 'browsePath', - S: { - default: 'slideshowDialog', - //shift: 'sortImages: "Date" -- Sort images by date', - shift: 'sortImages -- Sort images', - //alt: 'browseActions: "/Sort/"', - alt: 'sortDialog', - // XXX need to make this save to base_path if it exists and - // ask the user if it does not... now it always asks. - ctrl: 'saveIndexHere', - 'ctrl+shift': 'exportDialog', - }, - - // XXX still experimental... - U: { - default: 'undo', - shift: 'redo', - }, - Z: { - ctrl: 'undo', - 'ctrl+shift': 'redo', - }, - - G: { - default: 'editStatusBarIndex!', - shift: 'toggleStatusBarIndexMode!', - - // XXX for debug... - //ctrl: function(){ $('.viewer').toggleClass('visible-gid') }, - }, - - '?': 'showKeyboardBindings', - - W: 'testAction', - }, -} - - - -/*********************************************************************/ -// + simpler to group bindings -// - harder to automate binding creation (e.g. via customScale(..)) - -var keyboard2 = require('lib/keyboard2') - - -// XXX do we want to add sub-sections to better organize keys for -// documentation??? -var GLOBAL_KEYBOARD2 = -window.GLOBAL_KEYBOARD2 = module.GLOBAL_KEYBOARD2 = { 'Global': { doc: 'Global bindings that take priority over other sections.', @@ -770,10 +385,17 @@ module.GLOBAL_KEYBOARD2 = { } -keyboard = keyboard2 -GLOBAL_KEYBOARD = GLOBAL_KEYBOARD2 +//--------------------------------------------------------------------- + +// XXX DEBUG: remove when done... +window.kb = keyboard.Keyboard( + GLOBAL_KEYBOARD, + function checkGlobalMode(mode, keyboard, context){ + var pattern = keyboard[mode].pattern + return !pattern + || pattern == '*' + || $(keyboard[mode].pattern).length > 0 }) -window.kb = keyboard2.Keyboard(GLOBAL_KEYBOARD2, keyboard2.checkGlobalMode) @@ -979,6 +601,7 @@ var KeyboardActions = actions.Actions({ }], + // XXX move to gen2 // XXX need to pre-process the docs... // - remove the path component... // - insert the action name where not doc present... @@ -1013,13 +636,6 @@ var KeyboardActions = actions.Actions({ // // new // XXX BUG sections with doc do not show up in title... - // XXX BUG: - // ig.bindKey('Global', 'X', 'editKeyboardBindings') - // ig.editKeyboardBindings() - // -> shows alt-X instead of X - // ig.bindKey('Global', 'X', 'editKeyboardBindings') - // ig.editKeyboardBindings() - // -> shows two keys ctrl-Z and ctrl-shift-Z instead of Z // XXX sub-group by path (???) browseKeyboardBindings: ['Interface/Keyboard bindings...', widgets.makeUIDialog(function(path, edit){ diff --git a/ui (gen4)/lib/keyboard2.js b/ui (gen4)/lib/keyboard2.js index 633b9069..83959fef 100755 --- a/ui (gen4)/lib/keyboard2.js +++ b/ui (gen4)/lib/keyboard2.js @@ -125,7 +125,7 @@ function doc(text, func){ // - non-nested arrays or objects // // XXX should this be here??? -// XXX add support for suffix to return false... +// XXX add support for suffix to return false / stop_propagation... var parseActionCall = module.parseActionCall = function parseActionCall(txt){ @@ -151,7 +151,8 @@ function parseActionCall(txt){ action: action, arguments: args, doc: doc, - 'no-default': no_default, + no_default: no_default, + stop_propagation: false, } } @@ -160,6 +161,7 @@ function parseActionCall(txt){ //--------------------------------------------------------------------- // Helpers... +// Form standard key string from keyboard event... var event2key = module.event2key = function event2key(evt){ @@ -176,6 +178,7 @@ function event2key(evt){ } +// Get key code from key name... var key2code = module.key2code = function key2code(key){ @@ -184,6 +187,7 @@ function key2code(key){ : key.charCodeAt(0) } +// Get key name from key code... var code2key = module.code2key = function code2key(code){ @@ -193,6 +197,7 @@ function code2key(code){ : null } +// Check if string is a standard key string... var isKey = module.isKey = function isKey(key){ @@ -208,6 +213,11 @@ function isKey(key){ } +// Split key... +// +// NOTE: if this gets an array, it will get returned as-is... +// NOTE: no checks are made on the key, use isKey(..) in conjunction +// with normalizeKey(..) for checking... var splitKey = module.splitKey = function splitKey(key){ @@ -222,7 +232,9 @@ function splitKey(key){ .filter(function(c){ return c != '' }) } -// NOTE: this will not check if a key is a key... +// Normalize key string/array... +// +// NOTE: this will not check if a key is a key use isKey(..) for that. var normalizeKey = module.normalizeKey = function normalizeKey(key){ @@ -255,6 +267,11 @@ function normalizeKey(key){ } +// Get shifted key if available... +// +// Examples: +// - '{' -> 'shift+[' +// - ')' -> 'shift+#0' var shifted = module.shifted = function shifted(key){ @@ -281,19 +298,6 @@ function shifted(key){ -//--------------------------------------------------------------------- - -var checkGlobalMode = -module.checkGlobalMode = -function checkGlobalMode(mode, keyboard, context){ - var pattern = keyboard[mode].pattern - return !pattern - || pattern == '*' - || $(keyboard[mode].pattern).length > 0 -} - - - //--------------------------------------------------------------------- var KeyboardHandlerClassPrototype = { @@ -328,6 +332,14 @@ var KeyboardHandlerPrototype = { // }, // ... // } + // + // Reserved special handlers: + // - DROP - drop checking of key + // NOTE: this will prevent handling next sections + // for this key. + // - NEXT_SECTION - force check next section, this has priority + // over .drop + // __keyboard: null, get keyboard(){ return this.__keyboard instanceof Function ? @@ -337,7 +349,7 @@ var KeyboardHandlerPrototype = { this.__keyboard = value }, // XXX is this needed??? - context: null, + //context: null, // utils... event2key: KeyboardHandlerClassPrototype.event2key, @@ -382,11 +394,26 @@ var KeyboardHandlerPrototype = { //isModeApplicable: function(mode, keyboard, context){ return true }, //isModeApplicable: checkGlobalMode, - // get keys for handler... + // Get keys for handler... + // + // List all handlers... + // .keys() + // .keys('*') + // -> keys + // + // List keys for handler... + // .keys(handler) + // -> keys + // + // List keys for given handlers... + // .keys(handler, ...) + // .keys([handler, ...]) + // -> keys + // + // List keys for handlers that pass the func predicate... + // .keys(func) + // -> keys // - // NOTE: this will also return non-key aliases... - // NOTE: to match several compatible handlers, pass a list of handlers, - // the result for each will be merged into one common list. // // Format: // { @@ -397,17 +424,23 @@ var KeyboardHandlerPrototype = { // ... // } // + // + // NOTE: this will also return non-key aliases... + // NOTE: to match several compatible handlers, pass a list of handlers, + // the result for each will be merged into one common list. keys: function(handler){ var that = this var res = {} var keyboard = this.keyboard var key_separators = KEY_SEPARATORS + var service_fields = this.service_fields + || this.constructor.service_fields + handler = arguments.length > 1 ? [].slice.call(arguments) + : handler == null ? '*' : handler == '*' || handler instanceof Function ? handler : handler instanceof Array ? handler : [handler] - var service_fields = this.service_fields - || this.constructor.service_fields var walkAliases = function(res, rev, bindings, key, mod){ mod = mod || [] @@ -547,6 +580,13 @@ var KeyboardHandlerPrototype = { // -> this // // + // Format: + // { + // : , + // ... + // } + // + // // Search order: // - search for full key // - search for shifted key if applicable @@ -613,7 +653,7 @@ var KeyboardHandlerPrototype = { var shift_key = this.shifted(key) // match candidates... - var keys = genKeys(key, shift_key) + var keys = genKeys(key, shift_key).unique() // get modes... var modes = mode == '*' ? Object.keys(keyboard) @@ -629,12 +669,6 @@ var KeyboardHandlerPrototype = { var mod = genKeys(key.slice(0, -1).concat('')) - // also test single key and code if everything else fails... - // XXX make this an option... - keys = keys - // .concat([k, c]) - .unique() - var drop = mode == 'test' || mode == '?' for(var i=0; i < modes.length; i++){ var m = modes[i] @@ -654,7 +688,7 @@ var KeyboardHandlerPrototype = { mod) } - // handle explicit DROP... + // explicit DROP -- ignore next sections... if(drop && handler == 'DROP'){ break } @@ -690,11 +724,10 @@ var KeyboardHandlerPrototype = { var bindings = keyboard[m] // remove all matching keys... - keys - .unique() - .forEach(function(k){ - delete bindings[k] - }) + // NOTE: if key with modifiers, then this will remove only + // the full matched keys and shifted matches but will + // leave the key without modifiers as-is... + keys.forEach(function(k){ delete bindings[k] }) // set handler if given... if(handler && handler != ''){ @@ -719,6 +752,7 @@ var KeyboardHandlerPrototype = { context || that.context) }) : Object.keys(this.keyboard) }, + __init__: function(keyboard, is_mode_applicable){ this.keyboard = keyboard @@ -744,7 +778,8 @@ function makeKeyboardHandler(keyboard, unhandled, actions){ var kb = keyboard instanceof Keyboard ? keyboard - : Keyboard(keyboard, checkGlobalMode) + //: Keyboard(keyboard, checkGlobalMode) + : Keyboard(keyboard) return function(evt){ var res = undefined @@ -758,17 +793,31 @@ function makeKeyboardHandler(keyboard, unhandled, actions){ return } - var h = parseActionCall(handlers[mode]) + var handler = handlers[mode] - if(h && h.action in actions){ - did_handling = true + // raw function handler... + if(handler instanceof Function){ + res = handler.call(actions) - h.no_default - && evt.preventDefault() + // action call syntax... + } else { + var h = parseActionCall(handler) - // call the handler... - res = actions[h.action].apply(actions, h.args) - } + if(h && h.action in actions){ + did_handling = true + + h.no_default + && evt.preventDefault() + + // call the handler... + res = actions[h.action].apply(actions, h.args) + + if(h.stop_propagation){ + res = false + evt.stopPropagation() + } + } + } }) unhandled