changeset 1539:bfacecf7ea7e

Overhaul choice of layer to show scale, in Pane::drawVerticalScale, making it call out to the same logic used by View::getVisibleExtentsForUnit when appropriate. Also refuse to accept scale from dormant top layer.
author Chris Cannam
date Tue, 15 Oct 2019 14:53:25 +0100
parents 0ca4ca37809e
children 9ce6f69cd485
files view/Pane.cpp view/View.cpp view/View.h
diffstat 3 files changed, 134 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/view/Pane.cpp	Tue Oct 15 14:51:58 2019 +0100
+++ b/view/Pane.cpp	Tue Oct 15 14:53:25 2019 +0100
@@ -61,7 +61,8 @@
 
 #include "widgets/KeyReference.h" //!!! should probably split KeyReference into a data class in base and another that shows the widget
 
-//#define DEBUG_PANE
+//#define DEBUG_PANE 1
+//#define DEBUG_PANE_SCALE_CHOICE 1
 
 QCursor *Pane::m_measureCursor1 = nullptr;
 QCursor *Pane::m_measureCursor2 = nullptr;
@@ -525,99 +526,120 @@
 void
 Pane::drawVerticalScale(QRect r, Layer *topLayer, QPainter &paint)
 {
-    Layer *scaleLayer = nullptr;
-
-//    cerr << "Pane::drawVerticalScale[" << this << "]" << endl;
-    
     double min, max;
     bool log;
     QString unit;
 
-    // If the top layer has no scale and reports no display extents,
-    // but does report a unit, then the scale should be drawn from any
-    // (visible) underlying layer with a scale and that unit.  If the
-    // top layer has no scale and no value extents at all, then the
-    // scale should be drawn from any (visible) underlying layer with
-    // a scale regardless of unit.
-
-    int sw = topLayer->getVerticalScaleWidth
-        (this, m_manager->shouldShowVerticalColourScale(), paint);
+    bool includeColourScale = m_manager->shouldShowVerticalColourScale();
     
-    if (sw > 0) {
+    Layer *scaleLayer = nullptr;
+    int scaleWidth = 0;
+
+    // If the topmost layer is prepared to draw a scale, then use it.
+    //
+    // Otherwise: find the topmost layer that has value extents,
+    // i.e. for which a scale is relevant at all.
+    //
+    // If that layer is prepared to draw a scale directly, then use
+    // it. This could be the case even if the layer has no unit and so
+    // does not participate in scale-providing / auto-align layers.
+    // 
+    // Otherwise, request the scale-providing layer for that layer
+    // from the view, and if there is one and it can draw a scale, use
+    // that.
+    //
+    // In all cases ignore dormant layers, and if we hit an opaque
+    // layer before finding any with value extents, give up.
+
+    if (topLayer && !topLayer->isLayerDormant(this)) {
+        scaleWidth = topLayer->getVerticalScaleWidth
+            (this, includeColourScale, paint);
+
+#ifdef DEBUG_PANE_SCALE_CHOICE
+        SVCERR << "Pane[" << getId() << "]::drawVerticalScale: Top layer ("
+               << topLayer << ") offers vertical scale width of " << scaleWidth
+               << endl;
+#endif
+    }
+
+    if (scaleWidth > 0) {
         scaleLayer = topLayer;
-        m_scaleWidth = sw;
-
     } else {
 
-        bool hasDisplayExtents = topLayer->getDisplayExtents(min, max);
-        bool hasValueExtents = topLayer->getValueExtents(min, max, log, unit);
-            
-        if (!hasDisplayExtents) {
-
-            if (!hasValueExtents) {
-
-                for (LayerList::iterator vi = m_layerStack.end();
-                     vi != m_layerStack.begin(); ) {
-                        
-                    --vi;
-                        
-                    if ((*vi) == topLayer) continue;
-                    if ((*vi)->isLayerDormant(this)) continue;
-                        
-                    sw = (*vi)->getVerticalScaleWidth
-                        (this, m_manager->shouldShowVerticalColourScale(), paint);
-                        
-                    if (sw > 0) {
-                        scaleLayer = *vi;
-                        m_scaleWidth = sw;
-                        break;
-                    }
-                }
-            } else if (unit != "") { // && hasValueExtents && !hasDisplayExtents
-
-                QString requireUnit = unit;
-
-                for (LayerList::iterator vi = m_layerStack.end();
-                     vi != m_layerStack.begin(); ) {
-                        
-                    --vi;
-                        
-                    if ((*vi) == topLayer) continue;
-                    if ((*vi)->isLayerDormant(this)) continue;
-                        
-                    if ((*vi)->getDisplayExtents(min, max)) {
-                            
-                        // search no further than this: if the
-                        // scale from this layer isn't suitable,
-                        // we'll have to draw no scale (else we'd
-                        // risk ending up with the wrong scale)
-                            
-                        if ((*vi)->getValueExtents(min, max, log, unit) &&
-                            unit == requireUnit) {
-
-                            sw = (*vi)->getVerticalScaleWidth
-                                (this, m_manager->shouldShowVerticalColourScale(), paint);
-                            if (sw > 0) {
-                                scaleLayer = *vi;
-                                m_scaleWidth = sw;
-                            }
-                        }
-                        break;
-                    }
-                }
+        for (auto i = m_layerStack.rbegin(); i != m_layerStack.rend(); ++i) {
+            Layer *layer = *i;
+
+            if (layer->isLayerDormant(this)) {
+#ifdef DEBUG_PANE_SCALE_CHOICE
+                SVCERR << "Pane[" << getId() << "]::drawVerticalScale: "
+                       << "Layer " << layer << " is dormant, skipping" << endl;
+#endif
+                continue;
+            }
+
+            if (layer->getValueExtents(min, max, log, unit)) {
+                scaleLayer = layer;
+
+#ifdef DEBUG_PANE_SCALE_CHOICE
+                SVCERR << "Pane[" << getId() << "]::drawVerticalScale: "
+                       << "Layer " << layer << " has value extents (unit = "
+                       << unit << "), using this layer or unit" << endl;
+#endif
+                break;
+            }
+
+            if (layer->isLayerOpaque()) {
+#ifdef DEBUG_PANE
+                SVCERR << "Pane[" << getId() << "]::drawVerticalScale: "
+                       << "Layer " << layer
+                       << " is opaque, searching no further" << endl;
+#endif
+                break;
             }
         }
+
+        if (scaleLayer) {
+            scaleWidth = scaleLayer->getVerticalScaleWidth
+                (this, includeColourScale, paint);
+
+#ifdef DEBUG_PANE_SCALE_CHOICE
+            SVCERR << "Pane[" << getId() << "]::drawVerticalScale: Layer "
+                   << topLayer << " offers vertical scale width of "
+                   << scaleWidth << endl;
+#endif
+        }
+        
+        if (scaleWidth == 0 && unit != "") {
+#ifdef DEBUG_PANE_SCALE_CHOICE
+            SVDEBUG << "Pane[" << getId()
+                    << "]::drawVerticalScale: No good scale layer, then, "
+                    << "but we have a unit of " << unit
+                    << " - seeking scale-providing layer for that" << endl;
+#endif
+            
+            scaleLayer = getScaleProvidingLayerForUnit(unit);
+            
+#ifdef DEBUG_PANE_SCALE_CHOICE
+            SVDEBUG << "Pane[" << getId()
+                    << "]::drawVerticalScale: That returned "
+                    << scaleLayer << endl;
+#endif
+        }
     }
 
-    if (!scaleLayer) m_scaleWidth = 0;
-
-//    cerr << "m_scaleWidth = " << m_scaleWidth << ", r.left = " << r.left() << endl;
-    
+    if (scaleWidth > 0) {
+        m_scaleWidth = scaleWidth;
+    } else if (scaleLayer) {
+        m_scaleWidth = scaleLayer->getVerticalScaleWidth
+            (this, includeColourScale, paint);
+    } else {
+        m_scaleWidth = 0;
+    }
+        
     if (m_scaleWidth > 0 && r.left() < m_scaleWidth) {
 
 //      Profiler profiler("Pane::paintEvent - painting vertical scale", true);
 
-//      SVDEBUG << "Pane::paintEvent: calling paint.save() in vertical scale block" << endl;
         paint.save();
             
         paint.setPen(Qt::NoPen);
@@ -629,8 +651,8 @@
 
         paint.setBrush(Qt::NoBrush);
         scaleLayer->paintVerticalScale
-            (this, m_manager->shouldShowVerticalColourScale(),
-             paint, QRect(0, 0, m_scaleWidth, height()));
+            (this, includeColourScale, paint,
+             QRect(0, 0, m_scaleWidth, height()));
         
         paint.restore();
     }
--- a/view/View.cpp	Tue Oct 15 14:51:58 2019 +0100
+++ b/view/View.cpp	Tue Oct 15 14:53:25 2019 +0100
@@ -197,10 +197,34 @@
                                double &min, double &max,
                                bool &log) const
 {
-    bool have = false;
-
-    // Iterate in reverse order, so as to return display extents of
-    // topmost layer that fits the bill
+    Layer *layer = getScaleProvidingLayerForUnit(unit);
+    if (!layer) {
+        return false;
+    }
+
+    //!!! clumsy
+
+    QString layerUnit;
+    double layerMin, layerMax;
+
+    if (layer->getValueExtents(layerMin, layerMax, log, layerUnit)) {
+        if (layer->getDisplayExtents(min, max)) {
+            return true;
+        } else {
+            min = layerMin;
+            max = layerMax;
+            return true;
+        }
+    } else {
+        return false;
+    }
+}
+        
+Layer *
+View::getScaleProvidingLayerForUnit(QString unit) const
+{
+    // Iterate in reverse order, so as to use topmost layer that fits
+    // the bill
     
     for (auto i = m_layerStack.rbegin(); i != m_layerStack.rend(); ++i) { 
 
@@ -221,26 +245,10 @@
             continue;
         }
 
-        double displayMin = 0.0, displayMax = 0.0;
-        
-        if (layer->getDisplayExtents(displayMin, displayMax)) {
-
-            min = displayMin;
-            max = displayMax;
-            log = layerLog;
-            have = true;
-            break;
-
-        } else {
-
-            if (!have || layerMin < min) min = layerMin;
-            if (!have || layerMax > max) max = layerMax;
-            if (!have && layerLog) log = true;
-            have = true;
-        }
+        return layer;
     }
 
-    return have;
+    return nullptr;
 }
 
 bool
--- a/view/View.h	Tue Oct 15 14:51:58 2019 +0100
+++ b/view/View.h	Tue Oct 15 14:53:25 2019 +0100
@@ -502,6 +502,8 @@
     LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
     LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
 
+    Layer *getScaleProvidingLayerForUnit(QString unit) const;
+    
     ZoomLevel getZoomConstraintLevel(ZoomLevel level,
                                      ZoomConstraint::RoundingDirection dir =
                                      ZoomConstraint::RoundNearest) const;