tabs.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include <draw.h>
  5. #include <mouse.h>
  6. #include <keyboard.h>
  7. #include <control.h>
  8. #include "group.h"
  9. typedef struct Tab Tab;
  10. struct Tab {
  11. Control;
  12. int border;
  13. int selected;
  14. int separation;
  15. char *format;
  16. CImage *bordercolor;
  17. CImage *image;
  18. Control *tabrow;
  19. Control *tabstack;
  20. Control *tabcolumn;
  21. int ntabs;
  22. int nbuttons;
  23. Control **buttons;
  24. };
  25. enum{
  26. EAdd,
  27. EBorder,
  28. EBordercolor,
  29. EButton,
  30. EFocus,
  31. EFormat,
  32. EHide,
  33. EImage,
  34. ERect,
  35. EReveal,
  36. ESeparation,
  37. ESeparatorcolor,
  38. EShow,
  39. ESize,
  40. EValue,
  41. };
  42. static char *cmds[] = {
  43. [EAdd] = "add",
  44. [EBorder] = "border",
  45. [EBordercolor] = "bordercolor",
  46. [EButton] = "button",
  47. [EFocus] = "focus",
  48. [EFormat] = "format",
  49. [EHide] = "hide",
  50. [EImage] = "image",
  51. [ERect] = "rect",
  52. [EReveal] = "reveal",
  53. [ESeparation] = "separation",
  54. [ESeparatorcolor] = "separatorcolor",
  55. [EShow] = "show",
  56. [ESize] = "size",
  57. [EValue] = "value",
  58. };
  59. static void
  60. tabshow(Tab *t)
  61. {
  62. int i;
  63. Rectangle r;
  64. Group *g;
  65. if (t->hidden)
  66. return;
  67. for(i=0; i<t->nbuttons; i++){
  68. _ctlprint(t->buttons[i], "value %d", (t->selected==i));
  69. }
  70. _ctlprint(t->tabstack, "reveal %d", t->selected);
  71. _ctlprint(t->tabcolumn, "show");
  72. if (t->selected < 0)
  73. return;
  74. g = (Group*)t->tabcolumn;
  75. if (g->nseparators == 0){
  76. return;
  77. }
  78. r = g->separators[0];
  79. r.min.x = t->buttons[t->selected]->rect.min.x;
  80. r.max.x = t->buttons[t->selected]->rect.max.x;
  81. draw(t->screen, r, t->image->image, nil, t->image->image->r.min);
  82. flushimage(display, 1);
  83. }
  84. static void
  85. tabsize(Control *c)
  86. {
  87. Tab *t = (Tab*)c;
  88. if (t->tabcolumn && t->tabcolumn->setsize)
  89. t->tabcolumn->setsize((Control*)t->tabcolumn);
  90. }
  91. static void
  92. tabctl(Control *c, CParse *cp)
  93. {
  94. int cmd, i;
  95. Control *cbut, *cwin;
  96. Tab *t;
  97. Rectangle r;
  98. t = (Tab*)c;
  99. cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));
  100. switch(cmd){
  101. case EAdd:
  102. if ((cp->nargs & 1) == 0)
  103. ctlerror("%q: arg count: %s", t->name, cp->args[1]);
  104. for (i = 1; i < cp->nargs; i += 2){
  105. cbut = controlcalled(cp->args[i]);
  106. if (cbut == nil)
  107. ctlerror("%q: no such control: %s", t->name, cp->args[i]);
  108. cwin = controlcalled(cp->args[i+1]);
  109. if (cwin == nil)
  110. ctlerror("%q: no such control: %s", t->name, cp->args[i+1]);
  111. _ctladdgroup(t->tabrow, cbut);
  112. _ctlprint(t->tabstack, "add %q", cp->args[i+1]);
  113. _ctlprint(cbut, "format '%%s: %q button %%d'", t->name);
  114. controlwire(cbut, "event", t->controlset->ctl);
  115. t->buttons = ctlrealloc(t->buttons, (t->nbuttons+1)*sizeof(Control*));
  116. t->buttons[t->nbuttons] = cbut;
  117. t->nbuttons++;
  118. t->selected = -1;
  119. }
  120. _ctlprint(t->tabcolumn, "size");
  121. t->size = t->tabcolumn->size;
  122. break;
  123. case EBorder:
  124. _ctlargcount(t, cp, 2);
  125. if(cp->iargs[1] < 0)
  126. ctlerror("%q: bad border: %c", t->name, cp->str);
  127. t->border = cp->iargs[1];
  128. break;
  129. case EBordercolor:
  130. _ctlargcount(t, cp, 2);
  131. _setctlimage(t, &t->bordercolor, cp->args[1]);
  132. break;
  133. case EButton:
  134. _ctlargcount(t, cp, 2);
  135. if (cp->sender == nil)
  136. ctlerror("%q: senderless buttonevent: %q", t->name, cp->str);
  137. cbut = controlcalled(cp->sender);
  138. for(i=0; i<t->nbuttons; i++)
  139. if (cbut == t->buttons[i])
  140. break;
  141. if (i == t->nbuttons)
  142. ctlerror("%q: not my event: %q", t->name, cp->str);
  143. if(cp->iargs[1] == 0){
  144. /* button was turned off; turn it back on */
  145. _ctlprint(cbut, "value 1");
  146. }else{
  147. t->selected = i;
  148. if (t->format)
  149. chanprint(t->event, t->format, t->name, i);
  150. tabshow(t);
  151. }
  152. break;
  153. case EFocus:
  154. /* ignore focus change */
  155. break;
  156. case EFormat:
  157. _ctlargcount(t, cp, 2);
  158. t->format = ctlstrdup(cp->args[1]);
  159. break;
  160. case EImage:
  161. _ctlargcount(t, cp, 2);
  162. _setctlimage(t, &t->image, cp->args[1]);
  163. break;
  164. case ESeparation:
  165. t->tabrow->ctl(t->tabrow, cp);
  166. t->tabcolumn->ctl(t->tabcolumn, cp);
  167. break;
  168. case ERect:
  169. _ctlargcount(t, cp, 5);
  170. r.min.x = cp->iargs[1];
  171. r.min.y = cp->iargs[2];
  172. r.max.x = cp->iargs[3];
  173. r.max.y = cp->iargs[4];
  174. if(Dx(r)<=0 || Dy(r)<=0)
  175. ctlerror("%q: bad rectangle: %s", t->name, cp->str);
  176. t->rect = r;
  177. r = insetrect(r, t->border);
  178. _ctlprint(t->tabcolumn, "rect %R", r);
  179. break;
  180. case EReveal:
  181. _ctlargcount(t, cp, 1);
  182. case EHide:
  183. case ESize:
  184. t->tabcolumn->ctl(t->tabcolumn, cp);
  185. break;
  186. case EShow:
  187. tabshow(t);
  188. break;
  189. case EValue:
  190. _ctlargcount(t, cp, 2);
  191. if (cp->iargs[1] < 0 || cp->iargs[1] >= t->nbuttons)
  192. ctlerror("%q: illegal value '%s'", t->name, cp->str);
  193. t->selected = cp->iargs[1];
  194. tabshow(t);
  195. break;
  196. default:
  197. ctlerror("%q: unrecognized message '%s'", t->name, cp->str);
  198. break;
  199. }
  200. }
  201. static void
  202. tabfree(Control*c)
  203. {
  204. Tab *t = (Tab*)c;
  205. t->nbuttons = 0;
  206. free(t->buttons);
  207. t->buttons = 0;
  208. }
  209. static void
  210. activatetab(Control *c, int act)
  211. {
  212. Tab *t;
  213. t = (Tab*)c;
  214. if (act)
  215. activate(t->tabcolumn);
  216. else
  217. deactivate(t->tabcolumn);
  218. }
  219. Control *
  220. createtab(Controlset *cs, char *name)
  221. {
  222. char s[128];
  223. Tab *t;
  224. t = (Tab*)_createctl(cs, "tab", sizeof(Tab), name);
  225. t->selected = -1;
  226. t->nbuttons = 0;
  227. t->ctl = tabctl;
  228. t->mouse = nil;
  229. t->exit = tabfree;
  230. snprint(s, sizeof s, "_%s-row", name);
  231. t->tabrow = createrow(cs, s);
  232. snprint(s, sizeof s, "_%s-stack", name);
  233. t->tabstack = createstack(cs, s);
  234. snprint(s, sizeof s, "_%s-column", name);
  235. t->tabcolumn = createcolumn(cs, s);
  236. ctlprint(t->tabcolumn, "add %q %q", t->tabrow->name, t->tabstack->name);
  237. t->bordercolor = _getctlimage("black");
  238. t->image = _getctlimage("white");
  239. t->setsize = tabsize;
  240. t->activate = activatetab;
  241. return (Control*)t;
  242. }