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 }