mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 11:20:09 +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