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;
}
.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 {

View File

@ -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

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 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???

View File

@ -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: [
['<span class="show-on-hover">&#8599;</span>',
function(p){ o.browsePath(p) }],
// move to top...
['&diams;',
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 })

View File

@ -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

View File

@ -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 })

View File

@ -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
},
}

View File

@ -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: