code: purgatorio

ref: acc58dfee42368825f7595d63240fd6e88559776
dir: /appl/lib/tabs.b/

View raw version
implement Tabs;

# pseudo-widget for folder tab selections

#
# Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
# Revisions Copyright © 2000-2002 Vita Nuova Holdings Limited.  All rights reserved.
#

include "sys.m";
	sys: Sys;

include "draw.m";

include "tk.m";
	tk: Tk;

include "string.m";
	str: String;		# could load on demand

include "tabs.m";

TABSXdelta : con 2;
TABSXslant : con 5;
TABSXoff : con 5;
TABSYheight : con 35;
TABSYtop : con 10;
TABSBord : con 1;

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

mktabs(t: ref Tk->Toplevel, dot: string, tabs: array of (string, string), dflt: int): chan of string
{
	lab, widg: string;
	cmd(t, "canvas "+dot+" -height "+string TABSYheight);
	cmd(t, "pack propagate "+dot+" 0");
	c := chan of string;
	tk->namechan(t, c, dot[1:]);
	xpos := 2*TABSXdelta;
	ypos := TABSYheight - 3;
	back := cmd(t, dot+" cget -background");
	dark := "#999999";
	light := "#ffffff";
	w := 20;
	h := 30;
	last := "";
	for(i := 0; i < len tabs; i++){
		(lab, widg) = tabs[i];
		tag := "tag" + string i;
		sel := "sel" + string i;
		xs := xpos;
		xpos += TABSXslant + TABSXoff;
		v := cmd(t, dot+" create text "+string xpos+" "+string ypos+" -text "+tk->quote(lab)+" -anchor sw -tags "+tag);
		bbox := tk->cmd(t, dot+" bbox "+tag);
		if(bbox[0] == '!')
			break;
		(r, nil) := parserect(bbox);
		r.max.x += TABSXoff;
		x1 := " "+string xs;
		x2 := " "+string(xs + TABSXslant);
		x3 := " "+string r.max.x;
		x4 := " "+string(r.max.x + TABSXslant);
		y1 := " "+string(TABSYheight - 2);
		y2 := " "+string TABSYtop;
		cmd(t, dot+" create polygon " + x1+y1 + x2+y2 + x3+y2 + x4+y1 +
			" -fill "+back+" -tags "+tag);
		cmd(t, dot+" create line " + x3+y2 + x4+y1 +
			" -fill "+dark+" -width 1 -tags "+tag);
		cmd(t, dot+" create line " + x1+y1 + x2+y2 + x3+y2 +
			" -fill "+light+" -width 1 -tags "+tag);

		x1 = " "+string(xs+2);
		x4 = " "+string(r.max.x + TABSXslant - 2);
		y1 = " "+string(TABSYheight);
		cmd(t, dot+" create line " + x1+y1 + x4+y1 +
			" -fill "+back+" -width 2 -tags "+sel);

		cmd(t, dot+" raise "+v);
		cmd(t, dot+" bind "+tag+" <ButtonRelease-1> 'send "+
			dot[1:]+" "+string i);

		cmd(t, dot+" lower "+tag+" "+last);
		last = tag;

		xpos = r.max.x;
		ww := int cmd(t, widg+" cget -width");
		wh := int cmd(t, widg+" cget -height");
		if(wh > h)
			h = wh;
		if(ww > w)
			w = ww;
	}
	xpos += 4*TABSXslant;
	if(w < xpos)
		w = xpos;

	for(i = 0; i < len tabs; i++){
		(nil, widg) = tabs[i];
		cmd(t, "pack propagate "+widg+" 0");
		cmd(t, widg+" configure -width "+string w+" -height "+string h);
	}

	w += 2*TABSBord;
	h += 2*TABSBord + TABSYheight;

	cmd(t, dot+" create line 0 "+string TABSYheight+
		" "+string w+" "+string TABSYheight+" -width 2 -fill "+light);
	cmd(t, dot+" create line 1 "+string TABSYheight+
		" 1 "+string(h-1)+" -width 2 -fill "+light);
	cmd(t, dot+" create line  0 "+string(h-1)+
		" "+string w+" "+string(h-1)+" -width 2 -fill "+dark);
	cmd(t, dot+" create line "+string(w-1)+" "+string TABSYheight+
		" "+string(w-1)+" "+string(h-1)+" -width 2 -fill "+dark);

	cmd(t, dot+" configure -width "+string w+" -height "+string h);
	cmd(t, dot+" configure -scrollregion {0 0 "+string w+" "+string h+"}");
	tabsctl(t, dot, tabs, -1, string dflt);
	return c;
}

tabsctl(t: ref Tk->Toplevel,
	dot: string,
	tabs: array of (string, string),
	id: int,
	s: string): int
{
	lab, widg: string;

	nid := int s;
	if(id == nid)
		return id;
	if(id >= 0){
		(lab, widg) = tabs[id];
		tag := "tag" + string id;
		cmd(t, dot+" lower sel" + string id);
#		pos := cmd(t, dot+" coords " + tag);
#		if(len pos >= 1 && pos[0] != '!'){
#			(p, nil) := parsept(pos);
#			cmd(t, dot+" coords "+tag+" "+string(p.x+1)+
#				" "+string(p.y+1));
#		}
		if(id > 0)
			cmd(t, dot+" lower "+ tag + " tag"+string (id - 1));
		cmd(t, dot+" delete win" + string id);
	}
	id = nid;
	(lab, widg) = tabs[id];
#	pos := tk->cmd(t, dot+" coords tag" + string id);
#	if(len pos >= 1 && pos[0] != '!'){
#		(p, nil) := parsept(pos);
#		cmd(t, dot+" coords tag"+string id+" "+string(p.x-1)+" "+string(p.y-1));
#	}
	cmd(t, dot+" raise tag"+string id);
	cmd(t, dot+" raise sel"+string id);
	cmd(t, dot+" create window "+string TABSBord+" "+
		string(TABSYheight+TABSBord)+" -window "+widg+" -anchor nw -tags win"+string id);
	cmd(t, "update");
	return id;
}

parsept(s: string): (Draw->Point, string)
{
	p: Draw->Point;

	(p.x, s) = str->toint(s, 10);
	(p.y, s) = str->toint(s, 10);
	return (p, s);
}

parserect(s: string): (Draw->Rect, string)
{
	r: Draw->Rect;

	(r.min, s) = parsept(s);
	(r.max, s) = parsept(s);
	return (r, s);
}

cmd(top: ref Tk->Toplevel, s: string): string
{
	e := tk->cmd(top, s);
	if (e != nil && e[0] == '!')
		sys->fprint(sys->fildes(2), "%s: tk error %s on [%s]\n", PATH, e, s);
	return e;
}