mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	more refactoring -- unbloating features/ui.js
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									af7a8cf51f
								
							
						
					
					
						commit
						9e4e5eced5
					
				| @ -10,26 +10,29 @@ define(function(require){ var module = {} | |||||||
| 
 | 
 | ||||||
| // import features...
 | // import features...
 | ||||||
| var core = require('features/core') | var core = require('features/core') | ||||||
| var base = require('features/base') |  | ||||||
| var location = require('features/location') |  | ||||||
| var history = require('features/history') |  | ||||||
| var app = require('features/app') |  | ||||||
| var ui = require('features/ui') |  | ||||||
| var keyboard = require('features/keyboard') |  | ||||||
| var status = require('features/ui-status') |  | ||||||
| var marks = require('features/ui-marks') |  | ||||||
| var widgets = require('features/ui-widgets') |  | ||||||
| var slideshow = require('features/ui-slideshow') |  | ||||||
| var exteditor = require('features/external-editor') |  | ||||||
| var metadata = require('features/metadata') |  | ||||||
| var meta = require('features/meta') |  | ||||||
| 
 | 
 | ||||||
| var experimental = require('features/experimental') | require('features/base') | ||||||
| var demo = require('features/demo') | require('features/location') | ||||||
|  | require('features/history') | ||||||
|  | require('features/app') | ||||||
|  | require('features/ui') | ||||||
|  | require('features/ui-single-image') | ||||||
|  | require('features/ui-chrome') | ||||||
|  | require('features/keyboard') | ||||||
|  | require('features/ui-status') | ||||||
|  | require('features/ui-marks') | ||||||
|  | require('features/ui-widgets') | ||||||
|  | require('features/ui-slideshow') | ||||||
|  | require('features/external-editor') | ||||||
|  | require('features/metadata') | ||||||
|  | require('features/meta') | ||||||
|  | 
 | ||||||
|  | require('features/experimental') | ||||||
|  | require('features/demo') | ||||||
| 
 | 
 | ||||||
| if(window.nodejs != null){ | if(window.nodejs != null){ | ||||||
| 	var filesystem = require('features/filesystem') | 	require('features/filesystem') | ||||||
| 	var cli = require('features/cli') | 	require('features/cli') | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -928,6 +928,269 @@ core.ImageGridFeatures.Feature('base-full', [ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // Journal...
 | ||||||
|  | 
 | ||||||
|  | function logImageShift(action){ | ||||||
|  | 	return [action.slice(-4) != '.pre' ?  | ||||||
|  | 			action + '.pre'  | ||||||
|  | 			: action, | ||||||
|  | 		function(target){ | ||||||
|  | 			target = this.data.getImage(target) | ||||||
|  | 			var args = args2array(arguments) | ||||||
|  | 
 | ||||||
|  | 			var o = this.data.getImageOrder(target) | ||||||
|  | 			var r = this.data.getRibbon(target) | ||||||
|  | 			var current = this.current | ||||||
|  | 
 | ||||||
|  | 			return function(){ | ||||||
|  | 				var on = this.data.getImageOrder(target) | ||||||
|  | 				var rn = this.data.getRibbon(target) | ||||||
|  | 
 | ||||||
|  | 				if(o == on || r == rn){  | ||||||
|  | 					/* | ||||||
|  | 					this.journalPush( | ||||||
|  | 						this.current,  | ||||||
|  | 						action,  | ||||||
|  | 						args, | ||||||
|  | 						{ | ||||||
|  | 							before: [r, o], | ||||||
|  | 							after: [rn, on], | ||||||
|  | 						}) | ||||||
|  | 					*/ | ||||||
|  | 					this.journalPush({ | ||||||
|  | 						type: 'shift', | ||||||
|  | 						current: current,  | ||||||
|  | 						target: target, | ||||||
|  | 						action: action,  | ||||||
|  | 						args: args, | ||||||
|  | 						undo: journalActions[action], | ||||||
|  | 						diff: { | ||||||
|  | 							before: [r, o], | ||||||
|  | 							after: [rn, on], | ||||||
|  | 						}, | ||||||
|  | 					}) | ||||||
|  | 				} | ||||||
|  | 				 | ||||||
|  | 			} | ||||||
|  | 		}] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Format:
 | ||||||
|  | // 	{
 | ||||||
|  | // 		<action>: <undo-action> | <undo-function> | null,
 | ||||||
|  | // 		...
 | ||||||
|  | // 	}
 | ||||||
|  | var journalActions = { | ||||||
|  | 	clear: null, | ||||||
|  | 	load: null, | ||||||
|  | 
 | ||||||
|  | 	setBaseRibbon: null, | ||||||
|  | 
 | ||||||
|  | 	// XXX need to account for position change, i.e. if action had no 
 | ||||||
|  | 	// 		effect then do nothing...
 | ||||||
|  | 	// 		...take target position before and after...
 | ||||||
|  | 	shiftImageTo: null, | ||||||
|  | 
 | ||||||
|  | 	shiftImageUp: 'shiftImageDown', | ||||||
|  | 	shiftImageDown: 'shiftImageUp', | ||||||
|  | 	shiftImageLeft: 'shiftImageRight', | ||||||
|  | 	shiftImageRight: 'shiftImageLeft', | ||||||
|  | 	shiftRibbonUp: 'shiftRibbonDown', | ||||||
|  | 	shiftRibbonDown: 'shiftRibbonUp', | ||||||
|  | 
 | ||||||
|  | 	rotateCW: 'rotateCCW', | ||||||
|  | 	rotateCCW: 'rotateCW', | ||||||
|  | 	flipHorizontal: 'flipHorizontal', | ||||||
|  | 	flipVertical: 'flipVertical', | ||||||
|  | 
 | ||||||
|  | 	sortImages: null, | ||||||
|  | 	reverseImages: 'reverseImages', | ||||||
|  | 	reverseRibbons: 'reverseRibbons', | ||||||
|  | 
 | ||||||
|  | 	crop: null, | ||||||
|  | 	uncrop: null, | ||||||
|  | 
 | ||||||
|  | 	tag: null,  | ||||||
|  | 	untag: null, | ||||||
|  | 
 | ||||||
|  | 	group: null, | ||||||
|  | 	ungroup: null, | ||||||
|  | 	expandGroup: null, | ||||||
|  | 	collapseGroup: null, | ||||||
|  | 
 | ||||||
|  | 	runJournal: null, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // 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, | ||||||
|  | 
 | ||||||
|  | 		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: ['- Journal/Add an item to journal', | ||||||
|  | 			function(data){ | ||||||
|  | 				this.journal = (this.hasOwnProperty('journal')  | ||||||
|  | 						|| this.journal) ?  | ||||||
|  | 					this.journal  | ||||||
|  | 					: [] | ||||||
|  | 				this.journal.push(data) | ||||||
|  | 			}], | ||||||
|  | 		clearJournal: ['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: ['- Journal/Run journal', | ||||||
|  | 			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...
 | ||||||
|  | 		undoLast: ['Journal/Undo last', | ||||||
|  | 			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] | ||||||
|  | 
 | ||||||
|  | 					// we undo only a very specific set of actions...
 | ||||||
|  | 					if(a.undo && a.type == 'shift' && a.args.length == 0){ | ||||||
|  | 						this | ||||||
|  | 							.focusImage(a.current) | ||||||
|  | 							[a.undo].call(this, a.target) | ||||||
|  | 
 | ||||||
|  | 						// pop the undo command...
 | ||||||
|  | 						this.journal.pop() | ||||||
|  | 						this.rjournal.push(journal.splice(i, 1)[0]) | ||||||
|  | 						break | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		_redoLast: ['Journal/Redo last', | ||||||
|  | 			function(){ | ||||||
|  | 				if(!this.rjournal || this.rjournal.length == 0){ | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				this.runJournal([this.rjournal.pop()]) | ||||||
|  | 			}], | ||||||
|  | 	}), | ||||||
|  | 
 | ||||||
|  | 	// log state, action and its args... 
 | ||||||
|  | 	// 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.
 | ||||||
|  | 	// XXX would be good if we could know the name of the action in the 
 | ||||||
|  | 	// 		handler, thus enabling us to define a single handler rather
 | ||||||
|  | 	// 		than generating a custom handler per action...
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		logImageShift('shiftImageTo'), | ||||||
|  | 		logImageShift('shiftImageUp'), | ||||||
|  | 		logImageShift('shiftImageDown'), | ||||||
|  | 		logImageShift('shiftImageLeft'), | ||||||
|  | 		logImageShift('shiftImageRight'), | ||||||
|  | 		logImageShift('shiftRibbonUp'), | ||||||
|  | 		logImageShift('shiftRibbonDown'), | ||||||
|  | 
 | ||||||
|  | 	].concat([ | ||||||
|  | 			'clear', | ||||||
|  | 			'load', | ||||||
|  | 
 | ||||||
|  | 			'setBaseRibbon', | ||||||
|  | 
 | ||||||
|  | 			'rotateCW', | ||||||
|  | 			'rotateCCW', | ||||||
|  | 			'flipHorizontal', | ||||||
|  | 			'flipVertical', | ||||||
|  | 
 | ||||||
|  | 			'sortImages', | ||||||
|  | 			'reverseImages', | ||||||
|  | 			'reverseRibbons', | ||||||
|  | 
 | ||||||
|  | 			'crop', | ||||||
|  | 			'uncrop', | ||||||
|  | 
 | ||||||
|  | 			'tag',  | ||||||
|  | 			'untag', | ||||||
|  | 
 | ||||||
|  | 			'group', | ||||||
|  | 			'ungroup', | ||||||
|  | 			'expandGroup', | ||||||
|  | 			'collapseGroup', | ||||||
|  | 
 | ||||||
|  | 			//'runJournal',
 | ||||||
|  | 		].map(function(action){ | ||||||
|  | 			return [ | ||||||
|  | 				action+'.pre',  | ||||||
|  | 				function(){ | ||||||
|  | 					this.journalPush({ | ||||||
|  | 						type: 'basic', | ||||||
|  | 						current: this.current,  | ||||||
|  | 						action: action,  | ||||||
|  | 						args: args2array(arguments), | ||||||
|  | 					}) | ||||||
|  | 				}] | ||||||
|  | 		})),  | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /********************************************************************** | /********************************************************************** | ||||||
| * vim:set ts=4 sw=4 :                                                */ | * vim:set ts=4 sw=4 :                                                */ | ||||||
| return module }) | return module }) | ||||||
|  | |||||||
| @ -95,6 +95,9 @@ module.ExternalEditor = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		'base', | 		'base', | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-external-editor', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	isApplicable: function(){  | 	isApplicable: function(){  | ||||||
| 		return this.runtime == 'nw' || this.runtime == 'node' }, | 		return this.runtime == 'nw' || this.runtime == 'node' }, | ||||||
|  | |||||||
| @ -320,6 +320,10 @@ module.FileSystemLoader = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		'location', | 		'location', | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-fs-loader', | ||||||
|  | 		'fs-url-history', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	actions: FileSystemLoaderActions, | 	actions: FileSystemLoaderActions, | ||||||
| 
 | 
 | ||||||
| @ -505,6 +509,9 @@ module.FileSystemLoaderURLHistory = core.ImageGridFeatures.Feature({ | |||||||
| 		'fs-loader', | 		'fs-loader', | ||||||
| 		'url-history', | 		'url-history', | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-fs-url-history', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	handlers: [ | 	handlers: [ | ||||||
| 		pushToHistory('loadImages'),  | 		pushToHistory('loadImages'),  | ||||||
| @ -841,7 +848,12 @@ module.FileSystemWriter = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 	tag: 'fs-writer', | 	tag: 'fs-writer', | ||||||
| 	// NOTE: this is mostly because of the base path handling...
 | 	// NOTE: this is mostly because of the base path handling...
 | ||||||
| 	depends: ['fs-loader'], | 	depends: [ | ||||||
|  | 		'fs-loader' | ||||||
|  | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-fs-writer', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	actions: FileSystemWriterActions, | 	actions: FileSystemWriterActions, | ||||||
| 
 | 
 | ||||||
| @ -998,6 +1010,13 @@ module.FileSystemWriterUI = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | core.ImageGridFeatures.Feature('fs', [ | ||||||
|  | 	'fs-loader', | ||||||
|  | 	'fs-writer', | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /********************************************************************** | /********************************************************************** | ||||||
| * vim:set ts=4 sw=4 :                                                */ | * vim:set ts=4 sw=4 :                                                */ | ||||||
|  | |||||||
| @ -182,6 +182,11 @@ module.URLHistory = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		'location', | 		'location', | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'ui-url-history', | ||||||
|  | 		'url-history-local-storage', | ||||||
|  | 		'url-history-fs-writer', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	actions: URLHistoryActions, | 	actions: URLHistoryActions, | ||||||
| }) | }) | ||||||
|  | |||||||
| @ -38,11 +38,9 @@ core.ImageGridFeatures.Feature('viewer-minimal', [ | |||||||
| 	'image-marks', | 	'image-marks', | ||||||
| 	'image-bookmarks', | 	'image-bookmarks', | ||||||
| 
 | 
 | ||||||
| 	'fs-loader', | 	'fs', | ||||||
| 	'fs-writer', |  | ||||||
| 
 | 
 | ||||||
| 	'metadata', | 	'metadata', | ||||||
| 	'fs-metadata', |  | ||||||
| ]) | ]) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -62,7 +60,7 @@ core.ImageGridFeatures.Feature('viewer-testing', [ | |||||||
| 	//'ui-ribbon-align-to-first',
 | 	//'ui-ribbon-align-to-first',
 | ||||||
| 	//'ui-ribbon-manual-align',
 | 	//'ui-ribbon-manual-align',
 | ||||||
| 	 | 	 | ||||||
| 	'ui-single-image-view', | 	'ui-single-image', | ||||||
| 	'ui-partial-ribbons', | 	'ui-partial-ribbons', | ||||||
| 
 | 
 | ||||||
| 	// XXX
 | 	// XXX
 | ||||||
| @ -70,30 +68,16 @@ core.ImageGridFeatures.Feature('viewer-testing', [ | |||||||
| 	//'ui-direct-control',
 | 	//'ui-direct-control',
 | ||||||
| 	//'ui-indirect-control',
 | 	//'ui-indirect-control',
 | ||||||
| 
 | 
 | ||||||
| 	'image-marks', | 	'marks', | ||||||
| 	'image-bookmarks', |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| 	// local storage + url...
 | 	// local storage + url...
 | ||||||
| 	'config-local-storage', | 	'config-local-storage', | ||||||
| 	'ui-url-hash', | 	'ui-url-hash', | ||||||
| 	'url-history-local-storage', | 	'url-history', | ||||||
| 	'url-history-fs-writer', |  | ||||||
| 	'ui-single-image-view-local-storage', | 	'ui-single-image-view-local-storage', | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// fs...
 |  | ||||||
| 	'ui-fs-loader', |  | ||||||
| 	'fs-url-history', |  | ||||||
| 	'ui-fs-url-history', |  | ||||||
| 	'ui-fs-writer', |  | ||||||
| 
 |  | ||||||
| 	'metadata', |  | ||||||
| 	'fs-metadata', |  | ||||||
| 	'ui-metadata', |  | ||||||
| 
 |  | ||||||
| 	'external-editor', | 	'external-editor', | ||||||
| 	'ui-external-editor', |  | ||||||
| 
 | 
 | ||||||
| 	// chrome...
 | 	// chrome...
 | ||||||
| 	'ui-status-log', | 	'ui-status-log', | ||||||
| @ -118,8 +102,6 @@ core.ImageGridFeatures.Feature('viewer-testing', [ | |||||||
| 
 | 
 | ||||||
| 	// ui control...
 | 	// ui control...
 | ||||||
| 	'ui-clickable', | 	'ui-clickable', | ||||||
| 	//'ui-autohide-cursor',
 |  | ||||||
| 	'ui-autohide-cursor-single-image-view', |  | ||||||
| 	//'ui-direct-control-jquery',
 | 	//'ui-direct-control-jquery',
 | ||||||
| 	// XXX BUG: on touch down and first move this gets offset by a distance
 | 	// XXX BUG: on touch down and first move this gets offset by a distance
 | ||||||
| 	// 		not sure why...
 | 	// 		not sure why...
 | ||||||
|  | |||||||
| @ -75,6 +75,10 @@ module.Metadata = core.ImageGridFeatures.Feature({ | |||||||
| 	depends: [ | 	depends: [ | ||||||
| 		'base', | 		'base', | ||||||
| 	], | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'fs-metadata', | ||||||
|  | 		'ui-metadata', | ||||||
|  | 	], | ||||||
| 
 | 
 | ||||||
| 	actions: MetadataActions, | 	actions: MetadataActions, | ||||||
| }) | }) | ||||||
|  | |||||||
							
								
								
									
										619
									
								
								ui (gen4)/features/ui-chrome.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										619
									
								
								ui (gen4)/features/ui-chrome.js
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,619 @@ | |||||||
|  | /********************************************************************** | ||||||
|  | *  | ||||||
|  | * | ||||||
|  | * | ||||||
|  | **********************************************************************/ | ||||||
|  | 
 | ||||||
|  | define(function(require){ var module = {} | ||||||
|  | 
 | ||||||
|  | //var DEBUG = DEBUG != null ? DEBUG : true
 | ||||||
|  | 
 | ||||||
|  | var actions = require('lib/actions') | ||||||
|  | var features = require('lib/features') | ||||||
|  | var toggler = require('lib/toggler') | ||||||
|  | 
 | ||||||
|  | var core = require('features/core') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | // helper...
 | ||||||
|  | function didAdvance(indicator){ | ||||||
|  | 	return function(){ | ||||||
|  | 		var img = this.data.current | ||||||
|  | 		return function(){ | ||||||
|  | 			if(img == this.data.current){ | ||||||
|  | 				this.flashIndicator(indicator) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var BoundsIndicatorsActions = actions.Actions({ | ||||||
|  | 	flashIndicator: ['- Interface/Flash an indicator', | ||||||
|  | 		function(direction){ | ||||||
|  | 			if(this.ribbons.getRibbonSet().length == 0){ | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			var cls = { | ||||||
|  | 				// shift up/down...
 | ||||||
|  | 				up: '.up-indicator', | ||||||
|  | 				down: '.down-indicator', | ||||||
|  | 				// hit start/end/top/bottom of view...
 | ||||||
|  | 				start: '.start-indicator', | ||||||
|  | 				end: '.end-indicator', | ||||||
|  | 				top: '.top-indicator', | ||||||
|  | 				bottom: '.bottom-indicator', | ||||||
|  | 			}[direction] | ||||||
|  | 
 | ||||||
|  | 			var indicator = this.ribbons.viewer.find(cls) | ||||||
|  | 
 | ||||||
|  | 			if(indicator.length == 0){ | ||||||
|  | 				indicator = $('<div>') | ||||||
|  | 					.addClass(cls.replace('.', '') +' '+ this.tag) | ||||||
|  | 					.appendTo(this.ribbons.viewer) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return indicator | ||||||
|  | 				// NOTE: this needs to be visible in all cases and key press 
 | ||||||
|  | 				// 		rhythms... 
 | ||||||
|  | 				.show() | ||||||
|  | 				.delay(100) | ||||||
|  | 				.fadeOut(300) | ||||||
|  | 		}], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var BoundsIndicators =  | ||||||
|  | module.BoundsIndicators = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-bounds-indicators', | ||||||
|  | 	depends: ['ui'], | ||||||
|  | 
 | ||||||
|  | 	actions: BoundsIndicatorsActions, | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// basic navigation...
 | ||||||
|  | 		['nextImage.pre lastImage.pre', didAdvance('end')], | ||||||
|  | 		['prevImage.pre firstImage.pre', didAdvance('start')], | ||||||
|  | 		['nextRibbon.pre lastRibbon.pre', didAdvance('bottom')], | ||||||
|  | 		['prevRibbon.pre firstRibbon.pre', didAdvance('top')], | ||||||
|  | 
 | ||||||
|  | 		// vertical shifting...
 | ||||||
|  | 		['shiftImageUp.pre', | ||||||
|  | 			function(target){  | ||||||
|  | 				target = target || this.current | ||||||
|  | 				var r = this.data.getRibbonOrder(target) | ||||||
|  | 
 | ||||||
|  | 				var l = this.data.getImages(r).length | ||||||
|  | 				var l0 = this.data.getImages(0).length | ||||||
|  | 
 | ||||||
|  | 				return function(){ | ||||||
|  | 					// when shifting last image of top ribbon (i.e. length == 1)
 | ||||||
|  | 					// up the state essentially will not change...
 | ||||||
|  | 					if((r == 0 && l == 1)  | ||||||
|  | 							// we are shifting to a new empty ribbon...
 | ||||||
|  | 							|| (r == 1 && l == 1 && l0 == 0)){ | ||||||
|  | 						this.flashIndicator('top') | ||||||
|  | 					} else {	 | ||||||
|  | 						this.flashIndicator('up') | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		['shiftImageDown.pre', | ||||||
|  | 			function(target){  | ||||||
|  | 				target = target || this.current | ||||||
|  | 				var r0 = this.data.getRibbonOrder(target) | ||||||
|  | 				var l = this.data.getImages(r0).length | ||||||
|  | 
 | ||||||
|  | 				return function(){ | ||||||
|  | 					var r1 = this.data.getRibbonOrder(target) | ||||||
|  | 					if(r0 == r1 && r0 == this.data.ribbon_order.length-1 && l == 1){ | ||||||
|  | 						this.flashIndicator('bottom') | ||||||
|  | 					} else { | ||||||
|  | 						this.flashIndicator('down')  | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 
 | ||||||
|  | 		// horizontal shifting...
 | ||||||
|  | 		['shiftImageLeft.pre', | ||||||
|  | 			function(target){  | ||||||
|  | 				if(target == null  | ||||||
|  | 						//&& actions.data.getImageOrder('ribbon') == 0){
 | ||||||
|  | 						&& this.data.getImage('prev') == null){ | ||||||
|  | 					this.flashIndicator('start') | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		['shiftImageRight.pre', | ||||||
|  | 			function(target){  | ||||||
|  | 				if(target == null  | ||||||
|  | 						&& this.data.getImage('next') == null){ | ||||||
|  | 					this.flashIndicator('end') | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | var CurrentImageIndicatorActions = actions.Actions({ | ||||||
|  | 	config: { | ||||||
|  | 		'current-image-border': 3, | ||||||
|  | 		'current-image-min-border': 2, | ||||||
|  | 
 | ||||||
|  | 		'current-image-border-timeout': 200, | ||||||
|  | 		'current-image-shift-timeout': 200, | ||||||
|  | 
 | ||||||
|  | 		'current-image-indicator-fadein': 500, | ||||||
|  | 
 | ||||||
|  | 		'current-image-indicator-hide-timeout': 250, | ||||||
|  | 
 | ||||||
|  | 		// this can be:
 | ||||||
|  | 		// 	'hide'			- simply hide on next/prev screen action
 | ||||||
|  | 		// 					  and show on focus image.
 | ||||||
|  | 		// 	'hide-show'		- hide on fast scroll through screens and 
 | ||||||
|  | 		// 					  show when slowing down.
 | ||||||
|  | 		'current-image-indicator-screen-nav-mode': 'hide', | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	updateCurrentImageIndicator: ['- Interface/Update current image indicator', | ||||||
|  | 		function(target, update_border){ | ||||||
|  | 			var ribbon_set = this.ribbons.getRibbonSet() | ||||||
|  | 
 | ||||||
|  | 			if(ribbon_set.length == 0){ | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			var scale = this.ribbons.scale() | ||||||
|  | 			var cur = this.ribbons.getImage(target) | ||||||
|  | 			// NOTE: cur may be unloaded...
 | ||||||
|  | 			var ribbon = this.ribbons.getRibbon(cur.length > 0 ? target : this.currentRibbon) | ||||||
|  | 
 | ||||||
|  | 			var marker = ribbon.find('.current-marker') | ||||||
|  | 
 | ||||||
|  | 			// remove marker if current image is not loaded...
 | ||||||
|  | 			if(cur.length == 0){ | ||||||
|  | 				marker.remove() | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// get config...
 | ||||||
|  | 			var border = this.config['current-image-border'] | ||||||
|  | 			var min_border = this.config['current-image-min-border'] | ||||||
|  | 			var border_timeout = this.config['current-image-border-timeout'] | ||||||
|  | 			var fadein = this.config['current-image-indicator-fadein'] | ||||||
|  | 
 | ||||||
|  | 			// no marker found -- either in different ribbon or not created yet...
 | ||||||
|  | 			if(marker.length == 0){ | ||||||
|  | 				// get marker globally...
 | ||||||
|  | 				marker = this.ribbons.viewer.find('.current-marker') | ||||||
|  | 
 | ||||||
|  | 				// no marker exists -- create a marker...
 | ||||||
|  | 				if(marker.length == 0){ | ||||||
|  | 					var marker = $('<div/>') | ||||||
|  | 						.addClass('current-marker ui-current-image-indicator') | ||||||
|  | 						.css({ | ||||||
|  | 							opacity: '0', | ||||||
|  | 							// NOTE: these are not used for positioning
 | ||||||
|  | 							// 		but are needed for correct absolute
 | ||||||
|  | 							// 		placement...
 | ||||||
|  | 							top: '0px', | ||||||
|  | 							left: '0px', | ||||||
|  | 						}) | ||||||
|  | 						.appendTo(ribbon) | ||||||
|  | 						.animate({ | ||||||
|  | 							'opacity': 1 | ||||||
|  | 						}, fadein) | ||||||
|  | 					this.ribbons.dom.setOffset(marker, 0, 0) | ||||||
|  | 
 | ||||||
|  | 				// add marker to current ribbon...
 | ||||||
|  | 				} else { | ||||||
|  | 					marker.appendTo(ribbon) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// NOTE: we will update only the attrs that need to be updated...
 | ||||||
|  | 			var css = {} | ||||||
|  | 
 | ||||||
|  | 			var w = cur.outerWidth(true) | ||||||
|  | 			var h = cur.outerHeight(true) | ||||||
|  | 
 | ||||||
|  | 			// keep size same as the image...
 | ||||||
|  | 			if(marker.outerWidth() != w || marker.outerHeight() != h){ | ||||||
|  | 				css.width = w | ||||||
|  | 				css.height = h | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// update border...
 | ||||||
|  | 			if(update_border !== false){ | ||||||
|  | 				var border = Math.max(min_border, border / scale) | ||||||
|  | 
 | ||||||
|  | 				// set border right away...
 | ||||||
|  | 				if(update_border == 'before'){ | ||||||
|  | 					css.borderWidth = border | ||||||
|  | 
 | ||||||
|  | 				// set border with a delay...
 | ||||||
|  | 				// NOTE: this is to prevent the ugly border resize before
 | ||||||
|  | 				// 		the scale on scale down animation starts...
 | ||||||
|  | 				} else { | ||||||
|  | 					setTimeout(function(){  | ||||||
|  | 						marker.css({ borderWidth: border })  | ||||||
|  | 					}, border_timeout) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			//css.left = cur[0].offsetLeft
 | ||||||
|  | 			this.ribbons.dom.setOffset(marker, cur[0].offsetLeft, 0) | ||||||
|  | 
 | ||||||
|  | 			marker.css(css) | ||||||
|  | 		}], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var CurrentImageIndicator =  | ||||||
|  | module.CurrentImageIndicator = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-current-image-indicator', | ||||||
|  | 	depends: ['ui'], | ||||||
|  | 
 | ||||||
|  | 	actions: CurrentImageIndicatorActions, | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// move marker to current image...
 | ||||||
|  | 		['focusImage.post', | ||||||
|  | 			function(){ this.updateCurrentImageIndicator() }], | ||||||
|  | 		// prevent animations when focusing ribbons...
 | ||||||
|  | 		['focusRibbon.pre', | ||||||
|  | 			function(){ | ||||||
|  | 				var m = this.ribbons.viewer.find('.current-marker') | ||||||
|  | 				this.ribbons.preventTransitions(m) | ||||||
|  | 				return function(){ | ||||||
|  | 					this.ribbons.restoreTransitions(m) | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		// this is here to compensate for position change on ribbon 
 | ||||||
|  | 		// resize...
 | ||||||
|  | 		// NOTE: hide/show of indicator on resize appears to have solved
 | ||||||
|  | 		// 		the jumpy animation issue.
 | ||||||
|  | 		// 		this might cause some blinking on slow resizes (visible 
 | ||||||
|  | 		// 		only on next/prev screen)... 
 | ||||||
|  | 		// 		...still not sure why .preventTransitions(m) did not
 | ||||||
|  | 		// 		do the job.
 | ||||||
|  | 		['resizeRibbon.pre', | ||||||
|  | 			function(target, s){ | ||||||
|  | 				var m = this.ribbons.viewer.find('.current-marker') | ||||||
|  | 				// only update if marker exists and we are in current ribbon...
 | ||||||
|  | 				if(m.length != 0 && this.currentRibbon == this.data.getRibbon(target)){ | ||||||
|  | 					//this.ribbons.preventTransitions(m)
 | ||||||
|  | 					m.hide() | ||||||
|  | 
 | ||||||
|  | 					return function(){ | ||||||
|  | 						this.updateCurrentImageIndicator(target, false) | ||||||
|  | 						//this.ribbons.restoreTransitions(m, true)
 | ||||||
|  | 						m | ||||||
|  | 							.show() | ||||||
|  | 							// NOTE: keeping display in inline style will
 | ||||||
|  | 							// 		prevent the element from being hidden
 | ||||||
|  | 							// 		by css...
 | ||||||
|  | 							.css({display: ''}) | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		// Change border size in the appropriate spot in the animation:
 | ||||||
|  | 		// 	- before animation when scaling up
 | ||||||
|  | 		// 	- after when scaling down
 | ||||||
|  | 		// This is done to make the visuals consistent...
 | ||||||
|  | 		['fitImage.pre fitRibbon.pre', | ||||||
|  | 			function(w1){  | ||||||
|  | 				var w0 = this.screenwidth | ||||||
|  | 				w1 = w1 || 1 | ||||||
|  | 				return function(){ | ||||||
|  | 					this.updateCurrentImageIndicator(null, w0 > w1 ? 'before' : 'after')  | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		['shiftImageLeft.pre shiftImageRight.pre', | ||||||
|  | 			function(){ | ||||||
|  | 				this.ribbons.viewer.find('.current-marker').hide() | ||||||
|  | 				if(this._current_image_indicator_timeout != null){ | ||||||
|  | 					clearTimeout(this._current_image_indicator_timeout) | ||||||
|  | 					delete this._current_image_indicator_timeout | ||||||
|  | 				} | ||||||
|  | 				return function(){ | ||||||
|  | 					var ribbons = this.ribbons | ||||||
|  | 					var fadein = this.config['current-image-indicator-fadein'] | ||||||
|  | 					this._current_image_indicator_timeout = setTimeout(function(){  | ||||||
|  | 						ribbons.viewer.find('.current-marker').fadeIn(fadein) | ||||||
|  | 					}, this.config['current-image-shift-timeout']) | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var CurrentImageIndicatorHideOnFastScreenNav =  | ||||||
|  | module.CurrentImageIndicatorHideOnFastScreenNav = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-current-image-indicator-hide-on-fast-screen-nav', | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui', | ||||||
|  | 		'ui-current-image-indicator' | ||||||
|  | 	], | ||||||
|  | 	exclusive: ['ui-current-image-indicator-hide'], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// hide indicator on screen next/prev...
 | ||||||
|  | 		//
 | ||||||
|  | 		// XXX experimental -- not sure if we need this...
 | ||||||
|  | 		// XXX need to think about the trigger mechanics here and make 
 | ||||||
|  | 		// 		them more natural...
 | ||||||
|  | 		['prevScreen.pre nextScreen.pre', | ||||||
|  | 			function(){  | ||||||
|  | 				var m = this.ribbons.viewer.find('.current-marker') | ||||||
|  | 				var t = this.config['current-image-indicator-hide-timeout'] | ||||||
|  | 
 | ||||||
|  | 				var cur = this.current | ||||||
|  | 
 | ||||||
|  | 				return function(){ | ||||||
|  | 					var that = this | ||||||
|  | 
 | ||||||
|  | 					// delay fadeout...
 | ||||||
|  | 					if(cur != this.current  | ||||||
|  | 							&& m.css('opacity') == 1 | ||||||
|  | 							&& this.__current_indicator_t0 == null){ | ||||||
|  | 						this.__current_indicator_t0 = setTimeout(function(){ | ||||||
|  | 							delete that.__current_indicator_t0 | ||||||
|  | 
 | ||||||
|  | 							m.css({ opacity: 0 }) | ||||||
|  | 						}, t) | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// cancel/delay previous fadein...
 | ||||||
|  | 					if(this.__current_indicator_t1 != null){ | ||||||
|  | 						clearTimeout(this.__current_indicator_t1) | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					// cancel fadeout and do fadein...
 | ||||||
|  | 					this.__current_indicator_t1 = setTimeout(function(){ | ||||||
|  | 						delete that.__current_indicator_t1 | ||||||
|  | 
 | ||||||
|  | 						// cancel fadeout...
 | ||||||
|  | 						if(that.__current_indicator_t0 != null){ | ||||||
|  | 							clearTimeout(that.__current_indicator_t0) | ||||||
|  | 							delete that.__current_indicator_t0 | ||||||
|  | 						}  | ||||||
|  | 
 | ||||||
|  | 						// show...
 | ||||||
|  | 						m.animate({ opacity: '1' }) | ||||||
|  | 					}, t-50) | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var CurrentImageIndicatorHideOnScreenNav =  | ||||||
|  | module.CurrentImageIndicatorHideOnScreenNav = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-current-image-indicator-hide-on-screen-nav', | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui', | ||||||
|  | 		'ui-current-image-indicator' | ||||||
|  | 	], | ||||||
|  | 	exclusive: ['ui-current-image-indicator-hide'], | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// 	this does the following:
 | ||||||
|  | 		// 		- hide on screen jump
 | ||||||
|  | 		// 		- show on any other action
 | ||||||
|  | 		//
 | ||||||
|  | 		// NOTE: we use .pre events here to see if we have moved...
 | ||||||
|  | 		['prevScreen.post nextScreen.post', | ||||||
|  | 			function(){  | ||||||
|  | 				var m = this.ribbons.viewer.find('.current-marker') | ||||||
|  | 
 | ||||||
|  | 				m.css({ opacity: 0 }) | ||||||
|  | 			}], | ||||||
|  | 		['focusImage.post', | ||||||
|  | 			function(){  | ||||||
|  | 				var m = this.ribbons.viewer.find('.current-marker') | ||||||
|  | 
 | ||||||
|  | 				m.css({ opacity: '' }) | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // XXX this should:
 | ||||||
|  | // 	- float to the left of a ribbon if image #1 is fully visible (working)
 | ||||||
|  | // 	- float at left of viewer if image #1 is off screen...
 | ||||||
|  | // 	- float on the same level as the base ribbon...
 | ||||||
|  | 
 | ||||||
|  | // XXX make this an action...
 | ||||||
|  | var updateBaseRibbonIndicator = function(img){ | ||||||
|  | 	var scale = this.ribbons.scale() | ||||||
|  | 	var base = this.ribbons.getRibbon('base') | ||||||
|  | 	img = this.ribbons.getImage(img) | ||||||
|  | 	var m = base.find('.base-ribbon-marker') | ||||||
|  | 
 | ||||||
|  | 	if(base.length == 0){ | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(m.length == 0){ | ||||||
|  | 		m = this.ribbons.viewer.find('.base-ribbon-marker') | ||||||
|  | 
 | ||||||
|  | 		// make the indicator...
 | ||||||
|  | 		if(m.length == 0){ | ||||||
|  | 			m = $('<div>') | ||||||
|  | 				.addClass('base-ribbon-marker') | ||||||
|  | 				.text('base ribbon') | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		m.prependTo(base) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// XXX this is wrong -- need to calculate the offset after the move and not now...
 | ||||||
|  | 	if(base.offset().left < 0){ | ||||||
|  | 		m.css('left', (img.position().left + img.width()/2 - this.ribbons.viewer.width()/2) / scale) | ||||||
|  | 
 | ||||||
|  | 	} else { | ||||||
|  | 		m.css('left', '') | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var BaseRibbonIndicator =  | ||||||
|  | module.BaseRibbonIndicator = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-base-ribbon-indicator', | ||||||
|  | 	depends: ['ui'], | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// move marker to current image...
 | ||||||
|  | 		['focusImage.pre', | ||||||
|  | 			function(target){  | ||||||
|  | 				updateBaseRibbonIndicator.call(this, target) | ||||||
|  | 			}], | ||||||
|  | 		// prevent animations when focusing ribbons...
 | ||||||
|  | 		['focusRibbon.pre setBaseRibbon', | ||||||
|  | 			function(){ | ||||||
|  | 				updateBaseRibbonIndicator.call(this) | ||||||
|  | 
 | ||||||
|  | 				/* | ||||||
|  | 				this.ribbons.preventTransitions(m) | ||||||
|  | 				return function(){ | ||||||
|  | 					this.ribbons.restoreTransitions(m) | ||||||
|  | 				} | ||||||
|  | 				*/ | ||||||
|  | 			}], | ||||||
|  | 	] | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var PassiveBaseRibbonIndicator =  | ||||||
|  | module.PassiveBaseRibbonIndicator = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-passive-base-ribbon-indicator', | ||||||
|  | 	depends: ['ui'], | ||||||
|  | 
 | ||||||
|  | 	config: { | ||||||
|  | 		'ui-show-passive-base-ribbon-indicator': true, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	actions: actions.Actions({ | ||||||
|  | 		togglePassiveBaseRibbonIndicator: ['Interface/Toggle passive base ribbon indicator', | ||||||
|  | 			toggler.CSSClassToggler( | ||||||
|  | 				function(){ return this.ribbons.viewer },  | ||||||
|  | 				'show-passive-base-ribbon-indicator', | ||||||
|  | 				function(state){  | ||||||
|  | 					this.config['ui-show-passive-base-ribbon-indicator'] = state == 'on' }) ], | ||||||
|  | 	}), | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		['start', | ||||||
|  | 			function(){ | ||||||
|  | 				this.togglePassiveBaseRibbonIndicator( | ||||||
|  | 					this.config['ui-show-passive-base-ribbon-indicator'] ? | ||||||
|  | 						'on' : 'off') | ||||||
|  | 			}] | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | // XXX make this work in browser
 | ||||||
|  | var UIScaleActions = actions.Actions({ | ||||||
|  | 	config: { | ||||||
|  | 		// XXX
 | ||||||
|  | 		'ui-scale-modes': { | ||||||
|  | 			desktop: 0, | ||||||
|  | 			touch: 3, | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	// XXX need to account for scale in PartialRibbons
 | ||||||
|  | 	// XXX should this be browser API???
 | ||||||
|  | 	// XXX this does not re-scale the ribbons correctly in nw0.13
 | ||||||
|  | 	toggleInterfaceScale: ['Interface/Toggle interface modes', | ||||||
|  | 		core.makeConfigToggler('ui-scale-mode',  | ||||||
|  | 			function(){ return Object.keys(this.config['ui-scale-modes']) }, | ||||||
|  | 			function(state){  | ||||||
|  | 				var gui = requirejs('nw.gui') | ||||||
|  | 				var win = gui.Window.get() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 				this.ribbons.preventTransitions() | ||||||
|  | 
 | ||||||
|  | 				var w = this.screenwidth | ||||||
|  | 
 | ||||||
|  | 				// NOTE: scale = Math.pow(1.2, zoomLevel)
 | ||||||
|  | 				// XXX in nw0.13 this appears to be async...
 | ||||||
|  | 				win.zoomLevel = this.config['ui-scale-modes'][state] || 0 | ||||||
|  | 
 | ||||||
|  | 				this.screenwidth = w | ||||||
|  | 				this.centerViewer() | ||||||
|  | 
 | ||||||
|  | 				this.ribbons.restoreTransitions() | ||||||
|  | 			})], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // XXX enable scale loading...
 | ||||||
|  | // 		...need to make this play nice with restoring scale on startup...
 | ||||||
|  | var UIScale =  | ||||||
|  | module.UIScale = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-scale', | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: UIScaleActions, | ||||||
|  | 
 | ||||||
|  | 	// XXX test if in:
 | ||||||
|  | 	// 	- chrome app
 | ||||||
|  | 	// 	- nw
 | ||||||
|  | 	// 	- mobile
 | ||||||
|  | 	isApplicable: function(){ return this.runtime == 'nw' }, | ||||||
|  | 
 | ||||||
|  | 	// XXX show main window...
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		['start', | ||||||
|  | 			function(){  | ||||||
|  | 				// XXX this messes up ribbon scale...
 | ||||||
|  | 				// 		...too close/fast?
 | ||||||
|  | 				//this.toggleInterfaceScale('!')
 | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /********************************************************************** | ||||||
|  | * vim:set ts=4 sw=4 :                                                */ | ||||||
|  | return module }) | ||||||
| @ -292,6 +292,15 @@ module.ImageBookmarks = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | core.ImageGridFeatures.Feature('marks', [ | ||||||
|  | 	'image-marks', | ||||||
|  | 	'image-bookmarks', | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /********************************************************************** | /********************************************************************** | ||||||
| * vim:set ts=4 sw=4 :                                                */ | * vim:set ts=4 sw=4 :                                                */ | ||||||
| return module }) | return module }) | ||||||
|  | |||||||
							
								
								
									
										299
									
								
								ui (gen4)/features/ui-single-image.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										299
									
								
								ui (gen4)/features/ui-single-image.js
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,299 @@ | |||||||
|  | /********************************************************************** | ||||||
|  | *  | ||||||
|  | * | ||||||
|  | * | ||||||
|  | **********************************************************************/ | ||||||
|  | 
 | ||||||
|  | define(function(require){ var module = {} | ||||||
|  | 
 | ||||||
|  | //var DEBUG = DEBUG != null ? DEBUG : true
 | ||||||
|  | 
 | ||||||
|  | var actions = require('lib/actions') | ||||||
|  | var features = require('lib/features') | ||||||
|  | var toggler = require('lib/toggler') | ||||||
|  | 
 | ||||||
|  | var core = require('features/core') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | // helper...
 | ||||||
|  | // XXX should this be an action???
 | ||||||
|  | function updateImageProportions(){ | ||||||
|  | 	// XXX
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | var SingleImageActions = actions.Actions({ | ||||||
|  | 	config: { | ||||||
|  | 		// NOTE: these will get overwritten if/when the user changes the scale...
 | ||||||
|  | 		'single-image-scale': null, | ||||||
|  | 		'ribbon-scale': null, | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	toggleSingleImage: ['Interface/Toggle single image view',  | ||||||
|  | 		toggler.CSSClassToggler( | ||||||
|  | 			function(){ return this.ribbons.viewer },  | ||||||
|  | 			'single-image-mode') ], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // XXX an ideal case would be:
 | ||||||
|  | //
 | ||||||
|  | // A)
 | ||||||
|  | //       viewer
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //      |     image     |   - small image
 | ||||||
|  | //      |     +---+     |   - square image block
 | ||||||
|  | //      |     |   |     |   - smaller than this the block is always square
 | ||||||
|  | //      |     +---+     |   - we just change scale
 | ||||||
|  | //      |               |
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // B)
 | ||||||
|  | //       viewer
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //      | +-----------+ |   - bigger image
 | ||||||
|  | //      | | image     | |   - block close to viewer proportion
 | ||||||
|  | //      | |    <-->   | |   - image block growing parallel to viewer
 | ||||||
|  | //      | |           | |     longer side
 | ||||||
|  | //      | +-----------+ |   - this stage is not affected specific by image
 | ||||||
|  | //      +---------------+     proportions and can be done in bulk
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // C)
 | ||||||
|  | //       viewer
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //      | image         |   - image block same size as viewer
 | ||||||
|  | //      |               |   - need to account for chrome
 | ||||||
|  | //      |               |
 | ||||||
|  | //      |               |
 | ||||||
|  | //      |               |
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // D)
 | ||||||
|  | //       image
 | ||||||
|  | //      + - - - - - - - +
 | ||||||
|  | //      .               .
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //      | viewer        |   - image bigger than viewer in one dimension
 | ||||||
|  | //      |       ^       |   - block grows to fit image proportions
 | ||||||
|  | //      |       |       |   - need to account for individual image 
 | ||||||
|  | //      |       v       |     proportions
 | ||||||
|  | //      |               |   - drag enabled
 | ||||||
|  | //      +---------------+
 | ||||||
|  | //      .               .
 | ||||||
|  | //      + - - - - - - - +
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // E) 
 | ||||||
|  | //     image
 | ||||||
|  | //    + - - - - - - - - - +
 | ||||||
|  | //    .                   .
 | ||||||
|  | //    . +---------------+ .
 | ||||||
|  | //    . | viewer        | . - image bigger than viewer 
 | ||||||
|  | //    . |               | . - image block same proportion as image
 | ||||||
|  | //    . |               | . - we just change scale
 | ||||||
|  | //    . |               | . - drag enabled
 | ||||||
|  | //    . |               | .
 | ||||||
|  | //    . +---------------+ .
 | ||||||
|  | //    .                   .
 | ||||||
|  | //    + - - - - - - - - - +
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | var SingleImageView = | ||||||
|  | module.SingleImageView = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-single-image-view', | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui' | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: SingleImageActions, | ||||||
|  | 
 | ||||||
|  | 	handlers:[ | ||||||
|  | 		['fitImage.post', | ||||||
|  | 			function(){  | ||||||
|  | 
 | ||||||
|  | 				// singe image mode -- set image proportions...
 | ||||||
|  | 				if(this.toggleSingleImage('?') == 'on'){ | ||||||
|  | 					updateImageProportions.call(this) | ||||||
|  | 
 | ||||||
|  | 					this.config['single-image-scale'] = this.screenwidth | ||||||
|  | 
 | ||||||
|  | 				} else { | ||||||
|  | 					this.config['ribbon-scale'] = this.screenwidth | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		// NOTE: this is not part of the actual action above because we 
 | ||||||
|  | 		// 		need to see if the state has changed and doing this with 
 | ||||||
|  | 		// 		two separate pre/post callbacks (toggler callbacks) is 
 | ||||||
|  | 		// 		harder than with two nested callbacks (action callbacks)
 | ||||||
|  | 		// XXX this uses .screenwidth for scale, is this the right way to go?
 | ||||||
|  | 		['toggleSingleImage.pre',  | ||||||
|  | 			function(){  | ||||||
|  | 				var pre_state = this.toggleSingleImage('?') | ||||||
|  | 
 | ||||||
|  | 				return function(){ | ||||||
|  | 					var state = this.toggleSingleImage('?') | ||||||
|  | 
 | ||||||
|  | 					// singe image mode -- set image proportions...
 | ||||||
|  | 					if(state == 'on'){ | ||||||
|  | 						updateImageProportions.call(this) | ||||||
|  | 
 | ||||||
|  | 						// update scale...
 | ||||||
|  | 						if(state != pre_state){ | ||||||
|  | 							var w = this.screenwidth | ||||||
|  | 							this.config['ribbon-scale'] = w | ||||||
|  | 							this.screenwidth = this.config['single-image-scale'] || w | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 					// ribbon mode -- restore original image size...
 | ||||||
|  | 					} else { | ||||||
|  | 						this.ribbons.viewer.find('.image:not(.clone)').css({ | ||||||
|  | 							width: '', | ||||||
|  | 							height: '' | ||||||
|  | 						}) | ||||||
|  | 
 | ||||||
|  | 						// update scale...
 | ||||||
|  | 						if(state != pre_state){ | ||||||
|  | 							var w = this.screenwidth | ||||||
|  | 							this.config['single-image-scale'] = w | ||||||
|  | 							this.screenwidth = this.config['ribbon-scale'] || w | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var SingleImageViewLocalStorage = | ||||||
|  | module.SingleImageViewLocalStorage = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-single-image-view-local-storage', | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui-single-image-view', | ||||||
|  | 		'config-local-storage', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	handlers:[ | ||||||
|  | 		// set scale...
 | ||||||
|  | 		['load', | ||||||
|  | 			function(){ | ||||||
|  | 				// prevent this from doing anything while no viewer...
 | ||||||
|  | 				if(!this.ribbons || !this.ribbons.viewer || this.ribbons.viewer.length == 0){ | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if(this.toggleSingleImage('?') == 'on'){ | ||||||
|  | 					this.screenwidth = this.config['single-image-scale'] || this.screenwidth | ||||||
|  | 
 | ||||||
|  | 				} else { | ||||||
|  | 					this.screenwidth = this.config['ribbon-scale'] || this.screenwidth | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | // This will store/restore autohide state for single-image and ribbon 
 | ||||||
|  | // views...
 | ||||||
|  | //
 | ||||||
|  | // NOTE: chrome 49 + devtools open appears to prevent the cursor from being hidden...
 | ||||||
|  | //
 | ||||||
|  | // XXX hiding cursor on navigation for some reason does not work...
 | ||||||
|  | var SingleImageAutoHideCursor =  | ||||||
|  | module.SingleImageAutoHideCursor = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 	doc: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'ui-single-image-view-autohide-cursor', | ||||||
|  | 	depends: [ | ||||||
|  | 		'ui-autohide-cursor', | ||||||
|  | 		'ui-single-image-view', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	config: { | ||||||
|  | 		'cursor-autohide-single-image-view': 'on', | ||||||
|  | 		'cursor-autohide-ribbon-view': 'off', | ||||||
|  | 
 | ||||||
|  | 		//'cursor-autohide-on-navigate': true, 
 | ||||||
|  | 	}, | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// setup...
 | ||||||
|  | 		['load', | ||||||
|  | 			function(){ | ||||||
|  | 				var mode = this.toggleSingleImage('?') == 'on' ?  | ||||||
|  | 					'cursor-autohide-single-image-view' | ||||||
|  | 					: 'cursor-autohide-ribbon-view' | ||||||
|  | 
 | ||||||
|  | 				this.toggleAutoHideCursor(this.config[mode] || 'off') | ||||||
|  | 			}], | ||||||
|  | 		// store state for each mode...
 | ||||||
|  | 		['toggleAutoHideCursor', | ||||||
|  | 			function(){ | ||||||
|  | 				var mode = this.toggleSingleImage('?') == 'on' ?  | ||||||
|  | 					'cursor-autohide-single-image-view' | ||||||
|  | 					: 'cursor-autohide-ribbon-view' | ||||||
|  | 
 | ||||||
|  | 				this.config[mode] = this.toggleAutoHideCursor('?') | ||||||
|  | 			}], | ||||||
|  | 		// restore state per mode...
 | ||||||
|  | 		['toggleSingleImage',  | ||||||
|  | 			function(){ | ||||||
|  | 				if(this.toggleSingleImage('?') == 'on'){ | ||||||
|  | 					this.toggleAutoHideCursor(this.config['cursor-autohide-single-image-view']) | ||||||
|  | 
 | ||||||
|  | 				} else { | ||||||
|  | 					this.toggleAutoHideCursor(this.config['cursor-autohide-ribbon-view']) | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		/* XXX for some reason this does not work... | ||||||
|  | 		// autohide on navigation...
 | ||||||
|  | 		['focusImage',  | ||||||
|  | 			function(){ | ||||||
|  | 				//if(this.config['cursor-autohide-on-navigate'] 
 | ||||||
|  | 				//		&& this.toggleAutoHideCursor('?') == 'on'){
 | ||||||
|  | 				//	this.toggleAutoHideCursor('on')
 | ||||||
|  | 				//}
 | ||||||
|  | 				if(this.config['cursor-autohide-on-navigate']  | ||||||
|  | 						&& this.toggleAutoHideCursor('?') == 'on' | ||||||
|  | 						&& this.ribbons.viewer.prop('cursor-autohide')){ | ||||||
|  | 					this.ribbons.viewer | ||||||
|  | 						.addClass('cursor-hidden') | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		*/ | ||||||
|  | 	] | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | core.ImageGridFeatures.Feature('ui-single-image', [ | ||||||
|  | 	'ui-single-image-view', | ||||||
|  | 	'ui-single-image-view-local-storage', | ||||||
|  | 
 | ||||||
|  | 	'ui-single-image-view-autohide-cursor', | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /********************************************************************** | ||||||
|  | * vim:set ts=4 sw=4 :                                                */ | ||||||
|  | return module }) | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user