ref: e71361d5f47f408ca3192ecdf2a44de48c0aeef9
dir: /ui/ui.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <mouse.h> #include <keyboard.h> #include <thread.h> enum { Dback = 0, Dfhigh, Dfmed, Dflow, Dfinv, Dbhigh, Dbmed, Dblow, Dbinv, Numcolors, Knobleft360 = 0<<0, Knobtop180 = 1<<0, Knobvaluetop = 0<<1, Knobvaluebot = 1<<1, }; #define MIN(a,b) ((a)<=(b)?(a):(b)) #define MAX(a,b) ((a)>=(b)?(a):(b)) static struct { char *id; u32int color; }theme[Numcolors] = { [Dback] = {"background", 0x000000}, [Dfhigh] = {"f_high", 0xffffff}, [Dfmed] = {"f_med", 0x777777}, [Dflow] = {"f_low", 0x444444}, [Dfinv] = {"f_inv", 0x000000}, [Dbhigh] = {"b_high", 0xdddddd}, [Dbmed] = {"b_med", 0x72dec2}, [Dblow] = {"b_low", 0x222222}, [Dbinv] = {"b_inv", 0xffb545}, }; typedef struct Style Style; struct Style { struct { int r; int w; }knob; int margin; Font *font; }; static Style style = { .knob = { .r = 24, .w = 4, }, .margin = 4, }; static Image *color[Numcolors]; static Rectangle knobs[8][2]; static Rectangle knob(Rectangle r, char *d, char *vs, float v, int kt) { Point c, t, p0, p1; int a, hw, dw, vw; dw = stringwidth(style.font, d); vw = stringwidth(style.font, vs); hw = MAX(style.knob.r, MAX(dw, vw)/2); /* "half width", center of the component */ r.max = r.min; r.max.x += hw*2; /* value */ if (vw > 0 && !(kt&Knobvaluebot)) { valuebot: t.x = r.min.x + hw - vw/2; t.y = r.max.y; string(screen, t, color[Dfhigh], ZP, style.font, vs); r.max.y = t.y + style.font->height + style.margin; if (kt & Knobvaluebot) return r; } /* knob */ a = (kt&Knobtop180) ? 90 : 180; v = v*((kt&Knobtop180) ? -180 : -360); c.x = r.min.x + Dx(r)/2; c.y = r.max.y + style.knob.r; fillarc(screen, c, style.knob.r, style.knob.r, color[Dfhigh], ZP, a, v); fillellipse(screen, c, style.knob.r-style.knob.w, style.knob.r-style.knob.w, color[Dflow], ZP); icossin(a+v, &p0.x, &p0.y); p1.x = c.x + p0.x*(style.knob.r-style.knob.w*4/3)/1024; p1.y = c.y - p0.y*(style.knob.r-style.knob.w*4/3)/1024; p0.x = c.x + p0.x*style.knob.w/1024; p0.y = c.y - p0.y*style.knob.w/1024; line(screen, p0, p1, 0, 0, 0, color[Dfhigh], ZP); r.max.y += 2*style.knob.r; /* description */ if (dw > 0) { t.x = r.min.x + hw - dw/2; t.y = r.max.y + style.margin; string(screen, t, color[Dfhigh], ZP, style.font, d); r.max.y = t.y + style.font->height; } if (kt & Knobvaluebot) { r.max.y += style.margin; goto valuebot; } return r; } static void redraw(void) { float f; Rectangle r, t; char s[16]; int i; lockdisplay(display); r = screen->r; draw(screen, r, color[Dback], nil, ZP); r.min.x += style.margin; r.min.y += style.margin; for (i = 0; i < nelem(knobs); i++) { f = (i+1)*0.1; sprint(s, "%g", f); t = knob(r, nil, s+1, f, Knobleft360); knobs[i][0] = t; r.min.y += Dy(t) + 2*style.margin; f = (i-4)*0.2; sprint(s, "%+g", f); if (s[2] != 0) s[1] = s[0]; knobs[i][1] = knob(r, nil, s+1, f, Knobtop180|Knobvaluebot); r = t; r.min.x += Dx(r) + 2*style.margin; } flushimage(display, 1); unlockdisplay(display); } void threadmain(int argc, char **argv) { Mousectl *mctl; Keyboardctl *kctl; Rune key; Mouse m; int n, oldbuttons; Point oldxy; float zoom, oldzoom; Style s; Alt a[] = { { nil, &m, CHANRCV }, { nil, nil, CHANRCV }, { nil, &key, CHANRCV }, { nil, nil, CHANEND }, }; USED(argc); USED(argv); if (initdraw(nil, nil, "daw/ui") < 0) sysfatal("initdraw: %r"); style.font = font; display->locking = 1; unlockdisplay(display); if ((mctl = initmouse(nil, screen)) == nil) sysfatal("initmouse: %r"); if ((kctl = initkeyboard(nil)) == nil) sysfatal("initkeyboard: %r"); for (n = 0; n < Numcolors; n++) color[n] = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, theme[n].color<<8 | 0xff); a[0].c = mctl->c; a[1].c = mctl->resizec; a[2].c = kctl->c; threadsetname("daw/ui"); redraw(); oldbuttons = 0; oldxy = ZP; memmove(&s, &style, sizeof(s)); oldzoom = 1.0f; for (;;) { switch (alt(a)) { case 0: /* mouse */ if (m.buttons == 2) { if (oldbuttons == 0) { oldxy = m.xy; } else if (oldbuttons == 2) { zoom = MAX(0, oldzoom + m.xy.y-oldxy.y); style.knob.r = s.knob.r*(1 + zoom/100.f); style.knob.w = s.knob.w*(1 + zoom/100.f); redraw(); } } else if (m.buttons == 0) { if (oldbuttons == 2) oldzoom = zoom; } oldbuttons = m.buttons; break; case 1: /* resize */ getwindow(display, Refnone); redraw(); break; case 2: /* keyboard */ switch (key) { case Kdel: goto end; } break; } } end: threadexitsall(nil); }