diff --git a/ui (gen4)/features/collections.js b/ui (gen4)/features/collections.js index c1236531..56f56e19 100755 --- a/ui (gen4)/features/collections.js +++ b/ui (gen4)/features/collections.js @@ -10,16 +10,19 @@ var actions = require('lib/actions') var features = require('lib/features') +var browse = require('lib/widget/browse') + var core = require('features/core') +var widgets = require('features/ui-widgets') /*********************************************************************/ +// XXX should collections be in the Crop menu???? // XXX things we need to do to collections: // - add images from current state // - remove images (from collection) -// - check what collections is image in... var CollectionActions = actions.Actions({ collections: null, @@ -42,8 +45,7 @@ var CollectionActions = actions.Actions({ // locations: // - collection specific stuff (data) to collection path // - global stuff (images, tags, ...) to base index... - // XXX need to .reload() here... - loadCollection: ['-Collections/', + loadCollection: ['- Collections/', function(collection){ if(collection == null || this.collections == null @@ -71,20 +73,23 @@ var CollectionActions = actions.Actions({ title: collection, // XXX we need to trim .order to only the current images??? - data: this.data.clone(), + data: this.data + .clone() + .removeUnloadedGids(), } }], - inCollections: ['- Image/', core.doc`Get list of collections containing item`, function(gid){ var that = this return Object.keys(this.collections || {}) .filter(function(c){ - return that.collections[c].data.order.indexOf(gid) >= 0 }) + return !gid + || that.collections[c].data.order.indexOf(gid) >= 0 }) }], - toCollection: ['- Collections/', + + collect: ['- Collections/', core.doc`Add items to collection`, function(gids, collection){ var that = this @@ -98,13 +103,21 @@ var CollectionActions = actions.Actions({ : [gid] }) .reduce(function(a, b){ return a.concat(b) }, []) - console.log('>>>', gids) + collection = collection || this.collection // XXX add to collection... // XXX }], + uncollect: ['- Collections/', + function(gids, collection){ + // XXX + }], - + removeCollection: ['- Collections/', + function(collection){ + // XXX + delete this.collections[collection] + }], }) var Collection = @@ -117,6 +130,10 @@ module.Collection = core.ImageGridFeatures.Feature({ 'base', 'crop', ], + suggested: [ + 'ui-collections', + 'fs-collections', + ], actions: CollectionActions, @@ -125,5 +142,143 @@ module.Collection = core.ImageGridFeatures.Feature({ +//--------------------------------------------------------------------- + +// XXX show collections in image metadata... +var UICollectionActions = actions.Actions({ + // XXX highlight current collections.... + browseCollections: ['Collections/Collections...', + widgets.makeUIDialog(function(gid){ + var that = this + gid = gid != null ? this.data.getImage(gid) : gid + + var to_remove = [] + + return browse.makeLister(null, + function(path, make){ + var dialog = this + + //var collections = Object.keys(that.collections || {}) + var collections = that.inCollections(gid || null) + + make.EditableList(collections, + { + unique: true, + to_remove: to_remove, + itemopen: function(title){ + that.loadCollection(title) + gid + && that.focusImage(gid) + dialog.close() + }, + normalize: function(title){ + return title.trim() }, + check: function(title){ + return title.length > 0 }, + + itemadded: function(title){ + that.saveCollection(title) }, + }) + }) + .close(function(){ + to_remove.forEach(function(title){ + that.removeCollection(title) + }) + }) + })], + // XXX add kb handler??? + // XXX highlight current collections.... + // XXX this is very similar to .browseCollections(..), is this a problem??? + browseImageCollections: ['Image/Collections...', + {dialogTitle: 'Image Collections...'}, + widgets.makeUIDialog(function(gid){ + var that = this + gid = this.data.getImage(gid) + + var to_remove = [] + + return browse.makeLister(null, + function(path, make){ + var dialog = this + + var all = Object.keys(that.collections || {}) + var collections = that.inCollections(gid || null) + + // build the disabled list... + all.forEach(function(title){ + collections.indexOf(title) < 0 + && to_remove.push(title) + }) + + all.length > 0 ? + make.EditableList(all, + { + new_item: false, + to_remove: to_remove, + itemopen: function(title){ + that.loadCollection(title) + gid + && that.focusImage(gid) + dialog.close() + }, + }) + : make.Empty() + }) + .close(function(){ + to_remove.forEach(function(title){ + that.uncollect(gid, title) + }) + }) + })], + + // XXX this is not used by metadata yet... + metadataSection: ['- Image/', + function(gid, make){ + }], +}) + + +var UICollection = +module.UICollection = core.ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'ui-collections', + depends: [ + 'ui', + 'collections', + ], + + actions: UICollectionActions, + + handlers: [], +}) + + + +//--------------------------------------------------------------------- +// XXX +var FileSystemCollection = +module.FileSystemCollection = core.ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'fs-collections', + depends: [ + 'fs', + 'collections', + ], + + handlers: [], +}) + + + +//--------------------------------------------------------------------- +// XXX localstorage-collections (???) + + + + /********************************************************************** * vim:set ts=4 sw=4 : */ return module }) diff --git a/ui (gen4)/features/keyboard.js b/ui (gen4)/features/keyboard.js index 61573af1..34fdc035 100755 --- a/ui (gen4)/features/keyboard.js +++ b/ui (gen4)/features/keyboard.js @@ -1097,6 +1097,8 @@ var KeyboardUIActions = actions.Actions({ return dialog })], + // XXX this does not handle the passed container protocol... + // .editKeyboardBindings('Drawer') is broken... editKeyboardBindings: ['Interface/Keyboard bindings editor...', core.doc`Keyboard bindings editor... diff --git a/ui (gen4)/features/metadata.js b/ui (gen4)/features/metadata.js index cd0a304f..b3f5858d 100755 --- a/ui (gen4)/features/metadata.js +++ b/ui (gen4)/features/metadata.js @@ -336,6 +336,7 @@ var MetadataUIActions = actions.Actions({ // // XXX should we replace 'mode' with nested set of metadata??? // XXX make this support multiple images... + // XXX add support for .metadataSection(make) action to construct a section... showMetadata: ['Image/Metadata...', widgets.makeUIDialog(function(image, mode){ //function(image, mode){ diff --git a/ui (gen4)/features/ui-widgets.js b/ui (gen4)/features/ui-widgets.js index 5345ae4b..052efd3e 100755 --- a/ui (gen4)/features/ui-widgets.js +++ b/ui (gen4)/features/ui-widgets.js @@ -1361,7 +1361,7 @@ var BrowseActionsActions = actions.Actions({ Object.keys(paths).forEach(function(key){ // handle mode flag... var action = paths[key][0] - var mode = key.split(/^- /) + var mode = key.split(/^-\s*/) var path = mode.pop() mode = mode.length > 0 ? 'hidden' : null diff --git a/ui (gen4)/imagegrid/data.js b/ui (gen4)/imagegrid/data.js index 4e916822..6d67a988 100755 --- a/ui (gen4)/imagegrid/data.js +++ b/ui (gen4)/imagegrid/data.js @@ -2552,6 +2552,15 @@ var DataPrototype = { return this }, + // Remove unloaded gids... + // + // This removes: + // - images from .data that are not in any ribbon + removeUnloadedGids: function(){ + this.order = this.getImages('loaded') + return this + }, + /****************************************** JSON serialization ***/ diff --git a/ui (gen4)/lib/widget/browse.js b/ui (gen4)/lib/widget/browse.js index b158d2f6..4f290e37 100755 --- a/ui (gen4)/lib/widget/browse.js +++ b/ui (gen4)/lib/widget/browse.js @@ -569,6 +569,10 @@ function(data, options){ // // just use it for uniqueness testing... // unique: | function(value){ ... }, // +// // called when new item is added to list... +// // +// itemadded: function(value){ ... }, +// // // If true sort values... // // If function will be used as cmp for sorting... // sort: || function(a, b){ ... }, @@ -589,7 +593,7 @@ function(data, options){ // // list length limit is reached... // overflow: function(selected){ ... }, // -// // list if items to remove, if not given this will be maintained +// // list of items to remove, if not given this will be maintained // // internally // to_remove: null | , // @@ -938,6 +942,11 @@ function(list, options){ return } + // check if item pre-existed... + var preexisted = lst.indexOf(options.unique instanceof Function ? + options.unique(txt) + : txt) >= 0 + // add new value and sort list... lst.push(txt) @@ -950,6 +959,10 @@ function(list, options){ lst = lst.unique(options.unique) } + options.itemadded + && !(options.unique && preexisted) + && options.itemadded.call(dialog, txt) + // sort... if(options.sort){ lst = lst @@ -2018,7 +2031,7 @@ var BrowserPrototype = { // // // Finalize the dialog (optional)... - // - Call make.done() can optionally be called after all the itmes + // - Call make.done() can optionally be called after all the items // are created. This will update the dialog to align the // selected position. // This is useful for dialogs with async loading items.