From f83d5e4b8e315f2b17f0c8bf390bf967f02f5837 Mon Sep 17 00:00:00 2001
From: Marvin Borner
Date: Sun, 25 Oct 2020 12:09:38 +0100
Subject: Added buttons

---
 Makefile         |  2 +-
 apps/Makefile    |  2 +-
 apps/window.c    | 50 ++---------------------------------------------
 apps/wm.c        | 15 +++++++-------
 libgui/gui.c     | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 libgui/inc/gfx.h |  1 +
 libgui/inc/gui.h | 27 ++++++++++++++++++++++----
 run              |  3 ++-
 8 files changed, 94 insertions(+), 65 deletions(-)

diff --git a/Makefile b/Makefile
index 6775826..e5dba45 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ CFLAGS_EXTRA = -fno-tree-bit-ccp -fno-tree-builtin-call-dce -fno-tree-ccp -fno-t
 
 export
 
-all: compile clean
+all: compile
 
 compile:
 	@$(MAKE) clean --no-print-directory -C libc/
diff --git a/apps/Makefile b/apps/Makefile
index 155e069..3e4aaa0 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -12,7 +12,7 @@ all: $(COBJS)
 %.o: %.c
 	@mkdir -p ../build/apps/
 	@$(CC) -c $(CFLAGS) $< -o $@
-	@$(LD) -o $(@:.o=.elf) -Tlink.ld -L../build/ $@ -lc -lgui -ltxt
+	@$(LD) -o $(@:.o=.elf) -Tlink.ld -L../build/ $@ -lgui -ltxt -lc
 	@$(OC) -O binary $(@:.o=.elf) ../build/apps/$(@:.o=)
 # @cp $(@:.o=.elf) ../build/apps/$(@:.o=.dbg)
 
diff --git a/apps/window.c b/apps/window.c
index 70131a6..601f187 100644
--- a/apps/window.c
+++ b/apps/window.c
@@ -12,61 +12,15 @@ int main()
 {
 	print("[test context loaded]\n");
 
-	struct window *win = gui_init("test", 0, 0);
-	struct context *ctx = win->ctx;
-
-	int font_height = gfx_font_height();
-	int font_width = gfx_font_width();
-
-	char *hello = "Hello, world!";
-	gfx_write(ctx, ctx->width / 2 - (strlen(hello) * font_width) / 2, 0, COLOR_GREEN, hello);
+	struct element *container = gui_init("test", 0, 0);
+	gui_add_button(container, 10, 10, 100, 20, "hallo", COLOR_RED);
 
 	struct message *msg;
-	int char_x = 0;
-	int char_y = 1;
 	while (1) {
 		if (!(msg = msg_receive())) {
 			yield();
 			continue;
 		}
-
-		// TODO: Export to text widget or sth
-		switch (msg->type) {
-		case WM_KEYBOARD: {
-			struct msg_keyboard *event = msg->data;
-			char ch = event->ch;
-			if (!event->press)
-				break;
-
-			if (char_x * font_width >= (int)ctx->width) {
-				char_y++;
-				char_x = 0;
-			}
-
-			if (ch == '\n') {
-				char_x = 0;
-				char_y++;
-			} else if (ch == '\t') {
-				char_x += 8;
-			} else if (ch == '\b') {
-				if (char_x > 0) {
-					char_x--;
-					gfx_draw_rectangle(ctx, font_width * char_x,
-							   font_height * char_y,
-							   font_width * (char_x + 1),
-							   font_height * (char_y + 1), COLOR_BG);
-				}
-			} else if (ch == ' ' && event->scancode == KEY_SPACE) {
-				char_x++;
-			} else if (ch != ' ' && ch != '\0') {
-				gfx_write_char(ctx, font_width * char_x++, font_height * char_y,
-					       COLOR_CYAN, ch);
-			}
-			break;
-		}
-		default:
-			break;
-		}
 	}
 	return 0;
 }
diff --git a/apps/wm.c b/apps/wm.c
index 2443d87..0ce9a18 100644
--- a/apps/wm.c
+++ b/apps/wm.c
@@ -57,8 +57,8 @@ static struct context *context_at(int x, int y)
 	struct node *iterator = contexts->head;
 	while (iterator != NULL) {
 		struct context *ctx = iterator->data;
-		if (ctx != &root && x >= ctx->x && x <= ctx->x + (int)ctx->width && y >= ctx->y &&
-		    y <= ctx->y + (int)ctx->height)
+		if (ctx != &root && !(ctx->flags & WF_RELATIVE) && x >= ctx->x &&
+		    x <= ctx->x + (int)ctx->width && y >= ctx->y && y <= ctx->y + (int)ctx->height)
 			ret = ctx;
 		iterator = iterator->next;
 	}
@@ -73,7 +73,7 @@ static void redraw_all()
 	struct node *iterator = contexts->head;
 	while (iterator != NULL) {
 		struct context *ctx = iterator->data;
-		if (ctx != focused)
+		if (ctx != focused && !(ctx->flags & WF_RELATIVE))
 			gfx_ctx_on_ctx(&exchange, ctx, ctx->x, ctx->y);
 		iterator = iterator->next;
 	}
@@ -207,10 +207,10 @@ int main(int argc, char **argv)
 	gfx_write(&direct, 0, 0, COLOR_FG, "Welcome to Melvix!");
 	gfx_write(&direct, 0, 32, COLOR_FG, "Loading resources...");
 
-	gfx_fill(&root, COLOR_BG);
-	gfx_border(&root, COLOR_FG, 2);
+	gfx_fill(&root, COLOR_FG);
+	//gfx_border(&root, COLOR_FG, 2);
 	gfx_load_image(&cursor, "/res/cursor.bmp", 0, 0);
-	gfx_load_wallpaper(&root, "/res/wall.bmp");
+	//gfx_load_wallpaper(&root, "/res/wall.bmp");
 	redraw_all();
 
 	event_register(EVENT_MOUSE);
@@ -234,7 +234,8 @@ int main(int argc, char **argv)
 			ctx->pid = msg->src;
 			new_context(ctx, msg->src, x, y, width, height, ctx->flags);
 			list_add(contexts, ctx);
-			focused = ctx;
+			if (!(ctx->flags & WF_RELATIVE))
+				focused = ctx;
 			redraw_all();
 			msg_send(msg->src, WM_NEW_CONTEXT, ctx);
 			break;
diff --git a/libgui/gui.c b/libgui/gui.c
index 8ed79af..7ea341c 100644
--- a/libgui/gui.c
+++ b/libgui/gui.c
@@ -4,6 +4,7 @@
 #include <def.h>
 #include <gfx.h>
 #include <gui.h>
+#include <list.h>
 #include <mem.h>
 
 #define MAX_WINDOWS 10
@@ -23,8 +24,10 @@ struct window *new_window(const char *title, int x, int y, u32 width, u32 height
 	win->ctx->width = width > 0 ? width : 600;
 	win->ctx->height = height > 0 ? height : 400;
 	win->ctx->flags = flags;
+	win->id = window_count + 1;
 	win->title = title;
-	gfx_new_ctx(windows[window_count + 1].ctx);
+	win->childs = list_new();
+	gfx_new_ctx(win->ctx);
 
 	if (!win->ctx->fb)
 		return NULL;
@@ -34,7 +37,49 @@ struct window *new_window(const char *title, int x, int y, u32 width, u32 height
 	return win;
 }
 
-struct window *gui_init(const char *title, u32 width, u32 height)
+void merge_elements(struct element *container)
+{
+	if (!container->childs || !container->childs->head)
+		return;
+
+	struct node *iterator = container->childs->head;
+	while (iterator != NULL) {
+		struct element *elem = iterator->data;
+		struct context *ctx = elem->ctx;
+		merge_elements(elem);
+		gfx_ctx_on_ctx(container->ctx, ctx, ctx->x, ctx->y);
+		iterator = iterator->next;
+	}
+}
+
+struct element *gui_add_button(struct element *container, int x, int y, u32 width, u32 height,
+			       const char *text, u32 color)
+{
+	if (!container || !container->childs)
+		return NULL;
+
+	struct element *button = malloc(sizeof(*button));
+	button->type = GUI_TYPE_BUTTON;
+	button->window_id = container->window_id;
+	button->ctx = malloc(sizeof(*button->ctx));
+	button->ctx->x = x;
+	button->ctx->y = y;
+	button->ctx->width = width;
+	button->ctx->height = height;
+	button->ctx->flags = WF_RELATIVE;
+	button->childs = list_new();
+	button->data = malloc(sizeof(struct element_button));
+	((struct element_button *)button->data)->text = text;
+	((struct element_button *)button->data)->color = color;
+	gfx_new_ctx(button->ctx);
+	gfx_fill(button->ctx, color);
+	list_add(container->childs, button);
+	merge_elements(container);
+
+	return button;
+}
+
+struct element *gui_init(const char *title, u32 width, u32 height)
 {
 	if (window_count != 0)
 		return NULL;
@@ -46,5 +91,13 @@ struct window *gui_init(const char *title, u32 width, u32 height)
 	gfx_fill(win->ctx, COLOR_BG);
 	gfx_init("/font/spleen-12x24.psfu");
 
-	return win;
+	struct element *container = malloc(sizeof(*container));
+	container->type = GUI_TYPE_CONTAINER;
+	container->window_id = win->id;
+	container->ctx = win->ctx;
+	container->childs = list_new();
+	container->data = NULL;
+	list_add(win->childs, container);
+
+	return container;
 }
diff --git a/libgui/inc/gfx.h b/libgui/inc/gfx.h
index 342fe84..fe48ac2 100644
--- a/libgui/inc/gfx.h
+++ b/libgui/inc/gfx.h
@@ -37,6 +37,7 @@
 #define WF_NO_FOCUS (1 << 0)
 #define WF_NO_DRAG (1 << 1)
 #define WF_NO_RESIZE (1 << 2)
+#define WF_RELATIVE (1 << 3)
 
 enum message_type { WM_NEW_CONTEXT = EVENT_MAX + 1, WM_REDRAW, WM_KEYBOARD };
 
diff --git a/libgui/inc/gui.h b/libgui/inc/gui.h
index 565bcf6..ea1e40e 100644
--- a/libgui/inc/gui.h
+++ b/libgui/inc/gui.h
@@ -6,20 +6,39 @@
 
 #include <def.h>
 #include <gfx.h>
+#include <list.h>
 
 #define MAX_CHILDS 100
 
+enum element_type { GUI_TYPE_CONTAINER, GUI_TYPE_BUTTON, GUI_TYPE_TEXTBOX };
+
+struct element_button {
+	const char *text;
+	u32 color;
+};
+
+struct element_textbox {
+	const char *text;
+	u32 color;
+};
+
 struct element {
-	struct context *ctx;
+	enum element_type type;
+	u32 window_id;
+	struct context *ctx; // Coordinates are relative to container
+	struct list *childs;
+	void *data; // Who needs static types anyways :)
 };
 
 struct window {
+	u32 id;
 	const char *title;
-	struct element *childs[MAX_CHILDS];
+	struct list *childs;
 	struct context *ctx;
 };
 
-// TODO: Remove window return (internal)
-struct window *gui_init(const char *title, u32 width, u32 height);
+struct element *gui_init(const char *title, u32 width, u32 height);
+struct element *gui_add_button(struct element *container, int x, int y, u32 width, u32 height,
+			       const char *text, u32 color);
 
 #endif
diff --git a/run b/run
index 3a14d12..b18a550 100755
--- a/run
+++ b/run
@@ -113,7 +113,7 @@ make_build() {
     rm -rf build/*
 
     printf "\nBuilding...\n"
-    $MAKE
+    $MAKE -j $($NPROC)
 
     # Create disk image
     dd if=/dev/zero of=build/disk.img bs=1k count=32k status=none
@@ -262,6 +262,7 @@ elif [ "${mode}" = "test" ] || [ "${mode}" = "net" ] || [ "${mode}" = "" ]; then
     make_build
     make_sync &
     make_test
+    make_clean
 else
     echo "Usage: ./run {cross | clean | build | test | debug | again | disasm | sync | disk} [-y]"
     printf "\nDescription of options:\n"
-- 
cgit v1.2.3