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