ref: b8ce27374966893fe7ee3b587051161421ff0173
dir: /plumbto.c/
#include <u.h>
#include <libc.h>
#include <plumb.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include <control.h>
enum
{
Maxchans = 16,
Padding = 4,
};
enum
{
BACK,
TEXT,
SEL,
NCOLS,
};
int wfd;
Mousectl *mc;
Keyboardctl *kc;
Image *cols[NCOLS];
Point headerp;
Rectangle listr;
int sel = -1;
int plumbfd;
Channel *plumbc;
Plumbmsg *pm;
char *chans[Maxchans];
usize nchans;
void
plumbto(char *chan)
{
pm->attr = plumbdelattr(pm->attr, "channels");
pm->dst = strdup(chan);
plumbsend(plumbfd, pm);
plumbfree(pm);
pm = nil;
nchans = 0;
}
void
drawwait(void)
{
string(screen, headerp, cols[SEL], ZP, font, "waiting for plumb message...");
}
void
drawline(int index, int selected)
{
Point p, q;
Image *c;
p = Pt(listr.min.x, listr.min.y + index*font->height);
q = addpt(p, Pt(Dx(listr), font->height));
c = selected ? cols[SEL] : cols[BACK];
draw(screen, Rpt(p, q), c, nil, ZP);
p = string(screen, p, cols[TEXT], ZP, font, "» ");
string(screen, p, cols[TEXT], ZP, font, chans[index]);
}
void
redraw(void)
{
char *f, buf[1024] = {0};
int i;
lockdisplay(display);
draw(screen, screen->r, cols[BACK], nil, ZP);
if(pm == nil){
drawwait();
flushimage(display, 1);
unlockdisplay(display);
return;
}
f = plumblookup(pm->attr, "filename");
if(f != nil)
snprint(buf, sizeof buf, "Plumb '%s' to:", f);
else
snprint(buf, sizeof buf, "Plumb data to:");
string(screen, headerp, cols[TEXT], ZP, font, buf);
for(i = 0; i < nchans; i++){
drawline(i, 0);
}
flushimage(display, 1);
unlockdisplay(display);
}
void
evtresize(void)
{
headerp = addpt(screen->r.min, Pt(Padding, Padding));
listr = Rect(screen->r.min.x + Padding,
screen->r.min.y + Padding + font->height + Padding,
screen->r.max.x - Padding,
screen->r.max.y - Padding);
redraw();
}
void
evtmouse(Mouse *m)
{
int n;
if(!ptinrect(m->xy, listr)){
if(sel != -1){
sel = -1;
redraw();
}
return;
}
n = (m->xy.y - listr.min.y) / font->height;
if(m->buttons == 0){
if(n >= nchans){
sel = -1;
redraw();
}else if(n != sel){
if(sel != -1)
drawline(sel, 0);
drawline(n, 1);
flushimage(display, 1);
sel = n;
}
}else if(m->buttons == 1){
if(sel != -1){
sel = -1;
plumbto(chans[n]);
redraw();
fprint(wfd, "hide\n");
}
}
}
void
evtkeyboard(Rune k)
{
if(k == Kdel)
threadexitsall(nil);
}
void
evtplumb(Plumbmsg *p)
{
fprint(wfd, "unhide\n");
pm = p;
redraw();
}
void
initcols(void)
{
cols[BACK] = display->white;
cols[TEXT] = display->black;
cols[SEL] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xccccccff);
}
void
plumbproc(void *v)
{
Channel *c;
Plumbmsg *p;
int fd;
char *s;
c = v;
fd = plumbopen("chanselect", OREAD);
if(fd < 0)
sysfatal("plumbopen: %r");
for(;;){
p = plumbrecv(fd);
if(p == nil)
break;
s = plumblookup(p->attr, "channels");
if(s == nil || s[0] == 0){
plumbfree(p);
continue;
}
nchans = getfields(s, chans, nelem(chans), 0, ",");
if(nchans != 0)
sendp(c, p);
else
plumbfree(p);
}
threadexits(nil);
}
void
threadmain(int argc, char *argv[])
{
enum { Emouse, Eresize, Ekeyboard, Eplumb, };
Mouse m;
Rune k;
Plumbmsg *p;
Alt a[] = {
{ nil, &m, CHANRCV },
{ nil, nil, CHANRCV },
{ nil, &k, CHANRCV },
{ nil, &p, CHANRCV },
{ nil, nil, CHANEND },
};
ARGBEGIN{
}ARGEND;
nchans = 0;
if(initdraw(nil, nil, argv0) < 0)
sysfatal("initdisplay: %r");
unlockdisplay(display);
if((wfd = open("/dev/wctl", OWRITE)) < 0)
sysfatal("open: %r");
fprint(wfd, "hide\n");
if((mc = initmouse(nil, screen)) == nil)
sysfatal("initmouse: %r");
if((kc = initkeyboard(nil)) == nil)
sysfatal("initkeyboard: %r");
plumbfd = plumbopen("send", OWRITE);
if(plumbfd < 0)
sysfatal("plumbopen: %r");
plumbc = chancreate(sizeof(Plumbmsg*), 0);
if(plumbc == nil)
sysfatal("initchan: %r");
proccreate(plumbproc, plumbc, 8192);
a[Emouse].c = mc->c;
a[Eresize].c = mc->resizec;
a[Ekeyboard].c = kc->c;
a[Eplumb].c = plumbc;
initcols();
evtresize();
for(;;){
switch(alt(a)){
case Emouse:
evtmouse(&m);
break;
case Eresize:
if(getwindow(display, Refnone) < 0)
sysfatal("getwindow: %r");
evtresize();
break;
case Ekeyboard:
evtkeyboard(k);
break;
case Eplumb:
evtplumb(p);
break;
}
}
}