mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
reworked collections to use the full .data.order...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
4d26fca249
commit
861cef15b8
@ -1474,10 +1474,15 @@ module.CropActions = actions.Actions({
|
|||||||
|
|
||||||
Make a crop and use the given data object...
|
Make a crop and use the given data object...
|
||||||
NOTE: data must be an instance of data.Data
|
NOTE: data must be an instance of data.Data
|
||||||
|
NOTE: this will overwrite data.tags with this.data.tags
|
||||||
.crop(data)
|
.crop(data)
|
||||||
.crop(data, true)
|
|
||||||
-> this
|
-> 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
|
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
|
there is no need to bind to anything but this to handle a
|
||||||
crop unless specific action is required for a specific crop
|
crop unless specific action is required for a specific crop
|
||||||
@ -1489,12 +1494,14 @@ module.CropActions = actions.Actions({
|
|||||||
function(list, flatten){
|
function(list, flatten){
|
||||||
list = list || this.data.getImages()
|
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)
|
this.crop_stack.push(this.data)
|
||||||
|
|
||||||
if(list instanceof data.Data){
|
if(list instanceof data.Data){
|
||||||
|
if(flatten === false){
|
||||||
|
list.tags = this.data.tags
|
||||||
|
}
|
||||||
|
|
||||||
this.data = list
|
this.data = list
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -24,7 +24,6 @@ var widgets = require('features/ui-widgets')
|
|||||||
// XXX should collections be in the Crop menu????
|
// XXX should collections be in the Crop menu????
|
||||||
|
|
||||||
// XXX things we need to do to collections:
|
// XXX things we need to do to collections:
|
||||||
// - remove images (from collection) ????
|
|
||||||
// - auto-collections
|
// - auto-collections
|
||||||
// - tags -- adding/removing images adds/removes tags
|
// - tags -- adding/removing images adds/removes tags
|
||||||
// - ribbons -- top / bottom / n-m / top+2 / ..
|
// - ribbons -- top / bottom / n-m / top+2 / ..
|
||||||
@ -40,8 +39,21 @@ var widgets = require('features/ui-widgets')
|
|||||||
// locations:
|
// locations:
|
||||||
// - collection specific stuff (data) to collection path
|
// - collection specific stuff (data) to collection path
|
||||||
// - global stuff (images, tags, ...) to base index...
|
// - 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({
|
var CollectionActions = actions.Actions({
|
||||||
|
|
||||||
|
// Format:
|
||||||
|
// {
|
||||||
|
// <title>: {
|
||||||
|
// title: <title>,
|
||||||
|
// gid: <gid>,
|
||||||
|
// data: <data>,
|
||||||
|
// ...
|
||||||
|
// },
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
collections: null,
|
collections: null,
|
||||||
|
|
||||||
get collection(){
|
get collection(){
|
||||||
@ -49,7 +61,30 @@ var CollectionActions = actions.Actions({
|
|||||||
set collection(value){
|
set collection(value){
|
||||||
this.loadCollection(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/',
|
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){
|
function(collection){
|
||||||
if(collection == null
|
if(collection == null
|
||||||
|| this.collections == null
|
|| this.collections == null
|
||||||
@ -57,8 +92,33 @@ var CollectionActions = actions.Actions({
|
|||||||
return
|
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/',
|
saveCollection: ['- Collections/',
|
||||||
core.doc`Save current state to collection
|
core.doc`Save current state to collection
|
||||||
|
|
||||||
@ -71,6 +131,7 @@ var CollectionActions = actions.Actions({
|
|||||||
-> this
|
-> this
|
||||||
`,
|
`,
|
||||||
function(collection, empty){
|
function(collection, empty){
|
||||||
|
var that = this
|
||||||
collection = collection || this.collection
|
collection = collection || this.collection
|
||||||
|
|
||||||
if(collection == null){
|
if(collection == null){
|
||||||
@ -82,12 +143,12 @@ var CollectionActions = actions.Actions({
|
|||||||
collections[collection] = {
|
collections[collection] = {
|
||||||
title: collection,
|
title: collection,
|
||||||
|
|
||||||
// XXX we need to trim .order to only the current images???
|
// NOTE: we do not need to care about tags here as they
|
||||||
data: empty ?
|
// will get overwritten on load...
|
||||||
|
data: (empty ?
|
||||||
(new this.data.constructor())
|
(new this.data.constructor())
|
||||||
: this.data
|
: this.data
|
||||||
.clone()
|
.crop())
|
||||||
.removeUnloadedGIDs()
|
|
||||||
.run(function(){
|
.run(function(){
|
||||||
this.collection = collection
|
this.collection = collection
|
||||||
}),
|
}),
|
||||||
@ -104,7 +165,8 @@ var CollectionActions = actions.Actions({
|
|||||||
return Object.keys(this.collections || {})
|
return Object.keys(this.collections || {})
|
||||||
.filter(function(c){
|
.filter(function(c){
|
||||||
return !gid
|
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/',
|
collect: ['- Collections/',
|
||||||
@ -196,14 +258,27 @@ var CollectionActions = actions.Actions({
|
|||||||
return
|
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){
|
if(this.collection == collection){
|
||||||
this.data
|
this.data
|
||||||
.removeGIDs(gids)
|
.run(hideGIDs)
|
||||||
.removeEmptyRibbons()
|
.removeEmptyRibbons()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.collections[collection].data
|
this.collections[collection].data
|
||||||
.removeGIDs(gids)
|
.run(hideGIDs)
|
||||||
.removeEmptyRibbons()
|
.removeEmptyRibbons()
|
||||||
}],
|
}],
|
||||||
|
|
||||||
@ -216,15 +291,19 @@ var CollectionActions = actions.Actions({
|
|||||||
// manage serialization and loading...
|
// manage serialization and loading...
|
||||||
// XXX make this reflect the format automatically...
|
// XXX make this reflect the format automatically...
|
||||||
load: [function(json){
|
load: [function(json){
|
||||||
|
var that = this
|
||||||
var collections = {}
|
var collections = {}
|
||||||
var c = json.collections || {}
|
var c = json.collections || {}
|
||||||
|
|
||||||
Object.keys(c).forEach(function(title){
|
Object.keys(c).forEach(function(title){
|
||||||
|
var data = data.Data
|
||||||
|
.fromJSON(c[title].data)
|
||||||
|
|
||||||
// XXX make this reflect the format automatically...
|
// XXX make this reflect the format automatically...
|
||||||
collections[title] = {
|
collections[title] = {
|
||||||
title: title,
|
title: title,
|
||||||
|
|
||||||
data: data.Data.fromJSON(c[title].data)
|
data: data,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -237,17 +316,22 @@ var CollectionActions = actions.Actions({
|
|||||||
if(collections){
|
if(collections){
|
||||||
res.collections = {}
|
res.collections = {}
|
||||||
Object.keys(this.collections).forEach(function(title){
|
Object.keys(this.collections).forEach(function(title){
|
||||||
|
var data = collections[title].data.dumpJSON()
|
||||||
|
delete data.tags
|
||||||
|
|
||||||
// XXX make this reflect the format automatically...
|
// XXX make this reflect the format automatically...
|
||||||
res.collections[title] = {
|
res.collections[title] = {
|
||||||
title: title,
|
title: title,
|
||||||
|
|
||||||
data: collections[title].data.dumpJSON()
|
data: data,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} }],
|
} }],
|
||||||
clear: [function(){
|
clear: [function(){
|
||||||
|
this.collectionUnloaded('*')
|
||||||
delete this.collections
|
delete this.collections
|
||||||
|
delete this.location.collection
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -272,15 +356,18 @@ module.Collection = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
handlers: [
|
handlers: [
|
||||||
// maintain the .collection state...
|
// maintain the .collection state...
|
||||||
// XXX not yet sure if this is the right way to go...
|
['uncrop.pre',
|
||||||
['loadCollection',
|
|
||||||
function(_, collection){
|
|
||||||
if(this.collections && collection in this.collections){
|
|
||||||
this.data.collection = this.location.collection = collection
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
['uncrop',
|
|
||||||
function(){
|
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
|
var collection = this.location.collection = this.data.collection
|
||||||
|
|
||||||
// cleanup...
|
// cleanup...
|
||||||
@ -426,10 +513,11 @@ var UICollectionActions = actions.Actions({
|
|||||||
return this.browseCollections(function(title){
|
return this.browseCollections(function(title){
|
||||||
this.joinCollect(title) }) })],
|
this.joinCollect(title) }) })],
|
||||||
|
|
||||||
// XXX this is not used by metadata yet...
|
/*/ XXX this is not used by metadata yet...
|
||||||
metadataSection: ['- Image/',
|
metadataSection: ['- Image/',
|
||||||
function(gid, make){
|
function(gid, make){
|
||||||
}],
|
}],
|
||||||
|
//*/
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -463,6 +551,13 @@ module.UICollection = core.ImageGridFeatures.Feature({
|
|||||||
// - lazy load collections (load list, lazy-load data)
|
// - lazy load collections (load list, lazy-load data)
|
||||||
// - load directories as collections...
|
// - load directories as collections...
|
||||||
// - export collections to directories...
|
// - export collections to directories...
|
||||||
|
|
||||||
|
// XXX lazy load collections...
|
||||||
|
var FileSystemCollectionActions = actions.Actions({
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
var FileSystemCollection =
|
var FileSystemCollection =
|
||||||
module.FileSystemCollection = core.ImageGridFeatures.Feature({
|
module.FileSystemCollection = core.ImageGridFeatures.Feature({
|
||||||
title: '',
|
title: '',
|
||||||
@ -470,11 +565,61 @@ module.FileSystemCollection = core.ImageGridFeatures.Feature({
|
|||||||
|
|
||||||
tag: 'fs-collections',
|
tag: 'fs-collections',
|
||||||
depends: [
|
depends: [
|
||||||
|
'index-format',
|
||||||
'fs',
|
'fs',
|
||||||
'collections',
|
'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
|
||||||
|
}],
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,6 @@ core.ImageGridFeatures.Feature('viewer-commandline', [
|
|||||||
core.ImageGridFeatures.Feature('viewer-minimal', [
|
core.ImageGridFeatures.Feature('viewer-minimal', [
|
||||||
'lifecycle',
|
'lifecycle',
|
||||||
'base-full',
|
'base-full',
|
||||||
'collections',
|
|
||||||
|
|
||||||
'peer',
|
'peer',
|
||||||
|
|
||||||
@ -51,6 +50,12 @@ core.ImageGridFeatures.Feature('viewer-testing', [
|
|||||||
'viewer-commandline',
|
'viewer-commandline',
|
||||||
'viewer-minimal',
|
'viewer-minimal',
|
||||||
|
|
||||||
|
'collections',
|
||||||
|
|
||||||
|
// XXX remove when done testing...
|
||||||
|
'-fs-collections',
|
||||||
|
|
||||||
|
|
||||||
'alias',
|
'alias',
|
||||||
|
|
||||||
// read-only mode...
|
// read-only mode...
|
||||||
|
|||||||
@ -1293,9 +1293,11 @@ var DataPrototype = {
|
|||||||
//
|
//
|
||||||
// XXX needs more thought....
|
// XXX needs more thought....
|
||||||
// do we need to move images by this???
|
// 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
|
from = from != null && from.constructor !== Array ? [from] : from
|
||||||
|
|
||||||
|
var r = this.getRibbon('current')
|
||||||
|
|
||||||
this.eachImageList(function(cur, key, set){
|
this.eachImageList(function(cur, key, set){
|
||||||
set = this[set]
|
set = this[set]
|
||||||
|
|
||||||
@ -1323,6 +1325,11 @@ var DataPrototype = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// maintain focus...
|
||||||
|
if(from.indexOf(this.current) >= 0){
|
||||||
|
this.focusImage('r')
|
||||||
|
}
|
||||||
|
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2550,6 +2557,10 @@ var DataPrototype = {
|
|||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************** Cleanup and removal ***/
|
||||||
|
|
||||||
// Remove empty ribbons...
|
// Remove empty ribbons...
|
||||||
//
|
//
|
||||||
removeEmptyRibbons: function(){
|
removeEmptyRibbons: function(){
|
||||||
@ -2608,6 +2619,8 @@ var DataPrototype = {
|
|||||||
// Remove GIDs...
|
// Remove GIDs...
|
||||||
//
|
//
|
||||||
// NOTE: this may result in empty ribbons...
|
// 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){
|
removeGIDs: function(gids, direction){
|
||||||
var that = this
|
var that = this
|
||||||
gids = gids || []
|
gids = gids || []
|
||||||
@ -2628,15 +2641,12 @@ var DataPrototype = {
|
|||||||
// attempt to first get next/prev within the current ribbon...
|
// attempt to first get next/prev within the current ribbon...
|
||||||
r = r.length > 0 ? r : order
|
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.getImage(this.current, direction == 'after' ? 'before' : 'after', r)
|
||||||
|
|
||||||
this.current = cur
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.order = order
|
this.order = order
|
||||||
this
|
this.updateImagePositions()
|
||||||
.updateImagePositions()
|
|
||||||
|
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user