diff --git a/ui (gen4)/features/base.js b/ui (gen4)/features/base.js
index 99a2f350..976eb267 100755
--- a/ui (gen4)/features/base.js
+++ b/ui (gen4)/features/base.js
@@ -1474,10 +1474,15 @@ module.CropActions = actions.Actions({
Make a crop and use the given data object...
NOTE: data must be an instance of data.Data
+ NOTE: this will overwrite data.tags with this.data.tags
.crop(data)
- .crop(data, true)
-> this
+ Make a crop and use the given data object but keep data.tags...
+ .crop(data, false)
+ -> this
+
+
NOTE: this is used as a basis for all the crop operations, so
there is no need to bind to anything but this to handle a
crop unless specific action is required for a specific crop
@@ -1489,13 +1494,15 @@ module.CropActions = actions.Actions({
function(list, flatten){
list = list || this.data.getImages()
- if(this.crop_stack == null){
- this.crop_stack = []
- }
+ this.crop_stack = this.crop_stack || []
this.crop_stack.push(this.data)
if(list instanceof data.Data){
- this.data = list
+ if(flatten === false){
+ list.tags = this.data.tags
+ }
+
+ this.data = list
} else {
this.data = this.data.crop(list, flatten)
diff --git a/ui (gen4)/features/collections.js b/ui (gen4)/features/collections.js
index 7d926953..68e8e3b5 100755
--- a/ui (gen4)/features/collections.js
+++ b/ui (gen4)/features/collections.js
@@ -24,7 +24,6 @@ var widgets = require('features/ui-widgets')
// XXX should collections be in the Crop menu????
// XXX things we need to do to collections:
-// - remove images (from collection) ????
// - auto-collections
// - tags -- adding/removing images adds/removes tags
// - ribbons -- top / bottom / n-m / top+2 / ..
@@ -40,8 +39,21 @@ var widgets = require('features/ui-widgets')
// locations:
// - collection specific stuff (data) to collection path
// - global stuff (images, tags, ...) to base index...
+// XXX handle tags here???
+// ...keep them global or local to collection???
+// global sounds better...
var CollectionActions = actions.Actions({
+ // Format:
+ // {
+ //
: {
+ // title: ,
+ // gid: ,
+ // data: ,
+ // ...
+ // },
+ // ...
+ // }
collections: null,
get collection(){
@@ -49,7 +61,30 @@ var CollectionActions = actions.Actions({
set collection(value){
this.loadCollection(value) },
+ // XXX need a way to prevent multiple loads...
+ // ...checking if .collection is set to collection is logical but
+ // may prevent reloading of collections -- i.e. loading a collection
+ // anew if it is already loaded...
+ // XXX doc the protocol...
loadCollection: ['- Collections/',
+ core.doc`Load collection...
+
+ This will get collection data and crop into it.
+
+ If .data for a collection is not available this will do nothing,
+ this enables extending actions to handle the collection in
+ different ways.
+
+ The extending action if compatible must:
+ - construct data
+ - load data via:
+ this.crop(data)
+ - when done call:
+ this.collectionLoaded(collection)
+
+ XXX would be good to have a way to check if loading was done
+ within this .loadCollection(..) call...
+ `,
function(collection){
if(collection == null
|| this.collections == null
@@ -57,8 +92,33 @@ var CollectionActions = actions.Actions({
return
}
- this.crop(this.collections[collection].data)
+ var data = this.collections[collection].data
+
+ data
+ && this.crop(data)
+ && this.collectionLoaded(collection)
}],
+
+ collectionLoaded: ['- Collections/',
+ core.doc`This is called by .loadCollection(..) or one of the
+ overloading actions when collection load is done...
+
+ `,
+ core.notUserCallable(function(collection){
+ // This is the window resize event...
+ //
+ // Not for direct use.
+ this.data.collection = this.location.collection = collection
+ })],
+ collectionUnloaded: ['- Collections/',
+ core.doc`This is called when unloading a collection.
+ `,
+ core.notUserCallable(function(collection){
+ // This is the window resize event...
+ //
+ // Not for direct use.
+ })],
+
saveCollection: ['- Collections/',
core.doc`Save current state to collection
@@ -71,6 +131,7 @@ var CollectionActions = actions.Actions({
-> this
`,
function(collection, empty){
+ var that = this
collection = collection || this.collection
if(collection == null){
@@ -82,15 +143,15 @@ var CollectionActions = actions.Actions({
collections[collection] = {
title: collection,
- // XXX we need to trim .order to only the current images???
- data: empty ?
- (new this.data.constructor())
- : this.data
- .clone()
- .removeUnloadedGIDs()
- .run(function(){
- this.collection = collection
- }),
+ // NOTE: we do not need to care about tags here as they
+ // will get overwritten on load...
+ data: (empty ?
+ (new this.data.constructor())
+ : this.data
+ .crop())
+ .run(function(){
+ this.collection = collection
+ }),
}
}],
newCollection: ['- Collections/',
@@ -104,7 +165,8 @@ var CollectionActions = actions.Actions({
return Object.keys(this.collections || {})
.filter(function(c){
return !gid
- || that.collections[c].data.order.indexOf(gid) >= 0 })
+ || that.collections[c].data.getImage(gid) })
+ //|| that.collections[c].data.order.indexOf(gid) >= 0 })
}],
collect: ['- Collections/',
@@ -196,14 +258,27 @@ var CollectionActions = actions.Actions({
return
}
+ // NOTE: we are not using .data.updateImagePositions(gids, 'hide')
+ // here because it will remove the gids from everything
+ // while we need them removed only from ribbons...
+ var hideGIDs = function(){
+ var d = this
+ gids.forEach(function(gid){
+ var i = d.order.indexOf(gid)
+ Object.keys(d.ribbons).forEach(function(r){
+ delete d.ribbons[r][i]
+ })
+ })
+ }
+
if(this.collection == collection){
this.data
- .removeGIDs(gids)
+ .run(hideGIDs)
.removeEmptyRibbons()
}
this.collections[collection].data
- .removeGIDs(gids)
+ .run(hideGIDs)
.removeEmptyRibbons()
}],
@@ -216,15 +291,19 @@ var CollectionActions = actions.Actions({
// manage serialization and loading...
// XXX make this reflect the format automatically...
load: [function(json){
+ var that = this
var collections = {}
var c = json.collections || {}
Object.keys(c).forEach(function(title){
- // XXX make this reflect the format automatically...
+ var data = data.Data
+ .fromJSON(c[title].data)
+
+ // XXX make this reflect the format automatically...
collections[title] = {
title: title,
- data: data.Data.fromJSON(c[title].data)
+ data: data,
}
})
@@ -237,17 +316,22 @@ var CollectionActions = actions.Actions({
if(collections){
res.collections = {}
Object.keys(this.collections).forEach(function(title){
+ var data = collections[title].data.dumpJSON()
+ delete data.tags
+
// XXX make this reflect the format automatically...
res.collections[title] = {
title: title,
- data: collections[title].data.dumpJSON()
+ data: data,
}
})
}
} }],
clear: [function(){
+ this.collectionUnloaded('*')
delete this.collections
+ delete this.location.collection
}],
})
@@ -272,15 +356,18 @@ module.Collection = core.ImageGridFeatures.Feature({
handlers: [
// maintain the .collection state...
- // XXX not yet sure if this is the right way to go...
- ['loadCollection',
- function(_, collection){
- if(this.collections && collection in this.collections){
- this.data.collection = this.location.collection = collection
- }
- }],
- ['uncrop',
+ ['uncrop.pre',
function(){
+ var collection = this.collection
+ return function(){
+ collection != this.data.collection
+ && this.collectionUnloaded(collection) }
+ }],
+ ['collectionLoaded',
+ function(){
+ }],
+ ['collectionUnloaded',
+ function(collection){
var collection = this.location.collection = this.data.collection
// cleanup...
@@ -426,10 +513,11 @@ var UICollectionActions = actions.Actions({
return this.browseCollections(function(title){
this.joinCollect(title) }) })],
- // XXX this is not used by metadata yet...
+ /*/ XXX this is not used by metadata yet...
metadataSection: ['- Image/',
function(gid, make){
}],
+ //*/
})
@@ -463,6 +551,13 @@ module.UICollection = core.ImageGridFeatures.Feature({
// - lazy load collections (load list, lazy-load data)
// - load directories as collections...
// - export collections to directories...
+
+// XXX lazy load collections...
+var FileSystemCollectionActions = actions.Actions({
+
+})
+
+
var FileSystemCollection =
module.FileSystemCollection = core.ImageGridFeatures.Feature({
title: '',
@@ -470,11 +565,61 @@ module.FileSystemCollection = core.ImageGridFeatures.Feature({
tag: 'fs-collections',
depends: [
+ 'index-format',
'fs',
'collections',
],
- handlers: [],
+ actions: FileSystemCollectionActions,
+
+ handlers: [
+ // XXX maintain changes...
+ // XXX
+ [[
+ 'collect',
+ 'joinCollect',
+ 'uncollect',
+
+ 'saveCollection',
+
+ 'removeCollection',
+ ],
+ function(){
+ // XXX mark changed collections...
+ // XXX added/removed collection -> mark collection index as changed...
+ }],
+
+ // XXX handle removed collections -- move to trash (???)
+ // ...might be a good idea to add something like index gc API...
+ ['prepareIndexForWrite',
+ function(res, _, full){
+ var changed = full == true
+ || res.changes === true
+ || res.changes.collections
+
+ if(changed && res.raw.collections){
+ // select the actual changed collection list...
+ changed = changed === true ?
+ Object.keys(res.raw.collections)
+ : changed
+
+ // collection index...
+ res.index['collection-index'] = Object.keys(this.collections)
+
+ Object.keys(changed)
+ // skip the raw field...
+ .filter(function(k){ return changed.indexOf(k) >= 0 })
+ .forEach(function(k){
+ // XXX use collection gid...
+ res.index['collections/' + k] = res.raw.collections[k]
+ })
+ }
+ }],
+ ['prepareJSONForLoad',
+ function(res, json){
+ // XXX
+ }],
+ ],
})
diff --git a/ui (gen4)/features/meta.js b/ui (gen4)/features/meta.js
index 52bcc5ab..d81a2b98 100755
--- a/ui (gen4)/features/meta.js
+++ b/ui (gen4)/features/meta.js
@@ -33,7 +33,6 @@ core.ImageGridFeatures.Feature('viewer-commandline', [
core.ImageGridFeatures.Feature('viewer-minimal', [
'lifecycle',
'base-full',
- 'collections',
'peer',
@@ -51,6 +50,12 @@ core.ImageGridFeatures.Feature('viewer-testing', [
'viewer-commandline',
'viewer-minimal',
+ 'collections',
+
+ // XXX remove when done testing...
+ '-fs-collections',
+
+
'alias',
// read-only mode...
diff --git a/ui (gen4)/imagegrid/data.js b/ui (gen4)/imagegrid/data.js
index 778cad5f..63709c5a 100755
--- a/ui (gen4)/imagegrid/data.js
+++ b/ui (gen4)/imagegrid/data.js
@@ -1293,9 +1293,11 @@ var DataPrototype = {
//
// XXX needs more thought....
// do we need to move images by this???
- updateImagePositions: function(from, mode){
+ updateImagePositions: function(from, mode, direction){
from = from != null && from.constructor !== Array ? [from] : from
+ var r = this.getRibbon('current')
+
this.eachImageList(function(cur, key, set){
set = this[set]
@@ -1323,6 +1325,11 @@ var DataPrototype = {
}
})
+ // maintain focus...
+ if(from.indexOf(this.current) >= 0){
+ this.focusImage('r')
+ }
+
return this
},
@@ -2550,6 +2557,10 @@ var DataPrototype = {
return this
},
+
+
+ /***************************************** Cleanup and removal ***/
+
// Remove empty ribbons...
//
removeEmptyRibbons: function(){
@@ -2608,6 +2619,8 @@ var DataPrototype = {
// Remove GIDs...
//
// NOTE: this may result in empty ribbons...
+ // NOTE: to remove gids from lists but keep them in order use:
+ // .updateImagePositions(gids, 'hide')
removeGIDs: function(gids, direction){
var that = this
gids = gids || []
@@ -2628,15 +2641,12 @@ var DataPrototype = {
// attempt to first get next/prev within the current ribbon...
r = r.length > 0 ? r : order
- var cur = this.getImage(this.current, direction || 'before', r)
+ this.current = this.getImage(this.current, direction || 'before', r)
|| this.getImage(this.current, direction == 'after' ? 'before' : 'after', r)
-
- this.current = cur
}
this.order = order
- this
- .updateImagePositions()
+ this.updateImagePositions()
return this
},