summaryrefslogtreecommitdiffstats
path: root/umbrello/umbrello/toolbarstate.h
blob: e005c02169f51d86b975049b3b92a72ee08c5d4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   copyright (C) 2004-2006                                               *
 *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
 ***************************************************************************/

#ifndef TOOLBARSTATE_H
#define TOOLBARSTATE_H

#include <qevent.h>
#include <qobject.h>

class QEvent;
class QMouseEvent;

class AssociationWidget;
class MessageWidget;
class UMLView;
class UMLWidget;


/**
 * Base class for toolbar states.
 * All toolbar states inherit directly or indirectly from this class. Toolbar
 * states represent tools that work with the diagram (for example, to create
 * widgets, make associations...). All the mouse events received in the diagram
 * are delivered to the toolbar state currently active. The events are handled
 * in the tool and it executes the needed actions.
 *
 * All the mouse event handlers can be overridden in subclasses. However, the
 * behaviour of the main handlers shouldn't be modified (apart from extend it,
 * that is, call the base implementation before any other actions in the derived
 * method).
 *
 * In order to handle the events, each main handler has three protected
 * "sub-handlers" named like the main handler with the suffixes "Association",
 * "Wdiget" and "Empty". The events received in the main handlers are delivered
 * to the suitable handler, depending on if the event happened on an association,
 * on a widget or on an empty space of the diagram. Those methods are the ones to
 * override or extend to specify the behaviour of the toolbar state.
 *
 * The mouse events received in main handlers are tweaked to use the inverse
 * position. The modified event is saved in m_pMouseEvent. This is the event that
 * must be used everywhere.
 *
 * The association or widget that will receive the events is set in press event.
 * How they are set can be tweaked in subclasses overriding setCurrentElement().
 * Once a press event happens, all the mouse events and the release event are sent
 * to the same widget or association. Mouse events are delivered only when mouse
 * tracking is enabled. It is enabled in press event, and disabled in release
 * event. Also, it is disabled in the toolbar state initialization. Additionally,
 * it can be enabled or disabled in other situations by subclasses if needed.
 *
 * After handling a release event, the tool is changed if needed. Default
 * implementation sets the default tool if the button released was the right
 * button. Subclasses can override this behaviour if needed.
 *
 * When a toolbar state is selected, method init is called to revert its state
 * to the initial. Subclasses should extend that method as needed. Also, method
 * cleanBeforeChange() is called before changing it to the new tool. Subclasses
 * should extend that method as needed.
 *
 * @todo Handle, for example, left press, right press, left release, right
 *       release and other similar strange combinations?
 */
class ToolBarState: public QObject {
    Q_OBJECT
public:

    /**
     * Destroys this ToolBarState.
     * Frees m_pMouseEvent.
     */
    virtual ~ToolBarState();

    /**
     * Goes back to the initial state.
     * Subclasses can extend, but not override, this method as needed.
     */
    virtual void init();

    /**
     * Called when the current tool is changed to use another tool.
     * Subclasses can extend, but not override, this method as needed.
     * Default implementation does nothing.
     */
    virtual void cleanBeforeChange();

    /**
     * Handler for mouse press events.
     * Mouse tracking is enabled, any pop up menu removed, the position of the
     * cursor set and paste state disabled.
     * Then, the current association or widget are set (if any), and events are
     * delivered to the specific methods, depending on where the cursor was
     * pressed.
     *
     * @param ome The received event.
     * @see setCurrentElement()
     */
    virtual void mousePress(QMouseEvent *ome);

    /**
     * Handler for mouse release events.
     * Mouse tracking is disabled and the position of the cursor set.
     * The events are delivered to the specific methods, depending on where the
     * cursor was released, and the current association or widget cleaned.
     * Finally, the current tool is changed if needed.
     *
     * @param ome The received event.
     */
    virtual void mouseRelease(QMouseEvent* ome);

    /**
     * Handler for mouse double click events.
     * The current association or widget is set (if any), and events are
     * delivered to the specific methods, depending on where the cursor was pressed.
     * After delivering the events, the current association or widget is cleaned.
     *
     * @param ome The received event.
     */
    virtual void mouseDoubleClick(QMouseEvent* ome);

    /**
     * Handler for mouse double click events.
     * Events are delivered to the specific methods, depending on where the cursor
     * was pressed. It uses the current widget or association set in press event,
     * if any.
     * Then, the view is scrolled if needed (if the cursor is moved in any of the
     * 30 pixels width area from left, top, right or bottom sides, and there is
     * more diagram currently not being shown in that direction).
     * This method is only called when mouse tracking is enabled and the mouse
     * is moved.
     *
     * @param ome The received event.
     */
    virtual void mouseMove(QMouseEvent* ome);

public slots:

    /**
     * An association was removed from the UMLView.
     * If the association removed was the current association, the current
     * association is set to 0.
     * It can be extended in subclasses if needed.
     */
    virtual void slotAssociationRemoved(AssociationWidget* association);

    /**
     * A widget was removed from the UMLView.
     * If the widget removed was the current widget, the current widget is set
     * to 0.
     * It can be extended in subclasses if needed.
     */
    virtual void slotWidgetRemoved(UMLWidget* widget);

protected:

    /**
     * Creates a new ToolBarState.
     * UMLView is set as parent of this QObject, and name is left empty.
     * Protected to avoid classes other than derived to create objects of this
     * class.
     *
     * @param umlView The UMLView to use.
     */
    ToolBarState(UMLView *umlView);

    /**
     * Sets the current association or widget.
     * It sets the current element when a press event happened. The element will
     * be used until the next release event.
     * Default implementation first checks for associations, then message widgets
     * and then any other widgets.
     * It can be overridden in subclasses if needed.
     */
    virtual void setCurrentElement();

    /**
     * Called when the press event happened on an association.
     * Default implementation does nothing.
     */
    virtual void mousePressAssociation();

    /**
     * Called when the press event happened on a widget.
     * Default implementation does nothing.
     */
    virtual void mousePressWidget();

    /**
     * Called when the press event happened on an empty space.
     * Default implementation cleans the selection.
     */
    virtual void mousePressEmpty();

    /**
     * Called when the release event happened on an association.
     * Default implementation does nothing.
     */
    virtual void mouseReleaseAssociation();

    /**
     * Called when the release event happened on a widget.
     * Default implementation does nothing.
     */
    virtual void mouseReleaseWidget();

    /**
     * Called when the release event happened on an empty space.
     * Default implementation does nothing.
     */
    virtual void mouseReleaseEmpty();

    /**
     * Called when the double click event happened on an association.
     * Default implementation does nothing.
     */
    virtual void mouseDoubleClickAssociation();

    /**
     * Called when the double click event happened on a widget.
     * Default implementation does nothing.
     */
    virtual void mouseDoubleClickWidget();

    /**
     * Called when the double click event happened on an empty space.
     * Default implementation cleans the selection.
     */
    virtual void mouseDoubleClickEmpty();

    /**
     * Called when the move event happened when an association is
     * currently available.
     * Default implementation does nothing.
     */
    virtual void mouseMoveAssociation();

    /**
     * Called when the move event happened when a widget is
     * currently available.
     * Default implementation does nothing.
     */
    virtual void mouseMoveWidget();

    /**
     * Called when the move event happened when no association nor
     * widget are currently available.
     * Default implementation does nothing.
     */
    virtual void mouseMoveEmpty();

    /**
     * Changes the current tool to the default one if the right button was released.
     * It can be overridden in subclasses if needed.
     */
    virtual void changeTool();

    /**
     * Returns the widget currently in use.
     *
     * @return The widget currently in use.
     */
    virtual UMLWidget* getCurrentWidget() {
        return m_currentWidget;
    }

    /**
     * Sets the widget currently in use.
     * This method is called in main press events handler just before calling
     * the press event for widgets handler.
     * Default implementation is set the specified widget, although this
     * behaviour can be overridden in subclasses if needed.
     *
     * @param currentWidget The widget to be set.
     */
    virtual void setCurrentWidget(UMLWidget* currentWidget) {
        m_currentWidget = currentWidget;
    }

    /**
     * Returns the association currently in use.
     *
     * @return The association currently in use.
     */
    virtual AssociationWidget* getCurrentAssociation() {
        return m_currentAssociation;
    }

    /**
     * Sets the association currently in use.
     * This method is called in main press events handler just before calling
     * the press event for associations handler.
     * Default implementation is set the specified association, although this
     * behaviour can be overridden in subclasses if needed.
     *
     * @param currentAssociation The association to be set.
     */
    virtual void setCurrentAssociation(AssociationWidget* currentAssociation) {
        m_currentAssociation = currentAssociation;
    }

    /**
     * Sets m_pMouseEvent as the equivalent of the received event after transforming it
     * using the inverse world matrix in the UMLView.
     * This method is called at the beginning of the main event handler methods.
     *
     * @param ome The mouse event to transform.
     * @param type The type of the event.
     */
    void setMouseEvent(QMouseEvent* ome, const QEvent::Type &type);

    /**
     * Returns the AssociationWidget at the specified position, or null if there is none.
     * If there are more than one association at this point, it returns the first found.
     *
     * @param pos The position to get the association.
     * @return The AssociationWidget at the specified position, or null if there is none.
     * @todo Better handling for associations at the same point
     */
    AssociationWidget* getAssociationAt(const QPoint& pos);

    /**
     * Returns the MessageWidget at the specified position, or null if there is none.
     * The message is only returned if it is visible.
     * If there are more than one message at this point, it returns the first found.
     *
     * @param pos The position to get the message.
     * @return The MessageWidget at the specified position, or null if there is none.
     * @todo Better handling for messages at the same point
     */
    MessageWidget* getMessageAt(const QPoint& pos);

    /**
     * The UMLView.
     */
    UMLView* m_pUMLView;

    /**
     * The mouse event currently in use.
     * This event is the equivalent of the received event after transforming it
     * using the inverse world matrix in the UMLView.
     */
    QMouseEvent* m_pMouseEvent;

private:

    /**
     * The widget currently in use, if any.
     */
    UMLWidget* m_currentWidget;

    /**
     * The association currently in use, if any.
     */
    AssociationWidget* m_currentAssociation;

};

#endif //TOOLBARSTATE_H