DISTRHO Plugin Framework
Widget.hpp
1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
6  * or without fee is hereby granted, provided that the above copyright notice and this
7  * permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef DGL_WIDGET_HPP_INCLUDED
18 #define DGL_WIDGET_HPP_INCLUDED
19 
20 #include "Geometry.hpp"
21 
22 START_NAMESPACE_DGL
23 
24 // --------------------------------------------------------------------------------------------------------------------
25 // Forward class names
26 
27 class Application;
28 class SubWidget;
29 class TopLevelWidget;
30 class Window;
31 
32 // --------------------------------------------------------------------------------------------------------------------
33 
34 /**
35  Base DGL Widget class.
36 
37  This is the base Widget class, from which all widgets are built.
38 
39  All widgets have a parent widget where they'll be drawn, this can be the top-level widget or a group widget.
40  This parent is never changed during a widget's lifetime.
41 
42  Widgets receive events in relative coordinates. (0, 0) means its top-left position.
43 
44  The top-level widget will draw subwidgets in the order they are constructed.
45  Early subwidgets are drawn first, at the bottom, then newer ones on top.
46  Events are sent in the inverse order so that the top-most widgets get
47  a chance to catch the event and stop its propagation.
48 
49  All widget event callbacks do nothing by default and onDisplay MUST be reimplemented by subclasses.
50 
51  @note It is not possible to subclass this Widget class directly, you must use SubWidget or TopLevelWidget instead.
52  */
53 class Widget
54 {
55 public:
56  /**
57  Base event data.
58  These are the fields present on all Widget events.
59  */
60  struct BaseEvent {
61  /** Currently active keyboard modifiers. @see Modifier */
62  uint mod;
63  /** Event flags. @see EventFlag */
64  uint flags;
65  /** Event timestamp (if any). */
66  uint time;
67 
68  /** Constructor for default/null values */
69  BaseEvent() noexcept : mod(0x0), flags(0x0), time(0) {}
70  /** Destuctor */
71  virtual ~BaseEvent() noexcept {}
72  };
73 
74  /**
75  Keyboard event.
76 
77  This event represents low-level key presses and releases.
78  This can be used for "direct" keyboard handing like key bindings, but must not be interpreted as text input.
79 
80  Keys are represented portably as Unicode code points, using the "natural" code point for the key.
81  The @a key field is the code for the pressed key, without any modifiers applied.
82  For example, a press or release of the 'A' key will have `key` 97 ('a')
83  regardless of whether shift or control are being held.
84 
85  Alternatively, the raw @a keycode can be used to work directly with physical keys,
86  but note that this value is not portable and differs between platforms and hardware.
87 
88  @see onKeyboard
89  */
91  /** True if the key was pressed, false if released. */
92  bool press;
93  /** Unicode point of the key pressed. */
94  uint key;
95  /** Raw keycode. */
96  uint keycode;
97 
98  /** Constructor for default/null values */
99  KeyboardEvent() noexcept
100  : BaseEvent(),
101  press(false),
102  key(0),
103  keycode(0) {}
104  };
105 
106  /**
107  Special keyboard event.
108 
109  DEPRECATED This used to be part of DPF due to pugl, but now deprecated and simply non-functional.
110  All events go through KeyboardEvent or CharacterInputEvent, use those instead.
111  */
112  struct DISTRHO_DEPRECATED_BY("KeyboardEvent") SpecialEvent : BaseEvent {
113  bool press;
114  Key key;
115 
116  /** Constructor for default/null values */
117  SpecialEvent() noexcept
118  : BaseEvent(),
119  press(false),
120  key(Key(0)) {}
121  };
122 
123  /**
124  Character input event.
125 
126  This event represents text input, usually as the result of a key press.
127  The text is given both as a Unicode character code and a UTF-8 string.
128 
129  Note that this event is generated by the platform's input system,
130  so there is not necessarily a direct correspondence between text events and physical key presses.
131  For example, with some input methods a sequence of several key presses will generate a single character.
132 
133  @see onCharacterInput
134  */
136  /** Raw key code. */
137  uint keycode;
138  /** Unicode character code. */
139  uint character;
140  /** UTF-8 string. */
141  char string[8];
142 
143  /** Constructor for default/null values */
145  : BaseEvent(),
146  keycode(0),
147  character(0),
148 #ifdef DISTRHO_PROPER_CPP11_SUPPORT
149  string{'\0','\0','\0','\0','\0','\0','\0','\0'} {}
150 #else
151  string() { std::memset(string, 0, sizeof(string)); }
152 #endif
153  };
154 
155  /**
156  Mouse press or release event.
157  @see onMouse
158  */
160  /** The button number starting from 1. @see MouseButton */
161  uint button;
162  /** True if the button was pressed, false if released. */
163  bool press;
164  /** The widget-relative coordinates of the pointer. */
166  /** The absolute coordinates of the pointer. */
168 
169  /** Constructor for default/null values */
170  MouseEvent() noexcept
171  : BaseEvent(),
172  button(0),
173  press(false),
174  pos(0.0, 0.0),
175  absolutePos(0.0, 0.0) {}
176  };
177 
178  /**
179  Mouse motion event.
180  @see onMotion
181  */
183  /** The widget-relative coordinates of the pointer. */
185  /** The absolute coordinates of the pointer. */
187 
188  /** Constructor for default/null values */
189  MotionEvent() noexcept
190  : BaseEvent(),
191  pos(0.0, 0.0),
192  absolutePos(0.0, 0.0) {}
193  };
194 
195  /**
196  Mouse scroll event.
197 
198  The scroll distance is expressed in "lines",
199  an arbitrary unit that corresponds to a single tick of a detented mouse wheel.
200  For example, `delta.y` = 1.0 scrolls 1 line up.
201  Some systems and devices support finer resolution and/or higher values for fast scrolls,
202  so programs should handle any value gracefully.
203 
204  @see onScroll
205  */
207  /** The widget-relative coordinates of the pointer. */
209  /** The absolute coordinates of the pointer. */
211  /** The scroll distance. */
213  /** The direction of the scroll or "smooth". */
214  ScrollDirection direction;
215 
216  /** Constructor for default/null values */
217  ScrollEvent() noexcept
218  : BaseEvent(),
219  pos(0.0, 0.0),
220  absolutePos(0.0, 0.0),
221  delta(0.0, 0.0),
222  direction(kScrollSmooth) {}
223  };
224 
225  /**
226  Resize event.
227  @see onResize
228  */
229  struct ResizeEvent {
230  /** The new widget size. */
232  /** The previous size, can be null. */
234 
235  /** Constructor for default/null values */
236  ResizeEvent() noexcept
237  : size(0, 0),
238  oldSize(0, 0) {}
239  };
240 
241  /**
242  Widget position changed event.
243  @see onPositionChanged
244  */
246  /** The new absolute position of the widget. */
248  /** The previous absolute position of the widget. */
250 
251  /** Constructor for default/null values */
253  : pos(0, 0),
254  oldPos(0, 0) {}
255  };
256 
257 private:
258  /**
259  Private constructor, reserved for TopLevelWidget class.
260  */
261  explicit Widget(TopLevelWidget* topLevelWidget);
262 
263  /**
264  Private constructor, reserved for SubWidget class.
265  */
266  explicit Widget(Widget* widgetToGroupTo);
267 
268 public:
269  /**
270  Destructor.
271  */
272  virtual ~Widget();
273 
274  /**
275  Check if this widget is visible within its parent window.
276  Invisible widgets do not receive events except resize.
277  */
278  bool isVisible() const noexcept;
279 
280  /**
281  Set widget visible (or not) according to @a visible.
282  */
283  void setVisible(bool visible);
284 
285  /**
286  Show widget.
287  This is the same as calling setVisible(true).
288  */
289  void show();
290 
291  /**
292  Hide widget.
293  This is the same as calling setVisible(false).
294  */
295  void hide();
296 
297  /**
298  Get width.
299  */
300  uint getWidth() const noexcept;
301 
302  /**
303  Get height.
304  */
305  uint getHeight() const noexcept;
306 
307  /**
308  Get size.
309  */
310  const Size<uint> getSize() const noexcept;
311 
312  /**
313  Set width.
314  */
315  void setWidth(uint width) noexcept;
316 
317  /**
318  Set height.
319  */
320  void setHeight(uint height) noexcept;
321 
322  /**
323  Set size using @a width and @a height values.
324  */
325  void setSize(uint width, uint height) noexcept;
326 
327  /**
328  Set size.
329  */
330  void setSize(const Size<uint>& size) noexcept;
331 
332  /**
333  Get the Id associated with this widget.
334  @see setId
335  */
336  uint getId() const noexcept;
337 
338  /**
339  Set an Id to be associated with this widget.
340  @see getId
341  */
342  void setId(uint id) noexcept;
343 
344  /**
345  Get the application associated with this widget's window.
346  This is the same as calling `getTopLevelWidget()->getApp()`.
347  */
348  Application& getApp() const noexcept;
349 
350  /**
351  Get the window associated with this widget.
352  This is the same as calling `getTopLevelWidget()->getWindow()`.
353  */
354  Window& getWindow() const noexcept;
355 
356  /**
357  Get the graphics context associated with this widget's window.
358  GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable,
359  for example GraphicsContext.
360  @see CairoSubWidget, CairoTopLevelWidget
361  */
362  const GraphicsContext& getGraphicsContext() const noexcept;
363 
364  /**
365  Get top-level widget, as passed directly in the constructor
366  or going up the chain of group widgets until it finds the top-level one.
367  */
369 
370  /**
371  Request repaint of this widget's area to the window this widget belongs to.
372  On the raw Widget class this function does nothing.
373  */
374  virtual void repaint() noexcept;
375 
376  DISTRHO_DEPRECATED_BY("getApp()")
377  Application& getParentApp() const noexcept { return getApp(); }
378 
379  DISTRHO_DEPRECATED_BY("getWindow()")
380  Window& getParentWindow() const noexcept { return getWindow(); }
381 
382 protected:
383  /**
384  A function called to draw the widget contents.
385  */
386  virtual void onDisplay() = 0;
387 
388  /**
389  A function called when a key is pressed or released.
390  @return True to stop event propagation, false otherwise.
391  */
392  virtual bool onKeyboard(const KeyboardEvent&);
393 
394  /**
395  A function called when an UTF-8 character is received.
396  @return True to stop event propagation, false otherwise.
397  */
398  virtual bool onCharacterInput(const CharacterInputEvent&);
399 
400  /**
401  A function called when a mouse button is pressed or released.
402  @return True to stop event propagation, false otherwise.
403  */
404  virtual bool onMouse(const MouseEvent&);
405 
406  /**
407  A function called when the pointer moves.
408  @return True to stop event propagation, false otherwise.
409  */
410  virtual bool onMotion(const MotionEvent&);
411 
412  /**
413  A function called on scrolling (e.g. mouse wheel or track pad).
414  @return True to stop event propagation, false otherwise.
415  */
416  virtual bool onScroll(const ScrollEvent&);
417 
418  /**
419  A function called when the widget is resized.
420  */
421  virtual void onResize(const ResizeEvent&);
422 
423  /**
424  A function called when a special key is pressed or released.
425  DEPRECATED use onKeyboard or onCharacterInput
426  */
427 #if defined(__clang__)
428 # pragma clang diagnostic push
429 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
430 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460
431 # pragma GCC diagnostic push
432 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
433 #endif
434  virtual bool onSpecial(const SpecialEvent&) { return false; }
435 #if defined(__clang__)
436 # pragma clang diagnostic pop
437 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460
438 # pragma GCC diagnostic pop
439 #endif
440 
441 private:
442  struct PrivateData;
443  PrivateData* const pData;
444  friend class SubWidget;
445  friend class TopLevelWidget;
446 
447  DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget)
448 };
449 
450 // --------------------------------------------------------------------------------------------------------------------
451 
452 END_NAMESPACE_DGL
453 
454 #endif // DGL_WIDGET_HPP_INCLUDED
Definition: Application.hpp:43
Definition: SubWidget.hpp:40
Definition: TopLevelWidget.hpp:47
Definition: Widget.hpp:54
virtual bool onMouse(const MouseEvent &)
virtual bool onScroll(const ScrollEvent &)
Window & getWindow() const noexcept
uint getWidth() const noexcept
bool isVisible() const noexcept
void show()
Application & getApp() const noexcept
virtual bool onSpecial(const SpecialEvent &)
Definition: Widget.hpp:434
uint getId() const noexcept
void hide()
TopLevelWidget * getTopLevelWidget() const noexcept
virtual bool onMotion(const MotionEvent &)
void setVisible(bool visible)
virtual ~Widget()
const Size< uint > getSize() const noexcept
virtual bool onKeyboard(const KeyboardEvent &)
uint getHeight() const noexcept
void setSize(uint width, uint height) noexcept
virtual void repaint() noexcept
void setId(uint id) noexcept
void setHeight(uint height) noexcept
virtual void onResize(const ResizeEvent &)
virtual bool onCharacterInput(const CharacterInputEvent &)
virtual void onDisplay()=0
const GraphicsContext & getGraphicsContext() const noexcept
void setWidth(uint width) noexcept
Definition: Window.hpp:63
Definition: Base.hpp:212
Definition: Widget.hpp:60
BaseEvent() noexcept
Definition: Widget.hpp:69
uint mod
Definition: Widget.hpp:62
uint time
Definition: Widget.hpp:66
virtual ~BaseEvent() noexcept
Definition: Widget.hpp:71
uint flags
Definition: Widget.hpp:64
Definition: Widget.hpp:135
char string[8]
Definition: Widget.hpp:141
uint character
Definition: Widget.hpp:139
CharacterInputEvent() noexcept
Definition: Widget.hpp:144
uint keycode
Definition: Widget.hpp:137
Definition: Widget.hpp:90
uint keycode
Definition: Widget.hpp:96
uint key
Definition: Widget.hpp:94
KeyboardEvent() noexcept
Definition: Widget.hpp:99
bool press
Definition: Widget.hpp:92
Definition: Widget.hpp:182
MotionEvent() noexcept
Definition: Widget.hpp:189
Point< double > pos
Definition: Widget.hpp:184
Point< double > absolutePos
Definition: Widget.hpp:186
Definition: Widget.hpp:159
Point< double > pos
Definition: Widget.hpp:165
MouseEvent() noexcept
Definition: Widget.hpp:170
uint button
Definition: Widget.hpp:161
bool press
Definition: Widget.hpp:163
Point< double > absolutePos
Definition: Widget.hpp:167
Definition: Widget.hpp:245
PositionChangedEvent() noexcept
Definition: Widget.hpp:252
Point< int > oldPos
Definition: Widget.hpp:249
Point< int > pos
Definition: Widget.hpp:247
Definition: Widget.hpp:229
Size< uint > size
Definition: Widget.hpp:231
Size< uint > oldSize
Definition: Widget.hpp:233
ResizeEvent() noexcept
Definition: Widget.hpp:236
Definition: Widget.hpp:206
Point< double > delta
Definition: Widget.hpp:212
Point< double > absolutePos
Definition: Widget.hpp:210
ScrollDirection direction
Definition: Widget.hpp:214
ScrollEvent() noexcept
Definition: Widget.hpp:217
Point< double > pos
Definition: Widget.hpp:208