shithub: guifs

ref: 58363833ce933924ef340eb53f0caa4d0d1f6ae5
dir: /props.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <ctype.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <mouse.h>

#include "guifs.h"

#define Eparse "could not parse property"

int
allspace(char *r)
{
	while(*r){
		if(!isspace(*r))
			return 0;
		r++;
	}
	return 1;
}

PropVal
defcolour(int gtag, int ptag)
{
	PropVal v;
	ulong col = DTransparent;

	switch(ptag){
	case Pbackground:
		switch(gtag){
		case Gcontainer:
			col = DWhite;
			break;
		case Gtextbox:
			col = 0xFFFFEAFF;
			break;
		}
		break;
	case Pbordercolour:
		switch(gtag){
		case Gtextbox:
			col = DYellowgreen;
			break;
		default:
			col = DRed;
			break;
		}
		break;
	case Ptextcolour:
		col = DBlack;
		break;
	}

	v.colour = mkcolour(col);
	return v;
}

PropVal
defspacing(int gtag, int ptag)
{
	PropVal v;
	v.spacing = emalloc(sizeof(Spacing));

	int space = 0;

	switch(ptag){
	case Pborder:
		switch(gtag){
		case Gtextbox:
			space = 4;
			break;
		}
		break;
	case Ppadding:
		switch(gtag){
		case Gtextbox:
			space = 2;
			break;
		}
		break;
	}
	v.spacing->up = v.spacing->down = v.spacing->left = v.spacing->right = space;
	return v;
}

PropVal
deforientation(int gtag, int ptag)
{
	USED(gtag);
	USED(ptag);

	PropVal v;
	v.orientation = Horizontal;
	return v;
}

PropVal
deftext(int gtag, int ptag)
{
	USED(gtag);
	USED(ptag);

	PropVal v;
	v.text = emalloc(sizeof(Rune));
	v.text[0] = 0;
	return v;
}

char *
printcolour(PropVal p)
{
	int bufsize = 64;
	char *buf = emalloc(bufsize);
	snprint(buf, bufsize, "%08ulX\n", p.colour->code);
	return buf;
}

char *
printspacing(PropVal p)
{
	int bufsize = 256;
	char *buf = emalloc(bufsize);
	snprint(buf, bufsize, "%d %d %d %d\n", p.spacing->up, p.spacing->right, p.spacing->down, p.spacing->left);
	return buf;
}

char *
printorientation(PropVal p)
{
	char *str;
	switch(p.orientation){
	case Horizontal:
		str = estrdup9p("horizontal\n");
		break;
	case Vertical:
		str = estrdup9p("vertical\n");
		break;
	default:
		str = estrdup9p("???\n");
		break;
	}
	return str;
}

char *
printtext(PropVal p)
{
	char *str = smprint("%S", p.text);
	if(str == nil)
		sysfatal("smprint failed");
	return str;
}

char *
parsecolour(char *str, PropVal *p)
{
	char *r;
	ulong c = strtoul(str, &r, 16);
	if((r - str) != 8 || !allspace(r))
		return Eparse;
	(*p).colour = mkcolour(c);
	return nil;
}

char *
parsespacing(char *str, PropVal *p)
{
	USED(p);
	char *fields[5];
	int spacings[4];

	int n = getfields(str, fields, nelem(fields), 0, " ");
	if(!(n == 4 || n == 2 || n == 1))
		return Eparse;

	for(int i = 0; i < n; i++){
		char *r;
		spacings[i] = strtol(fields[i], &r, 10);
		if(!allspace(r))
			return Eparse;
	}

	Spacing *s = emalloc(sizeof(Spacing));
	switch(n){
	case 1:
		s->up = s->down = s->left = s->right = spacings[0];
		break;
	case 2:
		s->up = s->down = spacings[0];
		s->left = s->right = spacings[1];
		break;
	case 4:
		s->up = spacings[0];
		s->right = spacings[1];
		s->down = spacings[2];
		s->left = spacings[3];
		break;
	}
	(*p).spacing = s;

	return nil;
}

char *
parseorientation(char *str, PropVal *p)
{
	if(strncmp(str, "horizontal", 10) == 0 && allspace(str+10))
		(*p).orientation = Horizontal;
	else if(strncmp(str, "vertical", 8) == 0 && allspace(str+8))
		(*p).orientation = Vertical;
	else
		return Eparse;
	return nil;
}

char *
parsetext(char *str, PropVal *p)
{
	Rune *rstr = runesmprint("%s", str);
	if(rstr == nil)
		sysfatal("runesmprint failed");
	(*p).text = rstr;
	return nil;
}

PropVal
getprop(GuiElement *g, int tag, int lock)
{
	PropVal *v = nil;
	if(lock)
		rlock(&g->lock);
	for(int i = 0; i < g->nprops && v == nil; i++)
		if(g->props[i].tag == tag)
			v = &g->props[i].val;
	if(lock)
		runlock(&g->lock);

	if(v == nil)
		sysfatal("invalid prop for this gui element");
	else
		return *v;
}

void
setprop(GuiElement *g, int tag, PropVal val, int lock)
{
	if(lock)
		wlock(&g->lock);
	/* TODO: free old propval */
	for(int i = 0; i < g->nprops; i++)
		if(g->props[i].tag == tag)
			g->props[i].val = val;
	if(lock){
		wunlock(&g->lock);
		updategui(0); /* Can't update gui if the user has write-locked g */
	}
}

PropSpec propspecs[Pmax] = {
	[Pbackground] = {"background",	defcolour,	printcolour,	parsecolour},
	[Pborder] = {"border", 	defspacing,	printspacing,	parsespacing},
	[Pmargin] = {"margin", 	defspacing,	printspacing,	parsespacing},
	[Ppadding] = {"padding", defspacing,	printspacing,	parsespacing},
	[Porientation] = {"orientation",	deforientation,	printorientation,	parseorientation},
	[Pbordercolour] = {"bordercolour",	defcolour,	printcolour,	parsecolour},
	[Ptext] = {"text",	deftext,	printtext,	parsetext},
	[Ptextcolour] = {"textcolour",	defcolour,	printcolour,	parsecolour},
};

int baseprops[nbaseprops] = {Pbackground, Pborder, Pmargin, Ppadding, Pbordercolour};