aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorMarvin Borner2021-06-28 16:37:30 +0200
committerMarvin Borner2021-06-28 16:37:30 +0200
commit5a4eea5c6b39d221fe4828cb279c68c60bad8fae (patch)
tree64b91481a4257980785b3a57684b5580e5d81f80 /libs
parent461e6fcb6a0abbf594ea08d6828b841ea6dc964e (diff)
Implemented basic layout rendering
Diffstat (limited to 'libs')
-rw-r--r--libs/libgui/gui.c129
-rw-r--r--libs/libgui/gui.h18
-rw-r--r--libs/libgui/widgets.c7
-rw-r--r--libs/libgui/widgets.h2
4 files changed, 105 insertions, 51 deletions
diff --git a/libs/libgui/gui.c b/libs/libgui/gui.c
index d011126..144ead8 100644
--- a/libs/libgui/gui.c
+++ b/libs/libgui/gui.c
@@ -15,8 +15,7 @@ struct gui_widget {
struct gfx_context bg;
struct list *children;
- u32 margin; // Between sub-widgets
- u32 offset;
+ vec2 margin; // Between sub-widgets
enum gui_layout layout;
struct {
@@ -104,6 +103,33 @@ static void gui_connect_wm(void)
}
/**
+ * Layout stuff
+ */
+
+static vec2 gui_layout_position(struct gui_widget *parent)
+{
+ enum gui_layout layout = parent->layout;
+ vec2 pos = parent->margin;
+
+ struct node *iterator = parent->children->head;
+ while (iterator) {
+ struct gui_widget *widget = iterator->data;
+
+ if (layout == GUI_HLAYOUT) {
+ pos.x += MAX(widget->bg.size.x, widget->fg.size.x) + parent->margin.x;
+ } else if (layout == GUI_VLAYOUT) {
+ pos.y += MAX(widget->bg.size.y, widget->fg.size.y) + parent->margin.y;
+ } else {
+ gui_error(EINVAL);
+ }
+
+ iterator = iterator->next;
+ }
+
+ return pos;
+}
+
+/**
* GFX wrappers
*/
@@ -221,7 +247,8 @@ void gui_draw_line(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos1, v
* Widgets
*/
-static u8 gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_widget *buf)
+// TODO: Fix child location algorithm
+static u8 gui_widget_child_at(struct gui_widget *widget, vec2 pos, struct gui_widget *buf)
{
if (!widget || !widget->children || !buf)
gui_error(EFAULT);
@@ -236,7 +263,7 @@ static u8 gui_sub_widget_at(struct gui_widget *widget, vec2 pos, struct gui_widg
pos.y <= w->pos.y + w->bg.size.y)
ret = w;
- if (w->children->head && gui_sub_widget_at(w, pos, &sub))
+ if (w->children->head && gui_widget_child_at(w, pos, &sub))
ret = &sub;
iterator = iterator->next;
}
@@ -260,7 +287,7 @@ static u8 gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget)
struct gui_widget *ret = NULL;
struct gui_widget sub = { 0 };
- if (gui_sub_widget_at(win->main_widget, pos, &sub))
+ if (gui_widget_child_at(win->main_widget, pos, &sub))
ret = &sub;
if (!ret)
@@ -270,7 +297,7 @@ static u8 gui_widget_at(u32 win_id, vec2 pos, struct gui_widget *widget)
return 1;
}
-static void gui_sync_sub_widgets(struct gui_widget *widget)
+static void gui_widget_children_sync(struct gui_widget *widget)
{
if (!widget)
gui_error(EFAULT);
@@ -281,39 +308,39 @@ static void gui_sync_sub_widgets(struct gui_widget *widget)
struct node *iterator = widget->children->head;
while (iterator) {
struct gui_widget *w = iterator->data;
- gui_sync_sub_widgets(w);
+ gui_widget_children_sync(w);
gfx_ctx_on_ctx(&widget->bg, &w->bg, w->pos, GFX_NON_ALPHA);
gfx_ctx_on_ctx(&widget->fg, &w->fg, w->pos, GFX_NON_ALPHA);
iterator = iterator->next;
}
}
-static void gui_sync_widget(u32 win_id, u32 widget_id)
+static void gui_widget_sync(u32 win_id, u32 widget_id)
{
struct gui_window *win = gui_window_by_id(win_id);
struct gui_widget *widget = gui_widget_in_widget(win->main_widget, widget_id);
if (!widget)
gui_error(ENOENT);
- gui_sync_sub_widgets(widget);
+ gui_widget_children_sync(widget);
gfx_ctx_on_ctx(&win->ctx, &widget->bg, widget->pos, GFX_ALPHA);
gfx_ctx_on_ctx(&win->ctx, &widget->fg, widget->pos, GFX_ALPHA);
}
-static void gui_sync_widgets(u32 win_id)
+static void gui_widget_sync_all(u32 win_id)
{
struct gui_window *win = gui_window_by_id(win_id);
struct gui_widget *widget = win->main_widget;
if (!win)
gui_error(ENOENT);
- gui_sync_sub_widgets(win->main_widget);
+ gui_widget_children_sync(win->main_widget);
gfx_ctx_on_ctx(&win->ctx, &widget->bg, widget->pos, GFX_ALPHA);
gfx_ctx_on_ctx(&win->ctx, &widget->fg, widget->pos, GFX_ALPHA);
}
// TODO: This is very recursive and inefficient -> improve!
-static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *child)
+static vec2 gui_widget_offset(struct gui_widget *parent, struct gui_widget *child)
{
if (!parent || !parent->children || !child)
return vec2(0, 0);
@@ -330,7 +357,7 @@ static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *chil
struct gui_widget *sub = gui_widget_in_widget(w, child->id);
if (sub) {
offset = vec2_add(offset, w->pos);
- gui_offset_widget(w, child);
+ gui_widget_offset(w, child);
break;
}
@@ -340,7 +367,7 @@ static vec2 gui_offset_widget(struct gui_widget *parent, struct gui_widget *chil
return offset;
}
-static void gui_destroy_widget(u32 win_id, u32 widget_id)
+static void gui_widget_destroy(u32 win_id, u32 widget_id)
{
struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
if (!widget)
@@ -349,7 +376,7 @@ static void gui_destroy_widget(u32 win_id, u32 widget_id)
struct node *iterator = widget->children->head;
while (iterator) {
struct gui_widget *sub = iterator->data;
- gui_destroy_widget(win_id, sub->id);
+ gui_widget_destroy(win_id, sub->id);
iterator = iterator->next;
}
@@ -359,7 +386,7 @@ static void gui_destroy_widget(u32 win_id, u32 widget_id)
free(widget);
}
-static struct gui_widget *gui_plain_widget(vec2 pos, vec2 size, enum gui_layout layout, u8 bpp)
+static struct gui_widget *gui_widget_plain(vec2 pos, vec2 size, enum gui_layout layout, u8 bpp)
{
struct gui_widget *widget = zalloc(sizeof(*widget));
struct gfx_context bg;
@@ -371,25 +398,26 @@ static struct gui_widget *gui_plain_widget(vec2 pos, vec2 size, enum gui_layout
widget->bg = *gfx_new_ctx(&bg, size, bpp);
widget->fg = *gfx_new_ctx(&fg, size, bpp);
widget->children = list_new();
- widget->margin = 4;
+ widget->margin = vec2(4, 4);
widget->layout = layout;
return widget;
}
-u32 gui_widget(u32 win_id, u32 widget_id, vec2 pos, vec2 size)
+u32 gui_widget(u32 win_id, u32 widget_id, vec2 size)
{
struct gui_widget *parent = gui_widget_by_id(win_id, widget_id);
if (!parent)
gui_error(ENOENT);
- struct gui_widget *child = gui_plain_widget(pos, size, GUI_HLAYOUT, parent->bg.bpp);
+ vec2 pos = gui_layout_position(parent);
+ struct gui_widget *child = gui_widget_plain(pos, size, GUI_HLAYOUT, parent->bg.bpp);
list_add(parent->children, child);
return child->id;
}
-u32 gui_main_widget(u32 win_id)
+u32 gui_widget_main(u32 win_id)
{
struct gui_window *win = gui_window_by_id(win_id);
if (!win)
@@ -419,10 +447,10 @@ void gui_widget_listen(u32 win_id, u32 widget_id, enum gui_listener listener, u3
}
}
-void gui_redraw_widget(u32 win_id, u32 widget_id)
+void gui_widget_redraw(u32 win_id, u32 widget_id)
{
- gui_sync_widget(win_id, widget_id);
- gui_redraw_window_only(win_id);
+ gui_widget_sync(win_id, widget_id);
+ gui_window_redraw_plain(win_id);
}
/**
@@ -436,15 +464,15 @@ void gui_popup(const char *text)
{
vec2 pos = vec2(200, 200);
- u32 popup = gui_custom_window("Popup", pos, vec2(POPUP_WIDTH, POPUP_HEIGHT));
+ u32 popup = gui_window_custom("Popup", pos, vec2(POPUP_WIDTH, POPUP_HEIGHT));
struct gui_window *win = gui_window_by_id(popup);
gui_fill(popup, win->main_widget->id, GUI_LAYER_BG, COLOR_WHITE);
- u32 widget = gui_widget(popup, win->main_widget->id, vec2(0, 0), vec2(POPUP_WIDTH, 32));
+ u32 widget = gui_widget(popup, win->main_widget->id, vec2(POPUP_WIDTH, 32));
gui_fill(popup, widget, GUI_LAYER_BG, COLOR_WHITE);
gui_write(popup, widget, GUI_LAYER_FG, vec2(0, 0), FONT_32, COLOR_BLACK, text);
- gui_redraw_window(popup);
+ gui_window_redraw(popup);
}
/**
@@ -460,10 +488,30 @@ vec2 gui_window_size(u32 win_id)
}
/**
+ * Window data setters
+ */
+
+void gui_widget_margin(u32 win_id, u32 widget_id, vec2 margin)
+{
+ struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
+ if (!widget)
+ gui_error(ENOENT);
+ widget->margin = margin;
+}
+
+void gui_widget_layout(u32 win_id, u32 widget_id, enum gui_layout layout)
+{
+ struct gui_widget *widget = gui_widget_by_id(win_id, widget_id);
+ if (!widget)
+ gui_error(ENOENT);
+ widget->layout = layout;
+}
+
+/**
* Window manager interfaces
*/
-u32 gui_custom_window(const char *name, vec2 pos, vec2 size)
+u32 gui_window_custom(const char *name, vec2 pos, vec2 size)
{
if (!windows)
windows = list_new();
@@ -501,7 +549,7 @@ u32 gui_custom_window(const char *name, vec2 pos, vec2 size)
// Initialize GUI_MAIN widget
win->main_widget =
- gui_plain_widget(vec2(0, 0), win->ctx.size, GUI_HLAYOUT, win->ctx.bpp);
+ gui_widget_plain(vec2(0, 0), win->ctx.size, GUI_HLAYOUT, win->ctx.bpp);
return win->id;
}
@@ -511,10 +559,10 @@ u32 gui_custom_window(const char *name, vec2 pos, vec2 size)
u32 gui_window(const char *name)
{
- return gui_custom_window(name, vec2(0, 0), vec2(0, 0));
+ return gui_window_custom(name, vec2(0, 0), vec2(0, 0));
}
-void gui_redraw_window_only(u32 id)
+void gui_window_redraw_plain(u32 id)
{
struct message_redraw_window msg = { .id = id };
gui_connect_wm();
@@ -524,16 +572,16 @@ void gui_redraw_window_only(u32 id)
gui_error(EINVAL);
}
-void gui_redraw_window(u32 id)
+void gui_window_redraw(u32 id)
{
- gui_sync_widgets(id);
- gui_redraw_window_only(id);
+ gui_widget_sync_all(id);
+ gui_window_redraw_plain(id);
}
-static void gui_destroy_window(u32 id)
+static void gui_window_destroy(u32 id)
{
struct gui_window *win = gui_window_by_id(id);
- gui_destroy_widget(id, win->main_widget->id);
+ gui_widget_destroy(id, win->main_widget->id);
u8 *fb = win->ctx.fb - (win->off.y * win->ctx.pitch);
assert(sys_free(fb) == EOK);
@@ -545,13 +593,13 @@ static void gui_destroy_window(u32 id)
free(win);
}
-static void gui_destroy_windows(void)
+static void gui_window_destroy_all(void)
{
struct node *iterator = windows->head;
while (iterator) {
struct gui_window *win = iterator->data;
iterator = iterator->next;
- gui_destroy_window(win->id);
+ gui_window_destroy(win->id);
}
list_destroy(windows);
@@ -584,9 +632,10 @@ static void gui_handle_mouse(struct message_mouse *msg)
struct gui_widget widget = { 0 };
gui_widget_at(msg->id, msg->pos, &widget);
+ printf("%d\n", widget.id);
struct gui_window *win = gui_window_by_id(msg->id);
- vec2 offset = gui_offset_widget(win->main_widget, &widget);
+ vec2 offset = gui_widget_offset(win->main_widget, &widget);
vec2 pos = vec2_sub(msg->pos, offset);
struct gui_event_mouse event = {
@@ -608,7 +657,7 @@ static void gui_handle_mouse(struct message_mouse *msg)
static void gui_handle_destroy_window(struct message_destroy_window *msg)
{
- gui_destroy_window(msg->id);
+ gui_window_destroy(msg->id);
if (!windows || !windows->head || !windows->head->data) {
log("No more windows, exiting\n");
exit(0);
@@ -620,7 +669,7 @@ static void gui_handle_exit(void)
if (!windows)
return;
- gui_destroy_windows();
+ gui_window_destroy_all();
}
/**
diff --git a/libs/libgui/gui.h b/libs/libgui/gui.h
index a2a44ed..00f49b8 100644
--- a/libs/libgui/gui.h
+++ b/libs/libgui/gui.h
@@ -42,10 +42,10 @@ struct gui_event_mouse {
* Window operations
*/
-u32 gui_custom_window(const char *name, vec2 pos, vec2 size);
u32 gui_window(const char *name);
-void gui_redraw_window(u32 id);
-void gui_redraw_window_only(u32 id); // Without widgets
+u32 gui_window_custom(const char *name, vec2 pos, vec2 size);
+void gui_window_redraw(u32 id);
+void gui_window_redraw_plain(u32 id); // Without widgets
/**
* GFX wrappers
@@ -69,14 +69,20 @@ void gui_draw_line(u32 win_id, u32 widget_id, enum gui_layer layer, vec2 pos1, v
* Widget operations
*/
-u32 gui_widget(u32 win_id, u32 widget_id, vec2 pos, vec2 size);
-u32 gui_main_widget(u32 win_id);
+u32 gui_widget(u32 win_id, u32 widget_id, vec2 size);
+u32 gui_widget_main(u32 win_id);
void gui_widget_listen(u32 win_id, u32 widget_id, enum gui_listener listener, u32 func);
-void gui_redraw_widget(u32 win_id, u32 widget_id);
+void gui_widget_redraw(u32 win_id, u32 widget_id);
void gui_popup(const char *text);
+/**
+ * Getters/setters
+ */
+
vec2 gui_window_size(u32 win_id);
+void gui_widget_margin(u32 win_id, u32 widget_id, vec2 margin);
+void gui_widget_layout(u32 win_id, u32 widget_id, enum gui_layout layout);
void gui_loop(void);
diff --git a/libs/libgui/widgets.c b/libs/libgui/widgets.c
index d6e82cd..1881655 100644
--- a/libs/libgui/widgets.c
+++ b/libs/libgui/widgets.c
@@ -10,12 +10,12 @@
* Button
*/
-void gui_button_custom(u32 window, u32 widget, vec2 pos, enum font_type font_type, u32 bg, u32 fg,
+void gui_button_custom(u32 window, u32 widget, enum font_type font_type, u32 bg, u32 fg,
void (*click)(struct gui_event_mouse *event), const char *text)
{
vec2 font_size = gfx_font_size(font_type);
vec2 size = vec2(font_size.x * strlen(text) + TEXT_PAD * 2, font_size.y + TEXT_PAD * 2);
- u32 button = gui_widget(window, widget, pos, size);
+ u32 button = gui_widget(window, widget, size);
gui_fill(window, button, GUI_LAYER_BG, bg);
gui_write(window, button, GUI_LAYER_FG, vec2(TEXT_PAD, TEXT_PAD), font_type, fg, text);
gui_widget_listen(window, button, GUI_LISTEN_MOUSECLICK, (u32)click);
@@ -24,6 +24,5 @@ void gui_button_custom(u32 window, u32 widget, vec2 pos, enum font_type font_typ
void gui_button(u32 window, u32 widget, void (*click)(struct gui_event_mouse *event),
const char *text)
{
- gui_button_custom(window, widget, vec2(0, 0), FONT_16, COLOR_WHITE, COLOR_BLACK, click,
- text);
+ gui_button_custom(window, widget, FONT_16, COLOR_WHITE, COLOR_BLACK, click, text);
}
diff --git a/libs/libgui/widgets.h b/libs/libgui/widgets.h
index 64862f0..4028af6 100644
--- a/libs/libgui/widgets.h
+++ b/libs/libgui/widgets.h
@@ -6,7 +6,7 @@
#include <libgui/gfx.h>
#include <libgui/gui.h>
-void gui_button_custom(u32 window, u32 widget, vec2 pos, enum font_type font_type, u32 bg, u32 fg,
+void gui_button_custom(u32 window, u32 widget, enum font_type font_type, u32 bg, u32 fg,
void (*click)(struct gui_event_mouse *event), const char *text);
void gui_button(u32 window, u32 widget, void (*click)(struct gui_event_mouse *event),
const char *text);