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  string{'\0','\0','\0','\0','\0','\0','\0','\0'} {}
154  };
155 
156  /**
157  Mouse press or release event.
158 
159  @a button The button number starting from 1 (1 = left, 2 = middle, 3 = right).
160  @a press True if the button was pressed, false if released.
161  @a pos The widget-relative coordinates of the pointer.
162  @a absolutePos The absolute coordinates of the pointer.
163  @see onMouse
164  */
166  uint button;
167  bool press;
168  Point<double> pos;
169  Point<double> absolutePos;
170 
171  /** Constructor */
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 
183  @a pos The widget-relative coordinates of the pointer.
184  @a absolutePos The absolute coordinates of the pointer.
185  @see onMotion
186  */
188  Point<double> pos;
189  Point<double> absolutePos;
190 
191  /** Constructor */
192  MotionEvent() noexcept
193  : BaseEvent(),
194  pos(0.0, 0.0),
195  absolutePos(0.0, 0.0) {}
196  };
197 
198  /**
199  Mouse scroll event.
200 
201  The scroll distance is expressed in "lines",
202  an arbitrary unit that corresponds to a single tick of a detented mouse wheel.
203  For example, `delta.y` = 1.0 scrolls 1 line up.
204  Some systems and devices support finer resolution and/or higher values for fast scrolls,
205  so programs should handle any value gracefully.
206 
207  @a pos The widget-relative coordinates of the pointer.
208  @a absolutePos The absolute coordinates of the pointer.
209  @a delta The scroll distance.
210  @a direction The direction of the scroll or "smooth".
211  @see onScroll
212  */
214  Point<double> pos;
215  Point<double> absolutePos;
216  Point<double> delta;
217  ScrollDirection direction;
218 
219  /** Constructor */
220  ScrollEvent() noexcept
221  : BaseEvent(),
222  pos(0.0, 0.0),
223  absolutePos(0.0, 0.0),
224  delta(0.0, 0.0),
225  direction(kScrollSmooth) {}
226  };
227 
228  /**
229  Resize event.
230  @a size The new widget size.
231  @a oldSize The previous size, may be null.
232  @see onResize
233  */
234  struct ResizeEvent {
235  Size<uint> size;
236  Size<uint> oldSize;
237 
238  /** Constructor */
239  ResizeEvent() noexcept
240  : size(0, 0),
241  oldSize(0, 0) {}
242  };
243 
244  /**
245  Widget position changed event.
246  @a pos The new absolute position of the widget.
247  @a oldPos The previous absolute position of the widget.
248  @see onPositionChanged
249  */
251  Point<int> pos;
252  Point<int> oldPos;
253 
254  /** Constructor */
256  : pos(0, 0),
257  oldPos(0, 0) {}
258  };
259 
260 private:
261  /**
262  Private constructor, reserved for TopLevelWidget class.
263  */
264  explicit Widget(TopLevelWidget* topLevelWidget);
265 
266  /**
267  Private constructor, reserved for SubWidget class.
268  */
269  explicit Widget(Widget* widgetToGroupTo);
270 
271 public:
272  /**
273  Destructor.
274  */
275  virtual ~Widget();
276 
277  /**
278  Check if this widget is visible within its parent window.
279  Invisible widgets do not receive events except resize.
280  */
281  bool isVisible() const noexcept;
282 
283  /**
284  Set widget visible (or not) according to @a visible.
285  */
286  void setVisible(bool visible);
287 
288  /**
289  Show widget.
290  This is the same as calling setVisible(true).
291  */
292  void show();
293 
294  /**
295  Hide widget.
296  This is the same as calling setVisible(false).
297  */
298  void hide();
299 
300  /**
301  Get width.
302  */
303  uint getWidth() const noexcept;
304 
305  /**
306  Get height.
307  */
308  uint getHeight() const noexcept;
309 
310  /**
311  Get size.
312  */
313  const Size<uint> getSize() const noexcept;
314 
315  /**
316  Set width.
317  */
318  void setWidth(uint width) noexcept;
319 
320  /**
321  Set height.
322  */
323  void setHeight(uint height) noexcept;
324 
325  /**
326  Set size using @a width and @a height values.
327  */
328  void setSize(uint width, uint height) noexcept;
329 
330  /**
331  Set size.
332  */
333  void setSize(const Size<uint>& size) noexcept;
334 
335  /**
336  Get the Id associated with this widget.
337  @see setId
338  */
339  uint getId() const noexcept;
340 
341  /**
342  Set an Id to be associated with this widget.
343  @see getId
344  */
345  void setId(uint id) noexcept;
346 
347  /**
348  Get the application associated with this widget's window.
349  This is the same as calling `getTopLevelWidget()->getApp()`.
350  */
351  Application& getApp() const noexcept;
352 
353  /**
354  Get the window associated with this widget.
355  This is the same as calling `getTopLevelWidget()->getWindow()`.
356  */
357  Window& getWindow() const noexcept;
358 
359  /**
360  Get the graphics context associated with this widget's window.
361  GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable,
362  for example GraphicsContext.
363  @see CairoSubWidget, CairoTopLevelWidget
364  */
365  const GraphicsContext& getGraphicsContext() const noexcept;
366 
367  /**
368  Get top-level widget, as passed directly in the constructor
369  or going up the chain of group widgets until it finds the top-level one.
370  */
371  TopLevelWidget* getTopLevelWidget() const noexcept;
372 
373  /**
374  Request repaint of this widget's area to the window this widget belongs to.
375  On the raw Widget class this function does nothing.
376  */
377  virtual void repaint() noexcept;
378 
379  DISTRHO_DEPRECATED_BY("getApp()")
380  Application& getParentApp() const noexcept { return getApp(); }
381 
382  DISTRHO_DEPRECATED_BY("getWindow()")
383  Window& getParentWindow() const noexcept { return getWindow(); }
384 
385 protected:
386  /**
387  A function called to draw the widget contents.
388  */
389  virtual void onDisplay() = 0;
390 
391  /**
392  A function called when a key is pressed or released.
393  @return True to stop event propagation, false otherwise.
394  */
395  virtual bool onKeyboard(const KeyboardEvent&);
396 
397  /**
398  A function called when a special key is pressed or released.
399  @return True to stop event propagation, false otherwise.
400  */
401  virtual bool onSpecial(const SpecialEvent&);
402 
403  /**
404  A function called when an UTF-8 character is received.
405  @return True to stop event propagation, false otherwise.
406  */
407  virtual bool onCharacterInput(const CharacterInputEvent&);
408 
409  /**
410  A function called when a mouse button is pressed or released.
411  @return True to stop event propagation, false otherwise.
412  */
413  virtual bool onMouse(const MouseEvent&);
414 
415  /**
416  A function called when the pointer moves.
417  @return True to stop event propagation, false otherwise.
418  */
419  virtual bool onMotion(const MotionEvent&);
420 
421  /**
422  A function called on scrolling (e.g. mouse wheel or track pad).
423  @return True to stop event propagation, false otherwise.
424  */
425  virtual bool onScroll(const ScrollEvent&);
426 
427  /**
428  A function called when the widget is resized.
429  */
430  virtual void onResize(const ResizeEvent&);
431 
432 private:
433  struct PrivateData;
434  PrivateData* const pData;
435  friend class SubWidget;
436  friend class TopLevelWidget;
437 
438  DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget)
439 };
440 
441 // --------------------------------------------------------------------------------------------------------------------
442 
443 END_NAMESPACE_DGL
444 
445 #endif // DGL_WIDGET_HPP_INCLUDED
Widget::ScrollEvent
Definition: Widget.hpp:213
Widget::PositionChangedEvent::PositionChangedEvent
PositionChangedEvent() noexcept
Definition: Widget.hpp:255
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:239
Widget::MotionEvent
Definition: Widget.hpp:187
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:220
Widget::PositionChangedEvent
Definition: Widget.hpp:250
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:165
Widget::ResizeEvent
Definition: Widget.hpp:234
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:192
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:172
Widget::SpecialEvent
Definition: Widget.hpp:117
Widget
Definition: Widget.hpp:53
Widget::getGraphicsContext
const GraphicsContext & getGraphicsContext() const noexcept