ref: 228a7b0eeda3531eb0bf0efa2211e4532af69681
parent: a0b15f88e6274b4892061a7dfe790d85eb211078
author: sirjofri <sirjofri@sirjofri.de>
date: Sun Feb 9 10:32:47 EST 2025
next version of nate, reduce custom functions in favor of generic ones future: - get rid of getchildren function
--- a/n_box.c
+++ b/n_box.c
@@ -8,27 +8,30 @@
#define N_TYPE NBox_Type
char* NBox_Type = "NBox";
-Point
-box_calcsize(Nelem* nelem, Image* screen)
+Rectangle
+box_calcsize(Nelem* nelem, Image* screen, Rectangle r)
{
NBox* b = (NBox*)nelem;
GUARD(b);
if (!b->sizetocontent) {
- return b->size;
+ r.max = addpt(r.min, b->size);
+ b->r = r;
+ return r;
}
if (!lgetfirst(&b->child)) {
- return Pt(0, 0);
+ b->r = r;
+ return r;
}
- Point csize = ncallcalcsize(lgetfirst(&b->child), screen);
- Point ssize = Pt(b->borderwidth, b->borderwidth);
- csize = addpt(csize, addpt(ssize, ssize));
- return csize;
+ Rectangle csize = ncallcalcsize(lgetfirst(&b->child), screen, r);
+ b->r = insetrect(csize, b->borderwidth);
+ return b->r;
}
-void
-box_draw(Nelem* nelem, Image* img, Rectangle r)
+static void
+box_draw(Nelem* nelem, Image* img)
{
Nelem* f;
+ Rectangle r;
NBox* b = (NBox*)nelem;
GUARD(b);
f = lgetfirst(&b->child);
@@ -35,46 +38,33 @@
if (!f)
return;
+ r = b->r;
if (b->sizetocontent) {
- r.max = addpt(r.min, ncallcalcsize(nelem, img));
+ r = b->r;
} else {
+ r = b->r;
r.max = addpt(r.min, b->size);
}
border(img, r, b->borderwidth, b->bordercolor, ZP);
- ncalldraw(f, img, insetrect(r, b->borderwidth));
+ ncalldraw(f, img);
+
+ if (nateborders) {
+ border(img, r, 1, ncolor.red, ZP);
+ }
}
-Nelem*
-box_checkhit(Nelem* nelem, Image* screen, Rectangle rect, Mouse m)
+static Nelem*
+box_checkhit(Nelem *nelem, Image *screen, Mouse m)
{
- NBox* b = (NBox*)nelem;
- Nelem* r;
- Nelem* ch;
- Point size;
- Rectangle cr;
+ NBox *b = (NBox*)nelem;
GUARD(b);
- if (!(ch = lgetfirst(&b->child))) {
- if (m.buttons&1 && b->hitfunc) {
- return b;
- }
- return nil;
- }
+ if (!b->hitfunc)
+ return nd_checkhit(nelem, screen, m);
- 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) {
+ if (ptinrect(m.xy, b->r))
return b;
- }
return nil;
}
@@ -110,6 +100,18 @@
return &b->child;
}
+static char*
+box_getname(Nelem *nelem)
+{
+ Nelem *ch;
+ NBox *b = (NBox*)nelem;
+ GUARD(b);
+ ch = lgetfirst(&b->child);
+ if (!(ch && ch->funcs && ch->funcs->getname))
+ return b->name;
+ return ch->funcs->getname(ch);
+}
+
static Nelemfunctions Nboxfunctions = {
.calcsize = box_calcsize,
.draw = box_draw,
@@ -117,6 +119,7 @@
.hit = box_hit,
.free = box_free,
.getchildren = box_getchildren,
+ .getname = box_getname,
};
NBox*
@@ -132,58 +135,23 @@
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;
-}
+DEF_ACCESSOR_TwoParams(NBox, box_border, int, borderwidth, Image*, bordercolor);
+DEF_ACCESSOR_OneParam(NBox, box_sizetocontent, int, sizetocontent);
+DEF_ACCESSOR_OneParam(NBox, box_size, Point, size);
+DEF_ACCESSOR_OneParam(NBox, box_padding, Nmargin, padding);
+DEF_ACCESSOR_TwoParams(NBox, box_onclick, OnclickHandler, hitfunc, void*, hitaux);
-static NBox*
-box_size(Point size)
-{
- NBox *b = (NBox*)nc_get();
- GUARD(b);
- b->size = size;
- return b;
-}
-
NBox*
-box_onclick(int (*f)(Mouse, Nelem*, void*), void* aux)
+New_Box(char *name)
{
- 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);
+ NBox *b = MakeNelem(NBox, NBox_Type, &Nboxfunctions, name);
- b->type = NBox_Type;
- b->funcs = &Nboxfunctions;
-
b->Slot = box_slot;
b->Border = box_border;
b->SizeToContent = box_sizetocontent;
b->Size = box_size;
b->OnClick = box_onclick;
+ b->Padding = box_padding;
linit(&b->child);
b->sizetocontent = 0;
--- a/n_box.h
+++ b/n_box.h
@@ -7,7 +7,8 @@
DECL_ACCESSOR_TwoParams(NBox, Border, int, Image*);
DECL_ACCESSOR_OneParam(NBox, SizeToContent, int);
DECL_ACCESSOR_OneParam(NBox, Size, Point);
- DECL_ACCESSOR_TwoParams(NBox, OnClick, int (*f)(Mouse, Nelem*, void*), void*);
+ DECL_ACCESSOR_TwoParams(NBox, OnClick, OnclickHandler, void*);
+ DECL_ACCESSOR_OneParam(NBox, Padding, Nmargin);
// private members
Nlist child;
@@ -14,9 +15,10 @@
Point size;
int sizetocontent;
int borderwidth;
+ Nmargin padding;
Image* bordercolor;
int (*hitfunc)(Mouse, Nelem*, void*);
void* hitaux;
};
-NBox* New_Box(void);
+NBox* New_Box(char*);
--- a/n_button.c
+++ b/n_button.c
@@ -10,28 +10,29 @@
#define N_TYPE NButton_Type
char *NButton_Type = "NButton";
-static Point
-button_calcsize(Nelem *nelem, Image *screen)
+static Rectangle
+button_calcsize(Nelem *nelem, Image *screen, Rectangle r)
{
NButton *b = (NButton*)nelem;
GUARD(b);
- return b->box->funcs->calcsize(b->box, screen);
+ b->r = ncallcalcsize(b->box, screen, r);
+ return b->r;
}
static void
-button_draw(Nelem *nelem, Image *img, Rectangle r)
+button_draw(Nelem *nelem, Image *img)
{
NButton *b = (NButton*)nelem;
GUARD(b);
- b->box->funcs->draw(b->box, img, r);
+ ncalldraw(b->box, img);
}
static Nelem*
-button_checkhit(Nelem *nelem, Image *screen, Rectangle r, Mouse m)
+button_checkhit(Nelem *nelem, Image *screen, Mouse m)
{
NButton *b = (NButton*)nelem;
GUARD(b);
- return b->box->funcs->checkhit(b->box, screen, r, m);
+ return ncallcheckhit(b->box, screen, m);
}
static void
@@ -97,7 +98,7 @@
}
static NButton*
-button_onclick(int (*f)(Mouse, Nelem*, void*), void *aux)
+button_onclick(OnclickHandler f, void *aux)
{
NButton *c = (NButton*)nc_get();
GUARD(c);
@@ -119,7 +120,7 @@
}
static NButton*
-button_labelfunc(char* (*f)(void))
+button_labelfunc(StringGetter f)
{
NButton *c = (NButton*)nc_get();
GUARD(c);
@@ -130,18 +131,14 @@
}
NButton*
-New_Button(void)
+New_Button(char *name)
{
- NButton* b = malloc(sizeof(NButton));
- assert(b);
+ NButton *b = MakeNelem(NButton, NButton_Type, &Nbuttonfunctions, name);
- b->box = New_Box()
- ->Slot(NAssign(NLabel, &b->label, New_Label()));
+ b->box = New_Box(name)
+ ->Slot(NAssign(NLabel, &b->label, New_Label(nil)));
/* pop box from stack */
nc_pop();
-
- b->type = NButton_Type;
- b->funcs = &Nbuttonfunctions;
b->Slot = button_slot;
b->Border = button_border;
--- a/n_button.h
+++ b/n_button.h
@@ -6,7 +6,7 @@
DECL_ACCESSOR_OneParam(NButton, Slot, Nelem*);
DECL_ACCESSOR_TwoParams(NButton, Border, int, Image*);
DECL_ACCESSOR_OneParam(NButton, SizeToContent, int);
- DECL_ACCESSOR_TwoParams(NButton, OnClick, int (*f)(Mouse, Nelem*, void*), void*);
+ DECL_ACCESSOR_TwoParams(NButton, OnClick, OnclickHandler, void*);
DECL_ACCESSOR_OneParam(NButton, Label, char*);
DECL_ACCESSOR_OneParam(NButton, LabelFunc, char* (*f)(void));
@@ -18,4 +18,4 @@
NLabel *label;
};
-NButton* New_Button(void);
+NButton* New_Button(char*);
--- a/n_hbox.c
+++ b/n_hbox.c
@@ -8,110 +8,60 @@
#define N_TYPE NHBox_Type
char* NHBox_Type = "NHBox";
-Point currentsize;
-Image* currentscreen;
+typedef struct csizep csizep;
+struct csizep {
+ Rectangle crect;
+ Rectangle frect;
+ Image *screen;
+};
void
-hbox_childsize(Nelem* nelem, int)
+hbox_childsize(Nelem* nelem, int, void *aux)
{
- Point p = ncallcalcsize(nelem, currentscreen);
- currentsize.x += p.x;
- currentsize.y = currentsize.y > p.y ? currentsize.y : p.y;
+ csizep *p = (csizep*)aux;
+ Rectangle r = ncallcalcsize(nelem, p->screen, p->crect);
+ combinerect(&p->frect, r);
+ p->crect.min.x = r.max.x;
}
-Point
-hbox_calcsize(Nelem* nelem, Image* screen)
+static Rectangle
+hbox_calcsize(Nelem* nelem, Image* screen, Rectangle r)
{
+ csizep params;
NHBox* b = (NHBox*)nelem;
GUARD(b);
- currentsize = Pt(0, 0);
- currentscreen = screen;
+ params.screen = screen;
+ params.crect = r;
+ params.frect.min = r.min;
+ params.frect.max = r.min;
- lforeach(&b->children, hbox_childsize);
+ lforeach(&b->children, hbox_childsize, ¶ms);
- return currentsize;
+ nelem->r = params.frect;
+ return nelem->r;
}
-Rectangle currentrect;
-Image* currentimg;
-
void
-hbox_childdraw(Nelem* elem, int)
+hbox_childdraw(Nelem* elem, int, void *aux)
{
- Point p = ncallcalcsize(elem, currentimg);
- currentrect.max.x = currentrect.min.x + p.x;
- ncalldraw(elem, currentimg, currentrect);
- currentrect.min.x = currentrect.max.x;
+
+ ncalldraw(elem, (Image*)aux);
}
void
-hbox_draw(Nelem* nelem, Image* img, Rectangle r)
+hbox_draw(Nelem* nelem, Image* img)
{
NHBox* b = (NHBox*)nelem;
GUARD(b);
-
- if (b->sizetocontent) {
- r.max = addpt(r.min, ncallcalcsize(b, img));
- }
- currentrect = r;
- currentimg = img;
- lforeach(&b->children, hbox_childdraw);
-}
-
-Nelem* ch_ret;
-Image* ch_screen;
-Rectangle ch_rect;
-Mouse ch_mouse;
-
-void
-hbox_fe_checkhit(Nelem* nelem, int)
-{
- Point s;
- Nelem* e;
- Rectangle r;
+ lforeach(&b->children, hbox_childdraw, img);
- 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.x += s.x;
- return;
+ if (nateborders) {
+ border(img, b->r, 1, ncolor.red, ZP);
}
-
- e = ncallcheckhit(nelem, ch_screen, r, ch_mouse);
- ch_rect.min.x += s.x;
- if (e) {
- ch_ret = e;
- }
}
-Nelem*
-hbox_checkhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
-{
- NHBox* b = (NHBox*)nelem;
- GUARD(b);
-
- ch_ret = nil;
- ch_screen = screen;
- ch_rect = r;
- ch_mouse = m;
-
- ch_rect.max.x = ch_rect.min.x;
-
- lforeach(&b->children, hbox_fe_checkhit);
- return ch_ret;
-}
-
-int
-hbox_hit(Nelem* nelem, Mouse m)
-{
- GUARD(nelem);
- return -1;
-}
-
void
hbox_free(Nelem* nelem)
{
@@ -134,8 +84,6 @@
static Nelemfunctions Nhboxfunctions = {
.calcsize = hbox_calcsize,
.draw = hbox_draw,
- .checkhit = hbox_checkhit,
- .hit = hbox_hit,
.free = hbox_free,
.getchildren = hbox_getchildren,
};
@@ -153,23 +101,12 @@
return b;
}
-NHBox*
-hbox_sizetocontent(int stc)
-{
- NHBox* b = (NHBox*)nc_get();
- GUARD(b);
- b->sizetocontent = stc;
- return b;
-}
+DEF_ACCESSOR_OneParam(NHBox, hbox_sizetocontent, int, sizetocontent);
NHBox*
-New_HBox(void)
+New_HBox(char *name)
{
- NHBox* b = malloc(sizeof(NHBox));
- assert(b);
-
- b->type = NHBox_Type;
- b->funcs = &Nhboxfunctions;
+ NHBox *b = MakeNelem(NHBox, NHBox_Type, &Nhboxfunctions, name);
b->Slot = hbox_slot;
b->SizeToContent = hbox_sizetocontent;
--- a/n_hbox.h
+++ b/n_hbox.h
@@ -11,4 +11,4 @@
int sizetocontent;
};
-NHBox* New_HBox(void);
+NHBox* New_HBox(char*);
--- a/n_image.c
+++ b/n_image.c
@@ -8,44 +8,39 @@
#define N_TYPE NImage_Type
char *NImage_Type = "NImage";
-static Point
-image_calcsize(Nelem *nelem, Image*)
+static Rectangle
+image_calcsize(Nelem *nelem, Image*, Rectangle r)
{
+ Point p;
NImage *i = (NImage*)nelem;
GUARD(i);
+ if (!i->autosize) {
+ i->r = r;
+ return i->r;
+ }
+
+ p = ZP;
if (i->image)
- return Pt(Dx(i->image->r), Dy(i->image->r));
- return ZP;
+ p = Pt(Dx(i->image->r), Dy(i->image->r));
+ r.max = addpt(r.min, p);
+ i->r = r;
+ return i->r;
}
static void
-image_draw(Nelem *nelem, Image *img, Rectangle r)
+image_draw(Nelem *nelem, Image *img)
{
NImage *i = (NImage*)nelem;
GUARD(i);
if (!i->image) {
- draw(img, r, display->white, nil, ZP);
+ draw(img, i->r, display->white, nil, ZP);
return;
}
- draw(img, r, i->image, nil, i->offset);
+ draw(img, i->r, i->image, nil, i->offset);
}
-static Nelem*
-image_checkhit(Nelem *nelem, Image *screen, Rectangle r, Mouse m)
-{
- GUARD(nelem);
- return nil;
-}
-
-static int
-image_hit(Nelem *nelem, Mouse m)
-{
- GUARD(nelem);
- return -1;
-}
-
static void
image_free(Nelem *nelem)
{
@@ -64,43 +59,25 @@
static Nelemfunctions Nimagefunctions = {
.calcsize = image_calcsize,
.draw = image_draw,
- .checkhit = image_checkhit,
- .hit = image_hit,
.free = image_free,
.getchildren = image_getchildren,
};
-static NImage*
-setimage(Image *img)
-{
- NImage *i = (NImage*)nc_get();
- GUARD(i);
- i->image = img;
- return i;
-}
+DEF_ACCESSOR_OneParam(NImage, image_image, Image*, image);
+DEF_ACCESSOR_OneParam(NImage, image_offset, Point, offset);
+DEF_ACCESSOR_OneParam(NImage, image_autosize, int, autosize);
-static NImage*
-setimageoffset(Point p)
-{
- NImage *i = (NImage*)nc_get();
- GUARD(i);
- i->offset = p;
- return i;
-}
-
NImage*
-New_Image()
+New_Image(char *name)
{
- NImage *i = malloc(sizeof(NImage));
- assert(i);
- i->type = NImage_Type;
- i->funcs = &Nimagefunctions;
+ NImage *i = MakeNelem(NImage, NImage_Type, &Nimagefunctions, name);
i->image = nil;
i->offset = ZP;
- i->Image = setimage;
- i->ImageOffset = setimageoffset;
+ i->Image = image_image;
+ i->Offset = image_offset;
+ i->AutoSize = image_autosize;
nc_push(i);
return i;
}
--- a/n_image.h
+++ b/n_image.h
@@ -4,11 +4,13 @@
struct NImage {
Nelem;
DECL_ACCESSOR_OneParam(NImage, Image, Image*);
- DECL_ACCESSOR_OneParam(NImage, ImageOffset, Point);
+ DECL_ACCESSOR_OneParam(NImage, Offset, Point);
+ DECL_ACCESSOR_OneParam(NImage, AutoSize, int);
// private members
Image *image;
Point offset;
+ int autosize;
};
-NImage* New_Image(void);
+NImage* New_Image(char*);
--- a/n_label.c
+++ b/n_label.c
@@ -8,7 +8,7 @@
#define N_TYPE NLabel_Type
char* NLabel_Type = "NLabel";
-char*
+static char*
getlabelstr(NLabel* l)
{
if (l->labelfunc)
@@ -18,41 +18,41 @@
return "";
}
-Point
-label_calcsize(Nelem* nelem, Image*)
+static Rectangle
+label_calcsize(Nelem* nelem, Image*, Rectangle r)
{
NLabel* l = (NLabel*)nelem;
GUARD(l);
- return stringsize(l->font, getlabelstr(l));
+ r.max = stringsize(l->font, getlabelstr(l));
+ r.max.x += l->margin.left + l->margin.right;
+ r.max.y += l->margin.top + l->margin.bottom;
+ r.max = addpt(r.min, r.max);
+ l->r = r;
+ return r;
}
-void
-label_draw(Nelem* nelem, Image* img, Rectangle r)
+static void
+label_draw(Nelem* nelem, Image* img)
{
char* str;
+ Rectangle r;
NLabel* l = (NLabel*)nelem;
GUARD(l);
str = getlabelstr(l);
+ r = l->r;
+ r.min.x += l->margin.left;
+ r.min.y += l->margin.top;
+
string(img, r.min, l->color, ZP, l->font, str);
+
+ if (nateborders) {
+ border(img, l->r, 1, ncolor.blue, ZP);
+ }
}
-Nelem*
-label_checkhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
-{
- GUARD(nelem);
- return nil;
-}
-
-int
-label_hit(Nelem* nelem, Mouse m)
-{
- GUARD(nelem);
- return -1;
-}
-
void
label_free(Nelem* nelem)
{
@@ -68,63 +68,38 @@
return nil;
}
+static char*
+label_getname(Nelem *nelem)
+{
+ NLabel *l = (NLabel*)nelem;
+ GUARD(l);
+ return getlabelstr(l);
+}
+
static Nelemfunctions Nlabelfunctions = {
.calcsize = label_calcsize,
.draw = label_draw,
- .checkhit = label_checkhit,
- .hit = label_hit,
.free = label_free,
.getchildren = label_getchildren,
+ .getname = label_getname,
};
-NLabel*
-label(char* label)
-{
- NLabel* l = (NLabel*)nc_get();
- GUARD(l);
- l->label = label;
- return l;
-}
+DEF_ACCESSOR_OneParam(NLabel, label, char*, label);
+DEF_ACCESSOR_OneParam(NLabel, labelfunc, StringGetter, labelfunc);
+DEF_ACCESSOR_OneParam(NLabel, lfont, Font*, font);
+DEF_ACCESSOR_OneParam(NLabel, lcolor, Image*, color);
+DEF_ACCESSOR_OneParam(NLabel, lmargin, Nmargin, margin);
NLabel*
-labelfunc(char* (*f)(void))
+New_Label(char *name)
{
- NLabel* l = (NLabel*)nc_get();
- GUARD(l);
- l->labelfunc = f;
- return l;
-}
-
-NLabel*
-lfont(Font* newfont)
-{
- NLabel* l = (NLabel*)nc_get();
- GUARD(l);
- l->font = newfont;
- return l;
-}
-
-NLabel*
-lcolor(Image* img)
-{
- NLabel* l = (NLabel*)nc_get();
- GUARD(l);
- l->color = img;
- return l;
-}
-
-NLabel*
-New_Label()
-{
- NLabel* e = malloc(sizeof(NLabel));
- assert(e);
- e->type = NLabel_Type;
- e->funcs = &Nlabelfunctions;
+ NLabel *e = MakeNelem(NLabel, NLabel_Type, &Nlabelfunctions, name);
e->Label = label;
e->LabelFunc = labelfunc;
e->Font = lfont;
e->Color = lcolor;
+ e->Margin = lmargin;
e->label = nil;
e->labelfunc = nil;
--- a/n_label.h
+++ b/n_label.h
@@ -4,15 +4,17 @@
struct NLabel {
Nelem;
DECL_ACCESSOR_OneParam(NLabel, Label, char*);
- DECL_ACCESSOR_OneParam(NLabel, LabelFunc, char* (*f)(void));
+ DECL_ACCESSOR_OneParam(NLabel, LabelFunc, StringGetter);
DECL_ACCESSOR_OneParam(NLabel, Font, Font*);
DECL_ACCESSOR_OneParam(NLabel, Color, Image*);
+ DECL_ACCESSOR_OneParam(NLabel, Margin, Nmargin);
// private members
char* label;
- char* (*labelfunc)(void);
+ StringGetter labelfunc;
Font* font;
Image* color;
+ Nmargin margin;
};
-NLabel* New_Label(void);
+NLabel* New_Label(char*);
--- a/n_vbox.c
+++ b/n_vbox.c
@@ -8,110 +8,55 @@
#define N_TYPE NVBox_Type
char* NVBox_Type = "NVBox";
-Point currentsize;
-Image* currentscreen;
+typedef struct csizep csizep;
+struct csizep {
+ Rectangle crect;
+ Rectangle frect;
+ Image *screen;
+};
void
-vbox_childsize(Nelem* nelem, int)
+vbox_childsize(Nelem* nelem, int, void *aux)
{
- Point p = ncallcalcsize(nelem, currentscreen);
- currentsize.x = currentsize.x > p.x ? currentsize.x : p.x;
- currentsize.y += p.y;
+ csizep *p = (csizep*)aux;
+ Rectangle r = ncallcalcsize(nelem, p->screen, p->crect);
+ combinerect(&p->frect, r);
+ p->crect.min.y = r.max.y;
}
-Point
-vbox_calcsize(Nelem* nelem, Image* screen)
+static Rectangle
+vbox_calcsize(Nelem* nelem, Image* img, Rectangle r)
{
+ csizep params;
NVBox* b = (NVBox*)nelem;
GUARD(b);
- currentsize = Pt(0, 0);
- currentscreen = screen;
+ params.crect = r;
+ params.screen = img;
+ params.frect.min = r.min;
+ params.frect.max = r.min;
- 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));
- }
+ lforeach(&b->children, vbox_childsize, ¶ms);
- currentrect = r;
- currentimg = img;
- lforeach(&b->children, vbox_childdraw);
+ b->r = params.frect;
+ return b->r;
}
-Nelem* ch_ret;
-Image* ch_screen;
-Rectangle ch_rect;
-Mouse ch_mouse;
-
-void
-vbox_fe_checkhit(Nelem* nelem, int)
+static void
+vbox_childdraw(Nelem* elem, int, void *aux)
{
- 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;
- }
+ ncalldraw(elem, (Image*)aux);
}
-Nelem*
-vbox_checkhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
+static void
+vbox_draw(Nelem* nelem, Image* img)
{
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;
+ lforeach(&b->children, vbox_childdraw, img);
}
-int
-vbox_hit(Nelem* nelem, Mouse m)
-{
- GUARD(nelem);
- return -1;
-}
-
void
vbox_free(Nelem* nelem)
{
@@ -134,8 +79,6 @@
static Nelemfunctions Nvboxfunctions = {
.calcsize = vbox_calcsize,
.draw = vbox_draw,
- .checkhit = vbox_checkhit,
- .hit = vbox_hit,
.free = vbox_free,
.getchildren = vbox_getchildren,
};
@@ -153,23 +96,12 @@
return b;
}
-NVBox*
-vbox_sizetocontent(int stc)
-{
- NVBox* b = (NVBox*)nc_get();
- GUARD(b);
- b->sizetocontent = stc;
- return b;
-}
+DEF_ACCESSOR_OneParam(NVBox, vbox_sizetocontent, int, sizetocontent);
NVBox*
-New_VBox(void)
+New_VBox(char *name)
{
- NVBox* b = malloc(sizeof(NVBox));
- assert(b);
-
- b->type = NVBox_Type;
- b->funcs = &Nvboxfunctions;
+ NVBox *b = MakeNelem(NVBox, NVBox_Type, &Nvboxfunctions, name);
b->Slot = vbox_slot;
b->SizeToContent = vbox_sizetocontent;
--- a/n_vbox.h
+++ b/n_vbox.h
@@ -11,4 +11,4 @@
int sizetocontent;
};
-NVBox* New_VBox(void);
+NVBox* New_VBox(char*);
--- a/n_window.c
+++ b/n_window.c
@@ -8,22 +8,28 @@
#define N_TYPE NWindow_Type
char* NWindow_Type = "NWindow";
-Point
-wcalcsize(Nelem* nelem, Image* screen)
+Rectangle
+wcalcsize(Nelem* nelem, Image* screen, Rectangle r)
{
- GUARD(nelem);
- return subpt(screen->r.max, screen->r.min);
+ Nelem *f;
+ NWindow *w = (NWindow*)nelem;
+ GUARD(w);
+ f = lgetfirst(&w->child);
+ if (f)
+ ncallcalcsize(f, screen, screen->r);
+ nelem->r = r;
+ return screen->r;
}
-void
-wdraw(Nelem* nelem, Image* img, Rectangle r)
+static void
+wdraw(Nelem* nelem, Image* img)
{
- Nelem* f;
- NWindow* w = (NWindow*)nelem;
+ Nelem *f;
+ NWindow *w = (NWindow*)nelem;
GUARD(w);
f = lgetfirst(&w->child);
if (f)
- ncalldraw(f, img, r);
+ ncalldraw(f, img);
}
void
@@ -79,13 +85,9 @@
}
NWindow*
-New_Window(void)
+New_Window(char *name)
{
- NWindow* e = malloc(sizeof(NWindow));
- assert(e);
-
- e->type = NWindow_Type;
- e->funcs = &Nwindowfunctions;
+ NWindow *e = MakeNelem(NWindow, NWindow_Type, &Nwindowfunctions, name);
e->Slot = slot;
e->MakeRoot = makeroot;
--- a/n_window.h
+++ b/n_window.h
@@ -10,4 +10,4 @@
Nlist child;
};
-NWindow* New_Window(void);
+NWindow* New_Window(char*);
--- a/nate.c
+++ b/nate.c
@@ -4,6 +4,9 @@
#include <event.h>
#include "nate_construct.h"
+int nateborders = 0;
+int natetracehit = 0;
+
static Nlist rootchain = { nil };
static Nelem* rootelem = nil;
@@ -37,9 +40,9 @@
}
void
-nforeachroot(void (*f)(Nelem*, int))
+nforeachroot(void (*f)(Nelem*, int, void*), void *aux)
{
- lforeach(&rootchain, f);
+ lforeach(&rootchain, f, aux);
}
int
@@ -118,11 +121,11 @@
}
void
-lforeach(Nlist* list, void (*f)(Nelem*, int))
+lforeach(Nlist* list, void (*f)(Nelem*, int, void*), void *aux)
{
Nlistelem* l = list->first;
for (int i = 0; l; i++) {
- f(l->item, i);
+ f(l->item, i, aux);
l = l->next;
}
}
@@ -173,34 +176,45 @@
nelem->funcs->free(nelem);
}
-Point
-ncallcalcsize(Nelem* nelem, Image* dst)
+Rectangle
+ncallcalcsize(Nelem* nelem, Image* dst, Rectangle r)
{
assert(nelem);
- if (nelem->funcs && nelem->funcs->calcsize)
- return nelem->funcs->calcsize(nelem, dst);
+ if (nelem->funcs && nelem->funcs->calcsize) {
+ r = nelem->funcs->calcsize(nelem, dst, r);
+ //fprint(2, "calcsize %s: %R\n", nelem->type, r);
+ return r;
+ }
- return Pt(0,0);
+ return r;
}
void
-ncalldraw(Nelem* nelem, Image* dst, Rectangle r)
+ncalldraw(Nelem* nelem, Image* dst)
{
+ Rectangle or;
assert(nelem);
- if (nelem->funcs && nelem->funcs->draw)
- nelem->funcs->draw(nelem, dst, r);
+ if (nelem->funcs && nelem->funcs->draw) {
+ or = dst->clipr;
+ replclipr(dst, 0, nelem->r);
+ nelem->funcs->draw(nelem, dst);
+ replclipr(dst, 0, or);
+ }
}
Nelem*
-ncallcheckhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
+ncallcheckhit(Nelem* nelem, Image* screen, Mouse m)
{
assert(nelem);
- if (nelem->funcs && nelem->funcs->checkhit)
- return nelem->funcs->checkhit(nelem, screen, r, m);
- return nil;
+ nctracehit(nelem, !nelem->funcs->hit);
+ nctracehitlevel++;
+ if (nelem->funcs && nelem->funcs->checkhit) {
+ return nelem->funcs->checkhit(nelem, screen, m);
+ }
+ return nd_checkhit(nelem, screen, m);
}
int
@@ -235,15 +249,22 @@
nateinit()
{
nc_init();
+#define A(col) allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, col)
+ ncolor.red = A(DRed);
+ ncolor.green = A(DGreen);
+ ncolor.blue = A(DBlue);
+#undef A
}
void
-nateredraw()
+nateredraw(int all)
{
if (!rootelem)
return;
- ncalldraw(rootelem, screen, screen->r);
+ if (all)
+ ncallcalcsize(rootelem, screen, screen->r);
+ ncalldraw(rootelem, screen);
}
int
@@ -250,20 +271,18 @@
natemouseevent(Mouse m)
{
Nelem* el;
- Point s;
Rectangle r;
if (!rootelem)
return 0;
- s = ncallcalcsize(rootelem, screen);
- r.min = screen->r.min;
- r.max = addpt(r.min, s);
+ r = ncallcalcsize(rootelem, screen, screen->r);
if (!ptinrect(m.xy, r))
return 0;
- el = ncallcheckhit(rootelem, screen, screen->r, m);
+ nctracehitlevel = natetracehit - 1;
+ el = ncallcheckhit(rootelem, screen, m);
if (!el)
return 0;
--- a/nate.h
+++ b/nate.h
@@ -4,11 +4,30 @@
typedef struct Nelemfunctions Nelemfunctions;
typedef struct Nlist Nlist;
+
+/* common types
+ *****************/
+
+typedef int (*OnclickHandler)(Mouse, Nelem*, void*);
+typedef char* (*StringGetter)(void);
+
+typedef struct Nmargin Nmargin;
+
+struct Nmargin {
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+#define NMargin(l, t, r, b) ((Nmargin){l, t, r, b})
+#define NMargin2(x, y) ((Nmargin){x, y, x, y})
+
/* user functions
******************/
void nateinit(void);
-void nateredraw(void);
+void nateredraw(int all);
int natemouseevent(Mouse);
@@ -15,22 +34,35 @@
#define NAssign(T, A, B) ((T*)(nassign((Nelem**)A, B)))
Nelem* nassign(Nelem**, Nelem*);
+extern int nateborders;
+extern int natetracehit;
+struct {
+ Image *red;
+ Image *green;
+ Image *blue;
+} ncolor;
+
+
/* end user functions
*********************/
struct Nelem {
- char* type;
+ char *type;
+ char *name;
+ Rectangle r;
Nelemfunctions* funcs;
};
struct Nelemfunctions {
- Point (*calcsize)(Nelem*, Image*);
- void (*draw)(Nelem*, Image*, Rectangle);
- Nelem* (*checkhit)(Nelem*, Image*, Rectangle, Mouse);
+ Rectangle (*calcsize)(Nelem*, Image*, Rectangle);
+ void (*draw)(Nelem*, Image*);
+ Nelem* (*checkhit)(Nelem*, Image*, Mouse);
int (*hit)(Nelem*, Mouse);
void (*free)(Nelem*);
Nlist* (*getchildren)(Nelem*);
+
+ char* (*getname)(Nelem*);
};
/* nlist functions
@@ -51,7 +83,7 @@
void lins(Nlist* list, Nelem* item);
void ldel(Nlist* list, Nelem* item);
void linsert(Nlist* list, Nelem* before, Nelem* item);
-void lforeach(Nlist* list, void (*f)(Nelem*, int));
+void lforeach(Nlist* list, void (*f)(Nelem*, int, void*), void*);
void lfreelist(Nlist* list);
Nelem* lgetfirst(Nlist* list);
@@ -62,9 +94,9 @@
********************/
// calls on Nelem
-Point ncallcalcsize(Nelem*, Image*);
-void ncalldraw(Nelem*, Image*, Rectangle);
-Nelem* ncallcheckhit(Nelem*, Image*, Rectangle, Mouse);
+Rectangle ncallcalcsize(Nelem*, Image*, Rectangle);
+void ncalldraw(Nelem*, Image*);
+Nelem* ncallcheckhit(Nelem*, Image*, Mouse);
int ncallhit(Nelem*, Mouse);
void ncallfree(Nelem*);
Nlist* ncallgetchildren(Nelem*);
--- a/nate_construct.c
+++ b/nate_construct.c
@@ -52,44 +52,77 @@
return nc_stack ? nc_stack->elem : nil;
}
-Nelem* ch_retelem;
-Rectangle ch_rect;
-Image* ch_screen;
-Mouse ch_mouse;
+typedef struct chparams chparams;
+struct chparams {
+ Nelem *retelem;
+ Image *screen;
+ Mouse mouse;
+};
-void
-fe_checkhit(Nelem* elem, int)
+static void
+fe_checkhit(Nelem* elem, int, void *aux)
{
+ chparams *p = (chparams*)aux;
Rectangle r;
Nelem* e;
- Point s;
- s = ncallcalcsize(elem, ch_screen);
- r.min = ch_rect.min;
- r.max = addpt(r.min, s);
+ if (p->retelem)
+ return;
- if (!ptinrect(ch_mouse.xy, r))
+ border(p->screen, r, 1, ncolor.green, ZP);
+
+ if (!ptinrect(p->mouse.xy, elem->r))
return;
- e = ncallcheckhit(elem, ch_screen, ch_rect, ch_mouse);
+ e = ncallcheckhit(elem, p->screen, p->mouse);
+ nctracehitlevel--;
if (e) {
- ch_retelem = e;
+ p->retelem = e;
}
}
Nelem*
-nd_checkhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m)
+nd_checkhit(Nelem* nelem, Image* screen, Mouse m)
{
+ chparams params;
Nlist* l = ncallgetchildren(nelem);
if (!l)
return nil;
- ch_retelem = nil;
- ch_rect = r;
- ch_screen = screen;
- ch_mouse = m;
- lforeach(l, fe_checkhit);
+ params.retelem = nil;
+ params.screen = screen;
+ params.mouse = m;
+ lforeach(l, fe_checkhit, ¶ms);
- return ch_retelem;
+ return params.retelem;
+}
+
+Nelem*
+makenelem(long size, char *type, Nelemfunctions *funcs, char *name)
+{
+ Nelem *nel = mallocz(size, 1);
+ if (!nel)
+ sysfatal("oom: creating nelem %s", type);
+ nel->type = type;
+ nel->name = name;
+ nel->funcs = funcs;
+ return nel;
+}
+
+int nctracehitlevel = 0;
+void
+nctracehit(Nelem *el, int pt)
+{
+ char *name;
+ if (nctracehitlevel < 0)
+ return;
+ if (el->funcs && el->funcs->getname)
+ name = el->funcs->getname(el);
+ else
+ name = el->name;
+ fprint(2, "HIT: %*s%c%s%c %c%s%c\n",
+ nctracehitlevel * 3, nctracehitlevel?"↘":"", /* indent */
+ pt ? '(' : ' ', el->type, pt ? ')' : ' ', /* Nelem type */
+ name?'\"':' ', name ? name : "", name?'\"':' '); /* name */
}
--- a/nate_construct.h
+++ b/nate_construct.h
@@ -8,9 +8,51 @@
#define COND(N) (N->type == N_TYPE)
#define GUARD(N) assert(COND(N))
+// create with benefits
+Nelem *makenelem(long size, char *type, Nelemfunctions *funcs, char *name);
+#define MakeNelem(Type, Char, F, N) ((Type*)makenelem(sizeof(Type), Char, F, N));
+
// internal stuff
void nc_init(void);
+// trace hits
+extern int nctracehitlevel;
+void nctracehit(Nelem *el, int passthrough);
+
// default functionality
-Nelem* nd_checkhit(Nelem* nelem, Image* screen, Rectangle r, Mouse m);
+Nelem* nd_checkhit(Nelem* nelem, Image* screen, Mouse m);
+
+// syntactic sugar: default accessors
+#define DEF_ACCESSOR_OneParam(Type, Func, T1, N1) \
+ static Type* \
+ Func(T1 N1) \
+ { \
+ Type *b = (Type*)nc_get(); \
+ GUARD(b); \
+ b->N1 = N1; \
+ return b; \
+ }
+
+#define DEF_ACCESSOR_TwoParams(Type, Func, T1, N1, T2, N2) \
+ static Type* \
+ Func(T1 N1, T2 N2) \
+ { \
+ Type *b = (Type*)nc_get(); \
+ GUARD(b); \
+ b->N1 = N1; \
+ b->N2 = N2; \
+ return b; \
+ }
+
+#define DEF_ACCESSOR_ThreeParams(Type, Func, T1, N1, T2, N2, T3, N3) \
+ static Type* \
+ Func(T1 N1, T2 N2, T3 N3) \
+ { \
+ Type *b = (Type*)nc_get(); \
+ GUARD(b); \
+ b->N1 = N1; \
+ b->N2 = N2; \
+ b->N3 = N3; \
+ return b; \
+ }
--- a/test/ntest.c
+++ b/test/ntest.c
@@ -5,8 +5,10 @@
#include "../nate.h"
#include "../n_window.h"
#include "../n_hbox.h"
+#include "../n_vbox.h"
#include "../n_box.h"
#include "../n_label.h"
+#include "../n_image.h"
char*
getlabel(void)
@@ -35,7 +37,7 @@
if (new && getwindow(display, Refnone) < 0)
sysfatal("getwindow: %r");
- nateredraw();
+ nateredraw(1);
}
void
@@ -52,43 +54,73 @@
einit(Emouse);
nateinit();
+ nateborders = 1;
+ natetracehit = 1;
+
Image* red = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DRed);
Image* green = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DGreen);
Image* blue = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, DBlue);
- NAssign(NWindow, &mainwindow, New_Window())
+ NAssign(NWindow, &mainwindow, New_Window(nil))
->MakeRoot()
->Slot(
- New_Box()
+ New_VBox(nil)
->SizeToContent(1)
- ->Border(1, red)
->Slot(
- New_HBox()
+ New_HBox("first")
->SizeToContent(1)
->Slot(
- NAssign(NBox, &box1, New_Box())
+ NAssign(NBox, &box1, New_Box(nil))
->Border(1, green)
->SizeToContent(1)
+ ->Padding(NMargin2(5, 3))
->OnClick(callclick, nil)
->Slot(
- New_Label()
+ New_Label(nil)
->LabelFunc(getlabel)
+ ->Margin(NMargin2(5, 5))
)
)
->Slot(
- NAssign(NBox, &box2, New_Box())
+ NAssign(NBox, &box2, New_Box(nil))
->Border(1, blue)
->SizeToContent(1)
->OnClick(callclick, nil)
->Slot(
- New_Label()
+ New_Label(nil)
->Label("DEF")
+ ->Margin(NMargin2(5, 5))
)
)
+ ->Slot(
+ New_Box("imagebox")
+ ->Size(Pt(50, 50))
+ ->Slot(
+ New_Image(nil)
+ ->Image(display->black)
+ )
+ )
)
+ ->Slot(
+ New_HBox("second")
+ ->SizeToContent(1)
+ ->Slot(
+ New_Label(nil)
+ ->Label("abc")
+ )
+ )
);
eresized(0);
+
+ int p[2];
+ pipe(p);
+ dup(p[0], 2);
+ int fd = create("/srv/ntest", OWRITE|ORCLOSE, 0666);
+ if (fd < 0)
+ sysfatal("create: %r");
+ fprint(fd, "%d\n", p[1]);
+ close(p[1]);
for (;;) {
e = event(&ev);