refactoring, minor fixes and tweaks + module toc's...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-01-02 01:23:33 +03:00
parent 2e19c02b0c
commit 73c9e60933
6 changed files with 309 additions and 227 deletions

View File

@ -1,6 +1,19 @@
/**********************************************************************
*
* All the base features...
* Base features...
*
* Features:
* - base
* map to data and images
* - crop
* - tags
* - groups
* XXX experimental...
*
* Meta Features:
* - base-full
* combines the above features into one
*
*
*
**********************************************************************/
@ -20,35 +33,6 @@ var core = require('features/core')
/*********************************************************************/
// Helpers and meta stuff...
// mode can be:
// "ribbon" - next marked in current ribbon (default)
// "all" - next marked in sequence
//
// XXX add support for tag lists...
var makeTagWalker =
module.makeTagWalker =
function(direction, dfl_tag){
var meth = direction == 'next' ? 'nextImage' : 'prevImage'
return function(tag, mode){
mode = mode == null ? 'all' : mode
tag = tag || dfl_tag
// account for no tags or no images tagged...
var lst = this.data.tags != null ? this.data.tags[tag] : []
lst = lst || []
if(mode == 'ribbon'){
this[meth](this.data.getImages(lst, 'current'))
} else {
this[meth](lst)
}
}
}
// Generate an undo function for shift operations...
//
@ -67,8 +51,7 @@ var undoShift = function(undo){
this[undo](a.args.length == 0 ? a.current : a.args[0]) }}
/*********************************************************************/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX split this into read and write actions...
var BaseActions =
@ -759,6 +742,36 @@ module.Base = core.ImageGridFeatures.Feature({
//---------------------------------------------------------------------
// Tags...
// mode can be:
// "ribbon" - next marked in current ribbon (default)
// "all" - next marked in sequence
//
// XXX add support for tag lists...
var makeTagWalker =
module.makeTagWalker =
function(direction, dfl_tag){
var meth = direction == 'next' ? 'nextImage' : 'prevImage'
return function(tag, mode){
mode = mode == null ? 'all' : mode
tag = tag || dfl_tag
// account for no tags or no images tagged...
var lst = this.data.tags != null ? this.data.tags[tag] : []
lst = lst || []
if(mode == 'ribbon'){
this[meth](this.data.getImages(lst, 'current'))
} else {
this[meth](lst)
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var TagsActions =
module.TagsActions = actions.Actions({
// tags...
@ -1186,185 +1199,5 @@ core.ImageGridFeatures.Feature('base-full', [
//---------------------------------------------------------------------
// Journal...
// XXX is this the right level for this???
// ...data seems to be a better candidate...
// XXX would be great to add a mechanism define how to reverse actions...
// ...one way to do this at this point is to revert to last state
// and re-run the journal until the desired event...
// XXX need to define a clear journaling strategy in the lines of:
// - save state clears journal and adds a state load action
// - .load(..) clears journal
// XXX needs careful testing...
var Journal =
module.Journal = core.ImageGridFeatures.Feature({
title: 'Action Journal',
tag: 'system-journal',
depends: [
'base'
],
actions: actions.Actions({
journal: null,
rjournal: null,
journalable: null,
updateJournalableActions: ['System/Update list of journalable actions',
function(){
var that = this
var handler = function(action){
return function(){
var cur = this.current
var args = args2array(arguments)
return function(){
this.journalPush({
type: 'basic',
action: action,
args: args,
// the current image before the action...
current: cur,
// the target (current) image after action...
target: this.current,
})
}
}
}
this.journalable = this.actions
.filter(function(action){
return !!that.getAttr(action, 'undo')
|| !!that.getAttr(action, 'journal')
})
// reset the handler
.map(function(action){
that
.off(action+'.pre', 'journal-handler')
.on(action+'.pre', 'journal-handler', handler(action))
return action
})
}],
clone: [function(full){
return function(res){
res.rjournal = null
res.journal = null
if(full && this.hasOwnProperty('journal') && this.journal){
res.journal = JSON.parse(JSON.stringify(this.journal))
}
}
}],
// XXX might be good to add some kind of metadata to journal...
journalPush: ['- System/Journal/Add an item to journal',
function(data){
this.journal = (this.hasOwnProperty('journal')
|| this.journal) ?
this.journal || []
: []
this.journal.push(data)
}],
clearJournal: ['System/Journal/Clear the action journal',
function(){
if(this.journal){
// NOTE: overwriting here is better as it will keep
// shadowing the parent's .journal in case we
// are cloned.
// NOTE: either way this will have no effect as we
// only use the local .journal but the user may
// get confused...
//delete this.journal
this.journal = null
}
}],
runJournal: ['- System/Journal/Run journal',
//{journal: true},
function(journal){
var that = this
journal.forEach(function(e){
// load state...
that
.focusImage(e.current)
// run action...
[e.action].apply(that, e.args)
})
}],
// XXX need to clear the rjournal as soon as we do something...
// ...at this point it is really easy to mess things up by
// undoing something, and after some actions doing a
// .redoLast(..)
// XXX this is not ready for production...
undo: ['Edit/Undo',
{browseMode: function(){
return (this.journal && this.journal.length > 0) || 'disabled' }},
function(){
var journal = this.journal
this.rjournal = (this.hasOwnProperty('rjournal')
|| this.rjournal) ?
this.rjournal
: []
for(var i = journal.length-1; i >= 0; i--){
var a = journal[i]
// see if the actions has an explicit undo attr...
var undo = this.getAttr(a.action, 'undo')
// general undo...
if(undo){
this.focusImage(a.current)
var undo = undo instanceof Function ?
// pass the action name...
undo.call(this, a)
: typeof(undo) == typeof('str') ?
// pass journal structure as-is...
this[undo].apply(this, a)
: null
// pop the undo command...
this.journal.pop()
this.rjournal.push(journal.splice(i, 1)[0])
break
}
}
}],
// XXX this is not final -- needs careful revision...
redo: ['Edit/Redo',
{browseMode: function(){
return (this.rjournal && this.rjournal.length > 0) || 'disabled' }},
function(){
if(!this.rjournal || this.rjournal.length == 0){
return
}
this.runJournal([this.rjournal.pop()])
}],
}),
// XXX need to drop journal on save...
// XXX rotate/truncate journal???
// XXX need to check that all the listed actions are clean -- i.e.
// running the journal will produce the same results as user
// actions that generated the journal.
handlers: [
// log state, action and its args...
['start',
function(){ this.updateJournalableActions() }],
],
})
/**********************************************************************
* vim:set ts=4 sw=4 : */ return module })

View File

@ -1,7 +1,31 @@
/**********************************************************************
*
* Core features that setup the life-cycle and the base interfaces for
* features to use...
* Core features...
* Setup the life-cycle and the base interfaces for features to use...
*
* Defined here:
* - protocol action constructor
* - config value toggler constructor
* - meta actions
* - .isToggler(..) predicate
* - .preActionHandler(..) used to toggler special args
* - ImageGrid root object/constructor
* - ImageGridFeatures object
*
*
* Features:
* - lifecycle
* base life-cycle events (start/stop/..)
* - util
* - introspection
* - journal
* action journaling and undo/redo functionality
* XXX needs revision...
* - workspace
* XXX needs revision...
* - tasks
* XXX not yet used
*
*
*
**********************************************************************/
@ -333,6 +357,8 @@ module.notUserCallable = function(func){
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var IntrospectionActions = actions.Actions({
// user-callable actions...
get useractions(){
@ -356,6 +382,198 @@ module.Introspection = ImageGridFeatures.Feature({
//---------------------------------------------------------------------
// Journal...
// XXX would be great to add a mechanism define how to reverse actions...
// ...one way to do this at this point is to revert to last state
// and re-run the journal until the desired event...
// XXX need to define a clear journaling strategy in the lines of:
// - save state clears journal and adds a state load action
// - .load(..) clears journal
// XXX needs careful testing...
var JournalActions = actions.Actions({
clone: [function(full){
return function(res){
res.rjournal = null
res.journal = null
if(full && this.hasOwnProperty('journal') && this.journal){
res.journal = JSON.parse(JSON.stringify(this.journal))
}
}
}],
journal: null,
rjournal: null,
journalable: null,
updateJournalableActions: ['System/Update list of journalable actions',
function(){
var that = this
var handler = function(action){
return function(){
var cur = this.current
var args = args2array(arguments)
return function(){
this.journalPush({
type: 'basic',
action: action,
args: args,
// the current image before the action...
current: cur,
// the target (current) image after action...
target: this.current,
})
}
}
}
this.journalable = this.actions
.filter(function(action){
return !!that.getAttr(action, 'undo')
|| !!that.getAttr(action, 'journal')
})
// reset the handler
.map(function(action){
that
.off(action+'.pre', 'journal-handler')
.on(action+'.pre', 'journal-handler', handler(action))
return action
})
}],
journalPush: ['- System/Journal/Add an item to journal',
function(data){
// clear the reverse journal...
this.rjournal
&& (this.rjournal = null)
this.journal = (this.hasOwnProperty('journal') || this.journal) ?
this.journal || []
: []
this.journal.push(data)
}],
clearJournal: ['System/Journal/Clear the action journal',
function(){
// NOTE: overwriting here is better as it will keep
// shadowing the parent's .journal in case we
// are cloned.
// NOTE: either way this will have no effect as we
// only use the local .journal but the user may
// get confused...
//delete this.journal
this.journal
&& (this.journal = null)
this.rjournal
&& (this.rjournal = null)
}],
runJournal: ['- System/Journal/Run journal',
//{journal: true},
function(journal){
var that = this
journal.forEach(function(e){
// load state...
that
.focusImage(e.current)
// run action...
[e.action].apply(that, e.args)
})
}],
// XXX needs very careful revision...
// - should this be thread safe??? (likely not)
// - should the undo action have side-effects on the
// journal/rjournal or should we clean them out???
// (currently cleaned)
undo: ['Edit/Undo',
{browseMode: function(){
return (this.journal && this.journal.length > 0) || 'disabled' }},
function(){
var journal = this.journal.slice() || []
var rjournal = this.rjournal =
(this.hasOwnProperty('rjournal') || this.rjournal) ?
this.rjournal || []
: []
for(var i = journal.length-1; i >= 0; i--){
var a = journal[i]
// see if the action has an explicit undo attr...
var undo = this.getAttr(a.action, 'undo')
// general undo...
if(undo){
// restore focus to where it was when the action
// was called...
this.focusImage(a.current)
// call the undo method/action...
// NOTE: this is likely to have side-effect on the
// journal and maybe even rjournal...
// NOTE: these side-effects are cleaned out later.
var undo = undo instanceof Function ?
// pass the action name...
undo.call(this, a)
: typeof(undo) == typeof('str') ?
// pass journal structure as-is...
this[undo].apply(this, a)
: null
// push the undone command to the reverse journal...
rjournal.push(journal.splice(i, 1)[0])
// restore journal state...
// NOTE: calling the undo action would have cleared
// the rjournal and added stuff to the journal
// so we will need to restore things...
this.journal = journal
this.rjournal = rjournal
break
}
}
}],
redo: ['Edit/Redo',
{browseMode: function(){
return (this.rjournal && this.rjournal.length > 0) || 'disabled' }},
function(){
if(!this.rjournal || this.rjournal.length == 0){
return
}
this.runJournal([this.rjournal.pop()])
}],
})
var Journal =
module.Journal = ImageGridFeatures.Feature({
title: 'Action Journal',
tag: 'journal',
actions: JournalActions,
// XXX need to drop journal on save...
// XXX rotate/truncate journal???
// XXX need to check that all the listed actions are clean -- i.e.
// running the journal will produce the same results as user
// actions that generated the journal.
handlers: [
// log state, action and its args...
['start',
function(){ this.updateJournalableActions() }],
],
})
//---------------------------------------------------------------------
// Workspace...
//
@ -421,7 +639,6 @@ module.makeWorkspaceConfigLoader = function(keys, callback){
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX need a way to handle defaults...

View File

@ -1034,11 +1034,9 @@ var CommentsActions = actions.Actions({
__comments: null,
get comments(){
return this.__comments
},
return this.__comments },
set comments(value){
this.__comments = value
},
this.__comments = value },
})
var Comments =

View File

@ -48,11 +48,9 @@ var URLHistoryActions = actions.Actions({
// NOTE: though functions are supported they are not recommended as
// we can not stringify them to JSON...
get url_history(){
return this.hasOwnProperty('__url_history') ? this.__url_history : undefined
},
return this.hasOwnProperty('__url_history') ? this.__url_history : undefined },
set url_history(value){
this.__url_history = value
},
this.__url_history = value },
clone: [function(full){
@ -495,7 +493,7 @@ var URLHistoryUIActions = actions.Actions({
l++
})
// empty history...
// history is empty...
if(l == 0){
make('No history...', null, true)
.find('.button').remove()

View File

@ -52,7 +52,7 @@ core.ImageGridFeatures.Feature('viewer-testing', [
'ui',
'keyboard',
'ui-ribbons-placement',
//'ui-ribbons-placement',
// features...
'ui-ribbon-auto-align',
@ -121,7 +121,7 @@ core.ImageGridFeatures.Feature('viewer-testing', [
'ui-app-control',
// XXX not yet fully tested...
'system-journal',
'journal',
'fail-safe-devtools',

View File

@ -1,5 +1,41 @@
/**********************************************************************
*
* User Interface Features...
*
* Features:
* - ui
* maps ribbons to base (data + images)
* - config-local-storage
* maintain configuration state in local storage
* - ui-url-hash
* handle .location.hash
* - ui-ribbon-auto-align
* handle ribbon alignment...
* - ui-ribbon-align-to-order
* - ui-ribbon-align-to-first
* - ui-ribbon-manual-align
* - ui-animation
* manage UI non-css animations...
* - ui-autohide-cursor
* - ui-control
* control mechanics (touch/mouse)
*
* Dev Features:
* - fail-safe-devtools
* starts devtools if for some reason the main ui fails to start.
*
* Experimental Features:
* - ui-ribbons-placement
* manage different low level ribbon placement mechanics
* XXX experimental...
* - auto-single-image
* - auto-ribbon
*
* Legacy:
* - ui-clickable
* - ui-direct-control-hammer
* - ui-indirect-control
*
*
*
**********************************************************************/
@ -22,7 +58,6 @@ var base = require('features/base')
/*********************************************************************/
var reloadAfter =
module.reloadAfter =
function(force, callback){
@ -2058,6 +2093,7 @@ var ControlActions = actions.Actions({
}
})],
// XXX revise name...
makeRibbonVisible: ['- Interface/Make ribbon visible if it is off screen',
function(target, center_off_screen){
var r = this.ribbons.getRibbon(target)