ref: c04fd4ce67a03c04b342c38185523bb834f4e0b7
dir: /n_box.c/
#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";
Point
box_calcsize(Nelem* nelem, Image* screen)
{
NBox* b = (NBox*)nelem;
GUARD(b);
if (!lgetfirst(&b->child)) {
return Pt(0, 0);
}
Point csize = ncallcalcsize(lgetfirst(&b->child), screen);
Point ssize = Pt(b->borderwidth, b->borderwidth);
csize = addpt(csize, addpt(ssize, ssize));
return csize;
}
void
box_draw(Nelem* nelem, Image* img, Rectangle r)
{
Nelem* f;
NBox* b = (NBox*)nelem;
GUARD(b);
f = lgetfirst(&b->child);
if (!f)
return;
if (b->sizetocontent) {
r.max = addpt(r.min, ncallcalcsize(nelem, img));
}
border(img, r, b->borderwidth, b->bordercolor, ZP);
ncalldraw(f, img, insetrect(r, b->borderwidth));
}
Nelem*
box_checkhit(Nelem* nelem, Image* screen, Rectangle rect, Mouse m)
{
NBox* b = (NBox*)nelem;
Nelem* r;
Nelem* ch;
Point size;
Rectangle cr;
GUARD(b);
if (!(ch = lgetfirst(&b->child))) {
if (m.buttons&1 && b->hitfunc) {
return b;
}
return nil;
}
size = ncallcalcsize(ch, screen);
cr.min = rect.min;
cr.max = addpt(cr.min, size);
if (ptinrect(m.xy, cr)) {
r = ncallcheckhit(ch, screen, cr, m);
if (r)
return r;
}
if (m.buttons&1 && b->hitfunc) {
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 Nelemfunctions Nboxfunctions = {
.calcsize = box_calcsize,
.draw = box_draw,
.checkhit = box_checkhit,
.hit = box_hit,
.free = box_free,
.getchildren = box_getchildren,
};
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;
}
NBox*
box_border(int bwidth, Image* col)
{
NBox* b = (NBox*)nc_get();
GUARD(b);
b->borderwidth = bwidth;
if (col)
b->bordercolor = col;
return b;
}
NBox*
box_sizetocontent(int stc)
{
NBox* b = (NBox*)nc_get();
GUARD(b);
b->sizetocontent = stc;
return b;
}
NBox*
box_onclick(int (*f)(Mouse, Nelem*, void*), void* aux)
{
NBox* b = (NBox*)nc_get();
GUARD(b);
b->hitfunc = f;
b->hitaux = aux;
return b;
}
NBox*
New_Box(void)
{
NBox* b = malloc(sizeof(NBox));
assert(b);
b->type = NBox_Type;
b->funcs = &Nboxfunctions;
b->Slot = box_slot;
b->Border = box_border;
b->SizeToContent = box_sizetocontent;
b->OnClick = box_onclick;
linit(&b->child);
b->sizetocontent = 0;
b->hitfunc = nil;
b->hitaux = nil;
b->borderwidth = 0;
b->bordercolor = display->black;
nc_push(b);
return b;
}