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
}
|