diff --git a/ui (gen4)/css/layout.css b/ui (gen4)/css/layout.css
index 56b6dc2b..a38ba22c 100644
--- a/ui (gen4)/css/layout.css
+++ b/ui (gen4)/css/layout.css
@@ -209,11 +209,13 @@ button:hover {
width: 100%;
height: 100%;
}
+.viewer:empty:before,
+.viewer:empty:after,
.ribbon-set:empty:before,
.ribbon-set:empty:after {
display: block;
position: absolute;
- content: "Nothing loaded...";
+ content: attr(empty-msg);
top: 50%;
left: 0px;
width: 100%;
@@ -227,8 +229,9 @@ button:hover {
opacity: 0.9;
cursor: hand;
}
+.viewer:empty:after,
.ribbon-set:empty:after {
- content: "Press 'O' to load, 'F1' for help or '?' for keyboard mappings.";
+ content: attr(empty-help);
margin-top: 5px;
font-weight: normal;
font-size: 16px;
diff --git a/ui (gen4)/css/layout.less b/ui (gen4)/css/layout.less
index 774466d6..da9a7020 100755
--- a/ui (gen4)/css/layout.less
+++ b/ui (gen4)/css/layout.less
@@ -320,15 +320,28 @@ button:hover {
/* empty ribbon set... */
.ribbon-set:empty {
- width: 100%;
- height: 100%;
+ width: 100% !important;
+ height: 100% !important;
+
+ // place at top left corner...
+ top: 0px !important;
+ left: 0px !important;
+
+ -webkit-transform: none !important;
+ -moz-transform: none !important;
+ -o-transform: none !important;
+ -ms-transform: none !important;
+ transform: none !important;
}
+.viewer:empty:before,
+.viewer:empty:after,
.ribbon-set:empty:before,
.ribbon-set:empty:after {
display: block;
position: absolute;
- content: "Nothing loaded...";
+ //content: "Nothing loaded...";
+ content: attr(empty-msg);
top: 50%;
left: 0px;
@@ -346,9 +359,11 @@ button:hover {
cursor: hand;
}
+.viewer:empty:after,
.ribbon-set:empty:after {
- content: "Press 'O' to load, 'F1' for help or '?' for keyboard mappings.";
+ //content: "Press 'O' to load, 'F1' for help or '?' for keyboard mappings.";
+ content: attr(empty-help);
margin-top: 5px;
font-weight: normal;
diff --git a/ui (gen4)/data.js b/ui (gen4)/data.js
index d11f2584..996f7bce 100755
--- a/ui (gen4)/data.js
+++ b/ui (gen4)/data.js
@@ -608,7 +608,8 @@ var DataPrototype = {
// be truncated...
for(; i >= 0 && i < this.order.length; i+=step){
var cur = list[i]
- if(cur == null){
+ // skip undefined or unloaded images...
+ if(cur == null || this.getRibbon(cur) == null){
continue
}
offset -= 1
@@ -876,6 +877,9 @@ var DataPrototype = {
// image gid...
} else {
var i = this.order.indexOf(target)
+ if(i == -1){
+ return null
+ }
var k
for(k in ribbons){
if(ribbons[k][i] != null){
@@ -1872,6 +1876,28 @@ var DataWithTagsPrototype = {
return res
},
+ crop: function(){
+ var crop = DataWithTagsPrototype.__proto__.crop.apply(this, arguments)
+
+ // make the tags mutable...
+ if(this.tags != null){
+ crop.tags = this.tags
+ }
+
+ return crop
+ },
+ clone: function(){
+ var clone = DataWithTagsPrototype.__proto__.clone.apply(this, arguments)
+
+ if(this.tags != null){
+ clone.tags = {}
+ for(var k in this.tags){
+ clone.tags[k] = this.tags[k].slice()
+ }
+ }
+
+ return clone
+ },
sortTags: function(){
var that = this
diff --git a/ui (gen4)/index.html b/ui (gen4)/index.html
index 3a977236..31d978cb 100755
--- a/ui (gen4)/index.html
+++ b/ui (gen4)/index.html
@@ -92,6 +92,7 @@
}
+
/* DEBUG stuff... */
.container-center {
position: absolute;
@@ -156,7 +157,7 @@ require('nw.gui').Window.get().showDevTools()
-
+
@@ -176,7 +177,9 @@ require('nw.gui').Window.get().showDevTools()
-
+
+
+
diff --git a/ui (gen4)/ribbons.js b/ui (gen4)/ribbons.js
index 833ecaf8..2087a8ac 100755
--- a/ui (gen4)/ribbons.js
+++ b/ui (gen4)/ribbons.js
@@ -18,13 +18,6 @@ var object = require('object')
var data = require('data')
var images = require('images')
-
-
-// XXX STUB
-var IMAGE_UPDATERS =
-module.IMAGE_UPDATERS = []
-
-
var IMAGE = '.image:not(.clone)'
var RIBBON = '.ribbon:not(.clone)'
@@ -172,11 +165,12 @@ var RibbonsPrototype = {
if(now){
target.removeClass('no-transitions')
var t = target[0]
- getComputedStyle(t).webkitTransition
- getComputedStyle(t).mozTransition
- getComputedStyle(t).msTransition
- getComputedStyle(t).oTransition
- getComputedStyle(t).transition
+ var s = getComputedStyle(t)
+ s.webkitTransition
+ s.mozTransition
+ s.msTransition
+ s.oTransition
+ s.transition
// on next exec frame...
} else {
@@ -184,11 +178,12 @@ var RibbonsPrototype = {
setTimeout(function(){
target.removeClass('no-transitions')}, 0)
var t = target[0]
- getComputedStyle(t).webkitTransition
- getComputedStyle(t).mozTransition
- getComputedStyle(t).msTransition
- getComputedStyle(t).oTransition
- getComputedStyle(t).transition
+ var s = getComputedStyle(t)
+ s.webkitTransition
+ s.mozTransition
+ s.msTransition
+ s.oTransition
+ s.transition
}
return this
@@ -889,8 +884,7 @@ var RibbonsPrototype = {
// Loading and updating...
- // XXX this needs:
- // IMAGE_UPDATERS -- make it a callback/event (node/jquery)...
+ // XXX is .__image_updaters the right way to go???
updateImageIndicators: function(gid, image){
gid = gid == null ? this.getElemGID() : gid
image = image == null ? this.getImage() : $(image)
@@ -898,9 +892,12 @@ var RibbonsPrototype = {
// collect marks...
image.after(this.getImageMarks(gid))
- IMAGE_UPDATERS.forEach(function(update){
- update(gid, image)
- })
+
+ if(this.__image_updaters != null){
+ this.__image_updaters.forEach(function(update){
+ update(gid, image)
+ })
+ }
return image
},
@@ -1109,20 +1106,25 @@ var RibbonsPrototype = {
}
// remove all images that we do not need...
- var unloaded = $()
+ var unloaded = []
+ var unload_marks = []
loaded = loaded
.filter(function(i, img){
- if(gids.indexOf(that.getElemGID($(img))) >= 0){
+ var g = that.getElemGID($(img))
+ if(gids.indexOf(g) >= 0){
return true
}
unloaded.push(img)
+ unload_marks = unload_marks.concat(that.getImageMarks(g).toArray())
return false
})
// remove everything in one go...
- unloaded
+ $(unloaded)
.detach()
.removeClass('moving')
- unloaded = unloaded.toArray()
+ // clear marks...
+ $(unload_marks)
+ .remove()
$(gids).each(function(i, gid){
// support for sparse ribbons...
@@ -1297,14 +1299,16 @@ var RibbonsPrototype = {
clear: function(gids){
// clear all...
if(gids == null || gids == '*'){
- this.getRibbonSet().remove()
+ this.preventTransitions()
+ setElementOffset(this.getRibbonSet(), 0, 0).children().detach()
+ this.restoreTransitions()
// clear one or more gids...
} else {
gids = gids.constructor !== Array ? [gids] : gids
var that = this
gids.forEach(function(g){
- that.viewer.find('[gid='+JSON.stringify(g)+']').remove()
+ that.viewer.find('[gid='+JSON.stringify(g)+']').detach()
})
}
return this
@@ -1763,6 +1767,18 @@ var RibbonsPrototype = {
},
+ setEmptyMsg: function(msg, help){
+ this.viewer
+ .attr({
+ 'empty-msg': msg || '',
+ 'empty-help': help || '',
+ })
+ this.getRibbonSet()
+ .attr({
+ 'empty-msg': msg || '',
+ 'empty-help': help || '',
+ })
+ },
}
diff --git a/ui (gen4)/testing.js b/ui (gen4)/testing.js
index 25f62f68..22785a03 100755
--- a/ui (gen4)/testing.js
+++ b/ui (gen4)/testing.js
@@ -52,6 +52,11 @@ module.mock_data = {
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z']
},
+
+ tags: {
+ selected: ['b', 'z'],
+ bookmark: ['1', 'c', 'z'],
+ },
}
Object.keys(mock_data.ribbons).forEach(function(k){
mock_data.order = mock_data.order.concat(mock_data.ribbons[k])
diff --git a/ui (gen4)/ui.js b/ui (gen4)/ui.js
index b9a9c01c..283e4fd8 100755
--- a/ui (gen4)/ui.js
+++ b/ui (gen4)/ui.js
@@ -122,6 +122,8 @@ module.GLOBAL_KEYBOARD = {
')': 'nextImageInOrder',
',': 'prevMarked',
'.': 'nextMarked',
+ '[': 'prevBookmarked',
+ ']': 'nextBookmarked',
Up: {
default: 'prevRibbon',
shift: 'shiftImageUp',
@@ -161,6 +163,8 @@ module.GLOBAL_KEYBOARD = {
F2: {
default: 'cropRibbon',
shift: 'cropRibbonAndAbove',
+ ctrl: 'cropMarked',
+ alt: 'cropBookmarked',
},
Esc: {
default: 'uncrop',
@@ -197,6 +201,14 @@ $(function(){
// XXX
window.a = testing.setupActions()
+ .load({
+ viewer: $('.viewer')
+ })
+
+
+ // XXX for some reason this does not happen right away...
+ a.setEmptyMsg('Loading...')
+
viewer.Features.setup(a, [
// XXX I do not fully understand it yet, but PartialRibbons must be
@@ -209,26 +221,34 @@ $(function(){
'ui-partial-ribbons',
'ui-ribbon-align-to-order',
'ui-single-image-view',
+
+ 'image-marks',
+ 'image-bookmarks',
+
+ // chrome...
'ui-animation',
'ui-bounds-indicators',
'ui-current-image-indicator',
- 'image-marks',
- 'image-bookmarks',
])
// this publishes all the actions...
//module.GLOBAL_KEYBOARD.__proto__ = a
-
// load some testing data...
+ // NOTE: we can load this in parts...
a.load({
+ //viewer: $('.viewer'),
data: data.Data(testing.mock_data),
- viewer: $('.viewer'),
images: testing.makeTestImages(),
})
+ a.setEmptyMsg(
+ 'Nothing loaded...',
+ 'Press \'O\' to load, \'F1\' for help or \'?\' for keyboard mappings.')
+
+
// setup base keyboard for devel, in case something breaks...
$(document)
.keydown(
diff --git a/ui (gen4)/viewer.js b/ui (gen4)/viewer.js
index 88f9d20c..20277859 100755
--- a/ui (gen4)/viewer.js
+++ b/ui (gen4)/viewer.js
@@ -625,6 +625,8 @@ actions.Actions(Client, {
if(this.ribbons == null){
this.ribbons = ribbons.Ribbons(viewer, this.images)
+ // XXX is this correct???
+ this.ribbons.__image_updaters = [this.updateImage.bind(this)]
}
this.reload()
@@ -667,6 +669,8 @@ actions.Actions(Client, {
if(this.ribbons == null){
this.ribbons = ribbons.Ribbons(viewer, this.images)
+ // XXX is this correct???
+ this.ribbons.__image_updaters = [this.updateImage.bind(this)]
} else {
this.ribbons.clear()
@@ -1010,6 +1014,17 @@ actions.Actions(Client, {
this.reload()
}
}],
+
+ // a shorthand...
+ setEmptyMsg: ['Set message to be displayed when nothing is loaded.',
+ function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }],
+
+
+ // XXX experimental...
+ // ...need this to get triggered by .ribbons
+ // at this point manually triggering this will not do anything...
+ updateImage: ['',
+ function(gid, image){ }],
})
@@ -1240,7 +1255,12 @@ module.PartialRibbons = Feature({
handlers: [
['focusImage.pre centerImage.pre',
- function(target){
+ function(target, list){
+ // NOTE: we have to do this as we are called BEFORE the
+ // actual focus change happens...
+ // XXX is there a better way to do this???
+ target = list != null ? target = this.data.getImage(target, list) : target
+
this.updateRibbon(target)
}],
['fitImage.pre',
@@ -1811,6 +1831,7 @@ function makeTagTogglerAction(tag){
// XXX add image updater...
var ImageMarkActions = actions.Actions({
+ // a shorthand...
// NOTE: this will return a copy...
get marked(){
if(this.data == null
@@ -1877,8 +1898,13 @@ module.ImageMarks = Feature({
actions: ImageMarkActions,
- // XXX image update...
handlers: [
+ // XXX is this the right way to go???
+ ['updateImage', function(gid, img){
+ if(this.toggleMark(gid, '?') == 'on'){
+ this.ribbons.toggleImageMark(gid, 'selected', 'on')
+ }
+ }],
],
})
@@ -1887,6 +1913,7 @@ module.ImageMarks = Feature({
//---------------------------------------------------------------------
var ImageBookmarkActions = actions.Actions({
+ // a shorthand...
// NOTE: this will return a copy...
get bookmarked(){
if(this.data == null
@@ -1909,12 +1936,12 @@ var ImageBookmarkActions = actions.Actions({
}],
prevBookmarked: ['',
- function(mode){ this.prevTagged('bookmarked', mode) }],
+ function(mode){ this.prevTagged('bookmark', mode) }],
nextBookmarked: ['',
- function(mode){ this.nextTagged('bookmarked', mode) }],
+ function(mode){ this.nextTagged('bookmark', mode) }],
cropBookmarked: ['',
- function(flatten){ this.cropTagged('bookmarked', 'any', flatten) }],
+ function(flatten){ this.cropTagged('bookmark', 'any', flatten) }],
})
@@ -1927,6 +1954,14 @@ module.ImageBookmarks = Feature({
actions: ImageBookmarkActions,
+ handlers: [
+ // XXX is this the right way to go???
+ ['updateImage', function(gid, img){
+ if(this.toggleBookmark(gid, '?') == 'on'){
+ this.ribbons.toggleImageMark(gid, 'bookmark', 'on')
+ }
+ }],
+ ],
})