Widget.hpp (14448B)
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 */ 92 struct KeyboardEvent : BaseEvent { 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 */ 137 struct CharacterInputEvent : BaseEvent { 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 */ 146 CharacterInputEvent() noexcept 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 */ 161 struct MouseEvent : BaseEvent { 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. */ 167 Point<double> pos; 168 /** The absolute coordinates of the pointer. */ 169 Point<double> absolutePos; 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 */ 184 struct MotionEvent : BaseEvent { 185 /** The widget-relative coordinates of the pointer. */ 186 Point<double> pos; 187 /** The absolute coordinates of the pointer. */ 188 Point<double> absolutePos; 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 */ 208 struct ScrollEvent : BaseEvent { 209 /** The widget-relative coordinates of the pointer. */ 210 Point<double> pos; 211 /** The absolute coordinates of the pointer. */ 212 Point<double> absolutePos; 213 /** The scroll distance. */ 214 Point<double> delta; 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. */ 233 Size<uint> size; 234 /** The previous size, can be null. */ 235 Size<uint> oldSize; 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 */ 247 struct PositionChangedEvent { 248 /** The new absolute position of the widget. */ 249 Point<int> pos; 250 /** The previous absolute position of the widget. */ 251 Point<int> oldPos; 252 253 /** Constructor for default/null values */ 254 PositionChangedEvent() noexcept 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 */ 387 TopLevelWidget* getTopLevelWidget() const noexcept; 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