textbutton.c 6.5 KB

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