diff --git a/ui/bookmarks.js b/ui/bookmarks.js index 49018828..c9b5a70a 100755 --- a/ui/bookmarks.js +++ b/ui/bookmarks.js @@ -16,9 +16,6 @@ var BOOKMARKS = [] // BOOKMARKS, as the main structure. var BOOKMARKS_DATA = {} -var BOOKMARKS_FILE_DEFAULT = 'bookmarked.json' -var BOOKMARKS_FILE_PATTERN = /^[0-9]*-bookmarked.json$/ - /********************************************************************** @@ -38,8 +35,7 @@ var getBookmarkedGIDBefore = makeGIDBeforeGetterFromList( /*********************************************************************/ function cropBookmarkedImages(cmp, keep_ribbons, keep_unloaded_gids){ - cropDataTo(BOOKMARKS.slice(), keep_ribbons, keep_unloaded_gids) - + cropDataTo(BOOKMARKS, keep_ribbons, keep_unloaded_gids) return DATA } @@ -79,7 +75,7 @@ var toggleBookmarkedOnlyWithRibbonsView = makeCropModeToggler( var toggleBookmark = makeMarkToggler( 'bookmarked', 'bookmark', - 'togglingBookmark', + 'togglingBookmarks', function(gid, action){ // add a bookmark... if(action == 'on'){ @@ -130,8 +126,7 @@ var prevBookmark = makePrevFromListAction( var loadFileBookmarks = makeFileLoader( 'Bookmarks', - BOOKMARKS_FILE_DEFAULT, - BOOKMARKS_FILE_PATTERN, + CONFIG.bookmarks_file, [[], {}], function(data){ BOOKMARKS = populateSparceGIDList(data[0]) @@ -141,7 +136,7 @@ var loadFileBookmarks = makeFileLoader( var saveFileBookmarks = makeFileSaver( 'Bookmarks', - BOOKMARKS_FILE_DEFAULT, + CONFIG.bookmarks_file, function(){ return [ compactSparceList(BOOKMARKS), diff --git a/ui/crop.js b/ui/crop.js index 4ce31a6d..c9989e89 100755 --- a/ui/crop.js +++ b/ui/crop.js @@ -74,6 +74,10 @@ function makeCroppedData(gids, keep_ribbons, keep_unloaded_gids){ } +// Crop data to given gids and set viewer state... +// +// Returns original state +// // NOTE: if keep_ribbons is not set this will ALWAYS build a single ribbon // data-set... function cropDataTo(gids, keep_ribbons, keep_unloaded_gids){ diff --git a/ui/data.js b/ui/data.js index e04c38dd..631750e6 100755 --- a/ui/data.js +++ b/ui/data.js @@ -68,6 +68,32 @@ var CONFIG = { // Application name... app_name: 'ImageGrid.Viewer', + + // Filenames and patterns... + // file cache settings... + cache_dir: '.ImageGrid', + cache_dir_var: '${CACHE_DIR}', + + // extension to be used for JSON files... + json_ext: 'json', + // diff filename suffix... + diff_suffix: 'diff', + + // filename patterns... + base_file_pattern: '${BASE}.${EXT}', + file_pattern: '${DATE}-${BASE}.${EXT}', + diff_file_pattern: '${DATE}-${BASE}-${DIFF_SUFIX}.${EXT}', + + // filename bases... + // XXX should these be here??? + images_file: 'images', + data_file: 'data', + current_file: 'current', + marked_file: 'marked', + bookmarks_file: 'bookmarked', + tags_file: 'tags', + + // Navigation... // // The number of moves after which the default direction will be @@ -147,11 +173,6 @@ var CONFIG = { // localStorage prefix... data_attr: 'DATA', - // file cache settings... - cache_dir: '.ImageGrid', - cache_dir_var: '${CACHE_DIR}', - - // If true updateImages(..) will sort the images before updating, so as // to make the visible images update first... // @@ -646,6 +667,7 @@ function compactSparceList(lst){ // console.log('T:', Date.now()-t0) // >>> T: 171 // +// NOTE: this has no side-effects on the original gids list... function fastSortGIDsByOrder(gids, data){ return compactSparceList(populateSparceGIDList(gids, data)) } diff --git a/ui/files.js b/ui/files.js index 6443aba2..40dd57ed 100755 --- a/ui/files.js +++ b/ui/files.js @@ -10,20 +10,8 @@ // XXX do we need this? var IMAGES_CREATED = false -// XXX make these usable for both saving and loading... -// XXX get these from config... -var IMAGES_FILE_DEFAULT = 'images.json' -var IMAGES_FILE_PATTERN = /^[0-9]*-images.json$/ -var IMAGES_DIFF_FILE_PATTERN = /^[0-9]*-images-diff.json$/ - -var DATA_FILE_DEFAULT = 'data.json' -var DATA_FILE_PATTERN = /^[0-9]*-data.json$/ - -var CURRENT_FILE = 'current.json' - var IMAGE_PATTERN = /.*\.(jpg|jpeg|png|gif)$/i - var FILE_LOADERS = [] var FILE_SAVERS = {} var FILES_UPDATED = [] @@ -39,6 +27,44 @@ var FILES_UPDATED = [] /********************************************************* Helpers ***/ +function makeBaseFilename(base, date, ext){ + ext = ext == null ? CONFIG.json_ext : ext + + if(date == null){ + return CONFIG.base_file_pattern + .replace('${BASE}', base) + .replace('${EXT}', ext) + } + return date +'-'+ name +'.'+ ext +} +function makeFilename(base, date, ext){ + date = date == null ? Date.timeStamp() : date + ext = ext == null ? CONFIG.json_ext : ext + + return CONFIG.file_pattern + .replace('${DATE}', date) + .replace('${BASE}', base) + .replace('${EXT}', ext) +} +function makeFilenamePattern(base, ext){ + return RegExp(makeFilename(base, '^[0-9]*', ext)+'$') +} +function makeDiffFilename(base, date, diff, ext){ + date = date == null ? Date.timeStamp() : date + diff = diff == null ? CONFIG.diff_suffix : diff + ext = ext == null ? CONFIG.json_ext : ext + + return CONFIG.diff_file_pattern + .replace('${DATE}', date) + .replace('${BASE}', base) + .replace('${DIFF_SUFIX}', diff) + .replace('${EXT}', ext) +} +function makeDiffFilePattern(base, diff, ext){ + return RegExp(makeDiffFilename(base, '^[0-9]*', ext)+'$') +} + + // Report deferred progress // // This uses showStatus(...) and showErrorStatus(...) to report actions. @@ -208,35 +234,48 @@ function loadLatestFile(path, dfl, pattern, diff_pattern, default_data){ } -function makeFileLoader(title, file_dfl, file_pattern, default_data, set_data, error, evt_name, skip_reg){ +// XXX needs revision and testing... +function loadFile(title, path, file_dfl, file_pattern, default_data){ + var res = $.Deferred() + // default locations... + if(path == null){ + var base = normalizePath(CONFIG.cache_dir_var) + var loader = loadLatestFile(base, + file_dfl, + file_pattern, + null, + default_data) + + // explicit path... + // XXX need to account for paths without a CONFIG.cache_dir + } else { + path = normalizePath(path) + var base = path.split(CONFIG.cache_dir)[0] + //base = normalizePath(path +'/'+ CONFIG.cache_dir_var) + base = path +'/'+ CONFIG.cache_dir + + // XXX is this correct??? + var loader = loadLatestFile(base, + path.split(base)[0], + RegExp(path.split(base)[0]), + null, + default_data) + } + + bubbleProgress(title, loader, res) + + return res +} + + +function makeFileLoader(title, base, default_data, set_data, error, evt_name, skip_reg){ var _loader = function(path){ - var res = $.Deferred() - // default locations... - if(path == null){ - var base = normalizePath(CONFIG.cache_dir_var) - var loader = loadLatestFile(base, - file_dfl, - file_pattern, - null, - default_data) - - // explicit path... - // XXX need to account for paths without a CONFIG.cache_dir - } else { - path = normalizePath(path) - var base = path.split(CONFIG.cache_dir)[0] - //base = normalizePath(path +'/'+ CONFIG.cache_dir_var) - base = path +'/'+ CONFIG.cache_dir - - // XXX is this correct??? - var loader = loadLatestFile(base, - path.split(base)[0], - RegExp(path.split(base)[0]), - null, - default_data) - } - - bubbleProgress(title, loader, res) + var res = loadFile( + title, + path, + makeBaseFilename(base), + makeFilenamePattern(base), + default_data) res.done(set_data) @@ -246,7 +285,6 @@ function makeFileLoader(title, file_dfl, file_pattern, default_data, set_data, e if(evt_name != null){ res.done(function(){ $('.viewer').trigger(evt_name) }) } - return res } !skip_reg && FILE_LOADERS.push(_loader) @@ -255,12 +293,12 @@ function makeFileLoader(title, file_dfl, file_pattern, default_data, set_data, e // XXX make this check for updates -- no need to re-save if nothing // changed... function makeFileSaver(title, file_dfl, get_data, skip_reg){ - var _saver = function(name){ - name = name == null - ? normalizePath(CONFIG.cache_dir_var +'/'+ Date.timeStamp()) - : name + var _saver = function(path, date){ + path = path == null + ? normalizePath(CONFIG.cache_dir_var +'/'+ makeFilename(file_dfl, date)) + : path - dumpJSON(name + '-' + file_dfl, get_data()) + dumpJSON(path, get_data()) } if(!skip_reg){ FILE_SAVERS[title] = _saver @@ -285,13 +323,13 @@ function runFileLoaders(prefix, res){ } // NOTE: if all is set, this will force save everything... // XXX do we need bubbleProgress(..) here??? -function runFileSavers(name, all){ +function runFileSavers(path, date, all){ var updated = FILES_UPDATED FILES_UPDATED = [] for(var n in FILE_SAVERS){ if(all || updated.indexOf(n) >= 0){ showStatusQ('Saving: File:', n) - FILE_SAVERS[n](name) + FILE_SAVERS[n](path, date) } } } @@ -303,7 +341,7 @@ function runFileSavers(name, all){ var saveFileData = makeFileSaver( 'Data', - DATA_FILE_DEFAULT, + CONFIG.data_file, function(){ var data = getAllData() data.current = DATA.current @@ -398,17 +436,17 @@ function loadFileImages(path, no_load_diffs){ if(path == null){ var base = normalizePath(CONFIG.cache_dir_var) var loader = loadLatestFile(base, - IMAGES_FILE_DEFAULT, - IMAGES_FILE_PATTERN, - IMAGES_DIFF_FILE_PATTERN) + makeBaseFilename(CONFIG.images_file), + makeFilenamePattern(CONFIG.images_file), + makeDiffFilePattern(CONFIG.images_file)) // explicit base dir... } else if(!/\.json$/i.test(path)) { var base = normalizePath(path +'/'+ CONFIG.cache_dir_var) var loader = loadLatestFile(base, - IMAGES_FILE_DEFAULT, - IMAGES_FILE_PATTERN, - IMAGES_DIFF_FILE_PATTERN) + makeBaseFilename(CONFIG.images_file), + makeFilenamePattern(CONFIG.images_file), + makeDiffFilePattern(CONFIG.images_file)) // explicit path... } else { @@ -420,6 +458,7 @@ function loadFileImages(path, no_load_diffs){ res.done(function(images){ IMAGES = images IMAGES_UPDATED = [] + IMAGES_CREATED = false // XXX is this the correct spot to do this??? $('.viewer').trigger('imagesLoaded') @@ -434,12 +473,10 @@ function loadFileImages(path, no_load_diffs){ // If no name is given this will merge all the diffs and save a "clean" // (full) images.json file. Also removing the diff files. // -// NOTE: if an explicit name is given then this will not remove anything. // NOTE: this will use CONFIG.cache_dir as the location if no name is given. -function saveFileImages(name, remove_diffs){ - //remove_diffs = remove_diffs == null ? (name == null) : remove_diffs +function saveFileImages(name, date, remove_diffs){ remove_diffs = remove_diffs == null ? false : remove_diffs - name = name == null ? normalizePath(CONFIG.cache_dir_var +'/'+ Date.timeStamp()) : name + name = name == null ? normalizePath(CONFIG.cache_dir_var +'/'+ makeFilename(CONFIG.images_file, date)) : name if(window.dumpJSON == null){ showErrorStatus('Can\'t save to file.') @@ -448,18 +485,36 @@ function saveFileImages(name, remove_diffs){ // remove the diffs... if(remove_diffs){ + var diff_pattern = makeDiffFilePattern(CONFIG.images_file) $.each($.map(listDir(normalizePath(CONFIG.cache_dir_var)), function(e){ - return IMAGES_DIFF_FILE_PATTERN.test(e) ? e : null + return diff_pattern.test(e) ? e : null }), function(i, e){ - showStatusQ('removeing:', e) + showStatusQ('Removeing:', e) removeFile(normalizePath(CONFIG.cache_dir_var +'/'+ e)) }) - IMAGES_UPDATED = [] } // XXX use the pattern... - dumpJSON(name + '-images.json', IMAGES) - //DATA.image_file = normalizePath(name + '-images.json', null, 'relative') + dumpJSON(name, IMAGES) + + IMAGES_UPDATED = [] + IMAGES_CREATED = false +} + + +function saveFileImagesDiff(name, date){ + var path = normalizePath(CONFIG.cache_dir_var) + name = name == null + ? normalizePath(path +'/'+ makeDiffFilename(CONFIG.images_file, date)) + : name + + var updated = {} + $.each(IMAGES_UPDATED, function(i, e){ + updated[e] = IMAGES[e] + }) + + dumpJSON(name, updated) + IMAGES_UPDATED = [] } @@ -484,8 +539,8 @@ function loadFileState(path, prefix){ bubbleProgress(prefix, loadLatestFile(path, - DATA_FILE_DEFAULT, - DATA_FILE_PATTERN), res, true) + makeBaseFilename(CONFIG.data_file), + makeFilenamePattern(CONFIG.data_file)), res, true) .done(function(json){ setBaseURL(base) @@ -508,7 +563,7 @@ function loadFileState(path, prefix){ // added on 2.2 bubbleProgress(prefix, loadLatestFile(path, - CURRENT_FILE, + makeBaseFilename(CONFIG.current_file), null, null, DATA.current), res, true) @@ -549,43 +604,34 @@ function loadFileState(path, prefix){ // // NOTE: this will NOT save images, that operation must be explicitly // performed by saveFileImages(...) +// +// XXX do propper reporting... +// XXX check if name is needed and how it works... function saveFileState(name, no_normalize_path){ - name = name == null ? Date.timeStamp() : name + var date = Date.timeStamp() if(!no_normalize_path){ var path = normalizePath(CONFIG.cache_dir_var) - name = normalizePath(path +'/'+ name) - - // write .image_file only if saving data to a non-cache dir... - // XXX check if this is correct... - } else { - if(DATA.image_file == null){ - DATA.image_file = name + '-images.json' - } } - /* - var data = getAllData() - data.current = DATA.current - - dumpJSON(name + '-data.json', data) - */ - + var cur_file = makeBaseFilename(CONFIG.current_file) + showStatusQ('Saving: File:', cur_file) // allways update the current position... - dumpJSON(path + '/current.json', DATA.current) + dumpJSON(path +'/'+ cur_file, DATA.current) + + // save created images... + if(IMAGES_CREATED){ + showStatusQ('Saving: File: Images.') + saveFileImages(name, date) // save the updated images... - if(IMAGES_UPDATED.length > 0){ - var updated = {} - $.each(IMAGES_UPDATED, function(i, e){ - updated[e] = IMAGES[e] - }) - dumpJSON(name + '-images-diff.json', updated) - IMAGES_UPDATED = [] + } else if(IMAGES_UPDATED.length > 0){ + showStatusQ('Saving: File: Images diff.') + saveFileImagesDiff(name, date) } // save the rest of the data... - runFileSavers(name) + runFileSavers(name, date) } @@ -679,7 +725,7 @@ function loadDir(path, no_preview_processing, prefix){ // stop all workers running on current image set before we // move to the next... - // XXX is this the correct sopot for this??? + // XXX is this the correct spot for this??? killAllWorkers() IMAGES_CREATED = false @@ -755,8 +801,6 @@ function exportImageTo(gid, path, im_name, size){ // gid... dest = dest.replace('%gid', gid) dest = dest.replace('%g', gid.slice(34)) - // XXX Metadata... - // XXX dest = path +'/'+ dest diff --git a/ui/info.js b/ui/info.js index 7b4fb8d3..d39fee20 100755 --- a/ui/info.js +++ b/ui/info.js @@ -196,7 +196,7 @@ function setupInfo(viewer){ .on([ 'focusingImage', 'togglingMarks', - 'togglingBookmark', + 'togglingBookmarks', 'removeingAllMarks', 'removeingRibbonMarks', 'markingAll', diff --git a/ui/keybindings.js b/ui/keybindings.js index 57821afb..6b89e253 100755 --- a/ui/keybindings.js +++ b/ui/keybindings.js @@ -661,23 +661,10 @@ var KEYBOARD_CONFIG = { ctrl: doc('Save current state', function(){ event.preventDefault() - //saveLocalStorage() - - showStatusQ('Saving: localStorage: Data.') - saveLocalStorageData() - showStatusQ('Saving: localStorage: Marks.') - saveLocalStorageMarks() showStatusQ('Saving: localStorage: Settings.') saveLocalStorageSettings() - if(IMAGES_CREATED){ - showStatusQ('Saving: File: Images.') - dumpJSON(normalizePath(CACHE_DIR +'/'+ IMAGES_FILE_DEFAULT), IMAGES) - //saveFileImages() - IMAGES_CREATED = false - } - showStatusQ('Saving: File: State.') saveFileState() showStatusQ('Saving: Done.') diff --git a/ui/marks.js b/ui/marks.js index 5ed9cfc3..3c8fba32 100755 --- a/ui/marks.js +++ b/ui/marks.js @@ -22,9 +22,6 @@ // - really fast var MARKED = [] -var MARKED_FILE_DEFAULT = 'marked.json' -var MARKED_FILE_PATTERN = /^[0-9]*-marked.json$/ - /********************************************************************** @@ -51,8 +48,7 @@ function _addMark(cls, gid, image){ // make sure the mark is explicitly after the image... // XXX think of an eficient way to test if we need to re-insert... - mark - .insertAfter(image) + mark.insertAfter(image) return mark } @@ -159,7 +155,6 @@ var getMarked = makeMarkedLister(function(){ return MARKED }) var getUnmarked = makeUnmarkedSparseLister(function(){ return MARKED }) -// XXX make this undefined tolerant -- sparse list compatibility... var getMarkedGIDBefore = makeGIDBeforeGetterFromList( function(){ return compactSparceList(MARKED) @@ -361,10 +356,7 @@ var updateSelectedImageMark = makeMarkUpdater( // not exist, as there is no way to distinguish between the two // situations the cleanup is optional... function cropMarkedImages(keep_ribbons, keep_unloaded_gids){ - var marked = MARKED.slice() - - cropDataTo(marked, keep_ribbons, keep_unloaded_gids) - + cropDataTo(MARKED, keep_ribbons, keep_unloaded_gids) return DATA } @@ -387,7 +379,6 @@ var toggleMarkedOnlyWithRibbonsView = makeCropModeToggler( }) -// XXX shifting images and unmarking in this mode do not work correctly... var toggleMarksView = createCSSClassToggler( '.viewer', 'marks-visible', @@ -455,8 +446,8 @@ function markAllImagesTo(action, mode){ // - 'ribbon' (default) // - 'all' // -function unmarkAll(mode){ markAllImagesTo('off', mode) } function markAll(mode){ markAllImagesTo('on', mode) } +function unmarkAll(mode){ markAllImagesTo('off', mode) } // Invert marks on images... @@ -613,6 +604,7 @@ function shiftMarkedImagesDown(mode, new_ribbon){ } +/* // XXX these are ribbon wise only (???) // XXX this on first step this must pack all marked images function horizontalShiftMarkedImages(direction){ @@ -624,9 +616,10 @@ function shiftMarkedImagesLeft(){ function shiftMarkedImagesRight(){ return horizontalShiftMarkedImages('next') } +*/ -// Focus next/prev mark... +// Focus next/prev marked image... // // NOTE: these will not jump to marks on other ribbons... to prevent this // add true as the final argument (see restrict_to_ribbon argument @@ -639,6 +632,8 @@ var prevMark = makePrevFromListAction( function(){ return compactSparceList(MARKED) }) +// Focus next/prev unmarked image.. +// var nextUnmarked = makeNextFromListAction( getUnmarkedGIDBefore, function(ribbon){ @@ -738,8 +733,7 @@ function markImagesDialog(){ // NOTE: if no marks are found then set them to [] var loadFileMarks = makeFileLoader( 'Marks', - MARKED_FILE_DEFAULT, - MARKED_FILE_PATTERN, + CONFIG.marked_file, [], function(data){ MARKED = populateSparceGIDList(data) @@ -750,7 +744,7 @@ var loadFileMarks = makeFileLoader( // Save image marks to file var saveFileMarks = makeFileSaver( 'Marks', - MARKED_FILE_DEFAULT, + CONFIG.marked_file, function(){ return compactSparceList(MARKED) }) @@ -789,7 +783,6 @@ function setupMarks(viewer){ .click(function(){ toggleMark() }) return viewer - // XXX do we actually need this??? .on('sortedImages', function(){ MARKED = populateSparceGIDList(MARKED) marksUpdated() diff --git a/ui/tags.js b/ui/tags.js index ec2eff92..0159c30b 100755 --- a/ui/tags.js +++ b/ui/tags.js @@ -22,10 +22,6 @@ var UNSORTED_TAG = 'unsorted' var TAGS = {} -var TAGS_FILE_DEFAULT = 'tags.json' -var TAGS_FILE_PATTERN = /^[0-9]*-tags.json$/ - - /*********************************************************************/ @@ -470,8 +466,7 @@ function cropTagged(tags, keep_ribbons, keep_unloaded_gids){ var loadFileTags = makeFileLoader( 'Tags', - TAGS_FILE_DEFAULT, - TAGS_FILE_PATTERN, + CONFIG.tags_file, false, function(data){ // no tags loaded -- rebuild... @@ -492,7 +487,7 @@ var loadFileTags = makeFileLoader( // Save image marks to file var saveFileTags = makeFileSaver( 'Tags', - TAGS_FILE_DEFAULT, + CONFIG.tags_file, function(){ return TAGS })