rev |
line source |
nuclear@6
|
1 /*
|
nuclear@6
|
2 GoatKit - a themable/animated widget toolkit for games
|
nuclear@6
|
3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>
|
nuclear@6
|
4
|
nuclear@6
|
5 This program is free software: you can redistribute it and/or modify
|
nuclear@6
|
6 it under the terms of the GNU Lesser General Public License as published by
|
nuclear@6
|
7 the Free Software Foundation, either version 3 of the License, or
|
nuclear@6
|
8 (at your option) any later version.
|
nuclear@6
|
9
|
nuclear@6
|
10 This program is distributed in the hope that it will be useful,
|
nuclear@6
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@6
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@6
|
13 GNU Lesser General Public License for more details.
|
nuclear@6
|
14
|
nuclear@6
|
15 You should have received a copy of the GNU Lesser General Public License
|
nuclear@6
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
nuclear@6
|
17 */
|
nuclear@6
|
18 #include <stdio.h>
|
nuclear@6
|
19 #include <math.h>
|
nuclear@6
|
20 #include "slider.h"
|
nuclear@6
|
21 #include "screen.h"
|
nuclear@6
|
22
|
nuclear@6
|
23 namespace goatkit {
|
nuclear@6
|
24
|
nuclear@6
|
25 struct SliderImpl {
|
nuclear@6
|
26 float value, prev_value;
|
nuclear@6
|
27 float range_min, range_max;
|
nuclear@6
|
28 float padding;
|
nuclear@6
|
29 float step;
|
nuclear@6
|
30 bool dragging;
|
nuclear@6
|
31 bool cont_change;
|
nuclear@6
|
32 };
|
nuclear@6
|
33
|
nuclear@6
|
34 static float remap(float val, float inlow, float inhigh, float outlow, float outhigh);
|
nuclear@6
|
35
|
nuclear@6
|
36 Slider::Slider()
|
nuclear@6
|
37 {
|
nuclear@6
|
38 slider = new SliderImpl;
|
nuclear@6
|
39 slider->value = slider->prev_value = 0.0f;
|
nuclear@6
|
40 slider->dragging = false;
|
nuclear@6
|
41 slider->cont_change = true;
|
nuclear@6
|
42
|
nuclear@6
|
43 slider->range_min = 0.0;
|
nuclear@6
|
44 slider->range_max = 1.0;
|
nuclear@6
|
45 slider->step = 0.0;
|
nuclear@6
|
46
|
nuclear@6
|
47 slider->padding = -1.0;
|
nuclear@6
|
48 }
|
nuclear@6
|
49
|
nuclear@6
|
50 Slider::~Slider()
|
nuclear@6
|
51 {
|
nuclear@6
|
52 delete slider;
|
nuclear@6
|
53 }
|
nuclear@6
|
54
|
nuclear@6
|
55 const char *Slider::get_type_name() const
|
nuclear@6
|
56 {
|
nuclear@6
|
57 return "slider";
|
nuclear@6
|
58 }
|
nuclear@6
|
59
|
nuclear@6
|
60 void Slider::set_value(float val)
|
nuclear@6
|
61 {
|
nuclear@6
|
62 slider->value = remap(val, slider->range_min, slider->range_max, 0, 1);
|
nuclear@6
|
63 }
|
nuclear@6
|
64
|
nuclear@6
|
65 float Slider::get_value() const
|
nuclear@6
|
66 {
|
nuclear@6
|
67 return remap(slider->value, 0, 1, slider->range_min, slider->range_max);
|
nuclear@6
|
68 }
|
nuclear@6
|
69
|
nuclear@6
|
70 void Slider::set_value_norm(float val)
|
nuclear@6
|
71 {
|
nuclear@6
|
72 slider->value = val < 0.0 ? 0.0 : (val > 1.0 ? 1.0 : val);
|
nuclear@6
|
73 }
|
nuclear@6
|
74
|
nuclear@6
|
75 float Slider::get_value_norm() const
|
nuclear@6
|
76 {
|
nuclear@6
|
77 return slider->value;
|
nuclear@6
|
78 }
|
nuclear@6
|
79
|
nuclear@6
|
80 void Slider::set_padding(float pad)
|
nuclear@6
|
81 {
|
nuclear@6
|
82 slider->padding = pad;
|
nuclear@6
|
83 }
|
nuclear@6
|
84
|
nuclear@6
|
85 float Slider::get_padding() const
|
nuclear@6
|
86 {
|
nuclear@6
|
87 if(slider->padding < 0.0) {
|
nuclear@6
|
88 BBox box = get_box();
|
nuclear@6
|
89 return (box.bmax.y - box.bmin.y) * 0.25;
|
nuclear@6
|
90 }
|
nuclear@6
|
91 return slider->padding;
|
nuclear@6
|
92 }
|
nuclear@6
|
93
|
nuclear@6
|
94 void Slider::set_continuous_change(bool cont)
|
nuclear@6
|
95 {
|
nuclear@6
|
96 slider->cont_change = cont;
|
nuclear@6
|
97 }
|
nuclear@6
|
98
|
nuclear@6
|
99 bool Slider::get_continuous_change() const
|
nuclear@6
|
100 {
|
nuclear@6
|
101 return slider->cont_change;
|
nuclear@6
|
102 }
|
nuclear@6
|
103
|
nuclear@6
|
104 void Slider::set_range(float min, float max)
|
nuclear@6
|
105 {
|
nuclear@6
|
106 slider->range_min = min;
|
nuclear@6
|
107 slider->range_max = max;
|
nuclear@6
|
108 }
|
nuclear@6
|
109
|
nuclear@6
|
110 float Slider::get_range_min() const
|
nuclear@6
|
111 {
|
nuclear@6
|
112 return slider->range_min;
|
nuclear@6
|
113 }
|
nuclear@6
|
114
|
nuclear@6
|
115 float Slider::get_range_max() const
|
nuclear@6
|
116 {
|
nuclear@6
|
117 return slider->range_max;
|
nuclear@6
|
118 }
|
nuclear@6
|
119
|
nuclear@6
|
120 void Slider::set_step(float step)
|
nuclear@6
|
121 {
|
nuclear@6
|
122 slider->step = step;
|
nuclear@6
|
123 }
|
nuclear@6
|
124
|
nuclear@6
|
125 float Slider::get_step() const
|
nuclear@6
|
126 {
|
nuclear@6
|
127 return slider->step;
|
nuclear@6
|
128 }
|
nuclear@6
|
129
|
nuclear@6
|
130 void Slider::on_mouse_button(const ButtonEvent &ev)
|
nuclear@6
|
131 {
|
nuclear@6
|
132 if(ev.button == 0) {
|
nuclear@6
|
133 Screen *scr = get_screen();
|
nuclear@6
|
134
|
nuclear@6
|
135 slider->dragging = ev.press;
|
nuclear@6
|
136 if(ev.press) {
|
nuclear@6
|
137 if(scr) scr->grab_mouse(this);
|
nuclear@6
|
138 } else {
|
nuclear@6
|
139 if(scr) scr->grab_mouse(0);
|
nuclear@6
|
140
|
nuclear@6
|
141 // on release, if the value has changed send the appropriate event
|
nuclear@6
|
142 if(slider->prev_value != slider->value) {
|
nuclear@6
|
143 Event ev;
|
nuclear@6
|
144 ev.type = EV_CHANGE;
|
nuclear@6
|
145 handle_event(ev);
|
nuclear@6
|
146 slider->prev_value = slider->value;
|
nuclear@6
|
147 }
|
nuclear@6
|
148 }
|
nuclear@6
|
149 }
|
nuclear@6
|
150 }
|
nuclear@6
|
151
|
nuclear@6
|
152 #define ROUND(x) floor((x) + 0.5)
|
nuclear@6
|
153
|
nuclear@6
|
154 void Slider::on_mouse_motion(const MotionEvent &ev)
|
nuclear@6
|
155 {
|
nuclear@6
|
156 if(!slider->dragging) {
|
nuclear@6
|
157 return;
|
nuclear@6
|
158 }
|
nuclear@6
|
159
|
nuclear@6
|
160 BBox box = get_box();
|
nuclear@6
|
161
|
nuclear@6
|
162 float padding = get_padding();
|
nuclear@6
|
163 float start = box.bmin.x + padding;
|
nuclear@6
|
164 float end = box.bmax.x - padding;
|
nuclear@6
|
165 float new_val = (ev.pos.x - start) / (end - start);
|
nuclear@6
|
166
|
nuclear@6
|
167 // if we have a non-zero step, snap to the nearest value
|
nuclear@6
|
168 if(slider->step > 0.0) {
|
nuclear@6
|
169 float range = slider->range_max - slider->range_min;
|
nuclear@6
|
170 float st = slider->step / range;
|
nuclear@6
|
171
|
nuclear@6
|
172 new_val = ROUND(new_val / st) * st;
|
nuclear@6
|
173 }
|
nuclear@6
|
174
|
nuclear@6
|
175 if(new_val < 0.0) new_val = 0.0;
|
nuclear@6
|
176 if(new_val > 1.0) new_val = 1.0;
|
nuclear@6
|
177
|
nuclear@6
|
178 if(new_val != slider->value) {
|
nuclear@6
|
179 slider->value = new_val;
|
nuclear@6
|
180 if(slider->cont_change) {
|
nuclear@6
|
181 Event cev;
|
nuclear@6
|
182 cev.type = EV_CHANGE;
|
nuclear@6
|
183 handle_event(cev);
|
nuclear@6
|
184 }
|
nuclear@6
|
185 }
|
nuclear@6
|
186 }
|
nuclear@6
|
187
|
nuclear@6
|
188 static float remap(float val, float inlow, float inhigh, float outlow, float outhigh)
|
nuclear@6
|
189 {
|
nuclear@6
|
190 float t = (val - inlow) / (inhigh - inlow);
|
nuclear@6
|
191 if(t < 0.0) t = 0.0;
|
nuclear@6
|
192 if(t > 1.0) t = 1.0;
|
nuclear@6
|
193 return t * (outhigh - outlow) + outlow;
|
nuclear@6
|
194 }
|
nuclear@6
|
195
|
nuclear@6
|
196 } // namespace goatkit
|