ref: 855a60a7698acb993b68f8e64448bd2fc3ff86da
dir: /n_vbox.c/
#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;
if (!nelem->slot.fill&FILLX || !nelem->slot.fill&FILLY)
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)
{
Point pt;
dprepassp *p = (dprepassp*)aux;
if (nelem->slot.fill&FILLY) {
p->numfill++;
return;
}
pt = ncalldesiredsize(nelem, p->screen);
p->fixedheight += pt.y;
}
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;
if (pp.numfill)
cp.autoheight /= pp.numfill;
// TODO: check if numfill is correct!
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 pt;
cdsizep *p = (cdsizep*)aux;
pt = ncalldesiredsize(el, p->screen);
if (pt.x > p->size.x)
p->size.x = pt.x;
p->size.y += pt.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;
}