aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2023-11-19 12:29:04 +0100
committerFederico Angelilli <code@fedang.net>2023-11-19 12:29:04 +0100
commit6ac026b7a28dcf704a2d239184f75c81cbdae008 (patch)
tree0ca6991c5539b55ed83323e770ccb389dcfa658f /src
parentbd327c61eb3c59458b197e70f6c091d81dbde1ba (diff)
Add button alignment and layouting
Diffstat (limited to 'src')
-rw-r--r--src/button.c3
-rw-r--r--src/button.h4
-rw-r--r--src/comet.c18
-rw-r--r--src/draw.c107
-rw-r--r--src/draw.h2
5 files changed, 113 insertions, 21 deletions
diff --git a/src/button.c b/src/button.c
index 3a4e311..11ca2b7 100644
--- a/src/button.c
+++ b/src/button.c
@@ -2,10 +2,11 @@
#include "button.h"
-Button *button_create(const char *text)
+Button *button_create(const char *text, PangoAlignment align)
{
Button *btn = g_malloc0(sizeof(Button));
btn->text = g_strdup(text);
+ btn->align = align;
return btn;
}
diff --git a/src/button.h b/src/button.h
index 7df70d3..1d736e6 100644
--- a/src/button.h
+++ b/src/button.h
@@ -2,6 +2,7 @@
#define COMET_BUTTON_H
#include <stdbool.h>
+#include <pango/pangocairo.h>
// TODO: Generic button shapes/actions
@@ -12,9 +13,10 @@ typedef void (* ButtonAction)(Button *btn);
struct Button {
ButtonAction action;
char *text;
+ PangoAlignment align;
};
-Button *button_create(const char *text);
+Button *button_create(const char *text, PangoAlignment align);
void button_set_action(Button *btn, ButtonAction action);
diff --git a/src/comet.c b/src/comet.c
index 268d846..a1bc605 100644
--- a/src/comet.c
+++ b/src/comet.c
@@ -69,16 +69,24 @@ int main(int argc, char **argv)
for (int i = 0; i < 9; ++i) {
char text[] = { '1' + i, '\0' };
- Button *btn = button_create(text);
+ Button *btn = button_create(text, PANGO_ALIGN_LEFT);
button_set_action(btn, action);
state_add_button(state, btn);
}
- Button *btn = button_create("long button");
- button_set_action(btn, action);
- state_add_button(state, btn);
+ Button *long_btn = button_create("long button", PANGO_ALIGN_CENTER);
+ button_set_action(long_btn, action);
+ state_add_button(state, long_btn);
- draw_compute_layout(draw, state->btns, window_get_context(win));
+ Button *date_btn = button_create("date = today", PANGO_ALIGN_RIGHT);
+ button_set_action(date_btn, action);
+ state_add_button(state, date_btn);
+
+ Button *u_btn = button_create("U", PANGO_ALIGN_RIGHT);
+ button_set_action(u_btn, action);
+ state_add_button(state, u_btn);
+
+ draw_compute_layout(draw, win, state->btns);
connect_attach_state(con, state);
connect_attach_source(con);
diff --git a/src/draw.c b/src/draw.c
index 91ae186..310bca9 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -41,18 +41,27 @@ Drawable *draw_create(const char *font, int height, int left_pad, int right_pad,
return draw;
}
-void draw_paint(Drawable *draw, Window *win)
+static void compute_width(Drawable *draw, Window *win, int *width, int *height)
{
// FIXME: Does not work for scale != 1
//double scale = window_get_scale(win);
double scale = 1;
- int screen_width, screen_height;
- window_get_screen_size(win, &screen_width, &screen_height);
+ int screen_width = win->con->screen_size->width;
+ int screen_height = win->con->screen_size->height;
+
+ *width = round(screen_width - draw->right_pad - draw->left_pad * scale);
+ *height = round(draw->height * scale);
+}
+
+void draw_paint(Drawable *draw, Window *win)
+{
+ // FIXME: Does not work for scale != 1
+ //double scale = window_get_scale(win);
+ double scale = 1;
- int width0 = screen_width - draw->right_pad - draw->left_pad;
- int width = round(width0 * scale);
- int height = round(draw->height * scale);
+ int width, height;
+ compute_width(draw, win, &width, &height);
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
@@ -112,13 +121,23 @@ void draw_paint(Drawable *draw, Window *win)
// TODO: Move these somewhere else
window_move(win, draw->left_pad, draw->top_pad);
- window_resize(win, width0, draw->height);
+ window_resize(win, width, draw->height);
window_paint_surface(win, surface, width, height);
cairo_surface_destroy(surface);
}
-void draw_compute_layout(Drawable *draw, GList *btns, cairo_t *cr)
+static gint align_compare(gconstpointer a, gconstpointer b)
+{
+ PangoAlignment a_align = ((Button *)a)->align;
+ PangoAlignment b_align = ((Button *)b)->align;
+
+ if (a_align < b_align) return -1;
+ if (a_align > b_align) return 1;
+ return 0;
+}
+
+void draw_compute_layout(Drawable *draw, Window *win, GList *btns)
{
g_list_free_full(draw->layouts, (GDestroyNotify)layout_destroy);
draw->layouts = NULL;
@@ -127,20 +146,31 @@ void draw_compute_layout(Drawable *draw, GList *btns, cairo_t *cr)
//double scale = window_get_scale(win);
double scale = 1;
+ int width, height;
+ compute_width(draw, win, &width, &height);
+
int x = 0;
- int height = round(draw->height * scale);
int radius = height / 2;
+ btns = g_list_sort(btns, align_compare);
+
+ GList *adjust_center = NULL;
+ GList *adjust_right = NULL;
+
+ int end_xs[3] = { 0 };
+ Button *prev = NULL;
+
for (GList *it = btns; it; it = it->next) {
Button *btn = it->data;
+
Layout *layout = g_malloc(sizeof(Layout));
layout->btn = btn;
layout->x = x;
layout->y = 0;
- layout->pl = pango_cairo_create_layout(cr);
+ layout->pl = pango_cairo_create_layout(window_get_context(win));
pango_layout_set_font_description(layout->pl, draw->desc);
pango_layout_set_text(layout->pl, btn->text, -1);
pango_layout_set_alignment(layout->pl, PANGO_ALIGN_CENTER);
@@ -157,14 +187,65 @@ void draw_compute_layout(Drawable *draw, GList *btns, cairo_t *cr)
layout->width = text_l == 1 ? height : layout->text_w + 2 * radius;
layout->height = height;
- draw->layouts = g_list_append(draw->layouts, layout);
+ draw->layouts = g_list_prepend(draw->layouts, layout);
+
+ if (prev != NULL) {
+ if (prev->align == btn->align) {
+ int sep = 10 * scale;
+ x += sep;
+ // Ugly update for layout
+ layout->x = x;
+ } else {
+ if (btn->align == PANGO_ALIGN_CENTER) adjust_center = draw->layouts;
+ else if (btn->align == PANGO_ALIGN_RIGHT) adjust_right = draw->layouts;
+ }
+ }
- int sep = 10 * scale;
int line_w = 1 * scale;
- x += height + line_w * 2 + sep;
+ x += layout->width + line_w * 2;
+
+ prev = btn;
+ end_xs[btn->align] = x;
+ }
+
+ draw->layouts = g_list_reverse(draw->layouts);
+
+ int widths[3] = {
+ end_xs[0],
+ end_xs[1] - end_xs[0],
+ end_xs[2] - MAX(end_xs[1], end_xs[0]),
+ };
+
+ int start_xs[3] = {
+ 0,
+ end_xs[0],
+ MAX(end_xs[1], end_xs[0]),
+ };
+
+ log_info("e1 = %d, e2 = %d, e3 = %d", end_xs[0], end_xs[1], end_xs[2]);
+ log_info("s1 = %d, s2 = %d, s3 = %d", start_xs[0], start_xs[1], start_xs[2]);
+ log_info("w1 = %d, w2 = %d, w3 = %d", widths[0], widths[1], widths[2]);
+
+ int center = round(width / 2);
+ int center_off = (center - widths[1] / 2) - start_xs[1];
+ log_debug("Aligning center layout [x=%d, off=%d]", center, center_off);
+
+ for (GList *it = adjust_center; it != adjust_right; it = it->next) {
+ Layout *layout = it->data;
+ layout->x += center_off;
+ }
+
+ int right = width - widths[2];
+ int right_off = right - start_xs[2];
+ log_debug("Aligning right layout [x=%d, off=%d]", right, right_off);
+
+ for (GList *it = adjust_right; it != NULL; it = it->next) {
+ Layout *layout = it->data;
+ layout->x += right_off;
}
log_debug("Updated layouts");
+ g_list_free(btns);
}
void draw_destroy(Drawable *draw)
diff --git a/src/draw.h b/src/draw.h
index 9c46900..3d3f7ed 100644
--- a/src/draw.h
+++ b/src/draw.h
@@ -30,7 +30,7 @@ typedef struct {
Drawable *draw_create(const char *font, int height, int left_pad, int right_pad, int top_pad, double alpha);
-void draw_compute_layout(Drawable *draw, GList *btns, cairo_t *cr);
+void draw_compute_layout(Drawable *draw, Window *win, GList *btns);
void draw_paint(Drawable *draw, Window *win);