textbutton.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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 Textbutton Textbutton;
  17. struct Textbutton
  18. {
  19. Control Control;
  20. CFont *font;
  21. CImage *image;
  22. CImage *mask;
  23. CImage *light;
  24. CImage *bordercolor;
  25. CImage *textcolor;
  26. CImage *pressedtextcolor;
  27. CImage *paletextcolor;
  28. int pressed;
  29. int lastbut;
  30. int lastshow;
  31. char **line;
  32. int nline;
  33. int align;
  34. int border;
  35. int off;
  36. int showoff;
  37. int prepress;
  38. };
  39. enum{
  40. EAlign,
  41. EBorder,
  42. EBordercolor,
  43. EFocus,
  44. EFont,
  45. EFormat,
  46. EHide,
  47. EImage,
  48. ELight,
  49. EMask,
  50. EPaletextcolor,
  51. EPressedtextcolor,
  52. ERect,
  53. EReveal,
  54. EShow,
  55. ESize,
  56. EText,
  57. ETextcolor,
  58. EValue,
  59. };
  60. static char *cmds[] = {
  61. [EAlign] = "align",
  62. [EBorder] = "border",
  63. [EBordercolor] = "bordercolor",
  64. [EFocus] = "focus",
  65. [EFont] = "font",
  66. [EFormat] = "format",
  67. [EHide] = "hide",
  68. [EImage] = "image",
  69. [ELight] = "light",
  70. [EMask] = "mask",
  71. [EPaletextcolor] ="paletextcolor",
  72. [EPressedtextcolor] ="pressedtextcolor",
  73. [ERect] = "rect",
  74. [EReveal] = "reveal",
  75. [EShow] = "show",
  76. [ESize] = "size",
  77. [EText] = "text",
  78. [ETextcolor] = "textcolor",
  79. [EValue] = "value",
  80. nil
  81. };
  82. static void textbuttonshow(Textbutton*);
  83. static void
  84. textbuttonmouse(Control *c, Mouse *m)
  85. {
  86. Textbutton *t;
  87. t = (Textbutton *)c;
  88. if(m->buttons&7) {
  89. if (ptinrect(m->xy,t->Control.rect)) {
  90. if (t->off) {
  91. t->off = 0;
  92. textbuttonshow(t);
  93. }
  94. } else {
  95. if (!t->off) {
  96. t->off = 1;
  97. textbuttonshow(t);
  98. }
  99. }
  100. }
  101. if((m->buttons&7) != t->lastbut){
  102. if(m->buttons & 7){
  103. t->prepress = t->pressed;
  104. if (t->pressed)
  105. t->pressed = 0;
  106. else
  107. t->pressed = 1;
  108. textbuttonshow(t);
  109. }else{ /* generate event on button up */
  110. if (ptinrect(m->xy,t->Control.rect))
  111. chanprint(t->Control.event, t->Control.format, t->Control.name, t->pressed);
  112. else {
  113. t->off = 0;
  114. t->pressed = t->prepress;
  115. textbuttonshow(t);
  116. }
  117. }
  118. }
  119. t->lastbut = m->buttons & 7;
  120. }
  121. static void
  122. textbuttonfree(Control *c)
  123. {
  124. int i;
  125. Textbutton *t;
  126. t = (Textbutton*)c;
  127. _putctlfont(t->font);
  128. _putctlimage(t->image);
  129. _putctlimage(t->light);
  130. _putctlimage(t->mask);
  131. _putctlimage(t->textcolor);
  132. _putctlimage(t->bordercolor);
  133. _putctlimage(t->paletextcolor);
  134. _putctlimage(t->pressedtextcolor);
  135. for(i=0; i<t->nline; i++)
  136. free(t->line[i]);
  137. free(t->line);
  138. }
  139. static void
  140. textbuttonshow(Textbutton *t)
  141. {
  142. Rectangle r, clipr;
  143. int i, dx, dy, w;
  144. Font *f;
  145. Point p, q;
  146. Image *im;
  147. if(t->Control.hidden || (t->lastshow == t->pressed && t->showoff == t->off))
  148. return;
  149. f = t->font->font;
  150. draw(t->Control.screen, t->Control.rect, t->image->image, nil, t->image->image->r.min);
  151. if(t->border > 0)
  152. border(t->Control.screen, t->Control.rect, t->border, t->bordercolor->image, ZP);
  153. /* text goes here */
  154. dx = 0;
  155. for(i=0; i<t->nline; i++){
  156. w = stringwidth(f, t->line[i]);
  157. if(dx < w)
  158. dx = w;
  159. }
  160. dy = t->nline*f->height;
  161. clipr = insetrect(t->Control.rect, t->border);
  162. p = _ctlalignpoint(clipr, dx, dy, t->align);
  163. im = t->textcolor->image;
  164. if(t->off)
  165. im = t->paletextcolor->image;
  166. else if(t->pressed)
  167. im = t->pressedtextcolor->image;
  168. for(i=0; i<t->nline; i++){
  169. r.min = p;
  170. r.max.x = p.x+dx;
  171. r.max.y = p.y+f->height;
  172. q = _ctlalignpoint(r, stringwidth(f, t->line[i]), f->height, t->align%3);
  173. _string(t->Control.screen, q, im,
  174. ZP, f, t->line[i], nil, strlen(t->line[i]),
  175. clipr, nil, ZP, SoverD);
  176. p.y += f->height;
  177. }
  178. if(t->off || t->pressed)
  179. draw(t->Control.screen, t->Control.rect, t->light->image, t->mask->image, t->mask->image->r.min);
  180. t->lastshow = t->pressed;
  181. t->showoff = t->off;
  182. flushimage(display, 1);
  183. }
  184. static void
  185. textbuttonctl(Control *c, CParse *cp)
  186. {
  187. int cmd, i;
  188. Rectangle r;
  189. Textbutton *t;
  190. t = (Textbutton*)c;
  191. cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
  192. switch(cmd){
  193. default:
  194. ctlerror("%q: unrecognized message '%s'", t->Control.name, cp->str);
  195. break;
  196. case EAlign:
  197. _ctlargcount(&t->Control, cp, 2);
  198. t->align = _ctlalignment(cp->args[1]);
  199. t->lastshow = -1; /* force redraw */
  200. break;
  201. case EBorder:
  202. _ctlargcount(&t->Control, cp, 2);
  203. t->border = cp->iargs[1];
  204. t->lastshow = -1; /* force redraw */
  205. break;
  206. case EBordercolor:
  207. _ctlargcount(&t->Control, cp, 2);
  208. _setctlimage(&t->Control, &t->bordercolor, cp->args[1]);
  209. t->lastshow = -1; /* force redraw */
  210. break;
  211. case EFocus:
  212. break;
  213. case EFont:
  214. _ctlargcount(&t->Control, cp, 2);
  215. _setctlfont(&t->Control, &t->font, cp->args[1]);
  216. t->lastshow = -1; /* force redraw */
  217. break;
  218. case EFormat:
  219. _ctlargcount(&t->Control, cp, 2);
  220. t->Control.format = ctlstrdup(cp->args[1]);
  221. break;
  222. case EHide:
  223. _ctlargcount(&t->Control, cp, 1);
  224. t->Control.hidden = 1;
  225. break;
  226. case EImage:
  227. _ctlargcount(&t->Control, cp, 2);
  228. _setctlimage(&t->Control, &t->image, cp->args[1]);
  229. t->lastshow = -1; /* force redraw */
  230. break;
  231. case ELight:
  232. _ctlargcount(&t->Control, cp, 2);
  233. _setctlimage(&t->Control, &t->light, cp->args[1]);
  234. t->lastshow = -1; /* force redraw */
  235. break;
  236. case EMask:
  237. _ctlargcount(&t->Control, cp, 2);
  238. _setctlimage(&t->Control, &t->mask, cp->args[1]);
  239. t->lastshow = -1; /* force redraw */
  240. break;
  241. case EPaletextcolor:
  242. _ctlargcount(&t->Control, cp, 2);
  243. _setctlimage(&t->Control, &t->paletextcolor, cp->args[1]);
  244. t->lastshow = -1; /* force redraw */
  245. break;
  246. case EPressedtextcolor:
  247. _ctlargcount(&t->Control, cp, 2);
  248. _setctlimage(&t->Control, &t->pressedtextcolor, cp->args[1]);
  249. t->lastshow = -1; /* force redraw */
  250. break;
  251. case ERect:
  252. _ctlargcount(&t->Control, cp, 5);
  253. r.min.x = cp->iargs[1];
  254. r.min.y = cp->iargs[2];
  255. r.max.x = cp->iargs[3];
  256. r.max.y = cp->iargs[4];
  257. if(Dx(r)<=0 || Dy(r)<=0)
  258. ctlerror("%q: bad rectangle: %s", t->Control.name, cp->str);
  259. t->Control.rect = r;
  260. t->lastshow = -1; /* force redraw */
  261. break;
  262. case EReveal:
  263. _ctlargcount(&t->Control, cp, 1);
  264. t->Control.hidden = 0;
  265. t->lastshow = -1; /* force redraw */
  266. textbuttonshow(t);
  267. break;
  268. case EShow:
  269. _ctlargcount(&t->Control, cp, 1);
  270. t->lastshow = -1; /* force redraw */
  271. textbuttonshow(t);
  272. break;
  273. case ESize:
  274. if (cp->nargs == 3)
  275. r.max = Pt(0x7fffffff, 0x7fffffff);
  276. else{
  277. _ctlargcount(&t->Control, cp, 5);
  278. r.max.x = cp->iargs[3];
  279. r.max.y = cp->iargs[4];
  280. }
  281. r.min.x = cp->iargs[1];
  282. r.min.y = cp->iargs[2];
  283. 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)
  284. ctlerror("%q: bad sizes: %s", t->Control.name, cp->str);
  285. t->Control.size.min = r.min;
  286. t->Control.size.max = r.max;
  287. break;
  288. case EText:
  289. /* free existing text */
  290. for(i=0; i<t->nline; i++)
  291. free(t->line[i]);
  292. t->nline = cp->nargs-1;
  293. t->line = ctlrealloc(t->line, t->nline*sizeof(char*));
  294. for(i=0; i<t->nline; i++)
  295. t->line[i] = ctlstrdup(cp->args[i+1]);
  296. t->lastshow = -1; /* force redraw */
  297. textbuttonshow(t);
  298. break;
  299. case ETextcolor:
  300. _ctlargcount(&t->Control, cp, 2);
  301. _setctlimage(&t->Control, &t->textcolor, cp->args[1]);
  302. t->lastshow = -1; /* force redraw */
  303. break;
  304. case EValue:
  305. _ctlargcount(&t->Control, cp, 2);
  306. if((cp->iargs[1]!=0) != t->pressed){
  307. t->pressed ^= 1;
  308. textbuttonshow(t);
  309. }
  310. break;
  311. }
  312. }
  313. Control*
  314. createtextbutton(Controlset *cs, char *name)
  315. {
  316. Textbutton *t;
  317. t = (Textbutton *)_createctl(cs, "textbutton", sizeof(Textbutton), name);
  318. t->line = ctlmalloc(sizeof(char*));
  319. t->nline = 0;
  320. t->image = _getctlimage("white");
  321. t->light = _getctlimage("yellow");
  322. t->mask = _getctlimage("opaque");
  323. t->bordercolor = _getctlimage("black");
  324. t->textcolor = _getctlimage("black");
  325. t->pressedtextcolor = _getctlimage("black");
  326. t->paletextcolor = _getctlimage("paleyellow");
  327. t->font = _getctlfont("font");
  328. t->Control.format = ctlstrdup("%q: value %d");
  329. t->lastshow = -1;
  330. t->Control.mouse = textbuttonmouse;
  331. t->Control.ctl = textbuttonctl;
  332. t->Control.exit = textbuttonfree;
  333. t->prepress = 0;
  334. t->off = 0;
  335. t->showoff = -1;
  336. return (Control *)t;
  337. }