Rev 2199 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1528 | jag | 1 | /* |
2 | * slider.h |
||
2302 | jag | 3 | * DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath |
1528 | jag | 4 | * For more information, please visit http://dinisnoise.org/ |
5 | */ |
||
6 | |||
7 | |||
8 | #ifndef __slider |
||
9 | #define __slider |
||
10 | |||
11 | #include "widget.h" |
||
12 | #include "viewwin.h" |
||
13 | #include "utils.h" |
||
14 | #include "filled_button.h" |
||
2199 | jag | 15 | #include "input.h" |
1528 | jag | 16 | |
17 | #include <algorithm> |
||
18 | #include <vector> |
||
19 | |||
20 | extern int mousex; |
||
21 | extern viewport view; |
||
22 | extern int lmb; |
||
23 | |||
24 | template <typename S> struct after_slide_lis { |
||
25 | virtual void slided (S& s) = 0; |
||
26 | }; |
||
27 | |||
28 | template <typename S> struct start_slide_lis { |
||
29 | virtual void start_slide (S& s) = 0; |
||
30 | }; |
||
31 | |||
32 | template <typename T> struct values { |
||
33 | |||
34 | T low, high, delta, val; |
||
35 | float amount; |
||
36 | |||
37 | values (T l = 0, T h = 1, T v = 0) { |
||
38 | set_limits (l, h); |
||
39 | *this = v; |
||
40 | } |
||
41 | |||
42 | operator T() { |
||
43 | return ((T) val); |
||
44 | } |
||
45 | |||
46 | void set_limits (T l, T h) { |
||
47 | low = l; |
||
48 | high = h; |
||
49 | delta = high - low; |
||
50 | } |
||
51 | |||
52 | void get_limits (T& l, T& h) { |
||
53 | l = low; |
||
54 | h = high; |
||
55 | } |
||
56 | |||
57 | T operator() () const { return val; } |
||
58 | values& operator= (const T& v) { |
||
59 | val = v; |
||
60 | clamp<T> (low, val, high); |
||
61 | if (delta) amount = (val - low) * 1.0f / delta; else amount = 0; |
||
62 | return *this; |
||
63 | } |
||
64 | |||
65 | void set_amount (float a) { |
||
66 | amount = a; |
||
67 | clamp<float> (0.0f, amount, 1.0f); |
||
68 | val = (T) (low + delta * amount); |
||
69 | } |
||
70 | |||
71 | float get_amount () const { return amount; } |
||
72 | |||
73 | }; |
||
74 | |||
75 | template <typename T> struct slider : widget, move_listener { |
||
76 | |||
77 | values<T> vx; |
||
78 | int dx; |
||
2199 | jag | 79 | std::vector<int> dxa; |
1528 | jag | 80 | |
81 | int sliding; |
||
82 | int lmb_clicked; |
||
83 | |||
84 | change_listener<slider> *chgl; |
||
85 | after_slide_lis<slider> *asl; |
||
86 | start_slide_lis<slider> *ssl; |
||
87 | |||
88 | filled_button sizer; |
||
89 | static const int spc = 10; |
||
90 | |||
91 | slider (int sv = 0, int w = 64, int h = 16) : widget (0, 0, w, h), vx (0, 0, 0), sliding(0), lmb_clicked(0) { |
||
92 | chgl = 0; |
||
93 | asl = 0; |
||
94 | set_sizer_visible (sv); |
||
95 | } |
||
96 | |||
97 | void set_sizer_visible (int sv) { |
||
98 | sizer.visible = sv; |
||
99 | if (sizer.visible) { |
||
100 | sizer.set_moveable (1); |
||
101 | sizer.movlis = this; |
||
102 | } else { |
||
103 | sizer.set_moveable (0); |
||
104 | sizer.movlis = 0; |
||
105 | } |
||
106 | } |
||
107 | |||
108 | void set_pos (int x, int y) { |
||
109 | widget::set_pos (x, y); |
||
110 | sizer.set_pos (extents.right + spc, extents.bottom); |
||
111 | } |
||
112 | |||
113 | void set_right (int r) { |
||
114 | set_extents (extents.left, extents.bottom, r, extents.top); |
||
115 | dx = vx.get_amount () * extents.width; |
||
116 | } |
||
117 | |||
2064 | jag | 118 | void set_size (int w) { |
119 | set_extents (extents.left, extents.bottom, extents.left + w, extents.top); |
||
120 | dx = vx.get_amount () * extents.width; |
||
121 | } |
||
122 | |||
1528 | jag | 123 | void moved () { |
124 | int mpx = mousex - movr.prevx; |
||
125 | if (mpx) { |
||
126 | sizer.set_pos (mousex, extents.bottom); |
||
127 | int msx = mousex - spc; |
||
128 | if (msx > extents.left) set_right (msx); |
||
129 | } |
||
130 | } |
||
131 | |||
132 | int handle_input () { |
||
133 | |||
134 | widget::handle_input (); |
||
135 | |||
136 | if (sizer.visible && sizer.handle_input ()) return 1; |
||
137 | |||
138 | int ret = 0; |
||
139 | |||
140 | if (lmb) { |
||
141 | if (lmb_clicked == 0) { |
||
142 | if (sliding) { |
||
143 | sliding = 0; |
||
144 | if (asl) asl->slided (*this); |
||
145 | defocus (this); |
||
146 | ret = 1; |
||
147 | } else { |
||
148 | if (hover) { |
||
149 | sliding = 1; |
||
150 | if (ssl) ssl->start_slide (*this); |
||
151 | widget::focus = this; |
||
152 | ret = 1; |
||
153 | } |
||
154 | } |
||
155 | lmb_clicked = 1; |
||
156 | } |
||
157 | } else { |
||
158 | if (sliding) { |
||
159 | int nu_dx = mousex - extents.left; |
||
160 | clamp (0, nu_dx, extents.width); |
||
161 | if (nu_dx != dx) { |
||
162 | dx = nu_dx; |
||
163 | vx.set_amount (dx * extents.width_1); |
||
164 | if (chgl) chgl->changed (*this); |
||
165 | } |
||
2199 | jag | 166 | if (keypressed(SDLK_f)) dxa.push_back (dx); |
167 | if (keypressed(SDLK_BACKSPACE)) dxa.clear (); |
||
2064 | jag | 168 | } else |
169 | ret = 0; |
||
1528 | jag | 170 | lmb_clicked = 0; |
171 | } |
||
2199 | jag | 172 | |
173 | |||
1528 | jag | 174 | return ret; |
175 | |||
176 | } |
||
177 | |||
178 | void draw () { |
||
179 | |||
180 | widget::draw (); |
||
181 | |||
182 | glEnable (GL_BLEND); |
||
183 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
||
184 | |||
185 | const color& c = clr; |
||
186 | |||
2064 | jag | 187 | glColor4f (c.r, c.g, c.b, (GLfloat) 0.25); |
1528 | jag | 188 | |
189 | const box<int>& e = extents; |
||
190 | glRecti (e.left, e.bottom, e.right, e.top); |
||
191 | |||
2064 | jag | 192 | glColor4f (c.r, c.g, c.b, GLfloat (1)); |
1528 | jag | 193 | glRecti (e.left, e.bottom, e.left + dx, e.top); |
194 | |||
195 | glDisable (GL_BLEND); |
||
196 | |||
2199 | jag | 197 | glColor3f (1, 1, 1); |
198 | for (int i = 0, j = dxa.size (); i < j; ++i) { |
||
199 | int dxi = extents.left + dxa[i]; |
||
200 | glBegin (GL_LINES); |
||
201 | glVertex2i (dxi, extents.top + spc); |
||
202 | glVertex2i (dxi, extents.bottom - spc); |
||
203 | glEnd (); |
||
204 | } |
||
205 | |||
1528 | jag | 206 | if (sizer.visible) sizer.draw (); |
207 | |||
208 | } |
||
209 | |||
210 | void update () { |
||
211 | float amount = vx.get_amount (); |
||
212 | const box<int>& e = extents; |
||
213 | dx = (int) (amount * e.width); |
||
214 | } |
||
215 | |||
216 | void set_listener (change_listener<slider>* _chgl, start_slide_lis<slider>* _ssl = 0, after_slide_lis<slider>* _asl = 0) { |
||
217 | chgl = _chgl; |
||
218 | ssl = _ssl; |
||
219 | asl = _asl; |
||
220 | } |
||
221 | |||
222 | T operator() () const {return vx (); } |
||
223 | |||
224 | void set_val (const T& t) { |
||
225 | vx = t; |
||
226 | update (); |
||
227 | } |
||
228 | |||
229 | void set_limits (T l, T h) { |
||
230 | vx = values<T> (l, h, vx()); |
||
231 | update (); |
||
232 | } |
||
233 | |||
234 | void get_limits (T& l, T& h) { |
||
235 | vx.get_limits (l, h); |
||
236 | } |
||
237 | }; |
||
238 | |||
239 | #define MAKE_SLIDER_LISTENER(name,var) struct name : change_listener< slider<float> > { void changed (slider<float>& s); }; name var; |
||
240 | #define SLIDER_CHANGED(scope,name) void scope::name::changed (slider<float>& s) |
||
241 | #define MAKE_AFTER_SLIDE_LISTENER(name,type,var) struct name : after_slide_lis< type > { void slided (type& s); }; name var; |
||
242 | #define SLIDED(scope,name,type) void scope::name::slided (type& s) |
||
243 | #define MAKE_START_SLIDE_LISTENER(name,type,var) struct name : start_slide_lis< type > { void start_slide (type& s); }; name var; |
||
244 | #define START_SLIDE(scope,name,type) void scope::name::start_slide (type& s) |
||
245 | |||
246 | #endif |