Dusk Audio Framework
Loading...
Searching...
No Matches
Widget.hpp
1/*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2024 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
24START_NAMESPACE_DGL
25
26// --------------------------------------------------------------------------------------------------------------------
27// Forward class names
28
29class Application;
30class SubWidget;
31class TopLevelWidget;
32class 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 */
55class Widget
56{
57public:
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 /** Destructor */
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 DAF due to pugl, but now deprecated and simply non-functional.
112 All events go through KeyboardEvent or CharacterInputEvent, use those instead.
113 */
114 struct DAF_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. */
140 /** Unicode character code. */
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 DAF_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 Keyboard focus event.
245
246 This event is sent when the window a widget belongs to gains or loses the keyboard focus.
247 The @a mode field tells whether the change is a plain focus change or the side-effect of a
248 grab, which matters because a grab is temporary and does not mean the user moved away.
249
250 @see onFocusChanged
251 */
252 struct FocusEvent {
253 /** True if the window gained the focus, false if it lost it. */
254 bool focus;
255 /** The reason for the focus change. @see CrossingMode */
256 CrossingMode mode;
257
258 /** Constructor for default/null values */
259 FocusEvent() noexcept
260 : focus(false),
261 mode(kCrossingNormal) {}
262 };
263
264 /**
265 Widget position changed event.
266 @see onPositionChanged
267 */
269 /** The new absolute position of the widget. */
271 /** The previous absolute position of the widget. */
273
274 /** Constructor for default/null values */
276 : pos(0, 0),
277 oldPos(0, 0) {}
278 };
279
280private:
281 /**
282 Private constructor, reserved for TopLevelWidget class.
283 */
284 explicit Widget(TopLevelWidget* topLevelWidget);
285
286 /**
287 Private constructor, reserved for SubWidget class.
288 */
289 explicit Widget(Widget* widgetToGroupTo);
290
291public:
292 /**
293 Destructor.
294 */
295 virtual ~Widget();
296
297 /**
298 Check if this widget is visible within its parent window.
299 Invisible widgets do not receive events except resize.
300 */
301 bool isVisible() const noexcept;
302
303 /**
304 Set widget visible (or not) according to @a visible.
305 */
306 void setVisible(bool visible);
307
308 /**
309 Show widget.
310 This is the same as calling setVisible(true).
311 */
312 void show();
313
314 /**
315 Hide widget.
316 This is the same as calling setVisible(false).
317 */
318 void hide();
319
320 /**
321 Get width.
322 */
323 uint getWidth() const noexcept;
324
325 /**
326 Get height.
327 */
328 uint getHeight() const noexcept;
329
330 /**
331 Get size.
332 */
333 const Size<uint> getSize() const noexcept;
334
335 /**
336 Set width.
337 */
338 void setWidth(uint width) noexcept;
339
340 /**
341 Set height.
342 */
343 void setHeight(uint height) noexcept;
344
345 /**
346 Set size using @a width and @a height values.
347 */
348 void setSize(uint width, uint height) noexcept;
349
350 /**
351 Set size.
352 */
353 void setSize(const Size<uint>& size) noexcept;
354
355 /**
356 Get the Id associated with this widget.
357 Returns 0 by default.
358 @see setId
359 */
360 uint getId() const noexcept;
361
362 /**
363 Get the name associated with this widget.
364 This is completely optional, mostly useful for debugging purposes.
365 Returns an empty string by default.
366 @see setName
367 */
368 const char* getName() const noexcept;
369
370 /**
371 Set an Id to be associated with this widget.
372 @see getId
373 */
374 void setId(uint id) noexcept;
375
376 /**
377 Set a name to be associated with this widget.
378 This is completely optional, only useful for debugging purposes.
379 @note name must not be null
380 @see getName
381 */
382 void setName(const char* name) noexcept;
383
384 /**
385 Get the application associated with this widget's window.
386 This is the same as calling `getTopLevelWidget()->getApp()`.
387 */
388 Application& getApp() const noexcept;
389
390 /**
391 Get the window associated with this widget.
392 This is the same as calling `getTopLevelWidget()->getWindow()`.
393 */
394 Window& getWindow() const noexcept;
395
396 /**
397 Get the graphics context associated with this widget's window.
398 GraphicsContext is an empty struct and needs to be casted into a different type in order to be usable,
399 for example GraphicsContext.
400 @see CairoSubWidget, CairoTopLevelWidget
401 */
402 const GraphicsContext& getGraphicsContext() const noexcept;
403
404 /**
405 Get top-level widget, as passed directly in the constructor
406 or going up the chain of group widgets until it finds the top-level one.
407 */
408 TopLevelWidget* getTopLevelWidget() const noexcept;
409
410 /**
411 Get list of children (a subwidgets) that belong to this widget.
412 */
413 std::list<SubWidget*> getChildren() const noexcept;
414
415 /**
416 Request repaint of this widget's area to the window this widget belongs to.
417 On the raw Widget class this function does nothing.
418 */
419 virtual void repaint() noexcept;
420
421 /**
422 Whether this widget wants the keyboard focus right now, typically because a text field in it is being edited.
423
424 This reports the widget's own state only. Window::anyWidgetWantsKeyboardFocus() asks every visible widget of a
425 window, subwidgets included, so an override does not need to ask its children.
426
427 An embedded plugin editor on Windows uses the answer in the formats whose hosts have no keyboard focus API
428 (CLAP and VST2): the editor takes the focus when clicked, keeps it while some widget wants it and hands it back
429 to the host window once none does, so host shortcuts keep working after a click on a knob.
430 Elsewhere the answer is informational.
431
432 It is asked on every idle of such an editor, so it should be cheap.
433 The default implementation returns false.
434 */
435 virtual bool wantsKeyboardFocus();
436
437 DAF_DEPRECATED_BY("getApp()")
438 Application& getParentApp() const noexcept { return getApp(); }
439
440 DAF_DEPRECATED_BY("getWindow()")
441 Window& getParentWindow() const noexcept { return getWindow(); }
442
443protected:
444 /**
445 A function called to draw the widget contents.
446 */
447 virtual void onDisplay() {};
448
449 /**
450 A function called when a key is pressed or released.
451 @return True to stop event propagation, false otherwise.
452 */
453 virtual bool onKeyboard(const KeyboardEvent&);
454
455 /**
456 A function called when an UTF-8 character is received.
457 @return True to stop event propagation, false otherwise.
458 */
460
461 /**
462 A function called when a mouse button is pressed or released.
463 @return True to stop event propagation, false otherwise.
464 */
465 virtual bool onMouse(const MouseEvent&);
466
467 /**
468 A function called when the pointer moves.
469 @return True to stop event propagation, false otherwise.
470 */
471 virtual bool onMotion(const MotionEvent&);
472
473 /**
474 A function called on scrolling (e.g. mouse wheel or track pad).
475 @return True to stop event propagation, false otherwise.
476 */
477 virtual bool onScroll(const ScrollEvent&);
478
479 /**
480 A function called when the widget is resized.
481 */
482 virtual void onResize(const ResizeEvent&);
483
484 /**
485 A function called when the window this widget belongs to gains or loses the keyboard focus.
486 Unlike the input events this is delivered to every widget, visible or not,
487 so that a widget holding input state can clear it.
488 @note The window itself has its own Window::onFocus, this is the widget-side view of it.
489 */
490 virtual void onFocusChanged(const FocusEvent&);
491
492 /**
493 A function called when a special key is pressed or released.
494 DEPRECATED use onKeyboard or onCharacterInput
495 */
496 #if defined(_MSC_VER)
497 #pragma warning(push)
498 #pragma warning(disable:4996)
499 #elif defined(__clang__)
500 #pragma clang diagnostic push
501 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
502 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460
503 #pragma GCC diagnostic push
504 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
505 #endif
506 virtual bool onSpecial(const SpecialEvent&) { return false; }
507 #if defined(_MSC_VER)
508 #pragma warning(pop)
509 #elif defined(__clang__)
510 #pragma clang diagnostic pop
511 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 460
512 #pragma GCC diagnostic pop
513 #endif
514
515private:
516 struct PrivateData;
517 PrivateData* const pData;
518 friend class SubWidget;
519 friend class TopLevelWidget;
520
521 DAF_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget)
522};
523
524// --------------------------------------------------------------------------------------------------------------------
525
526END_NAMESPACE_DGL
527
528#endif // DGL_WIDGET_HPP_INCLUDED
Definition Application.hpp:90
Definition Geometry.hpp:41
Definition Geometry.hpp:133
Definition SubWidget.hpp:40
Definition TopLevelWidget.hpp:47
Definition Widget.hpp:56
virtual bool onMouse(const MouseEvent &)
virtual bool onScroll(const ScrollEvent &)
std::list< SubWidget * > getChildren() const noexcept
uint getWidth() const noexcept
bool isVisible() const noexcept
void show()
virtual bool wantsKeyboardFocus()
const GraphicsContext & getGraphicsContext() const noexcept
virtual bool onSpecial(const SpecialEvent &)
Definition Widget.hpp:506
uint getId() const noexcept
virtual void onDisplay()
Definition Widget.hpp:447
void hide()
virtual void onFocusChanged(const FocusEvent &)
void setName(const char *name) noexcept
virtual bool onMotion(const MotionEvent &)
void setVisible(bool visible)
const Size< uint > getSize() const noexcept
virtual ~Widget()
TopLevelWidget * getTopLevelWidget() const noexcept
const char * getName() 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
Application & getApp() const noexcept
virtual void onResize(const ResizeEvent &)
Window & getWindow() const noexcept
virtual bool onCharacterInput(const CharacterInputEvent &)
void setWidth(uint width) noexcept
Definition Window.hpp:67
Definition Base.hpp:287
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:252
CrossingMode mode
Definition Widget.hpp:256
bool focus
Definition Widget.hpp:254
FocusEvent() noexcept
Definition Widget.hpp:259
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
PositionChangedEvent() noexcept
Definition Widget.hpp:275
Point< int > oldPos
Definition Widget.hpp:272
Point< int > pos
Definition Widget.hpp:270
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