1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2016 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_COMMON_HPP_INCLUDED
18 #define DGL_COMMON_HPP_INCLUDED
19 
20 #include "../ImageWidgets.hpp"
21 
22 START_NAMESPACE_DGL
23 
24 // -----------------------------------------------------------------------
25 
26 struct ButtonImpl {
27     enum State {
28         kStateNormal = 0,
29         kStateHover,
30         kStateDown
31     };
32 
33     int button;
34     int state;
35     Widget* self;
36 
37     ImageButton::Callback* callback_img;
38 
ButtonImplButtonImpl39     ButtonImpl(Widget* const s) noexcept
40         : button(-1),
41           state(kStateNormal),
42           self(s),
43           callback_img(nullptr) {}
44 
onMouseButtonImpl45     bool onMouse(const Widget::MouseEvent& ev)
46     {
47         // button was released, handle it now
48         if (button != -1 && ! ev.press)
49         {
50             DISTRHO_SAFE_ASSERT(state == kStateDown);
51 
52             // release button
53             const int button2 = button;
54             button = -1;
55 
56             // cursor was moved outside the button bounds, ignore click
57             if (! self->contains(ev.pos))
58             {
59                 state = kStateNormal;
60                 self->repaint();
61                 return true;
62             }
63 
64             // still on bounds, register click
65             state = kStateHover;
66             self->repaint();
67 
68             if (callback_img != nullptr)
69                 callback_img->imageButtonClicked((ImageButton*)self, button2);
70 
71             return true;
72         }
73 
74         // button was pressed, wait for release
75         if (ev.press && self->contains(ev.pos))
76         {
77             button = ev.button;
78             state  = kStateDown;
79             self->repaint();
80             return true;
81         }
82 
83         return false;
84     }
85 
onMotionButtonImpl86     bool onMotion(const Widget::MotionEvent& ev)
87     {
88         // keep pressed
89         if (button != -1)
90             return true;
91 
92         if (self->contains(ev.pos))
93         {
94             // check if entering hover
95             if (state == kStateNormal)
96             {
97                 state = kStateHover;
98                 self->repaint();
99                 return true;
100             }
101         }
102         else
103         {
104             // check if exiting hover
105             if (state == kStateHover)
106             {
107                 state = kStateNormal;
108                 self->repaint();
109                 return true;
110             }
111         }
112 
113         return false;
114     }
115 
116     DISTRHO_PREVENT_HEAP_ALLOCATION
117     DISTRHO_DECLARE_NON_COPY_STRUCT(ButtonImpl)
118 };
119 
120 // -----------------------------------------------------------------------
121 
122 END_NAMESPACE_DGL
123 
124 #endif // DGL_APP_PRIVATE_DATA_HPP_INCLUDED
125