added status display API and some work on keyboard.js...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2013-05-30 19:15:38 +04:00
parent f0c1c816e9
commit e3004899f2
5 changed files with 188 additions and 42 deletions

View File

@ -943,7 +943,7 @@ function loadFileImages(path, no_load_diffs, callback){
}).sort().reverse()[0] }).sort().reverse()[0]
path = path == null ? 'images.json' : path path = path == null ? 'images.json' : path
console.log('Loading:', path) updateStatus('Loading: ' + path)
path = base +'/'+ path path = base +'/'+ path
@ -972,7 +972,7 @@ function loadFileImages(path, no_load_diffs, callback){
// whether we have one or more deffereds here... // whether we have one or more deffereds here...
.done(function(data){ .done(function(data){
diff_data[i+1] = data diff_data[i+1] = data
console.log('Loaded:', e) updateStatus('Loaded:', e)
}) })
})) }))
.then(function(){ .then(function(){
@ -988,12 +988,12 @@ function loadFileImages(path, no_load_diffs, callback){
$.extend(json, diff_data) $.extend(json, diff_data)
IMAGES = json IMAGES = json
console.log('Loaded IMAGES...') updateStatus('Loaded images...')
callback != null && callback() callback != null && callback()
}) })
.fail(function(){ .fail(function(){
console.error('ERROR LOADING:', path) updateErrorStatus('Loading: ' + path)
}) })
} }
@ -1009,7 +1009,7 @@ function saveFileImages(name){
name = name == null ? normalizePath(CACHE_DIR +'/'+ Date.timeStamp()) : name name = name == null ? normalizePath(CACHE_DIR +'/'+ Date.timeStamp()) : name
if(window.dumpJSON == null){ if(window.dumpJSON == null){
console.error('Can\'t save to file.') updateErrorStatus('Can\'t save to file.')
return return
} }
@ -1018,7 +1018,7 @@ function saveFileImages(name){
$.each($.map(listDir(normalizePath(CACHE_DIR)), function(e){ $.each($.map(listDir(normalizePath(CACHE_DIR)), function(e){
return /.*-images-diff.json$/.test(e) ? e : null return /.*-images-diff.json$/.test(e) ? e : null
}), function(i, e){ }), function(i, e){
console.log('removeing:', e) updateStatus('removeing:', e)
removeFile(normalizePath(CACHE_DIR +'/'+ e)) removeFile(normalizePath(CACHE_DIR +'/'+ e))
}) })
IMAGES_UPDATED = [] IMAGES_UPDATED = []
@ -1060,12 +1060,12 @@ function loadFileState(data_path, callback){
// unknown format... // unknown format...
} else { } else {
console.error('unknown format.') updateStatus('Unknown format.')
return return
} }
}) })
.fail(function(){ .fail(function(){
console.error('ERROR LOADING:', data_path) updateErrorStatus('Loading:', data_path)
}) })
return res return res
@ -1114,10 +1114,12 @@ function loadDir(path, raw_load){
var orig_path = path var orig_path = path
var data var data
updateStatus('Loading...').show()
var files = listDir(path) var files = listDir(path)
if(files == null){ if(files == null){
console.error('Path error:', path) updateErrorStatus('Path: ' + path)
return return
} }
@ -1143,11 +1145,14 @@ function loadDir(path, raw_load){
// load the found data file... // load the found data file...
if(data != null){ if(data != null){
console.log('Loading:', data) updateStatus('Loading: ', data)
data = path + '/' + data data = path + '/' + data
return loadFileState(data) return loadFileState(data)
.always(function(){
showStatus('Done.')
})
// load the dir as-is... // load the dir as-is...
} else { } else {
@ -1157,7 +1162,7 @@ function loadDir(path, raw_load){
}) })
if(image_paths.length == 0){ if(image_paths.length == 0){
console.error('No images in:', orig_path) updateErrorStatus('No images in:', orig_path)
return return
} }
@ -1168,6 +1173,7 @@ function loadDir(path, raw_load){
MARKED = [] MARKED = []
loadData() loadData()
showStatus('Done.')
} }
} }
@ -1183,7 +1189,7 @@ function updateRibbonsFromFavDirs(){
// NOTE: this will open the default editor/viewer. // NOTE: this will open the default editor/viewer.
function openImage(){ function openImage(){
if(window.runSystem == null){ if(window.runSystem == null){
console.error('Can\'t run external programs.') updateErrorStatus('Can\'t run external programs.')
return return
} }
// XXX if path is not present try and open the biggest preview... // XXX if path is not present try and open the biggest preview...
@ -1193,13 +1199,61 @@ function openImage(){
/********************************************************************** /**********************************************************************
* Actions * Info & status...
*/ */
// NOTE: if message is null, then just return the status element...
function updateStatus(message){
var elem = $('.global-status')
if(elem.length == 0){
elem = $('<div class="global-status"/>')
}
if(message == null){
return elem
}
if(arguments.length > 1){
message = Array.apply(Array, arguments).join(' ')
}
if(typeof(message) == typeof('s') && /^error.*/i.test(message)){
console.error.apply(console, arguments)
} else {
console.log.apply(console, arguments)
}
return updateInfo(elem, message)
}
function showStatus(message){
return updateStatus(message)
.stop()
.show()
.delay(500)
.fadeOut(800)
}
function showErrorStatus(message){
return updateStatus('Error:' + message)
.stop()
.show()
}
// XXX do we need a full rewrite here, or will it be better to just fill // XXX do we need a full rewrite here, or will it be better to just fill
// the slots... // the slots...
function updateGlobalImageInfo(image){ function updateGlobalImageInfo(image){
image = image == null ? getImage() : $(image) image = image == null ? getImage() : $(image)
image = image.length == 0 ? getImage() : image
var elem = $('.global-image-info')
if(elem.length == 0){
elem = $('<div class="global-image-info"/>')
}
// no image no update...
if(image.length == 0){
return elem
}
var gid = getImageGID(image) var gid = getImageGID(image)
var r = getRibbonIndex(getRibbon(image)) var r = getRibbonIndex(getRibbon(image))
@ -1222,11 +1276,6 @@ function updateGlobalImageInfo(image){
meta = meta.join(', ') meta = meta.join(', ')
meta = meta != '' ? '( '+ meta +' )' : '' meta = meta != '' ? '( '+ meta +' )' : ''
var elem = $('.global-image-info')
if(elem.length == 0){
elem = $('<div class="global-image-info"/>')
}
return updateInfo(elem, return updateInfo(elem,
// path... // path...
'<span class="expanding-text path">'+ '<span class="expanding-text path">'+
@ -1268,6 +1317,18 @@ function updateGlobalImageInfo(image){
function updateInlineImageInfo(image){ function updateInlineImageInfo(image){
image = image == null ? getImage() : $(image) image = image == null ? getImage() : $(image)
image = image.length == 0 ? getImage() : image
var elem = $('.inline-image-info')
if(elem.length == 0){
elem = $('<div class="inline-image-info"/>')
}
// no image no update...
if(image.length == 0){
return elem
}
var gid = getImageGID(image) var gid = getImageGID(image)
var r = getRibbonIndex(getRibbon(image)) var r = getRibbonIndex(getRibbon(image))
@ -1277,11 +1338,6 @@ function updateInlineImageInfo(image){
var orientation = data.orientation var orientation = data.orientation
orientation = orientation == null ? 0 : orientation orientation = orientation == null ? 0 : orientation
var elem = $('.inline-image-info')
if(elem.length == 0){
elem = $('<div class="inline-image-info"/>')
}
return updateInfo(elem, return updateInfo(elem,
// name... // name...
data.path.split('/').pop() +'<br>'+ data.path.split('/').pop() +'<br>'+
@ -1297,6 +1353,16 @@ function updateInlineImageInfo(image){
} }
function inlineImageInfoHoverHandler(evt){
var img = $(evt.target).closest('.image')
if(img.length > 0){
if(img.find('.inline-image-info:visible').length == 0){
updateInlineImageInfo(img)
}
}
}
/********************************************************************** /**********************************************************************
* Setup * Setup

View File

@ -254,7 +254,8 @@ body {
width: 100%; width: 100%;
background: black; background: black;
opacity: 0.7; opacity: 0.7;
}
.image .inline-image-info:hover {
-moz-user-select: auto; -moz-user-select: auto;
-webkit-user-select: auto; -webkit-user-select: auto;
-o-user-select: auto; -o-user-select: auto;
@ -328,7 +329,8 @@ body {
color: white; color: white;
opacity: 0.6; opacity: 0.6;
}
.overlay-info:hover {
-moz-user-select: auto; -moz-user-select: auto;
-webkit-user-select: auto; -webkit-user-select: auto;
-o-user-select: auto; -o-user-select: auto;
@ -526,6 +528,11 @@ body {
display: inline; display: inline;
} }
.global-status {
opacity: 1;
z-index: 1000;
}
</style> </style>
@ -578,18 +585,6 @@ $(function(){
function(k){ function(k){
window.DEBUG && console.log(k) window.DEBUG && console.log(k)
})) }))
.on('mouseover', function(evt){
var img = $(evt.target).closest('.image')
if(img.length > 0){
if(IMAGE_INFO){
if(img.find('.inline-image-info:visible').length == 0){
updateInlineImageInfo(img)
}
} else {
img.find('.inline-image-info').remove()
}
}
})
setupDataBindings() setupDataBindings()

View File

@ -16,7 +16,32 @@ var DIRECTION = 'next'
/*********************************************************************/ /*********************************************************************/
var KEYBOARD_CONFIG = { var KEYBOARD_CONFIG = {
// info overlay...
//
// NOTE: this is here to prevent selecting images while trying to
// select info text...
'.overlay-info:hover': {
title: 'Info overlay',
doc: 'NOTE: when the cursor is over the info overlay one can use '+
'Ctrl-A and Ctrl-D for info text selection, without affecting '+
'image selection/marks.',
ignore: [ 'A' ],
A: {
// NOTE: this is here only for documentation...
ctrl: doc('Select all'),
},
D: {
ctrl: doc('Clear selection',
function(){
document.getSelection().empty()
return false
})
}
},
// help mode... // help mode...
//
// NOTE: need to keep all info modes before the rest so as to give // NOTE: need to keep all info modes before the rest so as to give
// their bindings priority... // their bindings priority...
'.help-mode': { '.help-mode': {
@ -40,6 +65,7 @@ var KEYBOARD_CONFIG = {
// single image mode only... // single image mode only...
//
'.single-image-mode': { '.single-image-mode': {
title: 'Single image mode', title: 'Single image mode',
@ -59,6 +85,7 @@ var KEYBOARD_CONFIG = {
// single image mode only... // single image mode only...
//
'.marked-only-view:not(.single-image-mode)': { '.marked-only-view:not(.single-image-mode)': {
title: 'Marked only view', title: 'Marked only view',
@ -72,6 +99,7 @@ var KEYBOARD_CONFIG = {
// general setup... // general setup...
//
'.viewer:not(.overlay)': { '.viewer:not(.overlay)': {
title: 'Global', title: 'Global',
@ -285,7 +313,7 @@ var KEYBOARD_CONFIG = {
}, },
I: { I: {
// XXX group this with other info stuff into a single on/off toggle... // XXX group this with other info stuff into a single on/off toggle...
default: doc('Toggle image info visibility (on hover)', default: doc('Toggle image info display',
function(){ toggleImageInfo() }), function(){ toggleImageInfo() }),
// XXX STUB -- replace with a real info window... // XXX STUB -- replace with a real info window...
shift: doc('Show current image info', shift: doc('Show current image info',
@ -307,14 +335,30 @@ var KEYBOARD_CONFIG = {
'Position (global): '+ order +'/'+ DATA.order.length +'\n'+ 'Position (global): '+ order +'/'+ DATA.order.length +'\n'+
'') '')
}), }),
alt: doc('Toggle inline image info display',
function(){
toggleInlineImageInfo()
}),
// marking...
ctrl: doc('Invert image marks', ctrl: doc('Invert image marks',
function(){ invertImageMarks() }), function(){ invertImageMarks() }),
}, },
A: { A: {
shift: doc('Toggle marks in current contagious block', // XXX does not yet work with DATA (???)
function(){ toggleImageMarkBlock() }), //shift: doc('Toggle marks in current contagious block',
// function(){ toggleImageMarkBlock() }),
ctrl: doc('Mark current ribbon', ctrl: doc('Mark current ribbon',
function(){ markAll('ribbon') }), function(){ markAll('ribbon') }),
'ctrl+shift': doc('Mark all images',
function(){ markAll('all') }),
},
D: {
ctrl: doc('Unmark current ribbon',
function(){ removeImageMarks('ribbon') }),
'ctrl+shift': doc('Unmark all images',
function(){ removeImageMarks('all') }),
}, },
U: { U: {
ctrl: doc('Unmark current ribbon', ctrl: doc('Unmark current ribbon',

View File

@ -62,6 +62,17 @@ var _SPECIAL_KEYS = {
188: ',', 190: '.', 191: '/', 188: ',', 190: '.', 191: '/',
} }
var _SHIFT_KEYS = {
'`': '~', '-': '_', '=':'+',
1: '!', 2: '@', 3: '#', 4: '$', 5: '%',
6:'^', 7:'&', 8: '*', 9: '(', 0: ')',
'[': '{', ']': '}i', '\\': '|',
';': ':', '\'': '"',
',': '<', '.': '>', '/': '?'
}
var _KEY_CODES = {} var _KEY_CODES = {}
for(var k in _SPECIAL_KEYS){ for(var k in _SPECIAL_KEYS){
_KEY_CODES[_SPECIAL_KEYS[k]] = k _KEY_CODES[_SPECIAL_KEYS[k]] = k
@ -93,6 +104,7 @@ function toKeyCode(c){
// documentation wrapper... // documentation wrapper...
function doc(text, func){ function doc(text, func){
func = func == null ? function(){return true}: func
func.doc = text func.doc = text
return func return func
} }
@ -135,11 +147,12 @@ function doc(text, func){
* XXX BUG explicitly given modes do not yield results if the pattern * XXX BUG explicitly given modes do not yield results if the pattern
* does not match... * does not match...
*/ */
function getKeyHandlers(key, modifiers, keybindings, modes){ function getKeyHandlers(key, modifiers, keybindings, modes, shifted_keys){
var chr = null var chr = null
var did_handling = false var did_handling = false
modifiers = modifiers == null ? '' : modifiers modifiers = modifiers == null ? '' : modifiers
modes = modes == null ? 'any' : modes modes = modes == null ? 'any' : modes
shifted_keys = shifted_keys == null ? _SHIFT_KEYS : shifted_keys
if(typeof(key) == typeof(123)){ if(typeof(key) == typeof(123)){
key = key key = key
@ -149,6 +162,12 @@ function getKeyHandlers(key, modifiers, keybindings, modes){
key = toKeyCode(key) key = toKeyCode(key)
} }
/* XXX this is not done yet...
if(shifted_keys != false && key in shifted_keys){
key = shifted_keys[key]
}
*/
res = {} res = {}
for(var mode in keybindings){ for(var mode in keybindings){
@ -400,7 +419,8 @@ function makeKeyboardHandler(keybindings, unhandled){
* <keys-spec> - list of key names. * <keys-spec> - list of key names.
* *
*/ */
function buildKeybindingsHelp(keybindings){ function buildKeybindingsHelp(keybindings, shifted_keys){
shifted_keys = shifted_keys == null ? _SHIFT_KEYS : shifted_keys
var res = {} var res = {}
var mode, title var mode, title
@ -455,6 +475,13 @@ function buildKeybindingsHelp(keybindings){
var keys = [] var keys = []
section[doc] = keys section[doc] = keys
} }
// translate shifted keys...
if(shifted_keys != false && mod == 'shift' && key in shifted_keys){
mod = ''
key = shifted_keys[key]
}
keys.push((mod == '' || mod == 'default') ? key : (mod +'+'+ key)) keys.push((mod == '' || mod == 'default') ? key : (mod +'+'+ key))
} }

View File

@ -69,6 +69,20 @@ var toggleTheme = createCSSClassToggler('.viewer',
var toggleImageInfo = createCSSClassToggler('.viewer', '.image-info-visible') var toggleImageInfo = createCSSClassToggler('.viewer', '.image-info-visible')
var toggleInlineImageInfo = createCSSClassToggler('.viewer',
'.image-info-inline-visible',
function(action){
if(action == 'on'){
$(document)
.on('mouseover', inlineImageInfoHoverHandler)
} else {
$(document)
.off('mouseover', inlineImageInfoHoverHandler)
$('.inline-image-info').remove()
}
})
// NOTE: this confirmsto the css toggler protocol, but is not implemented // NOTE: this confirmsto the css toggler protocol, but is not implemented
// via createCSSClassToggler as we do not need to set any classes, // via createCSSClassToggler as we do not need to set any classes,
// al least at this point... // al least at this point...