From 1e3bd18b00a327a5699c38e1daa96277efd4d67a Mon Sep 17 00:00:00 2001
From: Lasse Holmstedt <lasse.holmstedt@nokia.com>
Date: Tue, 3 Aug 2010 12:32:56 +0200
Subject: [PATCH] QML Observer: Update hover rects when objects move

Also, update the gray mask that appears when user enters context of some
item. The mask is grown if the item changes its geometry, but never
shrunk, as this would introduce annoying flicker on the screen.
---
 .../editor/boundingrecthighlighter.cpp        | 43 +++++++++++--------
 .../editor/boundingrecthighlighter.h          |  1 +
 .../editor/subcomponenteditortool.cpp         | 32 +++++++-------
 .../editor/subcomponenteditortool.h           |  2 +-
 .../editor/subcomponentmasklayeritem.cpp      | 30 ++++++++++++-
 .../editor/subcomponentmasklayeritem.h        |  5 ++-
 6 files changed, 77 insertions(+), 36 deletions(-)

diff --git a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp
index 73654968113..90fb9446ebb 100644
--- a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp
+++ b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.cpp
@@ -99,14 +99,18 @@ void BoundingRectHighlighter::clear()
     if (m_boxes.length()) {
         m_animTimer->stop();
 
+        foreach(BoundingBox *box, m_boxes) {
+            if (!box->highlightedObject.isNull()) {
+                disconnect(box->highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
+                disconnect(box->highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
+                disconnect(box->highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
+                disconnect(box->highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
+                disconnect(box->highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
+            }
+        }
+
         qDeleteAll(m_boxes);
         m_boxes.clear();
-
-//        disconnect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
-//        disconnect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
-//        disconnect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
-//        disconnect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
-//        disconnect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
     }
 }
 
@@ -132,7 +136,7 @@ void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
     foreach(QGraphicsObject *itemToHighlight, items) {
         BoundingBox *box = boxFor(itemToHighlight);
         if (!box) {
-            box = new BoundingBox(itemToHighlight, this);
+            box = createBoundingBox(itemToHighlight);
             animate = true;
         }
 
@@ -157,7 +161,7 @@ void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
 
     BoundingBox *box = boxFor(itemToHighlight);
     if (!box) {
-        box = new BoundingBox(itemToHighlight, this);
+        box = createBoundingBox(itemToHighlight);
         m_boxes << box;
         animate = true;
         qSort(m_boxes);
@@ -166,11 +170,24 @@ void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
     highlightAll(animate);
 }
 
+BoundingBox *BoundingRectHighlighter::createBoundingBox(QGraphicsObject *itemToHighlight)
+{
+    BoundingBox *box = new BoundingBox(itemToHighlight, this);
+
+    connect(itemToHighlight, SIGNAL(xChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(yChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(widthChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(heightChanged()), this, SLOT(refresh()));
+    connect(itemToHighlight, SIGNAL(rotationChanged()), this, SLOT(refresh()));
+
+    return box;
+}
+
 void BoundingRectHighlighter::highlightAll(bool animate)
 {
     foreach(BoundingBox *box, m_boxes) {
         QGraphicsObject *item = box->highlightedObject.data();
-        if (!item) {
+        if (box->highlightedObject.isNull()) {
             m_boxes.removeOne(box);
             continue;
         }
@@ -186,14 +203,6 @@ void BoundingRectHighlighter::highlightAll(bool animate)
         box->highlightPolygon->setPolygon(QPolygonF(bboxRect));
         box->highlightPolygonEdge->setPolygon(QPolygonF(edgeRect));
 
-//        if (XXX) {
-//            connect(item, SIGNAL(xChanged()), this, SLOT(refresh()));
-//            connect(item, SIGNAL(yChanged()), this, SLOT(refresh()));
-//            connect(item, SIGNAL(widthChanged()), this, SLOT(refresh()));
-//            connect(item, SIGNAL(heightChanged()), this, SLOT(refresh()));
-//            connect(item, SIGNAL(rotationChanged()), this, SLOT(refresh()));
-//        }
-
         if (animate)
             box->highlightPolygonEdge->setOpacity(0);
     }
diff --git a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h
index 2e8e52226f2..948de90b13b 100644
--- a/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h
+++ b/src/libs/qmljsdebugger/editor/boundingrecthighlighter.h
@@ -34,6 +34,7 @@ private slots:
 private:
     BoundingBox *boxFor(QGraphicsObject *item) const;
     void highlightAll(bool animate);
+    BoundingBox *createBoundingBox(QGraphicsObject *itemToHighlight);
 
 private:
     Q_DISABLE_COPY(BoundingRectHighlighter);
diff --git a/src/libs/qmljsdebugger/editor/subcomponenteditortool.cpp b/src/libs/qmljsdebugger/editor/subcomponenteditortool.cpp
index d61afbcf99a..2bd96c80efd 100644
--- a/src/libs/qmljsdebugger/editor/subcomponenteditortool.cpp
+++ b/src/libs/qmljsdebugger/editor/subcomponenteditortool.cpp
@@ -143,12 +143,6 @@ void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
     if (!gfxObject)
         return;
 
-    connect(gfxObject, SIGNAL(xChanged()), SLOT(refresh()));
-    connect(gfxObject, SIGNAL(yChanged()), SLOT(refresh()));
-    connect(gfxObject, SIGNAL(scaleChanged()), SLOT(refresh()));
-    connect(gfxObject, SIGNAL(widthChanged()), SLOT(refresh()));
-    connect(gfxObject, SIGNAL(heightChanged()), SLOT(refresh()));
-
     //QString parentClassName = gfxObject->metaObject()->className();
     //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+")))
 
@@ -223,7 +217,13 @@ bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) c
 
 void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem)
 {
-    connect(contextItem, SIGNAL(destroyed(QObject*)), SLOT(contextDestroyed(QObject*)));
+    connect(contextItem, SIGNAL(destroyed(QObject*)), this, SLOT(contextDestroyed(QObject*)));
+    connect(contextItem, SIGNAL(xChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(yChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
+    connect(contextItem, SIGNAL(rotationChanged()), this, SLOT(resizeMask()));
+
     m_currentContext.push(contextItem);
     QString title = titleForItem(contextItem);
     emit contextPushed(title);
@@ -250,14 +250,15 @@ QGraphicsObject *SubcomponentEditorTool::popContext()
 
     emit contextPopped();
 
-    disconnect(popped, SIGNAL(xChanged()), this, SLOT(refresh()));
-    disconnect(popped, SIGNAL(yChanged()), this, SLOT(refresh()));
-    disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(refresh()));
-    disconnect(popped, SIGNAL(widthChanged()), this, SLOT(refresh()));
-    disconnect(popped, SIGNAL(heightChanged()), this, SLOT(refresh()));
+    disconnect(popped, SIGNAL(xChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(yChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(scaleChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(widthChanged()), this, SLOT(resizeMask()));
+    disconnect(popped, SIGNAL(heightChanged()), this, SLOT(resizeMask()));
 
     if (m_currentContext.size() > 1) {
-        m_mask->setCurrentItem(m_currentContext.top());
+        QGraphicsObject *item = m_currentContext.top();
+        m_mask->setCurrentItem(item);
         m_mask->setOpacity(MaxOpacity);
         m_mask->setVisible(true);
     } else {
@@ -267,9 +268,10 @@ QGraphicsObject *SubcomponentEditorTool::popContext()
     return popped;
 }
 
-void SubcomponentEditorTool::refresh()
+void SubcomponentEditorTool::resizeMask()
 {
-    m_mask->setCurrentItem(m_currentContext.top());
+    QGraphicsObject *item = m_currentContext.top();
+    m_mask->setCurrentItem(item);
 }
 
 QGraphicsObject *SubcomponentEditorTool::currentRootItem() const
diff --git a/src/libs/qmljsdebugger/editor/subcomponenteditortool.h b/src/libs/qmljsdebugger/editor/subcomponenteditortool.h
index 3a3f50bddc3..d54b6a71dc0 100644
--- a/src/libs/qmljsdebugger/editor/subcomponenteditortool.h
+++ b/src/libs/qmljsdebugger/editor/subcomponenteditortool.h
@@ -63,7 +63,7 @@ protected:
 private slots:
     void animate();
     void contextDestroyed(QObject *context);
-    void refresh();
+    void resizeMask();
 
 private:
     QGraphicsObject *popContext();
diff --git a/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.cpp b/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.cpp
index 32297771441..ce1b4371319 100644
--- a/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.cpp
+++ b/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.cpp
@@ -24,8 +24,28 @@ int SubcomponentMaskLayerItem::type() const
     return Constants::EditorItemType;
 }
 
+static QRectF resizeRect(const QRectF &newRect, const QRectF &oldRect)
+{
+    QRectF result = newRect;
+    if (oldRect.left() < newRect.left())
+        result.setLeft(oldRect.left());
+
+    if (oldRect.top() < newRect.top())
+        result.setTop(oldRect.top());
+
+    if (oldRect.right() > newRect.right())
+        result.setRight(oldRect.right());
+
+    if (oldRect.bottom() > newRect.bottom())
+        result.setBottom(oldRect.bottom());
+
+    return result;
+}
+
+
 void SubcomponentMaskLayerItem::setCurrentItem(QGraphicsItem *item)
 {
+    QGraphicsItem *prevItem = m_currentItem;
     m_currentItem = item;
 
     if (!m_currentItem)
@@ -38,11 +58,17 @@ void SubcomponentMaskLayerItem::setCurrentItem(QGraphicsItem *item)
     QPolygonF itemPoly(itemRect);
     itemPoly = item->mapToScene(itemPoly);
 
-    QRectF borderRect = itemPoly.boundingRect();
+    // if updating the same item as before, resize the rectangle only bigger, not smaller.
+    if (prevItem == item && prevItem != 0) {
+        m_itemPolyRect = resizeRect(itemPoly.boundingRect(), m_itemPolyRect);
+    } else {
+        m_itemPolyRect = itemPoly.boundingRect();
+    }
+    QRectF borderRect = m_itemPolyRect;
     borderRect.adjust(-1, -1, 1, 1);
     m_borderRect->setRect(borderRect);
 
-    itemPoly = viewPoly.subtracted(QPolygonF(itemPoly.boundingRect()));
+    itemPoly = viewPoly.subtracted(QPolygonF(m_itemPolyRect));
     setPolygon(itemPoly);
 }
 
diff --git a/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.h b/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.h
index 1cbc9e6abf0..9a646364612 100644
--- a/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.h
+++ b/src/libs/qmljsdebugger/editor/subcomponentmasklayeritem.h
@@ -13,12 +13,15 @@ public:
     explicit SubcomponentMaskLayerItem(QDeclarativeDesignView *view, QGraphicsItem *parentItem = 0);
     int type() const;
     void setCurrentItem(QGraphicsItem *item);
+    void setBoundingBox(const QRectF &boundingBox);
     QGraphicsItem *currentItem() const;
+    QRectF itemRect() const;
+
 private:
     QDeclarativeDesignView *m_view;
     QGraphicsItem *m_currentItem;
     QGraphicsRectItem *m_borderRect;
-
+    QRectF m_itemPolyRect;
 };
 
 } // namespace QmlViewer
-- 
GitLab