summaryrefslogtreecommitdiff
path: root/appl/lib/popup.b
blob: 78eef27e9902ede67435cd2f44bc1a244a1800dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
implement Popup;
include "sys.m";
	sys: Sys;
include "draw.m";
	Point: import Draw;
include "tk.m";
	tk: Tk;
include "popup.m";

init()
{
	sys = load Sys Sys->PATH;
	tk = load Tk Tk->PATH;
}

post(win: ref Tk->Toplevel, p: Point, a: array of string, n: int): chan of int
{
	rc := chan of int;
	spawn postproc(win, p, a, n, rc);
	return rc;
}

postproc(win: ref Tk->Toplevel, p: Point, a: array of string, n: int, rc: chan of int)
{
	c := chan of string;
	tk->namechan(win, c, "c.popup");
	mkpopupmenu(win, a);
	cmd(win, ".popup entryconfigure " + string n + " -state active");
	cmd(win, "bind .popup <Unmap> {send c.popup unmap}");

	dy := ypos(win, n) - ypos(win, 0);
	p.y -= dy;
	cmd(win, ".popup post " + string p.x + " " + string p.y +
		";grab set .popup");
	n = -1;
	while ((e := <-c) != "unmap")
		n = int e;

	cmd(win, "destroy .popup");
	rc <-= n;
}

mkpopupmenu(win: ref Tk->Toplevel, a: array of string)
{
	cmd(win, "menu .popup");
	for (i := 0; i < len a; i++) {
		cmd(win, ".popup add command -command {send c.popup " + string i +
			"} -text '" + a[i]);
	}
}

Blank: con "-----";

# XXX what should we do about popups containing no items.
mkbutton(win: ref Tk->Toplevel, w: string, a: array of string, n: int): chan of string
{
	c := chan of string;
	if (len a == 0) {
		cmd(win, "label " + w + " -bd 2 -relief raised -text '" + Blank);
		return c;
	}
	tk->namechan(win, c, "c" + w);
	mkpopupmenu(win, a);
	cmd(win, "label " + w + " -bd 2 -relief raised -width [.popup cget -width] -text '" + a[n]);
	cmd(win, "bind " + w + " <Button-1> {send c" + w + " " + w + "}");
	cmd(win, "destroy .popup");
	return c;
}

changebutton(win: ref Tk->Toplevel, w: string, a: array of string, n: int)
{
	if (len a > 0) {
		mkpopupmenu(win, a);
		cmd(win, w + " configure -width [.popup cget -width] -text '" + a[n]);
		cmd(win, "bind " + w + " <Button-1> {send c" + w + " " + w + "}");
		cmd(win, "destroy .popup");
	} else {
		cmd(win, w + " configure -text '" + Blank);
		cmd(win, "bind " + w + " <Button-1> {}");
	}
}

add(a: array of string, s: string): (array of string, int)
{
	for (i := 0; i < len a; i++)
		if (s == a[i])
			return (a, i);
	na := array[len a + 1] of string;
	na[0:] = a;
	na[len a] = s;
	return (na, len a);
}

#event(win: ref Tk->Toplevel, e: string, a: array of string): int
#{
#	w := e;
#	p := Point(int cmd(win, w + " cget -actx"), int cmd(win, w + " cget -acty"));
#	s := cmd(win, w + " cget -text");
#	for (i := 0; i < len a; i++)
#		if (s == a[i])
#			break;
#	if (i == len a)
#		i = 0;
#		
#	n := post(win, p, a, i);
#	if (n != -1) {
#		cmd(win, w + " configure -text '" + a[n]);
#		i = n;
#	}
#	return i;
#}

ypos(win: ref Tk->Toplevel, n: int): int
{
	return int cmd(win, ".popup yposition " + string n);
}

cmd(win: ref Tk->Toplevel, s: string): string
{
	r := tk->cmd(win, s);
	if (len r > 0 && r[0] == '!')
		sys->print("error executing '%s': %s\n", s, r[1:]);
	return r;
}