304 lines · 5.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <fcall.h>#include <thread.h>#include <9p.h>#include "common.h"#include "ui.h"#include "fs.h"#include "uiglue.h" static struct {	float *zone;	Meta *meta;	int nummeta;	int autovoice;	int crossvoice;}decl; File *uif;State *uis; 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%s%s\n", t, *ui->zone,				ui->autovoice ? "\tautovoice" : "",				ui->crossvoice ? "\tcrossvoice" : ""			);			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;} intui_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(const char *label, int type){	Aux *a;	File *f, *d; 	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->state = uis;	a->ui->zone = decl.zone;	a->ui->autovoice = decl.autovoice;	a->ui->crossvoice = decl.crossvoice;	a->ui->label = label;	a->ui->readstr = ui_readstr;	a->ui->writestr = ui_writestr;	if ((d = createfile(uif, label, nil, DMDIR|0775, a)) == nil)		sysfatal("failed to create '%s': %r", label);	if ((f = createfile(d, "ctl", nil, 0664, &a->ctl)) == nil)		sysfatal("failed to create '%s/ctl': %r", label);	closefile(f);	if ((f = createfile(d, "metadata", nil, 0664, &a->metadata)) == nil)		sysfatal("failed to create '%s/metadata': %r", label);	closefile(f);	closefile(d); 	free(decl.meta);	decl.zone = nil;	decl.meta = nil;	decl.nummeta = 0;	decl.autovoice = 0;	decl.crossvoice = 0; 	if (type == UITGroup || type == UIHGroup || type == UIVGroup)		uif = d; 	return a->ui;} static UI *newdef(int type, const char *label, float *zone){	if (zone != decl.zone) { /* no "declare" called before */		decl.zone = zone;		free(decl.meta);		decl.meta = nil;		decl.nummeta = 0;	}	return newui(label, type);} voidui_tgroup(const char *label){	newui(label, UITGroup);} voidui_hgroup(const char *label){	newui(label, UIHGroup);} voidui_vgroup(const char *label){	newui(label, UIVGroup);} voidui_endgroup(void){	uif = uif->parent;} UI *ui_button(const char *label, float *zone){	UI *ui; 	ui = newdef(UIButton, label, zone);	*zone = 0; 	return ui;} UI *ui_checkbox(const char *label, float *zone){	UI *ui; 	ui = newdef(UICheckBox, label, zone);	*zone = 0; 	return ui;} UI *ui_vslider(const char *label, float *zone, float init, float min, float max, float step){	UI *ui; 	ui = newdef(UIVSlider, label, zone);	ui->init = *zone = init;	ui->min = min;	ui->max = max;	ui->step = step; 	return ui;} UI *ui_hslider(const char *label, float *zone, float init, float min, float max, float step){	UI *ui; 	ui = newdef(UIHSlider, label, zone);	ui->init = *zone = init;	ui->min = min;	ui->max = max;	ui->step = step; 	return ui;} UI *ui_nentry(const char *label, float *zone, float init, float min, float max, float step){	UI *ui; 	ui = newdef(UINEntry, label, zone);	ui->init = *zone = init;	ui->min = min;	ui->max = max;	ui->step = step; 	return ui;} UI *ui_hbargraph(const char *label, float *zone, float min, float max){	UI *ui; 	ui = newdef(UIHBarGraph, label, zone);	ui->min = min;	ui->max = max;	*zone = 0; 	return ui;} UI *ui_vbargraph(const char *label, float *zone, float min, float max){	UI *ui; 	ui = newdef(UIVBarGraph, label, zone);	ui->min = min;	ui->max = max;	*zone = 0; 	return ui;} voidui_declare(float *zone, const char *key, const char *value){	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++;	if (strcmp(key, "autovoice") == 0)		decl.autovoice = 1;	else if (strcmp(key, "crossvoice") == 0)		decl.crossvoice = 1;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t