mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	most of the refactoring of .browseActions(..) is done, still have some things to work out...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									d4d49d95d0
								
							
						
					
					
						commit
						41cf0fd5d2
					
				| @ -1381,121 +1381,52 @@ var BrowseActionsActions = actions.Actions({ | |||||||
| 	//
 | 	//
 | ||||||
| 	// NOTE: we need to do this as .alias(..) is defined in actions and
 | 	// NOTE: we need to do this as .alias(..) is defined in actions and
 | ||||||
| 	// 		has no concept of the naming protocols used in ImageGrid.Viewer
 | 	// 		has no concept of the naming protocols used in ImageGrid.Viewer
 | ||||||
|  | 	// NOTE: this essentially defines and empty alias and puts it in
 | ||||||
|  | 	// 		'System/' hidden...
 | ||||||
| 	alias: ['- System/', ''], | 	alias: ['- System/', ''], | ||||||
| 
 | 
 | ||||||
|  | 	// XXX this should sort the tree leaves???
 | ||||||
|  | 	// 		...if sorting then exclude priorities...
 | ||||||
|  | 	// XXX add option not to run checks...
 | ||||||
|  | 	listActions: ['- System/', | ||||||
|  | 		core.doc`List actions in action tree...
 | ||||||
| 
 | 
 | ||||||
| 	// Browse actions dialog...
 | 			Build tree and return it... | ||||||
| 	//
 | 			.listActions('raw'[, tree]) | ||||||
| 	// This uses action definition to build and present an action tree.
 | 				-> tree | ||||||
| 	//
 | 
 | ||||||
| 	// This supports the following element (action doc) syntax:
 | 			Get sup-tree/action at path... | ||||||
| 	// 	- '/' separated action path (action short doc) to indicate the
 | 			.listActions(path[, tree]) | ||||||
| 	// 	  path to action.
 | 				-> sub-tree | ||||||
| 	//
 | 				-> action | ||||||
| 	// 	- leading path element number followed by colon to indicate 
 | 
 | ||||||
| 	// 	  element priority on level.
 | 
 | ||||||
| 	// 		Example:
 | 		This is used by .browseActions(..) to list the actions to be  | ||||||
| 	// 			'Path/99: To/50:Element'
 | 		drawn in the action menu. | ||||||
| 	// 	  NOTE: multiple path elements may have multiple priorities.
 | 		 | ||||||
| 	// 	  NOTE: an item with positive priority will be above and item 
 | 
 | ||||||
| 	// 	  		with less or no priority.
 | 		Action tree format: | ||||||
| 	// 	  NOTE: an item with negative priority will be below any item 
 | 			{ | ||||||
| 	// 	  		with greater or no priority.
 | 				// sub-tree...
 | ||||||
| 	//
 | 				<name>: <tree>, | ||||||
| 	// 	- leading '-' in path to indicate a hidden/disabled element.
 | 		 | ||||||
| 	// 		Example: 
 | 				// action...
 | ||||||
| 	// 			'- Path/To/Element'			(disabled/hidden)
 | 				<name>: [ | ||||||
| 	// 			'- 99:Path/To/Element'		(disabled/hidden)
 | 					<action-name>, | ||||||
| 	// 			'Path/To/Other element'		(enabled)
 | 					// mode...
 | ||||||
| 	//
 | 					'disabled' | 'hidden', | ||||||
| 	//
 | 				], | ||||||
| 	//
 | 		 | ||||||
| 	// Action mode (disabled/hidden) and also be controlled dynamically:
 | 				... | ||||||
| 	// 	- .browseMode() action method is called with actions as base.
 | 			} | ||||||
| 	//		Example:
 | 		`,
 | ||||||
| 	//			someAction: ['Path/To/Some action',
 | 		function(path, tree){ | ||||||
| 	//				{browseMode: function(){ ... }},
 |  | ||||||
| 	//				function(){
 |  | ||||||
| 	//					...
 |  | ||||||
| 	//				}],
 |  | ||||||
| 	//			someOtherAction: ['Path/To/Some action',
 |  | ||||||
| 	//				// alias
 |  | ||||||
| 	//				{browseMode: 'someAction'},
 |  | ||||||
| 	//				function(){
 |  | ||||||
| 	//					...
 |  | ||||||
| 	//				}],
 |  | ||||||
| 	//
 |  | ||||||
| 	//		.browseMode can be:
 |  | ||||||
| 	//			<function>			- action method.
 |  | ||||||
| 	//			<action-name>		- alias, name of action to get the
 |  | ||||||
| 	//									method from.
 |  | ||||||
| 	//
 |  | ||||||
| 	//		.browseMode() can return:
 |  | ||||||
| 	//			'disabled'		- item will be disabled.
 |  | ||||||
| 	//			'hidden'		- item will be both hidden and disabled.
 |  | ||||||
| 	//
 |  | ||||||
| 	//		NOTE: disabling in path has priority over .browseMode(), thus
 |  | ||||||
| 	//			it is possible to hide/disable an enabled item but not
 |  | ||||||
| 	//			possible to enable a disabled by default path.
 |  | ||||||
| 	//		NOTE: .browseMode() can be defined in any action in chain,
 |  | ||||||
| 	//			though only the last one is called...
 |  | ||||||
| 	//
 |  | ||||||
| 	//
 |  | ||||||
| 	// options format:
 |  | ||||||
| 	// 	{
 |  | ||||||
| 	// 		callback: <function>,
 |  | ||||||
| 	// 		no_disabled: false,
 |  | ||||||
| 	// 		no_hidden: false,
 |  | ||||||
| 	// 	}
 |  | ||||||
| 	//
 |  | ||||||
| 	//
 |  | ||||||
| 	// NOTE: if the action returns an instance of overlay.Overlay this
 |  | ||||||
| 	// 		will not close right away but rather bind to:
 |  | ||||||
| 	// 			overlay.close			-> self.focus()
 |  | ||||||
| 	// 			overlay.client.open		-> self.close()
 |  | ||||||
| 	// NOTE: we are not using the browse.PathList(..) here as we need 
 |  | ||||||
| 	// 		custom controls and special path handling...
 |  | ||||||
| 	// NOTE: this will keep the first instance title it encounters, this
 |  | ||||||
| 	// 		if a later instance includes a priority, it will be ignored.
 |  | ||||||
| 	// 		This may happen if several actions are in the same path and
 |  | ||||||
| 	// 		each one set a different priority in that path...
 |  | ||||||
| 	// 		...to avoid this use .config['action-category-order'] to set
 |  | ||||||
| 	// 		base order/priorities...
 |  | ||||||
| 	//
 |  | ||||||
| 	// XXX can we do a deep search on '/' -- find any nested action???
 |  | ||||||
| 	// XXX can this also do a flat mode???
 |  | ||||||
| 	// 		...this would help with the (global) search -- switch to 
 |  | ||||||
| 	// 		flat if searching in root mode...
 |  | ||||||
| 	browseActions: ['Interface|System/Dialog/Actions...', |  | ||||||
| 		makeUIDialog(function(path, options){ |  | ||||||
| 			var actions = this | 			var actions = this | ||||||
| 			options = options || {} |  | ||||||
| 
 | 
 | ||||||
| 			var PRIORITY = /^(-?[0-9]+)\s*:\s*/ | 			var PRIORITY = /^(-?[0-9]+)\s*:\s*/ | ||||||
| 			var MARKER = RegExp(this.config['browse-actions-shortcut-marker'], 'g') | 			var MARKER = RegExp(this.config['browse-actions-shortcut-marker'], 'g') | ||||||
| 			MARKER = MARKER || RegExp(MARKER, 'g') | 			MARKER = MARKER || RegExp(MARKER, 'g') | ||||||
| 
 | 
 | ||||||
| 			// prepare the config...
 |  | ||||||
| 			var cfg = { |  | ||||||
| 				cls: 'browse-actions', |  | ||||||
| 
 |  | ||||||
| 				path: path, |  | ||||||
| 
 |  | ||||||
| 				flat: false, |  | ||||||
| 				traversable: true, |  | ||||||
| 				pathPrefix: '/', |  | ||||||
| 				fullPathEdit: true, |  | ||||||
| 
 |  | ||||||
| 				item_shortcut_marker: MARKER, |  | ||||||
| 			} |  | ||||||
| 			cfg.__proto__ = this.config['browse-actions-settings'] |  | ||||||
| 
 |  | ||||||
| 			// get keys for each action...
 |  | ||||||
| 			var keys = this.getKeysForAction ? this.getKeysForAction() : {} |  | ||||||
| 			// Get keys for action...
 |  | ||||||
| 			var getKeys = function(action){ |  | ||||||
| 				return (keys[action] || []).join(' / ') } |  | ||||||
| 
 |  | ||||||
| 			// Get item from tree level taking into account additional 
 | 			// Get item from tree level taking into account additional 
 | ||||||
| 			// syntax like prioority...
 | 			// syntax like prioority...
 | ||||||
| 			// returns:
 | 			// returns:
 | ||||||
| @ -1536,6 +1467,210 @@ var BrowseActionsActions = actions.Actions({ | |||||||
| 				return [] | 				return [] | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | 			// Tree builder...
 | ||||||
|  | 			// XXX normalize actions -- whitespace, '!', args...
 | ||||||
|  | 			// XXX should this do level sorting???
 | ||||||
|  | 			var buildTree = function(path, leaf, action, mode, tree){ | ||||||
|  | 				path = path.slice() | ||||||
|  | 				// build leaf...
 | ||||||
|  | 				if(path.length == 0){ | ||||||
|  | 					// handle "|" in leavs...
 | ||||||
|  | 					leaf.split(/\|/g) | ||||||
|  | 						.forEach(function(leaf){ | ||||||
|  | 							var l = getItem(tree, leaf)[0] | ||||||
|  | 							tree[l || leaf] = action != null ? [action, mode] : action | ||||||
|  | 						}) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				// build alternative paths...
 | ||||||
|  | 				var p = path.shift() || '' | ||||||
|  | 				p.split(/\|/g) | ||||||
|  | 					.forEach(function(e){ | ||||||
|  | 						// build branch element...
 | ||||||
|  | 						var branch = getItem(tree, e) | ||||||
|  | 						branch = tree[branch[0] || e] = branch[1] || {} | ||||||
|  | 
 | ||||||
|  | 						// build sub-branch...
 | ||||||
|  | 						buildTree(path, leaf, action, mode, branch) | ||||||
|  | 					}) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// if no tree is given, build one...
 | ||||||
|  | 			if(tree == null){ | ||||||
|  | 				tree = {} | ||||||
|  | 
 | ||||||
|  | 				// pre-order the main categories...
 | ||||||
|  | 				// NOTE: pre_order can be a list of long paths...
 | ||||||
|  | 				var s = '' | ||||||
|  | 				var pre_order = (this.config['action-category-order'] || []) | ||||||
|  | 					.map(function(p, i){ | ||||||
|  | 						// make all separators unique...
 | ||||||
|  | 						// ...this will prevent us from losing or merging them.
 | ||||||
|  | 						if(p.trimRight().endsWith('---')){ | ||||||
|  | 							s += '-' | ||||||
|  | 							p = p.trimRight() + s | ||||||
|  | 						} | ||||||
|  | 						return p | ||||||
|  | 					}) | ||||||
|  | 				pre_order.forEach(function(key){ | ||||||
|  | 					var path = key.split(/[\\\/]/g) | ||||||
|  | 					var leaf = path.pop() | ||||||
|  | 
 | ||||||
|  | 					buildTree(path, leaf, null, null, tree) | ||||||
|  | 				}) | ||||||
|  | 
 | ||||||
|  | 				// build the tree...
 | ||||||
|  | 				var paths = this.getPath() | ||||||
|  | 				Object.keys(paths).forEach(function(key){ | ||||||
|  | 					// handle mode flag...
 | ||||||
|  | 					var action = paths[key][0] | ||||||
|  | 					var mode = key.split(/^-\s*/) | ||||||
|  | 					var path = mode.pop() | ||||||
|  | 					mode = mode.length > 0 ? 'hidden' : null | ||||||
|  | 
 | ||||||
|  | 					path = path.split(/[\\\/]/g) | ||||||
|  | 					var leaf = path.pop() | ||||||
|  | 
 | ||||||
|  | 					buildTree(path, leaf, action, mode, tree) | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// return the raw tree...
 | ||||||
|  | 			if(path == 'raw'){ | ||||||
|  | 				return tree | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// prepare path...
 | ||||||
|  | 			path = path || '/' | ||||||
|  | 			path = (path instanceof Array ? path : path.split(/[\\\/]/g)) | ||||||
|  | 				.filter(function(e){ return e.trim() != '' }) | ||||||
|  | 
 | ||||||
|  | 			// get the tree node...
 | ||||||
|  | 			var cur = tree | ||||||
|  | 			var rest = path.slice() | ||||||
|  | 			while(rest.length > 0 && !('*' in cur)){ | ||||||
|  | 				cur = getItem(cur, rest.shift()).pop() || {} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return cur | ||||||
|  | 		}], | ||||||
|  | 
 | ||||||
|  | 	// XXX can we do a deep search on '/' -- find any nested action???
 | ||||||
|  | 	// 		...or rather a search from this level and down...
 | ||||||
|  | 	// XXX can this also do a flat mode???
 | ||||||
|  | 	// 		...this would help with the (global) search -- switch to 
 | ||||||
|  | 	// 		flat if searching in root mode...
 | ||||||
|  | 	// XXX should this be live (options.live) or not??? (currently not)
 | ||||||
|  | 	browseActions: ['Interface|System/Dialog/Actions...', | ||||||
|  | 		core.doc`Browse actions dialog...
 | ||||||
|  | 
 | ||||||
|  | 		This uses action definition to build and present an action tree. | ||||||
|  | 
 | ||||||
|  | 		This supports the following element (action doc) syntax: | ||||||
|  | 			- '/' separated action path (action short doc) to indicate the | ||||||
|  | 			  path to action. | ||||||
|  | 
 | ||||||
|  | 			- leading path element number followed by colon to indicate  | ||||||
|  | 			  element priority on level. | ||||||
|  | 				Example: | ||||||
|  | 					'Path/99: To/50:Element' | ||||||
|  | 			  NOTE: multiple path elements may have multiple priorities. | ||||||
|  | 			  NOTE: an item with positive priority will be above and item  | ||||||
|  | 					with less or no priority. | ||||||
|  | 			  NOTE: an item with negative priority will be below any item  | ||||||
|  | 					with greater or no priority. | ||||||
|  | 
 | ||||||
|  | 			- leading '-' in path to indicate a hidden/disabled element. | ||||||
|  | 				Example:  | ||||||
|  | 					'- Path/To/Element'			(disabled/hidden) | ||||||
|  | 					'- 99:Path/To/Element'		(disabled/hidden) | ||||||
|  | 					'Path/To/Other element'		(enabled) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		Action mode (disabled/hidden) and also be controlled dynamically: | ||||||
|  | 			- .browseMode() action method is called with actions as base. | ||||||
|  | 			Example: | ||||||
|  | 				someAction: ['Path/To/Some action', | ||||||
|  | 					{browseMode: function(){ ... }}, | ||||||
|  | 					function(){ | ||||||
|  | 						... | ||||||
|  | 					}], | ||||||
|  | 				someOtherAction: ['Path/To/Some action', | ||||||
|  | 					// alias
 | ||||||
|  | 					{browseMode: 'someAction'}, | ||||||
|  | 					function(){ | ||||||
|  | 						... | ||||||
|  | 					}], | ||||||
|  | 
 | ||||||
|  | 			.browseMode can be: | ||||||
|  | 				<function>			- action method. | ||||||
|  | 				<action-name>		- alias, name of action to get the | ||||||
|  | 										method from. | ||||||
|  | 
 | ||||||
|  | 			.browseMode() can return: | ||||||
|  | 				'disabled'		- item will be disabled. | ||||||
|  | 				'hidden'		- item will be both hidden and disabled. | ||||||
|  | 
 | ||||||
|  | 			NOTE: disabling in path has priority over .browseMode(), thus | ||||||
|  | 				it is possible to hide/disable an enabled item but not | ||||||
|  | 				possible to enable a disabled by default path. | ||||||
|  | 			NOTE: .browseMode() can be defined in any action in chain, | ||||||
|  | 				though only the last one is called... | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		options format: | ||||||
|  | 			{ | ||||||
|  | 				callback: <function>, | ||||||
|  | 				no_disabled: false, | ||||||
|  | 				no_hidden: false, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		NOTE: if the action returns an instance of overlay.Overlay this | ||||||
|  | 				will not close right away but rather bind to: | ||||||
|  | 					overlay.close			-> self.focus() | ||||||
|  | 					overlay.client.open		-> self.close() | ||||||
|  | 		NOTE: we are not using the browse.PathList(..) here as we need  | ||||||
|  | 				custom controls and special path handling... | ||||||
|  | 		NOTE: this will keep the first instance title it encounters, this | ||||||
|  | 				if a later instance includes a priority, it will be ignored. | ||||||
|  | 				This may happen if several actions are in the same path and | ||||||
|  | 				each one set a different priority in that path... | ||||||
|  | 				...to avoid this use .config['action-category-order'] to set | ||||||
|  | 				base order/priorities... | ||||||
|  | 		`,
 | ||||||
|  | 		makeUIDialog(function(path, options){ | ||||||
|  | 			var actions = this | ||||||
|  | 			options = options || {} | ||||||
|  | 
 | ||||||
|  | 			var PRIORITY = /^(-?[0-9]+)\s*:\s*/ | ||||||
|  | 			var MARKER = RegExp(this.config['browse-actions-shortcut-marker'], 'g') | ||||||
|  | 			MARKER = MARKER || RegExp(MARKER, 'g') | ||||||
|  | 
 | ||||||
|  | 			// prepare the config...
 | ||||||
|  | 			var cfg = { | ||||||
|  | 				cls: 'browse-actions', | ||||||
|  | 
 | ||||||
|  | 				path: path, | ||||||
|  | 
 | ||||||
|  | 				flat: false, | ||||||
|  | 				traversable: true, | ||||||
|  | 				pathPrefix: '/', | ||||||
|  | 				fullPathEdit: true, | ||||||
|  | 
 | ||||||
|  | 				item_shortcut_marker: MARKER, | ||||||
|  | 
 | ||||||
|  | 				live: true, | ||||||
|  | 			} | ||||||
|  | 			cfg.__proto__ = this.config['browse-actions-settings'] | ||||||
|  | 
 | ||||||
|  | 			// get keys for each action...
 | ||||||
|  | 			var keys = this.getKeysForAction ? this.getKeysForAction() : {} | ||||||
|  | 			// Get keys for action...
 | ||||||
|  | 			var getKeys = function(action){ | ||||||
|  | 				return (keys[action] || []).join(' / ') } | ||||||
|  | 
 | ||||||
| 			// Get action browse mode (disabled or hidden)...
 | 			// Get action browse mode (disabled or hidden)...
 | ||||||
| 			var getMode = function(action){ | 			var getMode = function(action){ | ||||||
| 				var m = action | 				var m = action | ||||||
| @ -1572,102 +1707,15 @@ var BrowseActionsActions = actions.Actions({ | |||||||
| 				return child | 				return child | ||||||
| 			}.bind(this) | 			}.bind(this) | ||||||
| 
 | 
 | ||||||
| 			// Tree builder...
 | 			// pre-cache the action tree... 
 | ||||||
| 			// XXX normalize actions -- whitespace, '!', args...
 | 			var tree = cfg.live ?  | ||||||
| 			var buildTree = function(path, leaf, action, mode, tree){ | 				null  | ||||||
| 				path = path.slice() | 				: actions.listActions('raw') | ||||||
| 				// build leaf...
 |  | ||||||
| 				if(path.length == 0){ |  | ||||||
| 					// handle "|" in leavs...
 |  | ||||||
| 					leaf.split(/\|/g) |  | ||||||
| 						.forEach(function(leaf){ |  | ||||||
| 							var l = getItem(tree, leaf)[0] |  | ||||||
| 							tree[l || leaf] = action != null ? [action, mode] : action |  | ||||||
| 						}) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 				// build alternative paths...
 |  | ||||||
| 				var p = path.shift() || '' |  | ||||||
| 				p.split(/\|/g) |  | ||||||
| 					.forEach(function(e){ |  | ||||||
| 						// build branch element...
 |  | ||||||
| 						var branch = getItem(tree, e) |  | ||||||
| 						branch = tree[branch[0] || e] = branch[1] || {} |  | ||||||
| 
 |  | ||||||
| 						// build sub-branch...
 |  | ||||||
| 						buildTree(path, leaf, action, mode, branch) |  | ||||||
| 					}) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// Action tree...
 |  | ||||||
| 			//
 |  | ||||||
| 			// Format:
 |  | ||||||
| 			// 	{
 |  | ||||||
| 			// 		<name>: <tree>,
 |  | ||||||
| 			//
 |  | ||||||
| 			// 		<name>: [
 |  | ||||||
| 			// 			<action-name>,
 |  | ||||||
| 			// 			// mode...
 |  | ||||||
| 			// 			'disabled' | 'hidden',
 |  | ||||||
| 			// 		],
 |  | ||||||
| 			//
 |  | ||||||
| 			// 		...
 |  | ||||||
| 			// 	}
 |  | ||||||
| 			//
 |  | ||||||
| 			// NOTE: this is created once per call, so to refresh the 
 |  | ||||||
| 			// 		actions tree we'll need to re-open the dialog...
 |  | ||||||
| 			var tree = {} |  | ||||||
| 
 |  | ||||||
| 			// pre-order the main categories...
 |  | ||||||
| 			// NOTE: pre_order can be a list of long paths...
 |  | ||||||
| 			var s = '' |  | ||||||
| 			var pre_order = (this.config['action-category-order'] || []) |  | ||||||
| 				.map(function(p, i){ |  | ||||||
| 					// make all separators unique...
 |  | ||||||
| 					// ...this will prevent us from losing or merging them.
 |  | ||||||
| 					if(p.trimRight().endsWith('---')){ |  | ||||||
| 						s += '-' |  | ||||||
| 						p = p.trimRight() + s |  | ||||||
| 					} |  | ||||||
| 					return p |  | ||||||
| 				}) |  | ||||||
| 			pre_order.forEach(function(key){ |  | ||||||
| 				var path = key.split(/[\\\/]/g) |  | ||||||
| 				var leaf = path.pop() |  | ||||||
| 
 |  | ||||||
| 				buildTree(path, leaf, null, null, tree) |  | ||||||
| 			}) |  | ||||||
| 
 |  | ||||||
| 			// build the tree...
 |  | ||||||
| 			var paths = this.getPath() |  | ||||||
| 			Object.keys(paths).forEach(function(key){ |  | ||||||
| 				// handle mode flag...
 |  | ||||||
| 				var action = paths[key][0] |  | ||||||
| 				var mode = key.split(/^-\s*/) |  | ||||||
| 				var path = mode.pop() |  | ||||||
| 				mode = mode.length > 0 ? 'hidden' : null |  | ||||||
| 
 |  | ||||||
| 				path = path.split(/[\\\/]/g) |  | ||||||
| 				var leaf = path.pop() |  | ||||||
| 
 |  | ||||||
| 				buildTree(path, leaf, action, mode, tree) |  | ||||||
| 			}) |  | ||||||
| 
 |  | ||||||
| 			//console.log('!!!!', tree)
 |  | ||||||
| 
 | 
 | ||||||
| 			// now for the dialog...
 | 			// now for the dialog...
 | ||||||
| 			return browse.makeLister(null, function(path, make){ | 			return browse.makeLister(null, function(path, make){ | ||||||
| 				var that = this | 				var that = this | ||||||
| 				var cur = tree | 				var cur = actions.listActions(path.slice(), tree) | ||||||
| 
 |  | ||||||
| 				// get level...
 |  | ||||||
| 				// NOTE: we need to get the level till first '*'...
 |  | ||||||
| 				// NOTE: this needs to account for leading priority of 
 |  | ||||||
| 				// 		an element...
 |  | ||||||
| 				var rest = path.slice() |  | ||||||
| 				while(rest.length > 0 && !('*' in cur)){ |  | ||||||
| 					cur = getItem(cur, rest.shift()).pop() || {} |  | ||||||
| 				} |  | ||||||
| 
 | 
 | ||||||
| 				// render current level...
 | 				// render current level...
 | ||||||
| 				// NOTE: we can be at one of several level types, each 
 | 				// NOTE: we can be at one of several level types, each 
 | ||||||
| @ -1880,163 +1928,6 @@ var BrowseActionsActions = actions.Actions({ | |||||||
| 				this.menu(showDoc.bind(this)) | 				this.menu(showDoc.bind(this)) | ||||||
| 			}) })], | 			}) })], | ||||||
| 
 | 
 | ||||||
| 	// XXX might be a good idea to split out the lister out of .browseActions(..)
 |  | ||||||
| 	// 		...this would simplify debugging of actions...
 |  | ||||||
| 	listActions: ['- System/', |  | ||||||
| 		function(path, options){ |  | ||||||
| 			var actions = this |  | ||||||
| 			options = options || {} |  | ||||||
| 
 |  | ||||||
| 			var PRIORITY = /^(-?[0-9]+)\s*:\s*/ |  | ||||||
| 			var MARKER = RegExp(this.config['browse-actions-shortcut-marker'], 'g') |  | ||||||
| 			MARKER = MARKER || RegExp(MARKER, 'g') |  | ||||||
| 
 |  | ||||||
| 			// prepare the config...
 |  | ||||||
| 			var cfg = { |  | ||||||
| 				cls: 'browse-actions', |  | ||||||
| 
 |  | ||||||
| 				path: path, |  | ||||||
| 
 |  | ||||||
| 				flat: false, |  | ||||||
| 				traversable: true, |  | ||||||
| 				pathPrefix: '/', |  | ||||||
| 				fullPathEdit: true, |  | ||||||
| 
 |  | ||||||
| 				item_shortcut_marker: MARKER, |  | ||||||
| 			} |  | ||||||
| 			cfg.__proto__ = this.config['browse-actions-settings'] |  | ||||||
| 
 |  | ||||||
| 			// Get item from tree level taking into account additional 
 |  | ||||||
| 			// syntax like prioority...
 |  | ||||||
| 			// returns:
 |  | ||||||
| 			// 	[<existing-text>, <new-level>]
 |  | ||||||
| 			//
 |  | ||||||
| 			// XXX this may mess up the ordering of items when using 
 |  | ||||||
| 			// 		item patterns...
 |  | ||||||
| 			var getItem = function(level, text){ |  | ||||||
| 				// direct match...
 |  | ||||||
| 				if(text in level){ |  | ||||||
| 					return [text, level[text]] |  | ||||||
| 
 |  | ||||||
| 				// check if it's a priority path or a pattern... 
 |  | ||||||
| 				} else { |  | ||||||
| 					var t = text.replace(PRIORITY, '') |  | ||||||
| 					t = (MARKER ? t.replace(MARKER, '$1') : t).trim() |  | ||||||
| 
 |  | ||||||
| 					for(var e in level){ |  | ||||||
| 						var n = e.replace(PRIORITY, '') |  | ||||||
| 						n = (MARKER ? n.replace(MARKER, '$1') : n).trim() |  | ||||||
| 
 |  | ||||||
| 						if(n == t){ |  | ||||||
| 							return [e, level[e]] |  | ||||||
| 						} |  | ||||||
| 
 |  | ||||||
| 						// check pattern...
 |  | ||||||
| 						var p = /\.\*/.test(n) ? new RegExp('^'+ n +'$', 'i') : null |  | ||||||
| 
 |  | ||||||
| 						if(p && p.test(t)){ |  | ||||||
| 							// override item priority from pattern...
 |  | ||||||
| 							var pr = PRIORITY.exec(e) |  | ||||||
| 							pr = pr ? pr.pop() + ':' : '' |  | ||||||
| 
 |  | ||||||
| 							return [pr + text.replace(PRIORITY, ''), level[e]] |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 				return [] |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// Tree builder...
 |  | ||||||
| 			// XXX normalize actions -- whitespace, '!', args...
 |  | ||||||
| 			var buildTree = function(path, leaf, action, mode, tree){ |  | ||||||
| 				path = path.slice() |  | ||||||
| 				// build leaf...
 |  | ||||||
| 				if(path.length == 0){ |  | ||||||
| 					// handle "|" in leavs...
 |  | ||||||
| 					leaf.split(/\|/g) |  | ||||||
| 						.forEach(function(leaf){ |  | ||||||
| 							var l = getItem(tree, leaf)[0] |  | ||||||
| 							tree[l || leaf] = action != null ? [action, mode] : action |  | ||||||
| 						}) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 				// build alternative paths...
 |  | ||||||
| 				var p = path.shift() || '' |  | ||||||
| 				p.split(/\|/g) |  | ||||||
| 					.forEach(function(e){ |  | ||||||
| 						// build branch element...
 |  | ||||||
| 						var branch = getItem(tree, e) |  | ||||||
| 						branch = tree[branch[0] || e] = branch[1] || {} |  | ||||||
| 
 |  | ||||||
| 						// build sub-branch...
 |  | ||||||
| 						buildTree(path, leaf, action, mode, branch) |  | ||||||
| 					}) |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// Action tree...
 |  | ||||||
| 			//
 |  | ||||||
| 			// Format:
 |  | ||||||
| 			// 	{
 |  | ||||||
| 			// 		<name>: <tree>,
 |  | ||||||
| 			//
 |  | ||||||
| 			// 		<name>: [
 |  | ||||||
| 			// 			<action-name>,
 |  | ||||||
| 			// 			// mode...
 |  | ||||||
| 			// 			'disabled' | 'hidden',
 |  | ||||||
| 			// 		],
 |  | ||||||
| 			//
 |  | ||||||
| 			// 		...
 |  | ||||||
| 			// 	}
 |  | ||||||
| 			//
 |  | ||||||
| 			// NOTE: this is created once per call, so to refresh the 
 |  | ||||||
| 			// 		actions tree we'll need to re-open the dialog...
 |  | ||||||
| 			var tree = {} |  | ||||||
| 
 |  | ||||||
| 			// pre-order the main categories...
 |  | ||||||
| 			// NOTE: pre_order can be a list of long paths...
 |  | ||||||
| 			var s = '' |  | ||||||
| 			var pre_order = (this.config['action-category-order'] || []) |  | ||||||
| 				.map(function(p, i){ |  | ||||||
| 					// make all separators unique...
 |  | ||||||
| 					// ...this will prevent us from losing or merging them.
 |  | ||||||
| 					if(p.trimRight().endsWith('---')){ |  | ||||||
| 						s += '-' |  | ||||||
| 						p = p.trimRight() + s |  | ||||||
| 					} |  | ||||||
| 					return p |  | ||||||
| 				}) |  | ||||||
| 			pre_order.forEach(function(key){ |  | ||||||
| 				var path = key.split(/[\\\/]/g) |  | ||||||
| 				var leaf = path.pop() |  | ||||||
| 
 |  | ||||||
| 				buildTree(path, leaf, null, null, tree) |  | ||||||
| 			}) |  | ||||||
| 
 |  | ||||||
| 			// build the tree...
 |  | ||||||
| 			var paths = this.getPath() |  | ||||||
| 			Object.keys(paths).forEach(function(key){ |  | ||||||
| 				// handle mode flag...
 |  | ||||||
| 				var action = paths[key][0] |  | ||||||
| 				var mode = key.split(/^-\s*/) |  | ||||||
| 				var path = mode.pop() |  | ||||||
| 				mode = mode.length > 0 ? 'hidden' : null |  | ||||||
| 
 |  | ||||||
| 				path = path.split(/[\\\/]/g) |  | ||||||
| 				var leaf = path.pop() |  | ||||||
| 
 |  | ||||||
| 				buildTree(path, leaf, action, mode, tree) |  | ||||||
| 			}) |  | ||||||
| 
 |  | ||||||
| 			if(path == 'raw'){ |  | ||||||
| 				return tree |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// XXX get sub-path...
 |  | ||||||
| 			// XXX
 |  | ||||||
| 
 |  | ||||||
| 			return tree |  | ||||||
| 		}], |  | ||||||
| 
 |  | ||||||
| 	toggleBrowseActionKeys: ['Interface/Show keys in menu', | 	toggleBrowseActionKeys: ['Interface/Show keys in menu', | ||||||
| 		core.makeConfigToggler( | 		core.makeConfigToggler( | ||||||
| 			'browse-actions-keys',  | 			'browse-actions-keys',  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user