180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <draw.h>
480ee5cbfSDavid du Colombier #include <thread.h>
580ee5cbfSDavid du Colombier #include <mouse.h>
680ee5cbfSDavid du Colombier #include <keyboard.h>
780ee5cbfSDavid du Colombier #include <control.h>
880ee5cbfSDavid du Colombier
980ee5cbfSDavid du Colombier typedef struct Slider Slider;
1080ee5cbfSDavid du Colombier
1180ee5cbfSDavid du Colombier struct Slider
1280ee5cbfSDavid du Colombier {
1380ee5cbfSDavid du Colombier Control;
1480ee5cbfSDavid du Colombier int border;
1580ee5cbfSDavid du Colombier CImage *image;
1680ee5cbfSDavid du Colombier CImage *textcolor;
1780ee5cbfSDavid du Colombier CImage *bordercolor;
1880ee5cbfSDavid du Colombier CImage *indicatorcolor;
1980ee5cbfSDavid du Colombier int absolute;
2080ee5cbfSDavid du Colombier int max;
2180ee5cbfSDavid du Colombier int vis;
2280ee5cbfSDavid du Colombier int value;
2380ee5cbfSDavid du Colombier int clamphigh;
2480ee5cbfSDavid du Colombier int clamplow;
2580ee5cbfSDavid du Colombier int horizontal;
2680ee5cbfSDavid du Colombier int lastbut;
2780ee5cbfSDavid du Colombier };
2880ee5cbfSDavid du Colombier
2980ee5cbfSDavid du Colombier enum{
3080ee5cbfSDavid du Colombier EAbsolute,
3180ee5cbfSDavid du Colombier EBorder,
3280ee5cbfSDavid du Colombier EBordercolor,
3380ee5cbfSDavid du Colombier EClamp,
3480ee5cbfSDavid du Colombier EFocus,
3580ee5cbfSDavid du Colombier EFormat,
36*9a747e4fSDavid du Colombier EHide,
3780ee5cbfSDavid du Colombier EImage,
3880ee5cbfSDavid du Colombier EIndicatorcolor,
3980ee5cbfSDavid du Colombier EMax,
4080ee5cbfSDavid du Colombier EOrient,
4180ee5cbfSDavid du Colombier ERect,
42*9a747e4fSDavid du Colombier EReveal,
4380ee5cbfSDavid du Colombier EShow,
44*9a747e4fSDavid du Colombier ESize,
4580ee5cbfSDavid du Colombier EValue,
4680ee5cbfSDavid du Colombier EVis,
4780ee5cbfSDavid du Colombier };
4880ee5cbfSDavid du Colombier
4980ee5cbfSDavid du Colombier static char *cmds[] = {
5080ee5cbfSDavid du Colombier [EAbsolute] = "absolute",
5180ee5cbfSDavid du Colombier [EBorder] = "border",
5280ee5cbfSDavid du Colombier [EBordercolor] = "bordercolor",
5380ee5cbfSDavid du Colombier [EClamp] = "clamp",
5480ee5cbfSDavid du Colombier [EFocus] = "focus",
5580ee5cbfSDavid du Colombier [EFormat] = "format",
56*9a747e4fSDavid du Colombier [EHide] = "hide",
5780ee5cbfSDavid du Colombier [EImage] = "image",
5880ee5cbfSDavid du Colombier [EIndicatorcolor] = "indicatorcolor",
5980ee5cbfSDavid du Colombier [EMax] = "max",
6080ee5cbfSDavid du Colombier [EOrient] = "orient",
6180ee5cbfSDavid du Colombier [ERect] = "rect",
62*9a747e4fSDavid du Colombier [EReveal] = "reveal",
6380ee5cbfSDavid du Colombier [EShow] = "show",
64*9a747e4fSDavid du Colombier [ESize] = "size",
6580ee5cbfSDavid du Colombier [EValue] = "value",
6680ee5cbfSDavid du Colombier [EVis] = "vis",
6780ee5cbfSDavid du Colombier };
6880ee5cbfSDavid du Colombier
6980ee5cbfSDavid du Colombier static void
sliderfree(Control * c)70*9a747e4fSDavid du Colombier sliderfree(Control *c)
7180ee5cbfSDavid du Colombier {
7280ee5cbfSDavid du Colombier Slider *s;
7380ee5cbfSDavid du Colombier
74*9a747e4fSDavid du Colombier s = (Slider*)c;
7580ee5cbfSDavid du Colombier _putctlimage(s->image);
7680ee5cbfSDavid du Colombier _putctlimage(s->textcolor);
7780ee5cbfSDavid du Colombier _putctlimage(s->bordercolor);
7880ee5cbfSDavid du Colombier _putctlimage(s->indicatorcolor);
7980ee5cbfSDavid du Colombier }
8080ee5cbfSDavid du Colombier
8180ee5cbfSDavid du Colombier static void
slidershow(Slider * s)8280ee5cbfSDavid du Colombier slidershow(Slider *s)
8380ee5cbfSDavid du Colombier {
8480ee5cbfSDavid du Colombier Rectangle r, t;
8580ee5cbfSDavid du Colombier int l, h, d;
8680ee5cbfSDavid du Colombier
87*9a747e4fSDavid du Colombier if (s->hidden)
88*9a747e4fSDavid du Colombier return;
8980ee5cbfSDavid du Colombier r = s->rect;
9080ee5cbfSDavid du Colombier draw(s->screen, r, s->image->image, nil, s->image->image->r.min);
9180ee5cbfSDavid du Colombier if(s->border > 0){
9280ee5cbfSDavid du Colombier border(s->screen, r, s->border, s->bordercolor->image, s->bordercolor->image->r.min);
9380ee5cbfSDavid du Colombier r = insetrect(r, s->border);
9480ee5cbfSDavid du Colombier }
9580ee5cbfSDavid du Colombier if(s->max <= 0)
9680ee5cbfSDavid du Colombier return;
9780ee5cbfSDavid du Colombier if(s->horizontal)
9880ee5cbfSDavid du Colombier d = Dx(r);
9980ee5cbfSDavid du Colombier else
10080ee5cbfSDavid du Colombier d = Dy(r);
10180ee5cbfSDavid du Colombier l = muldiv(s->value, d, s->max);
10280ee5cbfSDavid du Colombier h = muldiv(s->value+s->vis, d, s->max);
10380ee5cbfSDavid du Colombier if(s->clamplow && s->clamphigh){
10480ee5cbfSDavid du Colombier l = 0;
10580ee5cbfSDavid du Colombier h = d;
10680ee5cbfSDavid du Colombier }else if(s->clamplow){
10780ee5cbfSDavid du Colombier h = l;
10880ee5cbfSDavid du Colombier l = 0;
10980ee5cbfSDavid du Colombier }else if(s->clamphigh)
11080ee5cbfSDavid du Colombier h = d;
11180ee5cbfSDavid du Colombier t = r;
11280ee5cbfSDavid du Colombier if(s->horizontal){
11380ee5cbfSDavid du Colombier r.max.x = r.min.x+h;
11480ee5cbfSDavid du Colombier r.min.x += l;
11580ee5cbfSDavid du Colombier }else{
11680ee5cbfSDavid du Colombier r.max.y = r.min.y+h;
11780ee5cbfSDavid du Colombier r.min.y += l;
11880ee5cbfSDavid du Colombier }
11980ee5cbfSDavid du Colombier if(rectclip(&r, t))
12080ee5cbfSDavid du Colombier draw(s->screen, r, s->indicatorcolor->image, nil, s->indicatorcolor->image->r.min);
12180ee5cbfSDavid du Colombier flushimage(display, 1);
12280ee5cbfSDavid du Colombier }
12380ee5cbfSDavid du Colombier
12480ee5cbfSDavid du Colombier static void
sliderctl(Control * c,CParse * cp)125*9a747e4fSDavid du Colombier sliderctl(Control *c, CParse *cp)
12680ee5cbfSDavid du Colombier {
12780ee5cbfSDavid du Colombier int cmd, prev;
12880ee5cbfSDavid du Colombier Rectangle r;
12980ee5cbfSDavid du Colombier Slider *s;
13080ee5cbfSDavid du Colombier
13180ee5cbfSDavid du Colombier s = (Slider*)c;
132*9a747e4fSDavid du Colombier cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
13380ee5cbfSDavid du Colombier switch(cmd){
13480ee5cbfSDavid du Colombier default:
135*9a747e4fSDavid du Colombier ctlerror("%q: unrecognized message '%s'", s->name, cp->str);
13680ee5cbfSDavid du Colombier break;
13780ee5cbfSDavid du Colombier case EAbsolute:
138*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
139*9a747e4fSDavid du Colombier s->absolute = cp->iargs[1];
14080ee5cbfSDavid du Colombier break;
14180ee5cbfSDavid du Colombier case EBorder:
142*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
143*9a747e4fSDavid du Colombier if(cp->iargs[1] < 0)
144*9a747e4fSDavid du Colombier ctlerror("%q: bad border: %c", s->name, cp->str);
145*9a747e4fSDavid du Colombier s->border = cp->iargs[1];
14680ee5cbfSDavid du Colombier break;
14780ee5cbfSDavid du Colombier case EBordercolor:
148*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
149*9a747e4fSDavid du Colombier _setctlimage(s, &s->bordercolor, cp->args[1]);
15080ee5cbfSDavid du Colombier break;
15180ee5cbfSDavid du Colombier case EClamp:
152*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 3);
153*9a747e4fSDavid du Colombier if(strcmp(cp->args[1], "high") == 0)
154*9a747e4fSDavid du Colombier s->clamphigh = cp->iargs[2];
155*9a747e4fSDavid du Colombier else if(strcmp(cp->args[1], "low") == 0)
156*9a747e4fSDavid du Colombier s->clamplow = cp->iargs[2];
15780ee5cbfSDavid du Colombier else
158*9a747e4fSDavid du Colombier ctlerror("%q: unrecognized clamp: %s", s->name, cp->str);
15980ee5cbfSDavid du Colombier break;
16080ee5cbfSDavid du Colombier case EFocus:
16180ee5cbfSDavid du Colombier /* ignore focus change */
16280ee5cbfSDavid du Colombier break;
16380ee5cbfSDavid du Colombier case EFormat:
164*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
165*9a747e4fSDavid du Colombier s->format = ctlstrdup(cp->args[1]);
166*9a747e4fSDavid du Colombier break;
167*9a747e4fSDavid du Colombier case EHide:
168*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 1);
169*9a747e4fSDavid du Colombier s->hidden = 1;
17080ee5cbfSDavid du Colombier break;
17180ee5cbfSDavid du Colombier case EImage:
172*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
173*9a747e4fSDavid du Colombier _setctlimage(s, &s->image, cp->args[1]);
17480ee5cbfSDavid du Colombier break;
17580ee5cbfSDavid du Colombier case EIndicatorcolor:
176*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
177*9a747e4fSDavid du Colombier _setctlimage(s, &s->indicatorcolor, cp->args[1]);
17880ee5cbfSDavid du Colombier break;
17980ee5cbfSDavid du Colombier case EMax:
180*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
181*9a747e4fSDavid du Colombier if(cp->iargs[1] < 0)
182*9a747e4fSDavid du Colombier ctlerror("%q: negative max value: %s", s->name, cp->str);
183*9a747e4fSDavid du Colombier if(s->max != cp->iargs[1]){
184*9a747e4fSDavid du Colombier s->max = cp->iargs[1];
18580ee5cbfSDavid du Colombier slidershow(s);
18680ee5cbfSDavid du Colombier }
18780ee5cbfSDavid du Colombier break;
18880ee5cbfSDavid du Colombier case EOrient:
189*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
19080ee5cbfSDavid du Colombier prev = s->horizontal;
191*9a747e4fSDavid du Colombier if(strncmp(cp->args[1], "hor", 3) == 0)
19280ee5cbfSDavid du Colombier s->horizontal = 1;
193*9a747e4fSDavid du Colombier else if(strncmp(cp->args[1], "ver", 3) == 0)
19480ee5cbfSDavid du Colombier s->horizontal = 0;
19580ee5cbfSDavid du Colombier else
196*9a747e4fSDavid du Colombier ctlerror("%q: unrecognized orientation: %s", s->name, cp->str);
19780ee5cbfSDavid du Colombier if(s->horizontal != prev)
19880ee5cbfSDavid du Colombier slidershow(s);
19980ee5cbfSDavid du Colombier break;
20080ee5cbfSDavid du Colombier case ERect:
201*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 5);
202*9a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
203*9a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
204*9a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
205*9a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
20680ee5cbfSDavid du Colombier if(Dx(r)<=0 || Dy(r)<=0)
207*9a747e4fSDavid du Colombier ctlerror("%q: bad rectangle: %s", s->name, cp->str);
20880ee5cbfSDavid du Colombier s->rect = r;
20980ee5cbfSDavid du Colombier break;
210*9a747e4fSDavid du Colombier case EReveal:
211*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 1);
212*9a747e4fSDavid du Colombier s->hidden = 0;
21380ee5cbfSDavid du Colombier slidershow(s);
21480ee5cbfSDavid du Colombier break;
215*9a747e4fSDavid du Colombier case EShow:
216*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 1);
217*9a747e4fSDavid du Colombier slidershow(s);
218*9a747e4fSDavid du Colombier break;
219*9a747e4fSDavid du Colombier case ESize:
220*9a747e4fSDavid du Colombier if (cp->nargs == 3)
221*9a747e4fSDavid du Colombier r.max = Pt(0x7fffffff, 0x7fffffff);
222*9a747e4fSDavid du Colombier else{
223*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 5);
224*9a747e4fSDavid du Colombier r.max.x = cp->iargs[3];
225*9a747e4fSDavid du Colombier r.max.y = cp->iargs[4];
226*9a747e4fSDavid du Colombier }
227*9a747e4fSDavid du Colombier r.min.x = cp->iargs[1];
228*9a747e4fSDavid du Colombier r.min.y = cp->iargs[2];
229*9a747e4fSDavid du Colombier 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*9a747e4fSDavid du Colombier ctlerror("%q: bad sizes: %s", s->name, cp->str);
231*9a747e4fSDavid du Colombier s->size.min = r.min;
232*9a747e4fSDavid du Colombier s->size.max = r.max;
233*9a747e4fSDavid du Colombier break;
23480ee5cbfSDavid du Colombier case EValue:
235*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
236*9a747e4fSDavid du Colombier if(s->value != cp->iargs[1]){
237*9a747e4fSDavid du Colombier s->value = cp->iargs[1];
23880ee5cbfSDavid du Colombier slidershow(s);
23980ee5cbfSDavid du Colombier }
24080ee5cbfSDavid du Colombier break;
24180ee5cbfSDavid du Colombier case EVis:
242*9a747e4fSDavid du Colombier _ctlargcount(s, cp, 2);
243*9a747e4fSDavid du Colombier if(s->vis != cp->iargs[1]){
244*9a747e4fSDavid du Colombier s->vis = cp->iargs[1];
24580ee5cbfSDavid du Colombier slidershow(s);
24680ee5cbfSDavid du Colombier }
24780ee5cbfSDavid du Colombier break;
24880ee5cbfSDavid du Colombier }
24980ee5cbfSDavid du Colombier }
25080ee5cbfSDavid du Colombier
25180ee5cbfSDavid du Colombier static void
slidermouse(Control * c,Mouse * m)252*9a747e4fSDavid du Colombier slidermouse(Control *c, Mouse *m)
25380ee5cbfSDavid du Colombier {
25480ee5cbfSDavid du Colombier Rectangle r;
25580ee5cbfSDavid du Colombier int v, l, d, b;
256*9a747e4fSDavid du Colombier Slider *s;
25780ee5cbfSDavid du Colombier
258*9a747e4fSDavid du Colombier s =(Slider*)c;
259*9a747e4fSDavid du Colombier if(m->buttons == 0){
26080ee5cbfSDavid du Colombier /* buttons now up */
26180ee5cbfSDavid du Colombier s->lastbut = 0;
26280ee5cbfSDavid du Colombier return;
26380ee5cbfSDavid du Colombier }
264*9a747e4fSDavid du Colombier if(!s->absolute && s->lastbut==m->buttons && s->lastbut!=2){
26580ee5cbfSDavid du Colombier /* clicks only on buttons 1 & 3; continuous motion on 2 (or when absolute) */
26680ee5cbfSDavid du Colombier return;
26780ee5cbfSDavid du Colombier }
268*9a747e4fSDavid du Colombier if(s->lastbut!=0 && m->buttons!=s->lastbut){
26980ee5cbfSDavid du Colombier /* buttons down have changed; wait for button up */
27080ee5cbfSDavid du Colombier return;
27180ee5cbfSDavid du Colombier }
272*9a747e4fSDavid du Colombier s->lastbut = m->buttons;
27380ee5cbfSDavid du Colombier
27480ee5cbfSDavid du Colombier r = insetrect(s->rect, s->border);
27580ee5cbfSDavid du Colombier if(s->horizontal){
276*9a747e4fSDavid du Colombier v = m->xy.x - r.min.x;
27780ee5cbfSDavid du Colombier d = Dx(r);
27880ee5cbfSDavid du Colombier }else{
279*9a747e4fSDavid du Colombier v = m->xy.y - r.min.y;
28080ee5cbfSDavid du Colombier d = Dy(r);
28180ee5cbfSDavid du Colombier }
28280ee5cbfSDavid du Colombier if(s->absolute)
28380ee5cbfSDavid du Colombier b = 2;
28480ee5cbfSDavid du Colombier else
285*9a747e4fSDavid du Colombier b = m->buttons;
28680ee5cbfSDavid du Colombier switch(b){
28780ee5cbfSDavid du Colombier default:
28880ee5cbfSDavid du Colombier return;
28980ee5cbfSDavid du Colombier case 1:
29080ee5cbfSDavid du Colombier l = s->value - muldiv(v, s->vis, d);
29180ee5cbfSDavid du Colombier break;
29280ee5cbfSDavid du Colombier case 2:
29380ee5cbfSDavid du Colombier l = muldiv(v, s->max, d);
29480ee5cbfSDavid du Colombier break;
29580ee5cbfSDavid du Colombier case 4:
29680ee5cbfSDavid du Colombier l = s->value + muldiv(v, s->vis, d);
29780ee5cbfSDavid du Colombier break;
29880ee5cbfSDavid du Colombier }
29980ee5cbfSDavid du Colombier if(l < 0)
30080ee5cbfSDavid du Colombier l = 0;
30180ee5cbfSDavid du Colombier if(l > s->max)
30280ee5cbfSDavid du Colombier l = s->max;
30380ee5cbfSDavid du Colombier if(l != s->value){
30480ee5cbfSDavid du Colombier s->value = l;
305*9a747e4fSDavid du Colombier chanprint(s->event, s->format, s->name, s->value);
30680ee5cbfSDavid du Colombier slidershow(s);
30780ee5cbfSDavid du Colombier }
30880ee5cbfSDavid du Colombier }
309*9a747e4fSDavid du Colombier
310*9a747e4fSDavid du Colombier Control*
createslider(Controlset * cs,char * name)311*9a747e4fSDavid du Colombier createslider(Controlset *cs, char *name)
312*9a747e4fSDavid du Colombier {
313*9a747e4fSDavid du Colombier Slider *s;
314*9a747e4fSDavid du Colombier
315*9a747e4fSDavid du Colombier s = (Slider*)_createctl(cs, "slider", sizeof(Slider), name);
316*9a747e4fSDavid du Colombier s->image = _getctlimage("white");
317*9a747e4fSDavid du Colombier s->textcolor = _getctlimage("black");
318*9a747e4fSDavid du Colombier s->bordercolor = _getctlimage("black");
319*9a747e4fSDavid du Colombier s->indicatorcolor = _getctlimage("black");
320*9a747e4fSDavid du Colombier s->format = ctlstrdup("%q: value %d");
321*9a747e4fSDavid du Colombier s->border = 0;
322*9a747e4fSDavid du Colombier s->mouse = slidermouse;
323*9a747e4fSDavid du Colombier s->ctl = sliderctl;
324*9a747e4fSDavid du Colombier s->exit = sliderfree;
325*9a747e4fSDavid du Colombier return (Control*)s;
326*9a747e4fSDavid du Colombier }
327