ref: 37d050563f02063f183566ee75c767da1e4e70be
dir: /layer.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <memdraw.h> #include <event.h> #include <bio.h> #include "blie.h" char Ebadfmt[] = "bad file format: "; typedef struct List List; struct List { Layer *layer; List *next; }; List *firstlayer = nil; static Drawop str2op(char *s) { #define OP(n) if (!strcmp(s, "n")) { return n; } OP(Clear); OP(SinD); OP(DinS); OP(SoutD); OP(DoutS); OP(S); OP(SoverD); OP(SatopD); OP(SxorD); OP(D); OP(DoverS); OP(DatopS); OP(DxorS); #undef OP return SoverD; } static char* op2str(Drawop op) { #define OP(n) if (op == n) { return "n"; } OP(Clear); OP(SinD); OP(DinS); OP(SoutD); OP(DoutS); OP(S); OP(SoverD); OP(SatopD); OP(SxorD); OP(D); OP(DoverS); OP(DatopS); OP(DxorS); #undef OP return "SoverD"; } static void _renum(Layer *l, int id, int, void*) { l->num = id; } static void renumlayers(void) { foreachlayer(_renum, nil); } static void addlayerl(Layer *l) { List *f; if (!firstlayer) { firstlayer = mallocz(sizeof(List), 1); firstlayer->layer = l; l->num = 0; return; } for (f = firstlayer; f->next; f = f->next) continue; f->next = mallocz(sizeof(List), 1); f->next->layer = l; l->num = f->layer->num + 1; } void addlayer(char *name) { Biobuf *b; char *file; char *ed, *lbl, *op; Layer *l; if (!name || !name[0]) return; file = smprint("%s/meta", name); b = Bopen(file, OREAD); free(file); if (!b) sysfatal("error opening file %s/meta: %r", name); ed = Brdstr(b, '\n', 1); if (!ed) sysfatal("%s%s/meta: missing editor", Ebadfmt, name); lbl = Brdstr(b, '\n', 1); if (!lbl) sysfatal("%s%s/meta: missing label", Ebadfmt, name); op = Brdstr(b, '\n', 1); if (!op) sysfatal("%s%s/meta: missing drawop", Ebadfmt, name); l = mallocz(sizeof(Layer), 1); l->name = strdup(name); l->label = strdup(lbl); l->editor = geteditor(ed); l->op = str2op(op); if (!l->editor) sysfatal("editor %s not found for %s", ed, name); addlayerl(l); free(lbl); free(ed); free(op); Bterm(b); } void movelayer(Layer *layer, int dir) { List *parent; List *l; if (firstlayer->layer == layer) { if (dir == DOWN) { l = firstlayer->next; firstlayer->next = l ? l->next : nil; l->next = firstlayer; firstlayer = l; return; } if (dir == UP) return; /* NOP */ } /* find parent */ for (l = firstlayer; l && l->next->layer != layer; l = l->next) continue; if (!l) return; /* not found */ parent = l; if (dir == DOWN) goto Movedown; if (dir != UP) sysfatal("code error: direction != UP|DOWN"); /* movelayer(layer, UP) == movelayer(parent, DOWN) */ movelayer(parent->layer, DOWN); return; Movedown: l = parent->next; if (!l) return; /* NOP: last element */ parent->next = l->next; l->next = l->next ? l->next->next : nil; parent->next->next = l; // TODO: verify! l->layer->num--; if (l->next) l->next->layer->num++; } void dirtylayer(Layer *layer) { if (layer->composited) freememimage(layer->composited); layer->composited = nil; } void savelayermeta(Layer *layer) { Biobuf *b; char *file; file = smprint("%s.meta", layer->name); b = Bopen(file, OWRITE|OTRUNC); free(file); if (!b) sysfatal("error opening file %s.meta for write: %r", layer->name); Bprint(b, "%s\n%s\n", layer->editor->name, layer->label); Bterm(b); } int foreachlayer(void (*f)(Layer*, int, int, void*), void* aux) { List *l; int i; i = 0; for (l = firstlayer; l; l = l->next, i++) { f(l->layer, i, !l->next, aux); } return i; } int layerheight; static void redrawlayer(Layer *l, int n, int, void *aux) { void **data; Image *img; Layer *active; Point p; Rectangle r; data = (void**)aux; img = data[0]; active = data[1]; p = img->r.min; p.y += n * layerheight; if (l == active) { r.min = r.max = p; r.max.x += vdata.layerwinwidth; r.max.y += layerheight; draw(img, r, vdata.gray, nil, ZP); } string(img, addpt(p, Pt(2, 2)), display->black, ZP, font, l->label); } void redrawlayers(Image *img, Layer *active) { void *data[2]; data[0] = img; data[1] = active; layerheight = vdata.fontheight + 10; draw(img, img->r, display->white, nil, ZP); foreachlayer(redrawlayer, data); line(img, img->r.min, Pt(img->r.min.x, img->r.max.y), Endsquare, Endsquare, 0, display->black, ZP); } static void checkclick(Layer *l, int n, int, void *aux) { void **a; void (*factivate)(Layer*); int *w; a = (void**)aux; factivate = a[0]; w = a[1]; if (n == *w) factivate(l); } void clicklayer(Mouse m, void (*f)(Layer*)) { void *aux[2]; int d; aux[0] = f; aux[1] = &d; d = m.xy.y / layerheight; foreachlayer(checkclick, aux); }