From e2219f58f5e40d42f9a1e54f225214c87fc5dce8 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Mon, 13 Oct 2014 00:18:26 +0400 Subject: [PATCH] fixed several bugs in data and jli, more work on actions... Signed-off-by: Alex A. Naanou --- ui (gen4)/data.js | 15 +++++- ui (gen4)/index.html | 43 +++++++++++++++ ui (gen4)/lib/actions.js | 26 +++++---- ui (gen4)/lib/jli.js | 3 +- ui (gen4)/ribbons.js | 86 +++++++++++++++++++++++++----- ui (gen4)/ui.js | 41 +++++++++++---- ui (gen4)/viewer.js | 111 +++++++++++++++++++++++++++++++++------ 7 files changed, 273 insertions(+), 52 deletions(-) diff --git a/ui (gen4)/data.js b/ui (gen4)/data.js index 62ff8c8a..ecd21e64 100755 --- a/ui (gen4)/data.js +++ b/ui (gen4)/data.js @@ -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] + } } } } diff --git a/ui (gen4)/index.html b/ui (gen4)/index.html index 2883b352..a6ef8d77 100755 --- a/ui (gen4)/index.html +++ b/ui (gen4)/index.html @@ -5,6 +5,49 @@ + + + diff --git a/ui (gen4)/lib/actions.js b/ui (gen4)/lib/actions.js index aa0591ff..1504c91e 100755 --- a/ui (gen4)/lib/actions.js +++ b/ui (gen4)/lib/actions.js @@ -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) + }], }) diff --git a/ui (gen4)/lib/jli.js b/ui (gen4)/lib/jli.js index 84e6a6c7..b3104555 100755 --- a/ui (gen4)/lib/jli.js +++ b/ui (gen4)/lib/jli.js @@ -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) } diff --git a/ui (gen4)/ribbons.js b/ui (gen4)/ribbons.js index 07d48740..40197249 100755 --- a/ui (gen4)/ribbons.js +++ b/ui (gen4)/ribbons.js @@ -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 }, diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js index 06a2ce66..848a52bc 100755 --- a/ui (gen4)/ui.js +++ b/ui (gen4)/ui.js @@ -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() }, + }, } diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js index 5f20e78e..65cbdfc4 100755 --- a/ui (gen4)/viewer.js +++ b/ui (gen4)/viewer.js @@ -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() + } + }], + + })