1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2002-2020 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 #ifndef ASSOCIATIONWIDGET_H
7 #define ASSOCIATIONWIDGET_H
8 
9 #include "associationwidgetlist.h"
10 #include "associationwidgetrole.h"
11 #include "linkwidget.h"
12 #include "messagewidgetlist.h"
13 #include "umlwidgetlist.h"
14 #include "widgetbase.h"
15 
16 class AssociationLine;
17 class ClassifierWidget;
18 class UMLScene;
19 class UMLAssociation;
20 class UMLAttribute;
21 class UMLClassifierListItem;
22 class UMLOperation;
23 
24 /**
25  * This class represents an association inside a diagram.
26  *
27  * Constructor is made non accessible:
28  * Users shall use the static create() methods for constructing AssociationWidgets.
29  *
30  * Associations exist not only between UML objects. For example, when a Note is
31  * attached to a UML object, the Note itself is not a UML object.
32  * This class supports both kinds of associations. An association where one or
33  * both roles are not a UML object is called a "pure widget association".
34  *
35  * An AssociationWidget where both roles are UML objects has a corresponding
36  * UMLAssociation. The UMLAssociation can be retrieved using the getAssociation
37  * method.
38  * A pure widget association does not have a corresponding UMLAssociation.
39  * The getAssociation method returns NULL in this case.
40  *
41  * @author Gustavo Madrigal
42  * @author Gopala Krishna
43  * @short This class represents an association inside a diagram.
44  * Bugs and comments to umbrello-devel@kde.org or https://bugs.kde.org
45  */
46 class AssociationWidget : public WidgetBase, public LinkWidget
47 {
48     Q_OBJECT
49 public:
50     static AssociationWidget* create(UMLScene *scene);
51     static AssociationWidget* create
52                      (UMLScene *scene, UMLWidget* WidgetA,
53                       Uml::AssociationType::Enum assocType, UMLWidget* WidgetB,
54                       UMLObject *umlobject = 0);
55 
56     virtual ~AssociationWidget();
57 
58     virtual void setUMLObject(UMLObject *obj);
59 
60     //---------- LinkWidget Interface methods implementation from now on.
61 
62     virtual void lwSetFont(QFont font);
63     virtual UMLClassifier *operationOwner();
64 
65     virtual UMLOperation *operation();
66     virtual void setOperation(UMLOperation *op);
67 
68     virtual QString customOpText();
69     virtual void setCustomOpText(const QString &opText);
70 
71     virtual void resetTextPositions();
72 
73     virtual void setMessageText(FloatingTextWidget *ft);
74     virtual void setText(FloatingTextWidget *ft, const QString &newText);
75 
76     virtual bool showPropertiesDialog();
77 
78     virtual QString lwOperationText();
79     virtual UMLClassifier *lwClassifier();
80     virtual void setOperationText(const QString &op);
81 
82     virtual void constrainTextPos(qreal &textX, qreal &textY,
83                                   qreal textWidth, qreal textHeight,
84                                   Uml::TextRole::Enum tr);
85 
86     virtual void calculateNameTextSegment();
87 
88     //---------- End LinkWidget Interface methods implementation.
89 
90     UMLAssociation* association() const;
91     UMLAttribute* attribute() const;
92 
93 //    AssociationWidget& operator=(const AssociationWidget& other);
94     bool operator==(const AssociationWidget& other) const;
95     bool operator!=(AssociationWidget& other) const;
96 
97     FloatingTextWidget* textWidgetByRole(Uml::TextRole::Enum tr) const;
98 
99     FloatingTextWidget* nameWidget() const;
100     QString name() const;
101     void setName(const QString &strRole);
102     void setStereotype(const QString &stereo);
103 
104     FloatingTextWidget* roleWidget(Uml::RoleType::Enum role) const;
105     QString roleName(Uml::RoleType::Enum role) const;
106     void setRoleName(const QString &strRole, Uml::RoleType::Enum role);
107 
108     QString roleDocumentation(Uml::RoleType::Enum role) const;
109     void setRoleDocumentation(const QString& doc, Uml::RoleType::Enum role);
110 
111     FloatingTextWidget* multiplicityWidget(Uml::RoleType::Enum role) const;
112     QString multiplicity(Uml::RoleType::Enum role) const;
113     void setMultiplicity(const QString& text, Uml::RoleType::Enum role);
114 
115     Uml::Visibility::Enum visibility(Uml::RoleType::Enum role) const;
116     void setVisibility(Uml::Visibility::Enum value, Uml::RoleType::Enum role);
117 
118     FloatingTextWidget* changeabilityWidget(Uml::RoleType::Enum role) const;
119     Uml::Changeability::Enum changeability(Uml::RoleType::Enum role) const;
120     void setChangeability(Uml::Changeability::Enum value, Uml::RoleType::Enum role);
121 
122     Uml::ID::Type widgetIDForRole(Uml::RoleType::Enum role) const;
123     Uml::ID::Type widgetLocalIDForRole(Uml::RoleType::Enum role) const;
124     UMLWidget* widgetForRole(Uml::RoleType::Enum role) const;
125     void setWidgetForRole(UMLWidget* widget, Uml::RoleType::Enum role);
126 
127     bool containsAsEndpoint(UMLWidget* widget);
128 
129     Uml::AssociationType::Enum associationType() const;
130     void setAssociationType(Uml::AssociationType::Enum type);
131 
132     bool isCollaboration() const;
133     bool isSelf() const;
134 
135     QString toString() const;
136 
137     bool isActivated() const;
138     void setActivated(bool active);
139 
140     AssociationLine* associationLine() const;
141 
142     virtual bool activate(IDChangeLog *changeLog = 0);
143     virtual QRectF boundingRect() const;
144     virtual QPainterPath shape() const;
145 
146     void widgetMoved(UMLWidget* widget, qreal x, qreal y);
147 
148     void saveIdealTextPositions();
149 
150     UMLWidget* onWidget(const QPointF &p);
151     bool onAssociation(const QPointF& point);
152     bool onAssocClassLine(const QPointF& point);
153 
154     void createAssocClassLine();
155     void createAssocClassLine(ClassifierWidget* classifierWidget,
156                               int linePathSegmentIndex);
157 
158     void selectAssocClassLine(bool sel = true);
159     void removeAssocClassLine();
160     void computeAssocClassLine();
161 
162     void setXEntireAssoc(qreal x);
163     void setYEntireAssoc(qreal y);
164 
165     void moveMidPointsBy(qreal x, qreal y);
166     void moveEntireAssoc(qreal x, qreal y);
167 
168     QFont font() const;
169 
170     virtual void setTextColor(const QColor &color);
171     virtual void setLineColor(const QColor &color);
172     virtual void setLineWidth(uint width);
173 
174     void calculateEndingPoints();
175 
176     void clipSize();
177 
178     bool loadFromXMI1(QDomElement& qElement, const UMLWidgetList& widgets,
179                      const MessageWidgetList* messages);
180     virtual bool loadFromXMI1(QDomElement& qElement);
181     virtual void saveToXMI1(QXmlStreamWriter& writer);
182 
183     void cleanup();
184 
185     bool isPointAddable();
186     bool isPointRemovable();
187     bool isAutoLayouted();
188     bool isLayoutChangeable();
189 
190     virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
191     virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
192     virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
193     virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
194 
195     virtual void setSelected(bool _select);
196 
197 public Q_SLOTS:  //:TODO: all virtual?
198     virtual void slotMenuSelection(QAction* action);
199     void slotClassifierListItemRemoved(UMLClassifierListItem* obj);
200     void slotAttributeChanged();
201 
202     void syncToModel();
203 
204 protected:
205     virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
206 
207     virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
208     virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
209     virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
210 
211 private:
212     QPointF calculateTextPosition(Uml::TextRole::Enum role);
213     void setTextPosition(Uml::TextRole::Enum role);
214     void setTextPositionRelatively(Uml::TextRole::Enum role, const QPointF &oldPosition);
215     void setFloatingText(Uml::TextRole::Enum role, const QString& text, FloatingTextWidget* &ft);
216 
217     AssociationWidget(UMLScene *scene);
218 
219     void setUMLAssociation(UMLAssociation * assoc);
220 
221     void mergeAssociationDataIntoUMLRepresentation();
222 
223     static Uml::Region::Enum findPointRegion(const QRectF& rect, const QPointF& pos);
224     static qreal findInterceptOnEdge(const QRectF &rect, Uml::Region::Enum region, const QPointF &point);
225     static QLineF::IntersectType intersect(const QRectF &rect, const QLineF &line,
226                                            QPointF* intersectionPoint);
227 
228     void moveEvent(QGraphicsSceneMouseEvent *me);
229 
230     Uml::TextRole::Enum calculateNameType(Uml::TextRole::Enum defaultRoleType);
231 
232     static QPointF swapXY(const QPointF &p);
233 
234     // not used at the moment
235     // static QPointF calculatePointAtDistance(const QPointF &P1, const QPointF &P2, float Distance);
236     // static QPointF calculatePointAtDistanceOnPerpendicular(const QPointF &P1, const QPointF &P2, float Distance);
237     // static float perpendicularProjection(const QPointF& P1, const QPointF& P2, const QPointF& P3, QPointF& ResultingPoint);
238 
239     static QPointF midPoint(const QPointF& p0, const QPointF& p1);
240 
241     void createPointsSelfAssociation();
242     void updatePointsSelfAssociation();
243     void createPointsException();
244     void updatePointsException();
245 
246     void updateRegionLineCount(int index, int totalCount,
247                                Uml::Region::Enum region, Uml::RoleType::Enum role);
248 
249     void updateAssociations(int totalCount, Uml::Region::Enum region, Uml::RoleType::Enum role);
250 
251     int getRegionCount(Uml::Region::Enum region, Uml::RoleType::Enum role);
252 
253     void doUpdates(const QPointF &otherP, Uml::RoleType::Enum role);
254 
255     void setChangeWidget(const QString &strChangeWidget, Uml::RoleType::Enum role);
256 
257     bool checkAddPoint(const QPointF &scenePos);
258     bool checkRemovePoint(const QPointF &scenePos);
259     bool checkAutoLayoutSpline();
260 
261     bool linePathStartsAt(const UMLWidget* widget);
262 
263     void insertIntoLists(qreal position, const AssociationWidget* assoc);
264 
265     qreal m_positions[100];           ///< auxiliary variable for updateAssociations()
266     int m_positions_len;              ///< auxiliary variable for updateAssociations()
267     AssociationWidgetList m_ordered;  ///< auxiliary variable for updateAssociations()
268 
269     bool m_activated;   ///< flag which is true if the activate method has been called for this class instance
270 
271     /**
272      * When the association has a Role Floating Text this text should move
273      * when the AssociationLine moves but only if the closest segment to the
274      * role text moves.
275      * This segment is:
276      * m_associationLine[m_unNameLineSegment] -- m_associationLine[m_unNameLineSegment+1]
277      */
278     int                 m_unNameLineSegment;
279 
280     QPointF m_oldNamePoint;    ///< Position of name floatingtext saved by saveIdealTextPositions()
281     QPointF m_oldMultiAPoint;  ///< Position of role A multiplicity floatingtext saved by saveIdealTextPositions()
282     QPointF m_oldMultiBPoint;  ///< Position of role B multiplicity floatingtext saved by saveIdealTextPositions()
283     QPointF m_oldChangeAPoint; ///< Position of role A changeability floatingtext saved by saveIdealTextPositions()
284     QPointF m_oldChangeBPoint; ///< Position of role B changeability floatingtext saved by saveIdealTextPositions()
285     QPointF m_oldRoleAPoint;   ///< Position of role A name floatingtext saved by saveIdealTextPositions()
286     QPointF m_oldRoleBPoint;   ///< Position of role B name floatingtext saved by saveIdealTextPositions()
287 
288     int m_nLinePathSegmentIndex;               ///< anchor for m_pAssocClassLine
289     QGraphicsLineItem *m_pAssocClassLine;      ///< used for connecting assoc. class
290     QGraphicsRectItem *m_pAssocClassLineSel0;  ///< selection decoration for the start point of the assoc. class line
291     QGraphicsRectItem *m_pAssocClassLineSel1;  ///< selection decoration for the end point of the assoc. class line
292 
293     AssociationLine *m_associationLine;      ///< the definition points for the association line
294     ClassifierWidget *m_associationClass;    ///< used if we have an assoc. class
295     Uml::AssociationType::Enum m_associationType;  ///< is only used if m_pObject is not set
296     AssociationWidgetRole  m_role[2];
297     FloatingTextWidget* m_nameWidget;  ///< displays the name of this association
298     QPointF m_eventScenePos;           ///< holds scene pos of contextMenuEvent()
299 
300 };
301 
302 #endif
303