Charles.Forsyth20060303a828770d19 years agoHistory
176 lines · 4.3 KB · Brainfuck
RawDownload
implement Table;include "sys.m";	sys: Sys;include "draw.m";	draw: Draw;	Point, Rect: import draw;include "tk.m";	tk: Tk;include "table.m"; init(){	sys = load Sys Sys->PATH;	draw = load Draw Draw->PATH;	tk = load Tk Tk->PATH;} newcell(w: string, span: Draw->Point): ref Cell{	return ref Cell(w, span, (0, 0));} layout(cells: array of array of ref Cell, win: ref Tk->Toplevel, w: string){	if (len cells == 0)		return;	dim := Point(len cells, len cells[0]);	for (y := 0; y < dim.y; y++) {		for (x := 0; x < dim.x; x++) {			cell := cells[x][y];			# XXX should take into account cell padding			if (cell != nil) {				cell.sizereq = getsize(win, cell.w);# sys->print("cell %d %d size %s span %s\n", x, y, p2s(cell.sizereq), p2s(cell.span));			}#  else# sys->print("cell %d %d blank\n", x, y);		}	} 	colwidths := array[dim.x] of {* => 0};	# calculate column widths (ignoring multi-column cells)	for (x := 0; x < dim.x; x++) {		for (y = 0; y < dim.y; y++) {			cell := cells[x][y];			if (cell != nil && cell.span.x == 1 && cell.sizereq.x > colwidths[x])				colwidths[x] = cell.sizereq.x;		}	} 	# now check that multi-column cells fit in their columns	colexpand := array[dim.x] of {* => 1};	for (x = 0; x < dim.x; x++) {		for (y = 0; y < dim.y; y++) {			cell := cells[x][y];			if (cell != nil && cell.span.x > 1)				expandwidths(x, cell.sizereq.x, cell.span.x, colwidths, colexpand);		}	}	colexpand = nil; 	rowheights := array[dim.y] of {* => 0};	# calculate row heights (ignoring multi-row cells)	for (y = 0; y < dim.y; y++) {		for (x = 0; x < dim.x; x++) {			cell := cells[x][y];			if (cell != nil && cell.span.y == 1 && cell.sizereq.y > rowheights[y])				rowheights[y] = cell.sizereq.y;		}	} # 	for (i := 0; i < len colwidths; i++)# 		sys->print("colwidth %d -> %d\n", i, colwidths[i]);# 	for (i = 0; i < len rowheights; i++)# 		sys->print("rowheight %d -> %d\n", i, rowheights[i]); 	rowexpand := array[dim.y] of {* => 1};	# now check that multi-row cells fit in their columns	for (y = 0; y < dim.y; y++) {		for (x = 0; x < dim.x; x++) {			cell := cells[x][y];			if (cell != nil && cell.span.y > 1)				expandwidths(y, cell.sizereq.y, cell.span.y, rowheights, rowexpand);		}	} #	if (rowequalise)#		equalise(rowheights, dim.y); #	if (colequalise)#		equalise(colwidths, dim.x); 	# calculate total width and height (including cell padding)	totsize := Point(0, 0);	for (x = 0; x < dim.x; x++)		totsize.x += colwidths[x];	for (y = 0; y < dim.y; y++)		totsize.y += rowheights[y]; 	cmd(win, "canvas " + w + " -width " + string totsize.x + " -bg white -height " + string totsize.y);	p := Point(0, 0);	for (y = 0; y < dim.y; y++) {		p.x = 0;		for (x = 0; x < dim.x; x++) {			cell := cells[x][y];			if (cell != nil) {				cellsize := Point(0, 0);				span := cell.span;				for (xx := 0; xx < span.x; xx++)					cellsize.x += colwidths[x + xx];				for (yy := 0; yy < span.y; yy++)					cellsize.y += rowheights[y + yy];# sys->print("cell [%d %d] %d %d +[%d %d]\n", x, y, p.x, p.y, cellsize.x, cellsize.y);				cmd(win, w + " create window " + p2s(p) +					" -anchor nw -window " + cell.w +					" -width " + string cellsize.x +					" -height " + string cellsize.y);			}			p.x += colwidths[x];		}		p.y += rowheights[y];	}} expandwidths(x: int, cellwidth, xcells: int, widths: array of int, expand: array of int){	# find out total space available for cell	share := 0;	tot := 0;	endx := x + xcells;	for (xx := x; xx < endx; xx++) {		tot += widths[xx];		if (expand[xx])			share++;	}	slack := cellwidth - tot; 	# if enough space, then nothing to do.	if (slack <= 0)		return; 	# allocate extra space amongst all cols that	# want to expand. (if any do, otherwise share it	# out between all of them)	if (share == 0)		share = xcells;	for (xx = x; xx < endx; xx++) {		m := slack / share;		widths[xx] += m;		slack -= m;		share--;	}} getsize(win: ref Tk->Toplevel, w: string): Point{	bd := 2 * int cmd(win, w + " cget -bd");	return Point(int cmd(win, w + " cget -width") + bd,			int cmd(win, w + " cget -height") + bd);} p2s(p: Point): string{	return string p.x + " " + string p.y;} cmd(win: ref Tk->Toplevel, s: string): string{#	sys->print("%ux	%s\n", win, s);	r := tk->cmd(win, s);	if (len r > 0 && r[0] == '!') {		sys->fprint(sys->fildes(2), "error executing '%s': %s\n", s, r);		raise "tk error";	}	return r;}