mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 19:30:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			420 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			420 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
| /**********************************************************************
 | |
| * 
 | |
| *
 | |
| *
 | |
| **********************************************************************/
 | |
| 
 | |
| 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 keyboard = require('lib/keyboard')
 | |
| 
 | |
| var core = require('features/core')
 | |
| 
 | |
| var widget = require('lib/widget/widget')
 | |
| var browse = require('lib/widget/browse')
 | |
| var overlay = require('lib/widget/overlay')
 | |
| var drawer = require('lib/widget/drawer')
 | |
| 
 | |
| 
 | |
| 
 | |
| /*********************************************************************/
 | |
| 
 | |
| // XXX add this to the global doc...
 | |
| var GLOBAL_KEYBOARD =
 | |
| module.GLOBAL_KEYBOARD = {
 | |
| 	'Global':{
 | |
| 		doc: 'Global bindings that take priority over other sections.',
 | |
| 		pattern: '*',
 | |
| 
 | |
| 		// XXX
 | |
| 	},
 | |
| 
 | |
| 	'Slideshow': {
 | |
| 		pattern: '.slideshow-running',
 | |
| 		ignore: [
 | |
| 			'Esc',
 | |
| 			'Up', 'Down', 'Enter',
 | |
| 			'R', 'L', 'G',
 | |
| 		],
 | |
| 
 | |
| 		Esc: 'toggleSlideshow: "off" -- Exit slideshow',
 | |
| 		Enter: 'slideshowDialog',
 | |
| 
 | |
| 		Left: 'resetSlideshowTimer',
 | |
| 		Right: 'resetSlideshowTimer',
 | |
| 		Home: 'resetSlideshowTimer',
 | |
| 		End: 'resetSlideshowTimer',
 | |
| 
 | |
| 		T: 'slideshowIntervalDialog',
 | |
| 		R: 'toggleSlideshowDirection',
 | |
| 		L: 'toggleSlideshowLooping',
 | |
| 	},
 | |
| 
 | |
| 	'Single Image': {
 | |
| 		pattern: '.single-image-mode',
 | |
| 		ignore: [
 | |
| 			'Esc',
 | |
| 
 | |
| 			// do not crop in single image mode...
 | |
| 			'C', 'F2',
 | |
| 
 | |
| 			// XXX not sure about this...
 | |
| 			//'Up', 'Down',
 | |
| 		],
 | |
| 
 | |
| 		Esc: 'toggleSingleImage: "off" -- Exit single image view',
 | |
| 	},
 | |
| 
 | |
| 	// XXX add "save as collection..."
 | |
| 	'Cropped': {
 | |
| 		pattern: '.crop-mode',
 | |
| 
 | |
| 		Esc: {
 | |
| 			default: 'uncrop',
 | |
| 			ctrl: 'uncropAll',
 | |
| 		},
 | |
| 	},
 | |
| 
 | |
| 	// XXX add "save as collection..." (???)
 | |
| 	// XXX cleanup...
 | |
| 	'Viewer': {
 | |
| 		doc: 'NOTE: binding priority is the same as the order of sections '+
 | |
| 			'on this page.',
 | |
| 		pattern: '*',
 | |
| 
 | |
| 		X: {
 | |
| 			alt: 'close',
 | |
| 		},
 | |
| 
 | |
| 		F4: {
 | |
| 			alt: 'close',
 | |
| 		},
 | |
| 		Q: {
 | |
| 			meta: 'close',
 | |
| 		},
 | |
| 		// XXX
 | |
| 		F5: keyboard.doc('Full reload viewer', 
 | |
| 			function(){ 
 | |
| 				//a.stop()
 | |
| 				/*
 | |
| 				killAllWorkers()
 | |
| 					.done(function(){
 | |
| 						reload() 
 | |
| 					})
 | |
| 				*/
 | |
| 				location.reload()
 | |
| 				return false
 | |
| 			}),
 | |
| 		F12: 'showDevTools',
 | |
| 		// NOTE: these are for systems where F** keys are not available 
 | |
| 		// 		or do other stuff...
 | |
| 		R: {
 | |
| 			default: 'rotateCW',
 | |
| 			shift: 'reverseImages',
 | |
| 			ctrl: 'reload!',
 | |
| 			'ctrl+shift': 'F5',
 | |
| 		},
 | |
| 		L: 'rotateCCW',
 | |
| 		H: {
 | |
| 			default: 'flipHorizontal',
 | |
| 			ctrl: 'listURLHistory',
 | |
| 			alt: 'browseActions: "/History/" -- Open history menu',
 | |
| 		},
 | |
| 		V: 'flipVertical',
 | |
| 		P: {
 | |
| 			'ctrl+shift': 'F12',
 | |
| 		},
 | |
| 
 | |
| 		// NOTE: this is handled by the wrapper at this point, so we do 
 | |
| 		// 		not have to do anything here...
 | |
| 		F11: 'toggleFullScreen', 
 | |
| 		F: {
 | |
| 			ctrl: 'F11',
 | |
| 			meta: 'F11',
 | |
| 		},
 | |
| 
 | |
| 		// XXX testing...
 | |
| 
 | |
| 		Enter: 'toggleSingleImage',
 | |
| 
 | |
| 		Home: {
 | |
| 			default: 'firstImage',
 | |
| 			ctrl: 'firstGlobalImage',
 | |
| 			shift: 'firstRibbon',
 | |
| 		},
 | |
| 		End: {
 | |
| 			default: 'lastImage',
 | |
| 			ctrl: 'lastGlobalImage',
 | |
| 			shift: 'lastRibbon',
 | |
| 		},
 | |
| 		Left: {
 | |
| 			default: 'prevImage',
 | |
| 			alt: 'shiftImageLeft!',
 | |
| 			ctrl: 'prevScreen',
 | |
| 			// XXX need to prevent default on mac + browser...
 | |
| 			meta: 'prevScreen',
 | |
| 		},
 | |
| 		PgUp: 'prevScreen',
 | |
| 		PgDown: 'nextScreen',
 | |
| 		Right: {
 | |
| 			default: 'nextImage',
 | |
| 			alt: 'shiftImageRight!',
 | |
| 			ctrl: 'nextScreen',
 | |
| 			// XXX need to prevent default on mac + browser...
 | |
| 			meta: 'nextScreen',
 | |
| 		},
 | |
| 		'(': 'prevImageInOrder',
 | |
| 		')': 'nextImageInOrder',
 | |
| 		',': 'prevMarked',
 | |
| 		'.': 'nextMarked',
 | |
| 		'[': 'prevBookmarked',
 | |
| 		']': 'nextBookmarked',
 | |
| 		Up: {
 | |
| 			default: 'prevRibbon',
 | |
| 			shift: 'shiftImageUp',
 | |
| 			'alt+shift': 'travelImageUp',
 | |
| 			'ctrl+shift': 'shiftImageUpNewRibbon',
 | |
| 		},
 | |
| 		Down: {
 | |
| 			default: 'nextRibbon',
 | |
| 			shift: 'shiftImageDown',
 | |
| 			'alt+shift': 'travelImageDown',
 | |
| 			'ctrl+shift': 'shiftImageDownNewRibbon',
 | |
| 		},
 | |
| 
 | |
| 		'#0': 'fitMax',
 | |
| 		'#1': {
 | |
| 			default: 'fitImage',
 | |
| 			shift: 'fitRibbon',
 | |
| 			ctrl: 'fitOrig!',
 | |
| 		},
 | |
| 		'#2': 'fitImage: 2 -- Fit 2 Images',
 | |
| 		'#3': {
 | |
| 			default: 'fitImage: 3 -- Fit 3 images',
 | |
| 			shift: 'fitRibbon: 3.5 -- Fit 3.5 ribbons',
 | |
| 		},
 | |
| 		'#4': 'fitImage: 4 -- Fit 4 images',
 | |
| 		'#5': {
 | |
| 			default: 'fitImage: 5 -- Fit 5 images',
 | |
| 			shift: 'fitRibbon: 5.5 -- Fit 5.5 ribbons',
 | |
| 		},
 | |
| 		'#6': 'fitImage: 6 -- Fit 6 images',
 | |
| 		'#7': 'fitImage: 7 -- Fit 7 images',
 | |
| 		'#8':'fitImage: 8 -- Fit 8 images',
 | |
| 		'#9': 'fitImage: 9 -- Fit 9 images',
 | |
| 		
 | |
| 		'+': 'zoomIn',
 | |
| 		'=': '+',
 | |
| 		'-': 'zoomOut',
 | |
| 
 | |
| 		F2: {
 | |
| 			default: 'cropRibbon',
 | |
| 			shift: 'cropRibbonAndAbove',
 | |
| 			ctrl: 'cropMarked',
 | |
| 			alt: 'cropBookmarked',
 | |
| 		},
 | |
| 
 | |
| 		// marking...
 | |
| 		M: {
 | |
| 			default: 'toggleMark',
 | |
| 			alt: 'browseActions: "/Mark/" -- Show mark menu',
 | |
| 		},
 | |
| 		A: {
 | |
| 			alt: 'browseActions',
 | |
| 			'alt+shift': 'listActions',
 | |
| 
 | |
| 			ctrl: 'toggleMark!: "ribbon" "on" -- Mark all images in ribbon',
 | |
| 		},
 | |
| 		D: {
 | |
| 			ctrl: 'toggleMark!: "ribbon" "off" -- Unmark all images in ribbon',
 | |
| 		},
 | |
| 		I: {
 | |
| 			default: 'showMetadata',
 | |
| 			shift: 'toggleStatusBar',
 | |
| 
 | |
| 			ctrl: 'toggleMark!: "ribbon" -- Invert marks in ribbon',
 | |
| 			'ctrl+shift': 'showMetadata: "current" "full" -- Show full metadata',
 | |
| 
 | |
| 			'meta+alt': 'showDevTools',
 | |
| 		},
 | |
| 		
 | |
| 		B: {
 | |
| 			default: 'toggleBookmark',
 | |
| 			ctrl: 'toggleTheme!',
 | |
| 			alt: 'browseActions: "/Bookmark/" -- Show bookmark menu',
 | |
| 		},
 | |
| 		E: {
 | |
| 			default: 'openInExtenalEditor',
 | |
| 			shift: 'openInExtenalEditor: 1 -- Open in alternative editor',
 | |
| 			alt: 'listExtenalEditors',
 | |
| 		},
 | |
| 		C: {
 | |
| 			default: 'browseActions: "/Crop/" -- Show crop menu',
 | |
| 			// do the default copy thing...
 | |
| 			// NOTE: this stops the default: handler from getting the ctrl:
 | |
| 			// 		key case...
 | |
| 			ctrl: '',
 | |
| 		},
 | |
| 		O: 'browsePath',
 | |
| 		S: {
 | |
| 			default: 'slideshowDialog',
 | |
| 			shift: 'sortImages: "birthtime ctime" -- Sort images by date',
 | |
| 			alt: 'browseActions: "/Sort/"',
 | |
| 			// XXX need to make this save to base_path if it exists and
 | |
| 			// 		ask the user if it does not... now it always asks.
 | |
| 			ctrl: 'saveIndexHere',
 | |
| 			'ctrl+shift': 'exportDialog',
 | |
| 		},
 | |
| 
 | |
| 		// XXX still experimental...
 | |
| 		U: {
 | |
| 			default: 'undoLast',
 | |
| 			shift: 'redoLast',
 | |
| 		},
 | |
| 		Z: {
 | |
| 			ctrl: 'undoLast',
 | |
| 			'ctrl+shift': 'redoLast',
 | |
| 		},
 | |
| 
 | |
| 		G: {
 | |
| 			default: 'editStatusBarIndex!',
 | |
| 			shift: 'toggleStatusBarIndexMode!',
 | |
| 
 | |
| 			// XXX for debug...
 | |
| 			ctrl: function(){ $('.viewer').toggleClass('visible-gid') },
 | |
| 		},
 | |
| 
 | |
| 		'?': 'showKeyboardBindings',
 | |
| 	},
 | |
| }	
 | |
| 
 | |
| 
 | |
| 
 | |
| /*********************************************************************/
 | |
| // XXX add a key binding list UI...
 | |
| // XXX add loading/storing of kb bindings...
 | |
| 
 | |
| // XXX add introspection and doc actions...
 | |
| var KeyboardActions = actions.Actions({
 | |
| 	config: {
 | |
| 		// limit key repeat to one per N milliseconds.
 | |
| 		//
 | |
| 		// Set this to -1 or null to run keys without any limitations.
 | |
| 		'max-key-repeat-rate': 0,
 | |
| 	},
 | |
| 
 | |
| 	get keyboard(){
 | |
| 		return this.__keyboard_config
 | |
| 	},
 | |
| 
 | |
| 	toggleKeyboardHandling: ['- Interface/Toggle keyboard handling',
 | |
| 		toggler.Toggler(null, function(_, state){ 
 | |
| 			if(state == null){
 | |
| 				return this.__keyboard_handler ? 'on' : 'off'
 | |
| 			}
 | |
| 
 | |
| 			// XXX this does not work yet...
 | |
| 			//var target = this.ribbons.viewer
 | |
| 			var target = $(document)
 | |
| 
 | |
| 			// start/reset keyboard handling...
 | |
| 			if(state == 'on'){
 | |
| 				var that = this
 | |
| 
 | |
| 				// need to reset...
 | |
| 				if(this.__keyboard_handler != null){
 | |
| 					target.off('keydown', this.__keyboard_handler)
 | |
| 				}
 | |
| 
 | |
| 				// setup base keyboard for devel, in case something breaks...
 | |
| 				// This branch does not drop keys...
 | |
| 				if(this.config['max-key-repeat-rate'] < 0 
 | |
| 						|| this.config['max-key-repeat-rate'] == null){
 | |
| 					//this.ribbons.viewer
 | |
| 					var handler = 
 | |
| 					this.__keyboard_handler =
 | |
| 						keyboard.makeKeyboardHandler(
 | |
| 							function(){ return that.__keyboard_config },
 | |
| 							function(k){ window.DEBUG && console.log(k) }, 
 | |
| 							this)
 | |
| 
 | |
| 				// drop keys if repeating too fast...
 | |
| 				// NOTE: this is done for smoother animations...
 | |
| 				} else {
 | |
| 					var handler = 
 | |
| 					this.__keyboard_handler =
 | |
| 						keyboard.dropRepeatingkeys(
 | |
| 							keyboard.makeKeyboardHandler(
 | |
| 								function(){ return that.__keyboard_config },
 | |
| 								function(k){ window.DEBUG && console.log(k) },
 | |
| 								this), 
 | |
| 							function(){ 
 | |
| 								return that.config['max-key-repeat-rate']
 | |
| 							})
 | |
| 				}
 | |
| 
 | |
| 				target.keydown(handler)
 | |
| 
 | |
| 			// stop keyboard handling...
 | |
| 			} else {
 | |
| 				target.off('keydown', this.__keyboard_handler)
 | |
| 				delete this.__keyboard_handler
 | |
| 			}
 | |
| 		},
 | |
| 		['on', 'off'])],
 | |
| 
 | |
| 	// XXX need to pre-process the docs...
 | |
| 	// 		- remove the path component...
 | |
| 	// 		- insert the action name where not doc present...
 | |
| 	// XXX cleanup CSS
 | |
| 	showKeyboardBindings: ['Interface/Show keyboard bindings',
 | |
| 		function(){
 | |
| 			var widget = drawer.Drawer($('body'), 
 | |
| 				keyboard.buildKeybindingsHelpHTML(this.__keyboard_config, this),
 | |
| 				{
 | |
| 					focusable: true,
 | |
| 				})
 | |
| 				.dom.find('.content')
 | |
| 					// XXX move to CSS...
 | |
| 					.css({
 | |
| 						background: 'white',
 | |
| 					})
 | |
| 		}],
 | |
| 
 | |
| })
 | |
| 
 | |
| var Keyboard = 
 | |
| module.Keyboard = core.ImageGridFeatures.Feature({
 | |
| 	title: '',
 | |
| 	doc: '',
 | |
| 
 | |
| 	tag: 'keyboard',
 | |
| 	depends: [
 | |
| 		'ui'
 | |
| 	],
 | |
| 
 | |
| 	actions: KeyboardActions, 
 | |
| 
 | |
| 	handlers: [
 | |
| 		['start',
 | |
| 			function(){
 | |
| 				var that = this
 | |
| 				this.__keyboard_config = this.keyboard || GLOBAL_KEYBOARD
 | |
| 
 | |
| 				this.toggleKeyboardHandling('on')
 | |
| 			}]
 | |
| 	],
 | |
| })
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /**********************************************************************
 | |
| * vim:set ts=4 sw=4 :                                                */
 | |
| return module })
 |