#include "dynlist.h" #include #include #define LOG_MODULE "dynlist" #include "../log.h" #include "../particle.h" struct private { int left_spacing; int right_spacing; struct exposable **exposables; size_t count; int *widths; }; static void dynlist_destroy(struct exposable *exposable) { struct private *e = exposable->private; for (size_t i = 0; i < e->count; i++) { struct exposable *ee = e->exposables[i]; ee->destroy(ee); } free(e->exposables); free(e->widths); free(e); free(exposable); } static int dynlist_begin_expose(struct exposable *exposable) { const struct private *e = exposable->private; exposable->width = 0; bool have_at_least_one = false; for (size_t i = 0; i < e->count; i++) { struct exposable *ee = e->exposables[i]; e->widths[i] = ee->begin_expose(ee); assert(e->widths[i] >= 0); if (e->widths[i] > 0) { exposable->width += e->left_spacing + e->widths[i] + e->right_spacing; have_at_least_one = true; } } if (have_at_least_one) exposable->width -= e->left_spacing + e->right_spacing; else assert(exposable->width == 0); return exposable->width; } static void dynlist_expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height) { const struct private *e = exposable->private; int left_spacing = e->left_spacing; int right_spacing = e->right_spacing; x -= left_spacing; for (size_t i = 0; i < e->count; i++) { const struct exposable *ee = e->exposables[i]; ee->expose(ee, pix, x + left_spacing, y, height); x += left_spacing + e->widths[i] + right_spacing; } } static void on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y) { const struct private *e = exposable->private; if (exposable->on_click[btn] != NULL) { exposable_default_on_mouse(exposable, bar, event, btn, x, y); return; } int px = /*p->left_margin;*/0; for (size_t i = 0; i < e->count; i++) { if (x >= px && x < px + e->exposables[i]->width) { if (e->exposables[i]->on_mouse != NULL) { e->exposables[i]->on_mouse( e->exposables[i], bar, event, btn, x - px, y); } return; } px += e->left_spacing + e->exposables[i]->width + e->right_spacing; } LOG_DBG("on_mouse missed all sub-particles"); exposable_default_on_mouse(exposable, bar, event, btn, x, y); } struct exposable * dynlist_exposable_new(struct exposable **exposables, size_t count, int left_spacing, int right_spacing) { struct private *e = calloc(1, sizeof(*e)); e->count = count; e->exposables = malloc(count * sizeof(e->exposables[0])); e->widths = calloc(count, sizeof(e->widths[0])); e->left_spacing = left_spacing; e->right_spacing = right_spacing; for (size_t i = 0; i < count; i++) e->exposables[i] = exposables[i]; struct exposable *exposable = exposable_common_new(NULL, NULL); exposable->private = e; exposable->destroy = &dynlist_destroy; exposable->begin_expose = &dynlist_begin_expose; exposable->expose = &dynlist_expose; exposable->on_mouse = &on_mouse; return exposable; }