refactoring...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2018-12-15 18:48:25 +03:00
parent fead30ce3d
commit 59d82686c8
4 changed files with 300 additions and 298 deletions

View File

@ -6,7 +6,6 @@
* - base * - base
* map to data and images * map to data and images
* - crop * - crop
* - tags
* - groups * - groups
* XXX experimental... * XXX experimental...
* *
@ -100,9 +99,7 @@ actions.Actions({
// Data... // Data...
get data(){ get data(){
var d = this.__data = this.__data || data.Data() return (this.__data = this.__data || data.Data()) },
return d
},
set data(value){ set data(value){
this.__data = value }, this.__data = value },
@ -154,8 +151,7 @@ actions.Actions({
get direction(){ get direction(){
return this._direction >= 0 ? 'right' return this._direction >= 0 ? 'right'
: this._direction < 0 ? 'left' : this._direction < 0 ? 'left'
: 'right' : 'right' },
},
set direction(value){ set direction(value){
// repeat last direction... // repeat last direction...
if(value == '!'){ if(value == '!'){
@ -473,7 +469,6 @@ actions.Actions({
has a slightly different signature to the above, this is done has a slightly different signature to the above, this is done
for simplicity... for simplicity...
`, `,
//function(img, list){ this.data.focusImage.apply(this.data, arguments) }],
function(img, list){ this.data.focusImage(...arguments) }], function(img, list){ this.data.focusImage(...arguments) }],
// Focuses a ribbon by selecting an image in it... // Focuses a ribbon by selecting an image in it...
// //
@ -1006,45 +1001,30 @@ actions.Actions({
// basic image editing... // basic image editing...
// //
// Rotate image...
//
// Rotate current image clockwise...
// .rotate()
// .rotate('cw')
// -> actions
//
// Rotate current image counterclockwise...
// .rotate('ccw')
// -> actions
//
// Rotate target image clockwise...
// .rotate(target)
// .rotate(target, 'cw')
// -> actions
//
// Rotate target image counterclockwise...
// .rotate(target, 'ccw')
// -> actions
//
//
// Flip is similar...
//
// Flip current image ('horizontal' is default)...
// .flip()
// .flip('horizontal')
// .flip('vertical')
// -> actions
//
// Flip target...
// .flip(target)
// .flip(target, 'horizontal')
// .flip(target, 'vertical')
// -> actions
//
//
// NOTE: target must be .data.getImage(..) compatible, see it for docs...
// XXX correct undo??? // XXX correct undo???
rotate: ['- Image|Edit/Rotate image', rotate: ['- Image|Edit/Rotate image',
core.doc`Rotate image...
Rotate current image clockwise...
.rotate()
.rotate('cw')
-> actions
Rotate current image counterclockwise...
.rotate('ccw')
-> actions
Rotate target image clockwise...
.rotate(target)
.rotate(target, 'cw')
-> actions
Rotate target image counterclockwise...
.rotate(target, 'ccw')
-> actions
NOTE: target must be .data.getImage(..) compatible, see it for docs...
`,
{journal: true}, {journal: true},
function(target, direction){ function(target, direction){
if(arguments.length == 0){ if(arguments.length == 0){
@ -1060,6 +1040,22 @@ actions.Actions({
&& this.images.rotateImage(target, direction || 'cw') && this.images.rotateImage(target, direction || 'cw')
}], }],
flip: ['- Image|Edit/Flip image', flip: ['- Image|Edit/Flip image',
core.doc`Flip image...
Flip current image ('horizontal' is default)...
.flip()
.flip('horizontal')
.flip('vertical')
-> actions
Flip target...
.flip(target)
.flip(target, 'horizontal')
.flip(target, 'vertical')
-> actions
NOTE: target must be .data.getImage(..) compatible, see it for docs...
`,
{journal: true}, {journal: true},
function(target, direction){ function(target, direction){
if(target == 'vertical' || target == 'horizontal'){ if(target == 'vertical' || target == 'horizontal'){
@ -1164,256 +1160,6 @@ core.ImageGridFeatures.Feature({
//---------------------------------------------------------------------
// Tags...
// mode can be:
// "ribbon" - next marked in current ribbon (default)
// "all" - next marked in sequence
//
// XXX add support for tag lists...
var makeTagWalker =
module.makeTagWalker =
function(direction, dfl_tag){
var meth = direction == 'next' ? 'nextImage' : 'prevImage'
return function(tag, mode){
this[meth](this.data.tags.values(tag || dfl_tag), mode) } }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var TagsActions =
module.TagsActions = actions.Actions({
prevTagged: ['- Navigate/Previous image tagged with tag',
makeTagWalker('prev')],
nextTagged: ['- Navigate/Next image tagged with tag',
makeTagWalker('next')],
})
var Tags =
module.Tags = core.ImageGridFeatures.Feature({
title: '',
tag: 'tags',
depends: [
'base',
],
suggested: [
'tags-edit',
],
actions: TagsActions,
})
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
var TagsEditActions =
module.TagsEditActions = actions.Actions({
// tags...
//
// XXX mark updated...
tag: ['- Tag/Tag image(s)',
{journal: true},
function(tags, gids){
gids = gids || this.current
gids = gids instanceof Array ? gids : [gids]
// XXX this is slow for very large data sets...
gids = this.data.getImages(gids)
tags = tags instanceof Array ? tags : [tags]
var that = this
if(gids.length == 0){
return
}
// data...
this.data.tag(tags, gids)
// images...
var images = this.images
gids.forEach(function(gid){
var img = images[gid] = images[gid] || {}
img.tags = img.tags || []
img.tags = img.tags.concat(tags).unique()
// XXX mark updated...
})
}],
// XXX mark updated...
untag: ['- Tag/Untag image(s)',
{journal: true},
function(tags, gids){
gids = gids || this.current
gids = gids instanceof Array ? gids : [gids]
tags = tags instanceof Array ? tags : [tags]
// data...
this.data.untag(tags, gids)
// images...
var images = this.images
gids.forEach(function(gid){
var img = images[gid]
if(img == null || img.tags == null){
return
}
img.tags = img.tags.filter(function(tag){ return tags.indexOf(tag) < 0 })
if(img.tags.length == 0){
delete img.tags
}
// XXX mark updated...
})
}],
// Sync tags...
//
// Sync both ways...
// .syncTags()
// .syncTags('both')
//
// Sync from .data
// .syncTags('data')
//
// Sync from .images
// .syncTags('images')
//
// Sync from <images> object
// .syncTags(<images>)
//
// NOTE: mode is data.tagsToImages(..) / data.tagsFromImages(..)
// compatible...
// NOTE: setting source to 'both' and mode to 'reset' is the same as
// 'images' and 'reset' as all .data tags will be lost on first
// pass...
syncTags: ['Tag/-10:Synchoronize tags between data and images',
{journal: true},
function(source, mode){
// can't do anything if either .data or .images are not
// defined...
if(this.images == null){
return
}
source = source || 'both'
mode = mode || 'merge'
var images = this.images
if(typeof(source) != typeof('str')){
images = source
source = 'images'
}
if(source == 'data' || source == 'both'){
this.data.tagsToImages(images, mode)
}
if(source == 'images' || source == 'both'){
this.data.tagsFromImages(images, mode)
}
}],
})
var TagsEdit =
module.TagsEdit = core.ImageGridFeatures.Feature({
title: '',
tag: 'tags-edit',
depends: [
'tags',
'edit',
],
actions: TagsEditActions,
handlers: [
// tags and images...
// NOTE: tags are also stored in images...
['tag untag',
function(_, tags, gids){
var that = this
var changes = []
gids = gids || this.current
gids = gids instanceof Array ? gids : [gids]
gids = this.data.getImages(gids)
tags = tags || []
tags = tags instanceof Array ? tags : [tags]
// tags...
if(tags.length > 0){
this.markChanged('tags')
tags.indexOf('marked') >= 0
&& this.markChanged('marked')
tags.indexOf('bookmark') >= 0
&& this.markChanged('bookmarked')
}
this.markChanged('images', gids)
}],
// store .tags and .tags.marked / .tags.bookmark separately from .data...
//
// XXX see if this can be automated...
['prepareIndexForWrite',
function(res){
var changes = res.changes
if(!changes || !res.raw.data){
return
}
if((changes === true || changes.tags) && res.raw.data.tags){
res.index.tags = res.raw.data.tags
}
// XXX should we save an empty list *iff* changes.marked is true???
if(changes === true || changes.marked){
res.index.marked =
(res.raw.data.tags.tags || {}).marked || []
}
// XXX should we save an empty list *iff* changes.bookmarked is true???
if(changes === true || changes.bookmarked){
res.index.bookmarked = [
(res.raw.data.tags.tags || {}).bookmark || [],
{},
]
}
// cleanup...
if(res.index.data && res.index.data.tags){
delete res.index.data.tags.tags.marked
delete res.index.data.tags.tags.bookmark
delete res.index.data.tags
}
}],
// merge the tags into data...
['prepareIndexForLoad.pre',
function(json){
// NOTE: this is done before we build the data to let
// Data handle format conversion...
json.data.tags = json.tags || {}
}],
// merge in marked and bookmark tags...
['prepareIndexForLoad',
function(res, json){
res.data.tag('marked', json.marked || [])
res.data.tag('bookmark', json.bookmarked ? json.bookmarked[0] : [])
}],
],
})
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Image Group... // Image Group...

View File

@ -18,10 +18,262 @@ var browse = require('lib/widget/browse')
/*********************************************************************/ /*********************************************************************/
// Tags...
// mode can be:
// "ribbon" - next marked in current ribbon (default)
// "all" - next marked in sequence
//
// XXX add support for tag lists...
var makeTagWalker =
module.makeTagWalker =
function(direction, dfl_tag){
var meth = direction == 'next' ? 'nextImage' : 'prevImage'
return function(tag, mode){
this[meth](this.data.tags.values(tag || dfl_tag), mode) } }
//---------------------------------------------------------------------
var TagsActions =
module.TagsActions = actions.Actions({
// Navigation...
//
prevTagged: ['- Navigate/Previous image tagged with tag',
makeTagWalker('prev')],
nextTagged: ['- Navigate/Next image tagged with tag',
makeTagWalker('next')],
})
var Tags =
module.Tags = core.ImageGridFeatures.Feature({
title: '',
tag: 'tags',
depends: [
'base',
],
suggested: [
'tags-edit',
],
actions: TagsActions,
})
//---------------------------------------------------------------------
var TagsEditActions =
module.TagsEditActions = actions.Actions({
// tags...
//
// XXX mark updated...
tag: ['- Tag/Tag image(s)',
{journal: true},
function(tags, gids){
gids = gids || this.current
gids = gids instanceof Array ? gids : [gids]
// XXX this is slow for very large data sets...
gids = this.data.getImages(gids)
tags = tags instanceof Array ? tags : [tags]
var that = this
if(gids.length == 0){
return
}
// data...
this.data.tag(tags, gids)
// images...
var images = this.images
gids.forEach(function(gid){
var img = images[gid] = images[gid] || {}
img.tags = img.tags || []
img.tags = img.tags.concat(tags).unique()
// XXX mark updated...
})
}],
// XXX mark updated...
untag: ['- Tag/Untag image(s)',
{journal: true},
function(tags, gids){
gids = gids || this.current
gids = gids instanceof Array ? gids : [gids]
tags = tags instanceof Array ? tags : [tags]
// data...
this.data.untag(tags, gids)
// images...
var images = this.images
gids.forEach(function(gid){
var img = images[gid]
if(img == null || img.tags == null){
return
}
img.tags = img.tags.filter(function(tag){ return tags.indexOf(tag) < 0 })
if(img.tags.length == 0){
delete img.tags
}
// XXX mark updated...
})
}],
// Sync tags...
//
// Sync both ways...
// .syncTags()
// .syncTags('both')
//
// Sync from .data
// .syncTags('data')
//
// Sync from .images
// .syncTags('images')
//
// Sync from <images> object
// .syncTags(<images>)
//
// NOTE: mode is data.tagsToImages(..) / data.tagsFromImages(..)
// compatible...
// NOTE: setting source to 'both' and mode to 'reset' is the same as
// 'images' and 'reset' as all .data tags will be lost on first
// pass...
syncTags: ['Tag/-10:Synchoronize tags between data and images',
{journal: true},
function(source, mode){
// can't do anything if either .data or .images are not
// defined...
if(this.images == null){
return
}
source = source || 'both'
mode = mode || 'merge'
var images = this.images
if(typeof(source) != typeof('str')){
images = source
source = 'images'
}
if(source == 'data' || source == 'both'){
this.data.tagsToImages(images, mode)
}
if(source == 'images' || source == 'both'){
this.data.tagsFromImages(images, mode)
}
}],
})
var TagsEdit =
module.TagsEdit = core.ImageGridFeatures.Feature({
title: '',
tag: 'tags-edit',
depends: [
'tags',
'edit',
],
actions: TagsEditActions,
handlers: [
// tags and images...
// NOTE: tags are also stored in images...
['tag untag',
function(_, tags, gids){
var that = this
var changes = []
gids = gids || this.current
gids = gids instanceof Array ? gids : [gids]
gids = this.data.getImages(gids)
tags = tags || []
tags = tags instanceof Array ? tags : [tags]
// tags...
if(tags.length > 0){
this.markChanged('tags')
tags.indexOf('marked') >= 0
&& this.markChanged('marked')
tags.indexOf('bookmark') >= 0
&& this.markChanged('bookmarked')
}
this.markChanged('images', gids)
}],
// store .tags and .tags.marked / .tags.bookmark separately from .data...
//
// XXX see if this can be automated...
['prepareIndexForWrite',
function(res){
var changes = res.changes
if(!changes || !res.raw.data){
return
}
if((changes === true || changes.tags) && res.raw.data.tags){
res.index.tags = res.raw.data.tags
}
// XXX should we save an empty list *iff* changes.marked is true???
if(changes === true || changes.marked){
res.index.marked =
(res.raw.data.tags.tags || {}).marked || []
}
// XXX should we save an empty list *iff* changes.bookmarked is true???
if(changes === true || changes.bookmarked){
res.index.bookmarked = [
(res.raw.data.tags.tags || {}).bookmark || [],
{},
]
}
// cleanup...
if(res.index.data && res.index.data.tags){
delete res.index.data.tags.tags.marked
delete res.index.data.tags.tags.bookmark
delete res.index.data.tags
}
}],
// merge the tags into data...
['prepareIndexForLoad.pre',
function(json){
// NOTE: this is done before we build the data to let
// Data handle format conversion...
json.data.tags = json.tags || {}
}],
// merge in marked and bookmark tags...
['prepareIndexForLoad',
function(res, json){
res.data.tag('marked', json.marked || [])
res.data.tag('bookmark', json.bookmarked ? json.bookmarked[0] : [])
}],
],
})
//---------------------------------------------------------------------
// Persistent tags (tree) // Persistent tags (tree)
// //
// XXX add save/load tree to fs... // XXX add save/load tree to fs...
// XXX
var PersistentTagsActions = actions.Actions({ var PersistentTagsActions = actions.Actions({
}) })
@ -43,7 +295,7 @@ module.PersistentTags = core.ImageGridFeatures.Feature({
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// Persistent tags UI... // Tags UI...
// //
// Provide the following interfaces: // Provide the following interfaces:
// - cloud // - cloud
@ -53,7 +305,6 @@ module.PersistentTags = core.ImageGridFeatures.Feature({
// - edit tag tree // - edit tag tree
// - edit image tags // - edit image tags
// //
var TagUIActions = actions.Actions({ var TagUIActions = actions.Actions({
config: { config: {
// XXX should this be a list or a tree (list of paths)???? // XXX should this be a list or a tree (list of paths)????

View File

@ -772,6 +772,10 @@ var DialogsActions = actions.Actions({
//fullPathEdit: true, //fullPathEdit: true,
//*/ //*/
}, options || {})) })], }, options || {})) })],
// XXX
showCloud: ['- Interface/',
makeUIDialog(function(list, options){
throw new Error('.showCloud(..): not implemented.') })],
// XXX do we need to split the options??? // XXX do we need to split the options???
showEditableList: ['- Interface/', showEditableList: ['- Interface/',

View File

@ -922,12 +922,13 @@ var TagsPrototype = {
// NOTE: if any renamed tag is renamed to '' it will be removed // NOTE: if any renamed tag is renamed to '' it will be removed
// untagging all relevant values... // untagging all relevant values...
// //
// XXX need to sanitize from -- it can not contain regex characters... // XXX need to sanitize tag -- it can not contain regex characters...
// ...should we guard against this??? // ...should we guard against this???
// XXX should both sides of the alias be renamed??? // XXX should both sides of the alias be renamed???
rename: function(tag, to, ...tags){ rename: function(tag, to, ...tags){
var that = this var that = this
// XXX should we bo more pedantic here???
tag = this.normalize(tag) tag = this.normalize(tag)
if(tag == ''){ if(tag == ''){
throw new Error(`.rename(..): first argument can not be an empty string.`) } throw new Error(`.rename(..): first argument can not be an empty string.`) }