Commit:ec1aec49349dab76af4e3063eb11e8a030c87de0 (browse)
Parent:86177eda0338c6773955897d9b5105fe89c980a0
Author:Tevo <estevan.cps@gmail.com>
Date:Sun Jan 10 19:43:04 CET 2021
Message:
Simple box

libwidget/base.c => libwidget/base.c
@@ -158,7 +158,8 @@
 void
 freewidget(Widget *w)
 {
-	w->cleanup(w);
+	if(w != nil)	/* freeing nil widgets should be a no-op */
+		w->cleanup(w);
 }
 
 void

/dev/null => libwidget/box.c
@@ -0,0 +1,118 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <String.h>
+
+#include <widget.h>
+#include "w-internal.h"
+
+static char *boxkind = "Box";
+
+int
+isbox(Widget *w)
+{
+	return strcmp(w->kind, boxkind) == 0;
+}
+
+static Box*
+coerce(Widget *w)
+{
+	if(!isbox(w))
+		werror("coerce: not a box");
+
+	return (Box*)w;
+}
+
+Point
+boxredraw(Widget *w, Image *dst, Rectangle r)
+{
+	Image *tmp;
+	Box *box;
+	Point boxsz, pos, sz;
+
+	box = coerce(w);
+
+	tmp = allocimage(dst->display, r, RGBA32, 0, DTransparent);
+	sz  = redrawwidget(box->content, tmp, r);
+
+	pos = boxsz = subpt(r.max, r.min);
+	pos = divpt(pos, 2);
+	pos = subpt(pos, divpt(sz, 2));
+
+	box->conrect = Rpt(pos, subpt(r.max, pos));
+
+	draw(dst, r, box->bg, nil, ZP);
+	draw(dst, box->conrect, tmp, nil, ZP);
+
+	freeimage(tmp);
+
+	return boxsz;
+}
+
+int
+boxmouse(Widget *w, Image *dst, Rectangle rect, Mouse m, Channel *chan)
+{
+	Box *box;
+
+	box = coerce(w);
+
+	if(ptinrect(m.xy, box->conrect))
+	{
+		box->focused = 1;
+		return mouseevent(box->content, dst, rect, m, chan);
+	}
+	else
+		box->focused = 0;
+
+	return 0;
+}
+
+int
+boxkbd(Widget *w, Image *dst, Rectangle rect, Rune r, Channel *chan)
+{
+	Box *box;
+
+	box = coerce(w);
+
+	if(box->focused)
+		return kbdevent(box->content, dst, rect, r, chan);
+
+	return 0;
+}
+
+void
+boxfree(Widget *w)
+{
+	Box *box;
+
+	box = coerce(w);
+	freewidget(box->content);
+	free(box);
+}
+
+Box*
+newbox(Widget *w, int flags)
+{
+	Box *box;
+
+	box = emallocz(sizeof(*box), 1);
+	wdefaults(box);
+	box->kind	= boxkind;
+	box->redraw	= boxredraw;
+	box->flags	= flags;
+	box->kbdevent	= boxkbd;
+	box->mouseevent	= boxmouse;
+	box->cleanup	= boxfree;
+	box->content	= w;
+
+	return box;
+}
+
+Box*
+newcenterbox(Widget *w)
+{
+	return newbox(w, B_CENTER_CONTENT);
+}

/dev/null => libwidget/box.h
@@ -0,0 +1,26 @@
+/*** Box ***/
+
+typedef struct Box Box;
+
+struct Box
+{
+	Widget;
+
+	Widget *content;
+	int flags;
+
+	/* don't touch */
+	Rectangle conrect;
+	int focused;
+};
+
+enum /* flags */
+{
+	B_CENTER_CONTENT	= 1<<0
+};
+
+int isbox(Widget*);
+
+Box* newbox(Widget*, int flags);
+Box* newcenterbox(Widget*);
+

libwidget/button.c => libwidget/button.c
@@ -18,33 +18,26 @@
 	return strcmp(w->kind, btnkind) == 0;
 }
 
-Point
-btnredraw(Widget *w, Image *dst, Rectangle r)
+static Button*
+coerce(Widget *w)
 {
-	Image *tmp;
-	Button *btn;
-	Point btsz, pos, sz;
-	Rectangle conrect;
-
 	if(!isbutton(w))
-		werror("btnredraw: not a button");
+		werror("coerce: not a button");
 
-	btn = (Button*)w;
-	tmp = allocimage(dst->display, r, RGBA32, 0, DTransparent);
-	sz  = redrawwidget(btn->content, tmp, r);
-
-	pos = btsz = subpt(r.max, r.min);
-	pos = divpt(pos, 2);
-	pos = subpt(pos, divpt(sz, 2));
+	return (Button*)w;
+}
 
-	conrect = Rpt(pos, subpt(r.max, pos));
+Point
+btnredraw(Widget *w, Image *dst, Rectangle r)
+{
+	Button *btn;
 
-	draw(dst, r, btn->pressed ? btn->fg : btn->bg, nil, ZP);
-	draw(dst, conrect, tmp, nil, ZP);
+	btn = coerce(w);
 
-	freeimage(tmp);
+	btn->box->content = btn->content;
+	btn->box->bg = btn->pressed ? btn->fg : btn->bg;
 
-	return btsz;
+	return redrawwidget(btn->box, dst, r);
 }
 
 int
@@ -54,10 +47,7 @@
 	int pressed;
 	Widgetmsg *msg;
 
-	if(!isbutton(w))
-		werror("btndraw: not a button");
-
-	btn = (Button*)w;
+	btn = coerce(w);
 	if((pressed = m.buttons & 1) != btn->pressed)
 	{
 		msg = newmsg(btn, pressed ? M_BUTTON_PRESSED : M_BUTTON_RELEASED);
@@ -75,11 +65,10 @@
 {
 	Button *btn;
 
-	if(!isbutton(w))
-		werror("btnfree: not a button");
-
-	btn = (Button*)w;
+	btn = coerce(w);
+	btn->box->content = nil;	/* to avoid double-free */
 	freewidget(btn->content);
+	freewidget(btn->box);
 	free(btn);
 }
 
@@ -98,6 +87,7 @@
 	wdefaults(btn);
 	btn->bg			= lightblue;
 	btn->fg			= darkblue;
+	btn->box		= newcenterbox(w);
 	btn->kind		= btnkind;
 	btn->redraw		= btnredraw;
 	btn->cleanup	= btnfree;

libwidget/button.h => libwidget/button.h
@@ -8,6 +8,9 @@
 
 	Widget *content;
 	int pressed;
+
+	/* don't touch */
+	Box *box;
 };
 
 int isbutton(Widget*);

libwidget/mkfile => libwidget/mkfile
@@ -5,13 +5,15 @@
 OFILES=\
 	base.$O		\
 	textbox.$O	\
-	button.$O
+	button.$O	\
+	box.$O
 
 HDR=widget.h
 
 HCOMP=\
 	base.h		\
 	textbox.h	\
+	box.h		\
 	button.h
 
 HFILES=\