aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/modelinglib
diff options
context:
space:
mode:
authorJochen Becher <jochen_becher@gmx.de>2018-08-09 09:11:25 +0200
committerJochen Becher <jochen_becher@gmx.de>2018-09-03 17:51:03 +0000
commit741885a52b29259c2798491cf7b1acf7ab728d08 (patch)
tree1dcacddf0fb150b94b9b3da83fc14fc610fd66e4 /src/libs/modelinglib
parent39d7aa7f70a30a53c55393298a16b61c6f5b1667 (diff)
ModelEditor: Layout elements on diagram
Change-Id: I7f02375a4c4626ba4719bb965eb949c07f628a01 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/libs/modelinglib')
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/capabilities/alignable.h6
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp36
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp4
-rw-r--r--src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp123
-rw-r--r--src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h9
5 files changed, 174 insertions, 4 deletions
diff --git a/src/libs/modelinglib/qmt/diagram_scene/capabilities/alignable.h b/src/libs/modelinglib/qmt/diagram_scene/capabilities/alignable.h
index 2b569ecce8d..34664957b6f 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/capabilities/alignable.h
+++ b/src/libs/modelinglib/qmt/diagram_scene/capabilities/alignable.h
@@ -41,7 +41,11 @@ public:
AlignVcenter,
AlignWidth,
AlignHeight,
- AlignSize
+ AlignSize,
+ AlignHCenterDistance,
+ AlignVCenterDistance,
+ AlignHBorderDistance,
+ AlignVBorderDistance
};
virtual ~IAlignable() {}
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
index d6cf0848be1..8bd92463364 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
@@ -447,6 +447,26 @@ void ObjectItem::align(IAlignable::AlignType alignType, const QString &identifie
minimumSize(m_diagramSceneModel->selectedItems()),
m_diagramSceneModel->diagram());
break;
+ case IAlignable::AlignHCenterDistance:
+ QMT_CHECK(identifier == "sameHCenterDistance");
+ m_diagramSceneModel->diagramSceneController()->alignHCenterDistance(m_diagramSceneModel->selectedElements(),
+ m_diagramSceneModel->diagram());
+ break;
+ case IAlignable::AlignVCenterDistance:
+ QMT_CHECK(identifier == "sameVCenterDistance");
+ m_diagramSceneModel->diagramSceneController()->alignVCenterDistance(m_diagramSceneModel->selectedElements(),
+ m_diagramSceneModel->diagram());
+ break;
+ case IAlignable::AlignHBorderDistance:
+ QMT_CHECK(identifier == "sameHBorderDistance");
+ m_diagramSceneModel->diagramSceneController()->alignHBorderDistance(m_diagramSceneModel->selectedElements(),
+ m_diagramSceneModel->diagram());
+ break;
+ case IAlignable::AlignVBorderDistance:
+ QMT_CHECK(identifier == "sameVBorderDistance");
+ m_diagramSceneModel->diagramSceneController()->alignVBorderDistance(m_diagramSceneModel->selectedElements(),
+ m_diagramSceneModel->diagram());
+ break;
}
}
@@ -1008,6 +1028,14 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
alignMenu.addAction(new ContextMenuAction(tr("Same Size"), "sameSize", &alignMenu));
alignMenu.setEnabled(m_diagramSceneModel->hasMultiObjectsSelection());
menu.addMenu(&alignMenu);
+ QMenu layoutMenu;
+ layoutMenu.setTitle(tr("Layout Objects"));
+ layoutMenu.addAction(new ContextMenuAction(tr("Equal Horizontal Distance"), "sameHCenterDistance", &alignMenu));
+ layoutMenu.addAction(new ContextMenuAction(tr("Equal Vertical Distance"), "sameVCenterDistance", &alignMenu));
+ layoutMenu.addAction(new ContextMenuAction(tr("Equal Horizontal Space"), "sameHBorderDistance", &alignMenu));
+ layoutMenu.addAction(new ContextMenuAction(tr("Equal Vertical Space"), "sameVBorderDistance", &alignMenu));
+ layoutMenu.setEnabled(m_diagramSceneModel->hasMultiObjectsSelection());
+ menu.addMenu(&layoutMenu);
menu.addAction(new ContextMenuAction(tr("Add Related Elements"), "addRelatedElements", &menu));
QAction *selectedAction = menu.exec(event->screenPos());
@@ -1045,6 +1073,14 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
align(IAlignable::AlignHcenter, "center");
} else if (action->id() == "alignBottom") {
align(IAlignable::AlignBottom, "bottom");
+ } else if (action->id() == "sameHCenterDistance") {
+ align(IAlignable::AlignHCenterDistance, "sameHCenterDistance");
+ } else if (action->id() == "sameVCenterDistance") {
+ align(IAlignable::AlignVCenterDistance, "sameVCenterDistance");
+ } else if (action->id() == "sameHBorderDistance") {
+ align(IAlignable::AlignHBorderDistance, "sameHBorderDistance");
+ } else if (action->id() == "sameVBorderDistance") {
+ align(IAlignable::AlignVBorderDistance, "sameVBorderDistance");
} else if (action->id() == "sameWidth") {
align(IAlignable::AlignWidth, "width");
} else if (action->id() == "sameHeight") {
diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp
index 4848d91c75b..6a68f5fdc70 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/parts/alignbuttonsitem.cpp
@@ -167,6 +167,10 @@ void AlignButtonsItem::addButton(IAlignable::AlignType alignType, const QString
case IAlignable::AlignWidth:
case IAlignable::AlignHeight:
case IAlignable::AlignSize:
+ case IAlignable::AlignHCenterDistance:
+ case IAlignable::AlignVCenterDistance:
+ case IAlignable::AlignHBorderDistance:
+ case IAlignable::AlignVBorderDistance:
QMT_CHECK(false);
break;
}
diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
index ef36d78b8eb..8147303adea 100644
--- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
+++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
@@ -654,6 +654,118 @@ void DiagramSceneController::alignSize(DObject *object, const DSelection &select
alignSize(object, selection, minimumSize, alignObjectSize, diagram);
}
+void DiagramSceneController::alignHCenterDistance(const DSelection &selection, MDiagram *diagram)
+{
+ QList<DObject *> sortedObjects = collectObjects(selection, diagram);
+ if (sortedObjects.length() > 2) {
+ std::sort(sortedObjects.begin(), sortedObjects.end(), [](const DObject *lhs, const DObject *rhs) {
+ return lhs->pos().x() < rhs->pos().x();
+ });
+ int n = sortedObjects.length() - 1;
+ DObject *leftObject = sortedObjects.at(0);
+ DObject *rightObject = sortedObjects.at(n);
+ double distance = rightObject->pos().x() - leftObject->pos().x();
+ double step = distance / n;
+ double startX = leftObject->pos().x();
+ for (int i = 1; i < n; ++i) {
+ DObject *selectedObject = sortedObjects.at(i);
+ QPointF newPos = selectedObject->pos();
+ newPos.setX(startX + i * step);
+ if (newPos != selectedObject->pos()) {
+ m_diagramController->startUpdateElement(selectedObject, diagram, DiagramController::UpdateGeometry);
+ selectedObject->setPos(newPos);
+ m_diagramController->finishUpdateElement(selectedObject, diagram, false);
+ }
+ }
+ }
+}
+
+void DiagramSceneController::alignVCenterDistance(const DSelection &selection, MDiagram *diagram)
+{
+ QList<DObject *> sortedObjects = collectObjects(selection, diagram);
+ if (sortedObjects.length() > 2) {
+ std::sort(sortedObjects.begin(), sortedObjects.end(), [](const DObject *lhs, const DObject *rhs) {
+ return lhs->pos().y() < rhs->pos().y();
+ });
+ int n = sortedObjects.length() - 1;
+ DObject *topObject = sortedObjects.at(0);
+ DObject *bottomObject = sortedObjects.at(n);
+ double distance = bottomObject->pos().y() - topObject->pos().y();
+ double step = distance / n;
+ double startY = topObject->pos().y();
+ for (int i = 1; i < n; ++i) {
+ DObject *selectedObject = sortedObjects.at(i);
+ QPointF newPos = selectedObject->pos();
+ newPos.setY(startY + i * step);
+ if (newPos != selectedObject->pos()) {
+ m_diagramController->startUpdateElement(selectedObject, diagram, DiagramController::UpdateGeometry);
+ selectedObject->setPos(newPos);
+ m_diagramController->finishUpdateElement(selectedObject, diagram, false);
+ }
+ }
+ }
+}
+
+void DiagramSceneController::alignHBorderDistance(const DSelection &selection, MDiagram *diagram)
+{
+ QList<DObject *> sortedObjects = collectObjects(selection, diagram);
+ if (sortedObjects.length() > 2) {
+ std::sort(sortedObjects.begin(), sortedObjects.end(), [](const DObject *lhs, const DObject *rhs) {
+ return lhs->pos().x() < rhs->pos().x();
+ });
+ int n = sortedObjects.length() - 1;
+ DObject *leftObject = sortedObjects.at(0);
+ DObject *rightObject = sortedObjects.at(n);
+ double space = rightObject->pos().x() + rightObject->rect().left() - (leftObject->pos().x() + leftObject->rect().right());
+ for (int i = 1; i < n; ++i)
+ space -= sortedObjects.at(i)->rect().width();
+ double step = space / n;
+ double x = leftObject->pos().x() + leftObject->rect().right();
+ for (int i = 1 ; i < n; ++i) {
+ DObject *selectedObject = sortedObjects.at(i);
+ QPointF newPos = selectedObject->pos();
+ x += step;
+ newPos.setX(x - selectedObject->rect().left());
+ x += selectedObject->rect().width();
+ if (newPos != selectedObject->pos()) {
+ m_diagramController->startUpdateElement(selectedObject, diagram, DiagramController::UpdateGeometry);
+ selectedObject->setPos(newPos);
+ m_diagramController->finishUpdateElement(selectedObject, diagram, false);
+ }
+ }
+ }
+}
+
+void DiagramSceneController::alignVBorderDistance(const DSelection &selection, MDiagram *diagram)
+{
+ QList<DObject *> sortedObjects = collectObjects(selection, diagram);
+ if (sortedObjects.length() > 2) {
+ std::sort(sortedObjects.begin(), sortedObjects.end(), [](const DObject *lhs, const DObject *rhs) {
+ return lhs->pos().y() < rhs->pos().y();
+ });
+ int n = sortedObjects.length() - 1;
+ DObject *topObject = sortedObjects.at(0);
+ DObject *bottomObject = sortedObjects.at(n);
+ double space = bottomObject->pos().y() + bottomObject->rect().top() - (topObject->pos().y() + topObject->rect().bottom());
+ for (int i = 1; i < n; ++i)
+ space -= sortedObjects.at(i)->rect().height();
+ double step = space / n;
+ double y = topObject->pos().y() + topObject->rect().bottom();
+ for (int i = 1 ; i < n; ++i) {
+ DObject *selectedObject = sortedObjects.at(i);
+ QPointF newPos = selectedObject->pos();
+ y += step;
+ newPos.setY(y - selectedObject->rect().top());
+ y += selectedObject->rect().height();
+ if (newPos != selectedObject->pos()) {
+ m_diagramController->startUpdateElement(selectedObject, diagram, DiagramController::UpdateGeometry);
+ selectedObject->setPos(newPos);
+ m_diagramController->finishUpdateElement(selectedObject, diagram, false);
+ }
+ }
+ }
+}
+
void DiagramSceneController::alignPosition(DObject *object, const DSelection &selection,
QPointF (*aligner)(DObject *, DObject *), MDiagram *diagram)
{
@@ -707,6 +819,17 @@ void DiagramSceneController::alignOnRaster(DElement *element, MDiagram *diagram)
element->accept(&visitor);
}
+QList<DObject *> DiagramSceneController::collectObjects(const DSelection &selection, MDiagram *diagram)
+{
+ QList<DObject *> list;
+ foreach (const DSelection::Index &index, selection.indices()) {
+ DObject *object = m_diagramController->findElement<DObject>(index.elementKey(), diagram);
+ if (object)
+ list.append(object);
+ }
+ return list;
+}
+
DElement *DiagramSceneController::addModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram)
{
DElement *element = nullptr;
diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
index 97717cbc21d..5f925df48b5 100644
--- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
+++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
@@ -125,9 +125,10 @@ public:
MDiagram *diagram);
void alignSize(DObject *object, const DSelection &selection, const QSizeF &minimumSize,
MDiagram *diagram);
- void distributeHorizontal(DObject *object, const DSelection &selection, MDiagram *diagram);
- void distributeVertical(DObject *object, const DSelection &selection, MDiagram *diagram);
- void distributeField(DObject *object, const DSelection &selection, MDiagram *diagram);
+ void alignHCenterDistance(const DSelection &selection, MDiagram *diagram);
+ void alignVCenterDistance(const DSelection &selection, MDiagram *diagram);
+ void alignHBorderDistance(const DSelection &selection, MDiagram *diagram);
+ void alignVBorderDistance(const DSelection &selection, MDiagram *diagram);
private:
void alignPosition(DObject *object, const DSelection &selection,
@@ -137,6 +138,8 @@ private:
QRectF (*aligner)(DObject *, const QSizeF &), MDiagram *diagram);
void alignOnRaster(DElement *element, MDiagram *diagram);
+ QList<DObject *> collectObjects(const DSelection &selection, MDiagram *diagram);
+
DElement *addModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram);
DObject *addObject(MObject *modelObject, const QPointF &pos, MDiagram *diagram);
DRelation *addRelation(MRelation *modelRelation, const QList<QPointF> &intermediatePoints,