shithub: libnate

ref: 228a7b0eeda3531eb0bf0efa2211e4532af69681
dir: /n_box.c/

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

#define N_TYPE NBox_Type
char* NBox_Type = "NBox";

Rectangle
box_calcsize(Nelem* nelem, Image* screen, Rectangle r)
{
	NBox* b = (NBox*)nelem;
	GUARD(b);
	if (!b->sizetocontent) {
		r.max = addpt(r.min, b->size);
		b->r = r;
		return r;
	}
	if (!lgetfirst(&b->child)) {
		b->r = r;
		return r;
	}
	Rectangle csize = ncallcalcsize(lgetfirst(&b->child), screen, r);
	b->r = insetrect(csize, b->borderwidth);
	return b->r;
}

static void
box_draw(Nelem* nelem, Image* img)
{
	Nelem* f;
	Rectangle r;
	NBox* b = (NBox*)nelem;
	GUARD(b);
	f = lgetfirst(&b->child);
	if (!f)
		return;

	r = b->r;
	if (b->sizetocontent) {
		r = b->r;
	} else {
		r = b->r;
		r.max = addpt(r.min, b->size);
	}

	border(img, r, b->borderwidth, b->bordercolor, ZP);
	ncalldraw(f, img);
	
	if (nateborders) {
		border(img, r, 1, ncolor.red, ZP);
	}
}

static Nelem*
box_checkhit(Nelem *nelem, Image *screen, Mouse m)
{
	NBox *b = (NBox*)nelem;
	GUARD(b);
	
	if (!b->hitfunc)
		return nd_checkhit(nelem, screen, m);
	
	if (ptinrect(m.xy, b->r))
		return b;
	return nil;
}

int
box_hit(Nelem* nelem, Mouse m)
{
	NBox* b = (NBox*)nelem;
	GUARD(b);
	
	if (b->hitfunc)
		return b->hitfunc(m, b, b->hitaux);
	return 0;
}

void
box_free(Nelem* nelem)
{
	Nelem* ch;
	NBox* b = (NBox*)nelem;
	if (nisroot(b))
		return;
	
	if ((ch = lgetfirst(&b->child)))
		ncallfree(ch);
	free(b);
}

Nlist*
box_getchildren(Nelem* nelem)
{
	NBox* b = (NBox*)nelem;
	GUARD(b);
	return &b->child;
}

static char*
box_getname(Nelem *nelem)
{
	Nelem *ch;
	NBox *b = (NBox*)nelem;
	GUARD(b);
	ch = lgetfirst(&b->child);
	if (!(ch && ch->funcs && ch->funcs->getname))
		return b->name;
	return ch->funcs->getname(ch);
}

static Nelemfunctions Nboxfunctions = {
	.calcsize = box_calcsize,
	.draw = box_draw,
	.checkhit = box_checkhit,
	.hit = box_hit,
	.free = box_free,
	.getchildren = box_getchildren,
	.getname = box_getname,
};

NBox*
box_slot(Nelem* child)
{
	if (child == nc_get()) {
		nc_pop();
	}
	NBox* b = (NBox*)nc_get();
	GUARD(b);
	// TODO: potential leak!
	lsetfirst(&b->child, child);
	return b;
}

DEF_ACCESSOR_TwoParams(NBox, box_border, int, borderwidth, Image*, bordercolor);
DEF_ACCESSOR_OneParam(NBox, box_sizetocontent, int, sizetocontent);
DEF_ACCESSOR_OneParam(NBox, box_size, Point, size);
DEF_ACCESSOR_OneParam(NBox, box_padding, Nmargin, padding);
DEF_ACCESSOR_TwoParams(NBox, box_onclick, OnclickHandler, hitfunc, void*, hitaux);

NBox*
New_Box(char *name)
{
	NBox *b = MakeNelem(NBox, NBox_Type, &Nboxfunctions, name);
	
	b->Slot = box_slot;
	b->Border = box_border;
	b->SizeToContent = box_sizetocontent;
	b->Size = box_size;
	b->OnClick = box_onclick;
	b->Padding = box_padding;
	
	linit(&b->child);
	b->sizetocontent = 0;
	b->size = ZP;
	b->hitfunc = nil;
	b->hitaux = nil;
	b->borderwidth = 0;
	b->bordercolor = display->black;
	nc_push(b);
	return b;
}