1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2019 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 <vector>
23 
24 // -----------------------------------------------------------------------
25 // Forward class names
26 
27 #ifdef DISTRHO_DEFINES_H_INCLUDED
28 START_NAMESPACE_DISTRHO
29 class UI;
30 END_NAMESPACE_DISTRHO
31 #endif
32 
33 START_NAMESPACE_DGL
34 
35 class Application;
36 class ImageSlider;
37 class NanoWidget;
38 class Window;
39 class StandaloneWindow;
40 
41 // -----------------------------------------------------------------------
42 
43 /**
44    Base DGL Widget class.
45 
46    This is the base Widget class, from which all widgets are built.
47 
48    All widgets have a parent Window where they'll be drawn.
49    This parent is never changed during the widget lifetime.
50 
51    Widgets receive events in relative coordinates.
52    (0, 0) means its top-left position.
53 
54    Windows paint widgets in the order they are constructed.
HandleNanoImage::Handle55    Early widgets are drawn first, at the bottom, then newer ones on top.
56    Events are sent in the inverse order so that the top-most widget gets
57    a chance to catch the event and stop its propagation.
58 
59    All widget event callbacks do nothing by default.
60  */
61 class Widget
62 {
63 public:
64    /**
65       Base event data.
66       @a mod  The currently active keyboard modifiers, @see Modifier.
67       @a time The timestamp (if any).
68     */
69     struct BaseEvent {
70         uint     mod;
71         uint32_t time;
72 
73         /** Constuctor */
74         BaseEvent() noexcept : mod(0x0), time(0) {}
75         /** Destuctor */
76         virtual ~BaseEvent() noexcept {}
77     };
78 
79    /**
80       Keyboard event.
81       @a press True if the key was pressed, false if released.
82       @a key   Unicode point of the key pressed.
83       @see onKeyboard
84     */
85     struct KeyboardEvent : BaseEvent {
86         bool press;
87         uint key;
88 
89         /** Constuctor */
90         KeyboardEvent() noexcept
91             : BaseEvent(),
92               press(false),
93               key(0) {}
94     };
95 
96    /**
97       Special keyboard event.
98       @a press True if the key was pressed, false if released.
99       @a key   The key pressed.
100       @see onSpecial
101     */
102     struct SpecialEvent : BaseEvent {
103         bool press;
104         Key  key;
105 
106         /** Constuctor */
107         SpecialEvent() noexcept
108             : BaseEvent(),
109               press(false),
110               key(Key(0)) {}
111     };
112 
113    /**
114       Mouse event.
115       @a button The button number (1 = left, 2 = middle, 3 = right).
116       @a press  True if the button was pressed, false if released.
117       @a pos    The widget-relative coordinates of the pointer.
118       @see onMouse
119     */
120     struct MouseEvent : BaseEvent {
121         int  button;
122         bool press;
123         Point<int> pos;
124 
125         /** Constuctor */
126         MouseEvent() noexcept
127             : BaseEvent(),
128               button(0),
129               press(false),
130               pos(0, 0) {}
131     };
132 
133    /**
134       Mouse motion event.
135       @a pos The widget-relative coordinates of the pointer.
136       @see onMotion
137     */
138     struct MotionEvent : BaseEvent {
139         Point<int> pos;
140 
141         /** Constuctor */
142         MotionEvent() noexcept
143             : BaseEvent(),
144               pos(0, 0) {}
145     };
146 
147    /**
148       Mouse scroll event.
149       @a pos   The widget-relative coordinates of the pointer.
150       @a delta The scroll distance.
151       @see onScroll
152     */
153     struct ScrollEvent : BaseEvent {
154         Point<int> pos;
155         Point<float> delta;
156 
157         /** Constuctor */
158         ScrollEvent() noexcept
159             : BaseEvent(),
160               pos(0, 0),
161               delta(0.0f, 0.0f) {}
162     };
163 
164    /**
165       Resize event.
166       @a size    The new widget size.
167       @a oldSize The previous size, may be null.
168       @see onResize
169     */
170     struct ResizeEvent {
171         Size<uint> size;
172         Size<uint> oldSize;
173 
174         /** Constuctor */
175         ResizeEvent() noexcept
176             : size(0, 0),
177               oldSize(0, 0) {}
178     };
179 
180    /**
181       Widget position changed event.
182       @a pos    The new absolute position of the widget.
183       @a oldPos The previous absolute position of the widget.
184       @see onPositionChanged
185     */
186     struct PositionChangedEvent {
187         Point<int> pos;
188         Point<int> oldPos;
189 
190         /** Constuctor */
191         PositionChangedEvent() noexcept
192             : pos(0, 0),
193               oldPos(0, 0) {}
194     };
195 
196    /**
197       Constructor.
198     */
199     explicit Widget(Window& parent);
200 
201    /**
202       Constructor for a subwidget.
203     */
204     explicit Widget(Widget* groupWidget);
205 
206    /**
207       Destructor.
208     */
209     virtual ~Widget();
210 
211    /**
212       Check if this widget is visible within its parent window.
213       Invisible widgets do not receive events except resize.
214     */
215     bool isVisible() const noexcept;
216 
217    /**
218       Set widget visible (or not) according to @a yesNo.
219     */
220     void setVisible(bool yesNo);
221 
222    /**
223       Show widget.
224       This is the same as calling setVisible(true).
225     */
226     void show();
227 
228    /**
229       Hide widget.
230       This is the same as calling setVisible(false).
231     */
232     void hide();
233 
234    /**
235       Get width.
236     */
237     uint getWidth() const noexcept;
238 
239    /**
240       Get height.
241     */
242     uint getHeight() const noexcept;
243 
244    /**
245       Get size.
246     */
247     const Size<uint>& getSize() const noexcept;
248 
249    /**
250       Set width.
251     */
252     void setWidth(uint width) noexcept;
253 
254    /**
255       Set height.
256     */
257     void setHeight(uint height) noexcept;
258 
259    /**
260       Set size using @a width and @a height values.
261     */
262     void setSize(uint width, uint height) noexcept;
263 
264    /**
265       Set size.
266     */
267     void setSize(const Size<uint>& size) noexcept;
268 
269    /**
270       Get absolute X.
271     */
272     int getAbsoluteX() const noexcept;
273 
274    /**
275       Get absolute Y.
276     */
277     int getAbsoluteY() const noexcept;
278 
279    /**
280       Get absolute position.
281     */
282     const Point<int>& getAbsolutePos() const noexcept;
283 
284    /**
285       Set absolute X.
286     */
287     void setAbsoluteX(int x) noexcept;
288 
289    /**
290       Set absolute Y.
291     */
292     void setAbsoluteY(int y) noexcept;
293 
294    /**
295       Set absolute position using @a x and @a y values.
296     */
297     void setAbsolutePos(int x, int y) noexcept;
298 
299    /**
300       Set absolute position.
301     */
302     void setAbsolutePos(const Point<int>& pos) noexcept;
303 
304    /**
305       Get this widget's window application.
306       Same as calling getParentWindow().getApp().
307     */
308     Application& getParentApp() const noexcept;
309 
310    /**
311       Get parent window, as passed in the constructor.
312     */
313     Window& getParentWindow() const noexcept;
314 
315    /**
316       Check if this widget contains the point defined by @a x and @a y.
317     */
318     bool contains(int x, int y) const noexcept;
319 
320    /**
321       Check if this widget contains the point @a pos.
322     */
323     bool contains(const Point<int>& pos) const noexcept;
324 
325    /**
326       Tell this widget's window to repaint itself.
327     */
328     void repaint() noexcept;
329 
330    /**
331       Get the Id associated with this widget.
332       @see setId
333     */
334     uint getId() const noexcept;
335 
336    /**
337       Set an Id to be associated with this widget.
338       @see getId
339     */
340     void setId(uint id) noexcept;
341 
342 protected:
343    /**
344       A function called to draw the view contents with OpenGL.
345     */
346     virtual void onDisplay() = 0;
347 
348    /**
349       A function called when a key is pressed or released.
350       @return True to stop event propagation, false otherwise.
351     */
352     virtual bool onKeyboard(const KeyboardEvent&);
353 
354    /**
355       A function called when a special key is pressed or released.
356       @return True to stop event propagation, false otherwise.
357     */
358     virtual bool onSpecial(const SpecialEvent&);
359 
360    /**
361       A function called when a mouse button is pressed or released.
362       @return True to stop event propagation, false otherwise.
363     */
364     virtual bool onMouse(const MouseEvent&);
365 
366    /**
367       A function called when the pointer moves.
368       @return True to stop event propagation, false otherwise.
369     */
370     virtual bool onMotion(const MotionEvent&);
371 
372    /**
373       A function called on scrolling (e.g. mouse wheel or track pad).
374       @return True to stop event propagation, false otherwise.
375     */
376     virtual bool onScroll(const ScrollEvent&);
377 
378    /**
379       A function called when the widget is resized.
380     */
381     virtual void onResize(const ResizeEvent&);
382 
383    /**
384       A function called when the widget's absolute position is changed.
385     */
386     virtual void onPositionChanged(const PositionChangedEvent&);
387 
388 private:
389     struct PrivateData;
390     PrivateData* const pData;
391 
392    /** @internal */
393     explicit Widget(Widget* groupWidget, bool addToSubWidgets);
394 
395     friend class ImageSlider;
396     friend class NanoWidget;
397     friend class Window;
398     friend class StandaloneWindow;
399 #ifdef DISTRHO_DEFINES_H_INCLUDED
400     friend class DISTRHO_NAMESPACE::UI;
401 #endif
402 
403     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Widget)
404 };
405 
406 // -----------------------------------------------------------------------
407 
408 END_NAMESPACE_DGL
409 
410 #endif // DGL_WIDGET_HPP_INCLUDED
411