From 774fcf0413dff05bf999fe2088e868e8ace4e02d Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sat, 30 Apr 2016 03:38:52 +0300 Subject: [PATCH] minor fixes + Makefile update... Signed-off-by: Alex A. Naanou --- ui (gen4)/Makefile | 73 ++++++--- ui (gen4)/features/base.js | 3 +- ui (gen4)/features/history.js | 118 +++++++------- ui (gen4)/features/sort.js | 81 +++++----- ui (gen4)/features/ui-single-image.js | 21 ++- ui (gen4)/features/ui-slideshow.js | 57 +++---- ui (gen4)/features/ui-widgets.js | 222 +++++++++++++++++++++----- ui (gen4)/features/ui.js | 4 + ui (gen4)/lib/actions.js | 39 +++-- 9 files changed, 412 insertions(+), 206 deletions(-) diff --git a/ui (gen4)/Makefile b/ui (gen4)/Makefile index 1673a5a2..d9789975 100755 --- a/ui (gen4)/Makefile +++ b/ui (gen4)/Makefile @@ -34,6 +34,7 @@ CSS_FILES := $(patsubst %.less,%.css,$(wildcard css/*.less)) LIB_DIR=lib EXT_LIB_DIR=ext-lib CSS_DIR=css +FEATURES_DIR=features NW_PROJECT_FILE=package.json JS_FILES := $(wildcard *.js) HTML_FILES := $(wildcard *.html) @@ -48,7 +49,7 @@ LOGS := *.log NODE_DIR=node_modules BUILD_DIR=build CHROME_APP_BUILD_DIR=build/Chrome-App/ImageGrid.Viewer -WIN_BUILD_DIR=build/Win32 +WIN_BUILD_DIR=build/Win MAC_BUILD_DIR=build/MacOSX MAC_10_6_BUILD_DIR=build/MacOSX-10.6 LINUX_IA32_BUILD_DIR=build/Linux-ia32 @@ -108,8 +109,8 @@ $(DIST_DIR): $(APP_ZIP): $(CSS_FILES) $(BUILD_DIR) $(NODE_DIR) node-deps zip -r $(APP_ZIP) $(NW_PROJECT_FILE) $(JS_FILES) $(CSS_FILES) \ - $(HTML_FILES) $(LIB_DIR) $(EXT_LIB_DIR) $(CSS_DIR) \ - $(NODE_DIR) + $(HTML_FILES) $(LIB_DIR) $(EXT_LIB_DIR) $(FEATURES_DIR) \ + $(CSS_DIR) $(NODE_DIR) zip: $(APP_ZIP) @@ -129,12 +130,12 @@ sharp: node-deps css: $(CSS_FILES) dev: css - #unzip -uj $(wildcard targets/node-webkit/node-webkit-*-win-ia32.zip) -d . + #unzip -uj $(wildcard targets/nwjs/nwjs-*-win-ia32.zip) -d . #rm -f nwsnapshot.exe credits.html #chmod +x *.{exe,dll} #dev-targets: -# mkdir -p targets/node-webkit +# mkdir -p targets/nwjs # wget @@ -151,12 +152,12 @@ chrome-app: $(APP_ZIP) $(CHROME_APP_BUILD_DIR) # this needs to be OS independent... chrome --pack-extension=$(CHROME_APP_BUILD_DIR) --pack-extension-key=$(CHROME_APP_KEY) -# node-webkit win32 +# nwjs win32 win32: $(APP_ZIP) $(WIN_BUILD_DIR) - unzip -u targets/node-webkit/node-webkit-*-win-ia32.zip \ + unzip -u targets/nwjs/nwjs-*-win-ia32.zip \ -d $(WIN_BUILD_DIR) - mv $(WIN_BUILD_DIR)/node-webkit*win-ia32/* $(WIN_BUILD_DIR)/ - rm -rf $(WIN_BUILD_DIR)/node-webkit*/ + mv $(WIN_BUILD_DIR)/nwjs*win-ia32/* $(WIN_BUILD_DIR)/ + rm -rf $(WIN_BUILD_DIR)/nwjs*/ cat $(APP_ZIP) >> $(WIN_BUILD_DIR)/nw.exe mv $(WIN_BUILD_DIR)/nw.exe $(WIN_BUILD_DIR)/$(APP_NAME).exe chmod +x $(WIN_BUILD_DIR)/*.{exe,dll} @@ -171,18 +172,38 @@ win32-dist: win32 $(DIST_DIR) -# node-webkit mac +# nwjs win32 +win64: $(APP_ZIP) $(WIN_BUILD_DIR) + unzip -u targets/nwjs/nwjs-*-win-x64.zip \ + -d $(WIN_BUILD_DIR) + mv $(WIN_BUILD_DIR)/nwjs*win-x64/* $(WIN_BUILD_DIR)/ + rm -rf $(WIN_BUILD_DIR)/nwjs*/ + cat $(APP_ZIP) >> $(WIN_BUILD_DIR)/nw.exe + mv $(WIN_BUILD_DIR)/nw.exe $(WIN_BUILD_DIR)/$(APP_NAME).exe + chmod +x $(WIN_BUILD_DIR)/*.{exe,dll} + rm -f $(WIN_BUILD_DIR)/nwsnapshot.exe \ + $(WIN_BUILD_DIR)/credits.html + +win64-dist: win64 $(DIST_DIR) + # XXX include vips... + # XXX build and include gid, buldcache... + # XXX include scripts/utils... + zip -r $(WIN_DIST_ZIP) $(WIN_BUILD_DIR) + + + +# nwjs mac # XXX BUG: rebuilding without cleaning will mess up folders... # XXX this is for 10.7+ osx: $(APP_ZIP) $(MAC_BUILD_DIR) Info.plist - unzip -u $(wildcard targets/node-webkit/node-webkit-*-osx-ia32.zip) \ + unzip -u $(wildcard targets/nwjs/nwjs-*-osx-ia32.zip) \ -d $(MAC_BUILD_DIR) - cp $(APP_ZIP) $(MAC_BUILD_DIR)/node-webkit.app/Contents/Resources/app.nw + cp $(APP_ZIP) $(MAC_BUILD_DIR)/nwjs.app/Contents/Resources/app.nw # XXX not sure if this is needed... - chmod +x $(MAC_BUILD_DIR)/node-webkit.app/Contents/Resources/app.nw + chmod +x $(MAC_BUILD_DIR)/nwjs.app/Contents/Resources/app.nw # XXX there is something wrong with the updated Info.plist, need to investigate... - cp Info.plist $(MAC_BUILD_DIR)/node-webkit.app/Contents/ - mv $(MAC_BUILD_DIR)/node-webkit.app $(MAC_BUILD_DIR)/$(APP_NAME).app + cp Info.plist $(MAC_BUILD_DIR)/nwjs.app/Contents/ + mv $(MAC_BUILD_DIR)/nwjs.app $(MAC_BUILD_DIR)/$(APP_NAME).app # XXX TODO: add real credits... rm -f $(MAC_BUILD_DIR)/nwsnapshot \ $(MAC_BUILD_DIR)/credits.html @@ -190,14 +211,14 @@ osx: $(APP_ZIP) $(MAC_BUILD_DIR) Info.plist # XXX this is almost identical to osx... # XXX BUG: rebuilding without cleaning will mess up folders... osx-10.6: $(APP_ZIP) $(MAC_10_6_BUILD_DIR) Info.plist - unzip -u $(wildcard targets/node-webkit/node-webkit-*-osx10.6-ia32.zip) \ + unzip -u $(wildcard targets/nwjs/nwjs-*-osx10.6-ia32.zip) \ -d $(MAC_10_6_BUILD_DIR) - cp $(APP_ZIP) $(MAC_10_6_BUILD_DIR)/node-webkit.app/Contents/Resources/app.nw + cp $(APP_ZIP) $(MAC_10_6_BUILD_DIR)/nwjs.app/Contents/Resources/app.nw # XXX not sure if this is needed... - chmod +x $(MAC_10_6_BUILD_DIR)/node-webkit.app/Contents/Resources/app.nw + chmod +x $(MAC_10_6_BUILD_DIR)/nwjs.app/Contents/Resources/app.nw # XXX there is something wrong with the updated Info.plist, need to investigate... - cp Info.plist $(MAC_10_6_BUILD_DIR)/node-webkit.app/Contents/ - mv $(MAC_10_6_BUILD_DIR)/node-webkit.app $(MAC_10_6_BUILD_DIR)/$(APP_NAME).app + cp Info.plist $(MAC_10_6_BUILD_DIR)/nwjs.app/Contents/ + mv $(MAC_10_6_BUILD_DIR)/nwjs.app $(MAC_10_6_BUILD_DIR)/$(APP_NAME).app # XXX TODO: add real credits... rm -f $(MAC_10_6_BUILD_DIR)/nwsnapshot \ $(MAC_10_6_BUILD_DIR)/credits.html @@ -212,10 +233,10 @@ osx-10.6-dist: osx $(DIST_DIR) -# node-webkit linux-ia32 +# nwjs linux-ia32 linux-ia32: $(APP_ZIP) $(LINUX_IA32_BUILD_DIR) tar --strip-components 1 \ - -xzf $(wildcard targets/node-webkit/node-webkit-*-linux-ia32.tar.gz) \ + -xzf $(wildcard targets/nwjs/nwjs-*-linux-ia32.tar.gz) \ -C $(LINUX_IA32_BUILD_DIR) cat $(APP_ZIP) >> $(LINUX_IA32_BUILD_DIR)/nw mv $(LINUX_IA32_BUILD_DIR)/nw $(LINUX_IA32_BUILD_DIR)/$(APP_NAME) @@ -229,10 +250,10 @@ linux-ia32-dist: linux-ia32 $(DIST_DIR) -# node-webkit linux-x64 +# nwjs linux-x64 linux-x64: $(APP_ZIP) $(LINUX_X64_BUILD_DIR) tar --strip-components 1 \ - -xzf $(wildcard targets/node-webkit/node-webkit-*-linux-x64.tar.gz) \ + -xzf $(wildcard targets/nwjs/nwjs-*-linux-x64.tar.gz) \ -C $(LINUX_X64_BUILD_DIR) cat $(APP_ZIP) >> $(LINUX_X64_BUILD_DIR)/nw mv $(LINUX_X64_BUILD_DIR)/nw $(LINUX_X64_BUILD_DIR)/$(APP_NAME) @@ -250,9 +271,9 @@ linux-x64-dist: linux-x64 $(DIST_DIR) # XXX iOS... -all: win32 osx osx-10.6 linux-ia32 linux-x64 +all: win64 win32 osx osx-10.6 linux-ia32 linux-x64 -dist: win32-dist osx-dist +dist: win64-dist win32-dist osx-dist #********************************************************************** diff --git a/ui (gen4)/features/base.js b/ui (gen4)/features/base.js index 4021b25e..5f42acdd 100755 --- a/ui (gen4)/features/base.js +++ b/ui (gen4)/features/base.js @@ -21,8 +21,6 @@ var core = require('features/core') /*********************************************************************/ - - // Helpers and meta stuff... // mode can be: @@ -53,6 +51,7 @@ function(direction, dfl_tag){ } + /*********************************************************************/ // XXX split this into read and write actions... diff --git a/ui (gen4)/features/history.js b/ui (gen4)/features/history.js index 764ddf7d..039a6010 100755 --- a/ui (gen4)/features/history.js +++ b/ui (gen4)/features/history.js @@ -12,6 +12,7 @@ var actions = require('lib/actions') var features = require('lib/features') var core = require('features/core') +var widgets = require('features/ui-widgets') var overlay = require('lib/widget/overlay') var browse = require('lib/widget/browse') @@ -399,7 +400,7 @@ var URLHistoryUIActions = actions.Actions({ // XXX need to check items... // XXX use svg icons for buttons... listURLHistory: ['History|File/Show history', - function(){ + widgets.makeUIDialog(function(){ var that = this var parent = this.preventClosing ? this.preventClosing() : null var cur = this.location.path @@ -418,66 +419,65 @@ var URLHistoryUIActions = actions.Actions({ to_remove = [] } - var o = overlay.Overlay(this.ribbons.viewer, - browse.makeList( - null, - Object.keys(this.url_history) - .reverse() - // NOTE: this might get a little slow for - // very large sets... - .map(function(p){ - return !that.checkURLFromHistory(p) ? - '- ' + p - : p - }), - { - // add item buttons... - itemButtons: [ - // move to top... - ['♦', - function(p){ - var top = this.filter('*', false).first() - var cur = this.filter('"'+p+'"', false) + var o = browse.makeList( + null, + Object.keys(this.url_history) + .reverse() + // NOTE: this might get a little slow for + // very large sets... + .map(function(p){ + return !that.checkURLFromHistory(p) ? + '- ' + p + : p + }), + { + // add item buttons... + itemButtons: [ + // move to top... + ['♦', + function(p){ + var top = this.filter('*', false).first() + var cur = this.filter('"'+p+'"', false) - console.log('!!!', p) + console.log('!!!', p) - if(!top.is(cur)){ - top.before(cur) - that.setTopURLHistory(p) + if(!top.is(cur)){ + top.before(cur) + that.setTopURLHistory(p) + } + }], + // mark for removal... + ['×', + function(p){ + var e = this.filter('"'+p+'"', false) + .toggleClass('strike-out') + + if(e.hasClass('strike-out')){ + to_remove.indexOf(p) < 0 + && to_remove.push(p) + + } else { + var i = to_remove.indexOf(p) + if(i >= 0){ + to_remove.splice(i, 1) } - }], - // mark for removal... - ['×', - function(p){ - var e = this.filter('"'+p+'"', false) - .toggleClass('strike-out') + } + }], + ], + }) + .open(function(evt, path){ + removeStriked('open') - if(e.hasClass('strike-out')){ - to_remove.indexOf(p) < 0 - && to_remove.push(p) + o.parent.close() - } else { - var i = to_remove.indexOf(p) - if(i >= 0){ - to_remove.splice(i, 1) - } - } - }], - ], - }) - .open(function(evt, path){ - removeStriked('open') + // close the parent ui... + parent + && parent.close + && parent.close() - o.close() - - // close the parent ui... - parent - && parent.close - && parent.close() - - that.openURLFromHistory(path) - })) - .close(function(){ + that.openURLFromHistory(path) + }) + .on('close', function(){ removeStriked('close') parent @@ -485,21 +485,19 @@ var URLHistoryUIActions = actions.Actions({ && parent.focus() }) - var list = o.client - /* Object.keys(this.url_history).reverse().forEach(function(p){ - that.checkURLFromHistory(p) || list.filter(p).addClass('disabled') + that.checkURLFromHistory(p) || o.filter(p).addClass('disabled') }) */ // select and highlight current path... - cur && list + cur && o .select('"'+ cur +'"') .addClass('highlighted') return o - }], + })], }) var URLHistoryUI = diff --git a/ui (gen4)/features/sort.js b/ui (gen4)/features/sort.js index c7478003..6e7a77f3 100755 --- a/ui (gen4)/features/sort.js +++ b/ui (gen4)/features/sort.js @@ -13,6 +13,7 @@ var features = require('lib/features') var toggler = require('lib/toggler') var core = require('features/core') +var widgets = require('features/ui-widgets') var overlay = require('lib/widget/overlay') var browse = require('lib/widget/browse') @@ -372,7 +373,7 @@ module.Sort = core.ImageGridFeatures.Feature({ var SortUIActions = actions.Actions({ // XXX should we be able to edit modes??? sortDialog: ['Edit|Sort/Sort images...', - function(){ + widgets.makeUIDialog(function(){ var that = this var dfl = this.config['default-sort'] @@ -389,54 +390,54 @@ var SortUIActions = actions.Actions({ } } - var o = overlay.Overlay(this.ribbons.viewer, - browse.makeLister(null, function(path, make){ - var cur = that.toggleImageSort('?') + var o = browse.makeLister(null, function(path, make){ + var lister = this + var cur = that.toggleImageSort('?') - that.toggleImageSort('??').forEach(function(mode){ - // skip 'none'... - if(mode == 'none'){ - return - } - make(mode) - .on('open', function(){ - that.toggleImageSort(null, mode, - that.config['default-sort-order'] == 'reverse') - o.close() - }) - .addClass(mode == cur ? 'highlighted' : '') - .addClass(mode == dfl ? 'default' : '') - }) - - // Commands... - make('---') - - make('Reverse images') + that.toggleImageSort('??').forEach(function(mode){ + // skip 'none'... + if(mode == 'none'){ + return + } + make(mode) .on('open', function(){ - that.reverseImages() - o.close() + that.toggleImageSort(null, mode, + that.config['default-sort-order'] == 'reverse') + lister.parent.close() }) - /* - make('Reverse ribbons') - .on('open', function(){ - that.reverseRibbons() - o.close() - }) - */ + .addClass(mode == cur ? 'highlighted' : '') + .addClass(mode == dfl ? 'default' : '') + }) - // Settings... - make('---') + // Commands... + make('---') - make(['Default order: ', that.config['default-sort-order'] || 'ascending']) - .on('open', _makeTogglHandler('toggleDefaultSortOrder')) - .addClass('item-value-view') - })) + make('Reverse images') + .on('open', function(){ + that.reverseImages() + lister.parent.close() + }) + /* + make('Reverse ribbons') + .on('open', function(){ + that.reverseRibbons() + o.close() + }) + */ + + // Settings... + make('---') + + make(['Default order: ', that.config['default-sort-order'] || 'ascending']) + .on('open', _makeTogglHandler('toggleDefaultSortOrder')) + .addClass('item-value-view') + }) // select the current order... - o.client.select('"' + this.toggleImageSort('?') + '"') + o.select('"' + this.toggleImageSort('?') + '"') return o - }] + })] }) var SortUI = diff --git a/ui (gen4)/features/ui-single-image.js b/ui (gen4)/features/ui-single-image.js index 596fd1fc..3b14c102 100755 --- a/ui (gen4)/features/ui-single-image.js +++ b/ui (gen4)/features/ui-single-image.js @@ -202,6 +202,9 @@ var SingleImageActions = actions.Actions({ // NOTE: setting this to null or to -1 will disable the feature... 'single-image-proportions-threshold': 2, + + // XXX HACK... + '-single-image-redraw-on-focus': true, }, toggleSingleImage: ['Interface/Toggle single image view', @@ -211,6 +214,11 @@ var SingleImageActions = actions.Actions({ }) +// XXX HACK: we are forcing redraw of images in some conditions (when +// they are close to their original size) to compensate for chrome +// rendering them blurry off screen in these conditions... +// XXX I would not bother and leave this as-is but this makes the +// image jump in size slightly when redrawing... var SingleImageView = module.SingleImageView = core.ImageGridFeatures.Feature({ title: '', @@ -235,7 +243,18 @@ module.SingleImageView = core.ImageGridFeatures.Feature({ // ...if needed do a .reload() / ctrl-r ['focusImage', function(){ - if(this.toggleSingleImage('?') == 'on'){ + var img = this.ribbons.getImage() + var d = Math.max(img.attr('preview-width')*1, img.attr('preview-width')*1) + var D = this.ribbons.getVisibleImageSize('max') + + if(this.config['-single-image-redraw-on-focus'] + // NOTE: redraw only when close to original preview + // size -- this is where chrome cheats and + // shows images blurry... + // XXX this causes some images to jump a bit, aligning + // to nearest pixel might fix this... + && Math.abs(D-d)/D < 0.30 + && this.toggleSingleImage('?') == 'on'){ this.scale = this.scale } }], diff --git a/ui (gen4)/features/ui-slideshow.js b/ui (gen4)/features/ui-slideshow.js index 0e5ceb50..e7dc3c2e 100755 --- a/ui (gen4)/features/ui-slideshow.js +++ b/ui (gen4)/features/ui-slideshow.js @@ -47,8 +47,10 @@ var SlideshowActions = actions.Actions({ }, // XXX use widgets.makeNestedConfigListEditor(...)??? - slideshowIntervalDialog: ['Slideshow/Slideshow interval', - function(){ + slideshowIntervalDialog: ['Slideshow/Slideshow interval...', + // XXX using both widgets.makeUIDialog(..) and widgets.makeConfigListEditor(..) + // is a bit too complicated... + widgets.makeUIDialog(function(){ var that = this // suspend the timer if it's not suspended outside... @@ -68,25 +70,28 @@ var SlideshowActions = actions.Actions({ callback: function(value){ that.config['slideshow-interval'] = value - o.close() + o.parent.close() }, }) - .close(function(){ + .on('close', function(){ // reset the timer if it was not suspended outside... suspended_timer || that.resetSlideshowTimer() }) - o.client.select(that.config['slideshow-interval']) + // XXX HACK: without a setTimeout(..) this will not select... + setTimeout(function(){ + o.select(that.config['slideshow-interval']) + }, 0) return o - }], + })], // XXX BUG: there are still problems with focus... // to reproduce: // click on the first option with a mouse... // result: // the top dialog is not focused... - slideshowDialog: ['Slideshow/Slideshow settings and start', - function(){ + slideshowDialog: ['Slideshow/Slideshow settings and start...', + widgets.makeUIDialog(function(){ var that = this // suspend the timer if it's not suspended outside... @@ -98,42 +103,38 @@ var SlideshowActions = actions.Actions({ return function(){ var txt = $(this).find('.text').first().text() that[toggler]() - o.client.update() - .then(function(){ o.client.select(txt) }) + o.update() + .then(function(){ o.select(txt) }) that.toggleSlideshow('?') == 'on' - && o.close() + && o.parent.close() } } - var o = overlay.Overlay(this.ribbons.viewer, - browse.makeLister(null, function(path, make){ + var o = browse.makeLister(null, function(path, make){ make(['Interval: ', function(){ return that.config['slideshow-interval'] }]) .on('open', function(){ var txt = $(this).find('.text').first().text() var oo = that.slideshowIntervalDialog() - .close(function(){ + .on('close', function(){ // slideshow is running -- close directly... if(that.toggleSlideshow('?') == 'on'){ - o.close() + o.parent.close() } else { - o.client.update() + o.update() .then(function(){ - o.client.select(txt) - - // XXX this is ugly... - o.focus() + o.select(txt) }) } }) // update slideshow menu... oo.client.open(function(){ - o.client.update() + o.update() .then(function(){ - o.client.select(txt) + o.select(txt) }) }) }) @@ -150,19 +151,19 @@ var SlideshowActions = actions.Actions({ return that.toggleSlideshow('?') == 'on' ? 'Stop' : 'Start' }]) .on('open', function(){ that.toggleSlideshow() - o.close() + o.parent.close() }) - })) - .close(function(){ + }) + .on('close', function(){ // reset the timer if it was not suspended outside... suspended_timer || that.resetSlideshowTimer() }) - o.client.dom.addClass('metadata-view tail-action') - o.client.select(-1) + o.dom.addClass('metadata-view tail-action') + o.select(-1) return o - }], + })], toggleSlideshowDirection: ['- Slideshow/Slideshow direction', core.makeConfigToggler('slideshow-direction', ['forward', 'reverse'])], diff --git a/ui (gen4)/features/ui-widgets.js b/ui (gen4)/features/ui-widgets.js index 1f80a479..1654d56a 100755 --- a/ui (gen4)/features/ui-widgets.js +++ b/ui (gen4)/features/ui-widgets.js @@ -205,9 +205,7 @@ function(actions, list_key, options){ options.callback && options.callback.call(list, path) } }) - - var o = overlay.Overlay(actions.ribbons.viewer, list) - .close(function(){ + .on('close', function(){ // prevent editing non-arrays... if(!(actions.config[list_key] instanceof Array)){ return @@ -230,7 +228,7 @@ function(actions, list_key, options){ new_button && list.dom.addClass('tail-action') - return o + return list } @@ -284,17 +282,140 @@ function(actions, parent, list_key, value_key, options){ +/*********************************************************************/ +// Dialogs and containers... + +var makeUIContainer = +module.makeUIContainer = function(make){ + var f = function(dialog){ + var o = make.call(this, dialog) + + // prevent the client event from bubbling up... + // XXX is this the right way to go??? + o.client.on('close', function(evt){ evt.stopPropagation() }) + + // notify the client that we are closing... + o.close(function(){ o.client.trigger('close') }) + + return o + } + f.__container__ = true + return f +} + +var makeUIDialog = +module.makeUIDialog = function(make){ + var f = function(){ + var args = [].slice.call(arguments) + + // see if the first arg is a container spec... + var container = this.uiContainers.indexOf(args[0]) >= 0 ? + args.shift() + : (this.config['ui-default-container'] || 'Overlay') + + return this[container](make.apply(this, args)) + } + f.__dialog__ = true + return f +} + + +//--------------------------------------------------------------------- + +var DialogsActions = actions.Actions({ + config: { + 'ui-default-container': 'Overlay', + }, + + // a bit of introspection... + get uiContainers(){ + return this.actions.filter(this.isUIContainer.bind(this)) }, + get uiDialogs(){ + return this.actions.filter(this.isUIDialog.bind(this)) }, + get uiElements(){ + return this.actions.filter(this.isUIElement.bind(this)) }, + + // get top overlay and overlay client... + get overlay(){ + return overlay.getOverlay(this.viewer) }, + + // testers... + isUIContainer: ['- Interface/', + actions.doWithRootAction(function(action){ + return action.__container__ == true })], + isUIDialog: ['- Interface/', + actions.doWithRootAction(function(action){ + return action.__dialog__ == true })], + isUIElement: ['- Interface/', + actions.doWithRootAction(function(action){ + return action.__dialog__ == true || action.__container__ == true })], + + + // container constructors... + // NOTE: there are not intended for direct use... + Overlay: ['- Interface/', + makeUIContainer(function(dialog){ + var that = this + return overlay.Overlay(this.ribbons.viewer, dialog) + // XXX focus parent on exit... + .on('close', function(){ + var o = that.overlay + + o && o.focus() + }) + })], + // XXX + Panel: ['- Interface/', + makeUIContainer(function(dialog){ + // XXX + })], + + + listDialogs: ['Interface/List dialogs...', + makeUIDialog(function(){ + var actions = this + + return browse.makeLister(null, function(path, make){ + var that = this + + actions.uiDialogs.forEach(function(dialog){ + make(actions.getDoc(dialog)[dialog][0].replace(/^- (.*)$/, '$1 (disabled)')) + .on('open', function(){ + actions[dialog]() + }) + }) + + }) + })], +}) + +var Dialogs = +module.Dialogs = core.ImageGridFeatures.Feature({ + title: '', + doc: '', + + tag: 'ui-dialogs', + depends: [ + 'ui', + ], + + actions: DialogsActions, +}) + + + /*********************************************************************/ // NOTE: if the action returns an instance of overlay.Overlay this will // not close right away but rather bind to: // overlay.close -> self.focus() // overlay.client.open -> self.close() +// XXX revise this... var makeActionLister = function(list, filter, pre_order){ pre_order = typeof(filter) == typeof(true) ? filter : pre_order filter = typeof(filter) == typeof(true) ? null : filter - return function(path, inline_state){ + return makeUIDialog(function(path, inline_state){ inline_state = inline_state == null ? this.config['actions-list-show-toggler-state-inline'] : inline_state @@ -302,7 +423,7 @@ var makeActionLister = function(list, filter, pre_order){ var that = this var paths = this.getPath() var actions = {} - var o + var d // pre-order the main categories... if(pre_order){ @@ -331,9 +452,9 @@ var makeActionLister = function(list, filter, pre_order){ if(child instanceof overlay.Overlay){ closingPrevented = true child - .on('close', function(){ o.focus() }) + .on('close', function(){ d.parent.focus() }) .client - .on('open', function(){ o.close() }) + .on('open', function(){ d.parent.close() }) } return child } @@ -368,7 +489,7 @@ var makeActionLister = function(list, filter, pre_order){ /* closingPrevented = true // XXX need to re-render the overlay paths... - that.getOverlay().client + that.overlay.client .pop() */ } @@ -379,30 +500,25 @@ var makeActionLister = function(list, filter, pre_order){ var config = Object.create(that.config['browse-actions-settings'] || {}) config.path = path - // XXX get the correct parent... - o = overlay.Overlay(that.ribbons.viewer, - list(null, actions, config) - .open(function(evt){ - if(!closingPrevented){ - o.close() - } - closingPrevented = false - })) + d = list(null, actions, config) + .open(function(evt){ + if(!closingPrevented){ + d.parent.close() + } + closingPrevented = false + }) // save show disabled state to .config... - .close(function(){ + .on('close', function(){ var config = that.config['browse-actions-settings'] - config.showDisabled = o.client.options.showDisabled + config.showDisabled = d.options.showDisabled }) - // XXX DEBUG - //window.LIST = o.client - - //return o.client - return o - } + return d + }) } +// NOTE: yes, this is a funny name ;) var BrowseActionsActions = actions.Actions({ config: { // NOTE: the slashes at the end are significant, of they are not @@ -422,16 +538,9 @@ var BrowseActionsActions = actions.Actions({ }, }, - // XXX move this to a generic modal overlay feature... - getOverlay: ['- Interface/Get overlay object', - function(o){ - return overlay.getOverlay(o || this.viewer) - }], - - - browseActions: ['Interface/Browse actions', + browseActions: ['Interface/Browse actions...', makeActionLister(browse.makePathList, true)], - listActions:['Interface/List actions', + listActions:['Interface/List actions...', makeActionLister(browse.makeList, // format the doc to: (, ..) // NOTE: this a bit naive... @@ -450,7 +559,8 @@ module.BrowseActions = core.ImageGridFeatures.Feature({ tag: 'ui-browse-actions', depends: [ - 'ui' + 'ui', + 'ui-dialogs', ], actions: BrowseActionsActions, @@ -510,6 +620,46 @@ module.ContextActionMenu = core.ImageGridFeatures.Feature({ // XXX make this not applicable to production... var WidgetTestActions = actions.Actions({ + + testBrowse: ['- Test/Demo new style dialog...', + makeUIDialog(function(){ + var actions = this + + console.log('>>> args:', [].slice.call(arguments)) + + return browse.makeLister(null, function(path, make){ + var that = this + + make('select last') + .on('open', function(){ + that.select(-1) + }) + + make('do nothing') + + make('nested dialog...') + .on('open', function(){ + actions.testBrowse() + }) + + make('---') + + make('close parent') + .on('open', function(){ + that.parent.close() + }) + + // XXX the parent is not yet set at this point... + //console.log('>>>', that.parent) + }) + // NOTE: this is not a dialog event, it is defined by the + // container to notify us that we are closing... + .on('close', function(){ + console.log('Dialog closing...') + }) + })], + + // XXX this is just a test... embededListerTest: ['Test/Lister test (embeded)/*', function(path, make){ diff --git a/ui (gen4)/features/ui.js b/ui (gen4)/features/ui.js index 629bc39d..3e8cd9c8 100755 --- a/ui (gen4)/features/ui.js +++ b/ui (gen4)/features/ui.js @@ -122,6 +122,10 @@ function updateImagePosition(actions, target){ // NOTE: this uses the base feature API but does not need it imported... // // XXX split this into read and write actions... +// XXX need a way to neutrally scale images and store that scale... +// - fit N images/ribbons is neutral but might mean different things +// depending on image and viewer proportions +// - .scale is a bad way to go... var ViewerActions = module.ViewerActions = actions.Actions({ config: { diff --git a/ui (gen4)/lib/actions.js b/ui (gen4)/lib/actions.js index d12e8372..b9e763a6 100755 --- a/ui (gen4)/lib/actions.js +++ b/ui (gen4)/lib/actions.js @@ -158,6 +158,19 @@ var normalizeTabs = function(str){ } +var doWithRootAction = +module.doWithRootAction = +function(func){ + return function(name){ + var handlers = (this.getHandlerList + || MetaActions.getHandlerList) + .call(this, name) + + return func.call(this, handlers.pop(), name) + } +} + + /*********************************************************************/ @@ -346,10 +359,19 @@ module.MetaActions = { get actions(){ var res = [] for(var k in this){ - // avoid recursion... - if(k == 'actions' || k == 'length'){ + // avoid recursion, skip props... + var cur = this + var prop = Object.getOwnPropertyDescriptor(cur, k) + while(!prop && cur.__proto__ != null){ + var cur = cur.__proto__ + var prop = Object.getOwnPropertyDescriptor(cur, k) + } + if(prop.get != null){ continue } + //if(k == 'actions' || k == 'length'){ + // continue + //} // get only actions... if(this[k] instanceof Action){ res.push(k) @@ -491,17 +513,8 @@ module.MetaActions = { // action can be or not be a toggler in different contexts. // // For more info on togglers see: lib/toggler.js - isToggler: function(name){ - var handlers = (this.getHandlerList - || MetaActions.getHandlerList) - .call(this, name) - - if(handlers.slice(-1)[0] instanceof toggler.Toggler){ - return true - } - - return false - }, + isToggler: doWithRootAction(function(action){ + return action instanceof toggler.Toggler }), // Register an action callback...