From d1ee0062e3cd236a74ea107c84665a5b5a830ecf Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Tue, 25 Nov 2014 15:56:59 +0300 Subject: [PATCH] added forced reloading (hack-ish, see viewer.js .load(..), .reload(..) and .updateRibbon(..) for more info) and some refactoring and cleanup... Signed-off-by: Alex A. Naanou --- ui (gen4)/data.js | 6 +- ui (gen4)/images.js | 22 +++++-- ui (gen4)/ribbons.js | 4 +- ui (gen4)/viewer.js | 142 +++++++++++++++++++++++-------------------- 4 files changed, 101 insertions(+), 73 deletions(-) diff --git a/ui (gen4)/data.js b/ui (gen4)/data.js index 13120ac7..02fd35b5 100755 --- a/ui (gen4)/data.js +++ b/ui (gen4)/data.js @@ -1583,10 +1583,14 @@ var DataPrototype = { // NOTE: group intersections are not allowed, i.e. images can not // belong to two groups. // NOTE: nesting groups is supported. (XXX test) + // + // XXX test if generated gid is unique... group: function(gids, group){ gids = gids == null ? this.getImage() : gids gids = gids.constructor !== Array ? [gids] : gids - group = group == null ? this.newGid('G') : group + // XXX not safe -- fast enough and one can generate two identical + // gids... + group = group == null ? this.newGid('G' + Date.now()) : group if(this.groups == null){ this.groups = {} diff --git a/ui (gen4)/images.js b/ui (gen4)/images.js index fb8b06d6..3bdeecc2 100755 --- a/ui (gen4)/images.js +++ b/ui (gen4)/images.js @@ -474,17 +474,27 @@ module.ImagesPrototype = { return gids }, // Shorthands... - // XXX these seem a bit messy... - sortByDate: function(gids, reverse){ return this.sortImages(gids, null, reverse) }, + // XXX default gids may include stray attributes... + sortByDate: function(gids, reverse){ + gids = gids == null ? Object.keys(this) : gids + return this.sortImages(gids, null, reverse) + }, sortByName: function(gids, reverse){ - return this.sortImages(gids, module.makeImageNameCmp(this), reverse) }, + gids = gids == null ? Object.keys(this) : gids + return this.sortImages(gids, module.makeImageNameCmp(this), reverse) + }, sortBySeqOrName: function(gids, reverse){ - return this.sortImages(gids, module.makeImageSeqOrNameCmp(this), reverse) }, + gids = gids == null ? Object.keys(this) : gids + return this.sortImages(gids, module.makeImageSeqOrNameCmp(this), reverse) + }, sortByNameXPStyle: function(gids, reverse){ + gids = gids == null ? Object.keys(this) : gids return this.sortImages(gids, module.makeImageSeqOrNameCmp(this, null, this.getImageNameLeadingSeq), - reverse) }, + reverse) + }, sortByDateOrSeqOrName: function(gids, reverse){ + gids = gids == null ? Object.keys(this) : gids return this.sortImages(gids, [ module.makeImageDateCmp(this), module.makeImageSeqOrNameCmp(this) @@ -492,6 +502,8 @@ module.ImagesPrototype = { }, // XXX sortedImagesByFileNameSeqWithOverflow: function(gids, reverse){ + gids = gids == null ? Object.keys(this) : gids + // XXX see ../ui/sort.js }, diff --git a/ui (gen4)/ribbons.js b/ui (gen4)/ribbons.js index 0c7e2876..57146182 100755 --- a/ui (gen4)/ribbons.js +++ b/ui (gen4)/ribbons.js @@ -1170,7 +1170,9 @@ var RibbonsPrototype = { // will not disable transitions, which at this point is the // responsibility of the caller... // NOTE: offset calculation depends on image blocks being square... - updateRibbon: function(gids, ribbon, reference, count){ + // NOTE: the argument force is currently ignored, it serves as a + // place holder for overloading... + updateRibbon: function(gids, ribbon, reference, force){ var that = this // get/create the ribbon... var r = this.getRibbon(ribbon) diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js index 320f1d2d..87883b42 100755 --- a/ui (gen4)/viewer.js +++ b/ui (gen4)/viewer.js @@ -19,12 +19,12 @@ var ribbons = require('ribbons') /*********************************************************************/ // helpers... -function reloadAfter(transitions){ +function reloadAfter(force){ return function(){ return function(){ // NOTE: this may seem like cheating, but .reload() should // be very efficient, reusing all of the items loaded... - this.reload() + this.reload(force) } } } @@ -677,7 +677,10 @@ actions.Actions(Client, { this.ribbons.clear() } + // NOTE: this is done unconditionally to avoid manually + // setting images and other stuff in the future... this.ribbons = ribbons.Ribbons(viewer, this.images) + // XXX is this correct??? this.ribbons.__image_updaters = [this.updateImage.bind(this)] @@ -686,20 +689,26 @@ actions.Actions(Client, { }], // NOTE: this will pass the .ribbons.updateData(..) a custom ribbon // updater if one is defined here as .updateRibbon(target) - // XXX actions.updateRibbon(..) and ribbons.updateRibbon(..) are NOT - // signature compatible... - // ...I'll fix this as/if I need to, right now there is no point to - // spend time and effort on unifying the interface when the common - // use-cases are not known + it seems quite logical as-is right now. + // XXX HACK: tow sins: + // - actions.updateRibbon(..) and ribbons.updateRibbon(..) + // are NOT signature compatible... + // - we depend on the internals of a custom add-on feature reload: ['Reload viewer', - function(){ + function(force){ this.ribbons.preventTransitions() + // NOTE: this essentially sets the update threshold to 0... + // XXX this should be a custom arg... + force = force ? 0 : null + return function(){ // see if we've got a custom ribbon updater... var that = this var settings = this.updateRibbon != null - ? { updateRibbon: function(_, ribbon){ that.updateRibbon(ribbon) } } + // XXX this should be: { updateRibbon: this.updateRibbon.bind(this) } + ? { updateRibbon: function(_, ribbon){ + that.updateRibbon(ribbon, null, null, force) + } } : null this.ribbons.updateData(this.data, settings) @@ -734,25 +743,20 @@ actions.Actions(Client, { }], - // XXX move this to a viewer window action set - close: ['Cloase viewer', - function(){ - // XXX should we do anything else here like auto-save??? - window.close() - }], - // XXX where should toggleFullscreenMode(..) be defined... - toggleFullScreen: ['', - function(){ - toggleFullscreenMode() - }], - // XXX revise this... - showDevTools: ['', - function(){ - if(window.showDevTools != null){ - showDevTools() - } - }], + // This is called by .ribbons, the goal is to use it to hook into + // image updating from features and extensions... + // + // NOTE: not intended for calling manually. + // + // XXX experimental... + // ...need this to get triggered by .ribbons + // at this point manually triggering this will not do anything... + updateImage: ['', + function(gid, image){ }], + + // General UI stuff... + // NOTE: this is applicable to all uses... toggleTheme: ['Toggle viewer theme', CSSClassToggler( function(){ return this.ribbons.viewer }, @@ -761,9 +765,35 @@ actions.Actions(Client, { 'dark', 'light' ]) ], + setEmptyMsg: ['Set message to be displayed when nothing is loaded.', + function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }], + + // App stuff... + // XXX move this to a viewer window action set + // XXX revise these... + close: ['Cloase viewer', + function(){ + // XXX should we do anything else here like auto-save??? + window.close() + }], + toggleFullScreen: ['', + function(){ + // XXX where should toggleFullscreenMode(..) be defined... + toggleFullscreenMode() + }], + showDevTools: ['', + function(){ + if(window.showDevTools != null){ + showDevTools() + } + }], + // align modes... - // XXX skip invisible ribbons (???) + // XXX these should also affect up/down navigation... + // ...navigate by proximity (closest to center) rather than by + // order... + // XXX skip off-screen ribbons (???) alignByOrder: ['Align ribbons by image order', function(target){ var ribbons = this.ribbons @@ -816,9 +846,6 @@ actions.Actions(Client, { } }, 50) }], - // XXX these should also affect up/down navigation... - // ...navigate by proximity (closest to center) rather than by - // order... alignByFirst: ['Aling ribbons except current to first image', function(target){ var ribbons = this.ribbons @@ -903,7 +930,6 @@ actions.Actions(Client, { } } }], - setBaseRibbon: [ function(target){ var r = this.data.getRibbon(target) @@ -961,7 +987,6 @@ actions.Actions(Client, { this.ribbons.setScale(1) this.ribbons.updateImage('*') }], - // NOTE: if this gets a count argument it will fit count images, // default is one. fitImage: ['Fit image', @@ -969,8 +994,6 @@ actions.Actions(Client, { this.ribbons.fitImage(count) this.ribbons.updateImage('*') }], - - fitMax: ['Fit the maximum number of images', function(){ this.fitImage(this.config['max-screen-images']) }], @@ -1000,8 +1023,6 @@ actions.Actions(Client, { shiftImageDown: [ function(target){ return updateImagePosition(this, target) }], - // XXX these produce jumpy animation when gathering images from the - // left from outside of the loaded partial ribbon... shiftImageLeft: [ function(target){ this.ribbons.placeImage(target, -1) @@ -1029,7 +1050,7 @@ actions.Actions(Client, { }], reverseImages: [ reloadAfter() ], - reverseRibbons: [ reloadAfter(true) ], + reverseRibbons: [ reloadAfter() ], // basic image editing... @@ -1045,20 +1066,21 @@ actions.Actions(Client, { function(target){ this.ribbons.flipHorizontal(target, 'view') }], + // group stuff... + group: [ reloadAfter(true) ], + ungroup: [ reloadAfter(true) ], + groupTo: [ reloadAfter(true) ], + groupMarked: [ reloadAfter(true) ], + expandGroup: [ reloadAfter(true) ], + collapseGroup: [ reloadAfter(true) ], + + crop: [ reloadAfter() ], uncrop: [ reloadAfter() ], - - // XXX need to force reload for actions that remove/add small numbers - // if images... - group: [ reloadAfter() ], - ungroup: [ reloadAfter() ], - groupTo: [ reloadAfter() ], - groupMarked: [ reloadAfter() ], - expandGroup: [ reloadAfter() ], - collapseGroup: [ reloadAfter() ], // XXX might be a good idea to do this in a new viewer in an overlay... cropGroup: [ reloadAfter() ], + // XXX experimental: not sure if this is the right way to go... // XXX make this play nice with crops... toggleRibbonList: ['Toggle ribbons as images view', @@ -1082,21 +1104,6 @@ actions.Actions(Client, { } }], - // a shorthand... - setEmptyMsg: ['Set message to be displayed when nothing is loaded.', - function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }], - - - // This is called by .ribbons, the goal is to use it to hook into - // image updating from features and extensions... - // - // NOTE: not intended for calling manually. - // - // XXX experimental... - // ...need this to get triggered by .ribbons - // at this point manually triggering this will not do anything... - updateImage: ['', - function(gid, image){ }], }) @@ -1229,7 +1236,9 @@ module.Features = Object.create(FeatureSet) // NOTE: this is split out to an action so as to enable ui elements to // adapt to ribbon size changes... // 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({ + // XXX this is not signature compatible with data.updateRibbon(..) updateRibbon: ['Update partial ribbon size', function(target, w, size, threshold){ target = target instanceof jQuery @@ -1242,9 +1251,10 @@ var PartialRibbonsActions = actions.Actions({ size = (size || this.config['ribbon-size-screens'] || 5) * w - threshold = (threshold - || this.config['ribbon-resize-threshold'] - || 1) * w + threshold = threshold == 0 ? threshold + : (threshold + || this.config['ribbon-resize-threshold'] + || 1) * w // next/prev loaded... var nl = this.ribbons.getImage(target).nextAll('.image:not(.clone)').length @@ -1258,7 +1268,7 @@ var PartialRibbonsActions = actions.Actions({ // do the update... // the target is not loaded... - if(this.ribbons.getImage(target).length == 0){ + if(threshold == 0 || this.ribbons.getImage(target).length == 0){ this.resizeRibbon(target, size) // do a late resize...