Plan 9 from Bell Labs’s /usr/web/sources/contrib/nemo/octopus/port/live/owprowcol.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


implement Pimpl;
include "mods.m";
mods, debug, win, tree: import dat;

Qrow, Qcol, Pmore, Phide, Ptag, Predraw, Pdirties,
Playout, Pdirty, intag, Panel: import wpanel;
Bw, Bws1, Bback, Bn, Bs, Be, Bne, Bse, Bsw, Cpointer, Taght,
bord, drawtag, Tagwid, Inset, borderkind, panelback: import gui;
panelctl, panelkbd, panelmouse, tagmouse, Min, Max, Full, Tree: import wtree;

Prowcol: adt {
	nwins:	int;
};

panels: array of ref Prowcol;

pimpl(p: ref Panel): ref Prowcol
{
	if (p.implid < 0 || p.implid > len panels || panels[p.implid] == nil)
		panic("rowcol: bug: no impl");
	return panels[p.implid];
}

init(d: Livedat): string
{
	prefixes = list of {"row:", "col:"};
	dat = d;
	initmods();
	return nil;
}

pinit(p: ref Panel)
{
	if (tree == nil)
		tree = dat->tree;
	if (len p.name > 4 && p.name[0:4] == "row:")
		p.rowcol = Qrow;
	else
		p.rowcol = Qcol;
	for (i := 0; i < len panels; i++)
		if (panels[i] == nil)
			break;
	if (i == len panels){
		npanels := array[i+16] of ref Prowcol;
		npanels[0:] = panels;
		panels = npanels;
	}
	p.implid = i;
	panels[i] = ref Prowcol(0);
}

pterm(p: ref Panel)
{
	if (p.implid != -1){
		pimpl(p);	# check
		panels[p.implid] = nil;
		p.implid = -1;
	}
}

updatemoreflag(p: ref Panel)
{
	p.flags &= ~Pmore;
	for (i := 0; i < len p.child; i++)
		if (p.child[i].flags&Phide){
			p.flags |= Pmore;
			return;
		}
	pi := pimpl(p);
	pi.nwins = 0;
}

pctl(p: ref Panel, s: string)
{
	panelctl(tree, p, s);
}


pupdate(nil: ref Panel, nil: array of byte)
{
	# nothing to do for row/col
}

pevent(nil: ref Panel, nil: string)
{
	# no events for row/col
}

# Details of how row/cols draw their components are kept not just
# here, but also in layout.b and in mouse processing code. This is built deep
# into o/live, inherited from the o/mero port from Plan B.

drawspacebar(p: ref Panel, k: int)
{
	if (p.space != 0){
		r: Rect;
		r.min.x = p.rect.min.x + Tagwid;
		r.max.x = p.rect.max.x - Inset;
		r.min.y = p.rect.min.y;
		r.max.y = p.rect.min.y + Inset;
		p.space--;
		p.space %= 3;
		win.image.draw(r, bord[Bws1 + p.space][k], nil, (0,0));
	}
}

pdraw(p: ref Panel)
{
	k := borderkind(p);
	cback := panelback(p);
	has := (p.flags&Ptag);
	dirty := (p.flags&Pdirty);
	r := p.rect.inset(Inset);
	if (has)
		r.min.x += Tagwid;

	max := Point(0, 0);
	last := 0;
	for (i := 0; i < len p.child; i++){
		np := p.child[i];
		npr := np.rect;
		nr := npr;
		dirty |= (np.flags&Pdirty);
		if (np.flags&Phide)
			continue;
		if (npr.dx() == 0 || npr.dy() == 0) # did not have room. ignore.
			continue;
		#clear space unused by component.
		max = npr.max;
		if (debug['L'] > 1)
			fprint(stderr, "\tnpr [%d %d %d %d]\n",
			npr.min.x, npr.min.y, npr.max.x, npr.max.y);
		if (p.rowcol == Qcol){
			nr.min.x = npr.max.x;
			nr.max.x = r.max.x;
		} else {
			nr.min.y = npr.max.y;
			nr.max.y = r.max.y;
		}
		win.image.draw(nr, cback, nil, (0,0));
		if (last != 0){
			# clear separator from previous component
			nr = r;
			if (p.rowcol == Qcol){
				nr.min.y = last;
				nr.max.y = nr.min.y + Inset;
			} else {
				nr.min.x = last;
				nr.max.x = nr.min.x + Inset;
			}
			win.image.draw(nr, cback, nil, (0,0));
		}
		if (p.rowcol == Qcol)
			last = np.rect.max.y;
		else
			last = np.rect.max.x;
	}

	if (max.x != 0 || max.y != 0){
		# Clear unused space at end of components
		nr := r;
		if (p.rowcol == Qcol)
			nr.min.y = max.y;
		else
			nr.min.x = max.x;
		win.image.draw(nr, cback, nil, (0,0));
	} else {
		# no inner component. clear all space.
		win.image.draw(r, cback, nil, (0,0));
	}

	r = p.rect;
	r.max.x = r.min.x + Inset;
	if (has)
		r.max.x += Tagwid;
	if (has){
		r.min.y += Taght;
		if (p.flags&Pdirties)
			r.max.y += Taght;
	}
	r.max.y -= Inset;
	if (has)
		win.image.draw(r, bord[Bw][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));

	r = p.rect;
	r.max.y = r.min.y + Inset;
	if (has)
		r.min.x += Tagwid;
	else
		r.min.x += Inset;
	r.max.x -= Inset;
	if (has)
		win.image.draw(r, bord[Bn][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));

	r = p.rect;
	r.min.y = r.max.y - Inset;
	r.min.x += Inset;
	if (has)
		r.min.x += Tagwid;
	r.max.x -= Inset;
	if (has)
		win.image.draw(r, bord[Bs][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));

	r = p.rect;
	r.min.x = r.max.x - Inset;
	r.min.y += Inset;
	r.max.y -= Inset;
	if (has)
		win.image.draw(r, bord[Be][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));

	r = p.rect;
	r.min.x = r.max.x - Inset;
	r.max.y = r.min.y + Inset;
	if (has)
		win.image.draw(r, bord[Bne][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));
	
	r = p.rect;
	r.min.y = r.max.y - Inset;
	r.min.x = r.max.x - Inset;
	if (has)
		win.image.draw(r, bord[Bse][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));
	
	r = p.rect;
	r.min.y = r.max.y - Inset;
	r.max.x = r.min.x + Inset;
	if (has)
		r.max.x += Tagwid;
	if (has)
		win.image.draw(r, bord[Bsw][k], nil, (0,0));
	else
		win.image.draw(r, bord[Bback][k], nil, (0,0));
	if (has)
		drawtag(p);

	if (0)
	if (has)
		drawspacebar(p, k);
}

pmouse(p: ref Panel, m: ref Cpointer, mc: chan of ref Cpointer)
{
	tagmouse(tree, p, m, mc);
}

zoomto(p: ref Panel, ndir: string)
{
	if (debug['E'])
		fprint(stderr, "zoom to %s\n", ndir);
	tree.layout(ndir);
	pt := p.rect.min.add((Tagwid/2, Taght/2));
	win.wmctl("ptr " + string pt.x + " " + string pt.y);
}

shl(p: ref Panel)
{
	# Take first in "order"
	# Out of tree, anyone could be moving things around.
	cc := p.child;
	if (len cc < 2)
		return;
	cp := cc[0];
	if (cp != nil)
		cp.fsctl(sprint("pos %d\n", len cc), 0);
}

shr(p: ref Panel)
{
	# Take last in "order"
	# Out of tree, anyone could be moving things around
	cc := p.child;
	if (len cc < 2)
		return;
	cp := cc[len cc - 1];
	if (cp != nil)
		cp.fsctl("pos 0\n", 0);
}

pkbd(p: ref Panel, r: int)
{
	Killchar:	con 16r08;

	case r {
	Keyboard->Up =>
		if (intag(p, tree.lastxy))
			tree.size(tree.path(p), Max);
		else
			shl(p);
		tree.tags("/");
		tree.layout(nil);
	Keyboard->Down =>
		if (intag(p, tree.lastxy))
			tree.size(tree.path(p), Min);
		else
			shr(p);
		tree.tags("/");
		tree.layout(nil);
	Keyboard->Left =>
		if (tree.slash == tree.dslash)	# top level
			return;
		ndir := tree.path(tree.dslash);
		zoomto(p, names->dirname(ndir));
	Keyboard->Right =>
		if (len p.path <= len tree.dslash.path)
			return;
		dslash := tree.path(tree.dslash);
		ndir := tree.path(p);
		if (dslash != "/")
			ndir = ndir[len dslash:];
		els := names->elements(ndir[1:]);
		if (els == nil)
			return;
		if (dslash != "/")
			ndir = dslash + "/" + hd els;
		else
			ndir = "/" + hd els;
		zoomto(p, ndir);
	Keyboard->Esc =>
		zoomto(p, "/");
	'\n' =>
		zoomto(p, tree.path(p));
	Keyboard->Ins =>
		p.fsctl("exec New\n", 1);
	Keyboard->Del =>
		p.fsctl("interrupt\n", 1);
	'\b' =>
		p.fsctl("exec Del\n", 1);
	}
}

psync(nil: ref Panel)
{
	# nothing for containers
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.