mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20: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...
|
||||
// - compound action is like a normal action with a set of other
|
||||
// actions chanined to it's main event.
|
||||
// - actions should accept arguments, both optional and required
|
||||
var BASE_ACTIONS =
|
||||
module.BASE_ACTIONS = {
|
||||
var BaseActions =
|
||||
module.BaseActions = actions.Actions({
|
||||
// state props...
|
||||
get current(){
|
||||
// XXX should this return a gid or a jQuery-like object for
|
||||
// image-oriented operations???
|
||||
return this.data.current
|
||||
},
|
||||
set current(val){
|
||||
return this.focusImage(val)
|
||||
},
|
||||
|
||||
// life-cycle / state...
|
||||
// XXX
|
||||
|
||||
// actions...
|
||||
focusImage: '',
|
||||
focusRibbon: '',
|
||||
|
||||
// basic editing...
|
||||
shiftImageUp:
|
||||
'Shift image to the ribbon above current, creating one if '
|
||||
@ -100,16 +197,14 @@ module.BASE_ACTIONS = {
|
||||
exportImages: '',
|
||||
|
||||
exit: '',
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var UI_ACTIONS =
|
||||
module.UI_ACTIONS = {
|
||||
focusImage: '',
|
||||
focusRibbon: '',
|
||||
var UIActions =
|
||||
module.UIActions = {
|
||||
|
||||
// basic navigation...
|
||||
nextImage: ['Focus next image in current ribbon', { focusImage: 'next' }],
|
||||
|
||||
@ -59,6 +59,7 @@ define(function(require){ var module = {}
|
||||
//
|
||||
// // event-like callbacks for actions...
|
||||
// O.on('m', function(){...})
|
||||
// O.on('m.pre', function(){...})
|
||||
//
|
||||
//
|
||||
// Comparing to the native system:
|
||||
@ -88,12 +89,21 @@ function _collect_handlers(obj, name){
|
||||
var handlers = []
|
||||
var cur = obj
|
||||
while(cur.__proto__ != null){
|
||||
if(obj._action_handlers == null){
|
||||
break
|
||||
// get action "event" handlers...
|
||||
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__
|
||||
}
|
||||
return handlers
|
||||
@ -105,6 +115,30 @@ function _collect_handlers(obj, name){
|
||||
|
||||
// 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 =
|
||||
module.Action =
|
||||
function Action(name, doc, ldoc, func){
|
||||
@ -126,30 +160,30 @@ function Action(name, doc, ldoc, func){
|
||||
var that = this
|
||||
var args = args2array(arguments)
|
||||
|
||||
// normal handlers -- pre phase...
|
||||
// get and call handlers -- pre phase...
|
||||
var handlers = _collect_handlers(this, name)
|
||||
.map(function(h){ return h.apply(that, args) })
|
||||
|
||||
// call the action...
|
||||
var res = func.apply(this, args)
|
||||
// NOTE: this action will get included and called by the code
|
||||
// above and below...
|
||||
|
||||
// simple post callback...
|
||||
//_collect_handlers(this, name)
|
||||
// .forEach(function(h){ return h.apply(that, args) })
|
||||
|
||||
// normal handlers -- post phase...
|
||||
handlers.forEach(function(h){
|
||||
// pre-callback returned a function...
|
||||
// call handlers -- post phase...
|
||||
// NOTE: post handlers need to get called last run pre first run post...
|
||||
handlers.reverse().forEach(function(h){
|
||||
// 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){
|
||||
h.resolve(res)
|
||||
//h.resolve(res)
|
||||
h.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
return res
|
||||
//return res
|
||||
return this
|
||||
}
|
||||
meth.__proto__ = this.__proto__
|
||||
|
||||
@ -158,6 +192,8 @@ function Action(name, doc, ldoc, func){
|
||||
meth.doc = doc
|
||||
meth.long_doc = ldoc
|
||||
|
||||
meth.func = func
|
||||
|
||||
return meth
|
||||
}
|
||||
|
||||
@ -235,7 +271,8 @@ module.MetaActions = {
|
||||
}
|
||||
// register a handler only once...
|
||||
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
|
||||
},
|
||||
@ -276,6 +313,7 @@ module.MetaActions = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Define an action set...
|
||||
//
|
||||
// Actions(<object>)
|
||||
@ -331,8 +369,8 @@ module.MetaActions = {
|
||||
// when the action is done.
|
||||
//
|
||||
// NOTE: the action, action pre-callback and post-callbacks will be
|
||||
// called with the same context as the original callback and the
|
||||
// action, i.e. the action set.
|
||||
// called with the same context (this) as the original callback
|
||||
// and the action, i.e. the action set.
|
||||
//
|
||||
//
|
||||
var Actions =
|
||||
@ -354,18 +392,8 @@ function Actions(a, b){
|
||||
|
||||
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...
|
||||
} else {
|
||||
obj[k] = new Action(k, args[0], args[0], func)
|
||||
}
|
||||
obj[k] = new Action(k, args[0], args[1], func)
|
||||
})
|
||||
|
||||
if(proto != null){
|
||||
@ -377,7 +405,6 @@ function Actions(a, b){
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
var test =
|
||||
@ -386,15 +413,17 @@ function test(){
|
||||
var TestActions =
|
||||
module.TestActions =
|
||||
Actions({
|
||||
|
||||
testActionGen1: ['baisc test action...',
|
||||
'some extra info',
|
||||
function(){
|
||||
console.log(' test!')
|
||||
console.log(' test 1!')
|
||||
return function(){
|
||||
console.log(' test 2!')
|
||||
}
|
||||
}],
|
||||
|
||||
testActionGen2: ['baisc 2\'nd gen test action...',
|
||||
'some extra info',
|
||||
// no extra info...
|
||||
function(){
|
||||
console.log(' test gen 2!')
|
||||
this.testActionGen1()
|
||||
@ -404,7 +433,6 @@ function test(){
|
||||
var TestActions2 =
|
||||
module.TestActions2 =
|
||||
Actions(TestActions, {
|
||||
|
||||
// NOTE: this looks like an action and feels like an action but
|
||||
// actually this is a callback as an action with this name
|
||||
// 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()')
|
||||
TestActions.testActionGen1()
|
||||
@ -439,7 +490,6 @@ function test(){
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* vim:set ts=4 sw=4 : */
|
||||
return module })
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user