shithub: blie

Download patch

ref: 7455a7027cde79e0304bade55b6616983e2e8e1a
parent: bb63f08a8acc62f17975b108c918f4ff20c1f2c0
author: sirjofri <sirjofri@sirjofri.de>
date: Fri Sep 6 12:46:29 EDT 2024

adds ask function (plus test)

--- /dev/null
+++ b/ask.c
@@ -1,0 +1,139 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <event.h>
+#include <keyboard.h>
+#include "blie.h"
+
+static int asklineheight = 50;
+static int numberasks = 0;
+static int width = 200;
+
+static void
+dodraw(Image *img, Rectangle r, Ask *asks)
+{
+	int i;
+	Point p;
+	Rectangle box;
+	
+	replclipr(img, 0, r);
+	draw(img, r, display->white, nil, ZP);
+	border(img, r, 1, display->black, ZP);
+	
+	box.min = ZP;
+	box.max.x = width - 2*5;
+	box.max.y = font->height + 4;
+	
+	p = r.min;
+	p.x += 5; /* margin left */
+	
+	for (i = 0; i < numberasks; i++) {
+		p.y = r.min.y + i * asklineheight;
+		p.y += 8;
+		string(img, p, display->black, ZP, font, asks[i].label);
+		p.y += font->height + 2;
+		border(img, rectaddpt(box, p), 1, display->black, ZP);
+		p.y += 2;
+		p.x += 3;
+		string(img, p, display->black, ZP, font, asks[i].value);
+		p.x -= 3;
+	}
+	
+	replclipr(img, 0, img->r);
+}
+
+static int
+handleclick(Ask *asks, Rectangle r, Mouse m)
+{
+	int i;
+	int y;
+	Mouse fm;
+	
+	y = m.xy.y - r.min.y;
+	i = y / asklineheight;
+	
+	if (i >= numberasks)
+		return 0;
+	
+	fm.xy = r.min;
+	fm.xy.y += i * asklineheight;
+	
+	return eenter(asks[i].label, asks[i].value, asks[i].nval, &m);
+}
+
+static int
+handlekeys(int kbdc)
+{
+	/* return values: 1: quit abort, 2: quit success, 0: NOP */
+	switch (kbdc) {
+	case 'q':
+	case Kdel:
+	case Kesc:
+		return 1;
+	case '\n':
+		return 2;
+	}
+	return 0;
+}
+
+int
+ask(Ask *asks, Mouse m)
+{
+	Image *img, *blit;
+	Rectangle r;
+	int height;
+	int e;
+	Event ev;
+	Point nbl;
+	Ask *a;
+	int ret;
+	
+	asklineheight = 2*font->height + 15;
+	
+	numberasks = 0;
+	for (a = asks; a->label; a++)
+		numberasks++;
+	
+	height = numberasks * asklineheight + 5;
+	r.min = m.xy;
+	r.max = r.min;
+	r.max.x += width;
+	r.max.y += height;
+	
+	if (screen->r.max.x <= r.max.x) {
+		r.max.x = screen->r.max.x;
+		r.min.x = r.max.x - width;
+	}
+	if (screen->r.max.y <= r.max.y) {
+		r.max.y = screen->r.max.y;
+		r.min.y = r.max.y - height;
+	}
+	
+	nbl = r.min;
+	
+	blit = allocimage(display, r, screen->chan, 0, DNofill);
+	draw(blit, blit->r, screen, nil, nbl);
+	
+	for (;;) {
+		dodraw(screen, r, asks);
+Nodraw:
+		switch (event(&ev)) {
+		case Ekeyboard:
+			if (ret = handlekeys(ev.kbdc))
+				goto Out;
+			goto Nodraw;
+		case Emouse:
+			if (ev.mouse.buttons) {
+				if (handleclick(asks, r, ev.mouse))
+					break;
+			}
+			goto Nodraw;
+		}
+	}
+Out:
+	draw(screen, blit->r, blit, nil, nbl);
+	freeimage(blit);
+	
+	return --ret;
+}
--- a/blie.h
+++ b/blie.h
@@ -18,6 +18,15 @@
 /* could be extracted to libdraw */
 int eentercolor(char*, ulong*, Mouse*);
 
+/* could be extracted to separate library */
+typedef struct Ask Ask;
+struct Ask {
+	char *label;
+	char *value;
+	int nval;
+};
+int ask(Ask*, Mouse);
+
 struct Layer {
 	char *name;
 	char *label;
--- a/mkfile
+++ b/mkfile
@@ -10,6 +10,7 @@
 	eentercolor.$O\
 	db.$O\
 	util.$O\
+	ask.$O\
 	p9image.$O\
 	efilter.$O\
 
--- a/test/mkfile
+++ b/test/mkfile
@@ -2,7 +2,10 @@
 
 TEST=\
 	tdb\
+	task\
 
 </sys/src/cmd/mktest
 
 6.tdb: tdb.6 ../db.6
+
+6.task: task.6 ../ask.6
--- /dev/null
+++ b/test/task.c
@@ -1,0 +1,62 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <event.h>
+#include "../blie.h"
+
+void
+eresized(int)
+{
+	draw(screen, screen->r, display->white, nil, ZP);
+}
+
+void
+main(int, char**)
+{
+	Event ev;
+	Ask asks[3];
+	char answer1[11];
+	char answer2[11];
+	
+	asks[0].label = "question A";
+	asks[0].value = answer1;
+	asks[0].nval = 10;
+	asks[1].label = "question B";
+	asks[1].value = answer2;
+	asks[1].nval = 10;
+	asks[2].label = nil;
+	asks[2].value = nil;
+	
+	snprint(answer1, sizeof answer1, "answer");
+	snprint(answer2, sizeof answer2, "%f", 50.54);
+	
+	if (!initdraw(nil, nil, "asktest"))
+		sysfatal("%r");
+	
+	eresized(0);
+	einit(Emouse|Ekeyboard);
+	
+	for (;;) {
+		switch (event(&ev)) {
+		case Emouse:
+			if (ev.mouse.buttons & 1) {
+				if (!ask(asks, ev.mouse)) {
+					fprint(2, "   abort:\n");
+					fprint(2, "0: %s: %s\n", asks[0].label, asks[0].value);
+					fprint(2, "1: %s: %s\n", asks[1].label, asks[1].value);
+					break;
+				}	
+				fprint(2, "   accept:\n");
+				fprint(2, "0: %s: %s\n", asks[0].label, asks[0].value);
+				fprint(2, "1: %s: %s\n", asks[1].label, asks[1].value);
+			}
+			break;
+		case Ekeyboard:
+			if (ev.kbdc == 'q')
+				exits(nil);
+			break;
+		}
+	}
+	exits(nil);
+}