diff view/Pane.cpp @ 343:1b6879d03cb6

* Fix #1848191 double clicking on time instants causes move Also fix tendency for navigate mode to continue navigating even after button release
author Chris Cannam
date Tue, 18 Dec 2007 10:35:55 +0000
parents 998786b3174f
children 6167a28d25fc
line wrap: on
line diff
--- a/view/Pane.cpp	Mon Dec 17 12:32:28 2007 +0000
+++ b/view/Pane.cpp	Tue Dec 18 10:35:55 2007 +0000
@@ -64,6 +64,8 @@
     m_ctrlPressed(false),
     m_navigating(false),
     m_resizing(false),
+    m_editing(false),
+    m_releasing(false),
     m_centreLineVisible(true),
     m_scaleWidth(0),
     m_headsUpDisplay(0),
@@ -1211,25 +1213,7 @@
         return;
     }
 
-    std::cerr << "mousePressEvent" << std::endl;
-
-    
-    //!!! need to avoid spurious mouse events when e.g. double-clicking.
-
-    // when double clicking, we get:
-    // mousePressEvent
-    // mouseReleaseEvent
-    // mouseMoveEvent <- called from mouseReleaseEvent
-    // mouseDoubleClickEvent
-    // mouseReleaseEvent
-    // mouseMoveEvent <- called from mouseReleaseEvent
-
-    // so we set a timer on the first press, if we're in a mode in
-    // which moving the mouse will do something
-
-    // the move method doesn't do anything unless that timer has
-    // elapsed
-    
+//    std::cerr << "mousePressEvent" << std::endl;
 
     m_clickPos = e->pos();
     m_mousePos = m_clickPos;
@@ -1244,6 +1228,9 @@
     if (m_manager) mode = m_manager->getToolMode();
 
     m_navigating = false;
+    m_resizing = false;
+    m_editing = false;
+    m_releasing = false;
 
     if (mode == ViewManager::NavigateMode ||
         (e->buttons() & Qt::MidButton) ||
@@ -1325,12 +1312,8 @@
 
     } else if (mode == ViewManager::EditMode) {
 
-	if (!editSelectionStart(e)) {
-	    Layer *layer = getSelectedLayer();
-	    if (layer && layer->isLayerEditable()) {
-		layer->editStart(this, e);
-	    }
-	}
+        // Do nothing here -- we'll do it in mouseMoveEvent when the
+        // drag threshold has been passed
 
     } else if (mode == ViewManager::MeasureMode) {
 
@@ -1349,11 +1332,13 @@
         return;
     }
 
-    std::cerr << "mouseReleaseEvent" << std::endl;
+//    std::cerr << "mouseReleaseEvent" << std::endl;
 
     ViewManager::ToolMode mode = ViewManager::NavigateMode;
     if (m_manager) mode = m_manager->getToolMode();
 
+    m_releasing = true;
+
     if (m_clickedInRange) {
 	mouseMoveEvent(e);
     }
@@ -1380,7 +1365,10 @@
 
     } else if (mode == ViewManager::SelectMode) {
 
-        if (!hasTopLayerTimeXAxis()) return;
+        if (!hasTopLayerTimeXAxis()) {
+            m_releasing = false;
+            return;
+        }
 
 	if (m_manager && m_manager->haveInProgressSelection()) {
 
@@ -1420,13 +1408,15 @@
 
     } else if (mode == ViewManager::EditMode) {
 
-	if (!editSelectionEnd(e)) {
-	    Layer *layer = getSelectedLayer();
-	    if (layer && layer->isLayerEditable()) {
-		layer->editEnd(this, e);
-		update();
-	    }
-	}
+        if (m_editing) {
+            if (!editSelectionEnd(e)) {
+                Layer *layer = getSelectedLayer();
+                if (layer && layer->isLayerEditable()) {
+                    layer->editEnd(this, e);
+                    update();
+                }
+            }
+        }
 
     } else if (mode == ViewManager::MeasureMode) {
 
@@ -1437,6 +1427,7 @@
     }
 
     m_clickedInRange = false;
+    m_releasing = false;
 
     emit paneInteractedWith();
 }
@@ -1448,15 +1439,24 @@
         return;
     }
 
-    std::cerr << "mouseMoveEvent" << std::endl;
-
-    //!!! if no buttons pressed, and not called from
-    //mouseReleaseEvent, we want to reset clicked-ness (to avoid
-    //annoying continual drags when we moved the mouse outside the
-    //window after pressing button first time).
+//    std::cerr << "mouseMoveEvent" << std::endl;
 
     updateContextHelp(&e->pos());
 
+    if (m_navigating && m_clickedInRange && !m_releasing) {
+
+        // if no buttons pressed, and not called from
+        // mouseReleaseEvent, we want to reset clicked-ness (to avoid
+        // annoying continual drags when we moved the mouse outside
+        // the window after pressing button first time).
+
+        if (!(e->buttons() & Qt::LeftButton) &&
+            !(e->buttons() & Qt::MidButton)) {
+            m_clickedInRange = false;
+            return;
+        }
+    }
+
     ViewManager::ToolMode mode = ViewManager::NavigateMode;
     if (m_manager) mode = m_manager->getToolMode();
 
@@ -1540,12 +1540,44 @@
 
     } else if (mode == ViewManager::EditMode) {
 
-	if (!editSelectionDrag(e)) {
-	    Layer *layer = getSelectedLayer();
-	    if (layer && layer->isLayerEditable()) {
-		layer->editDrag(this, e);
-	    }
-	}
+        if (m_editing) {
+            if (!editSelectionDrag(e)) {
+                Layer *layer = getSelectedLayer();
+                if (layer && layer->isLayerEditable()) {
+                    layer->editDrag(this, e);
+                }
+            }
+        }
+
+        if (!m_editing) {
+
+            DragMode newDragMode = updateDragMode
+                (m_dragMode,
+                 m_clickPos,
+                 e->pos(),
+                 true,  // can move horiz
+                 true,  // can move vert
+                 true,  // resist horiz
+                 true); // resist vert
+
+            if (newDragMode != UnresolvedDrag) {
+
+                m_editing = true;
+
+                QMouseEvent clickEvent(QEvent::MouseButtonPress,
+                                       m_clickPos,
+                                       Qt::NoButton,
+                                       e->buttons(),
+                                       e->modifiers());
+
+                if (!editSelectionStart(&clickEvent)) {
+                    Layer *layer = getSelectedLayer();
+                    if (layer && layer->isLayerEditable()) {
+                        layer->editStart(this, &clickEvent);
+                    }
+                }
+            }
+        }
 
     } else if (mode == ViewManager::MeasureMode) {
 
@@ -1646,51 +1678,17 @@
     // If the top layer is incapable of being dragged
     // vertically, the logic is short circuited.
 
-    int xdiff = e->x() - m_clickPos.x();
-    int ydiff = e->y() - m_clickPos.y();
-    int smallThreshold = 10, bigThreshold = 50;
+    m_dragMode = updateDragMode
+        (m_dragMode,
+         m_clickPos,
+         e->pos(),
+         true, // can move horiz
+         canTopLayerMoveVertical(), // can move vert
+         canTopLayerMoveVertical() || (m_manager && m_manager->isPlaying()), // resist horiz
+         !(m_manager && m_manager->isPlaying())); // resist vert
 
-    bool canMoveVertical = canTopLayerMoveVertical();
-    bool canMoveHorizontal = true;
-
-    if (!canMoveHorizontal) {
-        m_dragMode = HorizontalDrag;
-    }
-
-    if (m_dragMode == UnresolvedDrag) {
-
-        if (abs(ydiff) > smallThreshold &&
-            abs(ydiff) > abs(xdiff) * 2) {
-            m_dragMode = VerticalDrag;
-        } else if (abs(xdiff) > smallThreshold &&
-                   abs(xdiff) > abs(ydiff) * 2) {
-            m_dragMode = HorizontalDrag;
-        } else if (abs(xdiff) > smallThreshold &&
-                   abs(ydiff) > smallThreshold) {
-            m_dragMode = FreeDrag;
-        } else {
-            // When playing, we don't want to disturb the play
-            // position too easily; when not playing, we don't
-            // want to move up/down too easily
-            if (m_manager && m_manager->isPlaying()) {
-                canMoveHorizontal = false;
-            } else {
-                canMoveVertical = false;
-            }
-        }
-    }
-
-    if (m_dragMode == VerticalDrag) {
-        if (abs(xdiff) > bigThreshold) m_dragMode = FreeDrag;
-        else canMoveHorizontal = false;
-    }
-
-    if (m_dragMode == HorizontalDrag && canMoveVertical) {
-        if (abs(ydiff) > bigThreshold) m_dragMode = FreeDrag;
-        else canMoveVertical = false;
-    }
-
-    if (canMoveHorizontal) {
+    if (m_dragMode == HorizontalDrag ||
+        m_dragMode == FreeDrag) {
 
         long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x());
 
@@ -1717,7 +1715,8 @@
         }
     }
 
-    if (canMoveVertical) {
+    if (m_dragMode == VerticalDrag ||
+        m_dragMode == FreeDrag) {
 
         float vmin = 0.f, vmax = 0.f;
         float dmin = 0.f, dmax = 0.f;
@@ -1726,10 +1725,15 @@
 
 //            std::cerr << "ydiff = " << ydiff << std::endl;
 
+            int ydiff = e->y() - m_clickPos.y();
             float perpix = (dmax - dmin) / height();
             float valdiff = ydiff * perpix;
 //            std::cerr << "valdiff = " << valdiff << std::endl;
 
+            if (m_dragMode == UnresolvedDrag && ydiff != 0) {
+                m_dragMode = VerticalDrag;
+            }
+
             float newmin = m_dragStartMinValue + valdiff;
             float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff;
             if (newmin < vmin) {
@@ -1749,6 +1753,65 @@
     }
 }
 
+Pane::DragMode
+Pane::updateDragMode(DragMode dragMode,
+                     QPoint origin,
+                     QPoint point,
+                     bool canMoveHorizontal,
+                     bool canMoveVertical,
+                     bool resistHorizontal,
+                     bool resistVertical)
+{
+    int xdiff = point.x() - origin.x();
+    int ydiff = point.y() - origin.y();
+
+    int smallThreshold = 10, bigThreshold = 80;
+
+//    std::cerr << "Pane::updateDragMode: xdiff = " << xdiff << ", ydiff = "
+//              << ydiff << ", canMoveVertical = " << canMoveVertical << ", drag mode = " << m_dragMode << std::endl;
+
+    if (dragMode == UnresolvedDrag) {
+
+        if (abs(ydiff) > smallThreshold &&
+            abs(ydiff) > abs(xdiff) * 2 &&
+            canMoveVertical) {
+//            std::cerr << "Pane::updateDragMode: passed vertical threshold" << std::endl;
+            dragMode = VerticalDrag;
+        } else if (abs(xdiff) > smallThreshold &&
+                   abs(xdiff) > abs(ydiff) * 2 &&
+                   canMoveHorizontal) {
+//            std::cerr << "Pane::updateDragMode: passed horizontal threshold" << std::endl;
+            dragMode = HorizontalDrag;
+        } else if (abs(xdiff) > smallThreshold &&
+                   abs(ydiff) > smallThreshold &&
+                   canMoveVertical &&
+                   canMoveHorizontal) {
+//            std::cerr << "Pane::updateDragMode: passed both thresholds" << std::endl;
+            dragMode = FreeDrag;
+        }
+    }
+
+    if (dragMode == VerticalDrag && canMoveHorizontal) {
+        if (abs(xdiff) > bigThreshold) dragMode = FreeDrag;
+    }
+
+    if (dragMode == HorizontalDrag && canMoveVertical) {
+        if (abs(ydiff) > bigThreshold) dragMode = FreeDrag;
+    }
+
+    if (dragMode == UnresolvedDrag) {
+        if (!resistHorizontal && xdiff != 0) {
+            dragMode = HorizontalDrag;
+        }
+        if (!resistVertical && ydiff != 0) {
+            if (dragMode == HorizontalDrag) dragMode = FreeDrag;
+            else dragMode = VerticalDrag;
+        }
+    }
+    
+    return dragMode;
+}
+
 void
 Pane::dragExtendSelection(QMouseEvent *e)
 {
@@ -1828,7 +1891,7 @@
         return;
     }
 
-    std::cerr << "mouseDoubleClickEvent" << std::endl;
+//    std::cerr << "mouseDoubleClickEvent" << std::endl;
 
     m_clickPos = e->pos();
     m_clickedInRange = true;