changeset 550:d666f5f8b154

* Make a better job of picking the proper point to drag, edit, delete etc in note and region layers * Some work to do with region dragging, but this still needs more thought
author Chris Cannam
date Mon, 28 Sep 2009 12:29:12 +0000
parents e6122e4999a3
children c2ba2796cbee
files layer/NoteLayer.cpp layer/NoteLayer.h layer/RegionLayer.cpp layer/RegionLayer.h
diffstat 4 files changed, 150 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/layer/NoteLayer.cpp	Fri Sep 25 12:02:22 2009 +0000
+++ b/layer/NoteLayer.cpp	Mon Sep 28 12:29:12 2009 +0000
@@ -404,6 +404,34 @@
     return usePoints;
 }
 
+bool
+NoteLayer::getPointToDrag(View *v, int x, int y, NoteModel::Point &p) const
+{
+    if (!m_model) return false;
+
+    long frame = v->getFrameForX(x);
+
+    NoteModel::PointList onPoints = m_model->getPoints(frame);
+    if (onPoints.empty()) return false;
+
+    std::cerr << "frame " << frame << ": " << onPoints.size() << " candidate points" << std::endl;
+
+    int nearestDistance = -1;
+
+    for (NoteModel::PointList::const_iterator i = onPoints.begin();
+         i != onPoints.end(); ++i) {
+        
+        int distance = getYForValue(v, (*i).value) - y;
+        if (distance < 0) distance = -distance;
+        if (nearestDistance == -1 || distance < nearestDistance) {
+            nearestDistance = distance;
+            p = *i;
+        }
+    }
+
+    return true;
+}
+
 QString
 NoteLayer::getFeatureDescription(View *v, QPoint &pos) const
 {
@@ -818,10 +846,12 @@
 {
     if (!m_model) return;
 
-    NoteModel::PointList points = getLocalPoints(v, e->x());
-    if (points.empty()) return;
+//    NoteModel::PointList points = getLocalPoints(v, e->x());
+//    if (points.empty()) return;
 
-    m_editingPoint = *points.begin();
+//    m_editingPoint = *points.begin();
+
+    if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
 
     if (m_editingCommand) {
 	finish(m_editingCommand);
@@ -843,13 +873,18 @@
 
     m_editing = false;
 
+/*
     NoteModel::PointList points = getLocalPoints(v, e->x());
     if (points.empty()) return;
     if (points.begin()->frame != m_editingPoint.frame ||
         points.begin()->value != m_editingPoint.value) return;
+*/
 
-    m_editingCommand = new NoteModel::EditCommand
-        (m_model, tr("Erase Point"));
+    NoteModel::Point p(0);
+    if (!getPointToDrag(v, e->x(), e->y(), p)) return;
+    if (p.frame != m_editingPoint.frame || p.value != m_editingPoint.value) return;
+
+    m_editingCommand = new NoteModel::EditCommand(m_model, tr("Erase Point"));
 
     m_editingCommand->deletePoint(m_editingPoint);
 
@@ -865,10 +900,14 @@
 
     if (!m_model) return;
 
+/*
     NoteModel::PointList points = getLocalPoints(v, e->x());
     if (points.empty()) return;
 
     m_editingPoint = *points.begin();
+*/
+
+    if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
     m_originalPoint = m_editingPoint;
 
     if (m_editingCommand) {
@@ -935,11 +974,15 @@
 NoteLayer::editOpen(View *v, QMouseEvent *e)
 {
     if (!m_model) return false;
-
+/*
     NoteModel::PointList points = getLocalPoints(v, e->x());
     if (points.empty()) return false;
+*/
 
-    NoteModel::Point note = *points.begin();
+    NoteModel::Point note(0);
+    if (!getPointToDrag(v, e->x(), e->y(), note)) return false;
+
+//    NoteModel::Point note = *points.begin();
 
     ItemEditDialog *dialog = new ItemEditDialog
         (m_model->getSampleRate(),
--- a/layer/NoteLayer.h	Fri Sep 25 12:02:22 2009 +0000
+++ b/layer/NoteLayer.h	Mon Sep 28 12:29:12 2009 +0000
@@ -135,6 +135,8 @@
 
     NoteModel::PointList getLocalPoints(View *v, int) const;
 
+    bool getPointToDrag(View *v, int x, int y, NoteModel::Point &) const;
+
     NoteModel *m_model;
     bool m_editing;
     NoteModel::Point m_originalPoint;
--- a/layer/RegionLayer.cpp	Fri Sep 25 12:02:22 2009 +0000
+++ b/layer/RegionLayer.cpp	Mon Sep 28 12:29:12 2009 +0000
@@ -327,6 +327,32 @@
     return usePoints;
 }
 
+bool
+RegionLayer::getPointToDrag(View *v, int x, int y, RegionModel::Point &p) const
+{
+    if (!m_model) return false;
+
+    long frame = v->getFrameForX(x);
+
+    RegionModel::PointList onPoints = m_model->getPoints(frame);
+    if (onPoints.empty()) return false;
+
+    int nearestDistance = -1;
+
+    for (RegionModel::PointList::const_iterator i = onPoints.begin();
+         i != onPoints.end(); ++i) {
+        
+        int distance = getYForValue(v, (*i).value) - y;
+        if (distance < 0) distance = -distance;
+        if (nearestDistance == -1 || distance < nearestDistance) {
+            nearestDistance = distance;
+            p = *i;
+        }
+    }
+
+    return true;
+}
+
 QString
 RegionLayer::getFeatureDescription(View *v, QPoint &pos) const
 {
@@ -760,6 +786,9 @@
         textY = v->getTextLabelHeight(this, paint);
     }
     
+    int fontHeight = paint.fontMetrics().height();
+    int fontAscent = paint.fontMetrics().ascent();
+
     for (RegionModel::PointList::const_iterator i = points.begin();
 	 i != points.end(); ++i) {
 
@@ -781,10 +810,9 @@
         }
 
         if (m_plotStyle != PlotSegmentation) {
-            textY = y - paint.fontMetrics().height()
-                      + paint.fontMetrics().ascent();
-            if (textY < paint.fontMetrics().ascent() + 1) {
-                textY = paint.fontMetrics().ascent() + 1;
+            textY = y - fontHeight + fontAscent;
+            if (textY < fontAscent + 1) {
+                textY = fontAscent + 1;
             }
         }
 
@@ -829,11 +857,11 @@
             paint.drawLine(x+w, y - h/2, x + w, y + h/2);
         }
 
-	if (p.label != "") {
-//            if (ex > x + 6 + paint.fontMetrics().width(p.label)) {
-                paint.drawText(x + 5, textY, p.label);
-//            }
-	}
+        QString label = p.label;
+	if (label == "") {
+            label = QString("[%1]").arg(p.value);
+        }
+        v->drawVisibleText(paint, x + 5, textY, label, View::OutlinedText);
     }
 
     paint.restore();
@@ -852,7 +880,7 @@
 
     float value = getValueForY(v, e->y());
 
-    m_editingPoint = RegionModel::Point(frame, value, 0, tr("New Region"));
+    m_editingPoint = RegionModel::Point(frame, value, 0, "");
     m_originalPoint = m_editingPoint;
 
     if (m_editingCommand) finish(m_editingCommand);
@@ -860,6 +888,8 @@
                                                     tr("Draw Region"));
     m_editingCommand->addPoint(m_editingPoint);
 
+    recalcSpacing();
+
     m_editing = true;
 }
 
@@ -891,6 +921,8 @@
     m_editingPoint.value = newValue;
     m_editingPoint.duration = newDuration;
     m_editingCommand->addPoint(m_editingPoint);
+
+//    recalcSpacing();
 }
 
 void
@@ -901,6 +933,8 @@
     finish(m_editingCommand);
     m_editingCommand = 0;
     m_editing = false;
+
+    recalcSpacing();
 }
 
 void
@@ -908,17 +942,20 @@
 {
     if (!m_model) return;
 
+    if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
+/*
     RegionModel::PointList points = getLocalPoints(v, e->x());
     if (points.empty()) return;
 
     m_editingPoint = *points.begin();
-
+*/
     if (m_editingCommand) {
 	finish(m_editingCommand);
 	m_editingCommand = 0;
     }
 
     m_editing = true;
+    recalcSpacing();
 }
 
 void
@@ -932,11 +969,15 @@
     if (!m_model || !m_editing) return;
 
     m_editing = false;
-
+/*
     RegionModel::PointList points = getLocalPoints(v, e->x());
     if (points.empty()) return;
     if (points.begin()->frame != m_editingPoint.frame ||
         points.begin()->value != m_editingPoint.value) return;
+*/
+    RegionModel::Point p(0);
+    if (!getPointToDrag(v, e->x(), e->y(), p)) return;
+    if (p.frame != m_editingPoint.frame || p.value != m_editingPoint.value) return;
 
     m_editingCommand = new RegionModel::EditCommand
         (m_model, tr("Erase Region"));
@@ -946,19 +987,28 @@
     finish(m_editingCommand);
     m_editingCommand = 0;
     m_editing = false;
+    recalcSpacing();
 }
 
 void
 RegionLayer::editStart(View *v, QMouseEvent *e)
 {
-//    std::cerr << "RegionLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
+    std::cerr << "RegionLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
 
     if (!m_model) return;
 
-    RegionModel::PointList points = getLocalPoints(v, e->x());
-    if (points.empty()) return;
+//    OrderedPointList opoints = getNearbyPoints(v, e->x(), e->y());
+//    RegionLayer:
 
-    m_editingPoint = *points.begin();
+//    RegionModel::PointList points = getLocalPoints(v, e->x());
+//    if (points.empty()) return;
+
+//    m_editingPoint = *points.begin();
+    
+    if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) {
+        return;
+    }
+
     m_originalPoint = m_editingPoint;
 
     if (m_editingCommand) {
@@ -967,12 +1017,15 @@
     }
 
     m_editing = true;
+    m_dragYOrigin = e->y();
+    m_dragYRebase = e->y();
+    recalcSpacing();
 }
 
 void
 RegionLayer::editDrag(View *v, QMouseEvent *e)
 {
-//    std::cerr << "RegionLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
+    std::cerr << "RegionLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
 
     if (!m_model || !m_editing) return;
 
@@ -980,23 +1033,31 @@
     if (frame < 0) frame = 0;
     frame = frame / m_model->getResolution() * m_model->getResolution();
 
-    float value = getValueForY(v, e->y());
+    int activeY = e->y() + (m_dragYRebase - m_dragYOrigin);
+    float value = getValueForY(v, activeY);
 
     if (!m_editingCommand) {
 	m_editingCommand = new RegionModel::EditCommand(m_model,
 						      tr("Drag Region"));
     }
 
+    if (m_verticalScale == EqualSpaced) {
+        if (getYForValue(v, value) != getYForValue(v, m_editingPoint.value)) {
+            m_dragYRebase = e->y();
+        }
+    }
+
     m_editingCommand->deletePoint(m_editingPoint);
     m_editingPoint.frame = frame;
     m_editingPoint.value = value;
     m_editingCommand->addPoint(m_editingPoint);
+    recalcSpacing();
 }
 
 void
-RegionLayer::editEnd(View *, QMouseEvent *)
+RegionLayer::editEnd(View *, QMouseEvent *e)
 {
-//    std::cerr << "RegionLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
+    std::cerr << "RegionLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
     if (!m_model || !m_editing) return;
 
     if (m_editingCommand) {
@@ -1019,17 +1080,22 @@
 
     m_editingCommand = 0;
     m_editing = false;
+    recalcSpacing();
 }
 
 bool
 RegionLayer::editOpen(View *v, QMouseEvent *e)
 {
     if (!m_model) return false;
-
+/*
     RegionModel::PointList points = getLocalPoints(v, e->x());
     if (points.empty()) return false;
+*/
 
-    RegionModel::Point region = *points.begin();
+    RegionModel::Point region(0);
+    if (!getPointToDrag(v, e->x(), e->y(), region)) return false;
+
+//    RegionModel::Point region = *points.begin();
 
     ItemEditDialog *dialog = new ItemEditDialog
         (m_model->getSampleRate(),
@@ -1060,6 +1126,7 @@
     }
 
     delete dialog;
+    recalcSpacing();
     return true;
 }
 
@@ -1086,6 +1153,7 @@
     }
 
     finish(command);
+    recalcSpacing();
 }
 
 void
@@ -1125,6 +1193,7 @@
     }
 
     finish(command);
+    recalcSpacing();
 }
 
 void
@@ -1147,6 +1216,7 @@
     }
 
     finish(command);
+    recalcSpacing();
 }    
 
 void
@@ -1244,6 +1314,7 @@
     }
 
     finish(command);
+    recalcSpacing();
     return true;
 }
 
--- a/layer/RegionLayer.h	Fri Sep 25 12:02:22 2009 +0000
+++ b/layer/RegionLayer.h	Mon Sep 28 12:29:12 2009 +0000
@@ -125,10 +125,14 @@
 
     virtual int getDefaultColourHint(bool dark, bool &impose);
 
-    RegionModel::PointList getLocalPoints(View *v, int) const;
+    RegionModel::PointList getLocalPoints(View *v, int x) const;
+
+    bool getPointToDrag(View *v, int x, int y, RegionModel::Point &) const;
 
     RegionModel *m_model;
     bool m_editing;
+    int m_dragYOrigin;
+    int m_dragYRebase;
     RegionModel::Point m_originalPoint;
     RegionModel::Point m_editingPoint;
     RegionModel::EditCommand *m_editingCommand;