button.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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 Button Button;
  9. struct Button
  10. {
  11. Control;
  12. CImage *image;
  13. CImage *mask;
  14. CImage *light;
  15. CImage *pale;
  16. CImage *bordercolor;
  17. int pressed;
  18. int lastbut;
  19. int lastshow;
  20. int border;
  21. int align;
  22. int off;
  23. int prepress;
  24. };
  25. enum{
  26. EAlign,
  27. EBorder,
  28. EBordercolor,
  29. EFocus,
  30. EFormat,
  31. EHide,
  32. EImage,
  33. ELight,
  34. EMask,
  35. EPale,
  36. ERect,
  37. EReveal,
  38. EShow,
  39. ESize,
  40. EValue,
  41. };
  42. static char *cmds[] = {
  43. [EAlign] = "align",
  44. [EBorder] = "border",
  45. [EBordercolor] = "bordercolor",
  46. [EFocus] = "focus",
  47. [EFormat] = "format",
  48. [EHide] = "hide",
  49. [EImage] = "image",
  50. [ELight] = "light",
  51. [EMask] = "mask",
  52. [EPale] = "pale",
  53. [ERect] = "rect",
  54. [EReveal] = "reveal",
  55. [EShow] = "show",
  56. [ESize] = "size",
  57. [EValue] = "value",
  58. nil
  59. };
  60. static void
  61. buttonfree(Control *c)
  62. {
  63. Button *b;
  64. b = (Button *)c;
  65. _putctlimage(b->image);
  66. _putctlimage(b->mask);
  67. _putctlimage(b->light);
  68. _putctlimage(b->pale);
  69. _putctlimage(b->bordercolor);
  70. }
  71. static void
  72. buttonshow(Button *b)
  73. {
  74. Rectangle r;
  75. if (b->hidden)
  76. return;
  77. r = b->rect;
  78. if(b->border > 0){
  79. border(b->screen, r, b->border, b->bordercolor->image, ZP);
  80. r = insetrect(b->rect, b->border);
  81. }
  82. draw(b->screen, r, b->image->image, nil, b->image->image->r.min);
  83. if(b->off)
  84. draw(b->screen, r, b->pale->image, b->mask->image, b->mask->image->r.min);
  85. else if(b->pressed)
  86. draw(b->screen, r, b->light->image, b->mask->image, b->mask->image->r.min);
  87. b->lastshow = b->pressed;
  88. flushimage(display, 1);
  89. }
  90. static void
  91. buttonmouse(Control *c, Mouse *m)
  92. {
  93. Button *b;
  94. b = (Button*)c;
  95. if(m->buttons&7) {
  96. if (ptinrect(m->xy,b->rect)) {
  97. if (b->off) {
  98. b->off = 0;
  99. buttonshow(b);
  100. }
  101. } else {
  102. if (!b->off) {
  103. b->off = 1;
  104. buttonshow(b);
  105. }
  106. }
  107. }
  108. if((m->buttons&7) != b->lastbut){
  109. if(m->buttons & 7){
  110. b->prepress = b->pressed;
  111. if (b->pressed)
  112. b->pressed = 0;
  113. else
  114. b->pressed = m->buttons & 7;
  115. buttonshow(b);
  116. }else /* generate event on button up */
  117. if (ptinrect(m->xy,b->rect))
  118. chanprint(b->event, b->format, b->name, b->pressed);
  119. else {
  120. b->off = 0;
  121. b->pressed = b->prepress;
  122. buttonshow(b);
  123. }
  124. }
  125. b->lastbut = m->buttons & 7;
  126. }
  127. static void
  128. buttonctl(Control *c, CParse *cp)
  129. {
  130. int cmd;
  131. Rectangle r;
  132. Button *b;
  133. b = (Button*)c;
  134. cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
  135. switch(cmd){
  136. default:
  137. ctlerror("%q: unrecognized message '%s'", b->name, cp->str);
  138. break;
  139. case EAlign:
  140. _ctlargcount(b, cp, 2);
  141. b->align = _ctlalignment(cp->args[1]);
  142. b->lastshow = -1; /* force redraw */
  143. break;
  144. case EBorder:
  145. _ctlargcount(b, cp, 2);
  146. b->border = cp->iargs[1];
  147. b->lastshow = -1; /* force redraw */
  148. break;
  149. case EBordercolor:
  150. _ctlargcount(b, cp, 2);
  151. _setctlimage(b, &b->bordercolor, cp->args[1]);
  152. b->lastshow = -1; /* force redraw */
  153. break;
  154. case EFocus:
  155. /* ignore focus change */
  156. break;
  157. case EFormat:
  158. _ctlargcount(b, cp, 2);
  159. b->format = ctlstrdup(cp->args[1]);
  160. break;
  161. case EHide:
  162. _ctlargcount(b, cp, 1);
  163. b->hidden = 1;
  164. break;
  165. case EImage:
  166. _ctlargcount(b, cp, 2);
  167. _setctlimage(b, &b->image, cp->args[1]);
  168. b->lastshow = -1; /* force redraw */
  169. break;
  170. case ELight:
  171. _ctlargcount(b, cp, 2);
  172. _setctlimage(b, &b->light, cp->args[1]);
  173. b->lastshow = -1; /* force redraw */
  174. break;
  175. case EMask:
  176. _ctlargcount(b, cp, 2);
  177. _setctlimage(b, &b->mask, cp->args[1]);
  178. b->lastshow = -1; /* force redraw */
  179. break;
  180. case EPale:
  181. _ctlargcount(b, cp, 2);
  182. _setctlimage(b, &b->pale, cp->args[1]);
  183. b->lastshow = -1; /* force redraw */
  184. break;
  185. case ERect:
  186. _ctlargcount(b, cp, 5);
  187. r.min.x = cp->iargs[1];
  188. r.min.y = cp->iargs[2];
  189. r.max.x = cp->iargs[3];
  190. r.max.y = cp->iargs[4];
  191. if(Dx(r)<0 || Dy(r)<0)
  192. ctlerror("%q: bad rectangle: %s", b->name, cp->str);
  193. b->rect = r;
  194. b->lastshow = -1; /* force redraw */
  195. break;
  196. case EReveal:
  197. _ctlargcount(b, cp, 1);
  198. b->hidden = 0;
  199. buttonshow(b);
  200. break;
  201. case EShow:
  202. _ctlargcount(b, cp, 1);
  203. buttonshow(b);
  204. break;
  205. case ESize:
  206. if (cp->nargs == 3)
  207. r.max = Pt(0x7fffffff, 0x7fffffff);
  208. else{
  209. _ctlargcount(b, cp, 5);
  210. r.max.x = cp->iargs[3];
  211. r.max.y = cp->iargs[4];
  212. }
  213. r.min.x = cp->iargs[1];
  214. r.min.y = cp->iargs[2];
  215. 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)
  216. ctlerror("%q: bad sizes: %s", b->name, cp->str);
  217. b->size.min = r.min;
  218. b->size.max = r.max;
  219. break;
  220. case EValue:
  221. _ctlargcount(b, cp, 2);
  222. if((cp->iargs[1]!=0) != b->pressed){
  223. b->pressed ^= 1;
  224. buttonshow(b);
  225. }
  226. break;
  227. }
  228. }
  229. Control*
  230. createbutton(Controlset *cs, char *name)
  231. {
  232. Button *b;
  233. b = (Button*)_createctl(cs, "button", sizeof(Button), name);
  234. b->image = _getctlimage("white");
  235. b->mask = _getctlimage("opaque");
  236. b->light = _getctlimage("yellow");
  237. b->pale = _getctlimage("paleyellow");
  238. b->bordercolor = _getctlimage("black");
  239. b->format = ctlstrdup("%q: value %d");
  240. b->lastshow = -1;
  241. b->border = 0;
  242. b->align = Aupperleft;
  243. b->ctl = buttonctl;
  244. b->mouse = buttonmouse;
  245. b->key = nil;
  246. b->exit = buttonfree;
  247. b->off = 0;
  248. b->prepress = 0;
  249. return (Control*)b;
  250. }