fixed several bugs in data and jli, more work on actions...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2014-10-13 00:18:26 +04:00
parent 02a21f9c3c
commit e2219f58f5
7 changed files with 273 additions and 52 deletions

View File

@ -379,7 +379,7 @@ module.DataPrototype = {
}
// normalize target...
if(target in this.ribbons || target.constructor.name == 'Array'){
if(target in this.ribbons || target.constructor === Array){
list = target
target = this.current
} else if(['before', 'after', 'next', 'prev'].indexOf(target) >= 0){
@ -885,6 +885,7 @@ module.DataPrototype = {
// NOTE: this depends on setting length of an array, it works in
// Chrome but will it work the same in other systems???
reverseImages: function(){
var ribbons = this.ribbons
this.order.reverse()
var l = this.order.length
for(k in ribbons){
@ -1004,7 +1005,17 @@ module.DataPrototype = {
// update ribbons...
for(k in ribbons){
ribbons[k].splice(t+i, 0, ribbons[k].splice(f, 1)[0])
var e = ribbons[k].splice(f, 1)[0]
ribbons[k].splice(t+i, 0, e)
// remove the null/undefined if it was just inserted...
// NOTE: this needs to be done as splice inserts the 3'rd
// argument explicitly regardless of it's value,
// this if not done we'll end up with undefined
// inserted into a sparse ribbon which will be
// considered as an element...
if(e == null){
delete ribbons[k][t+i]
}
}
}
}

View File

@ -5,6 +5,49 @@
<link rel="stylesheet" href="css/layout.css">
<link rel="stylesheet" href="css/editor.css">
<!-- XXX remove before use... -->
<style>
.image:after {
content: attr(gid);
display: block;
position: relative;
color: red;
margin: 10px;
width: 20px;
height: 20px;
text-align: center;
border: solid 2px red;
border-radius: 50%;
background: black;
}
.image.current {
border-color: red;
}
/* basic animation... */
.viewer:not(.no-transitions) .ribbon-set {
-webkit-transition: all 0.2s ease;
-moz-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.viewer:not(.no-transitions) .ribbon {
-webkit-transition: all 0.2s ease;
-moz-transition: all 0.2s ease;
transition: all 0.2s ease;
}
.no-transitions {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
</style>
<!--script>
require('nw.gui').Window.get().showDevTools()
</script-->

View File

@ -101,8 +101,10 @@ define(function(require){ var module = {}
// helpers...
// XXX
function args2array(args){
return Array.apply(null, args)
if(typeof(args2array) != 'function'){
function args2array(args){
return [].slice.call(args)
}
}
@ -209,7 +211,7 @@ function Action(name, doc, ldoc, func){
.map(function(h){ return h.apply(that, args) })
// NOTE: this action will get included and called by the code
// above and below...
// above and below, so no need to explicitly call func...
// call handlers -- post phase...
// NOTE: post handlers need to get called last run pre first run post...
@ -519,12 +521,18 @@ function test(){
// NOTE: this looks like an action and feels like an action but
// actually this is a callback as an action with this name
// already exists...
testActionGen1: [function(){
console.log(' pre callback!')
return function(){
console.log(' post callback!')
}
}],
testActionGen1: [
function(){
console.log(' pre callback!')
return function(){
console.log(' post callback!')
}
}],
testAction2: ['this is an action',
function(){
console.log('testAction2 args:', arguments)
}],
})

View File

@ -1325,7 +1325,8 @@ Array.prototype.len = function(){
// convert JS arguments to Array...
function args2array(args){
return Array.apply(null, args)
//return Array.apply(null, args)
return [].slice.call(args)
}

View File

@ -169,6 +169,30 @@ module.RibbonsPrototype = {
// Helpers...
// XXX
preventTransitions: function(){
this.viewer.addClass('no-transitions')
},
restoreTransitions: function(now){
// sync...
if(now){
this.viewer.removeClass('no-transitions')
// on next exec frame...
} else {
var that = this
setTimeout(function(){
that.viewer.removeClass('no-transitions')}, 0)
}
},
noTransitions: function(func){
this.preventTransitions()
func.apply(this, args2array(arguments).slice(1))
this.restoreTransitions()
},
// Get visible image tile size...
//
// .getVisibleImageSize()
@ -187,11 +211,10 @@ module.RibbonsPrototype = {
//
// XXX try and make image size the product of vmin and scale...
// XXX is this the right place for this???
// XXX uses jli.js getElementScale(..)
getVisibleImageSize: function(dim){
dim = dim == null ? 'width' : dim
var img = this.viewer.find('.image')
var scale = getElementScale(this.viewer.find('.ribbon-set'))
var scale = this.getScale()
if(dim == 'height'){
return img.outerHeight(true) * scale
} else if(dim == 'width'){
@ -203,6 +226,24 @@ module.RibbonsPrototype = {
}
},
getScreenWidthImages: function(scale){
var scale = scale == null ? 1 : scale/this.getScale()
var W = this.viewer.width()
var w = this.getVisibleImageSize('width')*scale
return W/w
},
// XXX uses jli.js getElementScale(..) / setElementScale(..)
getScale: function(){
return getElementScale(this.viewer.find('.ribbon-set'))
},
setScale: function(scale){
setElementScale(this.viewer.find('.ribbon-set'), scale)
return this
},
// Contextual getters...
@ -1202,10 +1243,13 @@ module.RibbonsPrototype = {
// NOTE: image_offset is applicable ONLY when both vertical and
// horizontal are set to 'center', either explicitly or
// implicitly (i.e. the default)
_getOffset: function(target, vertical, horizontal, image_offset){
// NOTE: this will get absolute results relative to screen, view
// scaling will have no effect...
_getOffset: function(target, vertical, horizontal, image_offset, scale){
vertical = vertical == null ? 'center' : vertical
horizontal = horizontal == null ? 'center' : horizontal
image_offset = image_offset == null ? 'center' : image_offset
scale = scale == null ? this.getScale() : scale
if(vertical == 'before' || vertical == 'after'){
image_offset = vertical
@ -1227,8 +1271,8 @@ module.RibbonsPrototype = {
var W = viewer.width()
var H = viewer.height()
var w = image.width()
var h = image.height()
var w = image.width() * scale
var h = image.height() * scale
image_offset = image_offset == 'before' ? w/2
: image_offset == 'after' ? -w/2
@ -1258,9 +1302,11 @@ module.RibbonsPrototype = {
}
},
// center a ribbon vertically...
// XXX
centerRibbon: function(target, offset){
offset = offset == null ? this._getOffset(target) : offset
//
centerRibbon: function(target, offset, scale){
offset = offset == null
? this._getOffset(target, null, null, null, scale)
: offset
// vertical offset...
this.viewer.find('.ribbon-set')
@ -1271,22 +1317,34 @@ module.RibbonsPrototype = {
return this
},
// center an image horizontally...
// XXX
centerImage: function(target, mode, offset){
offset = offset == null ? this._getOffset(target, 'center', 'center', mode) : offset
//
centerImage: function(target, mode, offset, scale){
scale = scale == null ? this.getScale() : scale
offset = offset == null
? this._getOffset(target, 'center', 'center', mode, scale)
: offset
// horizontal offset, current ribbon...
this.getRibbon(target)
.css({
left: offset.left
left: offset.left / scale,
})
return this
},
// XXX
fitNImages: function(n){
// XXX
fitImage: function(n){
n = n == null ? 1 : n
var scale = this.getScreenWidthImages(1) / n
this
.setScale(scale)
//.centerRibbon(null, null, scale)
//.centerImage(null, null, null, scale)
return this
},

View File

@ -88,6 +88,12 @@ module.GLOBAL_KEYBOARD = {
}),
*/
'ctrl+shift': 'F5',
// XXX testing...
ctrl: function(){
event.preventDefault()
a.reverseImages()
},
},
P: {
'ctrl+shift': 'F12',
@ -104,20 +110,33 @@ module.GLOBAL_KEYBOARD = {
},
// XXX testing...
Home: doc('', function(){ a.firstImage() }),
End: doc('', function(){ a.lastImage() }),
Left: doc('', function(){ a.prevImage() }),
Right: doc('', function(){ a.nextImage() }),
Home: function(){ a.firstImage() },
End: function(){ a.lastImage() },
Left: {
default: function(){ a.prevImage() },
alt: function(){ a.shiftImageLeft() },
},
Right: {
default: function(){ a.nextImage() },
alt: function(){ a.shiftImageRight() },
},
Up: {
default: doc('', function(){ a.prevRibbon() }),
shift: doc('', function(){ a.shiftImageUp() }),
'ctrl+shift': doc('', function(){ a.shiftImageUpNewRibbon() }),
default: function(){ a.prevRibbon() },
shift: function(){ a.shiftImageUp() },
'ctrl+shift': function(){ a.shiftImageUpNewRibbon() },
},
Down: {
default: doc('', function(){ a.nextRibbon() }),
shift: doc('', function(){ a.shiftImageDown() }),
'ctrl+shift': doc('', function(){ a.shiftImageDownNewRibbon() }),
}
default: function(){ a.nextRibbon() },
shift: function(){ a.shiftImageDown() },
'ctrl+shift': function(){ a.shiftImageDownNewRibbon() },
},
'#0': function(){ a.fitImage(20) },
'#1': function(){ a.fitOrig() },
'#2': function(){ a.fitTwo() },
'#3': function(){ a.fitThree() },
'#4': function(){ a.fitFour() },
'#5': function(){ a.fitFive() },
},
}

View File

@ -132,9 +132,21 @@ actions.Actions({
function(target){
var data = this.data
var r = data.getRibbon(target)
var t = data.getImage('current', r)
// XXX is there a 'last' special case???
t = t == null ? data.getImage('first', r) : t
if(r == null){
return
}
var c = data.getRibbonOrder()
var i = data.getRibbonOrder(r)
// NOTE: we are not changing the direction here based on
// this.direction as swap will confuse the user...
var direction = c < i ? 'before' : 'after'
var t = data.getImage(r, direction)
// if there are no images in the requied direction, try the
// other way...
t = t == null ? data.getImage(r, direction == 'before' ? 'after' : 'before') : t
this.focusImage(t, r)
}],
@ -183,6 +195,9 @@ actions.Actions({
+'will shift to the next or previous image in the current '
+'ribbon depending on current direction.',
function(target){
// stop transitions...
this.ribbons.preventTransitions()
// by default we need to update the current position...
if(target == null){
var direction = this.direction == 'right' ? 'next' : 'prev'
@ -200,12 +215,20 @@ actions.Actions({
} else {
this.data.shiftImageUp(target)
}
// restore transitions...
return function(){
this.ribbons.restoreTransitions()
}
}],
shiftImageDown: ['Shift image down',
'If implicitly shifting current image (i.e. no arguments), focus '
+'will shift to the next or previous image in the current '
+'ribbon depending on current direction.',
function(target){
// stop transitions...
this.ribbons.preventTransitions()
// by default we need to update the current position...
if(target == null){
var direction = this.direction == 'right' ? 'next' : 'prev'
@ -223,6 +246,11 @@ actions.Actions({
} else {
this.data.shiftImageDown(target)
}
// restore transitions...
return function(){
this.ribbons.restoreTransitions()
}
}],
shiftImageUpNewRibbon: ['Shift image up to a new empty ribbon',
function(target){
@ -269,9 +297,8 @@ actions.Actions({
// XXX
sortImages: [
function(){ }],
// XXX
reverseImages: [
function(){ }],
function(){ this.data.reverseImages() }],
// basic image editing...
@ -288,6 +315,9 @@ actions.Actions({
// crop...
//
// XXX
})
@ -400,6 +430,51 @@ actions.Actions(Client, {
// XXX
}],
// zooming...
// XXX
zoomIn: ['Zoom in',
function(){ }],
zoomOut: ['Zoom out',
function(){ }],
fitOrig: ['Fit to original scale',
function(){ this.ribbons.setScale(1) }],
// NOTE: if this gets a count argument it will fit count images,
// default is one.
// XXX animation broken for this...
fitImage: ['Fit image',
function(count){
this.ribbons.fitImage(count)
this.ribbons.updateImage('*')
//this.focusImage()
}],
// XXX should these be relative to screen rather than actual image counts?
fitTwo: ['Fit two images', function(){ this.fitImage(2) }],
fitThree: ['Fit three images', function(){ this.fitImage(3) }],
fitFour: ['Fit four images', function(){ this.fitImage(4) }],
fitFive: ['Fit five images', function(){ this.fitImage(5) }],
fitSix: ['Fit six images', function(){ this.fitImage(6) }],
fitSeven: ['Fit seven images', function(){ this.fitImage(7) }],
fitEight: ['Fit eight images', function(){ this.fitImage(8) }],
fitNine: ['Fit nine images', function(){ this.fitImage(9) }],
// XXX
fitMax: ['Fit the maximum number of images',
function(){ }],
// XXX
fitSmall: ['Show small image',
function(){ }],
// XXX
fitNormal: ['Show normal image',
function(){ }],
// XXX
fitScreen: ['Fit image to screen',
function(){ }],
// XXX
shiftImageUp: [
function(target){
@ -415,16 +490,11 @@ actions.Actions(Client, {
this.reload()
}
}],
/* XXX these are not needed when reloading in .shiftImageUp(..) / .shiftImageDown(..)...
shiftImageUpNewRibbon: [
function(target){
// XXX only create a new ribbon...
}],
shiftImageDownNewRibbon: [
function(target){
// XXX only create a new ribbon...
}],
*/
// NOTE: .shiftImageDownNewRibbon(..) and .shiftImageUpNewRibbon(..)
// are not needed here when doing a reload on vertical
// shifting...
shiftImageLeft: [
function(target){
this.ribbons.placeImage(target, -1)
@ -442,6 +512,17 @@ actions.Actions(Client, {
function(target){
// XXX
}],
reverseImages: [
function(){
this.ribbons.preventTransitions()
return function(){
this.reload()
this.ribbons.restoreTransitions()
}
}],
})