shithub: libnate

ref: 69e287559e1faed50092d64659c5bc02f9bf395c
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";

typedef struct csizep csizep;
struct csizep {
	Rectangle crect;
	Image *screen;
	int autoheight;
	int fillwidth;
};

static void
childsize(Nelem* nelem, int, void *aux)
{
	Point pt;
	Rectangle r;
	csizep *p = (csizep*)aux;
	
	/* only call if no fill at all */
	if (!nelem->slot.fill)
		pt = ncalldesiredsize(nelem, p->screen);
	
	if (nelem->slot.fill&FILLX)
		pt.x = p->fillwidth;
	if (nelem->slot.fill&FILLY)
		pt.y = p->autoheight;
	
	r = p->crect;
	r.max = addpt(r.min, pt);
	ncallcalcrect(nelem, p->screen, r);
	p->crect.min.y = r.max.y;
}

typedef struct dprepassp dprepassp;
struct dprepassp {
	Image *screen;
	int numfill;
	int fixedheight;
};

static void
sizeprepass(Nelem *nelem, int, void *aux)
{
	dprepassp *p = (dprepassp*)aux;
	if (nelem->slot.fill & FILLY) {
		p->numfill++;
		return;
	}
	Rectangle r = ncalldesiredsize(nelem, p->screen);
	p->fixedheight += Dy(r);
}

static Rectangle
vbox_calcrect(Nelem* nelem, Image* img, Rectangle r)
{
	csizep cp;
	dprepassp pp;
	NVBox* b = (NVBox*)nelem;
	GUARD(b);
	
	b->slot.r = r;
	
	pp.screen = screen;
	pp.numfill = 0;
	pp.fixedheight = 0;
	
	lforeach(&b->children, sizeprepass, &pp);
	
	cp.crect = r;
	cp.screen = img;
	cp.fillwidth = Dx(r);
	cp.autoheight = (Dy(r) - pp.fixedheight) / pp.numfill;
	
	lforeach(&b->children, childsize, &cp);
	
	return b->slot.r;
}

typedef struct cdsizep cdsizep;
struct cdsizep {
	Image *screen;
	Point size;
};

static void
dsizechild(Nelem *el, int, void *aux)
{
	Point t;
	cdsizep *p = (cdsizep*)aux;
	t = ncalldesiredsize(el, p->screen);
	if (t.x > p->size.x)
		p->size.x = t.x;
	p->size.y += t.y;
}

static Point
vbox_desiredsize(Nelem *nelem, Image *screen)
{
	cdsizep p;
	NVBox *b = (NVBox*)nelem;
	GUARD(b);
	
	p.screen = screen;
	p.size = ZP;
	lforeach(&b->children, dsizechild, &p);
	return p.size;
}

static void
vbox_childdraw(Nelem* elem, int, void *aux)
{
	ncalldraw(elem, (Image*)aux);
}

static void
vbox_draw(Nelem* nelem, Image* img)
{
	NVBox* b = (NVBox*)nelem;
	GUARD(b);
	
	lforeach(&b->children, vbox_childdraw, img);
}

static Nelemfunctions Nvboxfunctions = {
	.calcrect = vbox_calcrect,
	.desiredsize = vbox_desiredsize,
	.draw = vbox_draw,
};

DEF_SLOTFUNC(NVBox, vbox_slot);

DEF_ACCESSOR_OneParam(NVBox, vbox_autowidth, int, autowidth);

NVBox*
New_VBox(char *name)
{
	NVBox *b = MakeNelem(NVBox, NVBox_Type, &Nvboxfunctions, name, -1);
	
	b->Slot = vbox_slot;
	b->AutoWidth = vbox_autowidth;
	
	linit(&b->children);
	b->autowidth = 0;
	nc_push(b);
	return b;
}