shithub: libnate

ref: aab184987c79fc7a8e5467200f9ac448700b797f
dir: /nate_construct.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include "nate.h"
#include "nate_construct.h"

typedef struct NCelem NCelem;
struct NCelem {
	Nelem* elem;
	NCelem* next;
};

static NCelem* nc_stack = nil;

void
nc_init()
{
	nc_stack = nil;
}

void
nc_push(Nelem* nelem)
{
	NCelem *n;
	if (!nc_stack) {
		nc_stack = malloc(sizeof(NCelem));
		assert(nc_stack);
		nc_stack->next = nil;
		nc_stack->elem = nelem;
	} else {
		n = malloc(sizeof(NCelem));
		assert(n);
		n->next = nc_stack;
		n->elem = nelem;
		nc_stack = n;
	}
}

void
nc_pop()
{
	if (!nc_stack)
		return;
	NCelem *nc = nc_stack;
	nc_stack = nc->next;
	free(nc);
}

Nelem*
nc_get()
{
	return nc_stack ? nc_stack->elem : nil;
}

typedef struct chparams chparams;
struct chparams {
	Nelem *retelem;
	Image *screen;
	Mouse mouse;
};

static void
fe_checkhit(Nelem* elem, int, void *aux)
{
	chparams *p = (chparams*)aux;
	Rectangle r;
	Nelem* e;
	
	if (p->retelem)
		return;
	
	if (!ptinrect(p->mouse.xy, elem->slot.r))
		return;
	
	e = ncallcheckhit(elem, p->screen, p->mouse);
	nctracehitlevel--;
	if (e) {
		p->retelem = e;
	}
}

Nelem*
nd_checkhit(Nelem* nelem, Image* screen, Mouse m)
{
	chparams params;
	Nlist* l = ncallgetchildren(nelem);
	
	if (!l)
		return nil;
	
	params.retelem = nil;
	params.screen = screen;
	params.mouse = m;
	lforeach(l, fe_checkhit, &params);
	
	return params.retelem;
}

void
nd_free(Nelem *el)
{
	if (nisroot(el))
		return;
	lfreelist(&el->children);
	free(el);
}

Nelem*
makenelem(long size, char *type, Nelemfunctions *funcs, Nelemaccessors *accs, char *name, int nchildren)
{
	Nelem *nel = mallocz(size, 1);
	if (!nel)
		sysfatal("oom: creating nelem %s", type);
	accs->type = type;
	nel->type = type;
	nel->name = name;
	nel->funcs = funcs;
	nel->accs = accs;
	nel->nchildren = nchildren;
	linit(&nel->children);
	return nel;
}

void
nc_addchild(Nelem *parent, Nelem *child)
{
	if (parent->nchildren < 0)
		goto Add;
	
	if (!parent->nchildren) {
		sysfatal("invalid add to parent: %s is leaf", parent->type);
	}
	
	if (parent->children.num + 1 > parent->nchildren) {
		sysfatal("children count exhausted: parent %s supports %d children", parent->type, parent->nchildren);
	}
	
Add:
	ladd(&parent->children, child);
}

int nctracehitlevel = 0;
void
nctracehit(Nelem *el, int pt)
{
	char *name;
	if (natedebugfd < 0)
		return;
	if (nctracehitlevel < 0)
		return;
	if (el->funcs && el->funcs->getname)
		name = el->funcs->getname(el);
	else
		name = el->name;
	fprint(natedebugfd, "HIT: %*s%c%s%c %c%s%c\n",
		nctracehitlevel * 3, nctracehitlevel?"↘":"", /* indent */
		pt ? '(' : ' ', el->type, pt ? ')' : ' ', /* Nelem type */
		name?'\"':' ', name ? name : "", name?'\"':' '); /* name */
}