diff options
author | Jochen Becher <jochen_becher@gmx.de> | 2019-11-16 17:43:31 +0100 |
---|---|---|
committer | Jochen Becher <jochen_becher@gmx.de> | 2020-02-25 19:21:48 +0000 |
commit | 23946de45755ce58d55004bf3e508a83d6299573 (patch) | |
tree | c284eadf8f2df71e309017a1b949e79292e4515d /src/libs/modelinglib | |
parent | 7dbf2c01c79e1e7ee78de4df3cb25bc54df21949 (diff) |
modeleditor: Intersect relations with shape of item
Change-Id: I40d898715772f74ffa225ac27b91ee7ad4d8fedc
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/libs/modelinglib')
16 files changed, 309 insertions, 38 deletions
diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp index fe070fc08ae..121fd1ff69d 100644 --- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp +++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp @@ -55,6 +55,7 @@ static const int KEYWORD_DISPLAY = 11; static const int KEYWORD_TEXTALIGN = 12; static const int KEYWORD_BASECOLOR = 13; static const int KEYWORD_SHAPE = 14; +static const int KEYWORD_OUTLINE = 15; // Shape items static const int KEYWORD_CIRCLE = 30; @@ -245,6 +246,7 @@ void StereotypeDefinitionParser::parse(ITextSource *source) << qMakePair(QString("textalignment"), KEYWORD_TEXTALIGN) << qMakePair(QString("basecolor"), KEYWORD_BASECOLOR) << qMakePair(QString("shape"), KEYWORD_SHAPE) + << qMakePair(QString("outline"), KEYWORD_OUTLINE) << qMakePair(QString("circle"), KEYWORD_CIRCLE) << qMakePair(QString("ellipse"), KEYWORD_ELLIPSE) << qMakePair(QString("line"), KEYWORD_LINE) @@ -436,6 +438,9 @@ void StereotypeDefinitionParser::parseIcon() case KEYWORD_SHAPE: stereotypeIcon.setIconShape(parseIconShape()); break; + case KEYWORD_OUTLINE: + stereotypeIcon.setOutlineShape(parseIconShape()); + break; case KEYWORD_NAME: stereotypeIcon.setName(parseStringProperty()); stereotypeIcon.setHasName(true); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp index 3e65c36daee..bf891a855b4 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp @@ -287,8 +287,13 @@ void ClassItem::update() bool ClassItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { + if (m_customIcon) { + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); + } QPolygonF polygon; - // TODO if m_customIcon then use that shape + label's shape as intersection path QRectF rect = object()->rect(); rect.translate(object()->pos()); polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp index 92b94a1b9ad..18e0fc5622e 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp @@ -160,13 +160,14 @@ void ComponentItem::update() bool ComponentItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else if (hasPlainShape()) { + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); + } + QPolygonF polygon; + if (hasPlainShape()) { QRectF rect = object()->rect(); rect.translate(object()->pos()); polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp index c3cce6a2972..a8e719b8d8e 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp @@ -122,17 +122,17 @@ void DiagramItem::update() bool DiagramItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else { - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); } + QPolygonF polygon; + QRectF rect = object()->rect(); + rect.translate(object()->pos()); + // TODO use real outline + polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); } diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp index e3b50bab1b6..3d623d40b5e 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp @@ -130,17 +130,16 @@ void ItemItem::update() bool ItemItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else { - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); } + QRectF rect = object()->rect(); + rect.translate(object()->pos()); + QPolygonF polygon; + polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); } diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp index 8cc4f7ed927..b5526e54239 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp @@ -141,21 +141,20 @@ void PackageItem::update() bool PackageItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - QPolygonF polygon; if (m_customIcon) { - // TODO use customIcon path as shape - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); - } else { - QRectF rect = object()->rect(); - rect.translate(object()->pos()); - ShapeGeometry shape = calcMinimumGeometry(); - polygon << rect.topLeft() << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), 0.0)) - << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), shape.m_minimumTabSize.height())) - << rect.topRight() + QPointF(0.0, shape.m_minimumTabSize.height()) - << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); + QList<QPolygonF> polygons = m_customIcon->outline(); + for (int i = 0; i < polygons.size(); ++i) + polygons[i].translate(object()->pos() + object()->rect().topLeft()); + return GeometryUtilities::intersect(polygons, line, nullptr, intersectionPoint, intersectionLine); } + QPolygonF polygon; + QRectF rect = object()->rect(); + rect.translate(object()->pos()); + ShapeGeometry shape = calcMinimumGeometry(); + polygon << rect.topLeft() << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), 0.0)) + << (rect.topLeft() + QPointF(shape.m_minimumTabSize.width(), shape.m_minimumTabSize.height())) + << rect.topRight() + QPointF(0.0, shape.m_minimumTabSize.height()) + << rect.bottomRight() << rect.bottomLeft() << rect.topLeft(); return GeometryUtilities::intersect(polygon, line, intersectionPoint, intersectionLine); } diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp index 374f1e786a9..13a8e4cbce4 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp @@ -33,6 +33,8 @@ #include <QPainter> +//#define DEBUG_OUTLINE + namespace qmt { CustomIconItem::CustomIconItem(DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent) @@ -102,9 +104,30 @@ void CustomIconItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *op painter->save(); painter->setBrush(m_brush); painter->setPen(m_pen); +#ifdef DEBUG_OUTLINE + ShapePolygonVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + IconShape shape = m_stereotypeIcon.outlineShape(); + if (shape.isEmpty()) + shape = m_stereotypeIcon.iconShape(); + shape.visitShapes(&visitor); + painter->drawPath(visitor.path()); + ShapePaintVisitor visitor1(painter, QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + m_stereotypeIcon.iconShape().visitShapes(&visitor1); +#else ShapePaintVisitor visitor(painter, QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); m_stereotypeIcon.iconShape().visitShapes(&visitor); +#endif painter->restore(); } +QList<QPolygonF> CustomIconItem::outline() const +{ + ShapePolygonVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + IconShape shape = m_stereotypeIcon.outlineShape(); + if (shape.isEmpty()) + shape = m_stereotypeIcon.iconShape(); + shape.visitShapes(&visitor); + return visitor.toPolygons(); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h index 93e083b9625..ce4ea972604 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h @@ -55,6 +55,8 @@ public: QRectF boundingRect() const override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + QList<QPolygonF> outline() const; + private: DiagramSceneModel *m_diagramSceneModel = nullptr; QString m_stereotypeIconId; diff --git a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp index 6f9b34aa0c2..91886cf49ed 100644 --- a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp +++ b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.cpp @@ -88,6 +88,49 @@ bool GeometryUtilities::intersect(const QPolygonF &polygon, const QLineF &line, return found; } +bool GeometryUtilities::intersect(const QList<QPolygonF> &polygons, const QLineF &line, + int *intersectionPolygon, QPointF *intersectionPoint, + QLineF *intersectionLine, int nearestPoint) +{ + bool found = false; + qreal mindist = 0; + int ipolygon = -1; + QPointF ipoint; + QLineF iline; + for (int p = 0; p < polygons.size(); ++p) { + const QPolygonF polygon = polygons.at(p); + for (int i = 0; i <= polygon.size() - 2; ++i) { + const QLineF polygonLine(polygon.at(i), polygon.at(i + 1)); + QPointF point; +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QLineF::IntersectType intersectionType = polygonLine.intersect(line, &point); +#else + QLineF::IntersectType intersectionType = polygonLine.intersects(line, &point); +#endif + if (intersectionType == QLineF::BoundedIntersection) { + qreal dist = QLineF(point, nearestPoint <= 0 ? line.p1() : line.p2()).length(); + if (!found || dist < mindist) { + mindist = dist; + ipolygon = p; + ipoint = point; + iline = polygonLine; + found = true; + } + } + } + } + if (found) { + if (intersectionPolygon) + *intersectionPolygon = ipolygon; + if (intersectionPoint) + *intersectionPoint = ipoint; + if (intersectionLine) + *intersectionLine = iline; + } + return found; +} + + namespace { class Candidate diff --git a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h index 2ec1701aa09..6f39352f3f7 100644 --- a/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h +++ b/src/libs/modelinglib/qmt/infrastructure/geometryutilities.h @@ -54,6 +54,9 @@ public: static bool intersect(const QPolygonF &polygon, const QLineF &line, QPointF *intersectionPoint = nullptr, QLineF *intersectionLine = nullptr, int nearestPoint = 1); + static bool intersect(const QList<QPolygonF> &polygons, const QLineF &line, + int *intersectionPolygon, QPointF *intersectionPoint = nullptr, QLineF *intersectionLine = nullptr, + int nearestPoint = 1); static bool placeRectAtLine(const QRectF &rect, const QLineF &line, double lineOffset, double distance, const QLineF &intersectionLine, QPointF *placement, Side *horizontalAlignedSide); diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp index 172bb369841..fc8e076ac8a 100644 --- a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp +++ b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp @@ -107,6 +107,11 @@ IconShape &IconShape::operator=(const IconShape &rhs) return *this; } +bool IconShape::isEmpty() const +{ + return d->m_shapes.isEmpty(); +} + void IconShape::addLine(const ShapePointF &pos1, const ShapePointF &pos2) { d->m_shapes.append(new LineShape(pos1, pos2)); diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.h b/src/libs/modelinglib/qmt/stereotype/iconshape.h index 215dc8adecf..87880f2c5cf 100644 --- a/src/libs/modelinglib/qmt/stereotype/iconshape.h +++ b/src/libs/modelinglib/qmt/stereotype/iconshape.h @@ -46,6 +46,7 @@ public: IconShape &operator=(const IconShape &rhs); + bool isEmpty() const; QSizeF size() const; void setSize(const QSizeF &size); diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp index 880835287ad..04c5a0a32c4 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp +++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp @@ -261,4 +261,152 @@ void ShapeSizeVisitor::visitPath(const PathShape *shapePath) m_boundingRect |= path.boundingRect(); } +ShapePolygonVisitor::ShapePolygonVisitor(const QPointF &scaledOrigin, const QSizeF &originalSize, + const QSizeF &baseSize, const QSizeF &size) + : m_scaledOrigin(scaledOrigin), + m_originalSize(originalSize), + m_baseSize(baseSize), + m_size(size) +{ + m_path.setFillRule(Qt::WindingFill); +} + +QList<QPolygonF> ShapePolygonVisitor::toPolygons() const +{ + return m_path.toSubpathPolygons(); +} + +void ShapePolygonVisitor::visitLine(const LineShape *shapeLine) +{ + QPointF p1 = shapeLine->pos1().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size); + QPointF p2 = shapeLine->pos2().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size); + m_path.moveTo(p1); + m_path.lineTo(p2); +} + +void ShapePolygonVisitor::visitRect(const RectShape *shapeRect) +{ + m_path.addRect(QRectF(shapeRect->pos().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + shapeRect->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size))); +} + +void ShapePolygonVisitor::visitRoundedRect(const RoundedRectShape *shapeRoundedRect) +{ + qreal radiusX = shapeRoundedRect->radius().mapScaledTo(0, m_originalSize.width(), + m_baseSize.width(), m_size.width()); + qreal radiusY = shapeRoundedRect->radius().mapScaledTo(0, m_originalSize.height(), + m_baseSize.height(), m_size.height()); + m_path.addRoundedRect(QRectF(shapeRoundedRect->pos().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + shapeRoundedRect->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size)), + radiusX, radiusY); +} + +void ShapePolygonVisitor::visitCircle(const CircleShape *shapeCircle) +{ + m_path.addEllipse(shapeCircle->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + shapeCircle->radius().mapScaledTo(m_scaledOrigin.x(), m_originalSize.width(), + m_baseSize.width(), m_size.width()), + shapeCircle->radius().mapScaledTo(m_scaledOrigin.y(), m_originalSize.height(), + m_baseSize.height(), m_size.height())); +} + +void ShapePolygonVisitor::visitEllipse(const EllipseShape *shapeEllipse) +{ + QSizeF radius = shapeEllipse->radius().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + m_path.addEllipse(shapeEllipse->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size), + radius.width(), radius.height()); +} + +void ShapePolygonVisitor::visitDiamond(const DiamondShape *shapeDiamond) +{ + QPainterPath path; + QPointF center = shapeDiamond->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + QSizeF size = shapeDiamond->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.moveTo(center + QPointF(0.0, size.height() / 2.0)); + path.lineTo(center + QPointF(-size.width() / 2.0, 0.0)); + path.lineTo(center + QPointF(0.0, -size.height() / 2.0)); + path.lineTo(center + QPointF(size.width() / 2.0, 0.0)); + path.closeSubpath(); + m_path.addPath(path); +} + +void ShapePolygonVisitor::visitTriangle(const TriangleShape *shapeTriangle) +{ + QPainterPath path; + QPointF center = shapeTriangle->center().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + QSizeF size = shapeTriangle->size().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.moveTo(center + QPointF(size.width() / 2.0, size.height() / 2.0)); + path.lineTo(center + QPointF(-size.width() / 2.0, size.height() / 2.0)); + path.lineTo(center + QPointF(0.0, -size.height() / 2.0)); + path.closeSubpath(); + m_path.addPath(path); +} + +void ShapePolygonVisitor::visitArc(const ArcShape *shapeArc) +{ + QSizeF radius = shapeArc->radius().mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + QRectF rect(shapeArc->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size) + - QPointF(radius.width(), radius.height()), radius * 2.0); + m_path.arcMoveTo(rect, shapeArc->startAngle()); + m_path.arcTo(rect, shapeArc->startAngle(), shapeArc->spanAngle()); +} + +void ShapePolygonVisitor::visitPath(const PathShape *shapePath) +{ + QPainterPath path; + for (const PathShape::Element &element: shapePath->elements()) { + switch (element.m_elementType) { + case PathShape::TypeNone: + // nothing to do + break; + case PathShape::TypeMoveto: + path.moveTo(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size)); + break; + case PathShape::TypeLineto: + path.lineTo(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size)); + break; + case PathShape::TypeArcmoveto: + { + QSizeF radius = element.m_size.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.arcMoveTo(QRectF(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size) + - QPointF(radius.width(), radius.height()), + radius * 2.0), + element.m_angle1); + break; + } + case PathShape::TypeArcto: + { + QSizeF radius = element.m_size.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size); + path.arcTo(QRectF(element.m_position.mapScaledTo(m_scaledOrigin, m_originalSize, + m_baseSize, m_size) + - QPointF(radius.width(), radius.height()), + radius * 2.0), + element.m_angle1, element.m_angle2); + break; + } + case PathShape::TypeClose: + path.closeSubpath(); + break; + } + } + m_path.addPath(path); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h index 92e340e3e94..8ad4074764e 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h +++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h @@ -31,6 +31,8 @@ #include <QPainter> #include <QPointF> #include <QSizeF> +#include <QPolygonF> +#include <QPainterPath> namespace qmt { @@ -84,4 +86,31 @@ private: QRectF m_boundingRect; }; +class QMT_EXPORT ShapePolygonVisitor : public ShapeConstVisitor +{ +public: + ShapePolygonVisitor(const QPointF &scaledOrigin, const QSizeF &originalSize, + const QSizeF &baseSize, const QSizeF &size); + + QPainterPath path() const { return m_path; } + QList<QPolygonF> toPolygons() const; + + void visitLine(const LineShape *shapeLine) override; + void visitRect(const RectShape *shapeRect) override; + void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) override; + void visitCircle(const CircleShape *shapeCircle) override; + void visitEllipse(const EllipseShape *shapeEllipse) override; + void visitDiamond(const DiamondShape *shapeDiamond) override; + void visitTriangle(const TriangleShape *shapeTriangle) override; + void visitArc(const ArcShape *shapeArc) override; + void visitPath(const PathShape *shapePath) override; + +private: + QPointF m_scaledOrigin; + QSizeF m_originalSize; + QSizeF m_baseSize; + QSizeF m_size; + QPainterPath m_path; +}; + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp index d11cace46bc..f9610851f3b 100644 --- a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp +++ b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.cpp @@ -109,4 +109,9 @@ void StereotypeIcon::setIconShape(const IconShape &iconShape) m_iconShape = iconShape; } +void StereotypeIcon::setOutlineShape(const IconShape &outlineShape) +{ + m_outlineShape = outlineShape; +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h index 4465734cfdd..ab837bd333d 100644 --- a/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h +++ b/src/libs/modelinglib/qmt/stereotype/stereotypeicon.h @@ -100,6 +100,8 @@ public: void setBaseColor(const QColor &baseColor); IconShape iconShape() const { return m_iconShape; } void setIconShape(const IconShape &iconShape); + IconShape outlineShape() const { return m_outlineShape; } + void setOutlineShape(const IconShape &outlineShape); private: QString m_id; @@ -117,6 +119,7 @@ private: TextAlignment m_textAlignment = TextalignBelow; QColor m_baseColor; IconShape m_iconShape; + IconShape m_outlineShape; }; } // namespace qmt |