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