ref: f759087b2470fc584b7373a9c1ad4a730f4c6c52
dir: /uiglue.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include "common.h" #include "uiglue.h" #include "aux.h" static struct { float *zone; Meta *meta; int nummeta; }decl; char * ui_readstr(UI *ui, int auxtype, char *s, int sz) { char *x, *t; int i; if (auxtype == Xuictl) { if (ui->type < 0 || ui->type >= UInum) sysfatal("unknown ui type %d", ui->type); t = uitypenames[ui->type]; switch (ui->type) { case UITGroup: case UIHGroup: case UIVGroup: snprint(s, sz, "%s\n", t); return s; case UIButton: case UICheckBox: snprint(s, sz, "%s\t%g\n", t, *ui->zone); return s; case UIVSlider: case UIHSlider: case UINEntry: snprint(s, sz, "%s\t%g\t%g\t%g\t%g\t%g\n", t, *ui->zone, ui->init, ui->min, ui->max, ui->step); return s; case UIHBarGraph: case UIVBarGraph: snprint(s, sz, "%s\t%g\t%g\t%g\n", t, *ui->zone, ui->min, ui->max); return s; default: sysfatal("readstr not implemented for ui type %d", ui->type); } } else if (auxtype == Xuimeta) { x = s; *x = 0; for (i = 0; i < ui->nummeta; i++) x = seprint(x, s+sz-1, "%s\t%s\n", ui->meta[i].k, ui->meta[i].v); return s; } else { sysfatal("unsupported ui aux %d", auxtype); } return nil; } int ui_writestr(UI *ui, int auxtype, char *s) { char *e; int failoor; float v; if (auxtype != Xuictl) sysfatal("unsupported ui aux %d", auxtype); /* FIXME optional argument should specify at which frame to apply the change */ v = 0.0f; failoor = 0; if (strncmp(s, "reset", 5) == 0) { /* FIXME reset for a box should reset ALL controls inside it */ v = ui->init; } else if (strncmp(s, "add", 3) == 0) { if (ui->zone != nil) v = *ui->zone + atof(s+3); } else if (strncmp(s, "sub", 3) == 0) { if (ui->zone != nil) v = *ui->zone - atof(s+3); } else { v = strtod(s, &e); if (*e != 0 && *e != '\n') return -1; failoor = 1; } if (ui->zone != nil) { if (ui->type == UIButton || ui->type == UICheckBox) { *ui->zone = v > 0 ? 1 : 0; } else { if (v < ui->min) { if (failoor) return -1; v = ui->min; } else if (v > ui->max) { if (failoor) return -1; v = ui->max; } *ui->zone = v; } } return 0; } static UI * newui(File *f, const char *label, int type) { Aux *a; a = calloc(1, sizeof(*a) + sizeof(UI) + sizeof(Meta)*decl.nummeta); a->type = Xui; a->ui = (UI*)(a+1); a->ui->type = type; a->ui->meta = (Meta*)(a->ui+1); a->ui->nummeta = decl.nummeta; memmove(a->ui->meta, decl.meta, sizeof(Meta)*decl.nummeta); a->ctl = Xuictl; a->metadata = Xuimeta; a->ui->zone = decl.zone; a->ui->label = label; a->ui->readstr = uiglue.readstr != nil ? uiglue.readstr : ui_readstr; a->ui->writestr = uiglue.writestr != nil ? uiglue.writestr : ui_writestr; a->ui->userdata = uiglue.userdata; if ((uiglue.f = createfile(f, label, nil, DMDIR|0775, a)) == nil) sysfatal("failed to create ui: %r"); if ((f = createfile(uiglue.f, "ctl", nil, 0664, &a->ctl)) == nil) sysfatal("failed to create ui ctl: %r"); closefile(f); if ((f = createfile(uiglue.f, "metadata", nil, 0664, &a->metadata)) == nil) sysfatal("failed to create ui metadata: %r"); closefile(f); closefile(uiglue.f); free(decl.meta); decl.zone = nil; decl.meta = nil; decl.nummeta = 0; return a->ui; } static void ui_tgroup(void *f, const char *label) { newui(f, label, UITGroup); } static void ui_hgroup(void *f, const char *label) { newui(f, label, UIHGroup); } static void ui_vgroup(void *f, const char *label) { newui(f, label, UIVGroup); } static void ui_close_group(void *file) { File *f; f = file; uiglue.f = f->parent; } static UI * ui_define(File *f, int type, const char *label, float *zone) { UI *ui; if (zone != decl.zone) { /* no "declare" called before */ decl.zone = zone; free(decl.meta); decl.meta = nil; decl.nummeta = 0; } ui = newui(f, label, type); uiglue.f = f; return ui; } static void ui_button(void *f, const char *label, float *zone) { UI *ui; ui = ui_define(f, UIButton, label, zone); *zone = 0; ui->writestr(ui, Xuictl, "reset"); } static void ui_checkbox(void *f, const char *label, float *zone) { UI *ui; ui = ui_define(f, UICheckBox, label, zone); *zone = 0; ui->writestr(ui, Xuictl, "reset"); } static void ui_vslider(void *f, const char *label, float *zone, float init, float min, float max, float step) { UI *ui; ui = ui_define(f, UIVSlider, label, zone); ui->init = *zone = init; ui->min = min; ui->max = max; ui->step = step; ui->writestr(ui, Xuictl, "reset"); } static void ui_hslider(void *f, const char *label, float *zone, float init, float min, float max, float step) { UI *ui; ui = ui_define(f, UIHSlider, label, zone); ui->init = *zone = init; ui->min = min; ui->max = max; ui->step = step; ui->writestr(ui, Xuictl, "reset"); } static void ui_nentry(void *f, const char *label, float *zone, float init, float min, float max, float step) { UI *ui; ui = ui_define(f, UINEntry, label, zone); ui->init = *zone = init; ui->min = min; ui->max = max; ui->step = step; ui->writestr(ui, Xuictl, "reset"); } static void ui_hbargraph(void *f, const char *label, float *zone, float min, float max) { UI *ui; ui = ui_define(f, UIHBarGraph, label, zone); ui->min = min; ui->max = max; *zone = 0; ui->writestr(ui, Xuictl, "reset"); } static void ui_vbargraph(void *f, const char *label, float *zone, float min, float max) { UI *ui; ui = ui_define(f, UIVBarGraph, label, zone); ui->min = min; ui->max = max; *zone = 0; ui->writestr(ui, Xuictl, "reset"); } static void ui_declare(void *f, float *zone, const char *key, const char *value) { USED(f); if (decl.zone != nil && decl.zone != zone) sysfatal("%s=\"%s\": zone mismatch during declaration (%p != %p)", key, value, decl.zone, zone); decl.zone = zone; decl.meta = realloc(decl.meta, sizeof(Meta)*(decl.nummeta+1)); decl.meta[decl.nummeta].k = key; decl.meta[decl.nummeta].v = value; decl.nummeta++; } UIGlue uiglue = { .openTabBox = ui_tgroup, .openHorizontalBox = ui_hgroup, .openVerticalBox = ui_vgroup, .closeBox = ui_close_group, .addButton = ui_button, .addCheckButton = ui_checkbox, .addVerticalSlider = ui_vslider, .addHorizontalSlider = ui_hslider, .addNumEntry = ui_nentry, .addHorizontalBargraph = ui_hbargraph, .addVerticalBargraph = ui_vbargraph, .declare = ui_declare, };