diff --git a/ui (gen4)/features/_feature.js b/ui (gen4)/features/_feature.js new file mode 100755 index 00000000..c467964f --- /dev/null +++ b/ui (gen4)/features/_feature.js @@ -0,0 +1,48 @@ +/********************************************************************** +* +* +* +**********************************************************************/ + +define(function(require){ var module = {} + +//var DEBUG = DEBUG != null ? DEBUG : true + +var actions = require('lib/actions') +var features = require('lib/features') + +var core = require('features/core') + + + +/*********************************************************************/ + +var FeatureActions = actions.Actions({ + emptyAction: ['- Demo/Empty action', + function(){ + // XXX + }], +}) + +var Feature = +module.Feature = core.ImageGridFeatures.Feature({ + title: '', + doc: '', + + // XXX + tag: 'feature-tag', + depends: [ + // XXX + ], + + actions: FeatureActions, + + handlers: [], +}) + + + + +/********************************************************************** +* vim:set ts=4 sw=4 : */ +return module }) diff --git a/ui (gen4)/features/all.js b/ui (gen4)/features/all.js index 69e67139..e268bfd2 100755 --- a/ui (gen4)/features/all.js +++ b/ui (gen4)/features/all.js @@ -15,6 +15,7 @@ var location = require('features/location') var history = require('features/history') var app = require('features/app') var ui = require('features/ui') +var keyboard = require('features/keyboard') var status = require('features/ui-status') var marks = require('features/ui-marks') var widgets = require('features/ui-widgets') diff --git a/ui (gen4)/features/demo.js b/ui (gen4)/features/demo.js index a877c18c..7999c929 100755 --- a/ui (gen4)/features/demo.js +++ b/ui (gen4)/features/demo.js @@ -10,7 +10,6 @@ define(function(require){ var module = {} var actions = require('lib/actions') var features = require('lib/features') -var toggler = require('lib/toggler') var data = require('data') var images = require('images') diff --git a/ui (gen4)/features/keyboard.js b/ui (gen4)/features/keyboard.js new file mode 100755 index 00000000..b98dc952 --- /dev/null +++ b/ui (gen4)/features/keyboard.js @@ -0,0 +1,345 @@ +/********************************************************************** +* +* +* +**********************************************************************/ + +define(function(require){ var module = {} + +//var DEBUG = DEBUG != null ? DEBUG : true + +var actions = require('lib/actions') +var features = require('lib/features') +var toggler = require('lib/toggler') +var keyboard = require('lib/keyboard') + +var core = require('features/core') + + + +/*********************************************************************/ + +// XXX add this to the global doc... +var GLOBAL_KEYBOARD = +module.GLOBAL_KEYBOARD = { + 'Slideshow': { + pattern: '.slideshow-running', + ignore: [ + 'Up', 'Down', 'Enter', + 'R', 'L', + ], + + Esc: 'toggleSlideshow: "off"', + Enter: 'slideshowDialog', + + Left: 'resetSlideshowTimer', + Right: 'resetSlideshowTimer', + Home: 'resetSlideshowTimer', + End: 'resetSlideshowTimer', + + R: 'toggleSlideshowDirection', + L: 'toggleSlideshowLooping', + }, + + 'Global': { + doc: 'NOTE: binding priority is the same as the order of sections '+ + 'on this page.', + pattern: '*', + + F4: { + alt: 'close', + }, + Q: { + meta: 'close', + }, + 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: 'reload!', + 'ctrl+shift': 'F5', + }, + L: 'rotateCCW', + H: { + default: 'flipHorizontal', + ctrl: 'listURLHistory', + alt: 'browseActions: "/History/"', + }, + V: 'flipVertical', + 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', + }, + '(': 'prevImageInOrder', + ')': 'nextImageInOrder', + ',': 'prevMarked', + '.': 'nextMarked', + '[': 'prevBookmarked', + ']': 'nextBookmarked', + 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', + '#3': { + default: 'fitImage: 3', + shift: 'fitRibbon: 3.5', + }, + '#4': 'fitImage: 4', + '#5': { + default: 'fitImage: 5', + shift: 'fitRibbon: 5.5', + }, + '#6': 'fitImage: 6', + '#7': 'fitImage: 7', + '#8':'fitImage: 8', + '#9': 'fitImage: 9', + + '+': 'zoomIn', + '=': '+', + '-': 'zoomOut', + + F2: { + default: 'cropRibbon', + shift: 'cropRibbonAndAbove', + ctrl: 'cropMarked', + alt: 'cropBookmarked', + }, + Esc: { + default: 'uncrop', + ctrl: 'uncropAll', + }, + + // marking... + M: { + default: 'toggleMark', + alt: 'browseActions: "/Mark/"', + }, + A: { + alt: 'browseActions', + 'alt+shift': 'listActions', + + ctrl: 'toggleMark!: "ribbon" "on"', + }, + D: { + ctrl: 'toggleMark!: "ribbon" "off"', + }, + I: { + default: 'showMetadata', + shift: 'toggleStatusBar', + + ctrl: 'toggleMark!: "ribbon"', + 'ctrl+shift': 'showMetadata: "current" "full"', + + 'meta+alt': 'showDevTools', + }, + + B: { + default: 'toggleBookmark', + ctrl: 'toggleTheme!', + alt: 'browseActions: "/Bookmark/"', + }, + E: { + default: 'openInExtenalEditor', + shift: 'openInExtenalEditor: 1', + alt: 'listExtenalEditors', + }, + C: 'browseActions: "/Crop/"', + O: 'browsePath', + S: { + //default: 'browseActions: "/Slideshow/"', + default: 'slideshowDialog', + // 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': 'browseSaveIndex', + }, + + // XXX still experimental... + U: { + default: 'undoLast', + shift: 'redoLast', + }, + Z: { + ctrl: 'undoLast', + 'ctrl+shift': 'redoLast', + }, + + G: { + default: 'editStatusBarIndex!', + shift: 'toggleStatusBarIndexMode!', + + // XXX for debug... + ctrl: function(){ $('.viewer').toggleClass('visible-gid') }, + }, + }, +} + + +/*********************************************************************/ + +var KeyboardActions = actions.Actions({ + config: { + // limit key repeat to one per N milliseconds. + // + // Set this to -1 or null to run keys without any limitations. + 'max-key-repeat-rate': 0, + }, + + get keyboard(){ + return this.__keyboard_config + }, + + toggleKeyboardHandling: ['- Interface/Toggle keyboard handling', + toggler.Toggler(null, function(_, state){ + if(state == null){ + return this.__keyboard_handler ? 'on' : 'off' + } + + // XXX this does not work yet... + //var target = this.ribbons.viewer + var target = $(document) + + // start/reset keyboard handling... + if(state == 'on'){ + var that = this + + // need to reset... + if(this.__keyboard_handler != null){ + target.off('keydown', this.__keyboard_handler) + } + + // setup base keyboard for devel, in case something breaks... + // This branch does not drop keys... + if(this.config['max-key-repeat-rate'] < 0 + || this.config['max-key-repeat-rate'] == null){ + //this.ribbons.viewer + var handler = + this.__keyboard_handler = + keyboard.makeKeyboardHandler( + function(){ return that.__keyboard_config }, + function(k){ window.DEBUG && console.log(k) }, + this) + + // drop keys if repeating too fast... + // NOTE: this is done for smoother animations... + } else { + var handler = + this.__keyboard_handler = + keyboard.dropRepeatingkeys( + keyboard.makeKeyboardHandler( + function(){ return that.__keyboard_config }, + function(k){ window.DEBUG && console.log(k) }, + this), + function(){ + return that.config['max-key-repeat-rate'] + }) + } + + target.keydown(handler) + + // stop keyboard handling... + } else { + target.off('keydown', this.__keyboard_handler) + delete this.__keyboard_handler + } + }, + ['on', 'off'])] +}) + +var Keyboard = +module.Keyboard = core.ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'keyboard', + depends: [ + 'ui' + ], + + actions: KeyboardActions, + + handlers: [ + ['start', + function(){ + var that = this + this.__keyboard_config = this.keyboard || GLOBAL_KEYBOARD + + this.toggleKeyboardHandling('on') + }] + ], +}) + + + + +/********************************************************************** +* vim:set ts=4 sw=4 : */ +return module }) diff --git a/ui (gen4)/features/meta.js b/ui (gen4)/features/meta.js index e47b38a4..34f089c3 100755 --- a/ui (gen4)/features/meta.js +++ b/ui (gen4)/features/meta.js @@ -52,6 +52,7 @@ core.ImageGridFeatures.Feature('viewer-testing', [ 'workspace', 'ui', + 'keyboard', 'ui-ribbons-placement', diff --git a/ui (gen4)/features/ui-status.js b/ui (gen4)/features/ui-status.js index 4494056b..1da7663f 100755 --- a/ui (gen4)/features/ui-status.js +++ b/ui (gen4)/features/ui-status.js @@ -180,16 +180,16 @@ var StatusBarActions = actions.Actions({ // global index... if(cls == 'global'){ item.find('.position:not(:focus)') - .text(this.data.getImageOrder(gid)+1) + .text(this.data ? this.data.getImageOrder(gid)+1 : 0) item.find('.length') - .text('/'+ this.data.length) + .text('/'+ (this.data ? this.data.length : 0)) // ribbon index... } else { item.find('.position:not(:focus)') - .text(this.data.getImageOrder('ribbon', gid)+1) + .text(this.data ? this.data.getImageOrder('ribbon', gid)+1 : 0) item.find('.length') - .text('/'+ this.data.getImages(gid).len) + .text('/'+ (this.data ? this.data.getImages(gid).len : 0)) } return item @@ -272,7 +272,7 @@ var StatusBarActions = actions.Actions({ // them here... // ...this also simpler than handling '?' and other // special toggler args in the handler... - var tags = this.data.getTags(gid) + var tags = this.data ? this.data.getTags(gid) : [] var tag = type == 'mark' ? 'selected' : 'bookmark' item[tags.indexOf(tag) < 0 ? 'removeClass' @@ -287,8 +287,14 @@ var StatusBarActions = actions.Actions({ // reconstruct all the items. toggleStatusBar: ['Interface/Toggle status bar modes', toggler.CSSClassToggler( + // get/construct status bar... // XXX change class... function(){ + // no viewer yet... + if(!this.ribbons || !this.ribbons.viewer){ + return $() + } + var bar = this.ribbons.viewer.find('.state-indicator-container.global-info') if(bar.length == 0){ bar = makeStateIndicator('global-info overlay-info') @@ -466,7 +472,7 @@ module.StatusBar = core.ImageGridFeatures.Feature({ function(){ this.toggleStatusBar(this.config['status-bar-mode']) }], - ['focusImage', + ['focusImage clear', function(){ this.updateStatusBar() }], diff --git a/ui (gen4)/features/ui.js b/ui (gen4)/features/ui.js index ef62e217..85cd7cce 100755 --- a/ui (gen4)/features/ui.js +++ b/ui (gen4)/features/ui.js @@ -135,13 +135,6 @@ module.ViewerActions = actions.Actions({ 'fit-overflow': 0.2, - // limit key repeat to one per N milliseconds. - // - // Set this to -1 or null to run keys without any limitations. - // XXX at this point the keyboard is setup in ui.js, need to - // move to a more logical spot... - 'max-key-repeat-rate': 0, - // Theme to set on startup... 'theme': null, diff --git a/ui (gen4)/lib/_module.js b/ui (gen4)/lib/_module.js new file mode 100755 index 00000000..4d34f52d --- /dev/null +++ b/ui (gen4)/lib/_module.js @@ -0,0 +1,20 @@ +/********************************************************************** +* +* +* +**********************************************************************/ + +define(function(require){ var module = {} +console.log('>>> viewer') + +//var DEBUG = DEBUG != null ? DEBUG : true + + +/*********************************************************************/ + + + + +/********************************************************************** +* vim:set ts=4 sw=4 : */ +return module }) diff --git a/ui (gen4)/lib/keyboard.js b/ui (gen4)/lib/keyboard.js index 2ef38551..991b3c14 100755 --- a/ui (gen4)/lib/keyboard.js +++ b/ui (gen4)/lib/keyboard.js @@ -669,6 +669,10 @@ function makeKeyboardHandler(keybindings, unhandled, actions){ var did_handling = false var res = null + var _keybindings = typeof(keybindings) == typeof(function(){}) ? + keybindings.call(this) + : keybindings + // key data... var key = evt.keyCode @@ -677,7 +681,7 @@ function makeKeyboardHandler(keybindings, unhandled, actions){ //window.DEBUG && console.log('KEY:', key, chr, modifiers) - var handlers = getKeyHandlers(key, modifiers, keybindings, null, null, actions) + var handlers = getKeyHandlers(key, modifiers, _keybindings, null, null, actions) for(var mode in handlers){ var handler = handlers[mode] @@ -691,7 +695,7 @@ function makeKeyboardHandler(keybindings, unhandled, actions){ did_handling = true //res = handler(evt) - res = handler.call(keybindings) + res = handler.call(_keybindings) if(res === false){ break diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js index a88c571d..1c67d0a6 100755 --- a/ui (gen4)/ui.js +++ b/ui (gen4)/ui.js @@ -48,243 +48,6 @@ var viewer = require('viewer') -/*********************************************************************/ - -// XXX move this to config... -// NOTE: setting this here (and only here) to -1 or null will desable -// key dropping... -// NOTE: keeping this disabled is recommended for development... -// NOTE: setting this to 0 will only allow a single keypress per -// execution frame... -// XXX yes there should be only one execution frame per event -// triggered but this actually improves things, thus the issue -// needs more investigation... -module.MAX_KEY_REPEAT_RATE = 0 - -// XXX add this to the global doc... -module.GLOBAL_KEYBOARD = { - 'Slideshow': { - pattern: '.slideshow-running', - ignore: [ - 'Up', 'Down', 'Enter', - 'R', 'L', - ], - - Esc: 'toggleSlideshow: "off"', - Enter: 'slideshowDialog', - - Left: 'resetSlideshowTimer', - Right: 'resetSlideshowTimer', - Home: 'resetSlideshowTimer', - End: 'resetSlideshowTimer', - - R: 'toggleSlideshowDirection', - L: 'toggleSlideshowLooping', - }, - - 'Global': { - doc: 'NOTE: binding priority is the same as the order of sections '+ - 'on this page.', - pattern: '*', - - F4: { - alt: 'close', - }, - Q: { - meta: 'close', - }, - F5: 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: 'reload!', - 'ctrl+shift': 'F5', - }, - L: 'rotateCCW', - H: { - default: 'flipHorizontal', - ctrl: 'listURLHistory', - alt: 'browseActions: "/History/"', - }, - V: 'flipVertical', - 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', - }, - '(': 'prevImageInOrder', - ')': 'nextImageInOrder', - ',': 'prevMarked', - '.': 'nextMarked', - '[': 'prevBookmarked', - ']': 'nextBookmarked', - 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', - '#3': { - default: 'fitImage: 3', - shift: 'fitRibbon: 3.5', - }, - '#4': 'fitImage: 4', - '#5': { - default: 'fitImage: 5', - shift: 'fitRibbon: 5.5', - }, - '#6': 'fitImage: 6', - '#7': 'fitImage: 7', - '#8':'fitImage: 8', - '#9': 'fitImage: 9', - - '+': 'zoomIn', - '=': '+', - '-': 'zoomOut', - - F2: { - default: 'cropRibbon', - shift: 'cropRibbonAndAbove', - ctrl: 'cropMarked', - alt: 'cropBookmarked', - }, - Esc: { - default: 'uncrop', - ctrl: 'uncropAll', - }, - - // marking... - M: { - default: 'toggleMark', - alt: 'browseActions: "/Mark/"', - }, - A: { - alt: 'browseActions', - 'alt+shift': 'listActions', - - ctrl: 'toggleMark!: "ribbon" "on"', - }, - D: { - ctrl: 'toggleMark!: "ribbon" "off"', - }, - I: { - default: 'showMetadata', - shift: 'toggleStatusBar', - - ctrl: 'toggleMark!: "ribbon"', - 'ctrl+shift': 'showMetadata: "current" "full"', - - 'meta+alt': 'showDevTools', - }, - - B: { - default: 'toggleBookmark', - ctrl: 'toggleTheme!', - alt: 'browseActions: "/Bookmark/"', - }, - E: { - default: 'openInExtenalEditor', - shift: 'openInExtenalEditor: 1', - alt: 'listExtenalEditors', - }, - C: 'browseActions: "/Crop/"', - O: 'browsePath', - S: { - //default: 'browseActions: "/Slideshow/"', - default: 'slideshowDialog', - // 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': 'browseSaveIndex', - }, - - // XXX still experimental... - U: { - default: 'undoLast', - shift: 'redoLast', - }, - Z: { - ctrl: 'undoLast', - 'ctrl+shift': 'redoLast', - }, - - G: { - default: 'editStatusBarIndex!', - shift: 'toggleStatusBarIndexMode!', - - // XXX for debug... - ctrl: function(){ $('.viewer').toggleClass('visible-gid') }, - }, - }, -} - - - /*********************************************************************/ $(function(){ @@ -300,13 +63,14 @@ $(function(){ .setup([ 'viewer-testing', + 'demo', + // XXX this is not for production... 'experiments', - 'demo', ]) - // used switch experimental actions on (set to true) or off (unset or false)... + // used to switch experimental actions on (set to true) or off (unset or false)... //a.experimental = true @@ -350,36 +114,6 @@ $(function(){ 'Nothing loaded...', 'Press \'O\' to load, \'F1\' for help or \'?\' for keyboard mappings.') - - - // setup base keyboard for devel, in case something breaks... - // This branch does not drop keys... - if(a.config['max-key-repeat-rate'] < 0 || a.config['max-key-repeat-rate'] == null){ - $(document) - .keydown( - keyboard.makeKeyboardHandler( - module.GLOBAL_KEYBOARD, - function(k){ - window.DEBUG && console.log(k) - }, - a)) - - // drop keys if repeating too fast... - // NOTE: this is done for smoother animations... - } else { - $(document) - .keydown( - keyboard.dropRepeatingkeys( - keyboard.makeKeyboardHandler( - module.GLOBAL_KEYBOARD, - function(k){ - window.DEBUG && console.log(k) - }, - a), - function(){ - return a.config['max-key-repeat-rate'] - })) - } })