button.c 4.4 KB

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