some refactoring and rework of feature logic...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2015-11-05 02:27:26 +03:00
parent 50bd9d2b45
commit c66eb2e354
2 changed files with 131 additions and 63 deletions

View File

@ -230,6 +230,8 @@ Feature.prototype.constructor = Feature
var FeatureSet =
module.FeatureSet = {
__feature__: Feature,
// Build feature list...
//
// Build a list of all registered features
@ -283,6 +285,15 @@ module.FeatureSet = {
// X will be before one of its dependencies...
// - dependency / priority conflict
// X will have higher priority than one of its dependencies...
// NOTE: feature that depend in unapplicable features are considered
// unapplicable.
// XXX not sure if this is 100% correct...
// NOTE: child high priority features will push their dependencies up
// to precede them.
// ...this will not resolve all the possible conflicts so be
// careful.
//
// XXX make suggested feature expansion recursive...
buildFeatureList: function(obj, lst, auto_include, depth){
lst = lst == null ? Object.keys(this) : lst
lst = lst.constructor !== Array ? [lst] : lst
@ -291,14 +302,14 @@ module.FeatureSet = {
var that = this
var missing = {}
// 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] = []
}
missing[d] = missing[d] != null ? missing[d] : []
if(missing[d].indexOf(feature) < 0){
missing[d].push(feature)
}
@ -306,39 +317,82 @@ module.FeatureSet = {
return missing[d] == null
})
}
var _sortDep = function(lst, missing){
var res = []
lst.forEach(function(n){
var e = that[n]
// no dependencies...
if(e.depends == null || e.depends.length == 0){
res.push(n)
var _sortDep = function(lst, missing, depth){
} else {
// auto-include dependencies...
if(auto_include){
var deps = e.depends
do {
var res = []
var l = lst.length
lst.forEach(function(n){
var e = that[n]
// no dependencies...
if(e.depends == null || e.depends.length == 0){
res.push(n)
// skip dependencies that are not in list...
} else {
var deps = _skipMissing(n, e.depends, missing)
// auto-include dependencies...
if(auto_include){
var deps = e.depends
// skip dependencies that are not in list...
} else {
var deps = _skipMissing(n, e.depends, missing)
}
// place dependencies before the depended...
res = res.concat(deps)
res.push(n)
}
// place dependencies before the depended...
res = res.concat(deps)
res.push(n)
}
})
lst = res
depth -= 1
} while(lst.length != l && depth > 0)
})
return res
return lst
}
var _getSuggested = function(featureset, feature, suggested, missing){
suggested = suggested || []
var s = (feature.suggested || [])
s
// remove the already visited suggenstions...
.filter(function(e){ return suggested.indexOf(e) < 0 })
// add unloaded features to missing...
.filter(function(e){
if(featureset[e] == null){
missing[e] = missing[e] != null ? missing[e] : []
if(missing[e].indexOf(feature.tag) < 0){
missing[e].push(feature.tag)
}
return false
}
return true
})
// load new suggenstions...
.forEach(function(n){
var e = featureset[n]
if(e != null && e.suggested != null){
suggested = suggested
.concat(_getSuggested(featureset, e, suggested, missing))
.unique()
}
suggested.push(n)
})
return suggested
}
// expand optional "suggested" features...
// XXX make this recursive...
var res = []
lst.forEach(function(n){
var e = that[n]
if(e != null && e.suggested != null){
res = res.concat(e.suggested)
//res = res.concat(e.suggested)
res = res.concat(_getSuggested(that, e, res, missing))
}
res.push(n)
})
@ -346,14 +400,7 @@ module.FeatureSet = {
// expand and sort dependencies...
// 2+ times untill depth is 0 or length stabelizes...
var 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)
lst = _sortDep(lst, missing, depth).unique()
// sort features via priority keeping the order as close to
// manual as possible...
@ -369,9 +416,14 @@ module.FeatureSet = {
// NOTE: for some reason JS compares lists as strings so we
// have to comare the list manually...
.sort(function(a, b){ return a[0] - b[0] || a[1] - b[1] })
// cleanup -- drom the table...
// cleanup -- drop the table...
.map(function(e){ return e[2] })
// sort dependencies again...
// NOTE: this bubles the "priority" up the dependency tree...
// NOTE: this will not resolve all the conflicts...
lst = _sortDep(lst, missing, depth).unique()
// clasify features...
var unapplicable = []
var conflicts = {}
@ -392,6 +444,16 @@ module.FeatureSet = {
return true
}
// mark feature unapplicable if it depends on an unapplicable...
// NOTE: we need to do this once as features at this point
// are sorted by dependencies...
if(e.depends.filter(function(dep){
return unapplicable.indexOf(dep) > -1
}).length > 0){
unapplicable.push(n)
return false
}
// keep only conflicting...
var deps = e.depends.filter(function(dep){
dep = lst.indexOf(dep)
@ -512,6 +574,12 @@ module.FeatureSet = {
}
})
},
// shorthand for: Feature(<feature-set>, ...)
// XXX should this return this?
Feature: function(){
return this.__feature__.apply(null, [this].concat(args2array(arguments)))
},
}

View File

@ -1293,13 +1293,11 @@ actions.Actions({
})
var Viewer =
module.Viewer = features.Feature(ImageGridFeatures, {
module.Viewer = ImageGridFeatures.Feature({
title: 'Graphical User Interface',
tag: 'ui',
priority: 'high',
config: {
// The maximum screen width allowed when zooming...
'max-screen-images': 30,
@ -1316,6 +1314,13 @@ module.Viewer = features.Feature(ImageGridFeatures, {
},
actions: ViewerActions,
// check if we are running in a UI context...
// NOTE: this will prevent loading of any features dependant on the
// UI in a non UI context...
isApplicable: function(){
return typeof(window) == typeof({})
},
})
@ -1332,7 +1337,7 @@ module.Viewer = features.Feature(ImageGridFeatures, {
// - .load(..) clears journal
// XXX needs careful testing...
var Journal =
module.Journal = features.Feature(ImageGridFeatures, {
module.Journal = ImageGridFeatures.Feature({
title: 'Action Journal',
tag: 'system-journal',
@ -1558,7 +1563,7 @@ var PartialRibbonsActions = actions.Actions({
// - shift image up
// XXX The two should be completely independent.... (???)
var PartialRibbons =
module.PartialRibbons = features.Feature(ImageGridFeatures, {
module.PartialRibbons = ImageGridFeatures.Feature({
title: 'Partial Ribbons',
doc: 'Maintains partially loaded ribbons, this enables very lage '
+'image sets to be hadled eficiently.',
@ -1704,7 +1709,7 @@ function updateImageProportions(){
//
//
var SingleImageView =
module.SingleImageView = features.Feature(ImageGridFeatures, {
module.SingleImageView = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -1763,7 +1768,7 @@ module.SingleImageView = features.Feature(ImageGridFeatures, {
// XXX should .alignByOrder(..) be a feature-specific action or global
// as it is now???
var AlignRibbonsToImageOrder =
module.AlignRibbonsToImageOrder = features.Feature(ImageGridFeatures, {
module.AlignRibbonsToImageOrder = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -1778,7 +1783,7 @@ module.AlignRibbonsToImageOrder = features.Feature(ImageGridFeatures, {
var AlignRibbonsToFirstImage =
module.AlignRibbonsToFirstImage = features.Feature(ImageGridFeatures, {
module.AlignRibbonsToFirstImage = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -1797,7 +1802,7 @@ module.AlignRibbonsToFirstImage = features.Feature(ImageGridFeatures, {
// XXX at this point this does not support target lists...
var ShiftAnimation =
module.ShiftAnimation = features.Feature(ImageGridFeatures, {
module.ShiftAnimation = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -1883,7 +1888,7 @@ function didAdvance(indicator){
}
var BoundsIndicators =
module.BoundsIndicators = features.Feature(ImageGridFeatures, {
module.BoundsIndicators = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2042,7 +2047,7 @@ var CurrentImageIndicatorActions = actions.Actions({
})
var CurrentImageIndicator =
module.CurrentImageIndicator = features.Feature(ImageGridFeatures, {
module.CurrentImageIndicator = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2143,7 +2148,7 @@ module.CurrentImageIndicator = features.Feature(ImageGridFeatures, {
var CurrentImageIndicatorHideOnFastScreenNav =
module.CurrentImageIndicatorHideOnFastScreenNav = features.Feature(ImageGridFeatures, {
module.CurrentImageIndicatorHideOnFastScreenNav = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2208,7 +2213,7 @@ module.CurrentImageIndicatorHideOnFastScreenNav = features.Feature(ImageGridFeat
})
var CurrentImageIndicatorHideOnScreenNav =
module.CurrentImageIndicatorHideOnScreenNav = features.Feature(ImageGridFeatures, {
module.CurrentImageIndicatorHideOnScreenNav = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2249,7 +2254,7 @@ module.CurrentImageIndicatorHideOnScreenNav = features.Feature(ImageGridFeatures
// XXX
var ImageStateIndicator =
module.ImageStateIndicator = features.Feature(ImageGridFeatures, {
module.ImageStateIndicator = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2263,7 +2268,7 @@ module.ImageStateIndicator = features.Feature(ImageGridFeatures, {
// XXX
var GlobalStateIndicator =
module.GlobalStateIndicator = features.Feature(ImageGridFeatures, {
module.GlobalStateIndicator = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2463,7 +2468,7 @@ var ActionTreeActions = actions.Actions({
})
var ActionTree =
module.ActionTree = features.Feature(ImageGridFeatures, {
module.ActionTree = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2496,7 +2501,7 @@ module.ActionTree = features.Feature(ImageGridFeatures, {
// XXX need to get the minimal size and not the width as results will
// depend on viewer format...
var AutoSingleImage =
module.AutoSingleImage = features.Feature(ImageGridFeatures, {
module.AutoSingleImage = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2655,7 +2660,7 @@ var ImageMarkActions = actions.Actions({
// NOTE: this is usable without ribbons...
var ImageMarks =
module.ImageMarks = features.Feature(ImageGridFeatures, {
module.ImageMarks = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2717,7 +2722,7 @@ var ImageBookmarkActions = actions.Actions({
// NOTE: this is usable without ribbons...
var ImageBookmarks =
module.ImageBookmarks = features.Feature(ImageGridFeatures, {
module.ImageBookmarks = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2767,7 +2772,7 @@ var AppControlActions = actions.Actions({
// XXX this needs a better .isApplicable(..)
var AppControl =
module.AppControl = features.Feature(ImageGridFeatures, {
module.AppControl = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2789,7 +2794,7 @@ module.AppControl = features.Feature(ImageGridFeatures, {
//---------------------------------------------------------------------
// XXX at this point this is a stub...
var FileSystemLoader =
module.FileSystemLoader = features.Feature(ImageGridFeatures, {
module.FileSystemLoader = ImageGridFeatures.Feature({
title: '',
doc: '',
@ -2812,7 +2817,7 @@ module.FileSystemLoader = features.Feature(ImageGridFeatures, {
// - editor - editing capability
//
features.Feature(ImageGridFeatures, 'viewer-testing', [
ImageGridFeatures.Feature('viewer-testing', [
'ui',
// features...
@ -2844,12 +2849,7 @@ features.Feature(ImageGridFeatures, 'viewer-testing', [
'system-journal',
])
features.Feature(ImageGridFeatures, 'commandline', [
'image-marks',
'image-bookmarks',
])
features.Feature(ImageGridFeatures, 'viewer-minimal', [
ImageGridFeatures.Feature('viewer-minimal', [
'ui',
'ui-ribbon-align-to-order',
'ui-animation',
@ -2860,11 +2860,11 @@ features.Feature(ImageGridFeatures, 'viewer-minimal', [
'ui-action-tree',
])
features.Feature(ImageGridFeatures, 'viewer', [
ImageGridFeatures.Feature('viewer', [
'viewer-minimal',
])
features.Feature(ImageGridFeatures, 'viewer-partial', [
ImageGridFeatures.Feature('viewer-partial', [
'viewer',
'ui-partial-ribbons',
])
@ -2883,7 +2883,7 @@ var ExperimentActions = actions.Actions({
})
var ExperimentFeature =
module.ExperimentFeature = features.Feature(ImageGridFeatures, {
module.ExperimentFeature = ImageGridFeatures.Feature({
title: '',
doc: '',