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 = var FeatureSet =
module.FeatureSet = { module.FeatureSet = {
__feature__: Feature,
// Build feature list... // Build feature list...
// //
// Build a list of all registered features // Build a list of all registered features
@ -283,6 +285,15 @@ module.FeatureSet = {
// X will be before one of its dependencies... // X will be before one of its dependencies...
// - dependency / priority conflict // - dependency / priority conflict
// X will have higher priority than one of its dependencies... // 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){ buildFeatureList: function(obj, lst, auto_include, depth){
lst = lst == null ? Object.keys(this) : lst lst = lst == null ? Object.keys(this) : lst
lst = lst.constructor !== Array ? [lst] : lst lst = lst.constructor !== Array ? [lst] : lst
@ -291,14 +302,14 @@ module.FeatureSet = {
var that = this var that = this
var missing = {}
// helpers... // helpers...
// NOTE: _skipMissing(..) will add missing dependencies to missing... // NOTE: _skipMissing(..) will add missing dependencies to missing...
var _skipMissing = function(feature, deps, missing){ var _skipMissing = function(feature, deps, missing){
return deps.filter(function(d){ return deps.filter(function(d){
if(lst.indexOf(d) < 0){ if(lst.indexOf(d) < 0){
if(missing[d] == null){ missing[d] = missing[d] != null ? missing[d] : []
missing[d] = []
}
if(missing[d].indexOf(feature) < 0){ if(missing[d].indexOf(feature) < 0){
missing[d].push(feature) missing[d].push(feature)
} }
@ -306,10 +317,15 @@ module.FeatureSet = {
return missing[d] == null return missing[d] == null
}) })
} }
var _sortDep = function(lst, missing){ var _sortDep = function(lst, missing, depth){
do {
var res = [] var res = []
var l = lst.length
lst.forEach(function(n){ lst.forEach(function(n){
var e = that[n] var e = that[n]
// no dependencies... // no dependencies...
if(e.depends == null || e.depends.length == 0){ if(e.depends == null || e.depends.length == 0){
res.push(n) res.push(n)
@ -330,15 +346,53 @@ module.FeatureSet = {
} }
}) })
return res lst = res
depth -= 1
} while(lst.length != l && depth > 0)
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... // expand optional "suggested" features...
// XXX make this recursive...
var res = [] var res = []
lst.forEach(function(n){ lst.forEach(function(n){
var e = that[n] var e = that[n]
if(e != null && e.suggested != null){ 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) res.push(n)
}) })
@ -346,14 +400,7 @@ module.FeatureSet = {
// expand and sort dependencies... // expand and sort dependencies...
// 2+ times untill depth is 0 or length stabelizes... // 2+ times untill depth is 0 or length stabelizes...
var missing = {} lst = _sortDep(lst, missing, depth).unique()
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 // sort features via priority keeping the order as close to
// manual as possible... // manual as possible...
@ -369,9 +416,14 @@ module.FeatureSet = {
// NOTE: for some reason JS compares lists as strings so we // NOTE: for some reason JS compares lists as strings so we
// have to comare the list manually... // have to comare the list manually...
.sort(function(a, b){ return a[0] - b[0] || a[1] - b[1] }) .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] }) .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... // clasify features...
var unapplicable = [] var unapplicable = []
var conflicts = {} var conflicts = {}
@ -392,6 +444,16 @@ module.FeatureSet = {
return true 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... // keep only conflicting...
var deps = e.depends.filter(function(dep){ var deps = e.depends.filter(function(dep){
dep = lst.indexOf(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 = var Viewer =
module.Viewer = features.Feature(ImageGridFeatures, { module.Viewer = ImageGridFeatures.Feature({
title: 'Graphical User Interface', title: 'Graphical User Interface',
tag: 'ui', tag: 'ui',
priority: 'high',
config: { config: {
// The maximum screen width allowed when zooming... // The maximum screen width allowed when zooming...
'max-screen-images': 30, 'max-screen-images': 30,
@ -1316,6 +1314,13 @@ module.Viewer = features.Feature(ImageGridFeatures, {
}, },
actions: ViewerActions, 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 // - .load(..) clears journal
// XXX needs careful testing... // XXX needs careful testing...
var Journal = var Journal =
module.Journal = features.Feature(ImageGridFeatures, { module.Journal = ImageGridFeatures.Feature({
title: 'Action Journal', title: 'Action Journal',
tag: 'system-journal', tag: 'system-journal',
@ -1558,7 +1563,7 @@ var PartialRibbonsActions = actions.Actions({
// - shift image up // - shift image up
// XXX The two should be completely independent.... (???) // XXX The two should be completely independent.... (???)
var PartialRibbons = var PartialRibbons =
module.PartialRibbons = features.Feature(ImageGridFeatures, { module.PartialRibbons = ImageGridFeatures.Feature({
title: 'Partial Ribbons', title: 'Partial Ribbons',
doc: 'Maintains partially loaded ribbons, this enables very lage ' doc: 'Maintains partially loaded ribbons, this enables very lage '
+'image sets to be hadled eficiently.', +'image sets to be hadled eficiently.',
@ -1704,7 +1709,7 @@ function updateImageProportions(){
// //
// //
var SingleImageView = var SingleImageView =
module.SingleImageView = features.Feature(ImageGridFeatures, { module.SingleImageView = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -1763,7 +1768,7 @@ module.SingleImageView = features.Feature(ImageGridFeatures, {
// XXX should .alignByOrder(..) be a feature-specific action or global // XXX should .alignByOrder(..) be a feature-specific action or global
// as it is now??? // as it is now???
var AlignRibbonsToImageOrder = var AlignRibbonsToImageOrder =
module.AlignRibbonsToImageOrder = features.Feature(ImageGridFeatures, { module.AlignRibbonsToImageOrder = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -1778,7 +1783,7 @@ module.AlignRibbonsToImageOrder = features.Feature(ImageGridFeatures, {
var AlignRibbonsToFirstImage = var AlignRibbonsToFirstImage =
module.AlignRibbonsToFirstImage = features.Feature(ImageGridFeatures, { module.AlignRibbonsToFirstImage = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -1797,7 +1802,7 @@ module.AlignRibbonsToFirstImage = features.Feature(ImageGridFeatures, {
// XXX at this point this does not support target lists... // XXX at this point this does not support target lists...
var ShiftAnimation = var ShiftAnimation =
module.ShiftAnimation = features.Feature(ImageGridFeatures, { module.ShiftAnimation = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -1883,7 +1888,7 @@ function didAdvance(indicator){
} }
var BoundsIndicators = var BoundsIndicators =
module.BoundsIndicators = features.Feature(ImageGridFeatures, { module.BoundsIndicators = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2042,7 +2047,7 @@ var CurrentImageIndicatorActions = actions.Actions({
}) })
var CurrentImageIndicator = var CurrentImageIndicator =
module.CurrentImageIndicator = features.Feature(ImageGridFeatures, { module.CurrentImageIndicator = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2143,7 +2148,7 @@ module.CurrentImageIndicator = features.Feature(ImageGridFeatures, {
var CurrentImageIndicatorHideOnFastScreenNav = var CurrentImageIndicatorHideOnFastScreenNav =
module.CurrentImageIndicatorHideOnFastScreenNav = features.Feature(ImageGridFeatures, { module.CurrentImageIndicatorHideOnFastScreenNav = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2208,7 +2213,7 @@ module.CurrentImageIndicatorHideOnFastScreenNav = features.Feature(ImageGridFeat
}) })
var CurrentImageIndicatorHideOnScreenNav = var CurrentImageIndicatorHideOnScreenNav =
module.CurrentImageIndicatorHideOnScreenNav = features.Feature(ImageGridFeatures, { module.CurrentImageIndicatorHideOnScreenNav = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2249,7 +2254,7 @@ module.CurrentImageIndicatorHideOnScreenNav = features.Feature(ImageGridFeatures
// XXX // XXX
var ImageStateIndicator = var ImageStateIndicator =
module.ImageStateIndicator = features.Feature(ImageGridFeatures, { module.ImageStateIndicator = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2263,7 +2268,7 @@ module.ImageStateIndicator = features.Feature(ImageGridFeatures, {
// XXX // XXX
var GlobalStateIndicator = var GlobalStateIndicator =
module.GlobalStateIndicator = features.Feature(ImageGridFeatures, { module.GlobalStateIndicator = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2463,7 +2468,7 @@ var ActionTreeActions = actions.Actions({
}) })
var ActionTree = var ActionTree =
module.ActionTree = features.Feature(ImageGridFeatures, { module.ActionTree = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2496,7 +2501,7 @@ module.ActionTree = features.Feature(ImageGridFeatures, {
// XXX need to get the minimal size and not the width as results will // XXX need to get the minimal size and not the width as results will
// depend on viewer format... // depend on viewer format...
var AutoSingleImage = var AutoSingleImage =
module.AutoSingleImage = features.Feature(ImageGridFeatures, { module.AutoSingleImage = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2655,7 +2660,7 @@ var ImageMarkActions = actions.Actions({
// NOTE: this is usable without ribbons... // NOTE: this is usable without ribbons...
var ImageMarks = var ImageMarks =
module.ImageMarks = features.Feature(ImageGridFeatures, { module.ImageMarks = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2717,7 +2722,7 @@ var ImageBookmarkActions = actions.Actions({
// NOTE: this is usable without ribbons... // NOTE: this is usable without ribbons...
var ImageBookmarks = var ImageBookmarks =
module.ImageBookmarks = features.Feature(ImageGridFeatures, { module.ImageBookmarks = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2767,7 +2772,7 @@ var AppControlActions = actions.Actions({
// XXX this needs a better .isApplicable(..) // XXX this needs a better .isApplicable(..)
var AppControl = var AppControl =
module.AppControl = features.Feature(ImageGridFeatures, { module.AppControl = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2789,7 +2794,7 @@ module.AppControl = features.Feature(ImageGridFeatures, {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// XXX at this point this is a stub... // XXX at this point this is a stub...
var FileSystemLoader = var FileSystemLoader =
module.FileSystemLoader = features.Feature(ImageGridFeatures, { module.FileSystemLoader = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',
@ -2812,7 +2817,7 @@ module.FileSystemLoader = features.Feature(ImageGridFeatures, {
// - editor - editing capability // - editor - editing capability
// //
features.Feature(ImageGridFeatures, 'viewer-testing', [ ImageGridFeatures.Feature('viewer-testing', [
'ui', 'ui',
// features... // features...
@ -2844,12 +2849,7 @@ features.Feature(ImageGridFeatures, 'viewer-testing', [
'system-journal', 'system-journal',
]) ])
features.Feature(ImageGridFeatures, 'commandline', [ ImageGridFeatures.Feature('viewer-minimal', [
'image-marks',
'image-bookmarks',
])
features.Feature(ImageGridFeatures, 'viewer-minimal', [
'ui', 'ui',
'ui-ribbon-align-to-order', 'ui-ribbon-align-to-order',
'ui-animation', 'ui-animation',
@ -2860,11 +2860,11 @@ features.Feature(ImageGridFeatures, 'viewer-minimal', [
'ui-action-tree', 'ui-action-tree',
]) ])
features.Feature(ImageGridFeatures, 'viewer', [ ImageGridFeatures.Feature('viewer', [
'viewer-minimal', 'viewer-minimal',
]) ])
features.Feature(ImageGridFeatures, 'viewer-partial', [ ImageGridFeatures.Feature('viewer-partial', [
'viewer', 'viewer',
'ui-partial-ribbons', 'ui-partial-ribbons',
]) ])
@ -2883,7 +2883,7 @@ var ExperimentActions = actions.Actions({
}) })
var ExperimentFeature = var ExperimentFeature =
module.ExperimentFeature = features.Feature(ImageGridFeatures, { module.ExperimentFeature = ImageGridFeatures.Feature({
title: '', title: '',
doc: '', doc: '',