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