1 /*
2     SPDX-License-Identifier: GPL-2.0-or-later
3     SPDX-FileCopyrightText: 2002-2021 Umbrello UML Modeller Authors <umbrello-devel@kde.org>
4 */
5 
6 #ifndef UMLWIDGET_H
7 #define UMLWIDGET_H
8 
9 #include "associationwidgetlist.h"
10 #include "basictypes.h"
11 #include "optionstate.h"
12 #include "umlobject.h"
13 #include "umlwidgetlist.h"
14 #include "widgetbase.h"
15 #include "diagramproxywidget.h"
16 
17 #include <QCursor>
18 #include <QFont>
19 
20 class IDChangeLog;
21 class UMLDoc;
22 class UMLObject;
23 class UMLScene;
24 
25 class QPainter;
26 class QFontMetrics;
27 
28 /**
29  * This is the base class for nearly all graphical widgets.
30  *
31  * @short The base class for graphical UML objects.
32  * @author  Paul Hensgen <phensgen@techie.com>
33  * Bugs and comments to umbrello-devel@kde.org or https://bugs.kde.org
34  */
35 class UMLWidget : public WidgetBase, public DiagramProxyWidget
36 {
37     Q_OBJECT
38 public:
39 
40     friend class ToolBarStateArrow;  // for calling the mouse*Event handlers
41 
42     static const QSizeF DefaultMinimumSize;
43     static const QSizeF DefaultMaximumSize;
44     static const int defaultMargin;
45     static const int selectionMarkerSize;
46     static const int resizeMarkerLineCount;
47 
48     explicit UMLWidget(UMLScene *scene, WidgetType type = wt_UMLWidget, UMLObject *o = 0);
49     explicit UMLWidget(UMLScene *scene, WidgetType type = wt_UMLWidget, Uml::ID::Type id = Uml::ID::None);
50     virtual ~UMLWidget();
51 
52     // Copy constructor - not implemented.
53     // UMLWidget(const UMLWidget& other);
54 
55     UMLWidget& operator=(const UMLWidget& other);
56 
57     bool operator==(const UMLWidget& other) const;
58 
59     virtual QSizeF minimumSize() const;
60     void setMinimumSize(const QSizeF &size);
61 
62     virtual QSizeF maximumSize();
63     void setMaximumSize(const QSizeF &size);
64 
65     virtual void setUseFillColor(bool fc);
66     void setUseFillColorCmd(bool fc);
67 
68     virtual void setTextColor(const QColor &color);
69     void setTextColorCmd(const QColor &color);
70 
71     virtual void setLineColor(const QColor &color);
72     virtual void setLineColorCmd(const QColor &color);
73 
74     virtual void setLineWidth(uint width);
75     void setLineWidthCmd(uint width);
76 
77     virtual void setFillColor(const QColor &color);
78     void setFillColorCmd(const QColor &color);
79 
80     void setSelectedFlag(bool _select);
81     virtual void setSelected(bool _select);
82 
83     void setScene(UMLScene *scene);
84 
85     virtual bool activate(IDChangeLog* changeLog = 0);
86 
87     void setPenFromSettings(QPainter &p);
88     void setPenFromSettings(QPainter *p);
89 
90     virtual void setFont(const QFont &font);
91     void setFontCmd(const QFont &font);
92 
93     /**
94      * Returns whether we triggered the update of position movement.
95      * If so, you probably don't want to move it.
96      *
97      * @return The moving state.
98      */
getStartMove()99     bool getStartMove() const {
100         return m_startMove;
101     }
102 
103     virtual qreal getX() const;
104     virtual qreal getY() const;
105     virtual QPointF getPos() const;
106     virtual void setX(qreal x);
107     virtual void setY(qreal y);
108 
109     /**
110      * Returns the height of widget.
111      */
height()112     qreal height() const {
113         return rect().height();
114     }
115 
116     /**
117      * Returns the width of the widget.
118      */
width()119     qreal width() const {
120         return rect().width();
121     }
122 
123     void setSize(qreal width, qreal height);
124     void setSize(const QSizeF& size);
125 
126     virtual void resizeWidget(qreal newW, qreal newH);
127     virtual void notifyParentResize();
128 
129     bool getIgnoreSnapToGrid() const;
130     void setIgnoreSnapToGrid(bool to);
131 
132     void moveByLocal(qreal dx, qreal dy);
133 
134     virtual void removeAssoc(AssociationWidget* pAssoc);
135     virtual void addAssoc(AssociationWidget* pAssoc);
136 
137     AssociationWidgetList &associationWidgetList() const;
138 
139     /**
140      * Read property of bool m_isInstance
141      */
isInstance()142     bool isInstance() const {
143         return m_isInstance;
144     }
145 
146     /**
147      * Write property of bool m_isInstance
148      */
setIsInstance(bool isInstance)149     void setIsInstance(bool isInstance) {
150         m_isInstance = isInstance;
151     }
152 
153     /**
154      * Write property of m_instanceName
155      */
setInstanceName(const QString & instanceName)156     void setInstanceName(const QString &instanceName) {
157         m_instanceName = instanceName;
158     }
159 
160     /**
161      * Read property of m_instanceName
162      */
instanceName()163     QString instanceName() const {
164         return m_instanceName;
165     }
166 
167     Uml::ShowStereoType::Enum showStereotype() const;
168     virtual void setShowStereotype(Uml::ShowStereoType::Enum flag);
169     QString tags() const;
170 
171     virtual bool showPropertiesDialog();
172 
173     virtual void adjustAssocs(qreal dx, qreal dy);
174     virtual void adjustUnselectedAssocs(qreal dx, qreal dy);
175 
176     bool isActivated() const;
177     void setActivated(bool active = true);
178 
179     virtual void cleanup();
180 
181     void updateGeometry(bool withAssocs = true);
182 
183     void clipSize();
184 
185     void forceUpdateFontMetrics(QPainter *painter);
186     void forceUpdateFontMetrics(QFont &font, QPainter *painter);
187 
188     virtual bool loadFromXMI1(QDomElement &qElement);
189     virtual void saveToXMI1(QXmlStreamWriter& writer);
190 
191     QPointF startMovePosition() const;
192     void setStartMovePosition(const QPointF &position);
193 
194     QSizeF startResizeSize() const;
195 
196     virtual QSizeF calculateSize(bool withExtensions = true) const;
197     void resize();
198 
fixedAspectRatio()199     bool fixedAspectRatio() const {
200         return m_fixedAspectRatio;
201     }
202 
setFixedAspectRatio(bool state)203     void setFixedAspectRatio(bool state) {
204         m_fixedAspectRatio = state;
205     }
206 
resizable()207     bool resizable() const {
208         return m_resizable;
209     }
210 
setResizable(bool state)211     void setResizable(bool state) {
212         m_resizable = state;
213     }
214 
215     typedef enum {
216         FT_NORMAL = 0,
217         FT_BOLD  = 1,
218         FT_ITALIC = 2,
219         FT_UNDERLINE = 3,
220         FT_BOLD_ITALIC = 4,
221         FT_BOLD_UNDERLINE = 5,
222         FT_ITALIC_UNDERLINE = 6,
223         FT_BOLD_ITALIC_UNDERLINE = 7,
224         FT_INVALID = 8
225     } FontType;
226 
227     virtual void setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType);
228     virtual void setDefaultFontMetrics(QFont &font, UMLWidget::FontType fontType, QPainter &painter);
229 
230     QFontMetrics &getFontMetrics(UMLWidget::FontType fontType) const;
231     void setFontMetrics(UMLWidget::FontType fontType, QFontMetrics fm);
232     void setupFontType(QFont &font, UMLWidget::FontType fontType);
233 
234     virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
235 
236 public Q_SLOTS:
237     virtual void updateWidget();
238     virtual void slotMenuSelection(QAction* action);
239     virtual void slotWidgetMoved(Uml::ID::Type id);
240     virtual void slotFillColorChanged(Uml::ID::Type viewID);
241     virtual void slotLineColorChanged(Uml::ID::Type viewID);
242     virtual void slotTextColorChanged(Uml::ID::Type viewID);
243     virtual void slotLineWidthChanged(Uml::ID::Type viewID);
244 
245     void slotSnapToGrid();
246 
247 signals:
248     /**
249      * Emit when the widget moves its' position.
250      * @param id The id of the object behind the widget.
251      */
252     void sigWidgetMoved(Uml::ID::Type id);
253 
254 protected:
255     virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
256     virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
257     virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
258     virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
259     virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
260 
261     virtual void moveEvent(QGraphicsSceneMouseEvent *event);
262     virtual void moveWidgetBy(qreal diffX, qreal diffY);
263     virtual void constrainMovementForAllWidgets(qreal &diffX, qreal &diffY);
264     virtual void constrain(qreal& width, qreal& height);
265 
266     virtual bool isInResizeArea(QGraphicsSceneMouseEvent *me);
267     virtual QCursor resizeCursor() const;
268 
269     void selectSingle(QGraphicsSceneMouseEvent *me);
270     void selectMultiple(QGraphicsSceneMouseEvent *me);
271     void deselect(QGraphicsSceneMouseEvent *me);
272     // void resetSelection();
273 
274     void setSelectionBounds();
275 
276     void resize(QGraphicsSceneMouseEvent *me);
277 
278     bool wasSizeChanged();
279     bool wasPositionChanged();
280 
281     virtual void toForeground();
282 
283 public:
284     enum AddWidgetOption { NoOption = 0, SetupSize = 1, SwitchDirection = 2, ShowProperties = 4, Default = SetupSize | ShowProperties };
285     Q_DECLARE_FLAGS(AddWidgetOptions, AddWidgetOption)
286 
287 protected:
288     void addConnectedWidget(UMLWidget *widget, Uml::AssociationType::Enum type = Uml::AssociationType::Association, AddWidgetOptions options = Default);
289     void addConnectedUMLObject(UMLObject::ObjectType otype, Uml::AssociationType::Enum type);
290     void addWidget(UMLWidget *widget, bool showProperties = true);
291 
292     ///////////////// Data Loaded/Saved /////////////////////////////////
293 
294     QString m_instanceName;  ///< instance name (used if on a deployment diagram)
295     bool m_isInstance;       ///< holds whether this widget is a component instance (i.e. on a deployment diagram)
296     Uml::ShowStereoType::Enum m_showStereotype;   ///< if and how the stereotype should be displayed
297 
298     ///////////////// End of Data Loaded/Saved //////////////////////////
299 
300     bool           m_startMove;
301     QPointF        m_startMovePostion;
302     QSizeF         m_startResizeSize;
303     int            m_nPosX;
304     UMLDoc        *m_doc;  ///< shortcut for UMLApp::app()->document()
305     bool           m_resizable;
306     QFontMetrics  *m_pFontMetrics[FT_INVALID];
307     QSizeF         m_minimumSize;
308     QSizeF         m_maximumSize;
309 
310     /// true if the activate function has been called for this class instance
311     bool m_activated;
312 
313     /**
314      * Change Widget Behaviour
315      */
316     bool m_ignoreSnapToGrid;
317     bool m_ignoreSnapComponentSizeToGrid;
318     bool m_fixedAspectRatio;
319 
320     /// The text in the status bar when the cursor was pressed.
321     QString m_oldStatusBarMsg;
322 
323     /// The X/Y offset from the position of the cursor when it was pressed to the
324     /// upper left corner of the widget.
325     QPointF m_pressOffset;
326 
327     /// The X/Y position the widget had when the movement started.
328     QPointF m_oldPos;
329 
330     /// The width/height the widget had when the resize started.
331     qreal m_oldW, m_oldH;
332 
333     /// If shift or control button were pressed in mouse press event.
334     bool m_shiftPressed;
335 
336     /**
337      * If cursor was in move/resize area when left button was pressed (and no
338      * other widgets were selected).
339      */
340     bool m_inMoveArea, m_inResizeArea;
341 
342     /**
343      * If the widget was selected/moved/resized in the press and release cycle.
344      * Moved/resized is true if the widget was moved/resized even if the final
345      * position/size is the same as the starting one.
346      */
347     bool m_moved, m_resized;
348 
349 private:
350     void init();
351 
352     /// A list of AssociationWidgets between the UMLWidget and other UMLWidgets in the diagram
353     mutable AssociationWidgetList m_Assocs;
354 };
355 Q_DECLARE_OPERATORS_FOR_FLAGS(UMLWidget::AddWidgetOptions)
356 #endif
357