1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4  *
5  * See the LICENSE file for terms of use.
6  */
7 #ifndef WINTERACT_WIDGET_H_
8 #define WINTERACT_WIDGET_H_
9 
10 #include <Wt/WWebWidget.h>
11 #include <Wt/WEvent.h>
12 
13 namespace Wt {
14 
15 class JSlot;
16 
17 /*! \class WInteractWidget Wt/WInteractWidget.h Wt/WInteractWidget.h
18  *  \brief An abstract widget that can receive user-interface interaction
19  *
20  * This abstract widget provides access to event signals that
21  * correspond to user-interface interaction through mouse or keyboard.
22  *
23  * When JavaScript is disabled, only the clicked() event will
24  * propagate (but without event details information).
25  *
26  * <h3>CSS</h3>
27  *
28  * Styling through CSS is not applicable.
29  */
30 class WT_API WInteractWidget : public WWebWidget
31 {
32 public:
33   /*! \brief Create an InteractWidget.
34    */
35   WInteractWidget();
36 
37   ~WInteractWidget();
38 
39   /*! \brief Event signal emitted when a keyboard key is pushed down.
40    *
41    * The keyWentDown signal is the first signal emitted when a key is
42    * pressed (before the keyPressed signal). Unlike keyPressed()
43    * however it is also emitted for modifier keys (such as "shift",
44    * "control", ...) or keyboard navigation keys that do not have a
45    * corresponding character.
46    *
47    * Form widgets (like WLineEdit) will receive key events when
48    * focussed. Other widgets will receive key events when they contain
49    * (directly or indirectly) a form widget that has focus.
50    *
51    * To capture a key down event when no element has focus, see
52    * WApplication::globalKeyWentDown()
53    *
54    * \sa keyPressed(), keyWentUp()
55    */
56   EventSignal<WKeyEvent>& keyWentDown();
57 
58   /*! \brief Event signal emitted when a "character" was entered.
59    *
60    * The keyPressed signal is emitted when a key is pressed, and a
61    * character is entered. Unlike keyWentDown(), it is emitted only
62    * for key presses that result in a character being entered, and
63    * thus not for modifier keys or keyboard navigation keys.
64    *
65    * Form widgets (like WLineEdit) will receive key events when
66    * focussed. Other widgets will receive key events when they contain
67    * (directly or indirectly) a form widget that has focus.
68    *
69    * To capture a key press when no element has focus, see
70    * WApplication::globalKeyPressed()
71    *
72    * \sa keyWentDown()
73    */
74   EventSignal<WKeyEvent>& keyPressed();
75 
76   /*! \brief Event signal emitted when a keyboard key is released.
77    *
78    * This is the counter-part of the keyWentDown() event. Every
79    * key-down has its corresponding key-up.
80    *
81    * Form widgets (like WLineEdit) will receive key events when
82    * focussed. Other widgets will receive key events when they contain
83    * (directly or indirectly) a form widget that has focus.
84    *
85    * To capture a key up event when no element has focus, see
86    * WApplication::globalKeyWentUp()
87    *
88    * \sa keyWentDown()
89    */
90   EventSignal<WKeyEvent>& keyWentUp();
91 
92   /*! \brief Event signal emitted when enter was pressed.
93    *
94    * This signal is emitted when the Enter or Return key was pressed.
95    *
96    * Form widgets (like WLineEdit) will receive key events when
97    * focussed. Other widgets will receive key events when they contain
98    * (directly or indirectly) a form widget that has focus.
99    *
100    * To capture an enter press when no element has focus, see
101    * WApplication::globalEnterPressed()
102    *
103    * \sa keyPressed(), Key::Enter
104    */
105   EventSignal<>& enterPressed();
106 
107   /*! \brief Event signal emitted when escape was pressed.
108    *
109    * This signal is emitted when the Escape key was pressed.
110    *
111    * Form widgets (like WLineEdit) will receive key events when
112    * focussed. Other widgets will receive key events when they contain
113    * (directly or indirectly) a form widget that has focus.
114    *
115    * To capture an escape press when no element has focus, see
116    * WApplication::globalEscapePressed()
117    *
118    * \sa keyPressed(), Key::Escape
119    */
120   EventSignal<>& escapePressed();
121 
122   /*! \brief Event signal emitted when the primary mouse button was clicked on this
123    *         widget.
124    *
125    * The event details contains information such as the \link
126    * WMouseEvent::button button\endlink, optional \link
127    * WMouseEvent::modifiers() keyboard modifiers\endlink, and mouse
128    * coordinates relative to the \link WMouseEvent::widget()
129    * widget\endlink, the window \link WMouseEvent::window()
130    * window\endlink, or the \link WMouseEvent::document()
131    * document\endlink.
132    *
133    * For more details, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event).
134    *
135    * \note When JavaScript is disabled, the event details contain
136    * invalid information.
137    */
138   EventSignal<WMouseEvent>& clicked();
139 
140   /*! \brief Event signal emitted when the primary mouse button was double clicked
141    *         on this widget.
142    *
143    * The event details contains information such as the \link
144    * WMouseEvent::button button\endlink, optional \link
145    * WMouseEvent::modifiers() keyboard modifiers\endlink, and mouse
146    * coordinates relative to the \link WMouseEvent::widget()
147    * widget\endlink, the window \link WMouseEvent::window()
148    * window\endlink, or the \link WMouseEvent::document()
149    * document\endlink.
150    *
151    * For more details, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event).
152    *
153    * \note When JavaScript is disabled, the signal will never fire.
154    */
155   EventSignal<WMouseEvent>& doubleClicked();
156 
157   /*! \brief Event signal emitted when a mouse button was pushed down on this
158    *         widget.
159    *
160    * The event details contains information such as the \link
161    * WMouseEvent::button button\endlink, optional \link
162    * WMouseEvent::modifiers() keyboard modifiers\endlink, and mouse
163    * coordinates relative to the \link WMouseEvent::widget()
164    * widget\endlink, the window \link WMouseEvent::window()
165    * window\endlink, or the \link WMouseEvent::document()
166    * document\endlink.
167    *
168    * \note When JavaScript is disabled, the signal will never fire.
169    */
170   EventSignal<WMouseEvent>& mouseWentDown();
171 
172   /*! \brief Event signal emitted when a mouse button was released on this
173    *         widget.
174    *
175    * The event details contains information such as the \link
176    * WMouseEvent::button button\endlink, optional \link
177    * WMouseEvent::modifiers() keyboard modifiers\endlink, and mouse
178    * coordinates relative to the \link WMouseEvent::widget()
179    * widget\endlink, the window \link WMouseEvent::window()
180    * window\endlink, or the \link WMouseEvent::document()
181    * document\endlink.
182    *
183    * If you connect also the mouseWentDown() signal, then a subsequent
184    * mouseWentUp() will be received by the same widget, even if mouse is
185    * no longer over the original widget.
186    *
187    * \note When JavaScript is disabled, the signal will never fire.
188    */
189   EventSignal<WMouseEvent>& mouseWentUp();
190 
191   /*! \brief Event signal emitted when the mouse went out of this widget.
192    *
193    * \note When JavaScript is disabled, the signal will never fire.
194    */
195   EventSignal<WMouseEvent>& mouseWentOut();
196 
197   /*! \brief Event signal emitted when the mouse entered this widget.
198    *
199    * The signal is emitted as soon as the mouse enters the widget, or
200    * after some delay as configured by setMouseOverDelay()
201    *
202    * \note When JavaScript is disabled, the signal will never fire.
203    */
204   EventSignal<WMouseEvent>& mouseWentOver();
205 
206   /*! \brief Event signal emitted when the mouse moved over this widget.
207    *
208    * The mouse event contains information on the button(s) currently
209    * pressed. If multiple buttons are currently pressed, only the
210    * button with smallest enum value is returned.
211    *
212    * \note When JavaScript is disabled, the signal will never fire.
213    */
214   EventSignal<WMouseEvent>& mouseMoved();
215 
216   /*! \brief Event signal emitted when the mouse is dragged over this widget.
217    *
218    * The mouse event contains information on the button(s) currently
219    * pressed. If multiple buttons are currently pressed, only the
220    * button with smallest enum value is returned.
221    *
222    * \note When JavaScript is disabled, the signal will never fire.
223    */
224   EventSignal<WMouseEvent>& mouseDragged();
225 
226   /*! \brief Event signal emitted when the mouse scroll wheel was used.
227    *
228    * The event details contains information such as the \link
229    * WMouseEvent::wheelDelta() wheel delta\endlink, optional \link
230    * WMouseEvent::modifiers() keyboard modifiers\endlink, and mouse
231    * coordinates relative to the \link WMouseEvent::widget()
232    * widget\endlink, the window \link WMouseEvent::window()
233    * window\endlink, or the \link WMouseEvent::document()
234    * document\endlink.
235    *
236    * \note When JavaScript is disabled, the signal will never fire.
237    */
238   EventSignal<WMouseEvent>& mouseWheel();
239 
240   /*! \brief Event signal emitted when a finger is placed on the screen.
241    *
242    * The event details contains information such as the \link
243    * WTouchEvent::touches() touches\endlink, \link WTouchEvent::targetTouches()
244    * target touches\endlink and \link WTouchEvent::changedTouches() changed
245    * touches\endlink.
246    *
247    * \note When JavaScript is disabled, the signal will never fire.
248    */
249   EventSignal<WTouchEvent>& touchStarted();
250 
251   /*! \brief Event signal emitted when a finger is removed from the screen.
252    *
253    * The event details contains information such as the \link
254    * WTouchEvent::touches() touches\endlink, \link WTouchEvent::targetTouches()
255    * target touches\endlink and \link WTouchEvent::changedTouches() changed
256    * touches\endlink.
257    *
258    * \note When JavaScript is disabled, the signal will never fire.
259    */
260   EventSignal<WTouchEvent>& touchEnded();
261 
262   /*! \brief Event signal emitted when a finger, which is already placed on the
263    *         screen, is moved across the screen.
264    *
265    * The event details contains information such as the \link
266    * WTouchEvent::touches() touches\endlink, \link WTouchEvent::targetTouches()
267    * target touches\endlink and \link WTouchEvent::changedTouches() changed
268    * touches\endlink.
269    *
270    * \note When JavaScript is disabled, the signal will never fire.
271    */
272   EventSignal<WTouchEvent>& touchMoved();
273 
274   /*! \brief Event signal emitted when a gesture is started.
275    *
276    * The event details contains information about the \link
277    * WGestureEvent::scale() scale\endlink and the \link
278    * WGestureEvent::rotation() rotation\endlink.
279    *
280    * \note When JavaScript is disabled, the signal will never fire.
281    */
282   EventSignal<WGestureEvent>& gestureStarted();
283 
284   /*! \brief Event signal emitted when a gesture is changed.
285    *
286    * The event details contains information about the \link
287    * WGestureEvent::scale() scale\endlink and the \link
288    * WGestureEvent::rotation() rotation\endlink.
289    *
290    * \note When JavaScript is disabled, the signal will never fire.
291    */
292   EventSignal<WGestureEvent>& gestureChanged();
293 
294   /*! \brief Event signal emitted when a gesture is ended.
295    *
296    * The event details contains information about the \link
297    * WGestureEvent::scale() scale\endlink and the \link
298    * WGestureEvent::rotation() rotation\endlink.
299    *
300    * \note When JavaScript is disabled, the signal will never fire.
301    */
302   EventSignal<WGestureEvent>& gestureEnded();
303 
304   /*! \brief Configure dragging for drag and drop.
305    *
306    * Enable drag&drop for this widget. The mimeType is used to find a
307    * suitable drop target, which must accept dropping of this mimetype.
308    *
309    * By default, the entire widget is dragged. One may specify another
310    * widget to be dragged (for example the parent as \p dragWidget) or
311    * a \p dragWidget whose function is only to represent the drag
312    * visually (when \p isDragWidgetOnly = \c true).
313    *
314    * The widget to be identified as source in the dropEvent may be given
315    * explicitly, and will default to this widget otherwise.
316    *
317    * When using a touch interface, the widget can also be dragged after
318    * a long press.
319    *
320    * \note When JavaScript is disabled, drag&drop does not work.
321    *
322    * \sa WWidget::dropEvent(), WWidget::acceptDrops(), WDropEvent
323    */
324   void setDraggable(const std::string& mimeType,
325 		    WWidget *dragWidget = nullptr,
326 		    bool isDragWidgetOnly = false,
327 		    WObject *sourceWidget = nullptr);
328 
329   /*! \brief Disable drag & drop for this widget.
330    *
331    * \sa setDraggable()
332    */
333   void unsetDraggable();
334 
335   /*! \brief Sets a delay for the mouse over event.
336    *
337    * This sets a delay (in milliseconds) before the mouse over event
338    * is emitted.
339    *
340    * The default value is 0.
341    *
342    * \sa mouseWentOver()
343    */
344   void setMouseOverDelay(int delay);
345 
346   /*! \brief Returns the mouse over signal delay.
347    *
348    * \sa setMouseOverDelay()
349    */
350   int mouseOverDelay() const;
351 
352   virtual void setPopup(bool popup) override;
353   virtual void load() override;
354   virtual bool isEnabled() const override;
355 
356 protected:
357   virtual void updateDom(DomElement& element, bool all) override;
358   virtual void propagateRenderOk(bool deep) override;
359   virtual void propagateSetEnabled(bool enabled) override;
360 
361   void updateEventSignals(DomElement& element, bool all);
362 
363   std::unique_ptr<JSlot> dragSlot_;
364   std::unique_ptr<JSlot> dragTouchSlot_;
365   std::unique_ptr<JSlot> dragTouchEndSlot_;
366 
367 protected:
368   // also used in WAbstractToggleButton
369   static const char *M_CLICK_SIGNAL;
370 
371 private:
372   static const char *CLICK_SIGNAL;
373   static const char *KEYDOWN_SIGNAL;
374   static const char *KEYPRESS_SIGNAL;
375   static const char *KEYUP_SIGNAL;
376   static const char *ENTER_PRESS_SIGNAL;
377   static const char *ESCAPE_PRESS_SIGNAL;
378   static const char *DBL_CLICK_SIGNAL;
379   static const char *MOUSE_DOWN_SIGNAL;
380   static const char *MOUSE_UP_SIGNAL;
381   static const char *MOUSE_OUT_SIGNAL;
382   static const char *MOUSE_OVER_SIGNAL;
383   static const char *MOUSE_MOVE_SIGNAL;
384   static const char *MOUSE_DRAG_SIGNAL;
385   static const char *MOUSE_WHEEL_SIGNAL;
386   static const char *WHEEL_SIGNAL;
387   static const char *TOUCH_START_SIGNAL;
388   static const char *TOUCH_MOVE_SIGNAL;
389   static const char *TOUCH_END_SIGNAL;
390   static const char *GESTURE_START_SIGNAL;
391   static const char *GESTURE_CHANGE_SIGNAL;
392   static const char *GESTURE_END_SIGNAL;
393   static const char *DRAGSTART_SIGNAL;
394 
395   friend class DomElement;
396   friend class WAbstractToggleButton;
397   friend class WWebWidget;
398 
399   int mouseOverDelay_;
400 };
401 
402 }
403 
404 #endif // WINTERACT_WIDGET_H_
405