diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libcontrol/slider.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libcontrol/slider.c')
-rwxr-xr-x | sys/src/libcontrol/slider.c | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/sys/src/libcontrol/slider.c b/sys/src/libcontrol/slider.c new file mode 100755 index 000000000..d7948cd2c --- /dev/null +++ b/sys/src/libcontrol/slider.c @@ -0,0 +1,326 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <thread.h> +#include <mouse.h> +#include <keyboard.h> +#include <control.h> + +typedef struct Slider Slider; + +struct Slider +{ + Control; + int border; + CImage *image; + CImage *textcolor; + CImage *bordercolor; + CImage *indicatorcolor; + int absolute; + int max; + int vis; + int value; + int clamphigh; + int clamplow; + int horizontal; + int lastbut; +}; + +enum{ + EAbsolute, + EBorder, + EBordercolor, + EClamp, + EFocus, + EFormat, + EHide, + EImage, + EIndicatorcolor, + EMax, + EOrient, + ERect, + EReveal, + EShow, + ESize, + EValue, + EVis, +}; + +static char *cmds[] = { + [EAbsolute] = "absolute", + [EBorder] = "border", + [EBordercolor] = "bordercolor", + [EClamp] = "clamp", + [EFocus] = "focus", + [EFormat] = "format", + [EHide] = "hide", + [EImage] = "image", + [EIndicatorcolor] = "indicatorcolor", + [EMax] = "max", + [EOrient] = "orient", + [ERect] = "rect", + [EReveal] = "reveal", + [EShow] = "show", + [ESize] = "size", + [EValue] = "value", + [EVis] = "vis", +}; + +static void +sliderfree(Control *c) +{ + Slider *s; + + s = (Slider*)c; + _putctlimage(s->image); + _putctlimage(s->textcolor); + _putctlimage(s->bordercolor); + _putctlimage(s->indicatorcolor); +} + +static void +slidershow(Slider *s) +{ + Rectangle r, t; + int l, h, d; + + if (s->hidden) + return; + r = s->rect; + draw(s->screen, r, s->image->image, nil, s->image->image->r.min); + if(s->border > 0){ + border(s->screen, r, s->border, s->bordercolor->image, s->bordercolor->image->r.min); + r = insetrect(r, s->border); + } + if(s->max <= 0) + return; + if(s->horizontal) + d = Dx(r); + else + d = Dy(r); + l = muldiv(s->value, d, s->max); + h = muldiv(s->value+s->vis, d, s->max); + if(s->clamplow && s->clamphigh){ + l = 0; + h = d; + }else if(s->clamplow){ + h = l; + l = 0; + }else if(s->clamphigh) + h = d; + t = r; + if(s->horizontal){ + r.max.x = r.min.x+h; + r.min.x += l; + }else{ + r.max.y = r.min.y+h; + r.min.y += l; + } + if(rectclip(&r, t)) + draw(s->screen, r, s->indicatorcolor->image, nil, s->indicatorcolor->image->r.min); + flushimage(display, 1); +} + +static void +sliderctl(Control *c, CParse *cp) +{ + int cmd, prev; + Rectangle r; + Slider *s; + + s = (Slider*)c; + cmd = _ctllookup(cp->args[0], cmds, nelem(cmds)); + switch(cmd){ + default: + ctlerror("%q: unrecognized message '%s'", s->name, cp->str); + break; + case EAbsolute: + _ctlargcount(s, cp, 2); + s->absolute = cp->iargs[1]; + break; + case EBorder: + _ctlargcount(s, cp, 2); + if(cp->iargs[1] < 0) + ctlerror("%q: bad border: %c", s->name, cp->str); + s->border = cp->iargs[1]; + break; + case EBordercolor: + _ctlargcount(s, cp, 2); + _setctlimage(s, &s->bordercolor, cp->args[1]); + break; + case EClamp: + _ctlargcount(s, cp, 3); + if(strcmp(cp->args[1], "high") == 0) + s->clamphigh = cp->iargs[2]; + else if(strcmp(cp->args[1], "low") == 0) + s->clamplow = cp->iargs[2]; + else + ctlerror("%q: unrecognized clamp: %s", s->name, cp->str); + break; + case EFocus: + /* ignore focus change */ + break; + case EFormat: + _ctlargcount(s, cp, 2); + s->format = ctlstrdup(cp->args[1]); + break; + case EHide: + _ctlargcount(s, cp, 1); + s->hidden = 1; + break; + case EImage: + _ctlargcount(s, cp, 2); + _setctlimage(s, &s->image, cp->args[1]); + break; + case EIndicatorcolor: + _ctlargcount(s, cp, 2); + _setctlimage(s, &s->indicatorcolor, cp->args[1]); + break; + case EMax: + _ctlargcount(s, cp, 2); + if(cp->iargs[1] < 0) + ctlerror("%q: negative max value: %s", s->name, cp->str); + if(s->max != cp->iargs[1]){ + s->max = cp->iargs[1]; + slidershow(s); + } + break; + case EOrient: + _ctlargcount(s, cp, 2); + prev = s->horizontal; + if(strncmp(cp->args[1], "hor", 3) == 0) + s->horizontal = 1; + else if(strncmp(cp->args[1], "ver", 3) == 0) + s->horizontal = 0; + else + ctlerror("%q: unrecognized orientation: %s", s->name, cp->str); + if(s->horizontal != prev) + slidershow(s); + break; + case ERect: + _ctlargcount(s, cp, 5); + r.min.x = cp->iargs[1]; + r.min.y = cp->iargs[2]; + r.max.x = cp->iargs[3]; + r.max.y = cp->iargs[4]; + if(Dx(r)<=0 || Dy(r)<=0) + ctlerror("%q: bad rectangle: %s", s->name, cp->str); + s->rect = r; + break; + case EReveal: + _ctlargcount(s, cp, 1); + s->hidden = 0; + slidershow(s); + break; + case EShow: + _ctlargcount(s, cp, 1); + slidershow(s); + break; + case ESize: + if (cp->nargs == 3) + r.max = Pt(0x7fffffff, 0x7fffffff); + else{ + _ctlargcount(s, cp, 5); + r.max.x = cp->iargs[3]; + r.max.y = cp->iargs[4]; + } + r.min.x = cp->iargs[1]; + r.min.y = cp->iargs[2]; + 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) + ctlerror("%q: bad sizes: %s", s->name, cp->str); + s->size.min = r.min; + s->size.max = r.max; + break; + case EValue: + _ctlargcount(s, cp, 2); + if(s->value != cp->iargs[1]){ + s->value = cp->iargs[1]; + slidershow(s); + } + break; + case EVis: + _ctlargcount(s, cp, 2); + if(s->vis != cp->iargs[1]){ + s->vis = cp->iargs[1]; + slidershow(s); + } + break; + } +} + +static void +slidermouse(Control *c, Mouse *m) +{ + Rectangle r; + int v, l, d, b; + Slider *s; + + s =(Slider*)c; + if(m->buttons == 0){ + /* buttons now up */ + s->lastbut = 0; + return; + } + if(!s->absolute && s->lastbut==m->buttons && s->lastbut!=2){ + /* clicks only on buttons 1 & 3; continuous motion on 2 (or when absolute) */ + return; + } + if(s->lastbut!=0 && m->buttons!=s->lastbut){ + /* buttons down have changed; wait for button up */ + return; + } + s->lastbut = m->buttons; + + r = insetrect(s->rect, s->border); + if(s->horizontal){ + v = m->xy.x - r.min.x; + d = Dx(r); + }else{ + v = m->xy.y - r.min.y; + d = Dy(r); + } + if(s->absolute) + b = 2; + else + b = m->buttons; + switch(b){ + default: + return; + case 1: + l = s->value - muldiv(v, s->vis, d); + break; + case 2: + l = muldiv(v, s->max, d); + break; + case 4: + l = s->value + muldiv(v, s->vis, d); + break; + } + if(l < 0) + l = 0; + if(l > s->max) + l = s->max; + if(l != s->value){ + s->value = l; + chanprint(s->event, s->format, s->name, s->value); + slidershow(s); + } +} + +Control* +createslider(Controlset *cs, char *name) +{ + Slider *s; + + s = (Slider*)_createctl(cs, "slider", sizeof(Slider), name); + s->image = _getctlimage("white"); + s->textcolor = _getctlimage("black"); + s->bordercolor = _getctlimage("black"); + s->indicatorcolor = _getctlimage("black"); + s->format = ctlstrdup("%q: value %d"); + s->border = 0; + s->mouse = slidermouse; + s->ctl = sliderctl; + s->exit = sliderfree; + return (Control*)s; +} |