slider.c 7.1 KB

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