mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 10:50:08 +00:00
reworked the action framework...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
f4abf42763
commit
dc53204eef
@ -42,14 +42,111 @@ var SCREEN_IMAGES = null
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
//
|
||||||
|
// Contexts:
|
||||||
|
// Browser node node-webkit PhoneGap
|
||||||
|
// UI o x o o
|
||||||
|
// navigation o o o o
|
||||||
|
// edit o, x o o, x o, x
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// The basic inheritance tree should be something like this:
|
||||||
|
//
|
||||||
|
// .
|
||||||
|
// Data . UI
|
||||||
|
// .
|
||||||
|
// MetaActions .
|
||||||
|
// ^ .
|
||||||
|
// | .
|
||||||
|
// | .
|
||||||
|
// BaseActions .
|
||||||
|
// ^ ^ .
|
||||||
|
// | +------------------ UIActions
|
||||||
|
// | . ^
|
||||||
|
// | . | -+
|
||||||
|
// BaseMarks . | |
|
||||||
|
// ^ . | | Plugin
|
||||||
|
// + - - - - -???- - - UIMarks |
|
||||||
|
// . -+
|
||||||
|
// .
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// XXX Need a way to combine a set of features into a view, preferably
|
||||||
|
// in runtime...
|
||||||
|
// - turn feature on/off at load
|
||||||
|
// - turn feature on/off in runtime
|
||||||
|
//
|
||||||
|
// XXX without multiple inheritance we'll need to either:
|
||||||
|
//
|
||||||
|
// - build inheritance chains per task -- i.e. connect blocks in
|
||||||
|
// a custom way depending on use
|
||||||
|
// ...this makes it really hard to have two systems configured
|
||||||
|
// differently in the same runtime...
|
||||||
|
//
|
||||||
|
// - build a multiple inheritance system
|
||||||
|
// ...without the ability to hook into attribute access this is
|
||||||
|
// not trivial... (feasibility unknown)
|
||||||
|
//
|
||||||
|
// - make the UI versions by copying methods from the base and UI
|
||||||
|
// into a single object, effectively creating two separate chains
|
||||||
|
// ...auto-creating proxy methods is another way to implement this
|
||||||
|
// + solves the problem
|
||||||
|
// - not dynamic -- changes have to be applied to both chains
|
||||||
|
// rather than to a single relevant object.
|
||||||
|
//
|
||||||
|
// - encapsulate and proxy?
|
||||||
|
//
|
||||||
|
// - static mixin...
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// XXX actions should be split by feature
|
||||||
|
// - basic navigation
|
||||||
|
// - basic editing
|
||||||
|
// - cropping
|
||||||
|
// - marking
|
||||||
|
// - bookmarking
|
||||||
|
// - tagging
|
||||||
|
// - image editing
|
||||||
|
// - url loading
|
||||||
|
// - url saving
|
||||||
|
// - fs loading
|
||||||
|
// - fs saving
|
||||||
|
// Features can be organized into contexts:
|
||||||
|
// - browser viewer
|
||||||
|
// - browser editor
|
||||||
|
// - app viewer
|
||||||
|
// - app editor
|
||||||
|
//
|
||||||
|
// XXX each plugin must be split into:
|
||||||
|
// - UI view -- display only
|
||||||
|
// - UI controls -- edit
|
||||||
|
// - base actions -- usable without UI
|
||||||
|
//
|
||||||
|
// XXX think about life-cycle...
|
||||||
|
//
|
||||||
|
//
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
// XXX need a way to define compound actions...
|
var BaseActions =
|
||||||
// - compound action is like a normal action with a set of other
|
module.BaseActions = actions.Actions({
|
||||||
// actions chanined to it's main event.
|
// state props...
|
||||||
// - actions should accept arguments, both optional and required
|
get current(){
|
||||||
var BASE_ACTIONS =
|
// XXX should this return a gid or a jQuery-like object for
|
||||||
module.BASE_ACTIONS = {
|
// image-oriented operations???
|
||||||
|
return this.data.current
|
||||||
|
},
|
||||||
|
set current(val){
|
||||||
|
return this.focusImage(val)
|
||||||
|
},
|
||||||
|
|
||||||
|
// life-cycle / state...
|
||||||
|
// XXX
|
||||||
|
|
||||||
|
// actions...
|
||||||
|
focusImage: '',
|
||||||
|
focusRibbon: '',
|
||||||
|
|
||||||
// basic editing...
|
// basic editing...
|
||||||
shiftImageUp:
|
shiftImageUp:
|
||||||
'Shift image to the ribbon above current, creating one if '
|
'Shift image to the ribbon above current, creating one if '
|
||||||
@ -100,16 +197,14 @@ module.BASE_ACTIONS = {
|
|||||||
exportImages: '',
|
exportImages: '',
|
||||||
|
|
||||||
exit: '',
|
exit: '',
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
var UI_ACTIONS =
|
var UIActions =
|
||||||
module.UI_ACTIONS = {
|
module.UIActions = {
|
||||||
focusImage: '',
|
|
||||||
focusRibbon: '',
|
|
||||||
|
|
||||||
// basic navigation...
|
// basic navigation...
|
||||||
nextImage: ['Focus next image in current ribbon', { focusImage: 'next' }],
|
nextImage: ['Focus next image in current ribbon', { focusImage: 'next' }],
|
||||||
|
|||||||
@ -59,6 +59,7 @@ define(function(require){ var module = {}
|
|||||||
//
|
//
|
||||||
// // event-like callbacks for actions...
|
// // event-like callbacks for actions...
|
||||||
// O.on('m', function(){...})
|
// O.on('m', function(){...})
|
||||||
|
// O.on('m.pre', function(){...})
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Comparing to the native system:
|
// Comparing to the native system:
|
||||||
@ -88,12 +89,21 @@ function _collect_handlers(obj, name){
|
|||||||
var handlers = []
|
var handlers = []
|
||||||
var cur = obj
|
var cur = obj
|
||||||
while(cur.__proto__ != null){
|
while(cur.__proto__ != null){
|
||||||
if(obj._action_handlers == null){
|
// get action "event" handlers...
|
||||||
break
|
if(cur.hasOwnProperty('_action_handlers')
|
||||||
|
&& name in cur._action_handlers){
|
||||||
|
handlers.splice.apply(handlers,
|
||||||
|
[handlers.length, 0].concat(cur._action_handlers[name]))
|
||||||
}
|
}
|
||||||
if(cur.hasOwnProperty('_action_handlers') && name in cur._action_handlers){
|
|
||||||
handlers.splice.apply(handlers, [0, 0].concat(cur._action_handlers[name]))
|
// get the overloading action...
|
||||||
|
// NOTE: this will get all the handlers including the root
|
||||||
|
// and the current handlers...
|
||||||
|
// NOTE: this will ignore "shadows" that are not actions...
|
||||||
|
if(cur.hasOwnProperty(name) && cur[name] instanceof Action){
|
||||||
|
handlers.push(cur[name].func)
|
||||||
}
|
}
|
||||||
|
|
||||||
cur = cur.__proto__
|
cur = cur.__proto__
|
||||||
}
|
}
|
||||||
return handlers
|
return handlers
|
||||||
@ -105,6 +115,30 @@ function _collect_handlers(obj, name){
|
|||||||
|
|
||||||
// Construct an action object...
|
// Construct an action object...
|
||||||
//
|
//
|
||||||
|
// Action format:
|
||||||
|
// function(){
|
||||||
|
// ... // pre code
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function(){
|
||||||
|
// ... // pre code
|
||||||
|
// return function(){
|
||||||
|
// ... // post code
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function(){
|
||||||
|
// ... // pre code
|
||||||
|
// return $.Deferred()
|
||||||
|
// .done(function(){
|
||||||
|
// ... // post code
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// NOTE: it is not possible to auto-generate Class.__proto__.meth(..) calls
|
||||||
|
// without explicitly knowing the Class, thus using the overloading
|
||||||
|
// mechanism is not feasible until this is solved...
|
||||||
var Action =
|
var Action =
|
||||||
module.Action =
|
module.Action =
|
||||||
function Action(name, doc, ldoc, func){
|
function Action(name, doc, ldoc, func){
|
||||||
@ -126,30 +160,30 @@ function Action(name, doc, ldoc, func){
|
|||||||
var that = this
|
var that = this
|
||||||
var args = args2array(arguments)
|
var args = args2array(arguments)
|
||||||
|
|
||||||
// normal handlers -- pre phase...
|
// get and call handlers -- pre phase...
|
||||||
var handlers = _collect_handlers(this, name)
|
var handlers = _collect_handlers(this, name)
|
||||||
.map(function(h){ return h.apply(that, args) })
|
.map(function(h){ return h.apply(that, args) })
|
||||||
|
|
||||||
// call the action...
|
// NOTE: this action will get included and called by the code
|
||||||
var res = func.apply(this, args)
|
// above and below...
|
||||||
|
|
||||||
// simple post callback...
|
// call handlers -- post phase...
|
||||||
//_collect_handlers(this, name)
|
// NOTE: post handlers need to get called last run pre first run post...
|
||||||
// .forEach(function(h){ return h.apply(that, args) })
|
handlers.reverse().forEach(function(h){
|
||||||
|
// function...
|
||||||
// normal handlers -- post phase...
|
|
||||||
handlers.forEach(function(h){
|
|
||||||
// pre-callback returned a function...
|
|
||||||
if(h instanceof Function){
|
if(h instanceof Function){
|
||||||
h.call(that, res)
|
//h.call(that, res)
|
||||||
|
h.call(that)
|
||||||
|
|
||||||
// pre-callback returned an object with a .resolve(..) method...
|
// deferred...
|
||||||
} else if(h != null && h.resolve instanceof Function){
|
} else if(h != null && h.resolve instanceof Function){
|
||||||
h.resolve(res)
|
//h.resolve(res)
|
||||||
|
h.resolve()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return res
|
//return res
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
meth.__proto__ = this.__proto__
|
meth.__proto__ = this.__proto__
|
||||||
|
|
||||||
@ -158,6 +192,8 @@ function Action(name, doc, ldoc, func){
|
|||||||
meth.doc = doc
|
meth.doc = doc
|
||||||
meth.long_doc = ldoc
|
meth.long_doc = ldoc
|
||||||
|
|
||||||
|
meth.func = func
|
||||||
|
|
||||||
return meth
|
return meth
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +271,8 @@ module.MetaActions = {
|
|||||||
}
|
}
|
||||||
// register a handler only once...
|
// register a handler only once...
|
||||||
if(this._action_handlers[action].indexOf(handler) < 0){
|
if(this._action_handlers[action].indexOf(handler) < 0){
|
||||||
this._action_handlers[action].push(handler)
|
// NOTE: last registered is first...
|
||||||
|
this._action_handlers[action].splice(0, 0, handler)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
@ -276,6 +313,7 @@ module.MetaActions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Define an action set...
|
// Define an action set...
|
||||||
//
|
//
|
||||||
// Actions(<object>)
|
// Actions(<object>)
|
||||||
@ -331,8 +369,8 @@ module.MetaActions = {
|
|||||||
// when the action is done.
|
// when the action is done.
|
||||||
//
|
//
|
||||||
// NOTE: the action, action pre-callback and post-callbacks will be
|
// NOTE: the action, action pre-callback and post-callbacks will be
|
||||||
// called with the same context as the original callback and the
|
// called with the same context (this) as the original callback
|
||||||
// action, i.e. the action set.
|
// and the action, i.e. the action set.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
var Actions =
|
var Actions =
|
||||||
@ -354,18 +392,8 @@ function Actions(a, b){
|
|||||||
|
|
||||||
var func = args.pop()
|
var func = args.pop()
|
||||||
|
|
||||||
// if an action already exists then register the function as its
|
|
||||||
// callback...
|
|
||||||
if(proto != null
|
|
||||||
&& k in proto
|
|
||||||
&& proto[k] instanceof Action){
|
|
||||||
delete obj[k]
|
|
||||||
proto.on.call(obj, k+'.pre', func)
|
|
||||||
|
|
||||||
// create a new action...
|
// create a new action...
|
||||||
} else {
|
obj[k] = new Action(k, args[0], args[1], func)
|
||||||
obj[k] = new Action(k, args[0], args[0], func)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if(proto != null){
|
if(proto != null){
|
||||||
@ -377,7 +405,6 @@ function Actions(a, b){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
var test =
|
var test =
|
||||||
@ -386,15 +413,17 @@ function test(){
|
|||||||
var TestActions =
|
var TestActions =
|
||||||
module.TestActions =
|
module.TestActions =
|
||||||
Actions({
|
Actions({
|
||||||
|
|
||||||
testActionGen1: ['baisc test action...',
|
testActionGen1: ['baisc test action...',
|
||||||
'some extra info',
|
'some extra info',
|
||||||
function(){
|
function(){
|
||||||
console.log(' test!')
|
console.log(' test 1!')
|
||||||
|
return function(){
|
||||||
|
console.log(' test 2!')
|
||||||
|
}
|
||||||
}],
|
}],
|
||||||
|
|
||||||
testActionGen2: ['baisc 2\'nd gen test action...',
|
testActionGen2: ['baisc 2\'nd gen test action...',
|
||||||
'some extra info',
|
// no extra info...
|
||||||
function(){
|
function(){
|
||||||
console.log(' test gen 2!')
|
console.log(' test gen 2!')
|
||||||
this.testActionGen1()
|
this.testActionGen1()
|
||||||
@ -404,7 +433,6 @@ function test(){
|
|||||||
var TestActions2 =
|
var TestActions2 =
|
||||||
module.TestActions2 =
|
module.TestActions2 =
|
||||||
Actions(TestActions, {
|
Actions(TestActions, {
|
||||||
|
|
||||||
// NOTE: this looks like an action and feels like an action but
|
// NOTE: this looks like an action and feels like an action but
|
||||||
// actually this is a callback as an action with this name
|
// actually this is a callback as an action with this name
|
||||||
// already exists...
|
// already exists...
|
||||||
@ -417,6 +445,29 @@ function test(){
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// XXX the main question here is that there is no way to know if a
|
||||||
|
// particular action is going to be a root action or an action
|
||||||
|
// callback because we do not know if the action in the parent
|
||||||
|
// will be available at mix time or not, and the two models
|
||||||
|
// are different...
|
||||||
|
// XXX one way to do this is to make all code a callback and
|
||||||
|
// just use the root as an event trigger...
|
||||||
|
//
|
||||||
|
// ...but this effectively means we are implementing
|
||||||
|
// inheritance ourselves as the traditional name resolution
|
||||||
|
// will no longer be used, and as in the case we implement
|
||||||
|
// MRO why not go the whole way and implement multiple
|
||||||
|
// inheritance in the first place...
|
||||||
|
//
|
||||||
|
// ...let's try and avoid this...
|
||||||
|
/*
|
||||||
|
var TestActionMixin =
|
||||||
|
module.TestActionMixin =
|
||||||
|
ActionMixin({
|
||||||
|
// XXX
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
console.log('TestActions.testActionGen1()')
|
console.log('TestActions.testActionGen1()')
|
||||||
TestActions.testActionGen1()
|
TestActions.testActionGen1()
|
||||||
@ -439,7 +490,6 @@ function test(){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* vim:set ts=4 sw=4 : */
|
* vim:set ts=4 sw=4 : */
|
||||||
return module })
|
return module })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user