shithub: libnate

ref: 6ff9ef0c4bef23bfd91f33f0c2f5cab0b88c0307
dir: /nate.c/

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

static Nlist rootchain = { nil };
static Nelem* rootelem = nil;

void
nregroot(Nelem* nelem)
{
	assert(nelem);

	// root must be inside rootchain
	nregister(nelem);

	if (rootelem)
		ncallfree(rootelem);

	rootelem = nelem;
}

void
nregister(Nelem* nelem)
{
	if (lhas(&rootchain, nelem))
		return;
		
	ladd(&rootchain, nelem);
}

void
nderegister(Nelem* nelem)
{
	ldel(&rootchain, nelem);
}

void
nforeachroot(void (*f)(Nelem*, int))
{
	lforeach(&rootchain, f);
}

int
nisroot(Nelem* nelem)
{
	return lhas(&rootchain, nelem);
}

void
linit(Nlist* list)
{
	list->first = nil;
}

int
lhas(Nlist* list, Nelem* item)
{
	Nlistelem* l = list->first;
	while (l) {
		if (l->item == item)
			return 1;
		l = l->next;
	}
	return 0;
}

void
ladd(Nlist* list, Nelem* item)
{
	Nlistelem* l;
	if (!list->first) {
		list->first = malloc(sizeof(Nlist));
		assert(list->first);
		list->first->item = item;
		list->first->next = nil;
		return;
	}
	
	l = list->first;
	while (l->next)
		l = l->next;
	
	l->next = malloc(sizeof(Nlist));
	assert(l->next);
	l->next->item = item;
	l->next->next = nil;
}

void
ldel(Nlist* list, Nelem* item)
{
	Nlistelem* l, *a;
	if (!list->first)
		return;
	
	l = list->first;
	while (l->next && l->next->item != item)
		l = l->next;
	
	a = l->next;
	l->next = a->next;
	free(a);
}

void
linsert(Nlist* list, Nelem* before, Nelem* item)
{
	Nlistelem* l = list->first, *a;
	while (l->next && l->item != before)
		l = l->next;
	
	a = l->next;
	l->next = malloc(sizeof(Nlist));
	l->next->next = a;
	l->next->item = item;
}

void
lforeach(Nlist* list, void (*f)(Nelem*, int))
{
	Nlistelem* l = list->first;
	for (int i = 0; l; i++) {
		f(l->item, i);
		l = l->next;
	}
}

void
lfreelist(Nlist* list)
{
	Nlistelem* a;
	Nlistelem* l = list->first;
	while (l) {
		a = l->next;
		if (l->item)
			free(l->item);
		free(l);
		l = a;
	}
}

Nelem*
lgetfirst(Nlist* list)
{
	return list->first ? list->first->item : nil;
}

Nelem*
lsetfirst(Nlist* list, Nelem* item)
{
	Nelem* f = lgetfirst(list);
	if (list->first) {
		list->first->item = item;
		return f;
	}
	list->first = malloc(sizeof(Nlistelem));
	list->first->next = nil;
	list->first->item = item;
	return f;
}

void
ncallfree(Nelem* nelem)
{
	assert(nelem);
	
	if (nisroot(nelem))
		return;
	
	if (nelem->funcs && nelem->funcs->free)
		nelem->funcs->free(nelem);
}

Point
ncallcalcsize(Nelem* nelem, Image* dst)
{
	assert(nelem);
	
	if (nelem->funcs && nelem->funcs->calcsize)
		return nelem->funcs->calcsize(nelem, dst);
	
	return Pt(0,0);
}

void
ncalldraw(Nelem* nelem, Image* dst, Rectangle r)
{
	assert(nelem);
	
	if (nelem->funcs && nelem->funcs->draw)
		nelem->funcs->draw(nelem, dst, r);
}

Nelem*
ncallcheckhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
{
	assert(nelem);
	
	if (nelem->funcs && nelem->funcs->checkhit)
		return nelem->funcs->checkhit(nelem, screen, r, m);
	return nil;
}

int
ncallhit(Nelem* nelem, Mouse m)
{
	assert(nelem);
	
	if (nelem->funcs && nelem->funcs->hit)
		return nelem->funcs->hit(nelem, m);
	return 0;
}

Nlist*
ncallgetchildren(Nelem* nelem)
{
	assert(nelem);
	
	if (nelem->funcs && nelem->funcs->getchildren)
		return nelem->funcs->getchildren(nelem);
	return nil;
}

Nelem*
nassign(Nelem** dst, Nelem* src)
{
	assert(dst && src);
	*dst = src;
	return src;
}

void
nateinit()
{
	nc_init();
}

void
nateredraw()
{
	if (!rootelem)
		return;
	
	ncalldraw(rootelem, screen, screen->r);
}

int
natemouseevent(Mouse m)
{
	Nelem* el;
	Point s;
	Rectangle r;
	
	if (!rootelem)
		return 0;
	
	s = ncallcalcsize(rootelem, screen);
	r.min = screen->r.min;
	r.max = addpt(r.min, s);
	
	if (!ptinrect(m.xy, r))
		return 0;
	
	el = ncallcheckhit(rootelem, screen, screen->r, m);
	if (!el)
		return 0;
	
	return ncallhit(el, m);
}