mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
refactoring, minor fixes and tweaks + module toc's...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
2e19c02b0c
commit
73c9e60933
@ -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 })
|
||||
|
||||
@ -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...
|
||||
|
||||
@ -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 =
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user