1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // classes slider_ctrl_impl, slider_ctrl
17 //
18 //----------------------------------------------------------------------------
19 
20 #include <string.h>
21 #include <stdio.h>
22 #include "ctrl/agg_slider_ctrl.h"
23 
24 namespace agg
25 {
26 
27     //------------------------------------------------------------------------
slider_ctrl_impl(double x1,double y1,double x2,double y2,bool flip_y)28     slider_ctrl_impl::slider_ctrl_impl(double x1, double y1,
29                                        double x2, double y2, bool flip_y) :
30         ctrl(x1, y1, x2, y2, flip_y),
31         m_border_width(1.0),
32         m_border_extra((y2 - y1) / 2),
33         m_text_thickness(1.0),
34         m_pdx(0.0),
35         m_mouse_move(false),
36         m_value(0.5),
37         m_preview_value(0.5),
38         m_min(0.0),
39         m_max(1.0),
40         m_num_steps(0),
41         m_descending(false),
42         m_text_poly(m_text)
43     {
44         m_label[0] = 0;
45         calc_box();
46     }
47 
48 
49     //------------------------------------------------------------------------
calc_box()50     void slider_ctrl_impl::calc_box()
51     {
52         m_xs1 = m_x1 + m_border_width;
53         m_ys1 = m_y1 + m_border_width;
54         m_xs2 = m_x2 - m_border_width;
55         m_ys2 = m_y2 - m_border_width;
56     }
57 
58 
59     //------------------------------------------------------------------------
normalize_value(bool preview_value_flag)60     bool slider_ctrl_impl::normalize_value(bool preview_value_flag)
61     {
62         bool ret = true;
63         if(m_num_steps)
64         {
65             int step = int(m_preview_value * m_num_steps + 0.5);
66             ret = m_value != step / double(m_num_steps);
67             m_value = step / double(m_num_steps);
68         }
69         else
70         {
71             m_value = m_preview_value;
72         }
73 
74         if(preview_value_flag)
75         {
76             m_preview_value = m_value;
77         }
78         return ret;
79     }
80 
81 
82     //------------------------------------------------------------------------
border_width(double t,double extra)83     void slider_ctrl_impl::border_width(double t, double extra)
84     {
85         m_border_width = t;
86         m_border_extra = extra;
87         calc_box();
88     }
89 
90 
91     //------------------------------------------------------------------------
value(double value)92     void slider_ctrl_impl::value(double value)
93     {
94         m_preview_value = (value - m_min) / (m_max - m_min);
95         if(m_preview_value > 1.0) m_preview_value = 1.0;
96         if(m_preview_value < 0.0) m_preview_value = 0.0;
97         normalize_value(true);
98     }
99 
100     //------------------------------------------------------------------------
label(const char * fmt)101     void slider_ctrl_impl::label(const char* fmt)
102     {
103         m_label[0] = 0;
104         if(fmt)
105         {
106             unsigned len = strlen(fmt);
107             if(len > 63) len = 63;
108             memcpy(m_label, fmt, len);
109             m_label[len] = 0;
110         }
111     }
112 
113     //------------------------------------------------------------------------
rewind(unsigned idx)114     void slider_ctrl_impl::rewind(unsigned idx)
115     {
116         m_idx = idx;
117 
118         switch(idx)
119         {
120         default:
121 
122         case 0:                 // Background
123             m_vertex = 0;
124             m_vx[0] = m_x1 - m_border_extra;
125             m_vy[0] = m_y1 - m_border_extra;
126             m_vx[1] = m_x2 + m_border_extra;
127             m_vy[1] = m_y1 - m_border_extra;
128             m_vx[2] = m_x2 + m_border_extra;
129             m_vy[2] = m_y2 + m_border_extra;
130             m_vx[3] = m_x1 - m_border_extra;
131             m_vy[3] = m_y2 + m_border_extra;
132             break;
133 
134         case 1:                 // Triangle
135             m_vertex = 0;
136             if(m_descending)
137             {
138                 m_vx[0] = m_x1;
139                 m_vy[0] = m_y1;
140                 m_vx[1] = m_x2;
141                 m_vy[1] = m_y1;
142                 m_vx[2] = m_x1;
143                 m_vy[2] = m_y2;
144                 m_vx[3] = m_x1;
145                 m_vy[3] = m_y1;
146             }
147             else
148             {
149                 m_vx[0] = m_x1;
150                 m_vy[0] = m_y1;
151                 m_vx[1] = m_x2;
152                 m_vy[1] = m_y1;
153                 m_vx[2] = m_x2;
154                 m_vy[2] = m_y2;
155                 m_vx[3] = m_x1;
156                 m_vy[3] = m_y1;
157             }
158             break;
159 
160         case 2:
161             m_text.text(m_label);
162             if(m_label[0])
163             {
164                 char buf[256];
165                 sprintf(buf, m_label, value());
166                 m_text.text(buf);
167             }
168             m_text.start_point(m_x1, m_y1);
169             m_text.size((m_y2 - m_y1) * 1.2, m_y2 - m_y1);
170             m_text_poly.width(m_text_thickness);
171             m_text_poly.line_join(round_join);
172             m_text_poly.line_cap(round_cap);
173             m_text_poly.rewind(0);
174             break;
175 
176         case 3:                 // pointer preview
177             m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_preview_value,
178                            (m_ys1 + m_ys2) / 2.0,
179                            m_y2 - m_y1,
180                            m_y2 - m_y1,
181                            32);
182             break;
183 
184 
185         case 4:                 // pointer
186             normalize_value(false);
187             m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value,
188                            (m_ys1 + m_ys2) / 2.0,
189                            m_y2 - m_y1,
190                            m_y2 - m_y1,
191                            32);
192             m_ellipse.rewind(0);
193             break;
194 
195         case 5:
196             m_storage.remove_all();
197             if(m_num_steps)
198             {
199                 unsigned i;
200                 double d = (m_xs2 - m_xs1) / m_num_steps;
201                 if(d > 0.004) d = 0.004;
202                 for(i = 0; i < m_num_steps + 1; i++)
203                 {
204                     double x = m_xs1 + (m_xs2 - m_xs1) * i / m_num_steps;
205                     m_storage.move_to(x, m_y1);
206                     m_storage.line_to(x - d * (m_x2 - m_x1), m_y1 - m_border_extra);
207                     m_storage.line_to(x + d * (m_x2 - m_x1), m_y1 - m_border_extra);
208                 }
209             }
210         }
211     }
212 
213 
214     //------------------------------------------------------------------------
vertex(double * x,double * y)215     unsigned slider_ctrl_impl::vertex(double* x, double* y)
216     {
217         unsigned cmd = path_cmd_line_to;
218         switch(m_idx)
219         {
220         case 0:
221             if(m_vertex == 0) cmd = path_cmd_move_to;
222             if(m_vertex >= 4) cmd = path_cmd_stop;
223             *x = m_vx[m_vertex];
224             *y = m_vy[m_vertex];
225             m_vertex++;
226             break;
227 
228         case 1:
229             if(m_vertex == 0) cmd = path_cmd_move_to;
230             if(m_vertex >= 4) cmd = path_cmd_stop;
231             *x = m_vx[m_vertex];
232             *y = m_vy[m_vertex];
233              m_vertex++;
234             break;
235 
236         case 2:
237             cmd = m_text_poly.vertex(x, y);
238             break;
239 
240         case 3:
241         case 4:
242             cmd = m_ellipse.vertex(x, y);
243             break;
244 
245         case 5:
246             cmd = m_storage.vertex(x, y);
247             break;
248 
249         default:
250             cmd = path_cmd_stop;
251             break;
252         }
253 
254         if(!is_stop(cmd))
255         {
256             transform_xy(x, y);
257         }
258 
259         return cmd;
260     }
261 
262 
263 
264     //------------------------------------------------------------------------
in_rect(double x,double y) const265     bool slider_ctrl_impl::in_rect(double x, double y) const
266     {
267         inverse_transform_xy(&x, &y);
268         return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
269     }
270 
271 
272     //------------------------------------------------------------------------
on_mouse_button_down(double x,double y)273     bool slider_ctrl_impl::on_mouse_button_down(double x, double y)
274     {
275         inverse_transform_xy(&x, &y);
276 
277         double xp = m_xs1 + (m_xs2 - m_xs1) * m_value;
278         double yp = (m_ys1 + m_ys2) / 2.0;
279 
280         if(calc_distance(x, y, xp, yp) <= m_y2 - m_y1)
281         {
282             m_pdx = xp - x;
283             m_mouse_move = true;
284             return true;
285         }
286         return false;
287     }
288 
289 
290     //------------------------------------------------------------------------
on_mouse_move(double x,double y,bool button_flag)291     bool slider_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
292     {
293         inverse_transform_xy(&x, &y);
294         if(!button_flag)
295         {
296             on_mouse_button_up(x, y);
297             return false;
298         }
299 
300         if(m_mouse_move)
301         {
302             double xp = x + m_pdx;
303             m_preview_value = (xp - m_xs1) / (m_xs2 - m_xs1);
304             if(m_preview_value < 0.0) m_preview_value = 0.0;
305             if(m_preview_value > 1.0) m_preview_value = 1.0;
306             return true;
307         }
308         return false;
309     }
310 
311 
312     //------------------------------------------------------------------------
on_mouse_button_up(double,double)313     bool slider_ctrl_impl::on_mouse_button_up(double, double)
314     {
315         m_mouse_move = false;
316         normalize_value(true);
317         return true;
318     }
319 
320 
321     //------------------------------------------------------------------------
on_arrow_keys(bool left,bool right,bool down,bool up)322     bool slider_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
323     {
324         double d = 0.005;
325         if(m_num_steps)
326         {
327             d = 1.0 / m_num_steps;
328         }
329 
330         if(right || up)
331         {
332             m_preview_value += d;
333             if(m_preview_value > 1.0) m_preview_value = 1.0;
334             normalize_value(true);
335             return true;
336         }
337 
338         if(left || down)
339         {
340             m_preview_value -= d;
341             if(m_preview_value < 0.0) m_preview_value = 0.0;
342             normalize_value(true);
343             return true;
344         }
345         return false;
346     }
347 
348 }
349 
350