diff --git a/Viewer/css/experimenting.css b/Viewer/css/experimenting.css index 99aa944b..9bd0f343 100755 --- a/Viewer/css/experimenting.css +++ b/Viewer/css/experimenting.css @@ -323,7 +323,7 @@ body { font-style: italic; } .browse-widget.tail-action .list .item:last-child .button { - display: none; + /*display: none;*/ } /* do not show top border if after another action or separator... */ diff --git a/Viewer/features/filesystem.js b/Viewer/features/filesystem.js index ba0bb811..7698b80c 100755 --- a/Viewer/features/filesystem.js +++ b/Viewer/features/filesystem.js @@ -3001,6 +3001,8 @@ var FileSystemWriterUIActions = actions.Actions({ .exportDialog(mode) .exportDialog(settings) + + NOTE: when saving a preset the dialog will trigger a 'save-preset' event. `, widgets.makeUIDialog(function(mode){ var that = this @@ -3075,8 +3077,23 @@ var FileSystemWriterUIActions = actions.Actions({ var mode = that.config['export-dialog-modes'][settings['mode']] that[mode.action](settings) - dialog.close() - }, + dialog.close() }, + buttons: [ + ['Save preset', + function(_, elem){ + that.exportPresetSave() + + // button press feedback... + var e = elem.find('.button small') + var text = e.text() + var reset = function(){ + e.text(text) } + e.text('Saved.') + e.one('mouseout', reset) + setTimeout(reset, 2000) + + make.dialog.trigger('save-preset') + }] ], }) make.done() @@ -3100,6 +3117,7 @@ var FileSystemWriterUIActions = actions.Actions({ // XXX add a 'name' field to the exportDialog(..)??? // XXX button icons... // XXX button shortcuts... + // XXX handle presets with repeating titles... exportPresets: ['- File/Export history...', widgets.makeUIDialog(function(mode){ var that = this @@ -3109,29 +3127,32 @@ var FileSystemWriterUIActions = actions.Actions({ var getName = function(preset){ return preset.name || `${ preset.mode }: "${ preset.path }"` } + var buildIndex = function(presets){ + var index + return [ + // index... + (index = presets + .reduce(function(res, e, i){ + res[getName(e)] = i + return res }, {})), + // keys... + Object.keys(index), ] } + var getPreset = function(title, presets, index){ + return presets[index[title]] } // 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) + var [index, keys] = buildIndex(presets) // history... // XXX var history = [] - var history_index = {} - var history_keys = Object.keys(history_index) - - var getPreset = function(title, presets, index){ - return presets[index[title]] } + var [history_index, history_keys] = buildIndex(history) return browse.makeLister(null, function(path, make){ // preset list... - keys.length == 0 ? - make.Empty('No presets...') - : make.EditableList(keys, { + keys.length > 0 + && make.EditableList(keys, { list_id: 'presets', sortable: true, update_merge: 'live', @@ -3140,7 +3161,7 @@ var FileSystemWriterUIActions = actions.Actions({ allow_empty: true, itemedit: function(evt, from, to){ var preset = getPreset(from, presets, index) - // clear... + // reset... if(to.trim() == ''){ delete preset.name to = keys[keys.indexOf(from)] = getName(preset) @@ -3158,18 +3179,32 @@ var FileSystemWriterUIActions = actions.Actions({ function(){ make.dialog.select(to) }) }, buttons: [ - ['edit', function(title){ - var preset = getPreset(title, presets, index) - that.exportDialog(preset) - .close(function(){ - 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() } })}], + // edit... + ['edit', + function(title){ + var preset = getPreset(title, presets, index) + that.exportDialog(preset) + .close(function(){ + 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() } })}], + // duplicate... + ['', + function(title){ + var preset = JSON.parse( + JSON.stringify( + getPreset(title, presets, index) )) + preset.name = title + ' (copy)' + // place preset in list... + var i = index[preset.name] = index[title]+1 + presets.splice(i, 0, preset) + keys.splice(keys.indexOf(title)+1, 0, preset.name) + make.dialog.update() }], ['♦', 'TO_TOP'], 'REMOVE'], // export... @@ -3188,6 +3223,14 @@ var FileSystemWriterUIActions = actions.Actions({ make('E$xport...', { open: function(){ that.exportDialog() + // new preset saved... + .on('save-preset', function(){ + var [idx, k] = buildIndex(presets) + index = idx + // NOTE: keys must be updated in-place... + keys.splice(0, keys.length, ...k) + make.dialog.update() }) + // close dialog on export... .close(function(evt, reason){ reason != 'reject' && make.dialog.close() }) }, }) @@ -3196,16 +3239,17 @@ var FileSystemWriterUIActions = actions.Actions({ make.Separator() history.length == 0 ? make.Empty('No export history...') - : ake.EditableList(history, { + : ake.EditableList(history_keys, { list_id: 'history', sortable: false, new_item: false, editable_items: false, buttons: [ // to preset... - ['P', function(){ - // XXX - }], + ['save', + function(){ + // XXX + }], 'REMOVE', ], // XXX export... @@ -3220,7 +3264,17 @@ var FileSystemWriterUIActions = actions.Actions({ this.keyboard.on('E', function(){ console.log('!!!!!!!!!!!!!', that.selected) }) - }) })], + }) + .close(function(){ + // update preset order and count... + that.config['export-presets'] = keys + .map(function(e){ + return getPreset(e, presets, index) }) + // handle history delete... + history.length != that.config['export-history'] + && that.config['export-history'] = history_keys + .map(function(e){ + return getPreset(e, history, history_index) }) }) })], // XXX these do note need the ui -- move to a separate feature... // XXX these are essentially the same as the history API, make a @@ -3235,7 +3289,7 @@ var FileSystemWriterUIActions = actions.Actions({ && (this.config['export-presets'] = this.config['export-presets'] || []) - .push(settings) }], + .push(JSON.parse(JSON.stringify( settings ))) }], // XXX need a way to reference a preset... exportPresetDelete: ['- File/', @@ -3255,7 +3309,7 @@ var FileSystemWriterUIActions = actions.Actions({ // add... // XXX need to check item uniqueness... settings - && history.push(settings) + && history.push(JSON.parse(JSON.stringify( settings ))) // trim the history... history.length > l && history.splice(0, history.length - l) }], diff --git a/Viewer/lib/widget/browse.js b/Viewer/lib/widget/browse.js index d964b277..f555605f 100755 --- a/Viewer/lib/widget/browse.js +++ b/Viewer/lib/widget/browse.js @@ -102,8 +102,7 @@ function(msg, options){ : true options.cls = (options.cls || '') + ' empty-msg' msg = msg || options.message || 'Empty...' - return this(msg, options) -} + return this(msg, options) } // NOTE: this is the same as make('---'[, options]) @@ -141,8 +140,7 @@ Items.Action = function(text, options){ options = Object.create(options || {}) options.cls = (options.cls || '') + ' action' - return this(text, options) -} + return this(text, options) } // Action requiring confirmation... // @@ -205,10 +203,7 @@ function(text, options){ // confirmed... } else { - callback && callback() - } - }) -} + callback && callback() } }) } // Item with auto selected text on select... // @@ -245,8 +240,7 @@ function(text, options){ text.selectText() }) - return elem -} + return elem } // Editable item or it's part... // @@ -385,8 +379,7 @@ function(text, options){ && elem .on(stop_propagation, function(e){ e.stopPropagation() }) - return elem -} + return elem } @@ -419,8 +412,7 @@ function(list){ .addClass('item-group') .appendTo($(res).parent()) .append($(res)) - return group -} + return group } // List of elements... @@ -516,19 +508,14 @@ function(data, options){ // no match -- restore text... } else { - txt = k - } - } - }) + txt = k } } }) if(opts.disabled && opts.disabled instanceof Array){ - opts.disabled = opts.disabled.indexOf(txt || k) >= 0 - } + opts.disabled = opts.disabled.indexOf(txt || k) >= 0 } if((opts.disabled && opts.skipDisabledItems) || (opts.hidden && opts.skipHiddenItems)){ - return - } + return } var elem = make(txt || k, opts) @@ -538,13 +525,11 @@ function(data, options){ opts.each && opts.each.call(elem, txt || k) - res.push(elem[0]) - }) + res.push(elem[0]) }) return options.groupList ? make.Group(res).children() - : $(res) -} + : $(res) } // Editable list of elements... @@ -1296,23 +1281,20 @@ function(list, pins, options){ // unpin... } else { - pins.splice(pins.indexOf(p), 1) - } + pins.splice(pins.indexOf(p), 1) } // XXX this is slow... that.dialog .update() .then(function(){ - that.dialog.trigger('pin_button', p, cur) - }) + that.dialog.trigger('pin_button', p, cur) }) }] ;[buttons, pins_buttons] .forEach(function(b){ var i = b.indexOf('PIN') i < 0 ? b.push(pin) - : (b[i] = pin) - }) + : (b[i] = pin) }) options.isItemHidden = function(e){ return pins.indexOf(e) >= 0 } options.skipHiddenItems = options.skipHiddenItems !== false ? true : false @@ -1333,8 +1315,7 @@ function(list, pins, options){ if(!sortable){ pins_options.sort = options.sort instanceof Function ? options.sort - : pins.sortAs(dialog.__list[id]) - } + : pins.sortAs(dialog.__list[id]) } //---------------------------------------------- build the list --- var res = this.EditableList(pins, pins_options) @@ -1350,8 +1331,7 @@ function(list, pins, options){ options) .toArray()) - return $(res) -} + return $(res) } @@ -1383,10 +1363,7 @@ Buttons.markForRemoval = function(list, html){ } else { var i = list.indexOf(p) i >= 0 - && list.splice(i, 1) - } - }] -} + && list.splice(i, 1) } }] } @@ -1688,6 +1665,7 @@ var BrowserPrototype = { 'open', 'menu', 'update', + 'close', ], // Shorthand elements... @@ -2252,6 +2230,7 @@ var BrowserPrototype = { // open: , // menu: , // update: , + // close: , // // // event handlers... // events: {