]> git.sesse.net Git - kdenlive/blobdiff - src/beziercurve/beziersplineeditor.cpp
Integrate with the required MLT hooks for getting Movit to work.
[kdenlive] / src / beziercurve / beziersplineeditor.cpp
index a5a5484c18d5695b583701d8a55ec5337fc61483..2ea438302bf49929eb2ed5bfd16dbc628a93edca 100644 (file)
  ***************************************************************************/
 
 #include "beziersplineeditor.h"
+#include "kdenlivesettings.h"
 
 #include <QPainter>
 #include <QMouseEvent>
 
 
 BezierSplineEditor::BezierSplineEditor(QWidget* parent) :
-        QWidget(parent),
-        m_mode(ModeNormal),
-        m_zoomLevel(0),
-        m_gridLines(3),
-        m_pixmapCache(NULL),
-        m_pixmapIsDirty(true),
-        m_currentPointIndex(-1)
+        QWidget(parent)
+        , m_mode(ModeNormal)
+        , m_zoomLevel(0)
+        , m_gridLines(3)
+        , m_showAllHandles(true)
+        , m_pixmapCache(NULL)
+        , m_pixmapIsDirty(true)
+        , m_currentPointIndex(-1)
+       , m_currentPointType(PTypeP)
+       , m_grabOffsetX(0)
+       , m_grabOffsetY(0)
 {
     setMouseTracking(true);
     setAutoFillBackground(false);
@@ -40,35 +45,40 @@ BezierSplineEditor::BezierSplineEditor(QWidget* parent) :
 
 BezierSplineEditor::~BezierSplineEditor()
 {
-    if (m_pixmapCache)
-        delete m_pixmapCache;
+    delete m_pixmapCache;
 }
 
-CubicBezierSpline BezierSplineEditor::spline()
+CubicBezierSpline BezierSplineEditor::spline() const
 {
     return m_spline;
 }
 
 void BezierSplineEditor::setSpline(const CubicBezierSpline& spline)
 {
-    // TODO: cleanup
-    m_spline.fromString(spline.toString());
+    m_spline = spline;
+    m_currentPointIndex = -1;
+    m_mode = ModeNormal;
+    emit currentPoint(BPoint());
+    emit modified();
+    update();
 }
 
 BPoint BezierSplineEditor::getCurrentPoint()
 {
     if (m_currentPointIndex >= 0)
-        return m_spline.points()[m_currentPointIndex];
+        return m_spline.getPoint(m_currentPointIndex);
     else
         return BPoint();
 }
 
-void BezierSplineEditor::updateCurrentPoint(const BPoint& p)
+void BezierSplineEditor::updateCurrentPoint(const BPoint& p, bool final)
 {
     if (m_currentPointIndex >= 0) {
         m_spline.setPoint(m_currentPointIndex, p);
         // during validation the point might have changed
-        emit currentPoint(m_spline.points()[m_currentPointIndex]);
+        emit currentPoint(m_spline.getPoint(m_currentPointIndex));
+        if (final)
+            emit modified();
         update();
     }
 }
@@ -94,7 +104,15 @@ void BezierSplineEditor::slotZoomOut()
     update();
 }
 
-int BezierSplineEditor::gridLines()
+void BezierSplineEditor::setShowAllHandles(bool show)
+{
+    if (m_showAllHandles != show) {
+        m_showAllHandles = show;
+        update();
+    }
+}
+
+int BezierSplineEditor::gridLines() const
 {
     return m_gridLines;
 }
@@ -107,20 +125,26 @@ void BezierSplineEditor::setGridLines(int lines)
 
 void BezierSplineEditor::paintEvent(QPaintEvent* event)
 {
-    Q_UNUSED(event);
+    Q_UNUSED(event)
 
     QPainter p(this);
 
+    /*
+     * Zoom
+     */
     int wWidth = width() - 1;
     int wHeight = height() - 1;
-    int offset = 1/8. * m_zoomLevel * (wWidth > wHeight ? wWidth : wHeight);
-    wWidth -= 2 * offset;
-    wHeight -= 2 * offset;
+    int offsetX = 1/8. * m_zoomLevel * wWidth;
+    int offsetY = 1/8. * m_zoomLevel * wHeight;
+    wWidth -= 2 * offsetX;
+    wHeight -= 2 * offsetY;
+
+    p.translate(offsetX, offsetY);
 
     /*
      * Background
      */
-    p.fillRect(rect(), palette().background());
+    p.fillRect(rect().translated(-offsetX, -offsetY), palette().background());
     if (!m_pixmap.isNull()) {
         if (m_pixmapIsDirty || !m_pixmapCache) {
             if (m_pixmapCache)
@@ -132,7 +156,7 @@ void BezierSplineEditor::paintEvent(QPaintEvent* event)
             cachePainter.drawPixmap(0, 0, m_pixmap);
             m_pixmapIsDirty = false;
         }
-        p.drawPixmap(offset, offset, *m_pixmapCache);
+        p.drawPixmap(0, 0, *m_pixmapCache);
     }
 
 
@@ -142,7 +166,7 @@ void BezierSplineEditor::paintEvent(QPaintEvent* event)
      * Borders
      */
     if (m_zoomLevel != 0) {
-        p.drawRect(offset, offset, wWidth, wHeight);
+        p.drawRect(0, 0, wWidth, wHeight);
     }
 
     /*
@@ -152,8 +176,8 @@ void BezierSplineEditor::paintEvent(QPaintEvent* event)
         double stepH = wWidth / (double)(m_gridLines + 1);
         double stepV = wHeight / (double)(m_gridLines + 1);
         for (int i = 1; i <= m_gridLines; ++i) {
-            p.drawLine(QLineF(i * stepH, 0, i * stepH, wHeight).translated(offset, offset));
-            p.drawLine(QLineF(0, i * stepV, wWidth, i * stepV).translated(offset, offset));
+            p.drawLine(QLineF(i * stepH, 0, i * stepH, wHeight));
+            p.drawLine(QLineF(0, i * stepV, wWidth, i * stepV));
         }
     }
 
@@ -162,63 +186,75 @@ void BezierSplineEditor::paintEvent(QPaintEvent* event)
     /*
      * Standard line
      */
-    p.drawLine(QLineF(0, wHeight, wWidth, 0).translated(offset, offset));
+    p.drawLine(QLineF(0, wHeight, wWidth, 0));
+
+
+    /*
+     * Prepare Spline, Points
+     */
+    int max = m_spline.points().count() - 1;
+    if (max < 1)
+        return;
+    BPoint point(m_spline.getPoint(0, wWidth, wHeight, true));
 
     /*
      * Spline
      */
-    double prevY = wHeight - m_spline.value(0.) * wHeight;
-    double prevX = 0.;
-    double curY;
-    double normalizedX = -1;
-    int x;
+    BPoint next;
     
-    p.setPen(QPen(Qt::black, 1, Qt::SolidLine));
-    for (x = 0 ; x < wWidth ; ++x) {
-        normalizedX = x / (double)wWidth;
-        curY = wHeight - m_spline.value(normalizedX, true) * wHeight;
-
-        /*
-         * Keep in mind that QLineF rounds doubles
-         * to ints mathematically, not just rounds down
-         * like in C
-         */
-        p.drawLine(QLineF(prevX, prevY,
-                          x, curY).translated(offset, offset));
-        prevX = x;
-        prevY = curY;
+    QPainterPath splinePath(QPointF(point.p.x(), point.p.y()));
+    for (int i = 0; i < max; ++i) {
+        point = m_spline.getPoint(i, wWidth, wHeight, true);
+        next = m_spline.getPoint(i + 1, wWidth, wHeight, true);
+        splinePath.cubicTo(point.h2, next.h1, next.p);
     }
-    p.drawLine(QLineF(prevX, prevY ,
-                      x, wHeight - m_spline.value(1.0, true) * wHeight).translated(offset, offset));
+    p.setPen(QPen(Qt::black, 1, Qt::SolidLine));
+    p.drawPath(splinePath);
+
 
     /*
      * Points + Handles
      */
-    int max = m_spline.points().count() - 1;
     p.setPen(QPen(Qt::red, 1, Qt::SolidLine));
-    BPoint point;
-    QPolygon handle(4);
-    handle.setPoints(4,
-                     1,  -2,
-                     4,  1,
-                     1,  4,
-                     -2, 1);
+
+    QPolygonF handle = QPolygonF() << QPointF(0, -3) << QPointF(3, 0) << QPointF(0, 3) << QPointF(-3, 0);
+#if QT_VERSION < 0x040600
+    QPolygonF tmp;
+#endif
+
     for (int i = 0; i <= max; ++i) {
-        point = m_spline.points().at(i);
+        point = m_spline.getPoint(i, wWidth, wHeight, true);
+
         if (i == m_currentPointIndex) {
+            // selected point: fill p and handles
             p.setBrush(QBrush(QColor(Qt::red), Qt::SolidPattern));
+            // connect p and handles with lines
             if (i != 0)
-                p.drawLine(QLineF(point.h1.x() * wWidth, wHeight - point.h1.y() * wHeight, point.p.x() * wWidth, wHeight - point.p.y() * wHeight).translated(offset, offset));
+                p.drawLine(QLineF(point.h1.x(), point.h1.y(), point.p.x(),point.p.y()));
             if (i != max)
-                p.drawLine(QLineF(point.p.x() * wWidth, wHeight - point.p.y() * wHeight, point.h2.x() * wWidth, wHeight - point.h2.y() * wHeight).translated(offset, offset));
+                p.drawLine(QLineF(point.p.x(), point.p.y(), point.h2.x(), point.h2.y()));
         }
 
-        p.drawEllipse(QRectF(point.p.x() * wWidth - 3,
-                             wHeight - 3 - point.p.y() * wHeight, 6, 6).translated(offset, offset));
-        if (i != 0)
-            p.drawConvexPolygon(handle.translated(point.h1.x() * wWidth, wHeight - point.h1.y() * wHeight).translated(offset, offset));
-        if (i != max)
-            p.drawConvexPolygon(handle.translated(point.h2.x() * wWidth, wHeight - point.h2.y() * wHeight).translated(offset, offset));
+        p.drawEllipse(QRectF(point.p.x() - 3,
+                             point.p.y() - 3, 6, 6));
+        if (i != 0 && (i == m_currentPointIndex || m_showAllHandles)) {
+#if QT_VERSION >= 0x040600
+            p.drawConvexPolygon(handle.translated(point.h1.x(), point.h1.y()));
+#else
+            tmp = handle;
+            tmp.translate(point.h1.x(), point.h1.y());
+            p.drawConvexPolygon(tmp);
+#endif
+        }
+        if (i != max && (i == m_currentPointIndex || m_showAllHandles)) {
+#if QT_VERSION >= 0x040600
+            p.drawConvexPolygon(handle.translated(point.h2.x(), point.h2.y()));
+#else
+            tmp = handle;
+            tmp.translate(point.h2.x(), point.h2.y());
+            p.drawConvexPolygon(tmp);
+#endif
+        }
 
         if ( i == m_currentPointIndex)
             p.setBrush(QBrush(Qt::NoBrush));
@@ -227,7 +263,6 @@ void BezierSplineEditor::paintEvent(QPaintEvent* event)
 
 void BezierSplineEditor::resizeEvent(QResizeEvent* event)
 {
-    m_spline.setPrecision(width());
     m_pixmapIsDirty = true;
     QWidget::resizeEvent(event);
 }
@@ -236,12 +271,13 @@ void BezierSplineEditor::mousePressEvent(QMouseEvent* event)
 {
     int wWidth = width() - 1;
     int wHeight = height() - 1;
-    int offset = 1/8. * m_zoomLevel * (wWidth > wHeight ? wWidth : wHeight);
-    wWidth -= 2 * offset;
-    wHeight -= 2 * offset;
+    int offsetX = 1/8. * m_zoomLevel * wWidth;
+    int offsetY = 1/8. * m_zoomLevel * wHeight;
+    wWidth -= 2 * offsetX;
+    wHeight -= 2 * offsetY;
 
-    double x = (event->pos().x() - offset) / (double)(wWidth);
-    double y = 1.0 - (event->pos().y() - offset) / (double)(wHeight);
+    double x = (event->pos().x() - offsetX) / (double)(wWidth);
+    double y = 1.0 - (event->pos().y() - offsetY) / (double)(wHeight);
 
     point_types selectedPoint;
     int closestPointIndex = nearestPointInRange(QPointF(x, y), wWidth, wHeight, &selectedPoint);
@@ -254,7 +290,7 @@ void BezierSplineEditor::mousePressEvent(QMouseEvent* event)
             --m_currentPointIndex;
         update();
         if (m_currentPointIndex >= 0)
-            emit currentPoint(m_spline.points()[m_currentPointIndex]);
+            emit currentPoint(m_spline.getPoint(m_currentPointIndex));
         else
             emit currentPoint(BPoint());
         emit modified();
@@ -264,49 +300,28 @@ void BezierSplineEditor::mousePressEvent(QMouseEvent* event)
     }
 
     if (closestPointIndex < 0) {
-        BPoint po;
-        po.p = QPointF(x, y);
-        po.h1 = QPointF(x-0.05, y-0.05);
-        po.h2 = QPointF(x+0.05, y+0.05);
-        m_currentPointIndex = m_spline.addPoint(po);
+        m_currentPointIndex = m_spline.addPoint(BPoint(QPointF(x-0.05, y-0.05),
+                                                       QPointF(x, y),
+                                                       QPointF(x+0.05, y+0.05)));
         m_currentPointType = PTypeP;
-        /*if (!d->jumpOverExistingPoints(newPoint, -1)) return;*/
     } else {
         m_currentPointIndex = closestPointIndex;
         m_currentPointType = selectedPoint;
     }
 
-    BPoint point = m_spline.points()[m_currentPointIndex];
-    QPointF p;
-    switch (m_currentPointType) {
-    case PTypeH1:
-        p = point.h1;
-        break;
-    case PTypeP:
-        p = point.p;
-        break;
-    case PTypeH2:
-        p = point.h2;
-    }
+    BPoint point = m_spline.getPoint(m_currentPointIndex);
 
-    m_grabOriginalX = p.x();
-    m_grabOriginalY = p.y();
-    m_grabOffsetX = p.x() - x;
-    m_grabOffsetY = p.y() - y;
+    m_grabPOriginal = point;
+    if (m_currentPointIndex > 0)
+        m_grabPPrevious = m_spline.getPoint(m_currentPointIndex - 1);
+    if (m_currentPointIndex < m_spline.points().count() - 1)
+        m_grabPNext = m_spline.getPoint(m_currentPointIndex + 1);
+    m_grabOffsetX = point[(int)m_currentPointType].x() - x;
+    m_grabOffsetY = point[(int)m_currentPointType].y() - y;
 
-    switch (m_currentPointType) {
-        case PTypeH1:
-            point.h1 = QPointF(x + m_grabOffsetX, y + m_grabOffsetY);
-            break;
-        case PTypeP:
-            point.p = QPointF(x + m_grabOffsetX, y + m_grabOffsetY);
-            break;
-        case PTypeH2:
-            point.h2 = QPointF(x + m_grabOffsetX, y + m_grabOffsetY);
-    }
-    m_spline.setPoint(m_currentPointIndex, point);
+    point[(int)m_currentPointType] = QPointF(x + m_grabOffsetX, y + m_grabOffsetY);
 
-    //d->m_draggedAwayPointIndex = -1;
+    m_spline.setPoint(m_currentPointIndex, point);
 
     m_mode = ModeDrag;
 
@@ -329,157 +344,150 @@ void BezierSplineEditor::mouseMoveEvent(QMouseEvent* event)
 {
     int wWidth = width() - 1;
     int wHeight = height() - 1;
-    int offset = 1/8. * m_zoomLevel * (wWidth > wHeight ? wWidth : wHeight);
-    wWidth -= 2 * offset;
-    wHeight -= 2 * offset;
+    int offsetX = 1/8. * m_zoomLevel * wWidth;
+    int offsetY = 1/8. * m_zoomLevel * wHeight;
+    wWidth -= 2 * offsetX;
+    wHeight -= 2 * offsetY;
 
-    double x = (event->pos().x() - offset) / (double)(wWidth);
-    double y = 1.0 - (event->pos().y() - offset) / (double)(wHeight);
+    double x = (event->pos().x() - offsetX) / (double)(wWidth);
+    double y = 1.0 - (event->pos().y() - offsetY) / (double)(wHeight);
     
-    if (m_mode == ModeNormal) { // If no point is selected set the the cursor shape if on top
+    if (m_mode == ModeNormal) {
+        // If no point is selected set the the cursor shape if on top
         point_types type;
         int nearestPointIndex = nearestPointInRange(QPointF(x, y), wWidth, wHeight, &type);
-        
+
         if (nearestPointIndex < 0)
             setCursor(Qt::ArrowCursor);
         else
             setCursor(Qt::CrossCursor);
-    } else { // Else, drag the selected point
-        /*bool crossedHoriz = event->pos().x() - width() > MOUSE_AWAY_THRES ||
-        event->pos().x() < -MOUSE_AWAY_THRES;
-        bool crossedVert =  event->pos().y() - height() > MOUSE_AWAY_THRES ||
-        event->pos().y() < -MOUSE_AWAY_THRES;
-        
-        bool removePoint = (crossedHoriz || crossedVert);
-        
-        if (!removePoint && d->m_draggedAwayPointIndex >= 0) {
-            // point is no longer dragged away so reinsert it
-            QPointF newPoint(d->m_draggedAwayPoint);
-            d->m_grab_point_index = d->m_curve.addPoint(newPoint);
-            d->m_draggedAwayPointIndex = -1;
-        }
-        
-        if (removePoint &&
-            (d->m_draggedAwayPointIndex >= 0))
-            return;
-        */
-        
+    } else {
+        // Else, drag the selected point
         setCursor(Qt::CrossCursor);
-        
+
         x += m_grabOffsetX;
         y += m_grabOffsetY;
-        
-        double leftX, rightX;
-        BPoint point = m_spline.points()[m_currentPointIndex];
+
+        double leftX = 0.;
+        double rightX = 1.;
+        BPoint point = m_spline.getPoint(m_currentPointIndex);
         switch (m_currentPointType) {
         case PTypeH1:
             rightX = point.p.x();
             if (m_currentPointIndex == 0)
-                leftX = -1000;
+                leftX = -4;
             else
-                leftX = m_spline.points()[m_currentPointIndex - 1].p.x();
+                leftX = m_spline.getPoint(m_currentPointIndex - 1).p.x();
+
             x = qBound(leftX, x, rightX);
-            point.h1 = QPointF(x, y);
+            point.setH1(QPointF(x, y));
             break;
+
         case PTypeP:
-            if (m_currentPointIndex == 0) {
-                leftX = 0.0;
+            if (m_currentPointIndex == 0)
                 rightX = 0.0;
-                /*if (d->m_curve.points().count() > 1)
-                 *           rightX = d->m_curve.points()[d->m_grab_point_index + 1].x() - POINT_AREA;
-                 *       else
-                 *           rightX = 1.0;*/
-            } else if (m_currentPointIndex == m_spline.points().count() - 1) {
-                leftX = 1.0;//m_spline.points()[m_currentPointIndex - 1].p.x();
-                rightX = 1.0;
-            } else {
-                //// the 1E-4 addition so we can grab the dot later.
-                leftX = m_spline.points()[m_currentPointIndex - 1].p.x();// + POINT_AREA;
-                rightX = m_spline.points()[m_currentPointIndex + 1].p.x();// - POINT_AREA;
-            }
+            else if (m_currentPointIndex == m_spline.points().count() - 1)
+                leftX = 1.0;
+
             x = qBound(leftX, x, rightX);
             y = qBound(0., y, 1.);
 
-            // move handles by same offset
-            point.h1 += QPointF(x, y) - point.p;
-            point.h2 += QPointF(x, y) - point.p;
+            // handles might have changed because we neared another point
+            // try to restore
+            point.h1 = m_grabPOriginal.h1;
+            point.h2 = m_grabPOriginal.h2;
+            // and move by same offset
+            // (using update handle in point.setP won't work because the offset between new and old point is very small)
+            point.h1 += QPointF(x, y) - m_grabPOriginal.p;
+            point.h2 += QPointF(x, y) - m_grabPOriginal.p;
 
-            point.p = QPointF(x, y);
+            point.setP(QPointF(x, y), false);
             break;
+
         case PTypeH2:
             leftX = point.p.x();
             if (m_currentPointIndex == m_spline.points().count() - 1)
-                rightX = 1001;
+                rightX = 5;
             else
-                rightX = m_spline.points()[m_currentPointIndex + 1].p.x();
+                rightX = m_spline.getPoint(m_currentPointIndex + 1).p.x();
+
             x = qBound(leftX, x, rightX);
-            point.h2 = QPointF(x, y);
+            point.setH2(QPointF(x, y));
         };
 
-        m_spline.setPoint(m_currentPointIndex, point);
-        
-        /*if (removePoint && d->m_curve.points().count() > 2) {
-            d->m_draggedAwayPoint = d->m_curve.points()[d->m_grab_point_index];
-            d->m_draggedAwayPointIndex = d->m_grab_point_index;
-            d->m_curve.removePoint(d->m_grab_point_index);
-            d->m_grab_point_index = bounds(d->m_grab_point_index, 0, d->m_curve.points().count() - 1);
+        int index = m_currentPointIndex;
+        m_currentPointIndex = m_spline.setPoint(m_currentPointIndex, point);
+
+        if (m_currentPointType == PTypeP) {
+            // we might have changed the handles of other points
+            // try to restore
+            if (index == m_currentPointIndex) {
+                if (m_currentPointIndex > 0)
+                    m_spline.setPoint(m_currentPointIndex - 1, m_grabPPrevious);
+                if (m_currentPointIndex < m_spline.points().count() -1)
+                    m_spline.setPoint(m_currentPointIndex + 1, m_grabPNext);
+            } else {
+                if (m_currentPointIndex < index) {
+                    m_spline.setPoint(index, m_grabPPrevious);
+                    m_grabPNext = m_grabPPrevious;
+                    if (m_currentPointIndex > 0)
+                        m_grabPPrevious = m_spline.getPoint(m_currentPointIndex - 1);
+                } else {
+                    m_spline.setPoint(index, m_grabPNext);
+                    m_grabPPrevious = m_grabPNext;
+                    if (m_currentPointIndex < m_spline.points().count() - 1)
+                        m_grabPNext = m_spline.getPoint(m_currentPointIndex + 1);
+                }
+            }
         }
-        
-        d->setCurveModified();*/
+
         emit currentPoint(point);
+        if (KdenliveSettings::dragvalue_directupdate())
+            emit modified();
         update();
     }
 }
 
+void BezierSplineEditor::mouseDoubleClickEvent(QMouseEvent* /*event*/)
+{
+    if (m_currentPointIndex >= 0) {
+        BPoint p = m_spline.getPoint(m_currentPointIndex);
+        p.handlesLinked = !p.handlesLinked;
+        m_spline.setPoint(m_currentPointIndex, p);
+        emit currentPoint(p);
+    }
+}
+
 void BezierSplineEditor::leaveEvent(QEvent* event)
 {
     QWidget::leaveEvent(event);
 }
 
-int BezierSplineEditor::nearestPointInRange(QPointF p, int wWidth, int wHeight, BezierSplineEditor::point_types* sel)
+int BezierSplineEditor::nearestPointInRange(const QPointF &p, int wWidth, int wHeight, BezierSplineEditor::point_types* sel)
 {
     double nearestDistanceSquared = 1000;
-    point_types selectedPoint;
+    point_types selectedPoint = PTypeP;
     int nearestIndex = -1;
     int i = 0;
 
     double distanceSquared;
+    // find out distance using the Pythagorean theorem
     foreach(const BPoint & point, m_spline.points()) {
-        distanceSquared = pow(point.h1.x() - p.x(), 2) + pow(point.h1.y() - p.y(), 2);
-        if (distanceSquared < nearestDistanceSquared) {
-            nearestIndex = i;
-            nearestDistanceSquared = distanceSquared;
-            selectedPoint = PTypeH1;
-        }
-        distanceSquared = pow(point.p.x() - p.x(), 2) + pow(point.p.y() - p.y(), 2);
-        if (distanceSquared < nearestDistanceSquared) {
-            nearestIndex = i;
-            nearestDistanceSquared = distanceSquared;
-            selectedPoint = PTypeP;
-        }
-        distanceSquared = pow(point.h2.x() - p.x(), 2) + pow(point.h2.y() - p.y(), 2);
-        if (distanceSquared < nearestDistanceSquared) {
-            nearestIndex = i;
-            nearestDistanceSquared = distanceSquared;
-            selectedPoint = PTypeH2;
+        for (int j = 0; j < 3; ++j) {
+            distanceSquared = pow(point[j].x() - p.x(), 2) + pow(point[j].y() - p.y(), 2);
+            if (distanceSquared < nearestDistanceSquared) {
+                nearestIndex = i;
+                nearestDistanceSquared = distanceSquared;
+                selectedPoint = (point_types)j;
+            }
         }
         ++i;
     }
 
-    if (nearestIndex >= 0) {
-        BPoint point = m_spline.points()[nearestIndex];
-        QPointF p2;
-        switch (selectedPoint) {
-        case PTypeH1:
-            p2 = point.h1;
-            break;
-        case PTypeP:
-            p2 = point.p;
-            break;
-        case PTypeH2:
-            p2 = point.h2;
-        }
-        if (qAbs(p.x() - p2.x()) * wWidth < 5 && qAbs(p.y() - p2.y()) * wHeight < 5) {
+    if (nearestIndex >= 0 && (nearestIndex == m_currentPointIndex || selectedPoint == PTypeP || m_showAllHandles)) {
+        // a point was found and it is not a hidden handle
+        BPoint point = m_spline.getPoint(nearestIndex);
+        if (qAbs(p.x() - point[(int)selectedPoint].x()) * wWidth < 5 && qAbs(p.y() - point[(int)selectedPoint].y()) * wHeight < 5) {
             *sel = selectedPoint;
             return nearestIndex;
         }