From dfce671fff9bc6f7e77002a1968bb80f43ccb037 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Mon, 8 Dec 2014 17:37:29 +0300 Subject: [PATCH] refactoring of feature loading, now meta features are supported... Signed-off-by: Alex A. Naanou --- ui (gen4)/lib/features.js | 118 +++++++++++++++++++++----------------- ui (gen4)/ui.js | 7 +-- ui (gen4)/viewer.js | 26 ++++++--- 3 files changed, 86 insertions(+), 65 deletions(-) diff --git a/ui (gen4)/lib/features.js b/ui (gen4)/lib/features.js index 4b97fba2..a2bacda2 100755 --- a/ui (gen4)/lib/features.js +++ b/ui (gen4)/lib/features.js @@ -190,40 +190,56 @@ module.FeatureSet = { // e.g. a -> b but a has a higher priority that b thus // making it impossible to order the two without // breaking either the dependency or priority ordering. - buildFeatureList: function(obj, lst){ + // + // + // Dependency sorting: + // + // These are order dependencies, i.e. for a dependency to be + // resolved it must satisfy ALL of the folowing: + // - all dependencies must exist in the list. + // - all dependencies must be positiond/setup before the dependant. + // + // The general algorithm is as folows: + // 1) place the dependencies befeore the dependant for each element + // 2) remove the duplicate features except fot the first occurance + // 3) repeat 1 and 2 for 2 to depth times or until the feature list + // stabelizes, i.e. no new features are added on the last run. + // + // NOTE: if auto_include is true (default) this will add dependencies + // as they are needed... + // This is useful for "meta-features" that do nothing other than + // depend/include sets of other features, for exmale: 'ui', + // 'core', 'browser', ...etc. + // NOTE: dependency chains larger than depth will be dropped, this + // can be fixed by setting a greater depth (default: 8)... + // NOTE: conflicts that can occur and can not be recovered from: + // - cyclic dependency + // X will be before one of its dependencies... + // - dependency / priority conflict + // X will have higher priority than one of its dependencies... + buildFeatureList: function(obj, lst, auto_include, depth){ lst = lst == null ? Object.keys(this) : lst lst = lst.constructor !== Array ? [lst] : lst + auto_include = auto_include == null ? true : false + depth = depth || 8 var that = this - // sort dependencies... - // - // These are order dependencies, i.e. for a dependency to be - // resolved it must satisfy ALL of the folowing: - // - all dependencies must exist in the list. - // - all dependencies must be positiond/setup before the - // dependant. - // - // The general algorithm is as folows: - // 1) place the dependencies befeore the dependant for each - // element - // 2) remove the duplicate features except fot the first - // occurance - // 3) repeat 1 and 2 for a second time to cover 2'nd gen - // dependencies... - // - // NOTE: recursice dependency expansion is not needed here as if - // a dependency is not included in the list then it is not - // needed... - // NOTE: stage 2 is done later when filtering the list... - // NOTE: if dependency errors/conflicts exist this will break at - // the next step. - // NOTE: conflicta that can occur and can not be recovered from: - // - cyclic dependency - // X will be before one of its dependencies... - // - dependency / priority conflict - // X will have higher priority than one of its - // dependencies... + // helpers... + // NOTE: _skipMissing(..) will add missing dependencies to missing... + var _skipMissing = function(feature, deps, missing){ + return deps.filter(function(d){ + if(lst.indexOf(d) < 0){ + if(missing[d] == null){ + missing[d] = [] + } + if(missing[d].indexOf(feature) < 0){ + missing[d].push(feature) + } + } + return missing[d] == null + }) + } var _sortDep = function(lst, missing){ var res = [] lst.forEach(function(n){ @@ -233,21 +249,14 @@ module.FeatureSet = { res.push(n) } else { + // auto-include dependencies... + if(auto_include){ + var deps = e.depends + // skip dependencies that are not in list... - var deps = e.depends.filter(function(d){ - if(lst.indexOf(d) < 0){ - if(missing[d] == null){ - missing[d] = [] - } - - if(missing[d].indexOf(n) < 0){ - missing[d].push(n) - } - - return false - } - return true - }) + } else { + var deps = _skipMissing(n, e.depends, missing) + } // place dependencies before the depended... res = res.concat(deps) @@ -258,19 +267,21 @@ module.FeatureSet = { return res } + // expand and sort dependencies... + // 2+ times untill depth is 0 or length stabelizes... var missing = {} - // sort twice to cover the dependencies of dependencies... - // ...if this does not work we give up ;) - lst = _sortDep(lst, missing) - lst = _sortDep(lst, missing) + lst = _sortDep(lst, missing).unique() + var l + do { + l = lst.length + lst = _sortDep(lst, missing).unique() + depth -= 1 + } while(l != lst.length && depth > 0) // sort features via priority keeping the order as close to // manual as possible... var l = lst.length lst = lst - // remove duplicates, keeping only the first occurance... - //.filter(function(e, i, l){ return l.indexOf(e) == i }) - .unique() // remove undefined and non-features... .filter(function(e){ return that[e] != null && that[e] instanceof Feature }) @@ -311,14 +322,17 @@ module.FeatureSet = { }) // skip missing dependencies... - deps = deps.filter(function(d){ return missing[d] == null }) + // NOTE: we need to check for missing again as a feature + // could have been removed due to inapplicability or + // being undefined... + deps = _skipMissing(n, deps, missing) // no conflicts... if(deps.length == 0){ return true } - // can't fix... + // dependency exists but in wrong order -- can't fix... conflicts[n] = deps return false diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js index 18027cfd..0ca63383 100755 --- a/ui (gen4)/ui.js +++ b/ui (gen4)/ui.js @@ -217,12 +217,12 @@ $(function(){ 'ui-single-image-view', 'ui-partial-ribbons', + 'image-marks', + 'image-bookmarks', + 'fs-loader', 'app-control', - // ui elements... - 'image-marks', - 'image-bookmarks', // chrome... 'ui-animation', @@ -258,7 +258,6 @@ $(function(){ //.syncTags() - a.setEmptyMsg( 'Nothing loaded...', 'Press \'O\' to load, \'F1\' for help or \'?\' for keyboard mappings.') diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js index bc509a06..4f4a8e12 100755 --- a/ui (gen4)/viewer.js +++ b/ui (gen4)/viewer.js @@ -2156,7 +2156,7 @@ function makeTagTogglerAction(tag){ } -// XXX add image updater... +// XXX .toggleMarkBlock(..) not done yet... var ImageMarkActions = actions.Actions({ // a shorthand... @@ -2217,6 +2217,7 @@ var ImageMarkActions = actions.Actions({ }) +// NOTE: this is usable without ribbons... var ImageMarks = module.ImageMarks = features.Feature(ImageGridFeatures, { title: '', @@ -2229,10 +2230,13 @@ module.ImageMarks = features.Feature(ImageGridFeatures, { handlers: [ // XXX is this the right way to go??? ['updateImage', function(gid, img){ - if(this.toggleMark(gid, '?') == 'on'){ - this.ribbons.toggleImageMark(gid, 'selected', 'on') - } else { - this.ribbons.toggleImageMark(gid, 'selected', 'off') + // update only when ribbons are preset... + if(this.ribbons != null){ + if(this.toggleMark(gid, '?') == 'on'){ + this.ribbons.toggleImageMark(gid, 'selected', 'on') + } else { + this.ribbons.toggleImageMark(gid, 'selected', 'off') + } } }], ], @@ -2275,6 +2279,7 @@ var ImageBookmarkActions = actions.Actions({ }) +// NOTE: this is usable without ribbons... var ImageBookmarks = module.ImageBookmarks = features.Feature(ImageGridFeatures, { title: '', @@ -2287,10 +2292,13 @@ module.ImageBookmarks = features.Feature(ImageGridFeatures, { handlers: [ // XXX is this the right way to go??? ['updateImage', function(gid, img){ - if(this.toggleBookmark(gid, '?') == 'on'){ - this.ribbons.toggleImageMark(gid, 'bookmark', 'on') - } else { - this.ribbons.toggleImageMark(gid, 'bookmark', 'off') + // update only when ribbons are preset... + if(this.ribbons != null){ + if(this.toggleBookmark(gid, '?') == 'on'){ + this.ribbons.toggleImageMark(gid, 'bookmark', 'on') + } else { + this.ribbons.toggleImageMark(gid, 'bookmark', 'off') + } } }], ],