diff --git a/Viewer/features/filesystem.js b/Viewer/features/filesystem.js
index 479f88fd..ba0bb811 100755
--- a/Viewer/features/filesystem.js
+++ b/Viewer/features/filesystem.js
@@ -3095,15 +3095,28 @@ var FileSystemWriterUIActions = actions.Actions({
'exportDialog: "images"'],
- // XXX export using a preset...
// XXX TODO:
// - format the element into: title (optional) + info
+ // XXX add a 'name' field to the exportDialog(..)???
+ // XXX button icons...
+ // XXX button shortcuts...
exportPresets: ['- File/Export history...',
widgets.makeUIDialog(function(mode){
var that = this
+ var logger = this.logger && this.logger.push('exportPresets')
+
+ // XXX these should be type-specific...
+ var getName = function(preset){
+ return preset.name
+ || `${ preset.mode }: "${ preset.path }"` }
// presets...
var presets = that.config['export-presets'] || []
+ var index = presets
+ .reduce(function(res, e, i){
+ res[getName(e)] = i
+ return res }, {})
+ var keys = Object.keys(index)
// history...
// XXX
@@ -3111,56 +3124,73 @@ var FileSystemWriterUIActions = actions.Actions({
var history_index = {}
var history_keys = Object.keys(history_index)
- // XXX
var getPreset = function(title, presets, index){
return presets[index[title]] }
return browse.makeLister(null, function(path, make){
-
- var index = presets
- .reduce(function(res, e, i){
- name = e.name
- // XXX these should be type-specific...
- || `${ e.mode }: "${ e.path }"`
- res[name] = i
- return res }, {})
- var keys = Object.keys(index)
-
- // presets...
- //make.Separator()
+ // preset list...
keys.length == 0 ?
make.Empty('No presets...')
: make.EditableList(keys, {
list_id: 'presets',
sortable: true,
+ update_merge: 'live',
new_item: false,
+ // NOTE: we use empty to restore the automatic value...
+ allow_empty: true,
+ itemedit: function(evt, from, to){
+ var preset = getPreset(from, presets, index)
+ // clear...
+ if(to.trim() == ''){
+ delete preset.name
+ to = keys[keys.indexOf(from)] = getName(preset)
+ // set...
+ } else {
+ to = preset.name = to.trim() }
+ // update index...
+ index[to] = index[from]
+ delete index[from]
+ // select item...
+ // NOTE: this is not done automatically because
+ // we are changing the title .EditableList(..)
+ // is expecting...
+ make.dialog.one('update',
+ function(){
+ make.dialog.select(to) }) },
buttons: [
- // XXX new export or should this be edit???
- ['E', function(title){
- that.exportDialog(getPreset(title, presets, index))
+ ['edit', function(title){
+ var preset = getPreset(title, presets, index)
+ that.exportDialog(preset)
.close(function(){
- // XXX for some reason on update when
- // name affected the item does not
- // get updated...
- make.dialog.update() })}],
- // XXX not sure about the default icon...
- ['T', 'TO_TOP'],
- 'REMOVE',
- ],
- // XXX export...
+ var n = getName(preset)
+ // update the list if name is affected...
+ if(n != title){
+ keys[keys.indexOf(title)] = n
+ index[n] = index[title]
+ delete index[title]
+ make.dialog.select(n)
+ make.dialog.update() } })}],
+ ['♦', 'TO_TOP'],
+ 'REMOVE'],
+ // export...
open: function(evt, title){
- that.exportAs(getPreset(title, presets, index))
- make.dialog.close() },
- // XXX handle rename -> update index...
- // XXX
- })
+ var preset = getPreset(title, presets, index)
+ // export only if we get a good preset...
+ if(preset && getName(preset) == title){
+ that.exportAs(preset)
+ return make.dialog.close() }
+ // error...
+ logger
+ && logger.emit('error', 'preset not found.') }, })
// export dialog...
make.Separator({ style: { opacity: '0.1' } })
make('E$xport...', {
open: function(){
- that.exportDialog()
- make.dialog.close() }, })
+ that.exportDialog()
+ .close(function(evt, reason){
+ reason != 'reject'
+ && make.dialog.close() }) }, })
// history...
make.Separator()
@@ -3186,30 +3216,49 @@ var FileSystemWriterUIActions = actions.Actions({
})
.run(function(){
var that = this
- // XXX
+ // XXX this does not work yet...
this.keyboard.on('E', function(){
console.log('!!!!!!!!!!!!!', that.selected)
})
- })
- .close(function(){
-
- // XXX need to merge history/presets back when dialog closes...
- // XXX
-
}) })],
// XXX these do note need the ui -- move to a separate feature...
// XXX these are essentially the same as the history API, make a
// generic list manager???
+ // XXX need to check preset uniqueness...
exportPresetSave: ['- File/',
- function(){}],
+ function(settings){
+ settings = settings
+ || this.config['export-settings']
+ // XXX need to check preset uniqueness...
+ settings
+ && (this.config['export-presets'] =
+ this.config['export-presets']
+ || [])
+ .push(settings) }],
+
+ // XXX need a way to reference a preset...
exportPresetDelete: ['- File/',
function(){}],
exportPresetRun: ['- File/',
function(){}],
+ // XXX need to check item uniqueness...
exportHistoryPush: ['- File/',
- function(){}],
+ function(settings){
+ settings = settings
+ || this.config['export-settings']
+ var l = this.config['export-history-length'] || 50
+ var history =
+ this.config['export-history'] =
+ this.config['export-history'] || []
+ // add...
+ // XXX need to check item uniqueness...
+ settings
+ && history.push(settings)
+ // trim the history...
+ history.length > l
+ && history.splice(0, history.length - l) }],
})
@@ -3226,6 +3275,13 @@ module.FileSystemWriterUI = core.ImageGridFeatures.Feature({
],
actions: FileSystemWriterUIActions,
+
+ handlers: [
+ [[
+ 'exportIndex',
+ 'exportDirs',
+ ], function(_, settings){}]
+ ],
})
diff --git a/Viewer/features/ui-widgets.js b/Viewer/features/ui-widgets.js
index 5bcad2d6..9ff4d38b 100755
--- a/Viewer/features/ui-widgets.js
+++ b/Viewer/features/ui-widgets.js
@@ -842,8 +842,7 @@ var DialogsActions = actions.Actions({
: options.sortable
return browse.makeLister(null,
function(path, make){
- make.EditableList(list, options)
- },
+ make.EditableList(list, options) },
options) })],
showActionList: ['- Interface/',
core.doc`Show list of actions dialog...
diff --git a/Viewer/lib/widget/browse.js b/Viewer/lib/widget/browse.js
index ea667ec3..d964b277 100755
--- a/Viewer/lib/widget/browse.js
+++ b/Viewer/lib/widget/browse.js
@@ -600,7 +600,14 @@ function(data, options){
//
// // Item edit event handler...
// //
-// itemedit: function(from, to){ ... },
+// itemedit: function(evt, from, to){ ... },
+//
+// // If true allow saving and triggering options.itemedit(..) on an
+// // empty value after editing the item... (default: null)
+// //
+// // NOTE: this will not save the empty value (see .Editable(..))
+// // this will only trigger the handler on an empty value...
+// allow_empty: null | ,
//
// // Item open event handler...
// //
@@ -659,10 +666,11 @@ function(data, options){
// // Merge list state and external list mode on update...
// //
// // This can be:
-// // null - keep dialog state, ignore external state (default)
+// // 'keep_changes' - keep dialog state, ignore external state (default)
+// // null - same as 'keep_changes'
// // 'drop_changes' - replace dialog state with input state
-// // 'keep_changes' - keep dialog state (ignoring input)
// // 'merge' - merge dialog state and input state
+// // 'live' - live edit
// // - merge the changes
// //
// update_merge: null | 'drop_changes' | 'keep_changes' | 'merge' | ,
@@ -861,19 +869,15 @@ function(list, options){
],
})
.on('edit-commit', function(evt, to){
- if(to.trim() != ''){
+ if(options.allow_empty || to.trim() != ''){
to = saveItem(to, from)
-
options.itemedit
- && options.itemedit.call(elem, evt, from, to)
- }
- })
+ && options.itemedit.call(elem, evt, from, to) } })
.on('edit-abort edit-commit', function(_, title){
title = title.trim() == '' ? from : title
title = title.replace(/\$/g, '')
dialog.update()
- .then(function(){ dialog.select(`"${title}"`) })
- }) }
+ .then(function(){ dialog.select(`"${title}"`) }) }) }
dialog.__list = dialog.__list || {}
dialog.__editable = dialog.__editable || {}
@@ -893,8 +897,7 @@ function(list, options){
options = options || {}
var opts = {}
for(var k in options){
- opts[k] = options[k]
- }
+ opts[k] = options[k] }
options = opts
var lst =
@@ -903,7 +906,9 @@ function(list, options){
(list instanceof Function ? list() : list)
// load dialog state (ignore input)...
- : (options.update_merge == null || options.update_merge == 'keep_changes') ?
+ : (options.update_merge == null
+ || options.update_merge == 'keep_changes'
+ || options.update_merge == 'live') ?
dialog.__list[id]
// load input/external state (ignore dialog state)...
@@ -922,8 +927,7 @@ function(list, options){
// via their position in local...
i = i == -1 ? input.indexOf(a) : i
j = j == -1 ? input.indexOf(b) : j
- return i - j
- })
+ return i - j })
})(dialog.__list[id] || [], list instanceof Function ? list() : list)
// user merge...
@@ -940,7 +944,11 @@ function(list, options){
var editable = dialog.__editable[id] = lst instanceof Array
// NOTE: we .slice() here to make the changes a bit better packaged
// or discrete and not done as they come in...
- lst = lst instanceof Array ? lst.slice() : Object.keys(lst)
+ lst = lst instanceof Array ?
+ (options.update_merge == 'live' ?
+ lst
+ : lst.slice())
+ : Object.keys(lst)
dialog.__list[id] = lst
@@ -959,8 +967,7 @@ function(list, options){
options.to_top_button
&& buttons.push('TO_TOP')
options.to_bottom_button
- && buttons.push('TO_BOTTOM')
- }
+ && buttons.push('TO_BOTTOM') }
// remove...
editable
&& options.delete_button !== false
@@ -1055,8 +1062,7 @@ function(list, options){
var key = button instanceof Array ? button[1] : button
// skip seen buttons...
if(seen.indexOf(key) >= 0){
- return key
- }
+ return key }
var res = button in __buttons ?
__buttons[button]
: button[1] in __buttons ?
@@ -1065,12 +1071,9 @@ function(list, options){
// group if at least one sort button is present...
if(res !== button){
options.groupList = true
-
// avoid duplicates...
- seen.push(key)
- }
- return res.slice()
- })
+ seen.push(key) }
+ return res.slice() })
// clear out the unused button placeholders...
.filter(function(b){
return ['UP', 'DOWN', 'TO_TOP', 'TO_BOTTOM', 'REMOVE'].indexOf(b) < 0 })
@@ -1260,8 +1263,8 @@ function(list, pins, options){
// link the to_remove lists of pins and the main list...
dialog.__to_remove = dialog.__to_remove || {}
if(dialog.__to_remove[id] == null){
- dialog.__to_remove[id] = dialog.__to_remove[pins_id] = []
- }
+ dialog.__to_remove[id] =
+ dialog.__to_remove[pins_id] = [] }
// XXX redraw....
// - sort - within one list this is trivial (history.js)
@@ -2027,8 +2030,7 @@ var BrowserPrototype = {
if(e.length <= 0){
return null
}
- return e.find('.text').text()
- },
+ return e.find('.text').text() },
set selected(value){
return this.select(value) },