From 4e31790f95213d5347c5a4146380dc09b70457ab Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Thu, 3 Dec 2015 00:58:43 +0300 Subject: [PATCH] reworked ribbon traverse and alignment + minor fix... Signed-off-by: Alex A. Naanou --- ui (gen4)/ribbons.js | 115 ++++++++++++++++++++++++++++++++- ui (gen4)/testing.js | 2 +- ui (gen4)/ui.js | 7 -- ui (gen4)/viewer.js | 149 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 257 insertions(+), 16 deletions(-) diff --git a/ui (gen4)/ribbons.js b/ui (gen4)/ribbons.js index 5233aa5f..c1e37ac5 100755 --- a/ui (gen4)/ribbons.js +++ b/ui (gen4)/ribbons.js @@ -297,10 +297,10 @@ var RibbonsPrototype = { // XXX try and make image size the product of vmin and scale... // XXX this might break when no images are loaded and proportions // are not square... - getVisibleImageSize: function(dim, scale){ + getVisibleImageSize: function(dim, scale, img){ scale = scale || this.getScale() dim = dim == null ? 'width' : dim - var img = this.viewer.find(IMAGE) + img = img || this.viewer.find(IMAGE) var tmp // if no images are loaded create one temporarily.... @@ -350,6 +350,117 @@ var RibbonsPrototype = { return H/h }, + // Get an image at a relative to viewer position... + // + // Get central image in current ribbon: + // .getImageByPosition() + // -> image + // + // Get central image closest to current: + // .getImageByPosition('current'[, ]) + // -> image + // + // Get central image closest to html element: + // .getImageByPosition([, ]) + // -> image + // + // Get image in a specific ribbon: + // .getImageByPosition('left'[, ]) + // .getImageByPosition('center'[, ]) + // .getImageByPosition('right'[, ]) + // -> image + // + // This can return a pair of images when position is either 'center', + // 'current' or a jquery object, this can happen when the two + // candidates are closer to the target than delta. + // + // + // NOTE: if no ribbon is given, current ribbon is assumed. + // NOTE: is the same as expected by .getRibbon(..) + // NOTE: position can also be an image... + // NOTE: delta is used ONLY if position is either 'center', 'current' + // or an jQuery object... + getImageByPosition: function(position, ribbon, delta){ + position = position || 'center' + ribbon = this.getRibbon(ribbon) + + var viewer = this.viewer + + var W = viewer.outerWidth() + var L = viewer.offset().left + + var target = position == 'current' ? this.getImage() + : position == 'center' ? viewer + : position == 'left' ? L + : position == 'right' ? L + W + : position + + // unknown keyword... + if(target == null){ + return $() + + // center of an element... + } else if(typeof(target) != typeof(123)){ + target = $(target) + var w = target.hasClass('image') ? + this.getVisibleImageSize('width', null, target) : + target.outerWidth() + // NOTE: we will need delta only in this branch, i.e. when + // position is either 'current', 'center' or a jQuery + // object... + delta = delta || w / 10 + target = target.offset().left + w/2 + } + + var that = this + var res = ribbon.find(IMAGE) + .toArray() + .map(function(img){ + img = $(img) + var l = img.offset().left + var w = that.getVisibleImageSize('width', null, img) + + // skip images not fully shown in viewer... + if(L > l || l+w > L+W){ + return + } + + // distance between centers... + if(position == 'center' || position == 'current'){ + return [target - (l + w/2), img] + + // distance between left edges... + } else if(position == 'left'){ + return [target - l, img] + + // distance between right edges... + } else { + return [target - (l + w), img] + } + }) + // drop images outside the viewer... + .filter(function(e){ return e != null }) + // sort images by distance... + .sort(function(a, b){ return Math.abs(a[0]) - Math.abs(b[0]) }) + + var a = res[0][0] + var b = res[1] ? res[1][0] : null + + // we have two images that are about the same distance from + // target... + // NOTE: this is a one-dimentional filter so the can not be more + // than two hits... + // NOTE: delta is used ONLY if position is either 'center', + // 'current' or an jQuery object... + if(b && (a >= 0) != (b >= 0) && Math.abs(a + b) < delta){ + return $([res[0][1][0], res[1][1][0]]) + + // a single hit... + } else { + return res[0][1] + } + }, + // Get ribbon set scale... // getScale: function(){ diff --git a/ui (gen4)/testing.js b/ui (gen4)/testing.js index 0e5b246a..bb7a0832 100755 --- a/ui (gen4)/testing.js +++ b/ui (gen4)/testing.js @@ -126,7 +126,7 @@ if(typeof(glob) != 'undefined'){ window.loadMBFWR1 = function(logger){ - a.loadPath('L:/mnt/hdd15 (photo)/NTFS2/media/img/my/work/20151022 - MBFWR (1),/preview (RAW)/', logger) + a.loadIndex('L:/mnt/hdd15 (photo)/NTFS2/media/img/my/work/20151022 - MBFWR (1),/preview (RAW)/', logger) } diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js index c39c4c0b..a9aa7b6b 100755 --- a/ui (gen4)/ui.js +++ b/ui (gen4)/ui.js @@ -79,13 +79,6 @@ module.GLOBAL_KEYBOARD = { F4: { alt: 'close', - /* - alt: doc('Close viewer', - function(){ - window.close() - return false - }), - */ }, Q: { meta: 'close', diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js index 870cee52..7b42c5e0 100755 --- a/ui (gen4)/viewer.js +++ b/ui (gen4)/viewer.js @@ -165,6 +165,16 @@ actions.Actions({ config: { // see .direction for details... 'steps-to-change-direction': 3, + + // determines the image selection mode when focusing ribbons... + // + // supported modes: + // 'order' - select image closest to current in order + // 'first' - select first image + // 'last' - select last image + // 'visual' - select image closest visually + //'ribbon-focus-mode': 'order', + 'ribbon-focus-mode': 'visual', }, // basic state... @@ -283,8 +293,16 @@ actions.Actions({ function(img, list){ this.data.focusImage(img, list) }], + // Focuses a ribbon by selecting an image in it... + // + // modes supported: + // 'order' - focus closest image to current in order + // 'first'/'last' - focus first/last image in ribbon + // 'visual' - focus visually closest to current image + // + // NOTE: default mode is set in .config.ribbon-focus-mode focusRibbon: ['Navigate/Focus Ribbon', - function(target){ + function(target, mode){ var data = this.data var r = data.getRibbon(target) if(r == null){ @@ -293,15 +311,36 @@ actions.Actions({ var c = data.getRibbonOrder() var i = data.getRibbonOrder(r) + mode = mode || this.config['ribbon-focus-mode'] || 'order' + // 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) + // closest image in order... + if(mode == 'order'){ + 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 + // if there are no images in the requied direction, try the + // other way... + t = t == null ? data.getImage(r, direction == 'before' ? 'after' : 'before') : t + + // first/last image... + } else if(mode == 'first' || mode == 'last'){ + var t = data.getImage(mode, r) + + // visually closest image... + //} else if(mode == 'visual'){ + } else { + var ribbons = this.ribbons + var t = ribbons.getImageByPosition('current', r) + + if(t.length > 1){ + t = t.eq(direction == 'before' ? 0 : 1) + } + + t = ribbons.getElemGID(t) + } this.focusImage(t, r) }], @@ -1984,6 +2023,66 @@ module.SingleImageView = ImageGridFeatures.Feature({ //--------------------------------------------------------------------- +// These feature glue traverse and ribbon alignment... + +// XXX manual align needs more work... +var AutoAlignRibbons = +module.AutoAlignRibbons = ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'ui-ribbon-auto-align', + depends: ['ui'], + exclusive: ['ui-ribbon-align'], + + config: { + // Control image selection and optionally ribbon alignment... + // + // NOTE: this only supports the following modes: + // - 'visual' + // - 'order' + // - 'fisrt' + // - 'manual' + // NOTE: if 'ribbon-align-mode' is not null this can be set to + // any mode without restriction. + //'ribbon-focus-mode': 'order', + 'ribbon-focus-mode': 'visual', + + // control ribbon alignment... + // + // NOTE: when this is null then 'ribbon-focus-mode' will be used... + // NOTE: this supports the same modes as 'ribbon-focus-mode'... + 'ribbon-align-mode': null, + }, + + handlers: [ + ['focusImage.post', + function(){ + var mode = this.config['ribbon-align-mode'] + || this.config['ribbon-focus-mode'] + + if(mode == 'visual' || mode == 'order'){ + this.alignByOrder() + + } else if(mode == 'first'){ + this.alignByFirst() + + // manual... + // XXX is this correct??? + } else { + this + .centerRibbon() + .centerImage() + } + }], + ], +}) + + +// XXX add a feature not to align the ribbons and focus the central +// image on next prev ribbon... +// XXX in general need a way to control .nextRibbon(..)/.prevRibbon(..) +// image selection... // XXX this should also define up/down navigation behavior e.g. what to // focus on next/prev ribbon... @@ -1998,6 +2097,11 @@ module.AlignRibbonsToImageOrder = ImageGridFeatures.Feature({ depends: ['ui'], exclusive: ['ui-ribbon-align'], + config: { + //'ribbon-focus-mode': 'order', + 'ribbon-focus-mode': 'visual', + }, + handlers: [ ['focusImage.post', function(){ this.alignByOrder() }] ], @@ -2013,11 +2117,41 @@ module.AlignRibbonsToFirstImage = ImageGridFeatures.Feature({ depends: ['ui'], exclusive: ['ui-ribbon-align'], + config: { + 'ribbon-focus-mode': 'first', + }, + handlers: [ ['focusImage.post', function(){ this.alignByFirst() }], ], }) +// XXX needs more work... +// XXX need to save position in some way, ad on each load the same +// initial state will get loaded... +// ...also would need an initial state... +var ManualAlignRibbons = +module.ManualAlignRibbons = ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'ui-ribbon-manual-align', + depends: ['ui'], + exclusive: ['ui-ribbon-align'], + + config: { + 'ribbon-focus-mode': 'visual', + }, + + handlers: [ + ['focusImage.post', function(){ + this + .centerRibbon() + .centerImage() + }], + ], +}) + //--------------------------------------------------------------------- @@ -3477,7 +3611,10 @@ ImageGridFeatures.Feature('viewer-testing', [ 'ui', // features... - 'ui-ribbon-align-to-order', + 'ui-ribbon-auto-align', + //'ui-ribbon-align-to-order', + //'ui-ribbon-align-to-first', + //'ui-ribbon-manual-align', 'ui-single-image-view', 'ui-partial-ribbons',