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