label.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #include <lib9.h>
  2. #include <kernel.h>
  3. #include "draw.h"
  4. #include "tk.h"
  5. #include "label.h"
  6. #define O(t, e) ((long)(&((t*)0)->e))
  7. TkOption tklabelopts[] =
  8. {
  9. "text", OPTtext, O(TkLabel, text), nil,
  10. "label", OPTtext, O(TkLabel, text), nil,
  11. "underline", OPTdist, O(TkLabel, ul), nil,
  12. "justify", OPTflag, O(TkLabel, justify), tkjustify,
  13. "anchor", OPTflag, O(TkLabel, anchor), tkanchor,
  14. "bitmap", OPTbmap, O(TkLabel, bitmap), nil,
  15. "image", OPTimag, O(TkLabel, img), nil,
  16. nil
  17. };
  18. char*
  19. tklabel(TkTop *t, char *arg, char **ret)
  20. {
  21. Tk *tk;
  22. char *e;
  23. TkLabel *tkl;
  24. TkName *names;
  25. TkOptab tko[3];
  26. tk = tknewobj(t, TKlabel, sizeof(Tk)+sizeof(TkLabel));
  27. if(tk == nil)
  28. return TkNomem;
  29. tkl = TKobj(TkLabel, tk);
  30. tkl->ul = -1;
  31. tkl->justify = Tkleft;
  32. tko[0].ptr = tk;
  33. tko[0].optab = tkgeneric;
  34. tko[1].ptr = tkl;
  35. tko[1].optab = tklabelopts;
  36. tko[2].ptr = nil;
  37. names = nil;
  38. e = tkparse(t, arg, tko, &names);
  39. if(e != nil) {
  40. tkfreeobj(tk);
  41. return e;
  42. }
  43. tksizelabel(tk);
  44. tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
  45. e = tkaddchild(t, tk, &names);
  46. tkfreename(names);
  47. if(e != nil) {
  48. tkfreeobj(tk);
  49. return e;
  50. }
  51. tk->name->link = nil;
  52. return tkvalue(ret, "%s", tk->name->name);
  53. }
  54. static char*
  55. tklabelcget(Tk *tk, char *arg, char **val)
  56. {
  57. TkOptab tko[3];
  58. TkLabel *tkl = TKobj(TkLabel, tk);
  59. tko[0].ptr = tk;
  60. tko[0].optab = tkgeneric;
  61. tko[1].ptr = tkl;
  62. tko[1].optab = tklabelopts;
  63. tko[2].ptr = nil;
  64. return tkgencget(tko, arg, val, tk->env->top);
  65. }
  66. static char*
  67. tklabelconf(Tk *tk, char *arg, char **val)
  68. {
  69. char *e;
  70. TkGeom g;
  71. int bd;
  72. TkOptab tko[3];
  73. TkLabel *tkl = TKobj(TkLabel, tk);
  74. tko[0].ptr = tk;
  75. tko[0].optab = tkgeneric;
  76. tko[1].ptr = tkl;
  77. tko[1].optab = tklabelopts;
  78. tko[2].ptr = nil;
  79. if(*arg == '\0')
  80. return tkconflist(tko, val);
  81. g = tk->req;
  82. bd = tk->borderwidth;
  83. e = tkparse(tk->env->top, arg, tko, nil);
  84. tksizelabel(tk);
  85. tksettransparent(tk, tkhasalpha(tk->env, TkCbackgnd));
  86. tkgeomchg(tk, &g, bd);
  87. tk->dirty = tkrect(tk, 1);
  88. return e;
  89. }
  90. void
  91. tksizelabel(Tk *tk)
  92. {
  93. Point p;
  94. int w, h;
  95. TkLabel *tkl;
  96. tkl = TKobj(TkLabel, tk);
  97. if(tkl->anchor == 0)
  98. tkl->anchor = Tkcenter;
  99. w = 0;
  100. h = 0;
  101. tkl->textheight = 0;
  102. if(tkl->img != nil) {
  103. w = tkl->img->w + 2*Bitpadx;
  104. h = tkl->img->h + 2*Bitpady;
  105. } else if(tkl->bitmap != nil) {
  106. w = Dx(tkl->bitmap->r) + 2*Bitpadx;
  107. h = Dy(tkl->bitmap->r) + 2*Bitpady;
  108. } else if(tkl->text != nil) {
  109. p = tkstringsize(tk, tkl->text);
  110. w = p.x + 2*Textpadx;
  111. h = p.y + 2*Textpady;
  112. if(tkl->ul != -1 && tkl->ul > strlen(tkl->text))
  113. tkl->ul = strlen(tkl->text); /* underline all */
  114. tkl->textheight = p.y;
  115. }
  116. if(tk->type == TKcascade) {
  117. w += CheckButton + 2*CheckButtonBW;
  118. if(h < CheckButton)
  119. h = CheckButton;
  120. }
  121. w += 2*tk->highlightwidth;
  122. h += 2*tk->highlightwidth;
  123. tkl->w = w;
  124. tkl->h = h;
  125. if((tk->flag & Tksetwidth) == 0)
  126. tk->req.width = w;
  127. if((tk->flag & Tksetheight) == 0)
  128. tk->req.height = h;
  129. }
  130. int
  131. tklabelmargin(Tk *tk)
  132. {
  133. TkLabel *tkl;
  134. Image *img;
  135. switch(tk->type){
  136. case TKseparator:
  137. return 0;
  138. case TKlabel:
  139. case TKcascade:
  140. tkl = TKobj(TkLabel, tk);
  141. img = nil;
  142. if (tkl->img != nil)
  143. img = tkl->img->img;
  144. else if (tkl->bitmap != nil)
  145. img = tkl->bitmap;
  146. if (img != nil)
  147. return Bitpadx;
  148. return Textpadx;
  149. default:
  150. fprint(2, "label margin: type %d\n", tk->type);
  151. return 0;
  152. }
  153. }
  154. void
  155. tkfreelabel(Tk *tk)
  156. {
  157. Image *i;
  158. int locked;
  159. Display *d;
  160. TkLabel *tkl;
  161. tkl = TKobj(TkLabel, tk);
  162. if(tkl->text != nil)
  163. free(tkl->text);
  164. if(tkl->command != nil)
  165. free(tkl->command);
  166. if(tkl->value != nil)
  167. free(tkl->value);
  168. if(tkl->variable != nil) {
  169. tkfreevar(tk->env->top, tkl->variable, tk->flag & Tkswept);
  170. free(tkl->variable);
  171. }
  172. if(tkl->img != nil)
  173. tkimgput(tkl->img);
  174. i = tkl->bitmap;
  175. if(i != nil) {
  176. d = i->display;
  177. locked = lockdisplay(d);
  178. freeimage(i);
  179. if(locked)
  180. unlockdisplay(d);
  181. }
  182. if(tkl->menu != nil)
  183. free(tkl->menu);
  184. }
  185. static void
  186. tktriangle(Point u, Image *i, TkEnv *e)
  187. {
  188. Point p[3];
  189. u.y++;
  190. p[0].x = u.x + CheckButton;
  191. p[0].y = u.y + CheckButton/2;
  192. p[1].x = u.x;
  193. p[1].y = u.y + CheckButton;
  194. p[2].x = u.x;
  195. p[2].y = u.y;
  196. fillpoly(i, p, 3, ~0, tkgc(e, TkCforegnd), p[0]);
  197. }
  198. /*
  199. * draw TKlabel, TKseparator, and TKcascade (cascade should really be a button)
  200. */
  201. char*
  202. tkdrawlabel(Tk *tk, Point orig)
  203. {
  204. TkEnv *e;
  205. TkLabel *tkl;
  206. Rectangle r, s, mainr, focusr;
  207. int dx, dy, h;
  208. Point p, u, v;
  209. Image *i, *dst, *ct, *img;
  210. int relief, bgnd, fgnd;
  211. e = tk->env;
  212. dst = tkimageof(tk);
  213. if(dst == nil)
  214. return nil;
  215. v.x = tk->act.width + 2*tk->borderwidth;
  216. v.y = tk->act.height + 2*tk->borderwidth;
  217. r.min = ZP;
  218. r.max = v;
  219. focusr = insetrect(r, tk->borderwidth);
  220. mainr = insetrect(focusr, tk->highlightwidth);
  221. relief = tk->relief;
  222. tkl = TKobj(TkLabel, tk);
  223. fgnd = TkCforegnd;
  224. bgnd = TkCbackgnd;
  225. if (tk->flag & Tkdisabled)
  226. fgnd = TkCdisablefgnd;
  227. else if (tk->flag & Tkactive) {
  228. fgnd = TkCactivefgnd;
  229. bgnd = TkCactivebgnd;
  230. }
  231. i = tkitmp(e, r.max, bgnd);
  232. if(i == nil)
  233. return nil;
  234. if(tk->flag & Tkactive)
  235. draw(i, r, tkgc(e, bgnd), nil, ZP);
  236. p = mainr.min;
  237. h = tkl->h - 2 * tk->highlightwidth;
  238. dx = tk->act.width - tkl->w - tk->ipad.x;
  239. dy = tk->act.height - tkl->h - tk->ipad.y;
  240. if((tkl->anchor & (Tknorth|Tksouth)) == 0)
  241. p.y += dy/2;
  242. else if(tkl->anchor & Tksouth)
  243. p.y += dy;
  244. if((tkl->anchor & (Tkeast|Tkwest)) == 0)
  245. p.x += dx/2;
  246. else if(tkl->anchor & Tkeast)
  247. p.x += dx;
  248. if(tk->type == TKcascade) {
  249. u.x = mainr.max.x - CheckButton - CheckButtonBW; /* TO DO: CheckButton etc is really the triangle/arrow */
  250. u.y = p.y + ButtonBorder + (h-CheckSpace)/2;
  251. tktriangle(u, i, e);
  252. }
  253. p.x += tk->ipad.x/2;
  254. p.y += tk->ipad.y/2;
  255. u = ZP;
  256. img = nil;
  257. if(tkl->img != nil && tkl->img->img != nil)
  258. img = tkl->img->img;
  259. else if (tkl->bitmap != nil)
  260. img = tkl->bitmap;
  261. if(img != nil) {
  262. s.min.x = p.x + Bitpadx;
  263. s.min.y = p.y + Bitpady;
  264. s.max.x = s.min.x + Dx(img->r);
  265. s.max.y = s.min.y + Dy(img->r);
  266. s = rectaddpt(s, u);
  267. if(tkchanhastype(img->chan, CGrey))
  268. draw(i, s, tkgc(e, fgnd), img, ZP);
  269. else
  270. draw(i, s, img, nil, ZP);
  271. } else if(tkl->text != nil) {
  272. u.x += Textpadx;
  273. u.y += Textpady;
  274. ct = tkgc(e, fgnd);
  275. p.y += (h - tkl->textheight) / 2;
  276. tkdrawstring(tk, i, addpt(u, p), tkl->text, tkl->ul, ct, tkl->justify);
  277. }
  278. if(tkhaskeyfocus(tk))
  279. tkbox(i, focusr, tk->highlightwidth, tkgc(e, TkChighlightfgnd));
  280. tkdrawrelief(i, tk, ZP, bgnd, relief);
  281. p.x = tk->act.x + orig.x;
  282. p.y = tk->act.y + orig.y;
  283. r = rectaddpt(r, p);
  284. draw(dst, r, i, nil, ZP);
  285. return nil;
  286. }
  287. void
  288. tklabelgetimgs(Tk *tk, Image **image, Image **mask)
  289. {
  290. TkLabel *tkl;
  291. tkl = TKobj(TkLabel, tk);
  292. *mask = nil;
  293. if (tkl->img != nil)
  294. *image = tkl->img->img;
  295. else
  296. *image = tkl->bitmap;
  297. }
  298. static
  299. TkCmdtab tklabelcmd[] =
  300. {
  301. "cget", tklabelcget,
  302. "configure", tklabelconf,
  303. nil
  304. };
  305. TkMethod labelmethod = {
  306. "label",
  307. tklabelcmd,
  308. tkfreelabel,
  309. tkdrawlabel,
  310. nil,
  311. tklabelgetimgs
  312. };