shithub: libnate

ref: a0b15f88e6274b4892061a7dfe790d85eb211078
dir: /n_vbox.c/

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

#define N_TYPE NVBox_Type
char* NVBox_Type = "NVBox";

Point currentsize;
Image* currentscreen;

void
vbox_childsize(Nelem* nelem, int)
{
	Point p = ncallcalcsize(nelem, currentscreen);
	currentsize.x = currentsize.x > p.x ? currentsize.x : p.x;
	currentsize.y += p.y;
}

Point
vbox_calcsize(Nelem* nelem, Image* screen)
{
	NVBox* b = (NVBox*)nelem;
	GUARD(b);
	
	currentsize = Pt(0, 0);
	currentscreen = screen;
	
	lforeach(&b->children, vbox_childsize);

	return currentsize;
}

Rectangle currentrect;
Image* currentimg;

void
vbox_childdraw(Nelem* elem, int)
{
	Point p = ncallcalcsize(elem, currentimg);
	currentrect.max.y = currentrect.min.y + p.y;
	ncalldraw(elem, currentimg, currentrect);
	currentrect.min.y = currentrect.max.y;
}

void
vbox_draw(Nelem* nelem, Image* img, Rectangle r)
{
	NVBox* b = (NVBox*)nelem;
	GUARD(b);

	if (b->sizetocontent) {
		r.max = addpt(r.min, ncallcalcsize(b, img));
	}
	
	currentrect = r;
	currentimg = img;
	lforeach(&b->children, vbox_childdraw);
}

Nelem* ch_ret;
Image* ch_screen;
Rectangle ch_rect;
Mouse ch_mouse;

void
vbox_fe_checkhit(Nelem* nelem, int)
{
	Point s;
	Nelem* e;
	Rectangle r;
	
	s = ncallcalcsize(nelem, ch_screen);
	r.min = ch_rect.min;
	r.max = addpt(r.min, s);
	
	if (!ptinrect(ch_mouse.xy, r)) {
		ch_rect.min.y += s.y;
		return;
	}
	
	e = ncallcheckhit(nelem, ch_screen, r, ch_mouse);
	ch_rect.min.y += s.y;
	if (e) {
		ch_ret = e;
	}
}

Nelem*
vbox_checkhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
{
	NVBox* b = (NVBox*)nelem;
	GUARD(b);
	
	ch_ret = nil;
	ch_screen = screen;
	ch_rect = r;
	ch_mouse = m;
	
	ch_rect.max.y = ch_rect.min.y;
	
	lforeach(&b->children, vbox_fe_checkhit);
	return ch_ret;
}

int
vbox_hit(Nelem* nelem, Mouse m)
{
	GUARD(nelem);
	return -1;
}

void
vbox_free(Nelem* nelem)
{
	NVBox* b = (NVBox*)nelem;
	if (nisroot(b))
		return;
	
	lfreelist(&b->children);
	free(b);
}

Nlist*
vbox_getchildren(Nelem* nelem)
{
	NVBox* b = (NVBox*)nelem;
	GUARD(b);
	return &b->children;
}

static Nelemfunctions Nvboxfunctions = {
	.calcsize = vbox_calcsize,
	.draw = vbox_draw,
	.checkhit = vbox_checkhit,
	.hit = vbox_hit,
	.free = vbox_free,
	.getchildren = vbox_getchildren,
};

NVBox*
vbox_slot(Nelem* child)
{
	if (child == nc_get()) {
		nc_pop();
	}
	NVBox* b = (NVBox*)nc_get();
	GUARD(b);
	
	ladd(&b->children, child);
	return b;
}

NVBox*
vbox_sizetocontent(int stc)
{
	NVBox* b = (NVBox*)nc_get();
	GUARD(b);
	b->sizetocontent = stc;
	return b;
}

NVBox*
New_VBox(void)
{
	NVBox* b = malloc(sizeof(NVBox));
	assert(b);
	
	b->type = NVBox_Type;
	b->funcs = &Nvboxfunctions;
	
	b->Slot = vbox_slot;
	b->SizeToContent = vbox_sizetocontent;
	
	linit(&b->children);
	b->sizetocontent = 0;
	nc_push(b);
	return b;
}