From 6f5572ff6b29d1919711995008d317e19b4ff0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sat, 29 Dec 2018 20:54:41 +0100 Subject: [PATCH] particle/map: implement left/right margin This is done by wrapping the selected particle/exposable in a ramp-specific exposable. This way, we can add the margins before delegating begin_expose() and expose() to the selected exposable. --- particles/map.c | 66 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/particles/map.c b/particles/map.c index 5735e9f..34d65ea 100644 --- a/particles/map.c +++ b/particles/map.c @@ -11,6 +11,45 @@ struct private { size_t count; }; +struct eprivate { + struct exposable *exposable; +}; + +static void +exposable_destroy(struct exposable *exposable) +{ + struct eprivate *e = exposable->private; + e->exposable->destroy(e->exposable); + + free(e); + exposable_default_destroy(exposable); +} + +static int +begin_expose(struct exposable *exposable, cairo_t *cr) +{ + struct eprivate *e = exposable->private; + + exposable->width = ( + exposable->particle->left_margin + + e->exposable->begin_expose(e->exposable, cr) + + exposable->particle->right_margin); + + return exposable->width; +} + +static void +expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height) +{ + const struct deco *deco = exposable->particle->deco; + if (deco != NULL) + deco->expose(deco, cr, x, y, exposable->width, height); + + struct eprivate *e = exposable->private; + e->exposable->expose( + e->exposable, cr, x + exposable->particle->left_margin, y, height); +} + static struct exposable * instantiate(const struct particle *particle, const struct tag_set *tags) { @@ -23,17 +62,35 @@ instantiate(const struct particle *particle, const struct tag_set *tags) const char *tag_value = tag->as_string(tag); + struct particle *pp = NULL; + for (size_t i = 0; i < p->count; i++) { const struct particle_map *e = &p->map[i]; if (strcmp(e->tag_value, tag_value) != 0) continue; - return e->particle->instantiate(e->particle, tags); + pp = e->particle; + break; } - assert(p->default_particle != NULL); - return p->default_particle->instantiate(p->default_particle, tags); + if (pp == NULL) { + assert(p->default_particle != NULL); + pp = p->default_particle; + } + + struct eprivate *e = malloc(sizeof(*e)); + e->exposable = pp->instantiate(pp, tags); + + char *on_click = tags_expand_template(particle->on_click_template, tags); + struct exposable *exposable = exposable_common_new(particle, on_click); + exposable->private = e; + exposable->destroy = &exposable_destroy; + exposable->begin_expose = &begin_expose; + exposable->expose = &expose; + + free(on_click); + return exposable; } static void @@ -61,9 +118,6 @@ particle_map_new(const char *tag, const struct particle_map *particle_map, size_t count, struct particle *default_particle, int left_margin, int right_margin) { - assert(left_margin == 0 && right_margin == 0 - && "map: margins not implemented"); - struct particle *particle = particle_common_new( left_margin, right_margin, NULL); particle->destroy = &particle_destroy;