diff --git a/ui/css/editor.css b/ui/css/editor.css
index 0604d140..968fa7b4 100755
--- a/ui/css/editor.css
+++ b/ui/css/editor.css
@@ -32,6 +32,10 @@
color: red;
text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5);
}
+.panel .panel-content {
+ display: block;
+ min-height: 30px;
+}
.panel button,
.panel details,
.panel .state {
diff --git a/ui/editor.js b/ui/editor.js
index db70aa30..bdb7f9b7 100755
--- a/ui/editor.js
+++ b/ui/editor.js
@@ -33,6 +33,9 @@ var toggleEditor = createCSSClassToggler(
// XXX add handlers for saving data to images...
// XXX
// make clicks on unfocusable elements remove focus...
+ .on('panelClosing', function(){
+ toggleEditor('off')
+ })
.click(function(){
if(event.target != $('.panel :focus')[0]){
$('.panel :focus').blur()
@@ -50,6 +53,7 @@ var toggleEditor = createCSSClassToggler(
} else {
ed.show()
}
+
// update the state...
reloadControls('.current.image')
diff --git a/ui/keybindings.js b/ui/keybindings.js
index 946fe39d..59dc91fd 100755
--- a/ui/keybindings.js
+++ b/ui/keybindings.js
@@ -169,6 +169,7 @@ var KEYBOARD_CONFIG = {
// blur focused element, if nothing focused close...
} else if(toggleEditor('?') == 'on'){
$(':focus').blur()
+ return false
}
}),
},
@@ -659,6 +660,7 @@ var KEYBOARD_CONFIG = {
//}
centerRibbons()
}),
+ ctrl: doc('Show mark dialog', function(){ markImagesDialog() }),
},
Ins: doc('Toggle mark on current image', function(){ toggleImageMark() }),
'invert-marks': doc('Invert image marks',
diff --git a/ui/layout.css b/ui/layout.css
old mode 100644
new mode 100755
index d5f88461..fc14abe0
--- a/ui/layout.css
+++ b/ui/layout.css
@@ -1214,11 +1214,16 @@ button:hover {
}
/* XXX this is experimental... */
.viewer.overlay .ribbon-set {
- /* XXX blur makes things slow with transparency... */
+ /* XXX blur makes things slow with transparency... */
- -webkit-filter: /*blur(2px)*/ grayscale(0.5);
- filter: /*blur(2px)*/ grayscale(0.5);
- /*
+ /*
+ -webkit-filter: blur(2px);
+ filter: blur(2px);
+ */
+ -webkit-filter: grayscale(0.5);
+ filter: grayscale(0.5);
+
+ /*
-webkit-animation-name: testAnim;
-webkit-animation-duration: .2s;
-webkit-animation-iteration-count: 1;
diff --git a/ui/lib/editor.js b/ui/lib/editor.js
index aea05b33..42cf6b63 100755
--- a/ui/lib/editor.js
+++ b/ui/lib/editor.js
@@ -100,6 +100,11 @@ function sortFilterSliders(order){
// Load state of sliders from target...
//
function loadSliderState(target){
+ // break the feedback loop that if present will write the state
+ // back...
+ var filters = $('.filter-list input[type=range]')
+ .prop('disabled', true)
+
var res = $(target)
.css('-webkit-filter')
var state = res
@@ -113,7 +118,6 @@ function loadSliderState(target){
})
// set the saved values...
while(state.length > 0){
- // XXX avoid using ids...
var e = $('[filter='+state.pop()+']')
if(e.prop('normalize')){
e.val(v2r(parseFloat(state.pop()))).change()
@@ -121,6 +125,9 @@ function loadSliderState(target){
e.val(parseFloat(state.pop())).change()
}
}
+
+ filters
+ .prop('disabled', false)
return res
}
@@ -191,6 +198,7 @@ function makeAbsRange(text, filter, target, min, max, dfl, step, translate, norm
$('')
.html(text)
.appendTo(elem)
+ // NOTE: the range element is the main "writer"...
var range = $('')
.attr({
filter: filter,
@@ -204,7 +212,9 @@ function makeAbsRange(text, filter, target, min, max, dfl, step, translate, norm
.change(function(){
var val = this.valueAsNumber
value.val(val)
- updateFilter(target, filter, translate(val))
+ if(!elem.prop('disabled') && !$(this).prop('disabled')){
+ updateFilter(target, filter, translate(val))
+ }
if(parseFloat(val) == dfl){
elem.addClass('at-default')
} else {
@@ -236,21 +246,25 @@ function makeLogRange(text, filter, target){
}
-// XXX add panel update events to help save settings...
-function makeEditorControls(target){
+function makePanel(title, open){
+ title = title == null ? ' ' : title
+
// tool panel...
- var panel = $(' ')
+ var panel = $(' ')
+ .prop('open', open == null ? true : open)
.addClass('panel')
.css({
position: 'absolute',
top: '100px',
left: '100px',
})
- .append($('Edit')
+ .append($(''+title+'')
.append($('')
.addClass('close-button')
.click(function(){
- $(this).parents('.panel').hide()
+ panel
+ .trigger('panelClosing')
+ .hide()
return false
})
.html('×')))
@@ -270,11 +284,33 @@ function makeEditorControls(target){
opacity: 0.7,
})
.appendTo(panel)
+ return panel
+}
- // filters...
- $(' ')
- .append($('Filters'))
- .append($('
')
+
+function makeSubPanel(title, open, parent){
+ title = title == null ? ' ' : title
+
+ var sub_panel = $(' ')
+ .prop('open', open == null ? true : open)
+ .append($(''+title+''))
+ .append($(''))
+
+ if(parent != null){
+ if(parent.hasClass('panel-content')){
+ sub_panel.appendTo(parent)
+ } else {
+ sub_panel.appendTo(parent.find('.panel-content'))
+ }
+ }
+
+ return sub_panel
+}
+
+
+function makeFilterPanel(parent, target){
+ return makeSubPanel('Filters', true, parent)
+ .find('.sub-panel-content')
.append($('')
//.append(makeLogRange('Gamma:', 'gamma', target))
.append(makeLogRange('Brightness:', 'brightness', target))
@@ -307,13 +343,12 @@ function makeEditorControls(target){
.click(function(){
$('.reset').click()
sortFilterSliders(DEFAULT_FILTER_ORDER)
- })))
- .appendTo(content)
+ }))
+}
- // snapshots...
- $(' ')
- .append($('Snapshots'))
- .append($('')
+function makeSnapshotsPanel(parent, target){
+ return makeSubPanel('Snapshots', true, parent)
+ .find('.sub-panel-content')
.append($(''))
.append($('
'))
.append($('')
@@ -335,8 +370,20 @@ function makeEditorControls(target){
ui.helper.remove()
}
- })))
- .appendTo(content)
+ }))
+}
+
+
+// XXX add panel update events to help save settings...
+function makeEditorControls(target){
+
+ var panel = makePanel()
+
+ // filters...
+ makeFilterPanel(panel, target)
+
+ // snapshots...
+ makeSnapshotsPanel(panel, target)
return panel
}
diff --git a/ui/marks.js b/ui/marks.js
index 50a67d56..beccdddd 100755
--- a/ui/marks.js
+++ b/ui/marks.js
@@ -105,15 +105,14 @@ var toggleMarkesView = createCSSClassToggler(
var toggleImageMark = createCSSClassToggler(
'.current.image',
'marked',
- function(action){
+ function(action, elem){
toggleMarkesView('on')
- // XXX
if(action == 'on'){
- _addMark('selected')
+ _addMark('selected', getImageGID(elem), elem)
} else {
- _removeMark('selected')
+ _removeMark('selected', getImageGID(elem), elem)
}
- $('.viewer').trigger('togglingMark', [getImage(), action])
+ $('.viewer').trigger('togglingMark', [elem, action])
})
@@ -126,13 +125,17 @@ function removeImageMarks(mode){
var ribbon = getRibbon()
var res = ribbon
.find('.marked')
- .removeClass('marked')
+ .each(function(){
+ toggleImageMark(this, 'off')
+ })
$('.viewer').trigger('removeingRibbonMarks', [ribbon])
// remove all marks...
} else if(mode == 'all'){
var res = $('.marked')
- .removeClass('marked')
+ .each(function(){
+ toggleImageMark(this, 'off')
+ })
$('.viewer').trigger('removeingAllMarks')
}
return res
@@ -140,16 +143,22 @@ function removeImageMarks(mode){
function markAll(mode){
- // remove marks from current ribbon (default)...
+ // current ribbon (default)...
if(mode == 'ribbon' || mode == null){
var ribbon = getRibbon()
var res = ribbon
.find('.image:not(.marked)')
- .addClass('marked')
+ .each(function(){
+ toggleImageMark(this, 'on')
+ })
$('.viewer').trigger('markingRibbon', [ribbon])
+ // mark everything...
} else if(mode == 'all'){
- var res = $('.image:not(.marked)').addClass('marked')
+ var res = $('.image:not(.marked)')
+ .each(function(){
+ toggleImageMark(this, 'on')
+ })
$('.viewer').trigger('markingAll')
}
return res
@@ -161,7 +170,9 @@ function invertImageMarks(){
var ribbon = getRibbon()
var res = ribbon
.find('.image')
- .toggleClass('marked')
+ .each(function(){
+ toggleImageMark(this, 'next')
+ })
$('.viewer').trigger('invertingMarks', [ribbon])
return res
}
@@ -179,6 +190,7 @@ function toggleImageMarkBlock(image){
var state = toggleImageMark()
var _convert = function(){
if(toggleImageMark(this, '?') == state){
+ // stop the iteration...
return false
}
toggleImageMark(this, state)
@@ -264,5 +276,75 @@ function shiftMarkedImagesRight(){
+/**********************************************************************
+* Dialogs...
+*/
+
+function markImagesDialog(){
+
+ updateStatus('Mark...').show()
+
+ var alg = 'Mark images: |'+
+ 'Use Esc and Shift-Esc to exit crop modes.'+
+ '\n\n'+
+ 'NOTE: all crop modes will produce a single ribbon unless\n'+
+ 'otherwise stated.'
+
+ var cur = toggleImageMark('?') == 'on' ? 'Unmark' : 'Mark'
+
+ cfg = {}
+ cfg[alg] = [
+ cur + ' current image',
+ cur + ' current block | '+
+ 'A block is a set of similarly marked images\n'+
+ 'to the left and right of the current image,\n'+
+ 'up until the closest images marked differently',
+ 'Invert marks in current ribbon',
+ 'Mark all in current ribbon',
+ 'Unmark all in current ribbon',
+ 'Unmark all images'
+ ]
+
+ formDialog(null, '',
+ cfg,
+ 'OK',
+ 'markImagesDialog')
+ .done(function(res){
+ res = res[alg]
+
+ // NOTE: these must be in order of least-specific last...
+ if(/current image/.test(res)){
+ toggleImageMark()
+ var msg = (cur + ' image').toLowerCase()
+
+ } else if(/current block/.test(res)){
+ toggleImageMarkBlock()
+ var msg = 'toggled block marks'
+
+ } else if(/Invert/.test(res)){
+ invertImageMarks()
+ var msg = 'inverted ribbon marks'
+
+ } else if(/Mark all/.test(res)){
+ markAll()
+ var msg = 'marked ribbon'
+
+ } else if(/Unmark all in/.test(res)){
+ removeImageMarks('ribbon')
+ var msg = 'unmarked ribbon'
+
+ } else if(/Unmark all images/.test(res)){
+ removeImageMarks('all')
+ var msg = 'unmarked all'
+ }
+
+ showStatusQ('Mark: '+msg+'...')
+ })
+ .fail(function(){
+ showStatusQ('Marking: canceled.')
+ })
+}
+
+
/**********************************************************************
* vim:set ts=4 sw=4 : */
diff --git a/ui/setup.js b/ui/setup.js
index 813c5373..1ab4490d 100755
--- a/ui/setup.js
+++ b/ui/setup.js
@@ -94,7 +94,6 @@ function setupDataBindings(viewer){
// skip all but the curent ribbon in single image view...
if(toggleSingleImageMode('?') == 'on' && r != getRibbonIndex()){
- console.log('>>>> skipping ribbon:', r)
return
}
@@ -114,7 +113,6 @@ function setupDataBindings(viewer){
var t = getRelativeVisualPosition(viewer, ribbon).top
// XXX also check for visibility...
if( t+h <= 0 || t >= H ){
- //console.log('#### skipping align of ribbon:', r)
return
}