1 #include "lib9.h"
2 #include "draw.h"
3 #include "tk.h"
4 #include "label.h"
5
6 #define O(t, e) ((long)(&((t*)0)->e))
7
8 /* Widget Commands (+ means implemented)
9 +cget
10 +configure
11 +invoke
12 +select
13 +deselect
14 +toggle
15 */
16
17 enum {
18 /* other constants */
19 InvokePause = 200, /* delay showing button in down state when invoked */
20 };
21
22 TkOption tkbutopts[] =
23 {
24 "text", OPTtext, O(TkLabel, text), nil,
25 "label", OPTtext, O(TkLabel, text), nil,
26 "underline", OPTdist, O(TkLabel, ul), nil,
27 "justify", OPTstab, O(TkLabel, justify), tkjustify,
28 "anchor", OPTflag, O(TkLabel, anchor), tkanchor,
29 "command", OPTtext, O(TkLabel, command), nil,
30 "bitmap", OPTbmap, O(TkLabel, bitmap), nil,
31 "image", OPTimag, O(TkLabel, img), nil,
32 nil
33 };
34
35 TkOption tkcbopts[] =
36 {
37 "variable", OPTtext, O(TkLabel, variable), nil,
38 "indicatoron", OPTstab, O(TkLabel, indicator), tkbool,
39 "onvalue", OPTtext, O(TkLabel, value), nil,
40 "offvalue", OPTtext, O(TkLabel, offvalue), nil,
41 nil,
42 };
43
44 TkOption tkradopts[] =
45 {
46 "variable", OPTtext, O(TkLabel, variable), nil,
47 "value", OPTtext, O(TkLabel, value), nil,
48 "indicatoron", OPTstab, O(TkLabel, indicator), tkbool,
49 nil,
50 };
51
52 static
53 TkEbind bb[] =
54 {
55 {TkEnter, "%W configure -state active"},
56 {TkLeave, "%W configure -state normal"},
57 {TkButton1P, "%W tkButton1P"},
58 {TkButton1R, "%W tkButton1R %x %y"},
59 {TkMotion|TkButton1P, "" },
60 {TkKey, "%W tkButtonKey 0x%K"},
61 };
62
63 static
64 TkEbind cb[] =
65 {
66 {TkEnter, "%W configure -state active"},
67 {TkLeave, "%W configure -state normal"},
68 {TkButton1P, "%W invoke"},
69 {TkMotion|TkButton1P, "" },
70 {TkKey, "%W tkButtonKey 0x%K"},
71 };
72
73
74 static char tkselbut[] = "selectedButton";
75
76 static char* newbutton(TkTop*, int, char*, char**);
77 static int istransparent(Tk*);
78 static void tkvarchanged(Tk*, char*, char*);
79
80 char*
tkbutton(TkTop * t,char * arg,char ** ret)81 tkbutton(TkTop *t, char *arg, char **ret)
82 {
83 return newbutton(t, TKbutton, arg, ret);
84 }
85
86 char*
tkcheckbutton(TkTop * t,char * arg,char ** ret)87 tkcheckbutton(TkTop *t, char *arg, char **ret)
88 {
89 return newbutton(t, TKcheckbutton, arg, ret);
90 }
91
92 char*
tkradiobutton(TkTop * t,char * arg,char ** ret)93 tkradiobutton(TkTop *t, char *arg, char **ret)
94 {
95 return newbutton(t, TKradiobutton, arg, ret);
96 }
97
98 static char*
newbutton(TkTop * t,int btype,char * arg,char ** ret)99 newbutton(TkTop *t, int btype, char *arg, char **ret)
100 {
101 Tk *tk;
102 char *e;
103 TkLabel *tkl;
104 TkName *names;
105 TkOptab tko[4];
106 TkVar *v;
107
108 tk = tkmkbutton(t, btype);
109 if(tk == nil)
110 return TkNomem;
111
112 tkl = TKobj(TkLabel, tk);
113
114 tko[0].ptr = tk;
115 tko[0].optab = tkgeneric;
116 tko[1].ptr = tkl;
117 tko[1].optab = tkbutopts;
118 switch(btype){
119 case TKcheckbutton:
120 tko[2].ptr = tkl;
121 tko[2].optab = tkcbopts;
122 break;
123 case TKradiobutton:
124 tko[2].ptr = tkl;
125 tko[2].optab = tkradopts;
126 break;
127 default:
128 tk->relief = TKraised;
129 tk->borderwidth = 1;
130 tko[2].ptr = nil;
131 break;
132 }
133 tko[3].ptr = nil;
134
135 names = nil;
136 e = tkparse(t, arg, tko, &names);
137 if(e != nil) {
138 tkfreeobj(tk);
139 return e;
140 }
141
142 tksettransparent(tk, istransparent(tk));
143 tksizebutton(tk);
144
145 e = tkaddchild(t, tk, &names);
146 tkfreename(names);
147 if(e != nil) {
148 tkfreeobj(tk);
149 return e;
150 }
151 tk->name->link = nil;
152
153 if (btype == TKradiobutton &&
154 tkl->variable != nil &&
155 strcmp(tkl->variable, tkselbut) == 0 &&
156 tkl->value == nil &&
157 tk->name != nil)
158 tkl->value = strdup(tk->name->name);
159
160 if (tkl->variable != nil) {
161 v = tkmkvar(t, tkl->variable, 0);
162 if (v == nil){
163 if(btype == TKcheckbutton){
164 e = tksetvar(t, tkl->variable, tkl->offvalue ? tkl->offvalue : "0");
165 if (e != nil)
166 goto err;
167 }
168 } else if(v->type != TkVstring){
169 e = TkNotvt;
170 goto err;
171 } else
172 tkvarchanged(tk, tkl->variable, v->value);
173 }
174
175 return tkvalue(ret, "%s", tk->name->name);
176
177 err:
178 tkfreeobj(tk);
179 return e;
180 }
181
182 Tk*
tkmkbutton(TkTop * t,int btype)183 tkmkbutton(TkTop *t, int btype)
184 {
185 Tk *tk;
186 TkLabel *tkl;
187 char *e;
188
189 tk = tknewobj(t, btype, sizeof(Tk)+sizeof(TkLabel));
190 if (tk == nil)
191 return nil;
192
193 e = nil;
194 tk->relief = TKraised;
195 tk->borderwidth = 0;
196 tk->highlightwidth = 1;
197 tk->flag |= Tktakefocus;
198 tkl = TKobj(TkLabel, tk);
199 tkl->ul = -1;
200 tkl->justify = Tkleft;
201
202 switch (btype) {
203 case TKbutton:
204 e = tkbindings(t, tk, bb, nelem(bb));
205 break;
206 case TKcheckbutton:
207 e = tkbindings(t, tk, cb, nelem(cb));
208 break;
209 case TKradiobutton:
210 tkl->variable = strdup(tkselbut);
211 e = tkbindings(t, tk, cb, nelem(cb));
212 break;
213 }
214
215 if (e != nil) {
216 print("tkmkbutton internal error: %s\n", e);
217 tkfreeobj(tk);
218 return nil;
219 }
220 return tk;
221 }
222
223 /*
224 * draw TKbutton, TKcheckbutton, TKradiobutton
225 */
226 char*
tkdrawbutton(Tk * tk,Point orig)227 tkdrawbutton(Tk *tk, Point orig)
228 {
229 TkEnv *e;
230 TkLabel *tkl;
231 Rectangle r, s, mainr, focusr;
232 int dx, dy, h;
233 Point p, u, v, pp[4];
234 Image *i, *dst, *cd, *cl, *ct, *img;
235 int relief, bgnd, fgnd;
236
237 e = tk->env;
238
239 dst = tkimageof(tk);
240 if(dst == nil)
241 return nil;
242
243 v.x = tk->act.width + 2*tk->borderwidth;
244 v.y = tk->act.height + 2*tk->borderwidth;
245
246 r.min = ZP;
247 r.max = v;
248 focusr = insetrect(r, tk->borderwidth);
249 mainr = insetrect(focusr, tk->highlightwidth);
250 relief = tk->relief;
251
252 tkl = TKobj(TkLabel, tk);
253
254 fgnd = TkCforegnd;
255 bgnd = TkCbackgnd;
256 if (tk->flag & Tkdisabled)
257 fgnd = TkCdisablefgnd;
258 else if ((tk->type == TKcheckbutton || tk->type == TKradiobutton) && tkl->indicator == BoolF && tkl->check)
259 bgnd = TkCselect;
260 else if (tk->flag & Tkactive) {
261 fgnd = TkCactivefgnd;
262 bgnd = TkCactivebgnd;
263 }
264
265 i = tkitmp(e, r.max, bgnd);
266 if(i == nil)
267 return nil;
268
269 if(tk->flag & Tkactive)
270 draw(i, r, tkgc(e, bgnd), nil, ZP);
271
272 p = mainr.min;
273 h = tkl->h - 2 * tk->highlightwidth;
274
275 dx = tk->act.width - tkl->w - tk->ipad.x;
276 dy = tk->act.height - tkl->h - tk->ipad.y;
277 if((tkl->anchor & (Tknorth|Tksouth)) == 0)
278 p.y += dy/2;
279 else if(tkl->anchor & Tksouth)
280 p.y += dy;
281
282 if((tkl->anchor & (Tkeast|Tkwest)) == 0)
283 p.x += dx/2;
284 else if(tkl->anchor & Tkeast)
285 p.x += dx;
286
287 switch(tk->type) {
288 case TKcheckbutton:
289 if(tkl->indicator == BoolF) {
290 relief = tkl->check? TKsunken: TKraised;
291 break;
292 }
293 u.x = p.x + ButtonBorder;
294 u.y = p.y + ButtonBorder + (h - CheckSpace) / 2;
295
296 cl = tkgc(e, bgnd+TkLightshade);
297 cd = tkgc(e, bgnd+TkDarkshade);
298 tkbevel(i, u, CheckButton, CheckButton, CheckButtonBW, cd, cl);
299 if(tkl->check) {
300 u.x += CheckButtonBW+1;
301 u.y += CheckButtonBW+1;
302 pp[0] = u;
303 pp[0].y += CheckButton/2-1;
304 pp[1] = pp[0];
305 pp[1].x += 2;
306 pp[1].y += 2;
307 pp[2] = u;
308 pp[2].x += CheckButton/4;
309 pp[2].y += CheckButton-2;
310 pp[3] = u;
311 pp[3].x += CheckButton-2;
312 pp[3].y++;
313 bezspline(i, pp, 4, Enddisc, Enddisc, 1, tkgc(e, TkCforegnd), ZP);
314 }
315 break;
316 case TKradiobutton:
317 if(tkl->indicator == BoolF) {
318 relief = tkl->check? TKsunken: TKraised;
319 break;
320 }
321 u.x = p.x + ButtonBorder;
322 u.y = p.y + ButtonBorder + (h - CheckSpace) / 2;
323 v = Pt(u.x+CheckButton/2,u.y+CheckButton/2);
324 ellipse(i, v, CheckButton/2, CheckButton/2, CheckButtonBW-1, tkgc(e, bgnd+TkDarkshade), ZP);
325 if(tkl->check)
326 fillellipse(i, v, CheckButton/2-2, CheckButton/2-2, tkgc(e, TkCforegnd), ZP); /* could be TkCselect */
327 break;
328 case TKbutton:
329 if ((tk->flag & (Tkactivated|Tkactive)) == (Tkactivated|Tkactive))
330 relief = TKsunken;
331 break;
332 }
333
334 p.x += tk->ipad.x/2;
335 p.y += tk->ipad.y/2;
336 u = ZP;
337 if(tk->type == TKbutton && relief == TKsunken) {
338 u.x++;
339 u.y++;
340 }
341 if((tk->type == TKcheckbutton || tk->type == TKradiobutton) && tkl->indicator != BoolF)
342 u.x += CheckSpace;
343
344 img = nil;
345 if (tkl->img != nil && tkl->img->img != nil)
346 img = tkl->img->img;
347 else if (tkl->bitmap != nil)
348 img = tkl->bitmap;
349 if (img != nil) {
350 s.min.x = p.x + Bitpadx;
351 s.min.y = p.y + Bitpady;
352 s.max.x = s.min.x + Dx(img->r);
353 s.max.y = s.min.y + Dy(img->r);
354 s = rectaddpt(s, u);
355 if(tkchanhastype(img->chan, CGrey))
356 draw(i, s, tkgc(e, fgnd), img, ZP);
357 else
358 draw(i, s, img, nil, ZP);
359 } else if(tkl->text != nil) {
360 u.x += Textpadx;
361 u.y += Textpady;
362 ct = tkgc(e, fgnd);
363
364 p.y += (h - tkl->textheight) / 2;
365 tkdrawstring(tk, i, addpt(u, p), tkl->text, tkl->ul, ct, tkl->justify);
366 }
367
368 // if(tkhaskeyfocus(tk))
369 // tkbox(i, focusr, tk->highlightwidth, tkgc(e, TkChighlightfgnd));
370 tkdrawrelief(i, tk, ZP, bgnd, relief);
371
372 p.x = tk->act.x + orig.x;
373 p.y = tk->act.y + orig.y;
374 r = rectaddpt(r, p);
375 draw(dst, r, i, nil, ZP);
376
377 return nil;
378 }
379
380 void
tksizebutton(Tk * tk)381 tksizebutton(Tk *tk)
382 {
383 int w, h;
384 TkLabel *tkl;
385
386 tkl = TKobj(TkLabel, tk);
387 if(tkl->anchor == 0)
388 tkl->anchor = Tkcenter;
389
390 tksizelabel(tk); /* text, bitmap or image, and highlight */
391 w = tkl->w;
392 h = tkl->h;
393
394 if((tk->type == TKcheckbutton || tk->type == TKradiobutton) && tkl->indicator != BoolF) {
395 w += CheckSpace;
396 if(h < CheckSpace)
397 h = CheckSpace;
398 }
399 tkl->w = w;
400 tkl->h = h;
401 if((tk->flag & Tksetwidth) == 0)
402 tk->req.width = w;
403 if((tk->flag & Tksetheight) == 0)
404 tk->req.height = h;
405 }
406
407 int
tkbuttonmargin(Tk * tk)408 tkbuttonmargin(Tk *tk)
409 {
410 TkLabel *tkl;
411 tkl = TKobj(TkLabel, tk);
412
413 switch (tk->type) {
414 case TKbutton:
415 if (tkl->img != nil || tkl->bitmap != nil)
416 return 0;
417 return Textpadx+tk->highlightwidth;
418 case TKcheckbutton:
419 case TKradiobutton:
420 return CheckButton + 2*CheckButtonBW + 2*ButtonBorder;
421 }
422 return tklabelmargin(tk);
423 }
424
425 void
tkfreebutton(Tk * tk)426 tkfreebutton(Tk *tk)
427 {
428 tkfreelabel(tk);
429 }
430
431 static char*
tkbuttoncget(Tk * tk,char * arg,char ** val)432 tkbuttoncget(Tk *tk, char *arg, char **val)
433 {
434 TkOptab tko[4];
435 TkLabel *tkl = TKobj(TkLabel, tk);
436
437 tko[0].ptr = tk;
438 tko[0].optab = tkgeneric;
439 tko[1].ptr = tkl;
440 tko[1].optab = tkbutopts;
441 switch(tk->type){
442 case TKcheckbutton:
443 tko[2].ptr = tkl;
444 tko[2].optab = tkcbopts;
445 break;
446 case TKradiobutton:
447 tko[2].ptr = tkl;
448 tko[2].optab = tkradopts;
449 break;
450 default:
451 tko[2].ptr = nil;
452 break;
453 }
454 tko[3].ptr = nil;
455 return tkgencget(tko, arg, val, tk->env->top);
456 }
457
458 static char*
tkbuttonconf(Tk * tk,char * arg,char ** val)459 tkbuttonconf(Tk *tk, char *arg, char **val)
460 {
461 char *e;
462 TkGeom g;
463 int bd;
464 TkOptab tko[4];
465 TkVar *v;
466 TkLabel *tkl = TKobj(TkLabel, tk);
467
468 tko[0].ptr = tk;
469 tko[0].optab = tkgeneric;
470 tko[1].ptr = tkl;
471 tko[1].optab = tkbutopts;
472 switch(tk->type){
473 case TKcheckbutton:
474 tko[2].ptr = tkl;
475 tko[2].optab = tkcbopts;
476 break;
477 case TKradiobutton:
478 tko[2].ptr = tkl;
479 tko[2].optab = tkradopts;
480 break;
481 default:
482 tko[2].ptr = nil;
483 break;
484 }
485 tko[3].ptr = nil;
486
487 if(*arg == '\0')
488 return tkconflist(tko, val);
489
490 g = tk->req;
491 bd = tk->borderwidth;
492 e = tkparse(tk->env->top, arg, tko, nil);
493 tksizebutton(tk);
494 tkgeomchg(tk, &g, bd);
495
496 tk->dirty = tkrect(tk, 1);
497 tksettransparent(tk, istransparent(tk));
498 /*
499 * XXX what happens if we're now disabled, but we were in
500 * active state before?
501 */
502 if (tkl->variable != nil) {
503 v = tkmkvar(tk->env->top, tkl->variable, 0);
504 if (v != nil) {
505 if (v->type != TkVstring) {
506 e = TkNotvt;
507 free(tkl->variable);
508 tkl->variable = nil;
509 }
510 else
511 tkvarchanged(tk, tkl->variable, v->value);
512 }
513 }
514 return e;
515 }
516
517 static int
istransparent(Tk * tk)518 istransparent(Tk *tk)
519 {
520 TkEnv *e = tk->env;
521 return (tkhasalpha(e, TkCbackgnd) || tkhasalpha(e, TkCselectbgnd) || tkhasalpha(e, TkCactivebgnd));
522 }
523
524 static void
tkvarchanged(Tk * tk,char * var,char * val)525 tkvarchanged(Tk *tk, char *var, char *val)
526 {
527 TkLabel *tkl;
528 char *sval;
529
530 tkl = TKobj(TkLabel, tk);
531 if (tkl->variable != nil && strcmp(tkl->variable, var) == 0) {
532 sval = tkl->value;
533 if (sval == nil)
534 sval = tk->type == TKcheckbutton ? "1" : "";
535 tkl->check = (strcmp(val, sval) == 0);
536 tk->dirty = tkrect(tk, 1);
537 tkdirty(tk);
538 }
539 }
540
541 static char*
tkbutton1p(Tk * tk,char * arg,char ** val)542 tkbutton1p(Tk *tk, char *arg, char **val)
543 {
544 USED(arg);
545 USED(val);
546 if(tk->flag & Tkdisabled)
547 return nil;
548 tk->flag |= Tkactivated;
549 tk->dirty = tkrect(tk, 1);
550 tkdirty(tk);
551 return nil;
552 }
553
554 static char*
tkbutton1r(Tk * tk,char * arg,char ** val)555 tkbutton1r(Tk *tk, char *arg, char **val)
556 {
557 char *e;
558 Point p;
559 Rectangle hitr;
560
561 USED(arg);
562
563 if(tk->flag & Tkdisabled)
564 return nil;
565 e = tkxyparse(tk, &arg, &p);
566 if (e == nil) {
567 hitr.min = ZP;
568 hitr.max.x = tk->act.width + tk->borderwidth*2;
569 hitr.max.y = tk->act.height + tk->borderwidth*2;
570 if(ptinrect(p, hitr) && (tk->flag & Tkactivated))
571 e = tkbuttoninvoke(tk, nil, val);
572 }
573 tk->flag &= ~Tkactivated;
574 tk->dirty = tkrect(tk, 1);
575 tkdirty(tk);
576 return e;
577 }
578
579 static char*
tkbuttonkey(Tk * tk,char * arg,char ** val)580 tkbuttonkey(Tk *tk, char *arg, char **val)
581 {
582 int key;
583
584 if(tk->flag & Tkdisabled)
585 return nil;
586
587 key = strtol(arg, nil, 0);
588 if (key == '\n' || key ==' ')
589 return tkbuttoninvoke(tk, nil, val);
590 return nil;
591 }
592
593 static char*
tkbuttontoggle(Tk * tk,char * arg,char ** val)594 tkbuttontoggle(Tk *tk, char *arg, char **val)
595 {
596 char *e;
597 TkLabel *tkl = TKobj(TkLabel, tk);
598 char *v;
599
600 USED(arg);
601 USED(val);
602 if(tk->flag & Tkdisabled)
603 return nil;
604 tkl->check = !tkl->check;
605 if (tkl->check)
606 v = tkl->value ? tkl->value : "1";
607 else
608 v = tkl->offvalue ? tkl->offvalue : "0";
609 e = tksetvar(tk->env->top, tkl->variable, v);
610 tk->dirty = tkrect(tk, 0);
611 return e;
612 }
613
614 static char*
buttoninvoke(Tk * tk,char ** val)615 buttoninvoke(Tk *tk, char **val)
616 {
617 char *e = nil;
618 TkTop *top;
619 TkLabel *tkl = TKobj(TkLabel, tk);
620
621 top = tk->env->top;
622 if (tk->type == TKcheckbutton)
623 e = tkbuttontoggle(tk, "", val);
624 else if (tk->type == TKradiobutton)
625 e = tksetvar(top, tkl->variable, tkl->value);
626 if(e != nil)
627 return e;
628 if(tkl->command != nil)
629 return tkexec(tk->env->top, tkl->command, val);
630 return nil;
631 }
632
633 static void
cancelinvoke(Tk * tk,void * v,int cancelled)634 cancelinvoke(Tk *tk, void *v, int cancelled)
635 {
636 int unset;
637 USED(cancelled);
638 USED(v);
639
640 /* if it was active before then leave it active unless cleared since */
641 if (v)
642 unset = 0;
643 else
644 unset = Tkactive;
645 unset &= (tk->flag & Tkactive);
646 unset |= Tkactivated;
647 tk->flag &= ~unset;
648 tksettransparent(tk, istransparent(tk));
649 tk->dirty = tkrect(tk, 1);
650 tkdirty(tk);
651 tkupdate(tk->env->top);
652 }
653
654 char*
tkbuttoninvoke(Tk * tk,char * arg,char ** val)655 tkbuttoninvoke(Tk *tk, char *arg, char **val)
656 {
657 char *e;
658 USED(arg);
659
660 if(tk->flag & Tkdisabled)
661 return nil;
662 e = buttoninvoke(tk, val);
663 if (e == nil && tk->type == TKbutton && !(tk->flag & Tkactivated)) {
664 tkrepeat(tk, cancelinvoke, (void*)(tk->flag&Tkactive), InvokePause, 0);
665 tk->flag |= Tkactivated | Tkactive;
666 tksettransparent(tk, istransparent(tk));
667 tk->dirty = tkrect(tk, 1);
668 tkdirty(tk);
669 tkupdate(tk->env->top);
670 }
671 return e;
672 }
673
674 static char*
tkbuttonselect(Tk * tk,char * arg,char ** val)675 tkbuttonselect(Tk *tk, char *arg, char **val)
676 {
677 char *e, *v;
678 TkLabel *tkl = TKobj(TkLabel, tk);
679
680 USED(arg);
681 USED(val);
682 if (tk->type == TKradiobutton)
683 v = tkl->value;
684 else if (tk->type == TKcheckbutton) {
685 v = tkl->value ? tkl->value : "1";
686 tkl->check = 1;
687 tk->dirty = tkrect(tk, 0);
688 } else
689 v = nil;
690 e = tksetvar(tk->env->top, tkl->variable, v);
691 if(e != nil)
692 return e;
693 return nil;
694 }
695
696 static char*
tkbuttondeselect(Tk * tk,char * arg,char ** val)697 tkbuttondeselect(Tk *tk, char *arg, char **val)
698 {
699 char *e, *v;
700 TkLabel *tkl = TKobj(TkLabel, tk);
701
702 USED(arg);
703 USED(val);
704
705 if (tk->type == TKcheckbutton) {
706 v = tkl->offvalue ? tkl->offvalue : "0";
707 tkl->check = 0;
708 tk->dirty = tkrect(tk, 0);
709 } else
710 v = nil;
711
712 e = tksetvar(tk->env->top, tkl->variable, v);
713 if(e != nil)
714 return e;
715 return nil;
716 }
717
718 static
719 TkCmdtab tkbuttoncmd[] =
720 {
721 "cget", tkbuttoncget,
722 "configure", tkbuttonconf,
723 "invoke", tkbuttoninvoke,
724 "tkButton1P", tkbutton1p,
725 "tkButton1R", tkbutton1r,
726 "tkButtonKey", tkbuttonkey,
727 nil
728 };
729
730 static
731 TkCmdtab tkchkbuttoncmd[] =
732 {
733 "cget", tkbuttoncget,
734 "configure", tkbuttonconf,
735 "invoke", tkbuttoninvoke,
736 "select", tkbuttonselect,
737 "deselect", tkbuttondeselect,
738 "toggle", tkbuttontoggle,
739 "tkButtonKey", tkbuttonkey,
740 nil
741 };
742
743 static
744 TkCmdtab tkradbuttoncmd[] =
745 {
746 "cget", tkbuttoncget,
747 "configure", tkbuttonconf,
748 "invoke", tkbuttoninvoke,
749 "select", tkbuttonselect,
750 "deselect", tkbuttondeselect,
751 "tkButtonKey", tkbuttonkey,
752 nil
753 };
754
755 TkMethod buttonmethod = {
756 "button",
757 tkbuttoncmd,
758 tkfreebutton,
759 tkdrawbutton,
760 nil,
761 tklabelgetimgs
762 };
763
764 TkMethod checkbuttonmethod = {
765 "checkbutton",
766 tkchkbuttoncmd,
767 tkfreebutton,
768 tkdrawbutton,
769 nil,
770 tklabelgetimgs,
771 nil,
772 nil,
773 nil,
774 nil,
775 nil,
776 nil,
777 tkvarchanged
778 };
779
780 TkMethod radiobuttonmethod = {
781 "radiobutton",
782 tkradbuttoncmd,
783 tkfreebutton,
784 tkdrawbutton,
785 nil,
786 nil,
787 nil,
788 nil,
789 nil,
790 nil,
791 nil,
792 nil,
793 tkvarchanged
794 };
795