changeset 273:e954c00cbe55

* proper (though ugly) handling of y coord for measure rects in scrollable layers
author Chris Cannam
date Fri, 29 Jun 2007 16:50:59 +0000
parents 87e4c880b4c8
children b9380f679f70
files layer/Layer.cpp layer/Layer.h layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h
diffstat 4 files changed, 90 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/layer/Layer.cpp	Fri Jun 29 13:58:08 2007 +0000
+++ b/layer/Layer.cpp	Fri Jun 29 16:50:59 2007 +0000
@@ -169,7 +169,7 @@
     }
 
     s += QString("startY=\"%1\" endY=\"%2\"/>\n")
-        .arg(pixrect.y()).arg(pixrect.y() + pixrect.height());
+        .arg(startY).arg(endY);
 
     return s;
 }
@@ -179,7 +179,7 @@
 {
     MeasureRect rect;
     QString fs = attributes.value("startFrame");
-    int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
+    int x0 = 0, x1 = 0;
     if (fs != "") {
         rect.startFrame = fs.toLong();
         rect.endFrame = attributes.value("endFrame").toLong();
@@ -189,9 +189,9 @@
         x1 = attributes.value("endX").toInt();
         rect.haveFrames = false;
     }
-    y0 = attributes.value("startY").toInt();
-    y1 = attributes.value("endY").toInt();
-    rect.pixrect = QRect(x0, y0, x1 - x0, y1 - y0);
+    rect.startY = attributes.value("startY").toDouble();
+    rect.endY = attributes.value("endY").toDouble();
+    rect.pixrect = QRect(x0, 0, x1 - x0, 0);
     addMeasureRectToSet(rect);
 }
 
@@ -224,6 +224,7 @@
     } else {
         m_draggingRect.haveFrames = false;
     }
+    setMeasureRectYCoord(v, m_draggingRect, true, e->y());
     m_haveDraggingRect = true;
 }
 
@@ -238,6 +239,8 @@
                                    e->y() - m_draggingRect.pixrect.y())
         .normalized();
 
+    setMeasureRectYCoord(v, m_draggingRect, false, e->y());
+    
     if (hasTimeXAxis()) {
         m_draggingRect.endFrame = v->getFrameForX(e->x());
     }
@@ -259,7 +262,7 @@
 Layer::paintMeasurementRects(View *v, QPainter &paint,
                              bool showFocus, QPoint focusPoint) const
 {
-    updateMeasurementPixrects(v);
+    updateMeasurePixrects(v);
 
     MeasureRectSet::const_iterator focusRectItr = m_measureRects.end();
 
@@ -281,7 +284,7 @@
 bool
 Layer::nearestMeasurementRectChanged(View *v, QPoint prev, QPoint now) const
 {
-    updateMeasurementPixrects(v);
+    updateMeasurePixrects(v);
     
     MeasureRectSet::const_iterator i0 = findFocusedMeasureRect(prev);
     MeasureRectSet::const_iterator i1 = findFocusedMeasureRect(now);
@@ -290,7 +293,7 @@
 }
 
 void
-Layer::updateMeasurementPixrects(View *v) const
+Layer::updateMeasurePixrects(View *v) const
 {
     long sf = v->getStartFrame();
     long ef = v->getEndFrame();
@@ -298,24 +301,54 @@
     for (MeasureRectSet::const_iterator i = m_measureRects.begin(); 
          i != m_measureRects.end(); ++i) {
 
-        if (!i->haveFrames) continue;
+        // This logic depends on the fact that if one measure rect in
+        // a layer has frame values, they all will.  That is in fact
+        // the case, because haveFrames is based on whether the layer
+        // hasTimeXAxis() or not.  Measure rect ordering in the rect
+        // set wouldn't work correctly either, if haveFrames could
+        // vary.
 
-        if (i->startFrame >= ef) break;
-        if (i->endFrame <= sf) continue;
+        if (i->haveFrames) {
+            if (i->startFrame >= ef) break;
+            if (i->endFrame <= sf) continue;
+        }
 
-        int x0 = -1;
-        int x1 = v->width() + 1;
-        
-        if (i->startFrame >= v->getStartFrame()) {
-            x0 = v->getXForFrame(i->startFrame);
-        }
-        if (i->endFrame <= long(v->getEndFrame())) {
-            x1 = v->getXForFrame(i->endFrame);
+        int x0 = i->pixrect.x();
+        int x1 = x0 + i->pixrect.width();
+
+        if (i->haveFrames) {
+            if (i->startFrame >= v->getStartFrame()) {
+                x0 = v->getXForFrame(i->startFrame);
+            }
+            if (i->endFrame <= long(v->getEndFrame())) {
+                x1 = v->getXForFrame(i->endFrame);
+            }
         }
         
-        QRect pr = QRect(x0, i->pixrect.y(), x1 - x0, i->pixrect.height());
+        i->pixrect = QRect(x0, i->pixrect.y(), x1 - x0, i->pixrect.height());
+
+        updateMeasureRectYCoords(v, *i);
         
-        i->pixrect = pr;
+        i->pixrect = i->pixrect.normalized();
+    }
+}
+
+void
+Layer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const
+{
+    int y0 = lrint(r.startY * v->height());
+    int y1 = lrint(r.endY * v->height());
+    r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
+}
+
+void
+Layer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const
+{
+    if (start) {
+        r.startY = double(y) / double(v->height());
+        r.endY = r.startY;
+    } else {
+        r.endY = double(y) / double(v->height());
     }
 }
 
--- a/layer/Layer.h	Fri Jun 29 13:58:08 2007 +0000
+++ b/layer/Layer.h	Fri Jun 29 16:50:59 2007 +0000
@@ -429,6 +429,8 @@
         bool haveFrames;
         long startFrame; // only valid if haveFrames
         long endFrame;   // ditto
+        double startY;
+        double endY;
 
         bool operator<(const MeasureRect &mr) const;
         QString toXmlString(QString indent) const;
@@ -467,7 +469,10 @@
     // Note that pixrects are only correct for a single view.
     // So we should update them at the start of the paint procedure
     // (painting is single threaded) and only use them after that.
-    void updateMeasurementPixrects(View *v) const;
+    void updateMeasurePixrects(View *v) const;
+
+    virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const;
+    virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const;
 
     // This assumes updateMeasurementPixrects has been called
     MeasureRectSet::const_iterator findFocusedMeasureRect(QPoint) const;
--- a/layer/SpectrogramLayer.cpp	Fri Jun 29 13:58:08 2007 +0000
+++ b/layer/SpectrogramLayer.cpp	Fri Jun 29 16:50:59 2007 +0000
@@ -3066,6 +3066,33 @@
     return new SpectrogramRangeMapper(m_model->getSampleRate(), m_fftSize);
 }
 
+void
+SpectrogramLayer::updateMeasureRectYCoords(View *v, const MeasureRect &r) const
+{
+    int y0 = 0;
+    if (r.startY > 0.0) y0 = getYForFrequency(v, r.startY);
+    
+    int y1 = y0;
+    if (r.endY > 0.0) y1 = getYForFrequency(v, r.endY);
+
+//    std::cerr << "SpectrogramLayer::updateMeasureRectYCoords: start " << r.startY << " -> " << y0 << ", end " << r.endY << " -> " << y1 << std::endl;
+
+    r.pixrect = QRect(r.pixrect.x(), y0, r.pixrect.width(), y1 - y0);
+}
+
+void
+SpectrogramLayer::setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const
+{
+    if (start) {
+        r.startY = getFrequencyForY(v, y);
+        r.endY = r.startY;
+    } else {
+        r.endY = getFrequencyForY(v, y);
+    }
+//    std::cerr << "SpectrogramLayer::setMeasureRectYCoord: start " << r.startY << " <- " << y << ", end " << r.endY << " <- " << y << std::endl;
+
+}
+
 QString
 SpectrogramLayer::toXmlString(QString indent, QString extraAttributes) const
 {
--- a/layer/SpectrogramLayer.h	Fri Jun 29 13:58:08 2007 +0000
+++ b/layer/SpectrogramLayer.h	Fri Jun 29 16:50:59 2007 +0000
@@ -401,6 +401,9 @@
     mutable std::vector<MagnitudeRange> m_columnMags;
     void invalidateMagnitudes();
     bool updateViewMagnitudes(View *v) const;
+
+    virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const;
+    virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const;
 };
 
 #endif