added full support for browse item sortcut keys + refactoring...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-01-28 01:09:05 +03:00
parent b79ef79242
commit 320290861b
5 changed files with 83 additions and 53 deletions

View File

@ -632,8 +632,6 @@ var URLHistoryUIActions = actions.Actions({
reason != 'reject' reason != 'reject'
&& o.close(reason) && o.close(reason)
}) } }) }
// clone the bindings so as not to mess up the global browser...
o.keybindings = JSON.parse(JSON.stringify(o.keybindings))
o.keyboard.handler('General', 'O', 'browsePath') o.keyboard.handler('General', 'O', 'browsePath')
return o return o

View File

@ -1233,8 +1233,6 @@ var KeyboardUIActions = actions.Actions({
dialog.newMode = function(){ dialog.newMode = function(){
that.editKeyboardMode() } that.editKeyboardMode() }
// clone the bindings so as not to mess up the global browser...
dialog.keybindings = JSON.parse(JSON.stringify(dialog.keybindings))
dialog.keyboard dialog.keyboard
.handler('General', 'N', 'newKey') .handler('General', 'N', 'newKey')
.handler('General', 'K', 'newKey') .handler('General', 'K', 'newKey')
@ -1371,7 +1369,6 @@ var KeyboardUIActions = actions.Actions({
abort = true abort = true
this.close() this.close()
} }
dialog.keybindings = JSON.parse(JSON.stringify(dialog.keybindings))
dialog.keyboard dialog.keyboard
.handler('General', 'Q', 'abort') .handler('General', 'Q', 'abort')
@ -1479,7 +1476,6 @@ var KeyboardUIActions = actions.Actions({
abort = true abort = true
this.close() this.close()
} }
dialog.keybindings = JSON.parse(JSON.stringify(dialog.keybindings))
dialog.keyboard dialog.keyboard
.handler('General', 'Q', 'abort') .handler('General', 'Q', 'abort')
@ -1569,7 +1565,6 @@ var KeyboardUIActions = actions.Actions({
abort = true abort = true
this.close() this.close()
} }
dialog.keybindings = JSON.parse(JSON.stringify(dialog.keybindings))
dialog.keyboard dialog.keyboard
.handler('General', 'Q', 'abort') .handler('General', 'Q', 'abort')

View File

@ -102,21 +102,21 @@ var SlideshowActions = actions.Actions({
} }
var o = browse.makeLister(null, function(path, make){ var o = browse.makeLister(null, function(path, make){
make(['Interval: ', make(['$Interval: ',
function(){ return that.config['slideshow-interval'] }]) function(){ return that.config['slideshow-interval'] }])
.on('open', function(){ .on('open', function(){
that.slideshowIntervalDialog(make.dialog) }) that.slideshowIntervalDialog(make.dialog) })
make(['Direction: ', make(['$Direction: ',
function(){ return that.config['slideshow-direction'] }]) function(){ return that.config['slideshow-direction'] }])
.on('open', _makeToggleHandler('toggleSlideshowDirection')) .on('open', _makeToggleHandler('toggleSlideshowDirection'))
make(['Looping: ', make(['$Looping: ',
function(){ return that.config['slideshow-looping'] }]) function(){ return that.config['slideshow-looping'] }])
.on('open', _makeToggleHandler('toggleSlideshowLooping')) .on('open', _makeToggleHandler('toggleSlideshowLooping'))
// Start/stop... // Start/stop...
make([function(){ make([function(){
return that.toggleSlideshow('?') == 'on' ? 'Stop' : 'Start' }]) return that.toggleSlideshow('?') == 'on' ? '$Stop' : '$Start' }])
.on('open', function(){ .on('open', function(){
that.toggleSlideshow() that.toggleSlideshow()
o.close() o.close()

View File

@ -721,18 +721,19 @@ module.Dialogs = core.ImageGridFeatures.Feature({
var BrowseActionsActions = actions.Actions({ var BrowseActionsActions = actions.Actions({
config: { config: {
'action-category-order': [ 'action-category-order': [
'99:File', //'99:File',
'99:$File',
// NOTE: we can order any sub-tree we want in the same // NOTE: we can order any sub-tree we want in the same
// manner as the root... // manner as the root...
'File/-80:Clear viewer', 'File/-80:Clear viewer',
'File/-90:Close viewer', 'File/-90:Close viewer',
// NOTE: non existing elements will not get drawn... // NOTE: non existing elements will not get drawn...
//'File/-99:moo', //'File/-99:moo',
'80:Edit', '80:$Edit',
'70:Navigate', '70:$Navigate',
'60:Image', '60:$Image',
'50:Ribbon', '50:$Ribbon',
'40:Crop', '40:$Crop',
'Crop/80:Crop marked images', 'Crop/80:Crop marked images',
'Crop/80:Crop bookmarked images', 'Crop/80:Crop bookmarked images',
// NOTE: we can also add separators here... // NOTE: we can also add separators here...
@ -745,9 +746,9 @@ var BrowseActionsActions = actions.Actions({
'Crop/-82:Uncrop', 'Crop/-82:Uncrop',
'-40:Interface', '-40:Interface',
'-50:Workspace', '-50:$Workspace',
'-60:System', '-60:System',
'-70:Help', '-70:$Help',
'-80:---', '-80:---',
'-90:Development', '-90:Development',
'-90:Test', '-90:Test',
@ -760,6 +761,8 @@ var BrowseActionsActions = actions.Actions({
}, },
'browse-actions-keys': true, 'browse-actions-keys': true,
'browse-actions-shortcut-marker': '\\$(\\w)',
}, },
// Browse actions dialog... // Browse actions dialog...
@ -840,6 +843,8 @@ var BrowseActionsActions = actions.Actions({
makeUIDialog(function(path, options){ makeUIDialog(function(path, options){
var actions = this var actions = this
var priority = /^(-?[0-9]+)\s*:\s*/ var priority = /^(-?[0-9]+)\s*:\s*/
var marker = RegExp(this.config['browse-actions-shortcut-marker'], 'g')
marker = marker || RegExp(marker, 'g')
var dialog var dialog
options = options || {} options = options || {}
@ -853,6 +858,8 @@ var BrowseActionsActions = actions.Actions({
traversable: true, traversable: true,
pathPrefix: '/', pathPrefix: '/',
fullPathEdit: true, fullPathEdit: true,
item_shortcut_marker: marker,
} }
cfg.__proto__ = this.config['browse-actions-settings'] cfg.__proto__ = this.config['browse-actions-settings']
@ -874,7 +881,10 @@ var BrowseActionsActions = actions.Actions({
// check if it's a priority path... // check if it's a priority path...
} else { } else {
for(var e in level){ for(var e in level){
if(e.replace(priority, '').trim() == text){ var n = e.replace(priority, '')
n = (marker ? n.replace(marker, '$1') : n).trim()
if(n == text){
return [e, level[e]] return [e, level[e]]
} }
} }
@ -1163,7 +1173,15 @@ var BrowseActionsActions = actions.Actions({
} else if(actions.config['browse-actions-settings'].showEmpty } else if(actions.config['browse-actions-settings'].showEmpty
|| (cur[key] != null || (cur[key] != null
&& Object.keys(cur[key]).length > 0)){ && Object.keys(cur[key]).length > 0)){
var p = '/'+ path.concat([text]).join('/') +'/'
p = marker ? p.replace(marker, '$1') : p
make(text + '/', { push_on_open: true }) make(text + '/', { push_on_open: true })
.attr({
keys: [
getKeys('browseActions: "'+ p +'"'),
getKeys('browseActions!: "'+ p +'"'),
].filter(function(e){ return e.trim() != '' }).join(' / '),
})
// item: line... // item: line...
} else if(text == '---'){ } else if(text == '---'){
@ -1190,8 +1208,6 @@ var BrowseActionsActions = actions.Actions({
action action
&& actions.showDoc(action) && actions.showDoc(action)
} }
// clone the bindings so as not to mess up the global browser...
dialog.keybindings = JSON.parse(JSON.stringify(dialog.keybindings))
dialog.keyboard.handler('General', '?', 'showDoc') dialog.keyboard.handler('General', '?', 'showDoc')
return dialog return dialog

View File

@ -880,7 +880,7 @@ var BrowserClassPrototype = {
} }
path = path path = path
// clear the '..'... // clear the '..' and markers...
// NOTE: we reverse to avoid setting elements with negative // NOTE: we reverse to avoid setting elements with negative
// indexes if we have a leading '..' // indexes if we have a leading '..'
.reverse() .reverse()
@ -1273,15 +1273,20 @@ var BrowserPrototype = {
}, },
// Call the constructor's .path2list(..).. // Call the constructor's .path2list(..) and clear out shortcut markers...
// //
// See: BrowserClassPrototype.path2list(..) for docs... // See: BrowserClassPrototype.path2list(..) for docs...
path2list: function(path){ path2list: function(path){
var marker = this.options.itemShortcutMarker
marker = marker && RegExp(marker, 'g')
// if list is flat we do not need to split it, just format... // if list is flat we do not need to split it, just format...
if(this.options.flat && path && path.constructor !== Array){ if(this.options.flat && path && path instanceof Array){
return path == '' || path.length == 0 ? [] : [path] return (path == '' || path.length == 0) ? [] : [path]
} }
return this.constructor.path2list.apply(this, arguments) return this.constructor
.path2list.apply(this, arguments)
.map(function(e){
return marker ? e.replace(marker, '$1') : e })
}, },
// Trigger jQuery events on Item then bubble to Browser... // Trigger jQuery events on Item then bubble to Browser...
@ -1820,9 +1825,9 @@ var BrowserPrototype = {
delete item_shortcuts[k] delete item_shortcuts[k]
} }
}) })
var item_shortcut_marker = this.options.itemShortcutMarker || /&(\w)/ var item_shortcut_marker = this.options.itemShortcutMarker
item_shortcut_marker = item_shortcut_marker ? item_shortcut_marker = item_shortcut_marker ?
RegExp(item_shortcut_marker) RegExp(item_shortcut_marker, 'g')
: null : null
// XXX revise signature... // XXX revise signature...
@ -1850,7 +1855,10 @@ var BrowserPrototype = {
buttons = buttons buttons = buttons
|| (that.options.itemButtons && that.options.itemButtons.slice()) || (that.options.itemButtons && that.options.itemButtons.slice())
// special case: shorthand...
// NOTE: this is becoming a bit big, so here the code is
// split into more wieldable sections...
//------------------------ special case: shorthand item ---
if(p && (p in (that.options.elementShorthand || {}) if(p && (p in (that.options.elementShorthand || {})
|| (p.hasClass || (p.hasClass
&& p in that.options.elementShorthand && p in that.options.elementShorthand
@ -1866,6 +1874,7 @@ var BrowserPrototype = {
return res return res
} }
//------------------------------------------- item text ---
// array of str/func/dom... // array of str/func/dom...
if(p.constructor === Array){ if(p.constructor === Array){
// resolve handlers... // resolve handlers...
@ -1910,7 +1919,7 @@ var BrowserPrototype = {
.text(p.replace(dir, '')) .text(p.replace(dir, ''))
} }
// keyboard shortcuts... //---------------------------------- keyboard shortcuts ---
if(item_shortcuts){ if(item_shortcuts){
// key set in options... // key set in options...
opts.shortcut_key && !item_shortcuts[opts.shortcut_key] opts.shortcut_key && !item_shortcuts[opts.shortcut_key]
@ -1944,7 +1953,9 @@ var BrowserPrototype = {
+'</span>' })) }) +'</span>' })) })
} }
} }
//---------------------------------------------------------
// tell the lister that we have started in interactive mode...
interactive = true interactive = true
// skip drawing of non-traversable or disabled elements if // skip drawing of non-traversable or disabled elements if
@ -1955,31 +1966,31 @@ var BrowserPrototype = {
return $() return $()
} }
// build list item... //------------------------------------------ build item ---
var res = $('<div>') var res = $('<div>')
// handle clicks ONLY when not disabled... // handle clicks ONLY when not disabled...
.click(function(){ .click(function(){
!$(this).hasClass('disabled') !$(this).hasClass('disabled')
&& that.push($(this)) }) && that.push($(this)) })
.addClass([
'item',
// XXX use the same algorithm as .select(..)
selection && res.text() == selection ? 'selected' : '',
!traversable ? 'not-traversable' : '',
disabled ? 'disabled' : '',
hidden ? 'hidden' : '',
opts.hide_on_search ? 'hide-on-search' : '',
(opts.hide_on_search || opts.not_searchable) ? 'not-searchable' : '',
opts.not_filtered_out ? 'not-filtered-out' : '',
].join(' '))
// append text elements... // append text elements...
.append(p) .append(p)
res.addClass([ opts.push_on_open
'item', && res.attr('push-on-open', 'on')
// XXX use the same algorithm as .select(..)
selection && res.text() == selection ? 'selected' : '',
!traversable ? 'not-traversable' : '', //--------------------------------------------- buttons ---
disabled ? 'disabled' : '',
hidden ? 'hidden' : '',
opts.hide_on_search ? 'hide-on-search' : '',
(opts.hide_on_search || opts.not_searchable) ? 'not-searchable' : '',
opts.not_filtered_out ? 'not-filtered-out' : '',
].join(' '))
opts.push_on_open && res.attr('push-on-open', 'on')
// buttons...
// button container... // button container...
var btn = res.find('.button-container') var btn = res.find('.button-container')
btn = btn.length == 0 ? btn = btn.length == 0 ?
@ -1988,7 +1999,7 @@ var BrowserPrototype = {
.appendTo(res) .appendTo(res)
: btn : btn
// action (open)... // action (open) button...
if(traversable && that.options.actionButton){ if(traversable && that.options.actionButton){
btn.append($('<div>') btn.append($('<div>')
.addClass('button') .addClass('button')
@ -2001,7 +2012,8 @@ var BrowserPrototype = {
that.action() that.action()
})) }))
} }
// push...
// push button...
if(traversable && that.options.pushButton){ if(traversable && that.options.pushButton){
btn.append($('<div>') btn.append($('<div>')
.addClass('button') .addClass('button')
@ -2045,7 +2057,7 @@ var BrowserPrototype = {
})) }))
}) })
// place in list... //--------------------------------------- place in list ---
// as-is... // as-is...
if(!sort_traversable || sort_traversable == 'none'){ if(!sort_traversable || sort_traversable == 'none'){
res.appendTo(l) res.appendTo(l)
@ -2062,6 +2074,7 @@ var BrowserPrototype = {
res.appendTo(l) res.appendTo(l)
} }
} }
//---------------------------------------------------------
return res return res
} }
@ -3564,15 +3577,23 @@ PathListPrototype.options = {
// Supported patterns: // Supported patterns:
// A - matches A exactly // A - matches A exactly
// A|B - matches either A or B // A|B - matches either A or B
// shortcut marker
// - see .options.itemShortcutMarker
//
// NOTE: only the second argument is checked for '|' patterns...
var match = function(a, path){ var match = function(a, path){
var marker = that.options.itemShortcutMarker
marker = marker && RegExp(marker, 'g')
path = marker ? e.replace(marker, '$1') : path
// NOTE: might be good to make this recursive when expanding // NOTE: might be good to make this recursive when expanding
// pattern support... // pattern support...
return a return a
.split('|') .split('|')
.map(function(e){
return marker ? e.replace(marker, '$1') : e })
.filter(function(e){ .filter(function(e){
return e == path return e == path })
}).length > 0 .length > 0 }
}
// get the '*' listers... // get the '*' listers...
var lister = keys var lister = keys