slider.c 6.3 KB

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