diff --git a/ui (gen4)/features/meta.js b/ui (gen4)/features/meta.js index a7236f5e..1fa36344 100755 --- a/ui (gen4)/features/meta.js +++ b/ui (gen4)/features/meta.js @@ -94,6 +94,7 @@ core.ImageGridFeatures.Feature('viewer-testing', [ 'ui-external-editor', // chrome... + 'ui-workspace', 'ui-status-log', 'ui-scale', 'ui-animation', diff --git a/ui (gen4)/features/metadata.js b/ui (gen4)/features/metadata.js index 5546e4ba..a8bcc5f5 100755 --- a/ui (gen4)/features/metadata.js +++ b/ui (gen4)/features/metadata.js @@ -361,11 +361,11 @@ var MetadataUIActions = actions.Actions({ ]) // comment and tags... - info.push(['Comment', + info.push(['Comment: ', function(){ return img.comment || '' }]) } - info.push(['Tags', + info.push(['Tags: ', function(){ return that.data.getTags().join(', ') || '' }]) // build fields... @@ -413,6 +413,10 @@ var MetadataUIActions = actions.Actions({ _selectElemText($(elem).find('.text').last()[0]) } }) + // XXX start editing onkeydown... + .on('keydown', function(){ + // XXX Enter + editable -> edit (only this???) + }) // path selected... .open(function(evt, path){ var editable = RegExp(that.config['metadata-editable-fields'] diff --git a/ui (gen4)/features/ui-slideshow.js b/ui (gen4)/features/ui-slideshow.js index 289d4f4b..2962eff3 100755 --- a/ui (gen4)/features/ui-slideshow.js +++ b/ui (gen4)/features/ui-slideshow.js @@ -22,6 +22,16 @@ var base = require('features/base') // XXX stub... var SlideshowActions = actions.Actions({ config: { + 'ui-slideshow-looping': true, + 'ui-slideshow-direction': 'next', + 'ui-slideshow-interval': '3s', + + 'ui-slideshow-saved-intervals': [ + '0.2s', + '3s', + '5s', + '7s', + ], }, // XXX @@ -65,6 +75,69 @@ var SlideshowActions = actions.Actions({ function(){}], toggleSlideshow: ['Slideshow/Start', function(){}], + + + // XXX might be good to add a slideshow countdown/indicator for + // timers longer than 0.5-1sec... + _startSlideshow: ['- Slideshow/', + function(){ + var that = this + + // reset the timer... + // NOTE: this means we were in a slideshow mode so we do not + // need to prepare... + if(this.__slideshouw_timer){ + clearTimeout(this.__slideshouw_timer) + delete this.__slideshouw_timer + + // prepare for the slideshow... + } else { + // XXX get state before setting/hiding things... + // XXX + + // single image mode... + this.toggleSingleImage('on') + + // XXX hide all marks... + // XXX + } + + // start the timer... + // XXX might be a good idea to add a pause button for either + // "toggle" or "hold to pause" mode... + this.__slideshouw_timer = setInterval(function(){ + var cur = that.current + + // next step... + that.config['ui-slideshow-direction'] == 'next' ? + that.nextImage() + : that.prevImage() + + // we have reached the end... + if(that.current == cur && that.config['ui-slideshow-looping']){ + that.config['ui-slideshow-direction'] == 'next' ? + that.firstImage() + : that.lastImage() + } + }, Date.str2ms(this.config['ui-slideshow-interval'] || '3s')) + }], + // XXX restart the countdown to the next image... + // ...this is useful after manual navigation... + // XXX do we need this??? + // ...might be a good idea to use .toggleSlideshow('on') instead... + _resetSlideshowTimer: ['- Slideshow/', + function(){ + this._startSlideshow() + }], + _stopSlideshow: ['- Slideshow/', + function(){ + // stop timer... + clearTimeout(this.__slideshouw_timer) + delete this.__slideshouw_timer + + // XXX restore state... + // XXX + }], }) @@ -76,6 +149,7 @@ module.Slideshow = core.ImageGridFeatures.Feature({ tag: 'ui-slideshow', depends: [ 'ui', + 'ui-single-image-view', ], actions: SlideshowActions, diff --git a/ui (gen4)/features/ui.js b/ui (gen4)/features/ui.js index d7b6fef8..f076c67b 100755 --- a/ui (gen4)/features/ui.js +++ b/ui (gen4)/features/ui.js @@ -112,8 +112,7 @@ function updateImagePosition(actions, target){ // // XXX split this into read and write actions... var ViewerActions = -module.ViewerActions = -actions.Actions({ +module.ViewerActions = actions.Actions({ config: { // The maximum screen width allowed when zooming... 'max-screen-images': 30, @@ -692,7 +691,6 @@ actions.Actions({ this.reload() }], - }) var Viewer = @@ -752,6 +750,89 @@ module.Viewer = core.ImageGridFeatures.Feature({ }) + +//--------------------------------------------------------------------- +// +// Basic protocol: +// A participating feature should: +// - react to .saveWorkspace(..) by saving it's relevant state data to the +// object returned by the .saveWorkspace() action. +// NOTE: it is recommended that a feature save its relevant .config +// data as-is. +// - react to .loadWorkspace(..) by loading it's state from the returned +// object... +// - react to .toggleChrome(..) and switch on and off the chrome +// visibility... (XXX) +// +// + +var WorkspaceActions = +module.WorkspaceActions = actions.Actions({ + config: { + 'workspace': 'default', + 'chrome-visible': 'on', + + 'saved-workspaces': {}, + }, + + get workspace(){ + return this.config.workspace + }, + set workspace(value){ + this.loadWorkspace(value) + }, + + // NOTE: these are mainly triggers for other features to save/load + // their specific states... + // XXX for some reason this does not trigger a .config save... + saveWorkspace: ['Workspace/Save Workspace', + function(name){ + this.config['saved-workspaces'] = this.config['saved-workspaces'] + + var res = this.config['saved-workspaces'][name || this.config.workspace] = {} + + return res + }], + // NOTE: merging the state data is the responsibility of the feature + // ...this is done so as not to restrict the feature to one + // specific way to do stuff... + loadWorkspace: ['Workspace/Load Workspace', + function(name){ + this.config.workspace = name + + return this.config['saved-workspaces'][name] || {} + }], + + // toggle chrome on and off... + toggleChrome: ['Workspace|Interface/Toggle chrome', + base.makeConfigToggler('chrome-visible', + ['off', 'on'])], + toggleWorkspace: ['Workspace/Toggle Workspace', + base.makeConfigToggler('workspace', + function(){ return Object.keys(this.config['saved-workspaces']) }, + function(state){ this.loadWorkspace(state) })], +}) + + +module.Workspace = core.ImageGridFeatures.Feature({ + title: '', + + tag: 'ui-workspace', + + depends: [ + 'ui', + ], + + actions: WorkspaceActions, + + handlers: [ + ['stop', + function(){ this.saveWorkspace() }], + ], +}) + + + //--------------------------------------------------------------------- // Format: diff --git a/ui (gen4)/lib/jli.js b/ui (gen4)/lib/jli.js index 77728793..b6104d53 100755 --- a/ui (gen4)/lib/jli.js +++ b/ui (gen4)/lib/jli.js @@ -1101,6 +1101,29 @@ Date.timeStamp = function(){ Date.fromTimeStamp = function(ts){ return (new Date()).setTimeStamp(ts) } +// convert string time period to milliseconds... +Date.str2ms = function(str, dfl){ + dfl = dfl || 'ms' + + if(typeof(str) == typeof(123)){ + var val = str + str = dfl + + } else { + str = str.trim() + + var val = parseFloat(str) + } + + var c = /(m(illi)?(-)?s(ec(ond(s)?)?)?)$/i.test(str) ? 1 + : /s(ec(ond(s)?)?)?$/i.test(str) ? 1000 + : /m(in(ute(s)?)?)?$/i.test(str) ? 1000*60 + : /h(our(s)?)?$/i.test(str) ? 1000*60*60 + : /d(ay(s)?)?$/i.test(str) ? 1000*60*60*24 + : Date.str2ms(val, dfl) + + return val * c +} function logCalls(func, logger){