mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 18:30:09 +00:00
cleanup and refactoring...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
22627468eb
commit
32fc5dc9b4
@ -26,7 +26,6 @@ require('features/ui-virtual-dom')
|
|||||||
require('features/ui-react')
|
require('features/ui-react')
|
||||||
// XXX
|
// XXX
|
||||||
require('features/ui-partial-ribbons-precache')
|
require('features/ui-partial-ribbons-precache')
|
||||||
require('features/ui-partial-ribbons')
|
|
||||||
require('features/ui-partial-ribbons-2')
|
require('features/ui-partial-ribbons-2')
|
||||||
require('features/ui-partial-ribbons-vdom')
|
require('features/ui-partial-ribbons-vdom')
|
||||||
require('features/ui-single-image')
|
require('features/ui-single-image')
|
||||||
|
|||||||
@ -71,6 +71,7 @@ core.ImageGridFeatures.Feature('viewer-testing', [
|
|||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
'ui-ribbons-render',
|
'ui-ribbons-render',
|
||||||
|
'ui-partial-ribbons-render',
|
||||||
'ui-vdom-render',
|
'ui-vdom-render',
|
||||||
//'ui-react-render',
|
//'ui-react-render',
|
||||||
//*/
|
//*/
|
||||||
|
|||||||
@ -1,199 +0,0 @@
|
|||||||
/**********************************************************************
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
**********************************************************************/
|
|
||||||
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
|
|
||||||
(function(require){ var module={} // make module AMD/node compatible...
|
|
||||||
/*********************************************************************/
|
|
||||||
|
|
||||||
var actions = require('lib/actions')
|
|
||||||
var features = require('lib/features')
|
|
||||||
|
|
||||||
var core = require('features/core')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
|
|
||||||
// NOTE: this is split out to an action so as to enable ui elements to
|
|
||||||
// adapt to ribbon size changes...
|
|
||||||
//
|
|
||||||
// XXX try using .ribbons.resizeRibbon(..) for basic tasks...
|
|
||||||
// XXX try a strategy: load more in the direction of movement by an offset...
|
|
||||||
// XXX updateRibbon(..) is not signature compatible with data.updateRibbon(..)
|
|
||||||
var PartialRibbonsActions = actions.Actions({
|
|
||||||
config: {
|
|
||||||
// Number of screen widths to load...
|
|
||||||
'ribbon-size-screens': 7,
|
|
||||||
|
|
||||||
// Number of screen widths to edge to trigger reload...
|
|
||||||
'ribbon-resize-threshold': 1.5,
|
|
||||||
|
|
||||||
// Timeout before a non-forced ribbon size update happens after
|
|
||||||
// the action...
|
|
||||||
// NOTE: if set to null, the update will be sync...
|
|
||||||
'ribbon-update-timeout': 120,
|
|
||||||
},
|
|
||||||
|
|
||||||
// NOTE: this will force sync resize if one of the following is true:
|
|
||||||
// - the target is not loaded
|
|
||||||
// - we are less than screen width from the edge
|
|
||||||
// - threshold is set to 0
|
|
||||||
// XXX this is not signature compatible with data.updateRibbon(..)
|
|
||||||
// XXX do not do anything for off-screen ribbons...
|
|
||||||
updateRibbon: ['- Interface/Update partial ribbon size',
|
|
||||||
function(target, w, size, threshold){
|
|
||||||
target = target instanceof jQuery
|
|
||||||
? this.ribbons.getElemGID(target)
|
|
||||||
// NOTE: data.getImage(..) can return null at start or end
|
|
||||||
// of ribbon, thus we need to account for this...
|
|
||||||
: (this.data.getImage(target)
|
|
||||||
|| this.data.getImage(target, 'after'))
|
|
||||||
|
|
||||||
w = w || this.screenwidth
|
|
||||||
|
|
||||||
// get config data and normalize...
|
|
||||||
size = (size
|
|
||||||
|| this.config['ribbon-size-screens']
|
|
||||||
|| 5) * w
|
|
||||||
threshold = threshold == 0 ? threshold
|
|
||||||
: (threshold
|
|
||||||
|| this.config['ribbon-resize-threshold']
|
|
||||||
|| 1) * w
|
|
||||||
|
|
||||||
var timeout = this.config['ribbon-update-timeout']
|
|
||||||
|
|
||||||
// next/prev loaded...
|
|
||||||
var img = this.ribbons.getImage(target)
|
|
||||||
var nl = img.nextAll('.image:not(.clone)').length
|
|
||||||
var pl = img.prevAll('.image:not(.clone)').length
|
|
||||||
|
|
||||||
// next/prev available...
|
|
||||||
// NOTE: we subtract 1 to remove the current and make these
|
|
||||||
// compatible with: nl, pl
|
|
||||||
var na = this.data.getImages(target, size, 'after').length - 1
|
|
||||||
var pa = this.data.getImages(target, size, 'before').length - 1
|
|
||||||
|
|
||||||
// do the update...
|
|
||||||
// no threshold means force load...
|
|
||||||
if(threshold == 0
|
|
||||||
// the target is not loaded...
|
|
||||||
|| img.length == 0
|
|
||||||
// passed hard threshold on the right...
|
|
||||||
|| (nl < w && na > nl)
|
|
||||||
// passed hard threshold on the left...
|
|
||||||
|| (pl < w && pa > pl)){
|
|
||||||
|
|
||||||
this.resizeRibbon(target, size)
|
|
||||||
|
|
||||||
// do a late resize...
|
|
||||||
// loaded more than we need (crop?)...
|
|
||||||
} else if(na + pa < nl + pl
|
|
||||||
// passed threshold on the right...
|
|
||||||
|| (nl < threshold && na > nl)
|
|
||||||
// passed threshold on the left...
|
|
||||||
|| (pl < threshold && pa > pl)
|
|
||||||
// loaded more than we need by threshold...
|
|
||||||
|| nl + pl + 1 > size + threshold){
|
|
||||||
|
|
||||||
return function(){
|
|
||||||
// sync update...
|
|
||||||
if(timeout == null){
|
|
||||||
this.resizeRibbon(target, size)
|
|
||||||
|
|
||||||
// async update...
|
|
||||||
} else {
|
|
||||||
// XXX need to check if we are too close to the edge...
|
|
||||||
var that = this
|
|
||||||
//setTimeout(function(){ that.resizeRibbon(target, size) }, 0)
|
|
||||||
if(this.__update_timeout){
|
|
||||||
clearTimeout(this.__update_timeout)
|
|
||||||
}
|
|
||||||
this.__update_timeout = setTimeout(function(){
|
|
||||||
delete that.__update_timeout
|
|
||||||
that.resizeRibbon(target, size)
|
|
||||||
}, timeout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
|
|
||||||
// NOTE: I do not fully understand it yet, but PartialRibbons must be
|
|
||||||
// setup BEFORE RibbonAlignToFirst, otherwise the later will break
|
|
||||||
// on shifting an image to a new ribbon...
|
|
||||||
// To reproduce:
|
|
||||||
// - setupe RibbonAlignToFirst first
|
|
||||||
// - go to top ribbon
|
|
||||||
// - shift image up
|
|
||||||
// XXX The two should be completely independent.... (???)
|
|
||||||
var PartialRibbons =
|
|
||||||
module.PartialRibbons = core.ImageGridFeatures.Feature({
|
|
||||||
title: 'Partial Ribbons',
|
|
||||||
doc: core.doc`Maintains partially loaded ribbons, this enables very large
|
|
||||||
image sets to be handled efficiently.`,
|
|
||||||
|
|
||||||
// NOTE: partial ribbons needs to be setup first...
|
|
||||||
// ...the reasons why things break otherwise is not too clear.
|
|
||||||
priority: 'high',
|
|
||||||
|
|
||||||
tag: 'ui-partial-ribbons',
|
|
||||||
exclusive: ['ui-partial-ribbons'],
|
|
||||||
depends: [
|
|
||||||
'ui'
|
|
||||||
],
|
|
||||||
suggested: [
|
|
||||||
'ui-partial-ribbons-precache',
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
actions: PartialRibbonsActions,
|
|
||||||
|
|
||||||
handlers: [
|
|
||||||
['focusImage.pre centerImage.pre',
|
|
||||||
function(target, list){
|
|
||||||
// NOTE: we have to do this as we are called BEFORE the
|
|
||||||
// actual focus change happens...
|
|
||||||
// XXX is there a better way to do this???
|
|
||||||
target = list != null ? target = this.data.getImage(target, list) : target
|
|
||||||
|
|
||||||
this.updateRibbon(target)
|
|
||||||
}],
|
|
||||||
['resizing.pre',
|
|
||||||
function(unit, size){
|
|
||||||
// keep constant size in single image...
|
|
||||||
if(this.toggleSingleImage && this.toggleSingleImage('?') == 'on'){
|
|
||||||
this.updateRibbon(
|
|
||||||
'current',
|
|
||||||
this.config['ribbons-resize-single-image'] || 13)
|
|
||||||
|
|
||||||
} else if(unit == 'scale'){
|
|
||||||
this.updateRibbon('current', this.screenwidth / size || 1)
|
|
||||||
|
|
||||||
} else if(unit == 'screenwidth'){
|
|
||||||
this.updateRibbon('current', size || 1)
|
|
||||||
|
|
||||||
} else if(unit == 'screenheight'){
|
|
||||||
size = size || 1
|
|
||||||
|
|
||||||
// convert target height in ribbons to width in images...
|
|
||||||
// NOTE: this does not account for compensation that
|
|
||||||
// .updateRibbon(..) makes for fitting whole image
|
|
||||||
// counts, this is a small enough error so as not
|
|
||||||
// to waste time on...
|
|
||||||
var s = this.ribbons.scale()
|
|
||||||
var h = this.ribbons.getScreenHeightRibbons()
|
|
||||||
var w = this.ribbons.getScreenWidthImages()
|
|
||||||
var nw = w / (h/size)
|
|
||||||
|
|
||||||
this.updateRibbon('current', nw)
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* vim:set ts=4 sw=4 : */ return module })
|
|
||||||
@ -18,8 +18,88 @@ var ribbons = require('imagegrid/ribbons')
|
|||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
// helpers...
|
||||||
|
|
||||||
var RibbonsActions = actions.Actions({
|
// XXX make this compatible with multiple images...
|
||||||
|
// XXX for muptiple targets this will just do a .reload()...
|
||||||
|
var updateImagePosition =
|
||||||
|
function updateImagePosition(actions, target){
|
||||||
|
var s = actions.ribbons.getRibbonLocator()
|
||||||
|
|
||||||
|
if(s.length == 0){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
target = target || actions.current
|
||||||
|
target = target instanceof jQuery
|
||||||
|
? actions.ribbons.getElemGID(target)
|
||||||
|
: target
|
||||||
|
|
||||||
|
var source_ribbon = actions.ribbons.getElemGID(actions.ribbons.getRibbon(target))
|
||||||
|
var source_order = actions.data.getImageOrder(target)
|
||||||
|
|
||||||
|
return function(){
|
||||||
|
actions.ribbons.preventTransitions(s)
|
||||||
|
var end = function(){
|
||||||
|
// XXX not sure why this does not work without a setTimeout(..)
|
||||||
|
//actions.ribbons.restoreTransitions(s, true)
|
||||||
|
setTimeout(function(){
|
||||||
|
actions.ribbons.restoreTransitions(s, true) }, 0) }
|
||||||
|
|
||||||
|
// XXX hack???
|
||||||
|
if(target instanceof Array){
|
||||||
|
actions.reload()
|
||||||
|
return end()
|
||||||
|
}
|
||||||
|
|
||||||
|
var target_ribbon = actions.data.getRibbon(target)
|
||||||
|
|
||||||
|
// nothing changed...
|
||||||
|
if(source_ribbon == target_ribbon
|
||||||
|
&& actions.data.getImageOrder(target) == source_order){
|
||||||
|
return end()
|
||||||
|
}
|
||||||
|
|
||||||
|
// place image at position...
|
||||||
|
var to = actions.data.getImage(target, 'next')
|
||||||
|
if(to != null){
|
||||||
|
actions.ribbons.placeImage(target, to, 'before')
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// place image after position...
|
||||||
|
to = actions.data.getImage(target, 'prev')
|
||||||
|
if(to != null){
|
||||||
|
actions.ribbons.placeImage(target, to, 'after')
|
||||||
|
|
||||||
|
// new ribbon...
|
||||||
|
} else {
|
||||||
|
to = actions.data.getRibbon(target)
|
||||||
|
|
||||||
|
if(actions.ribbons.getRibbon(to).length == 0){
|
||||||
|
actions.ribbons
|
||||||
|
.placeRibbon(to, actions.data.getRibbonOrder(target))
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.ribbons.placeImage(target, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(actions.data.getImages(source_ribbon).length == 0){
|
||||||
|
actions.ribbons.getRibbon(source_ribbon).remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.focusImage()
|
||||||
|
|
||||||
|
return end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
|
||||||
|
var RibbonsActions =
|
||||||
|
actions.Actions({
|
||||||
|
|
||||||
get dom(){
|
get dom(){
|
||||||
return this.ribbons ? this.ribbons.viewer : undefined },
|
return this.ribbons ? this.ribbons.viewer : undefined },
|
||||||
@ -351,14 +431,12 @@ var RibbonsActions = actions.Actions({
|
|||||||
return this.ribbons.rotate() || 0
|
return this.ribbons.rotate() || 0
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
|
||||||
// XXX move all the stuff from UI that binds actions to ribbons...
|
|
||||||
// XXX
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
var Ribbons =
|
var Ribbons =
|
||||||
module.Ribbons = core.ImageGridFeatures.Feature({
|
module.Ribbons =
|
||||||
|
core.ImageGridFeatures.Feature({
|
||||||
title: '',
|
title: '',
|
||||||
doc: '',
|
doc: '',
|
||||||
|
|
||||||
@ -379,53 +457,309 @@ module.Ribbons = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// XXX
|
|
||||||
|
|
||||||
var PartialRibbonsActions = actions.Actions({
|
var RibbonsEditActions =
|
||||||
|
actions.Actions({
|
||||||
|
setBaseRibbon: [
|
||||||
|
function(target){
|
||||||
|
var r = this.data.getRibbon(target)
|
||||||
|
r = r == null ? this.ribbons.getRibbon(target) : r
|
||||||
|
this.ribbons.setBaseRibbon(r)
|
||||||
|
}],
|
||||||
|
shiftImageLeft: [
|
||||||
|
function(target){ this.ribbons.placeImage(target, -1) }],
|
||||||
|
shiftImageRight: [
|
||||||
|
function(target){ this.ribbons.placeImage(target, 1) }],
|
||||||
|
shiftRibbonUp: [
|
||||||
|
function(target){
|
||||||
|
target = this.ribbons.getRibbon(target)
|
||||||
|
var i = this.ribbons.getRibbonOrder(target)
|
||||||
|
if(i > 0){
|
||||||
|
this.ribbons.placeRibbon(target, i-1)
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
shiftRibbonDown: [
|
||||||
|
function(target){
|
||||||
|
target = this.ribbons.getRibbon(target)
|
||||||
|
var i = this.ribbons.getRibbonOrder(target)
|
||||||
|
if(i < this.data.ribbon_order.length-1){
|
||||||
|
this.ribbons.placeRibbon(target, i+1)
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
|
||||||
|
// basic image editing...
|
||||||
|
//
|
||||||
|
// XXX should we have .rotate(..) and .flip(..) generic actions???
|
||||||
|
rotateCW: [
|
||||||
|
function(target){ this.ribbons.rotateCW(target) }],
|
||||||
|
rotateCCW: [
|
||||||
|
function(target){ this.ribbons.rotateCCW(target) }],
|
||||||
|
flipVertical: [
|
||||||
|
function(target){ this.ribbons.flipVertical(target, 'view') }],
|
||||||
|
flipHorizontal: [
|
||||||
|
function(target){ this.ribbons.flipHorizontal(target, 'view') }],
|
||||||
|
|
||||||
|
// tags...
|
||||||
|
tag: [
|
||||||
|
function(tags, gids){
|
||||||
|
gids = gids != null && gids.constructor !== Array ? [gids] : gids
|
||||||
|
return function(){
|
||||||
|
//this.ribbons.updateImage(gids)
|
||||||
|
this.refresh(gids)
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
untag: [
|
||||||
|
function(tags, gids){
|
||||||
|
gids = gids != null && gids.constructor !== Array ? [gids] : gids
|
||||||
|
return function(){
|
||||||
|
//this.ribbons.updateImage(gids)
|
||||||
|
this.refresh(gids)
|
||||||
|
}
|
||||||
|
}],
|
||||||
})
|
})
|
||||||
|
|
||||||
var PartialRibbons =
|
|
||||||
module.PartialRibbons = core.ImageGridFeatures.Feature({
|
|
||||||
title: '',
|
|
||||||
doc: '',
|
|
||||||
|
|
||||||
tag: 'ui-partial-ribbons-render',
|
|
||||||
exclusive: ['ui-render'],
|
|
||||||
depends: [
|
|
||||||
// XXX this will need to reuse part of the actions defined in Ribbons...
|
|
||||||
],
|
|
||||||
suggested: [
|
|
||||||
'ui-ribbons-edit-render',
|
|
||||||
],
|
|
||||||
|
|
||||||
actions: PartialRibbonsActions,
|
|
||||||
|
|
||||||
handlers: [],
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
|
||||||
var RibbonsEditActions = actions.Actions({
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
var RibbonsEdit =
|
var RibbonsEdit =
|
||||||
module.RibbonsEdit = core.ImageGridFeatures.Feature({
|
module.RibbonsEdit =
|
||||||
|
core.ImageGridFeatures.Feature({
|
||||||
title: '',
|
title: '',
|
||||||
doc: '',
|
doc: '',
|
||||||
|
|
||||||
tag: 'ui-ribbons-edit-render',
|
tag: 'ui-ribbons-edit-render',
|
||||||
depends: [
|
depends: [
|
||||||
'edit',
|
'edit',
|
||||||
|
'tags',
|
||||||
|
'sort',
|
||||||
|
'crop',
|
||||||
|
'image-group',
|
||||||
|
'ui-ribbons-render',
|
||||||
],
|
],
|
||||||
|
|
||||||
actions: RibbonsEditActions,
|
actions: RibbonsEditActions,
|
||||||
|
|
||||||
handlers: [],
|
handlers: [
|
||||||
|
[[
|
||||||
|
'shiftImageTo.pre',
|
||||||
|
'shiftImageUp.pre',
|
||||||
|
'shiftImageDown.pre',
|
||||||
|
],
|
||||||
|
function(target){
|
||||||
|
return updateImagePosition(this, target) }],
|
||||||
|
|
||||||
|
|
||||||
|
// manage the .crop-mode css class...
|
||||||
|
['crop uncrop',
|
||||||
|
function(){
|
||||||
|
this.dom[this.cropped ?
|
||||||
|
'addClass'
|
||||||
|
: 'removeClass']('crop-mode')
|
||||||
|
}],
|
||||||
|
|
||||||
|
// reloading and updating...
|
||||||
|
[[
|
||||||
|
'sortImages',
|
||||||
|
'alignToRibbon',
|
||||||
|
'group',
|
||||||
|
'ungroup',
|
||||||
|
'groupTo',
|
||||||
|
'groupMarked',
|
||||||
|
'expandGroup',
|
||||||
|
'collapseGroup',
|
||||||
|
'crop',
|
||||||
|
'uncrop',
|
||||||
|
],
|
||||||
|
function(target){ return this.reload(true) }],
|
||||||
|
[[
|
||||||
|
'reverseImages',
|
||||||
|
'reverseRibbons',
|
||||||
|
'cropGroup',
|
||||||
|
],
|
||||||
|
function(target){ return this.reload() }],
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
// Partial ribbons...
|
||||||
|
|
||||||
|
// XXX try using .ribbons.resizeRibbon(..) for basic tasks...
|
||||||
|
// XXX try a strategy: load more in the direction of movement by an offset...
|
||||||
|
// XXX updateRibbon(..) is not signature compatible with data.updateRibbon(..)
|
||||||
|
var PartialRibbonsActions =
|
||||||
|
actions.Actions({
|
||||||
|
config: {
|
||||||
|
// Number of screen widths to load...
|
||||||
|
'ribbon-size-screens': 7,
|
||||||
|
|
||||||
|
// Number of screen widths to edge to trigger reload...
|
||||||
|
'ribbon-resize-threshold': 1.5,
|
||||||
|
|
||||||
|
// Timeout before a non-forced ribbon size update happens after
|
||||||
|
// the action...
|
||||||
|
// NOTE: if set to null, the update will be sync...
|
||||||
|
'ribbon-update-timeout': 120,
|
||||||
|
},
|
||||||
|
|
||||||
|
// NOTE: this will force sync resize if one of the following is true:
|
||||||
|
// - the target is not loaded
|
||||||
|
// - we are less than screen width from the edge
|
||||||
|
// - threshold is set to 0
|
||||||
|
// XXX this is not signature compatible with data.updateRibbon(..)
|
||||||
|
// XXX do not do anything for off-screen ribbons...
|
||||||
|
updateRibbon: ['- Interface/Update partial ribbon size',
|
||||||
|
function(target, w, size, threshold){
|
||||||
|
target = target instanceof jQuery
|
||||||
|
? this.ribbons.getElemGID(target)
|
||||||
|
// NOTE: data.getImage(..) can return null at start or end
|
||||||
|
// of ribbon, thus we need to account for this...
|
||||||
|
: (this.data.getImage(target)
|
||||||
|
|| this.data.getImage(target, 'after'))
|
||||||
|
|
||||||
|
w = w || this.screenwidth
|
||||||
|
|
||||||
|
// get config data and normalize...
|
||||||
|
size = (size
|
||||||
|
|| this.config['ribbon-size-screens']
|
||||||
|
|| 5) * w
|
||||||
|
threshold = threshold == 0 ? threshold
|
||||||
|
: (threshold
|
||||||
|
|| this.config['ribbon-resize-threshold']
|
||||||
|
|| 1) * w
|
||||||
|
|
||||||
|
var timeout = this.config['ribbon-update-timeout']
|
||||||
|
|
||||||
|
// next/prev loaded...
|
||||||
|
var img = this.ribbons.getImage(target)
|
||||||
|
var nl = img.nextAll('.image:not(.clone)').length
|
||||||
|
var pl = img.prevAll('.image:not(.clone)').length
|
||||||
|
|
||||||
|
// next/prev available...
|
||||||
|
// NOTE: we subtract 1 to remove the current and make these
|
||||||
|
// compatible with: nl, pl
|
||||||
|
var na = this.data.getImages(target, size, 'after').length - 1
|
||||||
|
var pa = this.data.getImages(target, size, 'before').length - 1
|
||||||
|
|
||||||
|
// do the update...
|
||||||
|
// no threshold means force load...
|
||||||
|
if(threshold == 0
|
||||||
|
// the target is not loaded...
|
||||||
|
|| img.length == 0
|
||||||
|
// passed hard threshold on the right...
|
||||||
|
|| (nl < w && na > nl)
|
||||||
|
// passed hard threshold on the left...
|
||||||
|
|| (pl < w && pa > pl)){
|
||||||
|
|
||||||
|
this.resizeRibbon(target, size)
|
||||||
|
|
||||||
|
// do a late resize...
|
||||||
|
// loaded more than we need (crop?)...
|
||||||
|
} else if(na + pa < nl + pl
|
||||||
|
// passed threshold on the right...
|
||||||
|
|| (nl < threshold && na > nl)
|
||||||
|
// passed threshold on the left...
|
||||||
|
|| (pl < threshold && pa > pl)
|
||||||
|
// loaded more than we need by threshold...
|
||||||
|
|| nl + pl + 1 > size + threshold){
|
||||||
|
|
||||||
|
return function(){
|
||||||
|
// sync update...
|
||||||
|
if(timeout == null){
|
||||||
|
this.resizeRibbon(target, size)
|
||||||
|
|
||||||
|
// async update...
|
||||||
|
} else {
|
||||||
|
// XXX need to check if we are too close to the edge...
|
||||||
|
var that = this
|
||||||
|
//setTimeout(function(){ that.resizeRibbon(target, size) }, 0)
|
||||||
|
if(this.__update_timeout){
|
||||||
|
clearTimeout(this.__update_timeout)
|
||||||
|
}
|
||||||
|
this.__update_timeout = setTimeout(function(){
|
||||||
|
delete that.__update_timeout
|
||||||
|
that.resizeRibbon(target, size)
|
||||||
|
}, timeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
|
||||||
|
// NOTE: I do not fully understand it yet, but PartialRibbons must be
|
||||||
|
// setup BEFORE RibbonAlignToFirst, otherwise the later will break
|
||||||
|
// on shifting an image to a new ribbon...
|
||||||
|
// To reproduce:
|
||||||
|
// - setupe RibbonAlignToFirst first
|
||||||
|
// - go to top ribbon
|
||||||
|
// - shift image up
|
||||||
|
// XXX The two should be completely independent.... (???)
|
||||||
|
var PartialRibbons =
|
||||||
|
module.PartialRibbons =
|
||||||
|
core.ImageGridFeatures.Feature({
|
||||||
|
title: 'Partial Ribbons',
|
||||||
|
doc: core.doc`Maintains partially loaded ribbons, this enables very large
|
||||||
|
image sets to be handled efficiently.`,
|
||||||
|
|
||||||
|
// NOTE: partial ribbons needs to be setup first...
|
||||||
|
// ...the reasons why things break otherwise is not too clear.
|
||||||
|
priority: 'high',
|
||||||
|
|
||||||
|
tag: 'ui-partial-ribbons',
|
||||||
|
exclusive: ['ui-partial-ribbons'],
|
||||||
|
depends: [
|
||||||
|
'ui'
|
||||||
|
],
|
||||||
|
suggested: [
|
||||||
|
'ui-partial-ribbons-precache',
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
actions: PartialRibbonsActions,
|
||||||
|
|
||||||
|
handlers: [
|
||||||
|
['focusImage.pre centerImage.pre',
|
||||||
|
function(target, list){
|
||||||
|
// NOTE: we have to do this as we are called BEFORE the
|
||||||
|
// actual focus change happens...
|
||||||
|
// XXX is there a better way to do this???
|
||||||
|
target = list != null ? target = this.data.getImage(target, list) : target
|
||||||
|
|
||||||
|
this.updateRibbon(target)
|
||||||
|
}],
|
||||||
|
['resizing.pre',
|
||||||
|
function(unit, size){
|
||||||
|
// keep constant size in single image...
|
||||||
|
if(this.toggleSingleImage && this.toggleSingleImage('?') == 'on'){
|
||||||
|
this.updateRibbon(
|
||||||
|
'current',
|
||||||
|
this.config['ribbons-resize-single-image'] || 13)
|
||||||
|
|
||||||
|
} else if(unit == 'scale'){
|
||||||
|
this.updateRibbon('current', this.screenwidth / size || 1)
|
||||||
|
|
||||||
|
} else if(unit == 'screenwidth'){
|
||||||
|
this.updateRibbon('current', size || 1)
|
||||||
|
|
||||||
|
} else if(unit == 'screenheight'){
|
||||||
|
size = size || 1
|
||||||
|
|
||||||
|
// convert target height in ribbons to width in images...
|
||||||
|
// NOTE: this does not account for compensation that
|
||||||
|
// .updateRibbon(..) makes for fitting whole image
|
||||||
|
// counts, this is a small enough error so as not
|
||||||
|
// to waste time on...
|
||||||
|
var s = this.ribbons.scale()
|
||||||
|
var h = this.ribbons.getScreenHeightRibbons()
|
||||||
|
var w = this.ribbons.getScreenWidthImages()
|
||||||
|
var nw = w / (h/size)
|
||||||
|
|
||||||
|
this.updateRibbon('current', nw)
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* vim:set ts=4 sw=4 : */ return module })
|
* vim:set ts=4 sw=4 : */ return module })
|
||||||
|
|||||||
@ -47,101 +47,6 @@ var base = require('features/base')
|
|||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
var reloadAfter =
|
|
||||||
module.reloadAfter =
|
|
||||||
function(force, callback){
|
|
||||||
return function(){
|
|
||||||
return function(){
|
|
||||||
// NOTE: this may seem like cheating, but .reload() should
|
|
||||||
// be very efficient, reusing all of the items loaded...
|
|
||||||
this.reload(force)
|
|
||||||
|
|
||||||
callback && callback.apply(this, arguments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX make this compatible with multiple images...
|
|
||||||
// XXX for muptiple targets this will just do a .reload()...
|
|
||||||
var updateImagePosition =
|
|
||||||
module.updateImagePosition =
|
|
||||||
function updateImagePosition(actions, target){
|
|
||||||
var s = actions.ribbons.getRibbonLocator()
|
|
||||||
|
|
||||||
if(s.length == 0){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
target = target || actions.current
|
|
||||||
target = target instanceof jQuery
|
|
||||||
? actions.ribbons.getElemGID(target)
|
|
||||||
: target
|
|
||||||
|
|
||||||
var source_ribbon = actions.ribbons.getElemGID(actions.ribbons.getRibbon(target))
|
|
||||||
var source_order = actions.data.getImageOrder(target)
|
|
||||||
|
|
||||||
return function(){
|
|
||||||
actions.ribbons.preventTransitions(s)
|
|
||||||
var end = function(){
|
|
||||||
// XXX not sure why this does not work without a setTimeout(..)
|
|
||||||
//actions.ribbons.restoreTransitions(s, true)
|
|
||||||
setTimeout(function(){
|
|
||||||
actions.ribbons.restoreTransitions(s, true) }, 0) }
|
|
||||||
|
|
||||||
// XXX hack???
|
|
||||||
if(target instanceof Array){
|
|
||||||
actions.reload()
|
|
||||||
return end()
|
|
||||||
}
|
|
||||||
|
|
||||||
var target_ribbon = actions.data.getRibbon(target)
|
|
||||||
|
|
||||||
// nothing changed...
|
|
||||||
if(source_ribbon == target_ribbon
|
|
||||||
&& actions.data.getImageOrder(target) == source_order){
|
|
||||||
return end()
|
|
||||||
}
|
|
||||||
|
|
||||||
// place image at position...
|
|
||||||
var to = actions.data.getImage(target, 'next')
|
|
||||||
if(to != null){
|
|
||||||
actions.ribbons.placeImage(target, to, 'before')
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// place image after position...
|
|
||||||
to = actions.data.getImage(target, 'prev')
|
|
||||||
if(to != null){
|
|
||||||
actions.ribbons.placeImage(target, to, 'after')
|
|
||||||
|
|
||||||
// new ribbon...
|
|
||||||
} else {
|
|
||||||
to = actions.data.getRibbon(target)
|
|
||||||
|
|
||||||
if(actions.ribbons.getRibbon(to).length == 0){
|
|
||||||
actions.ribbons
|
|
||||||
.placeRibbon(to, actions.data.getRibbonOrder(target))
|
|
||||||
}
|
|
||||||
|
|
||||||
actions.ribbons.placeImage(target, to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(actions.data.getImages(source_ribbon).length == 0){
|
|
||||||
actions.ribbons.getRibbon(source_ribbon).remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
actions.focusImage()
|
|
||||||
|
|
||||||
return end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
|
|
||||||
// Viewer (widget/interface)...
|
// Viewer (widget/interface)...
|
||||||
//
|
//
|
||||||
// Workspaces:
|
// Workspaces:
|
||||||
@ -153,11 +58,11 @@ function updateImagePosition(actions, target){
|
|||||||
//
|
//
|
||||||
// NOTE: this uses the base feature API but does not need it imported...
|
// NOTE: this uses the base feature API but does not need it imported...
|
||||||
//
|
//
|
||||||
// XXX split this into read and write actions...
|
|
||||||
// XXX need a way to neutrally scale images and store that scale...
|
// XXX need a way to neutrally scale images and store that scale...
|
||||||
// - fit N images/ribbons is neutral but might mean different things
|
// - fit N images/ribbons is neutral but might mean different things
|
||||||
// depending on image and viewer proportions
|
// depending on image and viewer proportions
|
||||||
// - .scale is a bad way to go...
|
// - .scale is a bad way to go...
|
||||||
|
// XXX remove dependency on .ribbons
|
||||||
var ViewerActions =
|
var ViewerActions =
|
||||||
module.ViewerActions = actions.Actions({
|
module.ViewerActions = actions.Actions({
|
||||||
config: {
|
config: {
|
||||||
@ -714,8 +619,6 @@ module.Viewer = core.ImageGridFeatures.Feature({
|
|||||||
'ui-render',
|
'ui-render',
|
||||||
],
|
],
|
||||||
suggested: [
|
suggested: [
|
||||||
// XXX is this the right way???
|
|
||||||
'ui-edit',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
actions: ViewerActions,
|
actions: ViewerActions,
|
||||||
@ -780,150 +683,6 @@ module.Viewer = core.ImageGridFeatures.Feature({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
// Viewer edit actions...
|
|
||||||
|
|
||||||
// XXX Q: should this be further split into groups and tags???
|
|
||||||
var ViewerEditActions =
|
|
||||||
module.ViewerEditActions =
|
|
||||||
actions.Actions({
|
|
||||||
config: {
|
|
||||||
},
|
|
||||||
|
|
||||||
setBaseRibbon: [
|
|
||||||
function(target){
|
|
||||||
var r = this.data.getRibbon(target)
|
|
||||||
r = r == null ? this.ribbons.getRibbon(target) : r
|
|
||||||
this.ribbons.setBaseRibbon(r)
|
|
||||||
}],
|
|
||||||
|
|
||||||
shiftImageLeft: [
|
|
||||||
function(target){ this.ribbons.placeImage(target, -1) }],
|
|
||||||
shiftImageRight: [
|
|
||||||
function(target){ this.ribbons.placeImage(target, 1) }],
|
|
||||||
|
|
||||||
/*
|
|
||||||
// XXX how should these animate???
|
|
||||||
travelImageUp: [
|
|
||||||
function(){
|
|
||||||
}],
|
|
||||||
travelImageDown: [
|
|
||||||
function(){
|
|
||||||
}],
|
|
||||||
*/
|
|
||||||
|
|
||||||
shiftRibbonUp: [
|
|
||||||
function(target){
|
|
||||||
target = this.ribbons.getRibbon(target)
|
|
||||||
var i = this.ribbons.getRibbonOrder(target)
|
|
||||||
if(i > 0){
|
|
||||||
this.ribbons.placeRibbon(target, i-1)
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
shiftRibbonDown: [
|
|
||||||
function(target){
|
|
||||||
target = this.ribbons.getRibbon(target)
|
|
||||||
var i = this.ribbons.getRibbonOrder(target)
|
|
||||||
if(i < this.data.ribbon_order.length-1){
|
|
||||||
this.ribbons.placeRibbon(target, i+1)
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
|
|
||||||
reverseImages: [ reloadAfter() ],
|
|
||||||
reverseRibbons: [ reloadAfter() ],
|
|
||||||
sortImages: [ reloadAfter(true) ],
|
|
||||||
|
|
||||||
// basic image editing...
|
|
||||||
//
|
|
||||||
// XXX should we have .rotate(..) and .flip(..) generic actions???
|
|
||||||
rotateCW: [
|
|
||||||
function(target){ this.ribbons.rotateCW(target) }],
|
|
||||||
rotateCCW: [
|
|
||||||
function(target){ this.ribbons.rotateCCW(target) }],
|
|
||||||
flipVertical: [
|
|
||||||
function(target){ this.ribbons.flipVertical(target, 'view') }],
|
|
||||||
flipHorizontal: [
|
|
||||||
function(target){ this.ribbons.flipHorizontal(target, 'view') }],
|
|
||||||
|
|
||||||
// XXX this needs an interactive mode -- mark A, mark B, align between
|
|
||||||
alignToRibbon: [ reloadAfter(true) ],
|
|
||||||
|
|
||||||
|
|
||||||
// tags...
|
|
||||||
tag: [
|
|
||||||
function(tags, gids){
|
|
||||||
gids = gids != null && gids.constructor !== Array ? [gids] : gids
|
|
||||||
return function(){
|
|
||||||
//this.ribbons.updateImage(gids)
|
|
||||||
this.refresh(gids)
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
untag: [
|
|
||||||
function(tags, gids){
|
|
||||||
gids = gids != null && gids.constructor !== Array ? [gids] : gids
|
|
||||||
return function(){
|
|
||||||
//this.ribbons.updateImage(gids)
|
|
||||||
this.refresh(gids)
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
|
|
||||||
|
|
||||||
// group stuff...
|
|
||||||
group: [ reloadAfter(true) ],
|
|
||||||
ungroup: [ reloadAfter(true) ],
|
|
||||||
groupTo: [ reloadAfter(true) ],
|
|
||||||
groupMarked: [ reloadAfter(true) ],
|
|
||||||
expandGroup: [ reloadAfter(true) ],
|
|
||||||
collapseGroup: [ reloadAfter(true) ],
|
|
||||||
|
|
||||||
|
|
||||||
// XXX BUG? reloadAfter() here does not remove some images...
|
|
||||||
crop: [ reloadAfter(true) ],
|
|
||||||
// XXX BUG? reloadAfter() produces an align error...
|
|
||||||
uncrop: [ reloadAfter(true) ],
|
|
||||||
// XXX might be a good idea to do this in a new viewer in an overlay...
|
|
||||||
cropGroup: [ reloadAfter() ],
|
|
||||||
})
|
|
||||||
|
|
||||||
var ViewerEdit =
|
|
||||||
module.ViewerEdit =
|
|
||||||
core.ImageGridFeatures.Feature({
|
|
||||||
title: 'Graphical User Interface',
|
|
||||||
|
|
||||||
tag: 'ui-edit',
|
|
||||||
|
|
||||||
depends: [
|
|
||||||
'edit',
|
|
||||||
'tags',
|
|
||||||
'sort',
|
|
||||||
'crop',
|
|
||||||
'image-group',
|
|
||||||
'ui',
|
|
||||||
],
|
|
||||||
|
|
||||||
actions: ViewerEditActions,
|
|
||||||
|
|
||||||
handlers: [
|
|
||||||
[[
|
|
||||||
'shiftImageTo.pre',
|
|
||||||
'shiftImageUp.pre',
|
|
||||||
'shiftImageDown.pre',
|
|
||||||
],
|
|
||||||
function(target){
|
|
||||||
return updateImagePosition(this, target) }],
|
|
||||||
|
|
||||||
|
|
||||||
// manage the .crop-mode css class...
|
|
||||||
['crop uncrop',
|
|
||||||
function(){
|
|
||||||
this.dom[this.cropped ?
|
|
||||||
'addClass'
|
|
||||||
: 'removeClass']('crop-mode')
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
// User interfaces for different base features...
|
// User interfaces for different base features...
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user