diff layer/BoxLayer.cpp @ 1547:e6362cf5ff1d

Pass a y-coord, optionally, to Layer::snapToFeatureFrame. This is necessary for BoxLayer which needs to coordinate its snaps with the box it is highlighting for editing. Then in BoxLayer, merge getPointToDrag and getLocalPoints into a single getLocalPoint and use this throughout.
author Chris Cannam
date Thu, 17 Oct 2019 11:12:54 +0100
parents ec837d223bd9
children e95cefd4aa81
line wrap: on
line diff
--- a/layer/BoxLayer.cpp	Thu Oct 17 10:26:21 2019 +0100
+++ b/layer/BoxLayer.cpp	Thu Oct 17 11:12:54 2019 +0100
@@ -239,36 +239,12 @@
     }
 }
 
-EventVector
-BoxLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
+bool
+BoxLayer::getLocalPoint(LayerGeometryProvider *v, int x, int y,
+                        Event &point) const
 {
     auto model = ModelById::getAs<BoxModel>(m_model);
-    if (!model) return EventVector();
-
-    sv_frame_t frame = v->getFrameForX(x);
-
-    EventVector local = model->getEventsCovering(frame);
-    if (!local.empty()) return local;
-
-    int fuzz = ViewManager::scalePixelSize(2);
-    sv_frame_t start = v->getFrameForX(x - fuzz);
-    sv_frame_t end = v->getFrameForX(x + fuzz);
-
-    local = model->getEventsStartingWithin(frame, end - frame);
-    if (!local.empty()) return local;
-
-    local = model->getEventsSpanning(start, frame - start);
-    if (!local.empty()) return local;
-
-    return {};
-}
-
-bool
-BoxLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y,
-                         Event &point) const
-{
-    auto model = ModelById::getAs<BoxModel>(m_model);
-    if (!model) return false;
+    if (!model || !model->isReady()) return false;
 
     sv_frame_t frame = v->getFrameForX(x);
 
@@ -308,9 +284,10 @@
     } else {
         int nearestDistance = -1;
         for (const auto &p: onPoints) {
+            const auto r = getRange(p);
             int distance = std::min
-                (getYForValue(v, p.getValue()) - y,
-                 getYForValue(v, p.getValue() + fabsf(p.getLevel())) - y);
+                (getYForValue(v, r.first) - y,
+                 getYForValue(v, r.second) - y);
             if (distance < 0) distance = -distance;
             if (nearestDistance == -1 || distance < nearestDistance) {
                 nearestDistance = distance;
@@ -343,14 +320,12 @@
 BoxLayer::getFeatureDescription(LayerGeometryProvider *v,
                                 QPoint &pos) const
 {
-    int x = pos.x();
-
     auto model = ModelById::getAs<BoxModel>(m_model);
     if (!model || !model->getSampleRate()) return "";
-
-    EventVector points = getLocalPoints(v, x);
-
-    if (points.empty()) {
+    
+    Event box;
+    
+    if (!getLocalPoint(v, pos.x(), pos.y(), box)) {
         if (!model->isReady()) {
             return tr("In progress");
         } else {
@@ -358,32 +333,17 @@
         }
     }
 
-    Event box;
-    EventVector::iterator i;
-
-    for (i = points.begin(); i != points.end(); ++i) {
-
-        int y0 = getYForValue(v, i->getValue());
-        int y1 = getYForValue(v, i->getValue() + fabsf(i->getLevel()));
-
-        if (pos.y() >= y0 && pos.y() <= y1) {
-            box = *i;
-            break;
-        }
-    }
-
-    if (i == points.end()) return tr("No local points");
-
     RealTime rt = RealTime::frame2RealTime(box.getFrame(),
                                            model->getSampleRate());
     RealTime rd = RealTime::frame2RealTime(box.getDuration(),
                                            model->getSampleRate());
     
     QString rangeText;
-
+    auto r = getRange(box);
+    
     rangeText = tr("%1 %2 - %3 %4")
-        .arg(box.getValue()).arg(getScaleUnits())
-        .arg(box.getValue() + fabsf(box.getLevel())).arg(getScaleUnits());
+        .arg(r.first).arg(getScaleUnits())
+        .arg(r.second).arg(getScaleUnits());
 
     QString text;
 
@@ -409,11 +369,12 @@
 BoxLayer::snapToFeatureFrame(LayerGeometryProvider *v,
                              sv_frame_t &frame,
                              int &resolution,
-                             SnapType snap) const
+                             SnapType snap,
+                             int ycoord) const
 {
     auto model = ModelById::getAs<BoxModel>(m_model);
     if (!model) {
-        return Layer::snapToFeatureFrame(v, frame, resolution, snap);
+        return Layer::snapToFeatureFrame(v, frame, resolution, snap, ycoord);
     }
 
     // SnapLeft / SnapRight: return frame of nearest feature in that
@@ -425,57 +386,52 @@
 
     resolution = model->getResolution();
 
+    Event containing;
+
+    if (getLocalPoint(v, v->getXForFrame(frame), ycoord, containing)) {
+
+        switch (snap) {
+
+        case SnapLeft:
+        case SnapNeighbouring:
+            frame = containing.getFrame();
+            return true;
+
+        case SnapRight:
+            frame = containing.getFrame() + containing.getDuration();
+            return true;
+        }
+    }
+    
     if (snap == SnapNeighbouring) {
-        EventVector points = getLocalPoints(v, v->getXForFrame(frame));
-        if (points.empty()) return false;
-        frame = points.begin()->getFrame();
-        return true;
+        return false;
     }    
 
-    // Normally we snap to the start frame of whichever event we
-    // find. However here, for SnapRight only, if the end frame of
-    // whichever event we would have snapped to had we been snapping
-    // left is closer than the start frame of the next event to the
-    // right, then we snap to that frame instead. Clear?
+    // We aren't actually contained (in time) by any single event, so
+    // seek the next one in the relevant direction
+
+    Event e;
     
-    Event left;
-    bool haveLeft = false;
-    if (model->getNearestEventMatching
-        (frame, [](Event) { return true; }, EventSeries::Backward, left)) {
-        haveLeft = true;
-    }
+    if (snap == SnapLeft) {
+        if (model->getNearestEventMatching
+            (frame, [](Event) { return true; }, EventSeries::Backward, e)) {
 
-    if (snap == SnapLeft) {
-        frame = left.getFrame();
-        return haveLeft;
-    }
-
-    Event right;
-    bool haveRight = false;
-    if (model->getNearestEventMatching
-        (frame, [](Event) { return true; }, EventSeries::Forward, right)) {
-        haveRight = true;
-    }
-
-    if (haveLeft) {
-        sv_frame_t leftEnd = left.getFrame() + left.getDuration();
-        if (leftEnd > frame) {
-            if (haveRight) {
-                if (leftEnd - frame < right.getFrame() - frame) {
-                    frame = leftEnd;
-                } else {
-                    frame = right.getFrame();
-                }
+            if (e.getFrame() + e.getDuration() < frame) {
+                frame = e.getFrame() + e.getDuration();
             } else {
-                frame = leftEnd;
+                frame = e.getFrame();
             }
             return true;
         }
     }
+    
+    if (snap == SnapRight) {
+        if (model->getNearestEventMatching
+            (frame, [](Event) { return true; }, EventSeries::Forward, e)) {
 
-    if (haveRight) {
-        frame = right.getFrame();
-        return true;
+            frame = e.getFrame();
+            return true;
+        }
     }
 
     return false;
@@ -607,8 +563,8 @@
     bool shouldIlluminate = false;
 
     if (v->shouldIlluminateLocalFeatures(this, localPos)) {
-        shouldIlluminate = getPointToDrag(v, localPos.x(), localPos.y(),
-                                          illuminatePoint);
+        shouldIlluminate = getLocalPoint(v, localPos.x(), localPos.y(),
+                                         illuminatePoint);
     }
 
     paint.save();
@@ -620,11 +576,12 @@
          i != points.end(); ++i) {
 
         const Event &p(*i);
+        const auto r = getRange(p);
 
         int x = v->getXForFrame(p.getFrame());
         int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x;
-        int y = getYForValue(v, p.getValue());
-        int h = getYForValue(v, p.getValue() + fabsf(p.getLevel())) - y;
+        int y = getYForValue(v, r.first);
+        int h = getYForValue(v, r.second) - y;
         int ex = x + w;
         int gap = v->scalePixelSize(2);
 
@@ -655,11 +612,11 @@
             if (abs(h) > 2 * fm.height()) {
             
                 QString y0label = QString("%1 %2")
-                    .arg(p.getValue())
+                    .arg(r.first)
                     .arg(getScaleUnits());
 
                 QString y1label = QString("%1 %2")
-                    .arg(p.getValue() + fabsf(p.getLevel()))
+                    .arg(r.second)
                     .arg(getScaleUnits());
 
                 PaintAssistant::drawVisibleText
@@ -677,9 +634,9 @@
             } else {
             
                 QString ylabel = QString("%1 %2 - %3 %4")
-                    .arg(p.getValue())
+                    .arg(r.first)
                     .arg(getScaleUnits())
-                    .arg(p.getValue() + fabsf(p.getLevel()))
+                    .arg(r.second)
                     .arg(getScaleUnits());
 
                 PaintAssistant::drawVisibleText
@@ -880,7 +837,7 @@
     auto model = ModelById::getAs<BoxModel>(m_model);
     if (!model) return;
 
-    if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
+    if (!getLocalPoint(v, e->x(), e->y(), m_editingPoint)) return;
 
     if (m_editingCommand) {
         finish(m_editingCommand);
@@ -904,7 +861,7 @@
     m_editing = false;
 
     Event p(0);
-    if (!getPointToDrag(v, e->x(), e->y(), p)) return;
+    if (!getLocalPoint(v, e->x(), e->y(), p)) return;
     if (p.getFrame() != m_editingPoint.getFrame() ||
         p.getValue() != m_editingPoint.getValue()) return;
 
@@ -924,7 +881,7 @@
     auto model = ModelById::getAs<BoxModel>(m_model);
     if (!model) return;
 
-    if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) {
+    if (!getLocalPoint(v, e->x(), e->y(), m_editingPoint)) {
         return;
     }
 
@@ -1008,7 +965,7 @@
     if (!model) return false;
 
     Event region(0);
-    if (!getPointToDrag(v, e->x(), e->y(), region)) return false;
+    if (!getLocalPoint(v, e->x(), e->y(), region)) return false;
 
     ItemEditDialog::LabelOptions labelOptions;
     labelOptions.valueLabel = tr("Minimum Value");