ref: aab184987c79fc7a8e5467200f9ac448700b797f
dir: /n_hbox.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include "nate.h"
#include "nate_construct.h"
#include "n_hbox.h"
#define N_TYPE NHBox_Type
char* NHBox_Type = "NHBox";
typedef struct csizep csizep;
struct csizep {
Rectangle crect;
Image *screen;
int autowidth;
int fillheight;
};
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->autowidth;
if (nelem->slot.fill&FILLY)
pt.y = p->fillheight;
r = p->crect;
r.max = addpt(r.min, pt);
ncallcalcrect(nelem, p->screen, r);
p->crect.min.x = r.max.x;
}
typedef struct dprepassp dprepassp;
struct dprepassp {
Image *screen;
int numfill;
int fixedwidth;
};
static void
sizeprepass(Nelem *nelem, int, void *aux)
{
Point pt;
dprepassp *p = (dprepassp*)aux;
if (nelem->slot.fill&FILLX) {
p->numfill++;
return;
}
pt = ncalldesiredsize(nelem, p->screen);
p->fixedwidth += pt.x;
}
static Rectangle
hbox_calcrect(Nelem* nelem, Image* screen, Rectangle r)
{
csizep cp;
dprepassp pp;
NHBox* b = (NHBox*)nelem;
GUARD(b);
nelem->slot.r = r;
pp.screen = screen;
pp.numfill = 0;
pp.fixedwidth = 0;
lforeach(&b->children, sizeprepass, &pp);
cp.crect = r;
cp.screen = screen;
cp.fillheight = Dy(r);
cp.autowidth = Dx(r) - pp.fixedwidth;
if (pp.numfill)
cp.autowidth /= pp.numfill;
lforeach(&b->children, childsize, &cp);
return nelem->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.y > p->size.y)
p->size.y = pt.y;
p->size.x += pt.x;
}
static Point
hbox_desiredsize(Nelem *nelem, Image *screen)
{
cdsizep p;
NHBox *b = (NHBox*)nelem;
GUARD(b);
p.screen = screen;
p.size = ZP;
lforeach(&b->children, dsizechild, &p);
return p.size;
}
static void
hbox_childdraw(Nelem* elem, int, void *aux)
{
ncalldraw(elem, (Image*)aux);
}
static void
hbox_draw(Nelem* nelem, Image* img)
{
NHBox* b = (NHBox*)nelem;
GUARD(b);
lforeach(&b->children, hbox_childdraw, img);
}
static Nelemfunctions Nhboxfunctions = {
.calcrect = hbox_calcrect,
.desiredsize = hbox_desiredsize,
.draw = hbox_draw,
};
#define NTYPE NHBox
#define NACCS NHBoxAccessors
DEF_SLOTFUNC(hbox_slot);
static NACCS*
hbox_autoheight(int h)
{
NHBox *b = (NHBox*)nc_get();
GUARD(b);
if (h)
b->slot.fill |= FILLX;
else
if (b->slot.fill & FILLX)
b->slot.fill -= FILLX;
return (NACCS*)b->accs;
}
static NACCS accs = {
.Slot = hbox_slot,
.AutoHeight = hbox_autoheight,
};
NACCS*
New_HBox(char *name)
{
NHBox *b = MakeNelem(NHBox, NHBox_Type, &Nhboxfunctions, &accs, name, -1);
linit(&b->children);
b->autoheight = 0;
nc_push(b);
return (NACCS*)b->accs;
}