mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
more experimenting with ranges + new actions and action browse features...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
72e1cad416
commit
fdb280d519
@ -47,6 +47,12 @@ body {
|
||||
z-index: 5000;
|
||||
}
|
||||
|
||||
|
||||
.viewer:not(.no-transitions) .range-offscreen-indicator:not(.no-transitions) {
|
||||
transition: all 0.1s linear;
|
||||
}
|
||||
|
||||
|
||||
/* basic animation... */
|
||||
.viewer:not(.no-transitions) {
|
||||
-webkit-transition: background-color 0.8s ease;
|
||||
|
||||
@ -1772,6 +1772,30 @@ stretching in width... */
|
||||
}
|
||||
|
||||
|
||||
.range-offscreen-indicator {
|
||||
display: none;
|
||||
position: fixed;
|
||||
|
||||
width: @image-tile-size / 16;
|
||||
height: @image-tile-size / 4;
|
||||
|
||||
margin-top: -@image-tile-size / 8;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
border-top: solid @image-tile-size / 8 transparent;
|
||||
border-bottom: solid @image-tile-size / 8 transparent;
|
||||
}
|
||||
.range-offscreen-indicator.left {
|
||||
border-right: solid @image-tile-size / 16 yellow;
|
||||
border-left: solid @image-border * 2 transparent;
|
||||
}
|
||||
.range-offscreen-indicator.right {
|
||||
|
||||
border-left: solid @image-tile-size / 16 yellow;
|
||||
border-right: solid @image-border * 2 transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************** Progress bars ***/
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
*
|
||||
*
|
||||
**********************************************************************/
|
||||
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)(
|
||||
function(require){ var module={} // makes module AMD/node compatible...
|
||||
((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')
|
||||
|
||||
@ -25,6 +25,7 @@ require('features/ui-progress')
|
||||
require('features/keyboard')
|
||||
require('features/ui-status')
|
||||
require('features/ui-marks')
|
||||
require('features/ui-ranges')
|
||||
require('features/ui-widgets')
|
||||
require('features/ui-slideshow')
|
||||
require('features/external-editor')
|
||||
|
||||
@ -889,7 +889,7 @@ module.CropActions = actions.Actions({
|
||||
this.data = this.data.crop(list, flatten)
|
||||
}
|
||||
}],
|
||||
uncrop: ['Crop/Uncrop ribbons',
|
||||
uncrop: ['Crop/Uncrop',
|
||||
function(level, restore_current, keep_crop_order){
|
||||
level = level || 1
|
||||
|
||||
@ -936,7 +936,7 @@ module.CropActions = actions.Actions({
|
||||
// - the order is simple and already done above...
|
||||
// - I think that levels should be relative to images, the
|
||||
// only problem here is how to deal with new ribbons...
|
||||
mergeCrop: ['Crop|Edit/Merge crop',
|
||||
mergeCrop: ['- Crop|Edit/Merge crop',
|
||||
function(){
|
||||
// XXX
|
||||
}],
|
||||
|
||||
@ -133,6 +133,17 @@ module.GLOBAL_KEYBOARD = {
|
||||
},
|
||||
},
|
||||
|
||||
'Range': {
|
||||
doc: 'Range editing',
|
||||
pattern: '.brace',
|
||||
|
||||
// XXX add:
|
||||
// - range navigation
|
||||
// - range manipulation
|
||||
|
||||
Esc: 'clearRange',
|
||||
},
|
||||
|
||||
// XXX add "save as collection..." (???)
|
||||
// XXX cleanup...
|
||||
'Viewer': {
|
||||
|
||||
@ -120,7 +120,7 @@ var LocationActions = actions.Actions({
|
||||
// NOTE: .location will be set by the .load handler...
|
||||
//
|
||||
// XXX not sure about where to set the .__location -- see inside...
|
||||
loadLocation: ['File/Load location',
|
||||
loadLocation: ['- File/Load location',
|
||||
function(location){
|
||||
location = location || this.location
|
||||
|
||||
|
||||
346
ui (gen4)/features/ui-ranges.js
Executable file
346
ui (gen4)/features/ui-ranges.js
Executable file
@ -0,0 +1,346 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
**********************************************************************/
|
||||
((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')
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var RangeActions = actions.Actions({
|
||||
|
||||
// .makeBrace('open')
|
||||
// .makeBrace('open', image)
|
||||
// .makeBrace('close')
|
||||
// .makeBrace('close', image)
|
||||
//
|
||||
// XXX this should not be here...
|
||||
makeBrace: ['- Range/',
|
||||
function(type, gid){
|
||||
var cls = type == 'open' ? 'brace-open' : 'brace-close'
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
|
||||
var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls)
|
||||
|
||||
if(brace.length == 0){
|
||||
brace = $('<span>')
|
||||
.addClass('mark brace '+cls)
|
||||
|
||||
} else if(brace.length > 1){
|
||||
brace = brace.detach().first()
|
||||
}
|
||||
|
||||
brace
|
||||
.attr('gid', gid)
|
||||
|
||||
this.ribbons.getImage(gid)[type == 'open' ? 'before' : 'after'](brace)
|
||||
|
||||
// XXX this does not work for non-current images ...
|
||||
this.ribbons.preventTransitions(r)
|
||||
// XXX is this correct here???
|
||||
this.focusImage()
|
||||
this.ribbons.restoreTransitions(r)
|
||||
}],
|
||||
|
||||
// XXX add "brace off screen" indicators....
|
||||
updateRangeIndicators: ['- Range/',
|
||||
function(){
|
||||
var update = false
|
||||
var range = this.data.__range
|
||||
|
||||
// XXX not sure if this sweeping action is the right way to
|
||||
// go but it sure makes things simpler...
|
||||
if(range == null){
|
||||
update = true
|
||||
this.ribbons.viewer
|
||||
.find('.ribbon .mark.brace')
|
||||
.remove()
|
||||
|
||||
} else {
|
||||
var that = this
|
||||
|
||||
this.data.ribbon_order.forEach(function(r){
|
||||
var a = that.data.getImage(range[0], 'after', r)
|
||||
var b = that.data.getImage(range[1], 'before', r)
|
||||
|
||||
// only draw braces if some part of the ribbon is
|
||||
// in range...
|
||||
if(a != null && b != null){
|
||||
that
|
||||
.makeBrace('open', a)
|
||||
.makeBrace('close', b)
|
||||
|
||||
// remove braces from ribbon...
|
||||
} else {
|
||||
update = true
|
||||
that.ribbons.getRibbon(r)
|
||||
.find('.mark.brace')
|
||||
.remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if(update){
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
|
||||
// XXX this does not work for non-current images ...
|
||||
this.ribbons.preventTransitions(r)
|
||||
// XXX is this correct here???
|
||||
this.focusImage()
|
||||
this.ribbons.restoreTransitions(r)
|
||||
}
|
||||
}],
|
||||
clearRange: ['Range/Clear range',
|
||||
// XXX not sure if it is best to hide things or make them do a
|
||||
// sensible default thing...
|
||||
//{isDisabled: function(){ return !this.data.__range }},
|
||||
function(image){
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
|
||||
delete this.data.__range
|
||||
this.updateRangeIndicators()
|
||||
}],
|
||||
// procedure:
|
||||
// - set brace
|
||||
// when no braces set:
|
||||
// - sets two braces around target image
|
||||
// When a brace is set:
|
||||
// - check brace orientation and set open/close to target
|
||||
// - update braces on all ribbons
|
||||
setRangeBorder: ['Range/Set range border',
|
||||
function(image, type){
|
||||
var image = this.data.getImage(image)
|
||||
var range = this.data.__range = this.data.__range || []
|
||||
|
||||
// no range...
|
||||
if(range.length == 0){
|
||||
range.push(image)
|
||||
range.push(image)
|
||||
|
||||
// range set...
|
||||
} else {
|
||||
var a = this.data.getImageOrder(range[0])
|
||||
var b = this.data.getImageOrder(range[1])
|
||||
var t = this.data.getImageOrder(image)
|
||||
|
||||
|
||||
var i =
|
||||
// type/range conflict...
|
||||
type == 'close' && t < a ? null
|
||||
: type == 'open' && t > b ? null
|
||||
// extend left/right...
|
||||
: t <= a ? 0
|
||||
: t >= b ? 1
|
||||
// set left/right limit...
|
||||
: type == 'open' ? 0
|
||||
: type == 'close' ? 1
|
||||
// narrow to the closest brace...
|
||||
: a - t < b - t ? 0
|
||||
: 1
|
||||
|
||||
if(i == null){
|
||||
return
|
||||
}
|
||||
|
||||
range[i] = image
|
||||
}
|
||||
|
||||
this.updateRangeIndicators()
|
||||
}],
|
||||
openRange: ['Range/Open range',
|
||||
function(image){ this.setRangeBorder(image, 'open') }],
|
||||
closeRange: ['Range/Close range',
|
||||
function(image){ this.setRangeBorder(image, 'close') }],
|
||||
|
||||
cropRange: ['Range|Crop/Crop range',
|
||||
// XXX not sure if it is best to hide things or make them do a
|
||||
// sensible default thing...
|
||||
//{isDisabled: function(){ return !this.data.__range }},
|
||||
function(){
|
||||
var range = this.data.__range
|
||||
var order = this.data.order
|
||||
|
||||
range ?
|
||||
this.crop(order.slice(
|
||||
order.indexOf(range[0]),
|
||||
order.indexOf(range[1])+1))
|
||||
: this.crop([])
|
||||
}],
|
||||
cropRangeOut: ['Range|Crop/Crop out range',
|
||||
// XXX not sure if it is best to hide things or make them do a
|
||||
// sensible default thing...
|
||||
//{isDisabled: function(){ return !this.data.__range }},
|
||||
function(){
|
||||
var range = this.data.__range
|
||||
var order = this.data.order
|
||||
|
||||
range ?
|
||||
this.crop(order
|
||||
.slice(0, order.indexOf(range[0]))
|
||||
.concat(order.slice(order.indexOf(range[1])+1)))
|
||||
: this.crop()
|
||||
}],
|
||||
})
|
||||
|
||||
|
||||
var Range =
|
||||
module.Range = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'ui-range',
|
||||
depends: [
|
||||
'ui',
|
||||
],
|
||||
|
||||
actions: RangeActions,
|
||||
|
||||
handlers: [
|
||||
[[
|
||||
'crop',
|
||||
'reload',
|
||||
],
|
||||
function(){ this.updateRangeIndicators() }],
|
||||
['updateImage',
|
||||
function(_, gid){
|
||||
var range = this.data.__range
|
||||
|
||||
if(this.ribbons && range && gid){
|
||||
var r = this.data.getRibbon(gid)
|
||||
|
||||
var a = gid == range[0] ?
|
||||
this.makeBrace('open', gid)
|
||||
: this.data.getImage(range[0], 'after', r)
|
||||
|
||||
var b = gid == range[1] ?
|
||||
this.makeBrace('close', gid)
|
||||
: this.data.getImage(range[1], 'before', r)
|
||||
|
||||
if(a != null && b != null){
|
||||
gid == a
|
||||
&& this.makeBrace('open', gid)
|
||||
|
||||
gid == b
|
||||
&& this.makeBrace('close', gid)
|
||||
}
|
||||
}
|
||||
}],
|
||||
['shiftImage.pre',
|
||||
function(gid){
|
||||
var range = this.data.__range
|
||||
|
||||
if(this.ribbons && range){
|
||||
this.ribbons.getImageMarks(gid).filter('.brace').remove()
|
||||
|
||||
return function(){
|
||||
this.updateRangeIndicators()
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
// show/hide off-screen indicators...
|
||||
// XXX STUB: should we animate indicators???
|
||||
['setScale.pre',
|
||||
function(scale){
|
||||
var range = this.data.__range
|
||||
if(!this.ribbons || !range){
|
||||
return
|
||||
}
|
||||
|
||||
this.ribbons.getRibbonLocator()
|
||||
.find('.range-offscreen-indicator')
|
||||
.hide()
|
||||
}],
|
||||
[[
|
||||
'focusImage',
|
||||
'setScale',
|
||||
'updateRangeIndicators',
|
||||
],
|
||||
function(_, gid){
|
||||
gid = gid || this.current
|
||||
var that = this
|
||||
var locator = this.ribbons.getRibbonLocator()
|
||||
var range = this.data.__range
|
||||
|
||||
if(!this.ribbons || !range){
|
||||
locator.find('.range-offscreen-indicator').remove()
|
||||
return
|
||||
}
|
||||
|
||||
var Wr = this.ribbons.viewer.width()
|
||||
var W = (Wr / this.scale) / 2
|
||||
|
||||
var a = this.data.getImageOrder(range[0])
|
||||
var b = this.data.getImageOrder(range[1])
|
||||
|
||||
var _make = function(gid, ribbon, direction){
|
||||
var t = ribbon[0].offsetTop
|
||||
var h = ribbon[0].offsetHeight / 2
|
||||
|
||||
var i = that.data.getImageOrder(gid)
|
||||
|
||||
var indicator = locator
|
||||
.find('.range-offscreen-indicator.'+direction+'[gid="'+gid+'"]')
|
||||
|
||||
// XXX this only works if brace is loaded...
|
||||
if(direction == 'left'){
|
||||
var brace = ribbon.find('.mark.brace-open')
|
||||
if(brace.length == 0 || brace.offset().left >= 0){
|
||||
return indicator.remove()
|
||||
}
|
||||
|
||||
} else if(direction == 'right'){
|
||||
var brace = ribbon.find('.mark.brace-close')
|
||||
if(brace.length == 0 || brace.offset().left < Wr){
|
||||
return indicator.remove()
|
||||
}
|
||||
}
|
||||
|
||||
if(indicator.length == 0){
|
||||
locator.append($('<div>')
|
||||
.addClass('range-offscreen-indicator '+direction)
|
||||
.attr('gid', gid))
|
||||
}
|
||||
|
||||
var css = {}
|
||||
|
||||
css.left = (direction == 'left' ?
|
||||
-W
|
||||
: W-(indicator[0] && indicator[0].offsetWidth)) + 'px'
|
||||
css.top = (t + h) + 'px'
|
||||
|
||||
that.ribbons.preventTransitions(indicator)
|
||||
indicator
|
||||
.css(css)
|
||||
.show()
|
||||
that.ribbons.restoreTransitions(indicator)
|
||||
|
||||
return indicator
|
||||
}
|
||||
|
||||
|
||||
setTimeout(function(){
|
||||
that.data.ribbon_order.forEach(function(gid){
|
||||
var ribbon = that.ribbons.getRibbon(gid)
|
||||
|
||||
_make(gid, ribbon, 'left')
|
||||
_make(gid, ribbon, 'right')
|
||||
})
|
||||
}, 400)
|
||||
}],
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* vim:set ts=4 sw=4 : */ return module })
|
||||
@ -157,29 +157,31 @@ var StatusBarActions = actions.Actions({
|
||||
var type = item.attr('type')
|
||||
}
|
||||
|
||||
// update...
|
||||
// NOTE: using .toggleStatusBarIndexMode(..) here will fall
|
||||
// into an infinite recursion...
|
||||
var cls = (that.config['status-bar-index'] || {})['mode'] || 'normal'
|
||||
item
|
||||
.addClass(cls)
|
||||
.removeClass(cls != 'normal' ? 'normal' : 'global')
|
||||
|
||||
// global index...
|
||||
if(cls == 'global'){
|
||||
item.find('.position:not(:focus)')
|
||||
.text(this.data ? this.data.getImageOrder(gid)+1 : 0)
|
||||
item.find('.length')
|
||||
.text('/'+ (this.data ? this.data.length : 0))
|
||||
var i = this.data ? this.data.getImageOrder(gid) : -1
|
||||
var l = this.data ? this.data.length : 0
|
||||
|
||||
// ribbon index...
|
||||
} else {
|
||||
item.find('.position:not(:focus)')
|
||||
.text(this.data ? this.data.getImageOrder('ribbon', gid)+1 : 0)
|
||||
item.find('.length')
|
||||
.text('/'+ (this.data ? this.data.getImages(gid).len : 0))
|
||||
var i = this.data ? this.data.getImageOrder('ribbon', gid) : -1
|
||||
var l = this.data ? this.data.getImages(gid).len : 0
|
||||
}
|
||||
|
||||
// update...
|
||||
item
|
||||
.addClass(cls)
|
||||
.removeClass(cls != 'normal' ? 'normal' : 'global')
|
||||
.find('.position:not(:focus)')
|
||||
.text(i >= 0 ? i+1 : '-')
|
||||
.end()
|
||||
.find('.length')
|
||||
.text(l > 0 ? ('/' + l) : '')
|
||||
|
||||
return item
|
||||
},
|
||||
ribbon: function(item, gid, img){
|
||||
@ -188,7 +190,7 @@ var StatusBarActions = actions.Actions({
|
||||
// get ribbon number...
|
||||
var n = (this.data && this.data.ribbon_order.length > 0) ?
|
||||
this.data.getRibbonOrder(gid || this.current)
|
||||
: '-'
|
||||
: null
|
||||
var t = (this.config['status-bar-ribbon-count'] && this.data) ?
|
||||
this.data.ribbon_order.length
|
||||
: null
|
||||
@ -217,7 +219,7 @@ var StatusBarActions = actions.Actions({
|
||||
|
||||
item
|
||||
.find('.ribbon-number')
|
||||
.html(n+1)
|
||||
.html(n != null ? n+1 : '-')
|
||||
.end()
|
||||
.find('.ribbon-count')
|
||||
.html(t || '')
|
||||
|
||||
@ -763,6 +763,14 @@ var BrowseActionsActions = actions.Actions({
|
||||
'80:Edit',
|
||||
'70:Navigate',
|
||||
'60:Image',
|
||||
'50:Crop',
|
||||
'Crop/80:Crop marked images',
|
||||
'Crop/80:Crop bookmarked images',
|
||||
'Crop/70:Flatten',
|
||||
// ...
|
||||
'Crop/-80:Uncrop and keep crop image order',
|
||||
'Crop/-81:Uncrop all',
|
||||
'Crop/-82:Uncrop',
|
||||
|
||||
'-50:Interface',
|
||||
'-60:Workspace',
|
||||
@ -798,6 +806,20 @@ var BrowseActionsActions = actions.Actions({
|
||||
// with greater or no priority.
|
||||
//
|
||||
//
|
||||
// An action can also be disabled dynamically:
|
||||
// - .isDisabled() action method is called with actions as base if
|
||||
// action is not disabled.
|
||||
// Example:
|
||||
// someAction: ['Path/To/Some action',
|
||||
// {isDisabled: function(){ ... }},
|
||||
// function(){
|
||||
// ...
|
||||
// }],
|
||||
//
|
||||
// NOTE: disabling an action path has priority over the action
|
||||
// .isDisabled() predicate...
|
||||
//
|
||||
//
|
||||
// NOTE: if the action returns an instance of overlay.Overlay this
|
||||
// will not close right away but rather bind to:
|
||||
// overlay.close -> self.focus()
|
||||
@ -913,18 +935,25 @@ var BrowseActionsActions = actions.Actions({
|
||||
buildTree(path, leaf, null, null, tree)
|
||||
})
|
||||
|
||||
// buld the tree...
|
||||
// build the tree...
|
||||
var paths = this.getPath()
|
||||
Object.keys(paths).forEach(function(key){
|
||||
// handle disabled flag...
|
||||
var action = paths[key][0]
|
||||
var disabled = key.split(/^- /)
|
||||
var path = disabled.pop()
|
||||
disabled = disabled.length > 0
|
||||
|
||||
// prepare to handle disabled action predicate...
|
||||
disabled = (!disabled && actions[action].isDisabled) ?
|
||||
actions[action].isDisabled
|
||||
: disabled
|
||||
|
||||
|
||||
path = path.split(/[\\\/]/g)
|
||||
var leaf = path.pop()
|
||||
|
||||
buildTree(path, leaf, paths[key][0], disabled, tree)
|
||||
buildTree(path, leaf, action, disabled, tree)
|
||||
})
|
||||
|
||||
//console.log('!!!!', tree)
|
||||
@ -952,7 +981,12 @@ var BrowseActionsActions = actions.Actions({
|
||||
&& actions.isToggler && actions.isToggler(cur[0])){
|
||||
var action = cur[0]
|
||||
var disabled = cur[1]
|
||||
|
||||
|
||||
// handle disabled predicate...
|
||||
disabled = disabled instanceof Function ?
|
||||
disabled.call(actions)
|
||||
: disabled
|
||||
|
||||
var cur_state = actions[action]('?')
|
||||
var states = actions[action]('??')
|
||||
|
||||
@ -1016,6 +1050,11 @@ var BrowseActionsActions = actions.Actions({
|
||||
var action = cur[key][0]
|
||||
var disabled = cur[key][1]
|
||||
|
||||
// handle disabled predicate...
|
||||
disabled = disabled instanceof Function ?
|
||||
disabled.call(actions)
|
||||
: disabled
|
||||
|
||||
// Action: toggler -> add toggle button...
|
||||
if(actions.isToggler && actions.isToggler(action)){
|
||||
make(text + '/', {
|
||||
@ -1627,311 +1666,6 @@ module.WidgetTest = core.ImageGridFeatures.Feature({
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// XXX move this to a more appropriate place...
|
||||
|
||||
var RangeActions = actions.Actions({
|
||||
|
||||
// .makeBrace('open')
|
||||
// .makeBrace('open', image)
|
||||
// .makeBrace('close')
|
||||
// .makeBrace('close', image)
|
||||
//
|
||||
// XXX this should not be here...
|
||||
makeBrace: ['- Range/',
|
||||
function(type, gid){
|
||||
var cls = type == 'open' ? 'brace-open' : 'brace-close'
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
|
||||
var brace = this.ribbons.getRibbon(gid).find('.mark.'+cls)
|
||||
|
||||
if(brace.length == 0){
|
||||
brace = $('<span>')
|
||||
.addClass('mark brace '+cls)
|
||||
|
||||
} else if(brace.length > 1){
|
||||
brace = brace.detach().first()
|
||||
}
|
||||
|
||||
brace
|
||||
.attr('gid', gid)
|
||||
|
||||
this.ribbons.getImage(gid)[type == 'open' ? 'before' : 'after'](brace)
|
||||
|
||||
// XXX this does not work for non-current images ...
|
||||
this.ribbons.preventTransitions(r)
|
||||
// XXX is this correct here???
|
||||
this.focusImage()
|
||||
this.ribbons.restoreTransitions(r)
|
||||
}],
|
||||
|
||||
// XXX add "brace off screen" indicators....
|
||||
updateRangeIndicators: ['- Range/',
|
||||
function(){
|
||||
var update = false
|
||||
var range = this.data.__range
|
||||
|
||||
// XXX not sure if this sweeping action is the right way to
|
||||
// go but it sure makes things simpler...
|
||||
if(range == null){
|
||||
update = true
|
||||
this.ribbons.viewer
|
||||
.find('.ribbon .mark.brace')
|
||||
.remove()
|
||||
|
||||
} else {
|
||||
var that = this
|
||||
|
||||
this.data.ribbon_order.forEach(function(r){
|
||||
var a = that.data.getImage(range[0], 'after', r)
|
||||
var b = that.data.getImage(range[1], 'before', r)
|
||||
|
||||
// only draw braces if some part of the ribbon is
|
||||
// in range...
|
||||
if(a != null && b != null){
|
||||
that
|
||||
.makeBrace('open', a)
|
||||
.makeBrace('close', b)
|
||||
|
||||
// remove braces from ribbon...
|
||||
} else {
|
||||
update = true
|
||||
that.ribbons.getRibbon(r)
|
||||
.find('.mark.brace')
|
||||
.remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if(update){
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
|
||||
// XXX this does not work for non-current images ...
|
||||
this.ribbons.preventTransitions(r)
|
||||
// XXX is this correct here???
|
||||
this.focusImage()
|
||||
this.ribbons.restoreTransitions(r)
|
||||
}
|
||||
}],
|
||||
clearRange: ['Range/Clear range',
|
||||
function(image){
|
||||
var r = this.ribbons.viewer.find('.ribbon')
|
||||
|
||||
delete this.data.__range
|
||||
this.updateRangeIndicators()
|
||||
}],
|
||||
// procedure:
|
||||
// - set brace
|
||||
// when no braces set:
|
||||
// - sets two braces around target image
|
||||
// When a brace is set:
|
||||
// - check brace orientation and set open/close to target
|
||||
// - update braces on all ribbons
|
||||
setRangeBorder: ['Range/Set range border',
|
||||
function(image, type){
|
||||
var image = this.data.getImage(image)
|
||||
var range = this.data.__range = this.data.__range || []
|
||||
|
||||
// no range...
|
||||
if(range.length == 0){
|
||||
range.push(image)
|
||||
range.push(image)
|
||||
|
||||
// range set...
|
||||
} else {
|
||||
var a = this.data.getImageOrder(range[0])
|
||||
var b = this.data.getImageOrder(range[1])
|
||||
var t = this.data.getImageOrder(image)
|
||||
|
||||
|
||||
var i =
|
||||
// type/range conflict...
|
||||
type == 'close' && t < a ? null
|
||||
: type == 'open' && t > b ? null
|
||||
// extend left/right...
|
||||
: t <= a ? 0
|
||||
: t >= b ? 1
|
||||
// set left/right limit...
|
||||
: type == 'open' ? 0
|
||||
: type == 'close' ? 1
|
||||
// narrow to the closest brace...
|
||||
: a - t < b - t ? 0
|
||||
: 1
|
||||
|
||||
if(i == null){
|
||||
return
|
||||
}
|
||||
|
||||
range[i] = image
|
||||
}
|
||||
|
||||
this.updateRangeIndicators()
|
||||
}],
|
||||
openRange: ['Range/Open range',
|
||||
function(image){ this.setRangeBorder(image, 'open') }],
|
||||
closeRange: ['Range/Close range',
|
||||
function(image){ this.setRangeBorder(image, 'close') }],
|
||||
|
||||
cropRange: ['Range|Crop/Crop range',
|
||||
function(){
|
||||
var range = this.data.__range
|
||||
var order = this.data.order
|
||||
|
||||
range
|
||||
&& this.crop(order.slice(
|
||||
order.indexOf(range[0]),
|
||||
order.indexOf(range[1])+1))
|
||||
}],
|
||||
cropRangeOut: ['Range|Crop/Crop out range',
|
||||
function(){
|
||||
var range = this.data.__range
|
||||
var order = this.data.order
|
||||
|
||||
range
|
||||
&& this.crop(order
|
||||
.slice(0, order.indexOf(range[0])-1)
|
||||
.concat(order.slice(order.indexOf(range[1])+1)))
|
||||
}],
|
||||
})
|
||||
|
||||
|
||||
var Range =
|
||||
module.Range = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'ui-range',
|
||||
depends: [
|
||||
'ui',
|
||||
],
|
||||
|
||||
actions: RangeActions,
|
||||
|
||||
handlers: [
|
||||
[[
|
||||
'crop',
|
||||
'reload',
|
||||
],
|
||||
function(){ this.updateRangeIndicators() }],
|
||||
['updateImage',
|
||||
function(_, gid){
|
||||
var range = this.data.__range
|
||||
|
||||
if(this.ribbons && range && gid){
|
||||
var r = this.data.getRibbon(gid)
|
||||
|
||||
var a = gid == range[0] ?
|
||||
this.makeBrace('open', gid)
|
||||
: this.data.getImage(range[0], 'after', r)
|
||||
|
||||
var b = gid == range[1] ?
|
||||
this.makeBrace('close', gid)
|
||||
: this.data.getImage(range[1], 'before', r)
|
||||
|
||||
if(a != null && b != null){
|
||||
gid == a
|
||||
&& this.makeBrace('open', gid)
|
||||
|
||||
gid == b
|
||||
&& this.makeBrace('close', gid)
|
||||
}
|
||||
}
|
||||
}],
|
||||
['shiftImage.pre',
|
||||
function(gid){
|
||||
var range = this.data.__range
|
||||
|
||||
if(this.ribbons && range){
|
||||
this.ribbons.getImageMarks(gid).filter('.brace').remove()
|
||||
|
||||
return function(){
|
||||
this.updateRangeIndicators()
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
// show/hide off-screen indicators...
|
||||
// XXX STUB...
|
||||
[[
|
||||
'focusImage',
|
||||
'setScale',
|
||||
'updateRangeIndicators',
|
||||
],
|
||||
function(_, gid){
|
||||
gid = gid || this.current
|
||||
var that = this
|
||||
var locator = this.ribbons.getRibbonLocator()
|
||||
var range = this.data.__range
|
||||
|
||||
if(!this.ribbons || !range){
|
||||
locator.find('.range-offscreen-indicator').remove()
|
||||
return
|
||||
}
|
||||
|
||||
var Wr = this.ribbons.viewer.width()
|
||||
var W = (Wr / this.scale) / 2
|
||||
|
||||
var _make = function(gid, ribbon, direction){
|
||||
var t = ribbon[0].offsetTop
|
||||
var h = ribbon[0].offsetHeight / 2
|
||||
|
||||
var css = {}
|
||||
|
||||
// XXX STUB...
|
||||
css = {
|
||||
display: 'none',
|
||||
position: 'fixed',
|
||||
width: '100px',
|
||||
height: '100px',
|
||||
marginTop: '-50px',
|
||||
background: 'blue',
|
||||
zIndex: 9000,
|
||||
transition: 'all 0.1s ease',
|
||||
}
|
||||
|
||||
var indicator = locator
|
||||
.find('.range-offscreen-indicator.'+direction+'[gid="'+gid+'"]')
|
||||
|
||||
if(direction == 'left'){
|
||||
var brace = ribbon.find('.mark.brace-open')
|
||||
if(brace.length == 0 || brace.offset().left >= 0){
|
||||
return indicator.remove()
|
||||
}
|
||||
|
||||
} else if(direction == 'right'){
|
||||
var brace = ribbon.find('.mark.brace-close')
|
||||
if(brace.length == 0 || brace.offset().left < Wr){
|
||||
return indicator.remove()
|
||||
}
|
||||
}
|
||||
|
||||
if(indicator.length == 0){
|
||||
locator.append($('<div>')
|
||||
.addClass('range-offscreen-indicator '+direction)
|
||||
.attr('gid', gid))
|
||||
}
|
||||
|
||||
css.left = (direction == 'left'? -W : W-100) + 'px'
|
||||
css.top = (t + h) + 'px'
|
||||
|
||||
return indicator
|
||||
.css(css)
|
||||
.show(0)
|
||||
}
|
||||
|
||||
setTimeout(function(){
|
||||
that.data.ribbon_order.forEach(function(gid){
|
||||
var ribbon = that.ribbons.getRibbon(gid)
|
||||
|
||||
_make(gid, ribbon, 'left')
|
||||
_make(gid, ribbon, 'right')
|
||||
})
|
||||
}, 400)
|
||||
}],
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* vim:set ts=4 sw=4 : */ return module })
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
"glob": "^4.0.6",
|
||||
"guarantee-events": "^1.0.0",
|
||||
"ig-features": "^2.0.0",
|
||||
"ig-actions": "^1.0.0",
|
||||
"ig-actions": "^1.8.0",
|
||||
"ig-object": "^1.0.1",
|
||||
"openseadragon": "^2.1.0",
|
||||
"requirejs": "^2.1.23",
|
||||
|
||||
@ -115,8 +115,6 @@ $(function(){
|
||||
//'-commandline',
|
||||
//'-ui-partial-ribbons',
|
||||
|
||||
'-ui-clickable',
|
||||
|
||||
// XXX BUG: disabling features on this level does not
|
||||
// work, yet works deeper down...
|
||||
// Example:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user