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