refactoring + .loadImagesAsRibbon(..)...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-01-23 20:49:05 +03:00
parent f8e149a8f5
commit 08492cbf35
8 changed files with 210 additions and 99 deletions

View File

@ -263,6 +263,19 @@ body {
font-weight: bolder !important; 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... */ /* Dialog highlight experiment... */
.browse-widget { .browse-widget {

View File

@ -204,13 +204,14 @@ actions.Actions({
this.images = images.Images(d.images) this.images = images.Images(d.images)
this.data = data.Data(d.data) this.data = data.Data(d.data)
}], }],
// XXX should this clear or load empty???
clear: ['File/Clear', clear: ['File/Clear',
{journal: true}, {journal: true},
function(){ function(){
//delete this.data //this.data = null
//delete this.images //this.images = null
this.data = null this.data = new data.DataWithTags()
this.images = null this.images = new images.Images()
}], }],
// NOTE: for complete isolation it is best to completely copy the // NOTE: for complete isolation it is best to completely copy the

View File

@ -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...
// //
// Load new images from current path... // Load new images from current path...
@ -846,6 +913,14 @@ var FileSystemLoaderUIActions = actions.Actions({
config: { config: {
// list of loaders to complete .browsePath(..) action // 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 // NOTE: these will be displayed in the same order as they appear
// in the list. // in the list.
// NOTE: the first one is auto-selected. // NOTE: the first one is auto-selected.
@ -853,6 +928,9 @@ var FileSystemLoaderUIActions = actions.Actions({
'loadIndex', 'loadIndex',
'loadImages', 'loadImages',
//'loadPath', //'loadPath',
'---',
'loadImagesAsRibbon: "$PATH" "above" -- Load images to new ribbon above',
'loadImagesAsRibbon: "$PATH" "below" -- Load images to new ribbon below',
], ],
'file-browser-settings': { 'file-browser-settings': {
@ -911,8 +989,29 @@ var FileSystemLoaderUIActions = actions.Actions({
} else { } else {
var loaders = {} var loaders = {}
that.config['path-loaders'].forEach(function(m){ that.config['path-loaders'].forEach(function(m){
loaders[that.getDoc(m)[m][0].split('/').pop()] = function(){ var a = keyboard.parseActionCall(m)
return that[m](path)
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() this.saveIndex()
} else { } else {
this.browseSaveIndex() this.browseExportIndex()
} }
}], }],
// XXX should this be a UI action??? // XXX should this be a UI action???

View File

@ -454,7 +454,6 @@ var URLHistoryUIActions = actions.Actions({
}) })
to_remove = [] to_remove = []
} }
var makeHistoryList = function(fs_state){ var makeHistoryList = function(fs_state){
fs_state = fs_state || {} fs_state = fs_state || {}
var history = Object.keys(that.url_history).reverse() var history = Object.keys(that.url_history).reverse()
@ -531,6 +530,19 @@ var URLHistoryUIActions = actions.Actions({
return list 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, var o = browse.makeLister(null,
function(path, make){ function(path, make){
@ -548,6 +560,8 @@ var URLHistoryUIActions = actions.Actions({
}, },
// add item buttons... // add item buttons...
{ itemButtons: [ { itemButtons: [
['<span class="show-on-hover">&#8599;</span>',
function(p){ o.browsePath(p) }],
// move to top... // move to top...
['&diams;', ['&diams;',
function(p){ function(p){
@ -640,6 +654,13 @@ var URLHistoryUIActions = actions.Actions({
return this 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 return o
})], })],
}) })
@ -654,58 +675,11 @@ module.URLHistoryUI = core.ImageGridFeatures.Feature({
'ui', 'ui',
'url-history', 'url-history',
], ],
suggested: [
'ui-url-history-browsable',
],
actions: URLHistoryUIActions, 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 }) * vim:set ts=4 sw=4 : */ return module })

View File

@ -101,6 +101,10 @@ var LocationActions = actions.Actions({
}, },
clearLoaction: ['File/Clear location',
function(){ delete this.__location }],
// Load location... // Load location...
// //
// Reload current location... // Reload current location...
@ -191,9 +195,7 @@ module.Location = core.ImageGridFeatures.Feature({
} }
}], }],
['clear', ['clear',
function(){ function(){ this.clearLoaction() }],
delete this.__location
}],
// 1) store .location // 1) store .location
// 2) cleanup .images[..].base_path // 2) cleanup .images[..].base_path

View File

@ -159,9 +159,20 @@ var DataPrototype = {
// .current (gid) // .current (gid)
// gid of the current image // 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) // .base (gid)
// gid of the base ribbon // 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 // .order
// List of image gids setting the image 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, // NOTE: this list may contain gids not loaded at the moment,
// a common case for this is when data is cropped. // a common case for this is when data is cropped.
// //
//
// .ribbon_order // .ribbon_order
// List of ribbon gids setting the ribbon order. // List of ribbon gids setting the ribbon order.
// //
// format: // format:
// [ gid, .. ] // [ gid, .. ]
// //
//
// .ribbons // .ribbons
// Dict of ribbons, indexed by ribbon gid, each ribbon is a // Dict of ribbons, indexed by ribbon gid, each ribbon is a
// sparse list of image gids. // sparse list of image gids.
@ -189,16 +202,17 @@ var DataPrototype = {
// //
/*****************************************************************/ /*****************************************************************/
// XXX is this a good name for this??? (see: object.js) get current(){
__init__: function(json){ return this.__current = this.__current
// load initial state... || this.getImages(this.ribbon_order[0])[0]
if(json != null){ || this.order[0] },
this.loadJSON(json) set current(value){
} else { this.__current = value },
this._reset()
} get base(){
return this 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... // no more ribbons left...
if(that.ribbon_order.length == 0){ if(that.ribbon_order.length == 0){
that.base = null delete that.__base
// shift base up or to first image... // shift base up or to first image...
} else if(that.base == gid){ } else if(that.base == gid){
@ -449,7 +463,7 @@ var DataPrototype = {
}) })
if(that.current == gid){ if(that.current == gid){
that.current = null delete that.__current
} }
} }
}) })
@ -1082,8 +1096,7 @@ var DataPrototype = {
}, },
// same as .getRibbon(..) but returns ribbon order... // same as .getRibbon(..) but returns ribbon order...
getRibbonOrder: function(target, offset){ 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(){ reverseRibbons: function(){
this.ribbon_order.reverse() this.ribbon_order.reverse() },
},
// Gather gids into a connected section... // Gather gids into a connected section...
@ -2479,8 +2491,9 @@ var DataPrototype = {
// Reset the state to empty... // Reset the state to empty...
// //
_reset: function(){ _reset: function(){
this.base = null delete this.__base
this.current = null delete this.__current
this.order = [] this.order = []
this.ribbon_order = [] this.ribbon_order = []
this.ribbons = {} this.ribbons = {}
@ -2554,6 +2567,20 @@ var DataPrototype = {
} }
return res 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 }) * vim:set ts=4 sw=4 : */ return module })

View File

@ -348,22 +348,8 @@ module.ImagesClassPrototype = {
var ImagesPrototype = var ImagesPrototype =
module.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(){ get length(){
return Object.keys(this).length return Object.keys(this).length },
},
// Generic iterators... // Generic iterators...
// //
@ -435,8 +421,7 @@ module.ImagesPrototype = {
}, },
keys: function(){ keys: function(){
return Object.keys(this) return Object.keys(this) },
},
// Build an image index relative to an attribute... // Build an image index relative to an attribute...
// //
@ -670,8 +655,7 @@ module.ImagesPrototype = {
clone: function(){ 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, // NOTE: this will join the other data into the current object in-place,
// use .clone() to preserve current data... // use .clone() to preserve current data...
join: function(other){ join: function(other){
@ -702,6 +686,18 @@ module.ImagesPrototype = {
_reset: function(){ _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
},
} }

View File

@ -1125,8 +1125,7 @@ var RibbonsPrototype = {
// Like .getRibbon(..) but returns ribbon index instead of the actual // Like .getRibbon(..) but returns ribbon index instead of the actual
// ribbon object... // ribbon object...
getRibbonOrder: function(target){ getRibbonOrder: function(target){
return this.viewer.find(RIBBON).index(this.getRibbon(target)) return this.viewer.find(RIBBON).index(this.getRibbon(target)) },
},
// Basic manipulation... // Basic manipulation...
@ -2090,8 +2089,7 @@ var RibbonsPrototype = {
// Get image rotation... // Get image rotation...
// //
getImageRotation: function(target){ getImageRotation: function(target){
return (this.getImage(target).attr('orientation') || 0)*1 return (this.getImage(target).attr('orientation') || 0)*1 },
},
// Rotate an image... // Rotate an image...
// //
// Rotate image clockwise: // Rotate image clockwise: