changeset 158:e8d2740703df

ui: make message auto-spacing lines
author David Demelier <markand@malikania.fr>
date Fri, 16 Oct 2020 17:45:39 +0200
parents fb306ed990f8
children e05a792f6910
files examples/example-message.c librpg/rpg/message.c
diffstat 2 files changed, 38 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-message.c	Fri Oct 16 14:32:22 2020 +0200
+++ b/examples/example-message.c	Fri Oct 16 17:45:39 2020 +0200
@@ -38,7 +38,7 @@
 #define H       (720)
 
 #define MW      (W * 0.75)
-#define MH      (H * 0.130)
+#define MH      (H * 0.120)
 #define MX      ((W / 2) - (MW / 2))
 #define MY      (100)
 
@@ -303,7 +303,7 @@
 		.h = 500,
 		.text = {
 			"And this one is terribly large.",
-			"But lines are still padded at top."
+			"So lines will have large spacing."
 		},
 	};
 
--- a/librpg/rpg/message.c	Fri Oct 16 14:32:22 2020 +0200
+++ b/librpg/rpg/message.c	Fri Oct 16 17:45:39 2020 +0200
@@ -78,25 +78,50 @@
 	frame_draw(&frame);
 }
 
+static inline unsigned int
+spacing(const struct message *msg, const struct theme *t, unsigned int fh)
+{
+	assert(msg);
+	assert(t);
+
+	/* No vertical spacing if only one message. */
+	if (MESSAGE_LINES_MAX <= 1)
+		return 0;
+
+	return ((msg->h - t->padding * 2) - (fh * MESSAGE_LINES_MAX)) / (MESSAGE_LINES_MAX - 1);
+}
+
+static inline unsigned int
+height(const struct theme *t, unsigned int lvreq)
+{
+	assert(t);
+
+	return lvreq * MESSAGE_LINES_MAX;
+}
+
 static void
 draw_lines(const struct message *msg)
 {
 	struct theme theme;
-	unsigned int lineh, totalh;
+	unsigned int lvreq, vreq, vspace = 0;
 
 	/* Shallow copy theme to modify colors. */
 	theme_shallow(&theme, msg->theme);
 
 	/*
-	 * Compute text size for list alignment and full height required to emit
-	 * a warning if the message box is too small.
+	 * Compute the maximum line height for the given font.
+	 *
+	 * Then, compute the minimum height required to draw the lines (without
+	 * their vertical spacing).
 	 */
-	lineh = font_height(theme.fonts[THEME_FONT_INTERFACE]);
-	totalh = lineh * MESSAGE_LINES_MAX + (MESSAGE_LINES_MAX + 1) * theme.padding;
+	lvreq = font_height(theme.fonts[THEME_FONT_INTERFACE]);
+	vreq = height(&theme, lvreq);
 
-	/* Check if there is enough room to draw all lines. */
-	if (totalh > msg->h)
-		trace("message height is too small: %u < %u", msg->h, totalh);
+	/* Now if enough space, compute the spacing between lines. */
+	if (vreq > msg->h)
+		trace("message height is too small: %u < %u", msg->h, vreq);
+	else
+		vspace = spacing(msg, &theme, lvreq);
 
 	for (int i = 0; i < MESSAGE_LINES_MAX; ++i) {
 		if (!msg->text[i])
@@ -104,7 +129,7 @@
 
 		struct label label = {
 			.x = theme.padding,
-			.y = theme.padding * (i + 1) + i * lineh,
+			.y = theme.padding + (i * (lvreq + vspace)),
 			.w = msg->w,
 			.h = msg->h,
 			.theme = &theme,
@@ -118,9 +143,9 @@
 		 * we need to cheat the normal color.
 		 */
 		if (msg->flags & MESSAGE_FLAGS_QUESTION && msg->index == (unsigned int)i)
-			theme.colors[THEME_COLOR_NORMAL] = THEME(msg)->colors[THEME_COLOR_SELECTED];
+			theme.colors[THEME_COLOR_NORMAL] = theme.colors[THEME_COLOR_SELECTED];
 		else
-			theme.colors[THEME_COLOR_NORMAL] = THEME(msg)->colors[THEME_COLOR_NORMAL];
+			theme.colors[THEME_COLOR_NORMAL] = theme.colors[THEME_COLOR_NORMAL];
 
 		label_query(&label);