Commit d9897751 authored by Lasse Holmstedt's avatar Lasse Holmstedt Committed by Olivier Goffart
Browse files

rewrote bounding rect highlighting to support multiselection

parent 4ecad983
......@@ -13,6 +13,51 @@ const qreal AnimDelta = 0.025f;
const int AnimInterval = 30;
const int AnimFrames = 10;
class BoundingBoxPolygonItem : public QGraphicsPolygonItem
{
public:
explicit BoundingBoxPolygonItem(QGraphicsItem *item);
int type() const;
};
class BoundingBox
{
public:
explicit BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem);
~BoundingBox();
QWeakPointer<QGraphicsObject> highlightedObject;
QGraphicsPolygonItem *highlightPolygon;
QGraphicsPolygonItem *highlightPolygonEdge;
private:
Q_DISABLE_COPY(BoundingBox);
};
BoundingBox::BoundingBox(QGraphicsObject *itemToHighlight, QGraphicsItem *parentItem)
: highlightedObject(itemToHighlight),
highlightPolygon(0),
highlightPolygonEdge(0)
{
highlightPolygon = new BoundingBoxPolygonItem(parentItem);
highlightPolygonEdge = new BoundingBoxPolygonItem(parentItem);
highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));
highlightPolygon->setFlag(QGraphicsItem::ItemIsSelectable, false);
highlightPolygonEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
}
BoundingBox::~BoundingBox()
{
delete highlightPolygon;
delete highlightPolygonEdge;
highlightPolygon = 0;
highlightPolygonEdge = 0;
highlightedObject.clear();
}
BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item)
{
QPen pen;
......@@ -28,8 +73,6 @@ int BoundingBoxPolygonItem::type() const
BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeDesignView *view) :
LayerItem(view->scene()),
m_view(view),
m_highlightPolygon(0),
m_highlightPolygonEdge(0),
m_animFrame(0)
{
m_animTimer = new QTimer(this);
......@@ -44,89 +87,140 @@ void BoundingRectHighlighter::animTimeout()
m_animTimer->stop();
}
m_highlightPolygon->setPen(QPen(QColor(0, 22, 159)));
m_highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255)));
qreal alpha = m_animFrame / float(AnimFrames);
m_highlightPolygonEdge->setOpacity(alpha);
foreach(BoundingBox *box, m_boxes) {
box->highlightPolygonEdge->setOpacity(alpha);
}
}
void BoundingRectHighlighter::clear()
{
if (m_highlightPolygon) {
m_view->scene()->removeItem(m_highlightPolygon);
delete m_highlightPolygon;
m_highlightPolygon = 0;
delete m_highlightPolygonEdge;
m_highlightPolygonEdge = 0;
if (m_boxes.length()) {
m_animTimer->stop();
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()));
qDeleteAll(m_boxes);
m_boxes.clear();
m_highlightedObject.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()));
}
}
void BoundingRectHighlighter::highlight(QGraphicsObject* item)
BoundingBox *BoundingRectHighlighter::boxFor(QGraphicsObject *item) const
{
if (!item)
foreach(BoundingBox *box, m_boxes) {
if (box->highlightedObject.data() == item) {
return box;
}
}
return 0;
}
void BoundingRectHighlighter::highlight(QList<QGraphicsObject*> items)
{
if (items.isEmpty())
return;
bool animate = false;
QGraphicsPolygonItem *polygonItem = 0;
QGraphicsPolygonItem *polygonItemEdge = 0;
if (item != m_highlightedObject.data() || !m_highlightPolygon) {
animate = true;
polygonItem = new BoundingBoxPolygonItem(this);
polygonItemEdge = new BoundingBoxPolygonItem(this);
} else {
polygonItem = m_highlightPolygon;
polygonItemEdge = m_highlightPolygonEdge;
QList<BoundingBox*> newBoxes;
foreach(QGraphicsObject *itemToHighlight, items) {
BoundingBox *box = boxFor(itemToHighlight);
if (!box) {
box = new BoundingBox(itemToHighlight, this);
animate = true;
}
newBoxes << box;
}
qSort(newBoxes);
QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect();
if (newBoxes != m_boxes) {
clear();
m_boxes << newBoxes;
}
QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace);
QRectF bboxRect = boundingRectInLayerItemSpace.boundingRect();
QRectF edgeRect = boundingRectInLayerItemSpace.boundingRect();
edgeRect.adjust(-1, -1, 1, 1);
highlightAll(animate);
}
polygonItem->setPolygon(QPolygonF(bboxRect));
polygonItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
{
if (!itemToHighlight)
return;
polygonItemEdge->setPolygon(QPolygonF(edgeRect));
polygonItemEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
bool animate = false;
if (item != m_highlightedObject.data())
clear();
BoundingBox *box = boxFor(itemToHighlight);
if (!box) {
box = new BoundingBox(itemToHighlight, this);
m_boxes << box;
animate = true;
qSort(m_boxes);
}
m_highlightPolygon = polygonItem;
m_highlightPolygonEdge = polygonItemEdge;
m_highlightedObject = item;
highlightAll(animate);
}
if (item != m_highlightedObject.data()) {
connect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh()));
connect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh()));
connect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh()));
connect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh()));
connect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh()));
void BoundingRectHighlighter::highlightAll(bool animate)
{
foreach(BoundingBox *box, m_boxes) {
QGraphicsObject *item = box->highlightedObject.data();
if (!item) {
m_boxes.removeOne(box);
continue;
}
QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect();
QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace);
QRectF bboxRect = boundingRectInLayerItemSpace.boundingRect();
QRectF edgeRect = boundingRectInLayerItemSpace.boundingRect();
edgeRect.adjust(-1, -1, 1, 1);
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);
}
if (animate) {
m_highlightPolygonEdge->setOpacity(0);
m_animFrame = 0;
m_animTimer->start();
}
}
void BoundingRectHighlighter::removeHighlight(QGraphicsObject *item)
{
if (!item)
return;
BoundingBox *box = boxFor(item);
if (box) {
m_boxes.removeOne(box);
delete box;
box = 0;
}
}
void BoundingRectHighlighter::refresh()
{
if (!m_highlightedObject.isNull())
highlight(m_highlightedObject.data());
if (!m_boxes.isEmpty())
highlightAll(true);
}
......
......@@ -15,13 +15,7 @@ QT_FORWARD_DECLARE_CLASS(QTimer);
namespace QmlViewer {
class QDeclarativeDesignView;
class BoundingBoxPolygonItem : public QGraphicsPolygonItem
{
public:
explicit BoundingBoxPolygonItem(QGraphicsItem *item);
int type() const;
};
class BoundingBox;
class BoundingRectHighlighter : public LayerItem
{
......@@ -29,19 +23,26 @@ class BoundingRectHighlighter : public LayerItem
public:
explicit BoundingRectHighlighter(QDeclarativeDesignView *view);
void clear();
void highlight(QList<QGraphicsObject*> items);
void highlight(QGraphicsObject* item);
void removeHighlight(QGraphicsObject *item);
private slots:
void refresh();
void animTimeout();
private:
BoundingBox *boxFor(QGraphicsObject *item) const;
void highlightAll(bool animate);
private:
Q_DISABLE_COPY(BoundingRectHighlighter);
QDeclarativeDesignView *m_view;
QWeakPointer<QGraphicsObject> m_highlightedObject;
QGraphicsPolygonItem *m_highlightPolygon;
QGraphicsPolygonItem *m_highlightPolygonEdge;
QList<BoundingBox*> m_boxes;
// QList<QWeakPointer<QGraphicsObject> > m_highlightedObjects;
// QGraphicsPolygonItem *m_highlightPolygon;
// QGraphicsPolygonItem *m_highlightPolygonEdge;
QTimer *m_animTimer;
qreal m_animScale;
......
......@@ -222,7 +222,7 @@ void SelectionTool::contextMenuElementHovered(QAction *action)
{
int itemListIndex = action->data().toInt();
if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
view()->highlightBoundingRect(m_contextMenuItemList.at(itemListIndex));
view()->highlight(m_contextMenuItemList.at(itemListIndex));
}
}
......@@ -286,9 +286,9 @@ void SelectionTool::hoverMoveEvent(QMouseEvent * event)
}
}
view()->highlightBoundingRect(topSelectableItem);
view()->highlight(topSelectableItem);
} else {
view()->clearHighlightBoundingRect();
view()->clearHighlight();
}
}
......
......@@ -71,7 +71,7 @@ void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event)
void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event)
{
if (!containsCursor(event->pos()) && m_currentContext.size() > 1) {
view()->clearHighlightBoundingRect();
view()->clearHighlight();
}
}
......@@ -164,7 +164,7 @@ void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem)
m_animIncrement = 0.05f;
m_animTimer->start();
view()->clearHighlightBoundingRect();
view()->clearHighlight();
view()->setSelectedItems(QList<QGraphicsItem*>());
pushContext(gfxObject);
......
......@@ -63,7 +63,7 @@ QDeclarativeDesignView::~QDeclarativeDesignView()
void QDeclarativeDesignView::reloadView()
{
m_subcomponentEditorTool->clear();
clearHighlightBoundingRect();
clearHighlight();
emit reloadRequested();
}
......@@ -73,7 +73,7 @@ void QDeclarativeDesignView::leaveEvent(QEvent *event)
QDeclarativeView::leaveEvent(event);
return;
}
clearHighlightBoundingRect();
clearHighlight();
}
void QDeclarativeDesignView::mousePressEvent(QMouseEvent *event)
......@@ -227,7 +227,7 @@ void QDeclarativeDesignView::setDesignModeBehavior(bool value)
m_designModeBehavior = value;
if (m_subcomponentEditorTool) {
m_subcomponentEditorTool->clear();
clearHighlightBoundingRect();
clearHighlight();
setSelectedItems(QList<QGraphicsItem*>());
if (rootObject())
......@@ -269,22 +269,32 @@ AbstractFormEditorTool *QDeclarativeDesignView::currentTool() const
return m_currentTool;
}
void QDeclarativeDesignView::clearHighlightBoundingRect()
void QDeclarativeDesignView::clearHighlight()
{
m_boundingRectHighlighter->clear();
}
void QDeclarativeDesignView::highlightBoundingRect(QGraphicsItem *item)
void QDeclarativeDesignView::highlight(QGraphicsItem * item)
{
if (!item)
highlight(QList<QGraphicsItem*>() << item);
}
void QDeclarativeDesignView::highlight(QList<QGraphicsItem *> items)
{
if (items.isEmpty())
return;
QGraphicsItem *itemToHighlight = m_subcomponentEditorTool->firstChildOfContext(item);
if (itemToHighlight) {
m_boundingRectHighlighter->highlight(itemToHighlight->toGraphicsObject());
} else {
clearHighlightBoundingRect();
QList<QGraphicsObject*> objectList;
foreach(QGraphicsItem *item, items) {
QGraphicsItem *child = m_subcomponentEditorTool->firstChildOfContext(item);
if (child) {
QGraphicsObject *childObject = child->toGraphicsObject();
if (childObject)
objectList << childObject;
}
}
m_boundingRectHighlighter->highlight(objectList);
}
bool QDeclarativeDesignView::mouseInsideContextItem() const
......@@ -480,9 +490,9 @@ void QDeclarativeDesignView::onCurrentObjectsChanged(QList<QObject*> objects)
}
setSelectedItems(items);
clearHighlightBoundingRect();
clearHighlight();
if (!items.isEmpty())
highlightBoundingRect(items.first());
highlight(items);
}
QToolBar *QDeclarativeDesignView::toolbar() const
......
......@@ -35,8 +35,9 @@ public:
void changeTool(Constants::DesignTool tool,
Constants::ToolFlags flags = Constants::NoToolFlags);
void clearHighlightBoundingRect();
void highlightBoundingRect(QGraphicsItem *item);
void clearHighlight();
void highlight(QList<QGraphicsItem *> item);
void highlight(QGraphicsItem *item);
bool mouseInsideContextItem() const;
bool isEditorItem(QGraphicsItem *item) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment