From d81f9e750627a83c12afeb4718eb12bbb53f5270 Mon Sep 17 00:00:00 2001
From: Joanna Hulboj <joanna.hulboj@isode.com>
Date: Fri, 3 Feb 2017 10:19:53 +0000
Subject: Fix mouse movement when resizing trellis layout.

Test-Information:

From view menu choose "Change Layout", move mouse to resize trellis.
Trellis resizing works fine.

Change-Id: I112c0bd84dc57abb3bb95f825f74b2efa1f8e183

diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp
index de9d2d2..ad95a07 100644
--- a/Swift/QtUI/QtChatTabs.cpp
+++ b/Swift/QtUI/QtChatTabs.cpp
@@ -382,7 +382,7 @@ void QtChatTabs::handleOpenLayoutChangeDialog() {
     gridSelectionDialog_->show();
 
     QPoint pos(gridSelectionDialog_->getFrameSize().width() / 2, gridSelectionDialog_->getFrameSize().height() / 2);
-    QCursor::setPos(gridSelectionDialog_->windowHandle()->screen(), gridSelectionDialog_->mapToGlobal(QPoint(gridSelectionDialog_->width(), gridSelectionDialog_->height()) - pos));
+    QCursor::setPos(gridSelectionDialog_->windowHandle()->screen(), gridSelectionDialog_->mapToGlobal(QPoint(gridSelectionDialog_->width(), (gridSelectionDialog_->height() - gridSelectionDialog_->getDescriptionTextHeight())) - pos));
 }
 
 void QtChatTabs::storeTabPositions() {
diff --git a/Swift/QtUI/Trellis/QtGridSelectionDialog.cpp b/Swift/QtUI/Trellis/QtGridSelectionDialog.cpp
index fb9734d..0533edf 100644
--- a/Swift/QtUI/Trellis/QtGridSelectionDialog.cpp
+++ b/Swift/QtUI/Trellis/QtGridSelectionDialog.cpp
@@ -32,11 +32,7 @@ QSize QtGridSelectionDialog::sizeHint() const {
     int width = horizontalMargin + frameSize.width() + (padding + frameSize.width()) * (currentGridSize.width() - 1) + horizontalMargin;
     int height = verticalMargin + frameSize.height() + (padding + frameSize.height()) * (currentGridSize.height() - 1) + verticalMargin;
 
-    // Add space for descriptive centered text below.
-    auto fontMetrics = QFontMetrics(QApplication::font());
-    auto descriptionBB = fontMetrics.boundingRect(QRect(0,0,width - 2*horizontalMargin,1000), Qt::TextWordWrap, descriptionText, 0, 0);
-
-    height += descriptionBB.height() + descriptionBB.y();
+    height += getDescriptionTextHeight(width);
 
     return QSize(width, height);
 }
@@ -72,6 +68,19 @@ QSize QtGridSelectionDialog::getFrameSize() const {
     return frameSize;
 }
 
+int QtGridSelectionDialog::getDescriptionTextHeight() const {
+    auto width = horizontalMargin + frameSize.width() + (padding + frameSize.width()) * (currentGridSize.width() - 1) + horizontalMargin;
+    return getDescriptionTextHeight(width);
+}
+
+int QtGridSelectionDialog::getDescriptionTextHeight(int width) const {
+    // Height of descriptive centered text below trellis
+    auto fontMetrics = QFontMetrics(QApplication::font());
+    auto descriptionBB = fontMetrics.boundingRect(QRect(0, 0, width - 2 * horizontalMargin, 1000), Qt::TextWordWrap, descriptionText, 0, 0);
+
+    return (descriptionBB.height() + descriptionBB.y());
+}
+
 void QtGridSelectionDialog::keyReleaseEvent(QKeyEvent* event) {
     if (event) {
         QSize newGridSize = currentGridSize;
@@ -100,7 +109,7 @@ void QtGridSelectionDialog::keyReleaseEvent(QKeyEvent* event) {
 
             QSize newSizeHint = sizeHint();
             resize(newSizeHint);
-            QCursor::setPos(mapToGlobal(QPoint(newSizeHint.width(), newSizeHint.height()) - QPoint(frameSize.width() / 2, frameSize.height() / 2)));
+            QCursor::setPos(mapToGlobal(QPoint(newSizeHint.width(), newSizeHint.height()- getDescriptionTextHeight()) - QPoint(frameSize.width() / 2, frameSize.height() / 2)));
         }
     }
 }
@@ -137,43 +146,42 @@ void QtGridSelectionDialog::paintEvent(QPaintEvent*) {
 }
 
 void QtGridSelectionDialog::showEvent(QShowEvent*) {
-    setMouseTracking(true);
+    timerId = startTimer(1000 / 25);
 }
 
 void QtGridSelectionDialog::hideEvent(QHideEvent*) {
-    setMouseTracking(false);
-}
-
-void QtGridSelectionDialog::mouseMoveEvent(QMouseEvent*) {
-    QPoint diff = (frameGeometry().bottomRight() - QCursor::pos());
-    QSize newDimensions = currentGridSize;
-    if (diff.x() > frameSize.width() * 1.5) {
-        newDimensions -= QSize(diff.x() / (frameSize.width() * 1.5), 0);
-    }
-    if (diff.y() > frameSize.height() * 1.5) {
-        newDimensions -= QSize(0, diff.y() / (frameSize.height() * 1.5));
-    }
-    if (minGridSize.expandedTo(newDimensions).boundedTo(maxGridSize) != currentGridSize) {
-        currentGridSize = minGridSize.expandedTo(newDimensions).boundedTo(maxGridSize);
-        resize(sizeHint());
-    }
-}
+    killTimer(timerId);
+}
+
+void QtGridSelectionDialog::timerEvent(QTimerEvent*) {
+
+    const QPoint diff = QCursor::pos() - frameGeometry().topLeft() - QPoint(horizontalMargin, verticalMargin);
+    const auto toleranceFactor = 4; // Ratio of how far (1/tolerance) the mouse should move for the next frame to be plotted
+    // dx, dy - mouse position with respect to first top-left square
+    const auto dx = diff.x();
+    const auto dy = diff.y();
+    // width, height - dimension of each square with padding
+    const auto width = frameSize.width() + padding;
+    const auto height = frameSize.height() + padding;
+    // xThreshold, yThreshold - how far the mouse should be moved so that a new square is added or the existing one is hidden
+    const auto xThreshold = width / toleranceFactor;
+    const auto yThreshold = height / toleranceFactor;
+
+    const auto getSize = [](int length, int threshold, int delta) {
+        if (delta < length + threshold) {
+            return 1;
+        }
+        else {
+            return (delta + (length - threshold)) / length;
+        }
+    };
+    const QSize newGridSize(getSize(width, xThreshold, dx), getSize(height, yThreshold, dy));
 
-void QtGridSelectionDialog::leaveEvent(QEvent *) {
-    QPoint diff = (frameGeometry().bottomRight() - QCursor::pos());
-    QSize newGridSize = currentGridSize;
-    if (diff.x() < 0) {
-        newGridSize += QSize(1,0);
-    }
-    if (diff.y() < 0) {
-        newGridSize += QSize(0,1);
-    }
     if (minGridSize.expandedTo(newGridSize).boundedTo(maxGridSize) != currentGridSize) {
         currentGridSize = minGridSize.expandedTo(newGridSize).boundedTo(maxGridSize);
         resize(sizeHint());
     }
 }
-
 bool QtGridSelectionDialog::event(QEvent* event) {
     // Hide the window when it becomes a non-top-level window.
     if (event->type() == QEvent::WindowDeactivate) {
diff --git a/Swift/QtUI/Trellis/QtGridSelectionDialog.h b/Swift/QtUI/Trellis/QtGridSelectionDialog.h
index 3ccba55..2cb36ca 100644
--- a/Swift/QtUI/Trellis/QtGridSelectionDialog.h
+++ b/Swift/QtUI/Trellis/QtGridSelectionDialog.h
@@ -30,6 +30,7 @@ namespace Swift {
             QSize getMaxGridSize() const;
 
             QSize getFrameSize() const;
+            int getDescriptionTextHeight() const;
 
         signals:
             void currentGridSizeChanged(QSize);
@@ -39,17 +40,20 @@ namespace Swift {
         protected:
             void keyReleaseEvent(QKeyEvent* event);
             void mousePressEvent(QMouseEvent* event);
-            void mouseMoveEvent(QMouseEvent* event);
             void paintEvent(QPaintEvent* event);
             void showEvent(QShowEvent* event);
             void hideEvent(QHideEvent* event);
-            void leaveEvent(QEvent *event);
             bool event(QEvent* event);
+            void timerEvent(QTimerEvent* event);
+
+    private:
+        int getDescriptionTextHeight(int width) const;
 
         private:
             int padding;
             int horizontalMargin;
             int verticalMargin;
+            int timerId;
 
             QSize frameSize;
 
-- 
cgit v0.10.2-6-g49f6