1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <mouse.h> 6 #include <keyboard.h> 7 #include <control.h> 8 9 typedef struct Slider Slider; 10 11 struct Slider 12 { 13 Control; 14 int border; 15 CImage *image; 16 CImage *textcolor; 17 CImage *bordercolor; 18 CImage *indicatorcolor; 19 int absolute; 20 int max; 21 int vis; 22 int value; 23 int clamphigh; 24 int clamplow; 25 int horizontal; 26 int lastbut; 27 }; 28 29 enum{ 30 EAbsolute, 31 EBorder, 32 EBordercolor, 33 EClamp, 34 EFocus, 35 EFormat, 36 EHide, 37 EImage, 38 EIndicatorcolor, 39 EMax, 40 EOrient, 41 ERect, 42 EReveal, 43 EShow, 44 ESize, 45 EValue, 46 EVis, 47 }; 48 49 static char *cmds[] = { 50 [EAbsolute] = "absolute", 51 [EBorder] = "border", 52 [EBordercolor] = "bordercolor", 53 [EClamp] = "clamp", 54 [EFocus] = "focus", 55 [EFormat] = "format", 56 [EHide] = "hide", 57 [EImage] = "image", 58 [EIndicatorcolor] = "indicatorcolor", 59 [EMax] = "max", 60 [EOrient] = "orient", 61 [ERect] = "rect", 62 [EReveal] = "reveal", 63 [EShow] = "show", 64 [ESize] = "size", 65 [EValue] = "value", 66 [EVis] = "vis", 67 }; 68 69 static void 70 sliderfree(Control *c) 71 { 72 Slider *s; 73 74 s = (Slider*)c; 75 _putctlimage(s->image); 76 _putctlimage(s->textcolor); 77 _putctlimage(s->bordercolor); 78 _putctlimage(s->indicatorcolor); 79 } 80 81 static void 82 slidershow(Slider *s) 83 { 84 Rectangle r, t; 85 int l, h, d; 86 87 if (s->hidden) 88 return; 89 r = s->rect; 90 draw(s->screen, r, s->image->image, nil, s->image->image->r.min); 91 if(s->border > 0){ 92 border(s->screen, r, s->border, s->bordercolor->image, s->bordercolor->image->r.min); 93 r = insetrect(r, s->border); 94 } 95 if(s->max <= 0) 96 return; 97 if(s->horizontal) 98 d = Dx(r); 99 else 100 d = Dy(r); 101 l = muldiv(s->value, d, s->max); 102 h = muldiv(s->value+s->vis, d, s->max); 103 if(s->clamplow && s->clamphigh){ 104 l = 0; 105 h = d; 106 }else if(s->clamplow){ 107 h = l; 108 l = 0; 109 }else if(s->clamphigh) 110 h = d; 111 t = r; 112 if(s->horizontal){ 113 r.max.x = r.min.x+h; 114 r.min.x += l; 115 }else{ 116 r.max.y = r.min.y+h; 117 r.min.y += l; 118 } 119 if(rectclip(&r, t)) 120 draw(s->screen, r, s->indicatorcolor->image, nil, s->indicatorcolor->image->r.min); 121 flushimage(display, 1); 122 } 123 124 static void 125 sliderctl(Control *c, CParse *cp) 126 { 127 int cmd, prev; 128 Rectangle r; 129 Slider *s; 130 131 s = (Slider*)c; 132 cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); 133 switch(cmd){ 134 default: 135 ctlerror("%q: unrecognized message '%s'", s->name, cp->str); 136 break; 137 case EAbsolute: 138 _ctlargcount(s, cp, 2); 139 s->absolute = cp->iargs[1]; 140 break; 141 case EBorder: 142 _ctlargcount(s, cp, 2); 143 if(cp->iargs[1] < 0) 144 ctlerror("%q: bad border: %c", s->name, cp->str); 145 s->border = cp->iargs[1]; 146 break; 147 case EBordercolor: 148 _ctlargcount(s, cp, 2); 149 _setctlimage(s, &s->bordercolor, cp->args[1]); 150 break; 151 case EClamp: 152 _ctlargcount(s, cp, 3); 153 if(strcmp(cp->args[1], "high") == 0) 154 s->clamphigh = cp->iargs[2]; 155 else if(strcmp(cp->args[1], "low") == 0) 156 s->clamplow = cp->iargs[2]; 157 else 158 ctlerror("%q: unrecognized clamp: %s", s->name, cp->str); 159 break; 160 case EFocus: 161 /* ignore focus change */ 162 break; 163 case EFormat: 164 _ctlargcount(s, cp, 2); 165 s->format = ctlstrdup(cp->args[1]); 166 break; 167 case EHide: 168 _ctlargcount(s, cp, 1); 169 s->hidden = 1; 170 break; 171 case EImage: 172 _ctlargcount(s, cp, 2); 173 _setctlimage(s, &s->image, cp->args[1]); 174 break; 175 case EIndicatorcolor: 176 _ctlargcount(s, cp, 2); 177 _setctlimage(s, &s->indicatorcolor, cp->args[1]); 178 break; 179 case EMax: 180 _ctlargcount(s, cp, 2); 181 if(cp->iargs[1] < 0) 182 ctlerror("%q: negative max value: %s", s->name, cp->str); 183 if(s->max != cp->iargs[1]){ 184 s->max = cp->iargs[1]; 185 slidershow(s); 186 } 187 break; 188 case EOrient: 189 _ctlargcount(s, cp, 2); 190 prev = s->horizontal; 191 if(strncmp(cp->args[1], "hor", 3) == 0) 192 s->horizontal = 1; 193 else if(strncmp(cp->args[1], "ver", 3) == 0) 194 s->horizontal = 0; 195 else 196 ctlerror("%q: unrecognized orientation: %s", s->name, cp->str); 197 if(s->horizontal != prev) 198 slidershow(s); 199 break; 200 case ERect: 201 _ctlargcount(s, cp, 5); 202 r.min.x = cp->iargs[1]; 203 r.min.y = cp->iargs[2]; 204 r.max.x = cp->iargs[3]; 205 r.max.y = cp->iargs[4]; 206 if(Dx(r)<=0 || Dy(r)<=0) 207 ctlerror("%q: bad rectangle: %s", s->name, cp->str); 208 s->rect = r; 209 break; 210 case EReveal: 211 _ctlargcount(s, cp, 1); 212 s->hidden = 0; 213 slidershow(s); 214 break; 215 case EShow: 216 _ctlargcount(s, cp, 1); 217 slidershow(s); 218 break; 219 case ESize: 220 if (cp->nargs == 3) 221 r.max = Pt(0x7fffffff, 0x7fffffff); 222 else{ 223 _ctlargcount(s, cp, 5); 224 r.max.x = cp->iargs[3]; 225 r.max.y = cp->iargs[4]; 226 } 227 r.min.x = cp->iargs[1]; 228 r.min.y = cp->iargs[2]; 229 if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y) 230 ctlerror("%q: bad sizes: %s", s->name, cp->str); 231 s->size.min = r.min; 232 s->size.max = r.max; 233 break; 234 case EValue: 235 _ctlargcount(s, cp, 2); 236 if(s->value != cp->iargs[1]){ 237 s->value = cp->iargs[1]; 238 slidershow(s); 239 } 240 break; 241 case EVis: 242 _ctlargcount(s, cp, 2); 243 if(s->vis != cp->iargs[1]){ 244 s->vis = cp->iargs[1]; 245 slidershow(s); 246 } 247 break; 248 } 249 } 250 251 static void 252 slidermouse(Control *c, Mouse *m) 253 { 254 Rectangle r; 255 int v, l, d, b; 256 Slider *s; 257 258 s =(Slider*)c; 259 if(m->buttons == 0){ 260 /* buttons now up */ 261 s->lastbut = 0; 262 return; 263 } 264 if(!s->absolute && s->lastbut==m->buttons && s->lastbut!=2){ 265 /* clicks only on buttons 1 & 3; continuous motion on 2 (or when absolute) */ 266 return; 267 } 268 if(s->lastbut!=0 && m->buttons!=s->lastbut){ 269 /* buttons down have changed; wait for button up */ 270 return; 271 } 272 s->lastbut = m->buttons; 273 274 r = insetrect(s->rect, s->border); 275 if(s->horizontal){ 276 v = m->xy.x - r.min.x; 277 d = Dx(r); 278 }else{ 279 v = m->xy.y - r.min.y; 280 d = Dy(r); 281 } 282 if(s->absolute) 283 b = 2; 284 else 285 b = m->buttons; 286 switch(b){ 287 default: 288 return; 289 case 1: 290 l = s->value - muldiv(v, s->vis, d); 291 break; 292 case 2: 293 l = muldiv(v, s->max, d); 294 break; 295 case 4: 296 l = s->value + muldiv(v, s->vis, d); 297 break; 298 } 299 if(l < 0) 300 l = 0; 301 if(l > s->max) 302 l = s->max; 303 if(l != s->value){ 304 s->value = l; 305 chanprint(s->event, s->format, s->name, s->value); 306 slidershow(s); 307 } 308 } 309 310 Control* 311 createslider(Controlset *cs, char *name) 312 { 313 Slider *s; 314 315 s = (Slider*)_createctl(cs, "slider", sizeof(Slider), name); 316 s->image = _getctlimage("white"); 317 s->textcolor = _getctlimage("black"); 318 s->bordercolor = _getctlimage("black"); 319 s->indicatorcolor = _getctlimage("black"); 320 s->format = ctlstrdup("%q: value %d"); 321 s->border = 0; 322 s->mouse = slidermouse; 323 s->ctl = sliderctl; 324 s->exit = sliderfree; 325 return (Control*)s; 326 } 327