diff view/Pane.cpp @ 373:0895517bb2d1 1.2-stable

* merge from trunk (1.2 ended up being tracked from trunk, but we may want this branch for fixes later)
author Chris Cannam
date Wed, 27 Feb 2008 10:32:45 +0000
parents 2f83b6e3b8ca
children
line wrap: on
line diff
--- a/view/Pane.cpp	Thu Nov 29 10:43:54 2007 +0000
+++ b/view/Pane.cpp	Wed Feb 27 10:32:45 2008 +0000
@@ -22,6 +22,7 @@
 #include "ViewManager.h"
 #include "base/CommandHistory.h"
 #include "base/TextAbbrev.h"
+#include "base/Preferences.h"
 #include "layer/WaveformLayer.h"
 
 //!!! ugh
@@ -49,6 +50,8 @@
 
 #include "widgets/KeyReference.h" //!!! should probably split KeyReference into a data class in base and another that shows the widget
 
+//#define DEBUG_PANE
+
 using std::cerr;
 using std::endl;
 
@@ -63,6 +66,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),
@@ -388,6 +393,7 @@
     View::paintEvent(e);
 
     paint.begin(this);
+    setPaintFont(paint);
 
     if (e) paint.setClipRect(r);
 
@@ -1209,6 +1215,8 @@
         return;
     }
 
+//    std::cerr << "mousePressEvent" << std::endl;
+
     m_clickPos = e->pos();
     m_mousePos = m_clickPos;
     m_clickedInRange = true;
@@ -1222,6 +1230,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) ||
@@ -1303,12 +1314,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) {
 
@@ -1327,9 +1334,13 @@
         return;
     }
 
+//    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);
     }
@@ -1356,7 +1367,10 @@
 
     } else if (mode == ViewManager::SelectMode) {
 
-        if (!hasTopLayerTimeXAxis()) return;
+        if (!hasTopLayerTimeXAxis()) {
+            m_releasing = false;
+            return;
+        }
 
 	if (m_manager && m_manager->haveInProgressSelection()) {
 
@@ -1396,13 +1410,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) {
 
@@ -1413,6 +1429,7 @@
     }
 
     m_clickedInRange = false;
+    m_releasing = false;
 
     emit paneInteractedWith();
 }
@@ -1424,8 +1441,24 @@
         return;
     }
 
+//    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();
 
@@ -1509,12 +1542,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) {
 
@@ -1615,51 +1680,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());
 
@@ -1672,7 +1703,12 @@
         } else {
             newCentreFrame = 0;
         }
-	    
+
+#ifdef DEBUG_PANE	    
+        std::cerr << "Pane::dragTopLayer: newCentreFrame = " << newCentreFrame <<
+            ", models end frame = " << getModelsEndFrame() << std::endl;
+#endif
+
         if (newCentreFrame >= getModelsEndFrame()) {
             newCentreFrame = getModelsEndFrame();
             if (newCentreFrame > 0) --newCentreFrame;
@@ -1683,7 +1719,8 @@
         }
     }
 
-    if (canMoveVertical) {
+    if (m_dragMode == VerticalDrag ||
+        m_dragMode == FreeDrag) {
 
         float vmin = 0.f, vmax = 0.f;
         float dmin = 0.f, dmax = 0.f;
@@ -1692,10 +1729,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) {
@@ -1715,6 +1757,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)
 {