DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

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