diff --git a/app/view/window/image/ImageViewer.js b/app/view/window/image/ImageViewer.js index 767056f4..0aaf5041 100644 --- a/app/view/window/image/ImageViewer.js +++ b/app/view/window/image/ImageViewer.js @@ -672,7 +672,7 @@ Ext.define('EdiromOnline.view.window.image.ImageViewer', { me.showRect(0, 0, me.imgWidth, me.imgHeight); }, - showRect: function(x, y, width, height, highlight) { + showRect: function(x, y, width, height, highlight, fitHeight) { var me = this; @@ -684,7 +684,8 @@ Ext.define('EdiromOnline.view.window.image.ImageViewer', { y:y, width:width, height:height, - highlight:highlight + highlight:highlight, + fitHeight:fitHeight }; me.hiResImg.hide(); @@ -698,7 +699,13 @@ Ext.define('EdiromOnline.view.window.image.ImageViewer', { var diffWidth = 0; var diffHeight = 0; - if((contWidth / width) > (contHeight / height)) { + // fitHeight forces the zone height to fill the container and left-aligns it (no centering), + // so each part shows its full staff at the common zoom and the measures start at the same x + // across the vertically stacked parts in measureBasedView. Otherwise fit to whichever + // dimension is more constraining and centre (default, used by the page-based view). + if(fitHeight) { + me.setSVGZoom((contHeight / height)); + }else if((contWidth / width) > (contHeight / height)) { me.setSVGZoom((contHeight / height)); diffWidth = Math.round((contWidth - (width * me.zoom)) / 2); }else { @@ -726,7 +733,7 @@ Ext.define('EdiromOnline.view.window.image.ImageViewer', { // Re-fit the stored rect to the (now final) container size so the zone keeps the same // displayed height across viewers; fall back to a hi-res refresh when nothing is shown. if(me.rect && me.rect != null) - me.showRect(me.rect.x, me.rect.y, me.rect.width, me.rect.height, false); + me.showRect(me.rect.x, me.rect.y, me.rect.width, me.rect.height, false, me.rect.fitHeight); else me.calculateHiResImg(); }, diff --git a/app/view/window/image/OpenSeaDragonViewer.js b/app/view/window/image/OpenSeaDragonViewer.js index c46ccc1a..968e3dcf 100644 --- a/app/view/window/image/OpenSeaDragonViewer.js +++ b/app/view/window/image/OpenSeaDragonViewer.js @@ -126,7 +126,7 @@ Ext.define('EdiromOnline.view.window.image.OpenSeaDragonViewer', { }] }); me.viewer.addOnceHandler('tile-drawn', function() { - if(me.rect && me.rect != null) me.showRect(me.rect.x, me.rect.y, me.rect.width, me.rect.height, me.rect.highlight); + if(me.rect && me.rect != null) me.showRect(me.rect.x, me.rect.y, me.rect.width, me.rect.height, me.rect.highlight, me.rect.fitHeight); }); me.fireEvent('imageChanged', me, path, pageId); }, @@ -162,15 +162,17 @@ Ext.define('EdiromOnline.view.window.image.OpenSeaDragonViewer', { }; }, - showRect: function(x, y, width, height, highlight) { + showRect: function(x, y, width, height, highlight, fitHeight, alignment) { var me = this; me.rect = { - x:x, - y:y, - width:width, - height:height, - highlight:highlight + x: x, + y: y, + width: width, + height: height, + highlight: highlight, + fitHeight: fitHeight, + alignment: alignment || 'center' }; me.fitStoredRect(); @@ -181,7 +183,33 @@ Ext.define('EdiromOnline.view.window.image.OpenSeaDragonViewer', { var me = this; if(!me.viewer || !me.rect || me.rect == null) return; - var rect = me.viewer.viewport.imageToViewportRectangle(me.rect.x, me.rect.y, me.rect.width, me.rect.height); + var r = me.rect; + + // fitHeight maps the zone height to the full container height and positions the visible + // region horizontally according to r.alignment: + // 'left' – zone's left edge at the left of the viewport (right-side page in a spread) + // 'right' – zone's right edge at the right of the viewport (left-side page in a spread) + // 'center' – zone centred in the viewport (single viewer or inner part) + if(r.fitHeight) { + var contW = me.getWidth(); + var contH = me.getHeight(); + if(contW > 0 && contH > 0) { + var visWidth = r.height * (contW / contH); + var xStart; + if(r.alignment === 'left') { + xStart = r.x; + } else if(r.alignment === 'right') { + xStart = r.x + r.width - visWidth; + } else { + xStart = r.x + r.width / 2 - visWidth / 2; + } + var hRect = me.viewer.viewport.imageToViewportRectangle(xStart, r.y, visWidth, r.height); + me.viewer.viewport.fitBounds(hRect, true); + return; + } + } + + var rect = me.viewer.viewport.imageToViewportRectangle(r.x, r.y, r.width, r.height); me.viewer.viewport.fitBoundsWithConstraints(rect); }, diff --git a/app/view/window/source/MeasureBasedView.js b/app/view/window/source/MeasureBasedView.js index 962f7287..125c251c 100644 --- a/app/view/window/source/MeasureBasedView.js +++ b/app/view/window/source/MeasureBasedView.js @@ -621,6 +621,8 @@ Ext.define('EdiromOnline.view.window.source.HorizontalMeasureViewer', { me.forceComponentLayout(); + var partHeight = 0; + for(var i = 0; i < viewerCount; i++) { var viewer = me.imageViewers[i]; @@ -646,7 +648,34 @@ Ext.define('EdiromOnline.view.window.source.HorizontalMeasureViewer', { var width = lrx - ulx; var height = lry - uly; - viewer.showRect(ulx, uly, width, height, true); + // remember the tallest slice as this part's representative height + if(height > partHeight) partHeight = height; + + // fitHeight=true so each part shows its full staff height at the common zoom. + // Alignment depends on position in the row: + // single viewer → center + // two viewers → right (left viewer) / left (right viewer) + // three or more → right (first) / left (last) / center (inner) + var alignment; + if(viewerCount <= 1) { + alignment = 'center'; + } else if(i === 0) { + alignment = 'right'; + } else if(i === viewerCount - 1) { + alignment = 'left'; + } else { + alignment = 'center'; + } + viewer.showRect(ulx, uly, width, height, true, true, alignment); + } + + // Split the vertical space between parts proportionally to each part's height. Because each + // part is fit to its row height, rowHeight ∝ height makes the resulting zoom identical for + // every part (the common zoom ≈ windowHeight / Σ partHeight), and every staff is shown in + // full. The image viewers re-fit to the new row height via their onResize handler. + if(partHeight > 0) { + me.flex = partHeight; + if(me.ownerCt) me.ownerCt.updateLayout(); } },