diff --git a/ui (gen4)/css/experimenting.css b/ui (gen4)/css/experimenting.css index 524badcd..efac1944 100755 --- a/ui (gen4)/css/experimenting.css +++ b/ui (gen4)/css/experimenting.css @@ -263,6 +263,19 @@ body { font-weight: bolder !important; } +.browse-widget .list>div .show-on-hover { + opacity: 0; +} +.browse-widget .list>div:hover .show-on-hover { + opacity: inherit; +} +.browse-widget .list>div .show-on-select { + opacity: 0; +} +.browse-widget .list>.selected .show-on-select { + opacity: inherit; +} + /* Dialog highlight experiment... */ .browse-widget { diff --git a/ui (gen4)/features/base.js b/ui (gen4)/features/base.js index e7a70732..68d82cdf 100755 --- a/ui (gen4)/features/base.js +++ b/ui (gen4)/features/base.js @@ -204,13 +204,14 @@ actions.Actions({ this.images = images.Images(d.images) this.data = data.Data(d.data) }], + // XXX should this clear or load empty??? clear: ['File/Clear', {journal: true}, function(){ - //delete this.data - //delete this.images - this.data = null - this.images = null + //this.data = null + //this.images = null + this.data = new data.DataWithTags() + this.images = new images.Images() }], // NOTE: for complete isolation it is best to completely copy the diff --git a/ui (gen4)/features/filesystem.js b/ui (gen4)/features/filesystem.js index 885dca7d..50c8c757 100755 --- a/ui (gen4)/features/filesystem.js +++ b/ui (gen4)/features/filesystem.js @@ -668,6 +668,73 @@ var FileSystemLoaderActions = actions.Actions({ }) }], + // + // .loadImagesAsRibbon(path[, logger]) + // -> promise + // + // .loadImagesAsRibbon(path, 'above'[, logger]) + // .loadImagesAsRibbon(path, 'below'[, logger]) + // -> promise + // + // NOTE: this does not touch .location + // + // XXX EXPERIMENTAL... + // XXX should this be usable only in crops??? + // ....also would be a good idea to add things like .removeRibbon(..)... + loadImagesAsRibbon: ['- File/Load images into ribbon', + function(path, direction, logger){ + var that = this + if(path == null){ + return + } + + if(logger === undefined + && direction + && typeof(direction) != typeof('str')){ + logger = direction + direction = null + } + + direction = direction || 'below' + + console.log('>>>>', direction) + + logger = logger || this.logger + logger = logger && logger.push('Load images to ribbon') + + return this.getImagesInPath( + path, + that.config['image-file-read-stat'], + that.config['image-file-skip-previews'], + logger) + // load the data... + .then(function(imgs){ + that.clearLoaction() + + var d = that.data + var nd = data.Data.fromArray(imgs.keys()) + + var r = d.getRibbon() + + // splice the order... + d.order.splice.apply(d.order, + [d.order.indexOf(d.current)+1, 0] + .concat(nd.order)) + + // new ribbon and data... + var n = d.newRibbon(r, direction) + d.ribbons[n] = nd.ribbons[nd.ribbon_order[0]] + + // sort elements within the new ribbon... + d.updateImagePositions() + + // join images... + that.images.join(imgs) + + that.reload(true) + }) + }], + // Load new images... // // Load new images from current path... @@ -846,6 +913,14 @@ var FileSystemLoaderUIActions = actions.Actions({ config: { // list of loaders to complete .browsePath(..) action // + // The loader can be action name or a keyboard.parseActionCall(..) + // compatible syntax. + // + // If an argument string containing "$PATH" is passed then it + // will be replaces by the selected path... + // Example: + // 'someAction: "$PATH" -- doc' + // // NOTE: these will be displayed in the same order as they appear // in the list. // NOTE: the first one is auto-selected. @@ -853,6 +928,9 @@ var FileSystemLoaderUIActions = actions.Actions({ 'loadIndex', 'loadImages', //'loadPath', + '---', + 'loadImagesAsRibbon: "$PATH" "above" -- Load images to new ribbon above', + 'loadImagesAsRibbon: "$PATH" "below" -- Load images to new ribbon below', ], 'file-browser-settings': { @@ -911,8 +989,29 @@ var FileSystemLoaderUIActions = actions.Actions({ } else { var loaders = {} that.config['path-loaders'].forEach(function(m){ - loaders[that.getDoc(m)[m][0].split('/').pop()] = function(){ - return that[m](path) + var a = keyboard.parseActionCall(m) + + if(a.action in that){ + var args = a.arguments + // empty args... + args = args.length == 0 ? + [path] + : args + // replace the path placeholder... + var i = args.indexOf('$PATH') + i >= 0 + && args.splice(i, 1, path) + + // the callback... + loaders[a.doc != '' ? + a.doc + : that.getDocTitle(a.action)] = + function(){ + return that[a.action].apply(that, a.arguments) } + + // non-actions... + } else { + loaders[m] = null } }) } @@ -2232,7 +2331,7 @@ var FileSystemWriterUIActions = actions.Actions({ this.saveIndex() } else { - this.browseSaveIndex() + this.browseExportIndex() } }], // XXX should this be a UI action??? diff --git a/ui (gen4)/features/history.js b/ui (gen4)/features/history.js index c64d5077..d16e178a 100755 --- a/ui (gen4)/features/history.js +++ b/ui (gen4)/features/history.js @@ -454,7 +454,6 @@ var URLHistoryUIActions = actions.Actions({ }) to_remove = [] } - var makeHistoryList = function(fs_state){ fs_state = fs_state || {} var history = Object.keys(that.url_history).reverse() @@ -531,6 +530,19 @@ var URLHistoryUIActions = actions.Actions({ return list } + // this will take care of any number of child dialogs... + // XXX should this be generic??? + var onOpen = function(){ + // we are the top dialog --> close... + if(that.modal.client === o){ + o.close() + + // child dialog, ask to close us when opening... + } else { + that.modal.client.open(onOpen) + } + } + var o = browse.makeLister(null, function(path, make){ @@ -548,6 +560,8 @@ var URLHistoryUIActions = actions.Actions({ }, // add item buttons... { itemButtons: [ + ['', + function(p){ o.browsePath(p) }], // move to top... ['♦', function(p){ @@ -640,6 +654,13 @@ var URLHistoryUIActions = actions.Actions({ return this } + // handle 'O' button to browse path... + o.browsePath = function(p){ + that.browsePath(p || this.selected).open(onOpen) } + // clone the bindings so as not to mess up the global browser... + o.keybindings = JSON.parse(JSON.stringify(o.keybindings)) + o.keyboard.handler('General', 'O', 'browsePath') + return o })], }) @@ -654,58 +675,11 @@ module.URLHistoryUI = core.ImageGridFeatures.Feature({ 'ui', 'url-history', ], - suggested: [ - 'ui-url-history-browsable', - ], - actions: URLHistoryUIActions, }) -//--------------------------------------------------------------------- - -var URLHistoryUIBrowsable = -module.URLHistoryUIBrowsable = core.ImageGridFeatures.Feature({ - title: '', - doc: '', - - tag: 'ui-url-history-browsable', - depends: [ - 'ui', - 'url-history', - 'ui-fs-loader', - ], - - handlers: [ - ['listURLHistory', - function(dialog){ - var that = this - - // this will take care of any number of child dialogs... - var onOpen = function(){ - // we are the top dialog --> close... - if(that.modal.client === dialog){ - dialog.close() - - // child dialog, ask to close us when opening... - } else { - that.modal.client.open(onOpen) - } - } - - dialog.browsePath = function(){ - that.browsePath(this.selected).open(onOpen) } - - // clone the bindings so as not to mess up the global browser... - dialog.keybindings = JSON.parse(JSON.stringify(dialog.keybindings)) - - dialog.keyboard.handler('General', 'O', 'browsePath') - }]], -}) - - - /********************************************************************** * vim:set ts=4 sw=4 : */ return module }) diff --git a/ui (gen4)/features/location.js b/ui (gen4)/features/location.js index 1d89dcb8..28737e6f 100755 --- a/ui (gen4)/features/location.js +++ b/ui (gen4)/features/location.js @@ -101,6 +101,10 @@ var LocationActions = actions.Actions({ }, + clearLoaction: ['File/Clear location', + function(){ delete this.__location }], + + // Load location... // // Reload current location... @@ -191,9 +195,7 @@ module.Location = core.ImageGridFeatures.Feature({ } }], ['clear', - function(){ - delete this.__location - }], + function(){ this.clearLoaction() }], // 1) store .location // 2) cleanup .images[..].base_path diff --git a/ui (gen4)/imagegrid/data.js b/ui (gen4)/imagegrid/data.js index cc8a450e..475c7b51 100755 --- a/ui (gen4)/imagegrid/data.js +++ b/ui (gen4)/imagegrid/data.js @@ -158,10 +158,21 @@ var DataPrototype = { // // .current (gid) // gid of the current image + // + // NOTE: if no current image is set explicitly this defaults + // to first image in first ribbon, or first in .order. + // // // .base (gid) // gid of the base ribbon // + // NOTE: if no base ribbon is explicitly set, this defaults to + // last ribbon. + // This may not seem logical at first but this is by design + // behavior, the goal is to keep all sets not explicitly + // aligned (i.e. sorted) be misaligned by default. + // + // // .order // List of image gids setting the image order // @@ -171,12 +182,14 @@ var DataPrototype = { // NOTE: this list may contain gids not loaded at the moment, // a common case for this is when data is cropped. // + // // .ribbon_order // List of ribbon gids setting the ribbon order. // // format: // [ gid, .. ] // + // // .ribbons // Dict of ribbons, indexed by ribbon gid, each ribbon is a // sparse list of image gids. @@ -189,16 +202,17 @@ var DataPrototype = { // /*****************************************************************/ - // XXX is this a good name for this??? (see: object.js) - __init__: function(json){ - // load initial state... - if(json != null){ - this.loadJSON(json) - } else { - this._reset() - } - return this - }, + get current(){ + return this.__current = this.__current + || this.getImages(this.ribbon_order[0])[0] + || this.order[0] }, + set current(value){ + this.__current = value }, + + get base(){ + return this.__base || this.ribbon_order.slice(-1)[0] }, + set base(value){ + this.__base = value }, @@ -432,7 +446,7 @@ var DataPrototype = { // no more ribbons left... if(that.ribbon_order.length == 0){ - that.base = null + delete that.__base // shift base up or to first image... } else if(that.base == gid){ @@ -449,7 +463,7 @@ var DataPrototype = { }) if(that.current == gid){ - that.current = null + delete that.__current } } }) @@ -1082,8 +1096,7 @@ var DataPrototype = { }, // same as .getRibbon(..) but returns ribbon order... getRibbonOrder: function(target, offset){ - return this.ribbon_order.indexOf(this.getRibbon(target, offset)) - }, + return this.ribbon_order.indexOf(this.getRibbon(target, offset)) }, @@ -1313,8 +1326,7 @@ var DataPrototype = { }, reverseRibbons: function(){ - this.ribbon_order.reverse() - }, + this.ribbon_order.reverse() }, // Gather gids into a connected section... @@ -2479,8 +2491,9 @@ var DataPrototype = { // Reset the state to empty... // _reset: function(){ - this.base = null - this.current = null + delete this.__base + delete this.__current + this.order = [] this.ribbon_order = [] this.ribbons = {} @@ -2554,6 +2567,20 @@ var DataPrototype = { } return res }, + + + + /*****************************************************************/ + // XXX is this a good name for this??? (see: object.js) + __init__: function(json){ + // load initial state... + if(json != null){ + this.loadJSON(json) + } else { + this._reset() + } + return this + }, } @@ -2975,5 +3002,6 @@ module.Data = DataWithTags + /********************************************************************** * vim:set ts=4 sw=4 : */ return module }) diff --git a/ui (gen4)/imagegrid/images.js b/ui (gen4)/imagegrid/images.js index 0c9092fa..c8b85458 100755 --- a/ui (gen4)/imagegrid/images.js +++ b/ui (gen4)/imagegrid/images.js @@ -348,22 +348,8 @@ module.ImagesClassPrototype = { var ImagesPrototype = module.ImagesPrototype = { - - // XXX is this a good name for this??? (see: object.js) - __init__: function(json){ - // load initial state... - if(json != null){ - this.loadJSON(json) - } else { - this._reset() - } - return this - }, - - get length(){ - return Object.keys(this).length - }, + return Object.keys(this).length }, // Generic iterators... // @@ -435,8 +421,7 @@ module.ImagesPrototype = { }, keys: function(){ - return Object.keys(this) - }, + return Object.keys(this) }, // Build an image index relative to an attribute... // @@ -670,8 +655,7 @@ module.ImagesPrototype = { clone: function(){ - return (new Images()).loadJSON(this.dumpJSON()) - }, + return (new Images()).loadJSON(this.dumpJSON()) }, // NOTE: this will join the other data into the current object in-place, // use .clone() to preserve current data... join: function(other){ @@ -702,6 +686,18 @@ module.ImagesPrototype = { _reset: function(){ }, + + + // XXX is this a good name for this??? (see: object.js) + __init__: function(json){ + // load initial state... + if(json != null){ + this.loadJSON(json) + } else { + this._reset() + } + return this + }, } diff --git a/ui (gen4)/imagegrid/ribbons.js b/ui (gen4)/imagegrid/ribbons.js index 2633d59b..5d607620 100755 --- a/ui (gen4)/imagegrid/ribbons.js +++ b/ui (gen4)/imagegrid/ribbons.js @@ -1125,8 +1125,7 @@ var RibbonsPrototype = { // Like .getRibbon(..) but returns ribbon index instead of the actual // ribbon object... getRibbonOrder: function(target){ - return this.viewer.find(RIBBON).index(this.getRibbon(target)) - }, + return this.viewer.find(RIBBON).index(this.getRibbon(target)) }, // Basic manipulation... @@ -2090,8 +2089,7 @@ var RibbonsPrototype = { // Get image rotation... // getImageRotation: function(target){ - return (this.getImage(target).attr('orientation') || 0)*1 - }, + return (this.getImage(target).attr('orientation') || 0)*1 }, // Rotate an image... // // Rotate image clockwise: