textbutton3.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /* use button 3 for a proper function to the application, that is not for plumber
  2. * as default control(2) supposes.
  3. * codes are mostly from /sys/src/libcontrol/textbutton.c
  4. */
  5. #include <u.h>
  6. #include <libc.h>
  7. #include <draw.h>
  8. #include <thread.h>
  9. #include <mouse.h>
  10. #include <keyboard.h>
  11. #include <control.h>
  12. typedef struct Textbutton3 Textbutton3;
  13. struct Textbutton3
  14. {
  15. Control;
  16. CFont *font;
  17. CImage *image;
  18. CImage *mask;
  19. CImage *light;
  20. CImage *bordercolor;
  21. CImage *textcolor;
  22. CImage *pressedtextcolor;
  23. int pressed;
  24. int lastbut;
  25. int lastshow;
  26. char **line;
  27. int nline;
  28. int align;
  29. int border;
  30. int left;
  31. int middle;
  32. int right;
  33. int toggle;
  34. int gettextflg;
  35. };
  36. enum{
  37. EAlign,
  38. EBorder,
  39. EBordercolor,
  40. EFocus,
  41. EFont,
  42. EFormat,
  43. EHide,
  44. EImage,
  45. ELight,
  46. EMask,
  47. EPressedtextcolor,
  48. ERect,
  49. EReveal,
  50. EShow,
  51. ESize,
  52. EText,
  53. ETextcolor,
  54. EEnable,
  55. EDisable,
  56. EToggle,
  57. EGettext,
  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. [EPressedtextcolor] ="pressedtextcolor",
  72. [ERect] = "rect",
  73. [EReveal] = "reveal",
  74. [EShow] = "show",
  75. [ESize] = "size",
  76. [EText] = "text",
  77. [ETextcolor] = "textcolor",
  78. [EEnable] = "enable",
  79. [EDisable] = "disable",
  80. [EToggle] = "toggle",
  81. [EGettext] = "gettext",
  82. [EValue] = "value",
  83. nil
  84. };
  85. static void textbutton3show(Textbutton3 *);
  86. static void
  87. textbutton3mouse(Control *c, Mouse *m)
  88. {
  89. Textbutton3 *t;
  90. t = (Textbutton3 *)c;
  91. if(t->left == 1) {
  92. if((m->buttons&1) == 1 && (t->lastbut&1) == 0){
  93. t->pressed ^= 1;
  94. textbutton3show(t);
  95. t->lastbut = m->buttons & 1;
  96. }else if((m->buttons&1) == 0 && (t->lastbut&1) == 1){
  97. if(t->gettextflg == 0)
  98. chanprint(t->event, t->format, t->name, t->pressed, m->xy.x, m->xy.y);
  99. else
  100. chanprint(t->event, "%q: value %q", t->name, t->line[0]);
  101. t->pressed ^= 1;
  102. textbutton3show(t);
  103. t->lastbut = m->buttons & 1;
  104. }
  105. }
  106. if(t->middle == 1) {
  107. if((m->buttons&2) == 2 && (t->lastbut&2) == 0){
  108. t->pressed ^= 2;
  109. textbutton3show(t);
  110. t->lastbut = m->buttons & 2;
  111. }else if((m->buttons&2) == 0 && (t->lastbut&2) == 2){
  112. if(t->gettextflg == 0)
  113. chanprint(t->event, t->format, t->name, t->pressed, m->xy.x, m->xy.y);
  114. else
  115. chanprint(t->event, "%q: value %q", t->name, t->line[0]);
  116. t->pressed ^= 2;
  117. textbutton3show(t);
  118. t->lastbut = m->buttons & 2;
  119. }
  120. }
  121. if(t->right == 1) {
  122. if((m->buttons&4) == 4 && (t->lastbut&4) == 0){
  123. t->pressed ^= 4;
  124. textbutton3show(t);
  125. t->lastbut = m->buttons & 4;
  126. }else if((m->buttons&4) == 0 && (t->lastbut&4) == 4){
  127. if(t->gettextflg == 0)
  128. chanprint(t->event, t->format, t->name, t->pressed, m->xy.x, m->xy.y);
  129. else
  130. chanprint(t->event, "%q: value %q", t->name, t->line[0]);
  131. t->pressed ^= 4;
  132. textbutton3show(t);
  133. t->lastbut = m->buttons & 4;
  134. }
  135. }
  136. }
  137. static void
  138. textbutton3free(Control *c)
  139. {
  140. int i;
  141. Textbutton3 *t;
  142. t = (Textbutton3*)c;
  143. _putctlfont(t->font);
  144. _putctlimage(t->image);
  145. _putctlimage(t->light);
  146. _putctlimage(t->mask);
  147. _putctlimage(t->textcolor);
  148. _putctlimage(t->bordercolor);
  149. _putctlimage(t->pressedtextcolor);
  150. for(i=0; i<t->nline; i++)
  151. free(t->line[i]);
  152. free(t->line);
  153. }
  154. static void
  155. textbutton3show(Textbutton3 *t)
  156. {
  157. Rectangle r, clipr;
  158. int i, dx, dy, w;
  159. Font *f;
  160. Point p, q;
  161. Image *im;
  162. if(t->hidden || t->lastshow == t->pressed)
  163. return;
  164. f = t->font->font;
  165. draw(t->screen, t->rect, t->image->image, nil, t->image->image->r.min);
  166. if(t->pressed || t->toggle)
  167. draw(t->screen, t->rect, t->light->image, t->mask->image, t->mask->image->r.min);
  168. if(t->border > 0)
  169. border(t->screen, t->rect, t->border, t->bordercolor->image, ZP);
  170. /* text goes here */
  171. dx = 0;
  172. for(i=0; i<t->nline; i++){
  173. w = stringwidth(f, t->line[i]); /*****/
  174. if(dx < w)
  175. dx = w;
  176. }
  177. dy = t->nline*f->height;
  178. clipr = insetrect(t->rect, t->border);
  179. p = _ctlalignpoint(clipr, dx, dy, t->align);
  180. im = t->textcolor->image;
  181. if(t->pressed)
  182. im = t->pressedtextcolor->image;
  183. for(i=0; i<t->nline; i++){
  184. r.min = p;
  185. r.max.x = p.x+dx;
  186. r.max.y = p.y+f->height;
  187. q = _ctlalignpoint(r, stringwidth(f, t->line[i]), f->height, t->align%3);
  188. _string(t->screen, q, im,
  189. ZP, f, t->line[i], nil, strlen(t->line[i]),
  190. clipr, nil, ZP, SoverD);
  191. p.y += f->height;
  192. }
  193. t->lastshow = t->pressed;
  194. flushimage(display, 1);
  195. }
  196. static void
  197. textbutton3ctl(Control *c, CParse *cp)
  198. {
  199. int cmd, i;
  200. Rectangle r;
  201. Textbutton3 *t;
  202. t = (Textbutton3*)c;
  203. cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
  204. switch(cmd){
  205. default:
  206. ctlerror("%q: unrecognized message '%s'", t->name, cp->str);
  207. break;
  208. case EAlign:
  209. _ctlargcount(t, cp, 2);
  210. t->align = _ctlalignment(cp->args[1]);
  211. t->lastshow = -1; /* force redraw */
  212. break;
  213. case EBorder:
  214. _ctlargcount(t, cp, 2);
  215. t->border = cp->iargs[1];
  216. t->lastshow = -1; /* force redraw */
  217. break;
  218. case EBordercolor:
  219. _ctlargcount(t, cp, 2);
  220. _setctlimage(t, &t->bordercolor, cp->args[1]);
  221. t->lastshow = -1; /* force redraw */
  222. break;
  223. case EFocus:
  224. break;
  225. case EFont:
  226. _ctlargcount(t, cp, 2);
  227. _setctlfont(t, &t->font, cp->args[1]);
  228. t->lastshow = -1; /* force redraw */
  229. break;
  230. case EFormat:
  231. _ctlargcount(t, cp, 2);
  232. t->format = ctlstrdup(cp->args[1]);
  233. break;
  234. case EHide:
  235. _ctlargcount(t, cp, 1);
  236. t->hidden = 1;
  237. break;
  238. case EImage:
  239. _ctlargcount(t, cp, 2);
  240. _setctlimage(t, &t->image, cp->args[1]);
  241. t->lastshow = -1; /* force redraw */
  242. break;
  243. case ELight:
  244. _ctlargcount(t, cp, 2);
  245. _setctlimage(t, &t->light, cp->args[1]);
  246. t->lastshow = -1; /* force redraw */
  247. break;
  248. case EMask:
  249. _ctlargcount(t, cp, 2);
  250. _setctlimage(t, &t->mask, cp->args[1]);
  251. t->lastshow = -1; /* force redraw */
  252. break;
  253. case EPressedtextcolor:
  254. _ctlargcount(t, cp, 2);
  255. _setctlimage(t, &t->pressedtextcolor, cp->args[1]);
  256. t->lastshow = -1; /* force redraw */
  257. break;
  258. case ERect:
  259. _ctlargcount(t, cp, 5);
  260. r.min.x = cp->iargs[1];
  261. r.min.y = cp->iargs[2];
  262. r.max.x = cp->iargs[3];
  263. r.max.y = cp->iargs[4];
  264. if(Dx(r)<=0 || Dy(r)<=0)
  265. ctlerror("%q: bad rectangle: %s", t->name, cp->str);
  266. t->rect = r;
  267. t->lastshow = -1; /* force redraw */
  268. break;
  269. case EReveal:
  270. _ctlargcount(t, cp, 1);
  271. t->hidden = 0;
  272. t->lastshow = -1; /* force redraw */
  273. textbutton3show(t);
  274. break;
  275. case EShow:
  276. _ctlargcount(t, cp, 1);
  277. t->lastshow = -1; /* force redraw */
  278. textbutton3show(t);
  279. break;
  280. case ESize:
  281. if (cp->nargs == 3)
  282. r.max = Pt(0x7fffffff, 0x7fffffff);
  283. else{
  284. _ctlargcount(t, cp, 5);
  285. r.max.x = cp->iargs[3];
  286. r.max.y = cp->iargs[4];
  287. }
  288. r.min.x = cp->iargs[1];
  289. r.min.y = cp->iargs[2];
  290. 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)
  291. ctlerror("%q: bad sizes: %s", t->name, cp->str);
  292. t->size.min = r.min;
  293. t->size.max = r.max;
  294. break;
  295. case EText:
  296. /* free existing text */
  297. for(i=0; i<t->nline; i++)
  298. free(t->line[i]);
  299. t->nline = cp->nargs-1;
  300. t->line = ctlrealloc(t->line, t->nline*sizeof(char*));
  301. for(i=0; i<t->nline; i++)
  302. t->line[i] = ctlstrdup(cp->args[i+1]);
  303. t->lastshow = -1; /* force redraw */
  304. textbutton3show(t);
  305. break;
  306. case ETextcolor:
  307. _ctlargcount(t, cp, 2);
  308. _setctlimage(t, &t->textcolor, cp->args[1]);
  309. t->lastshow = -1; /* force redraw */
  310. break;
  311. case EEnable:
  312. _ctlargcount(t, cp, 2);
  313. if(strcmp(cp->args[1], "left") == 0)
  314. t->left = 1;
  315. else if(strcmp(cp->args[1], "middle") == 0)
  316. t->middle = 1;
  317. else if(strcmp(cp->args[1], "right") == 0)
  318. t->right = 1;
  319. break;
  320. case EDisable:
  321. _ctlargcount(t, cp, 2);
  322. if(strcmp(cp->args[1], "left") == 0)
  323. t->left = 0;
  324. else if(strcmp(cp->args[1], "middle") == 0)
  325. t->middle = 0;
  326. else if(strcmp(cp->args[1], "right") == 0)
  327. t->right = 0;
  328. break;
  329. case EToggle:
  330. _ctlargcount(t, cp, 2);
  331. if(strcmp(cp->args[1], "on") == 0)
  332. t->toggle = 1;
  333. else if(strcmp(cp->args[1], "off") == 0)
  334. t->toggle = 0;
  335. t->lastshow = -1; /* force redraw */
  336. break;
  337. case EGettext:
  338. _ctlargcount(t, cp, 2);
  339. if(strcmp(cp->args[1], "on") == 0)
  340. t->gettextflg = 1;
  341. else if(strcmp(cp->args[1], "off") == 0)
  342. t->gettextflg = 0;
  343. break;
  344. case EValue:
  345. _ctlargcount(t, cp, 2);
  346. if((cp->iargs[1]!=0) != t->pressed){
  347. t->pressed ^= 1;
  348. textbutton3show(t);
  349. }
  350. break;
  351. }
  352. }
  353. Control*
  354. createtextbutton3(Controlset *cs, char *name)
  355. {
  356. Textbutton3 *t;
  357. t = (Textbutton3 *)_createctl(cs, "textbutton3", sizeof(Textbutton3), name);
  358. t->line = ctlmalloc(sizeof(char*));
  359. t->nline = 0;
  360. t->image = _getctlimage("white");
  361. t->light = _getctlimage("yellow");
  362. t->mask = _getctlimage("opaque");
  363. t->bordercolor = _getctlimage("black");
  364. t->textcolor = _getctlimage("black");
  365. t->pressedtextcolor = _getctlimage("black");
  366. t->font = _getctlfont("font");
  367. t->format = ctlstrdup("%q: value %d %d %d");
  368. t->lastshow = -1;
  369. t->mouse = textbutton3mouse;
  370. t->ctl = textbutton3ctl;
  371. t->exit = textbutton3free;
  372. t->left = 1;
  373. t->middle = 1;
  374. t->right = 1;
  375. t->toggle = 0;
  376. t->gettextflg = 0;
  377. return (Control *)t;
  378. }