diff options
| author | Federico Angelilli <code@fedang.net> | 2023-11-19 12:29:04 +0100 |
|---|---|---|
| committer | Federico Angelilli <code@fedang.net> | 2023-11-19 12:29:04 +0100 |
| commit | 6ac026b7a28dcf704a2d239184f75c81cbdae008 (patch) | |
| tree | 0ca6991c5539b55ed83323e770ccb389dcfa658f | |
| parent | bd327c61eb3c59458b197e70f6c091d81dbde1ba (diff) | |
Add button alignment and layouting
| -rw-r--r-- | src/button.c | 3 | ||||
| -rw-r--r-- | src/button.h | 4 | ||||
| -rw-r--r-- | src/comet.c | 18 | ||||
| -rw-r--r-- | src/draw.c | 107 | ||||
| -rw-r--r-- | src/draw.h | 2 |
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); @@ -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) @@ -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); |
