diff --git a/ui (gen4)/features/metadata.js b/ui (gen4)/features/metadata.js index 83be30e7..8a74a0b0 100755 --- a/ui (gen4)/features/metadata.js +++ b/ui (gen4)/features/metadata.js @@ -411,7 +411,9 @@ var MetadataUIActions = actions.Actions({ Object.assign( this.graph || document.createElement('ig-image-graph'), - config) + config, + // orientation.... + {orientation: (that.images[gid] || {}).orientation || 0}) Object.assign(elem.style, { width: '500px', height: '200px', diff --git a/ui (gen4)/lib/components/ig-image-graph.js b/ui (gen4)/lib/components/ig-image-graph.js index f278927b..92a4fee9 100644 --- a/ui (gen4)/lib/components/ig-image-graph.js +++ b/ui (gen4)/lib/components/ig-image-graph.js @@ -39,11 +39,11 @@ module.Filters = { } else { context.drawImage(img, 0, 0, w, h) } - return context.getImageData(0,0,c.width,c.height) + return context.getImageData(0, 0, c.width, c.height) }, setPixels: function(c, data, w, h){ - c.width = data.width - c.height = data.height + w = c.width = w || data.width + h = c.height = h || data.height var context = c.getContext('2d') context.putImageData(data, 0, 0) }, @@ -74,8 +74,9 @@ module.Filters = { color = color || 'fill' mode = mode || 'luminance' - var w = 255 - var h = 255 + var size = 255 + var w = size + var h = size // output buffer... var out = this.getPixels(null, w, h) @@ -105,14 +106,14 @@ module.Filters = { count[b*4+2] = (count[b*4+2] || 0) + 1 } } } - var m = 255 / Math.max(...count.filter(function(){ return true })) + var m = size / Math.max(...count.filter(function(){ return true })) var pos = function(i, value){ return ( // horizontal position... i*4 // value vertical offset... - + (255-Math.round(value*m))*w*4) } + + (size-Math.round(value*m))*w*4) } // XXX would be nice to have an option to draw full columns... count.forEach(function(v, i){ @@ -228,9 +229,11 @@ module.Filters = { var WAVEFORM_SIZE = module.WAVEFORM_SIZE = 1000 +// XXX need to account for image rotation... var waveform = module.waveform = -function(img, canvas, mode, color){ +function(img, canvas, mode, color, rotation){ + // XXX rotate... var d = Filters.getPixels(img, WAVEFORM_SIZE) var w = Filters.waveform(d, mode, color) Filters.setPixels(canvas, w) } @@ -334,8 +337,9 @@ object.Constructor('igImageGraph', HTMLElement, { 'src', 'mode', 'color', - 'nocontrols', 'graph', + 'orientation', + 'nocontrols', ]}, attributeChangedCallback: function(name, from, to){ name == 'nocontrols' @@ -387,6 +391,15 @@ object.Constructor('igImageGraph', HTMLElement, { value === undefined && this.removeAttribute('color') this.update() }, + get orientation(){ + return this.getAttribute('orientation') || 0 }, + set orientation(value){ + ;(['top', 'left', 'bottom', 'right'].includes(value) + || typeof(value) == typeof(123)) + && this.setAttribute('orientation', value) + value == null + && this.removeAttribute('orientation') + this.update() }, get nocontrols(){ return this.getAttribute('nocontrols') != null }, set nocontrols(value){ @@ -477,7 +490,12 @@ object.Constructor('igImageGraph', HTMLElement, { var canvas = this.__shadow.querySelector('canvas') if(this.image){ - graph(this.image, canvas, this.mode, this.color) + var orientation = this.orientation + orientation = parseFloat( + {top: 180, left: 90, bottom: 0, right: 270}[orientation] + || orientation) + + graph(this.image, canvas, this.mode, this.color, orientation) } else if(this.src){ this.src = this.src diff --git a/ui (gen4)/lib/widget/browse-walk.js b/ui (gen4)/lib/widget/browse-walk.js index 968522ef..304d5671 100755 --- a/ui (gen4)/lib/widget/browse-walk.js +++ b/ui (gen4)/lib/widget/browse-walk.js @@ -97,9 +97,7 @@ function(path, make){ resolve(fs.statSync(path)) } catch(err){ reject(err) - } - }) - } + } }) } /* var stat = function(path){ @@ -129,9 +127,7 @@ function(path, make){ if(drive == 'Z'){ resolve() } - }) - }) - }) + }) }) }) // list dirs... } else { @@ -150,8 +146,7 @@ function(path, make){ elem.attr('count', lst.length) }) } - return elem - } + return elem } return new Promise(function(resolve, reject){ // XXX should this be a promise??? @@ -291,9 +286,9 @@ var listDir = module.listDir = listDirfs // XXX for some reason pop does not focus the container dir correctly... // ...this is potentially due to the list not being ready yet... // XXX this should be smarter and support other URL schemes... -var WalkPrototype = { - __proto__: browse.Browser.prototype, - +var Walk = +module.Walk = +object.Constructor('Walk', browse.Browser, { options: { __proto__: browse.Browser.prototype.options, @@ -346,33 +341,20 @@ var WalkPrototype = { cur && this.select(cur) return this }, -} - - -var Walk = -module.Walk = -object.Constructor('Walk', - browse.Browser, - WalkPrototype) +}) var makeWalk = module.makeWalk = function(elem, path, fileCountPattern, rest){ - var opts = {} - if(rest){ - for(var k in rest){ - opts[k] = rest[k] - } - } - - opts.path = path - - opts.fileCountPattern = fileCountPattern == null ? - WalkPrototype.options.fileCountPattern - : fileCountPattern - - return Walk(elem, opts) -} + return Walk(elem, + Object.assign({}, + rest, + { + path: path, + fileCountPattern: fileCountPattern == null ? + Walk.prototype.options.fileCountPattern + : fileCountPattern, + })) } diff --git a/ui (gen4)/lib/widget/browse.js b/ui (gen4)/lib/widget/browse.js index d8f198a0..626b1745 100755 --- a/ui (gen4)/lib/widget/browse.js +++ b/ui (gen4)/lib/widget/browse.js @@ -3284,21 +3284,18 @@ var BrowserPrototype = { // Toggle filter view mode... toggleFilterViewMode: function(){ this.dom.toggleClass('show-filtered-out') - return this - }, + return this }, // XXX should this be a toggler??? disableElements: function(pattern){ this.filter(pattern, false) .addClass('disabled') .removeClass('selected') - return this - }, + return this }, enableElements: function(pattern){ this.filter(pattern, false) .removeClass('disabled') - return this - }, + return this }, // Select an element from current list... // @@ -4040,15 +4037,17 @@ var BrowserPrototype = { list: function(path, make){ path = path || this.path var m = this.options.list - return m ? m.apply(this, arguments) : [] - }, + return m ? + m.apply(this, arguments) + : [] }, // Run a function in the context of the object... // run: function(func){ var res = func ? func.call(this) : undefined - return res === undefined ? this : res - }, + return res === undefined ? + this + : res }, // XXX need to get a container -- UI widget API.... // XXX paste does not work on IE yet... @@ -4056,7 +4055,7 @@ var BrowserPrototype = { __init__: function(parent, options){ var that = this - object.parent(BrowserPrototype.__init__, this).call(this, parent, options) + object.parentCall(Browser.prototype.__init__, this, parent, options) var dom = this.dom options = this.options @@ -4110,9 +4109,8 @@ var BrowserPrototype = { */ // attach to parent... - if(parent != null){ - parent.append(dom) - } + parent != null + && parent.append(dom) // load the initial state... // NOTE: path can be a number so simply or-ing here is a bad idea... @@ -4134,11 +4132,13 @@ var BrowserPrototype = { // XXX not sure if we need this... // ...currently this is used only when path is // a list and we need to also select an item... - selected ? that.select(selected) - // we have a manually selected item but that was - // not aligned... - : that.selected ? that.select() - : null }) + selected ? + that.select(selected) + // we have a manually selected item but that was + // not aligned... + : that.selected ? + that.select() + : null }) }, } @@ -4146,40 +4146,31 @@ var BrowserPrototype = { var Browser = module.Browser = object.Constructor('Browser', + widget.Widget, BrowserClassPrototype, BrowserPrototype) -// inherit from widget... -Browser.prototype.__proto__ = widget.Widget.prototype - - /*********************************************************************/ -var ListerPrototype = Object.create(Browser.prototype) -ListerPrototype.options = { - pathPrefix: '', - fullPathEdit: false, - traversable: false, - flat: true, - - // XXX not sure if we need these... - skipDisabledItems: false, - // NOTE: to disable this set it to false or null - isItemDisabled: '^- ', -} -// XXX should we inherit or copy options??? -// ...inheriting might pose problems with deleting values reverting -// them to default instead of nulling them and mutable options might -// get overwritten... -ListerPrototype.options.__proto__ = Browser.prototype.options - var Lister = module.Lister = -object.Constructor('Lister', - BrowserClassPrototype, - ListerPrototype) +object.Constructor('Lister', Browser, { + options: { + __proto__: Browser.prototype.options, + + pathPrefix: '', + fullPathEdit: false, + traversable: false, + flat: true, + + // XXX not sure if we need these... + skipDisabledItems: false, + // NOTE: to disable this set it to false or null + isItemDisabled: '^- ', + }, +}) // This is a shorthand for: new List(, { data: }) @@ -4217,49 +4208,46 @@ module.makeLister = function(elem, lister, options){ // // NOTE: this essentially a different default configuration of Browser... // NOTE: this is essentially a wrapper around make.List(...) -var ListPrototype = Object.create(Browser.prototype) -ListPrototype.options = { - - pathPrefix: '', - fullPathEdit: false, - traversable: false, - flat: true, - - // XXX not sure if we need these... - skipDisabledItems: false, - // NOTE: to disable this set it to false or null - isItemDisabled: '^- ', - - list: function(path, make){ - var that = this - var data = this.options.data - - var res = [] - - // this is here to get the modified titles... - var _make = function(txt){ - res.push(txt) - return make.apply(make, arguments) - } - _make.__proto__ = make - - // build the list... - _make - .List(data, { - isItemDisabled: this.options.isItemDisabled, - skipDisabledItems: this.options.skipDisabledItems, - }) - - return res - }, -} -ListPrototype.options.__proto__ = Browser.prototype.options - var List = module.List = -object.Constructor('List', - BrowserClassPrototype, - ListPrototype) +object.Constructor('List', Browser, { + options: { + __proto__: Browser.prototype.options, + + pathPrefix: '', + fullPathEdit: false, + traversable: false, + flat: true, + + // XXX not sure if we need these... + skipDisabledItems: false, + // NOTE: to disable this set it to false or null + isItemDisabled: '^- ', + + list: function(path, make){ + var that = this + var data = this.options.data + + var res = [] + + // this is here to get the modified titles... + var _make = function(txt){ + res.push(txt) + return make.apply(make, arguments) + } + _make.__proto__ = make + + // build the list... + _make + .List(data, { + isItemDisabled: this.options.isItemDisabled, + skipDisabledItems: this.options.skipDisabledItems, + }) + + return res + }, + }, +}) // This is a shorthand for: new List(, { data: }) @@ -4378,151 +4366,149 @@ function(list, options){ // NOTE: currently only trailing '*' are supported. // // XXX add support for '*' and '**' glob patterns... -var PathListPrototype = Object.create(Browser.prototype) -PathListPrototype.options = { - - fullPathEdit: true, - traversable: true, - flat: false, - - // XXX not sure if we need these... - skipDisabledItems: false, - // NOTE: to disable this set it to false or null - isItemDisabled: '^- ', - - list: function(path, make){ - var that = this - var data = this.options.data - var keys = data.constructor == Array ? data : Object.keys(data) - var pattern = this.options.isItemDisabled - && RegExp(this.options.isItemDisabled) - - if(pattern && this.options.skipDisabledItems){ - keys = keys.filter(function(k){ return !pattern.test(k) }) - } - - var visited = [] - - // match path elements accounting for patterns... - // - // Supported patterns: - // A - matches A exactly - // A|B - matches either A or B - // shortcut marker - // - see .options.itemShortcutMarker - // - // NOTE: only the second argument is checked for '|' patterns... - var match = function(a, path){ - var marker = that.options.itemShortcutMarker - marker = marker && RegExp(marker, 'g') - path = marker ? path.replace(marker, '$1') : path - // NOTE: might be good to make this recursive when expanding - // pattern support... - return a - .split('|') - .map(function(e){ - return marker ? e.replace(marker, '$1') : e }) - .filter(function(e){ - return e == path }) - .length > 0 } - - // get the '*' listers... - var lister = keys - .filter(function(k){ - return k.trim().split(/[\\\/]+/g).pop() == '*' }) - .filter(function(k){ - k = k.split(/[\\\/]+/) - // remove the trailing '*'... - .slice(0, -1) - - // do the match... - return k.length <= path.length - && k.filter(function(e, i){ - return e != '*' && !match(e, path[i]) - }).length == 0 }) - .sort(function(a, b){ return a.length - b.length}) - .pop() - - // use the custom lister (defined by trailing '*')... - if(data !== keys && lister){ - return data[lister].call(this, this.options.pathPrefix + path.join('/'), make) - - // list via provided paths... - } else { - return keys - .map(function(k){ - var disable = null - if(pattern){ - var n = k.replace(pattern, '') - disable = n != k - k = n - } - - var kp = k.split(/[\\\/]+/g) - kp[0] == '' && kp.shift() - - // see if we have a star... - var star = kp.slice(-1)[0] == '*' - star && kp.pop() - - // get and check current path, continue if relevant... - var p = kp.splice(0, path.length) - if(kp.length == 0 - || p.length < path.length - || p.filter(function(e, i){ return !match(e, path[i]) }).length > 0){ - return false - } - - // get current path element if one exists and we did not create it already... - cur = kp.shift() - if(cur == undefined){ - return false - } - - cur.split('|') - // skip empty path items... - // NOTE: this avoids creating empty items in cases - // of paths ending with '/' or containing '//' - .filter(function(e){ return e.trim() != '' }) - .forEach(function(cur){ - if(visited.indexOf(cur) >= 0){ - // set element to traversable if we visit it again... - if(kp.length > 0){ - that.filter(cur, false) - .removeClass('not-traversable') - //.removeClass('disabled') - } - return false - } - visited.push(cur) - - // build the element.... - var e = make(cur, - star || kp.length > 0, - // XXX this might still disable a dir... - !star && kp.length == 0 && disable) - - // setup handlers... - if(!star && data !== keys && kp.length == 0 && data[k] != null){ - e.on('open', function(){ - return that.options.data[k].apply(this, arguments) - }) - } - }) - - return cur - }) - .filter(function(e){ return e !== false }) - } - }, -} -PathListPrototype.options.__proto__ = Browser.prototype.options - var PathList = module.PathList = -object.Constructor('PathList', - BrowserClassPrototype, - PathListPrototype) +object.Constructor('PathList', Browser, { + options: { + __proto__: Browser.prototype.options, + + fullPathEdit: true, + traversable: true, + flat: false, + + // XXX not sure if we need these... + skipDisabledItems: false, + // NOTE: to disable this set it to false or null + isItemDisabled: '^- ', + + list: function(path, make){ + var that = this + var data = this.options.data + var keys = data.constructor == Array ? data : Object.keys(data) + var pattern = this.options.isItemDisabled + && RegExp(this.options.isItemDisabled) + + if(pattern && this.options.skipDisabledItems){ + keys = keys.filter(function(k){ return !pattern.test(k) }) + } + + var visited = [] + + // match path elements accounting for patterns... + // + // Supported patterns: + // A - matches A exactly + // A|B - matches either A or B + // shortcut marker + // - see .options.itemShortcutMarker + // + // NOTE: only the second argument is checked for '|' patterns... + var match = function(a, path){ + var marker = that.options.itemShortcutMarker + marker = marker && RegExp(marker, 'g') + path = marker ? path.replace(marker, '$1') : path + // NOTE: might be good to make this recursive when expanding + // pattern support... + return a + .split('|') + .map(function(e){ + return marker ? e.replace(marker, '$1') : e }) + .filter(function(e){ + return e == path }) + .length > 0 } + + // get the '*' listers... + var lister = keys + .filter(function(k){ + return k.trim().split(/[\\\/]+/g).pop() == '*' }) + .filter(function(k){ + k = k.split(/[\\\/]+/) + // remove the trailing '*'... + .slice(0, -1) + + // do the match... + return k.length <= path.length + && k.filter(function(e, i){ + return e != '*' && !match(e, path[i]) + }).length == 0 }) + .sort(function(a, b){ return a.length - b.length}) + .pop() + + // use the custom lister (defined by trailing '*')... + if(data !== keys && lister){ + return data[lister].call(this, this.options.pathPrefix + path.join('/'), make) + + // list via provided paths... + } else { + return keys + .map(function(k){ + var disable = null + if(pattern){ + var n = k.replace(pattern, '') + disable = n != k + k = n + } + + var kp = k.split(/[\\\/]+/g) + kp[0] == '' && kp.shift() + + // see if we have a star... + var star = kp.slice(-1)[0] == '*' + star && kp.pop() + + // get and check current path, continue if relevant... + var p = kp.splice(0, path.length) + if(kp.length == 0 + || p.length < path.length + || p.filter(function(e, i){ return !match(e, path[i]) }).length > 0){ + return false + } + + // get current path element if one exists and we did not create it already... + cur = kp.shift() + if(cur == undefined){ + return false + } + + cur.split('|') + // skip empty path items... + // NOTE: this avoids creating empty items in cases + // of paths ending with '/' or containing '//' + .filter(function(e){ return e.trim() != '' }) + .forEach(function(cur){ + if(visited.indexOf(cur) >= 0){ + // set element to traversable if we visit it again... + if(kp.length > 0){ + that.filter(cur, false) + .removeClass('not-traversable') + //.removeClass('disabled') + } + return false + } + visited.push(cur) + + // build the element.... + var e = make(cur, + star || kp.length > 0, + // XXX this might still disable a dir... + !star && kp.length == 0 && disable) + + // setup handlers... + if(!star && data !== keys && kp.length == 0 && data[k] != null){ + e.on('open', function(){ + return that.options.data[k].apply(this, arguments) + }) + } + }) + + return cur + }) + .filter(function(e){ return e !== false }) + } + }, + }, +}) + var makePathList = module.makePathList = makeBrowserMaker(PathList) diff --git a/ui (gen4)/lib/widget/widget.js b/ui (gen4)/lib/widget/widget.js index a9370bb2..3859d9be 100755 --- a/ui (gen4)/lib/widget/widget.js +++ b/ui (gen4)/lib/widget/widget.js @@ -95,9 +95,9 @@ function(){ /*********************************************************************/ var WidgetClassPrototype = { - make: function(obj, client, options){ - console.error('Widget must define a .make method.') - }, + //make: function(obj, client, options){ + // console.error('Widget must define a .make method.') + //}, } @@ -168,14 +168,13 @@ var WidgetPrototype = { var that = this parent = this.parent = $(parent || 'body') - options = options || {} this.keybindings = JSON.parse(JSON.stringify(this.keybindings)) // merge options... - var opts = Object.create(this.options) - Object.keys(options).forEach(function(n){ opts[n] = options[n] }) - options = this.options = opts + options = this.options = Object.assign( + Object.create(this.options), + options || {}) // build the dom... if(this.constructor.make){ @@ -203,13 +202,11 @@ var WidgetPrototype = { this.keyboard, options.logKeys, this, - function(){ return this.options.keyboardRepeatPause })) - } + function(){ return this.options.keyboardRepeatPause })) } - if(this.options.nonPropagatedEvents != null){ - this.on(this.options.nonPropagatedEvents.join(' '), + this.options.nonPropagatedEvents != null + && this.on(this.options.nonPropagatedEvents.join(' '), function(evt){ evt.stopPropagation() }) - } return this }, @@ -253,7 +250,6 @@ var ContainerPrototype = { var that = this parent = this.parent = $(parent || 'body') - options = options || {} this.keybindings = JSON.parse(JSON.stringify(this.keybindings)) @@ -261,9 +257,9 @@ var ContainerPrototype = { client.parent = this // merge options... - var opts = Object.create(this.options) - Object.keys(options).forEach(function(n){ opts[n] = options[n] }) - options = this.options = opts + options = this.options = Object.assign( + Object.create(this.options), + options || {}) // build the dom... if(this.constructor.make){ @@ -301,10 +297,10 @@ var ContainerPrototype = { var Container = module.Container = object.Constructor('Container', - ContainerClassPrototype, - ContainerPrototype) + Widget, + ContainerClassPrototype, + ContainerPrototype) -Container.prototype.__proto__ = Widget.prototype