changeset 609:d97674d33764

ui: grid menu be more flexible
author David Demelier <markand@malikania.fr>
date Fri, 11 Aug 2023 18:01:28 +0200
parents 2527b000aaa5
children 90ac81e4c190
files examples/example-gridmenu/example-gridmenu.c libmlk-ui/mlk/ui/frame.c libmlk-ui/mlk/ui/gridmenu.c libmlk-ui/mlk/ui/gridmenu.h libmlk-ui/mlk/ui/label.c libmlk-ui/mlk/ui/label.h
diffstat 6 files changed, 120 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-gridmenu/example-gridmenu.c	Fri Aug 11 19:45:00 2023 +0200
+++ b/examples/example-gridmenu/example-gridmenu.c	Fri Aug 11 18:01:28 2023 +0200
@@ -61,12 +61,6 @@
 
 static struct mlk_style style;
 
-static struct mlk_frame frame = {
-	.w = 300,
-	.h = 100,
-	.delegate = &mlk_frame_delegate,
-	.style = &mlk_style
-};
 static struct mlk_gridmenu menu = {
 	.nrows = 3,
 	.ncols = 2,
@@ -131,7 +125,6 @@
 
 	mlk_painter_set_color(MLK_EXAMPLE_BG);
 	mlk_painter_clear();
-	mlk_frame_draw(&frame);
 	mlk_gridmenu_draw(&menu);
 	mlk_painter_present();
 }
@@ -146,10 +139,7 @@
 	};
 
 	mlk_gridmenu_resize(&menu, 0, 0, 300, 100);
-
 	mlk_align(MLK_ALIGN_CENTER, &menu.x, &menu.y, menu.w, menu.h, 0, 0, mlk_window.w, mlk_window.h);
-	frame.x = menu.x;
-	frame.y = menu.y;
 
 	mlk_game_init();
 	mlk_game_push(&state);
--- a/libmlk-ui/mlk/ui/frame.c	Fri Aug 11 19:45:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/frame.c	Fri Aug 11 18:01:28 2023 +0200
@@ -77,3 +77,12 @@
 	if (frame->delegate->draw)
 		frame->delegate->draw(frame->delegate, frame);
 }
+
+void
+mlk_frame_finish(struct mlk_frame *frame)
+{
+	assert(frame);
+
+	if (frame->delegate->finish)
+		frame->delegate->finish(frame->delegate, frame);
+}
--- a/libmlk-ui/mlk/ui/gridmenu.c	Fri Aug 11 19:45:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/gridmenu.c	Fri Aug 11 18:01:28 2023 +0200
@@ -24,11 +24,12 @@
 #include <mlk/core/font.h>
 #include <mlk/core/maths.h>
 #include <mlk/core/painter.h>
-#include <mlk/core/texture.h>
 #include <mlk/core/trace.h>
 #include <mlk/core/window.h>
 
 #include "gridmenu.h"
+#include "frame.h"
+#include "label.h"
 #include "style.h"
 #include "ui_p.h"
 
@@ -185,60 +186,49 @@
 }
 
 static void
-draw(struct mlk_gridmenu_delegate *self, const struct mlk_gridmenu *menu)
+draw_frame(struct mlk_gridmenu_delegate *self, const struct mlk_gridmenu *menu)
 {
 	(void)self;
 
-	const struct mlk_style *st = menu->style;
-	size_t pagesz, pagenr, item, c = 0, r = 0;
-	struct mlk_texture tex;
-	struct mlk_font *font;
-	unsigned long color;
-	int x, y;
+	struct mlk_frame frame;
 
-	/*
-	 * Select the first top-left column based on the current selection and
-	 * the number of rows/columns.
-	 */
-	pagesz = menu->nrows * menu->ncols;
-	pagenr = menu->selected / pagesz;
+	mlk_frame_init(&frame, menu->style, &mlk_frame_delegate);
+	frame.x = menu->x;
+	frame.y = menu->y;
+	frame.w = menu->w;
+	frame.h = menu->h;
 
-	for (size_t i = 0; i < pagesz; ++i) {
-		item = i + pagenr * pagesz;
-
-		if (item >= menu->itemsz || !menu->items[item])
-			continue;
+	mlk_frame_draw(&frame);
+	mlk_frame_finish(&frame);
+}
 
-		x = (int)(menu->x + st->normal.geo.padding + (c * menu->eltw) + (c * menu->spacew));
-		y = (int)(menu->y + st->normal.geo.padding + (r * menu->elth) + (r * menu->spaceh));
-
-		if (i == menu->selected % pagesz) {
-			color = st->selected.color.text;
-			font = st->selected.font;
-		} else {
-			color = st->normal.color.text;
-			font = st->normal.font;
-		}
+static void
+draw_item(struct mlk_gridmenu_delegate *self,
+          const struct mlk_gridmenu *menu,
+          const char *item,
+          unsigned int row,
+          unsigned int col,
+          int selected)
+{
+	(void)self;
 
-		if (mlk_font_render(font, &tex, menu->items[item], color) < 0) {
-			mlk_tracef(_("unable to render grid menu item: %s"), mlk_err());
-			continue;
-		}
+	struct mlk_label label;
 
-		mlk_texture_draw(&tex, x, y);
-		mlk_texture_finish(&tex);
+	mlk_label_init(&label, menu->style, &mlk_label_delegate);
+	label.x = menu->x + menu->style->normal.geo.padding + (col * menu->eltw) + (col * menu->spacew);
+	label.y = menu->y + menu->style->normal.geo.padding + (row * menu->elth) + (row * menu->spaceh);
+	label.text = item;
+	label.selected = selected;
 
-		if (++c >= menu->ncols) {
-			++r;
-			c = 0;
-		}
-	}
+	mlk_label_draw(&label);
+	mlk_label_finish(&label);
 }
 
 struct mlk_gridmenu_delegate mlk_gridmenu_delegate = {
 	.resize = resize,
 	.handle = handle,
-	.draw = draw
+	.draw_frame = draw_frame,
+	.draw_item = draw_item
 };
 
 void
@@ -310,6 +300,41 @@
 {
 	assert(menu);
 
-	if (menu->delegate->draw)
-		menu->delegate->draw(menu->delegate, menu);
+	size_t pagesz, pagenr, item;
+	unsigned int row = 0, col = 0;
+	int selected;
+
+	if (menu->delegate->draw_frame)
+		menu->delegate->draw_frame(menu->delegate, menu);
+
+	/*
+	 * Select the first top-left column based on the current selection and
+	 * the number of rows/columns.
+	 */
+	pagesz = menu->nrows * menu->ncols;
+	pagenr = menu->selected / pagesz;
+
+	for (size_t i = 0; i < pagesz; ++i) {
+		item = i + pagenr * pagesz;
+
+		if (item >= menu->itemsz || !menu->items[item])
+			continue;
+
+		selected = i == menu->selected % pagesz;
+
+		if (menu->delegate->draw_item)
+			menu->delegate->draw_item(
+			    menu->delegate,
+			    menu,
+			    menu->items[item],
+			    row,
+			    col,
+			    selected
+			);
+
+		if (++col >= menu->ncols) {
+			++row;
+			col = 0;
+		}
+	}
 }
--- a/libmlk-ui/mlk/ui/gridmenu.h	Fri Aug 11 19:45:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/gridmenu.h	Fri Aug 11 18:01:28 2023 +0200
@@ -166,13 +166,32 @@
 	/**
 	 * (read-write, optional)
 	 *
-	 * Draw this menu.
+	 * Draw a frame box for this menu.
 	 *
 	 * \param self this delegate
-	 * \param menu the menu to draw
+	 * \param menu the underlying menu
 	 */
-	void (*draw)(struct mlk_gridmenu_delegate *self,
-	             const struct mlk_gridmenu *menu);
+	void (*draw_frame)(struct mlk_gridmenu_delegate *self,
+	                   const struct mlk_gridmenu *menu);
+
+	/**
+	 * (read-write, optional)
+	 *
+	 * Draw a specific item.
+	 *
+	 * \param self this delegate
+	 * \param menu the underlying menu
+	 * \param item the item content
+	 * \param row the row number (relative)
+	 * \param col the column number (relative)
+	 * \param selected non-zero if the item is currently selected
+	 */
+	void (*draw_item)(struct mlk_gridmenu_delegate *self,
+	                  const struct mlk_gridmenu *menu,
+	                  const char *item,
+	                  unsigned int row,
+	                  unsigned int col,
+	                  int selected);
 
 	/**
 	 * (read-write, optional)
@@ -187,6 +206,9 @@
 
 };
 
+/**
+ * \brief Default stateless delegate for gridmenu.
+ */
 extern struct mlk_gridmenu_delegate mlk_gridmenu_delegate;
 
 #if defined(__cplusplus)
@@ -238,7 +260,10 @@
 mlk_gridmenu_update(struct mlk_gridmenu *menu, unsigned int ticks);
 
 /**
- * Invoke ::mlk_gridmenu_delegate::draw.
+ * Invoke the functions:
+ *
+ * - ::mlk_gridmenu_delegate::draw_frame,
+ * - ::mlk_gridmenu_delegate::draw_item.
  */
 void
 mlk_gridmenu_draw(const struct mlk_gridmenu *menu);
--- a/libmlk-ui/mlk/ui/label.c	Fri Aug 11 19:45:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/label.c	Fri Aug 11 18:01:28 2023 +0200
@@ -41,7 +41,12 @@
 {
 	(void)self;
 
-	const struct mlk_style_attr *attr = &label->style->normal;
+	const struct mlk_style_attr *attr;
+
+	if (label->selected)
+		attr = &label->style->selected;
+	else
+		attr = &label->style->normal;
 
 	mlk_ui_draw_text(
 		MLK_ALIGN_NONE,
--- a/libmlk-ui/mlk/ui/label.h	Fri Aug 11 19:45:00 2023 +0200
+++ b/libmlk-ui/mlk/ui/label.h	Fri Aug 11 18:01:28 2023 +0200
@@ -55,6 +55,13 @@
 	const char *text;
 
 	/**
+	 * (read-write)
+	 *
+	 * Tells if label is considered selected.
+	 */
+	int selected;
+
+	/**
 	 * (read-write, borrowed)
 	 *
 	 * Label style.