forked from qt-creator/qt-creator
rewrote bounding rect highlighting to support multiselection
This commit is contained in:
committed by
Olivier Goffart
parent
4ecad983ec
commit
d98977513d
@@ -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);
|
||||
|
||||
if (newBoxes != m_boxes) {
|
||||
clear();
|
||||
m_boxes << newBoxes;
|
||||
}
|
||||
|
||||
QRectF itemAndChildRect = item->boundingRect() | item->childrenBoundingRect();
|
||||
highlightAll(animate);
|
||||
}
|
||||
|
||||
QPolygonF boundingRectInSceneSpace(item->mapToScene(itemAndChildRect));
|
||||
QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace);
|
||||
QRectF bboxRect = boundingRectInLayerItemSpace.boundingRect();
|
||||
QRectF edgeRect = boundingRectInLayerItemSpace.boundingRect();
|
||||
edgeRect.adjust(-1, -1, 1, 1);
|
||||
void BoundingRectHighlighter::highlight(QGraphicsObject* itemToHighlight)
|
||||
{
|
||||
if (!itemToHighlight)
|
||||
return;
|
||||
|
||||
polygonItem->setPolygon(QPolygonF(bboxRect));
|
||||
polygonItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
bool animate = false;
|
||||
|
||||
polygonItemEdge->setPolygon(QPolygonF(edgeRect));
|
||||
polygonItemEdge->setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
BoundingBox *box = boxFor(itemToHighlight);
|
||||
if (!box) {
|
||||
box = new BoundingBox(itemToHighlight, this);
|
||||
m_boxes << box;
|
||||
animate = true;
|
||||
qSort(m_boxes);
|
||||
}
|
||||
|
||||
if (item != m_highlightedObject.data())
|
||||
clear();
|
||||
highlightAll(animate);
|
||||
}
|
||||
|
||||
m_highlightPolygon = polygonItem;
|
||||
m_highlightPolygonEdge = polygonItemEdge;
|
||||
m_highlightedObject = item;
|
||||
void BoundingRectHighlighter::highlightAll(bool animate)
|
||||
{
|
||||
foreach(BoundingBox *box, m_boxes) {
|
||||
QGraphicsObject *item = box->highlightedObject.data();
|
||||
if (!item) {
|
||||
m_boxes.removeOne(box);
|
||||
continue;
|
||||
}
|
||||
|
||||
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()));
|
||||
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)
|
||||
return;
|
||||
QGraphicsItem *itemToHighlight = m_subcomponentEditorTool->firstChildOfContext(item);
|
||||
highlight(QList<QGraphicsItem*>() << item);
|
||||
}
|
||||
|
||||
if (itemToHighlight) {
|
||||
m_boundingRectHighlighter->highlight(itemToHighlight->toGraphicsObject());
|
||||
} else {
|
||||
clearHighlightBoundingRect();
|
||||
void QDeclarativeDesignView::highlight(QList<QGraphicsItem *> items)
|
||||
{
|
||||
if (items.isEmpty())
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user