particles: caller of from_conf() must provide base particle instance

This commit is contained in:
Daniel Eklöf 2019-01-13 13:25:14 +01:00
parent 770f2a0e7c
commit 7776135454
10 changed files with 107 additions and 147 deletions

View file

@ -149,17 +149,22 @@ particle_simple_list_from_config(const struct yml_node *node,
/* Lazy-loaded function pointer to particle_list_new() */ /* Lazy-loaded function pointer to particle_list_new() */
static struct particle *(*particle_list_new)( static struct particle *(*particle_list_new)(
struct particle *common,
struct particle *particles[], size_t count, struct particle *particles[], size_t count,
int left_spacing, int right_spacing, int left_margin, int right_margin, int left_spacing, int right_spacing) = NULL;
const char *on_click_template) = NULL;
if (particle_list_new == NULL) { if (particle_list_new == NULL) {
const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE); const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE);
particle_list_new = dlsym(plug->lib, "particle_list_new"); particle_list_new = dlsym(plug->lib, "particle_list_new");
assert(particle_list_new != NULL); assert(particle_list_new != NULL);
} }
return particle_list_new(parts, count, 0, 2, 0, 0, NULL); struct particle *common = particle_common_new(
0, 0, NULL, font_clone(parent_font),
(struct rgba){1.0, 1.0, 1.0, 1.0}, NULL);
return particle_list_new(common, parts, count, 0, 2);
} }
struct particle * struct particle *
@ -175,6 +180,9 @@ conf_to_particle(const struct yml_node *node, const struct font *parent_font)
const struct yml_node *left_margin = yml_get_value(pair.value, "left-margin"); const struct yml_node *left_margin = yml_get_value(pair.value, "left-margin");
const struct yml_node *right_margin = yml_get_value(pair.value, "right-margin"); const struct yml_node *right_margin = yml_get_value(pair.value, "right-margin");
const struct yml_node *on_click = yml_get_value(pair.value, "on-click"); const struct yml_node *on_click = yml_get_value(pair.value, "on-click");
const struct yml_node *font_node = yml_get_value(pair.value, "font");
const struct yml_node *foreground_node = yml_get_value(pair.value, "foreground");
const struct yml_node *deco_node = yml_get_value(pair.value, "deco");
int left = margin != NULL ? yml_value_as_int(margin) : int left = margin != NULL ? yml_value_as_int(margin) :
left_margin != NULL ? yml_value_as_int(left_margin) : 0; left_margin != NULL ? yml_value_as_int(left_margin) : 0;
@ -183,19 +191,19 @@ conf_to_particle(const struct yml_node *node, const struct font *parent_font)
const char *on_click_template const char *on_click_template
= on_click != NULL ? yml_value_as_string(on_click) : NULL; = on_click != NULL ? yml_value_as_string(on_click) : NULL;
struct font *font = font_node != NULL
? conf_to_font(font_node) : font_clone(parent_font);
struct rgba foreground = foreground_node != NULL
? conf_to_color(foreground_node) : (struct rgba){1.0, 1.0, 1.0, 1.0};
struct deco *deco = deco_node != NULL ? deco_from_config(deco_node) : NULL;
struct particle *common = particle_common_new(
left, right, on_click_template, font, foreground, deco);
const struct particle_info *info = plugin_load_particle(type); const struct particle_info *info = plugin_load_particle(type);
assert(info != NULL); assert(info != NULL);
struct particle *ret = info->from_conf( return info->from_conf(pair.value, common);
pair.value, parent_font, left, right, on_click_template);
const struct yml_node *deco_node = yml_get_value(pair.value, "deco");
if (deco_node != NULL)
ret->deco = deco_from_config(deco_node);
return ret;
} }
struct bar * struct bar *

View file

@ -17,19 +17,25 @@ particle_default_destroy(struct particle *particle)
{ {
if (particle->deco != NULL) if (particle->deco != NULL)
particle->deco->destroy(particle->deco); particle->deco->destroy(particle->deco);
font_destroy(particle->font);
free(particle->on_click_template); free(particle->on_click_template);
free(particle); free(particle);
} }
struct particle * struct particle *
particle_common_new(int left_margin, int right_margin, particle_common_new(int left_margin, int right_margin,
const char *on_click_template) const char *on_click_template,
struct font *font, struct rgba foreground,
struct deco *deco)
{ {
struct particle *p = malloc(sizeof(*p)); struct particle *p = malloc(sizeof(*p));
p->left_margin = left_margin; p->left_margin = left_margin;
p->right_margin = right_margin; p->right_margin = right_margin;
p->on_click_template = on_click_template != NULL ? strdup(on_click_template) : NULL; p->on_click_template =
p->deco = NULL; on_click_template != NULL ? strdup(on_click_template) : NULL;
p->foreground = foreground;
p->font = font;
p->deco = deco;
return p; return p;
} }

View file

@ -1,5 +1,4 @@
#pragma once #pragma once
#include <cairo.h> #include <cairo.h>
#include "color.h" #include "color.h"
@ -15,10 +14,7 @@ struct exposable;
struct particle_info { struct particle_info {
bool (*verify_conf)(keychain_t *chain, const struct yml_node *node); bool (*verify_conf)(keychain_t *chain, const struct yml_node *node);
struct particle *(*from_conf)(const struct yml_node *node, struct particle *(*from_conf)(const struct yml_node *node, struct particle *common);
const struct font *parent_font,
int left_margin, int right_margin,
const char *on_click_template);
#define PARTICLE_COMMON_ATTRS_COUNT 5 #define PARTICLE_COMMON_ATTRS_COUNT 5
#define PARTICLE_COMMON_ATTRS \ #define PARTICLE_COMMON_ATTRS \
@ -26,6 +22,8 @@ struct particle_info {
{"left-margin", false, &conf_verify_int}, \ {"left-margin", false, &conf_verify_int}, \
{"right-margin", false, &conf_verify_int}, \ {"right-margin", false, &conf_verify_int}, \
{"on-click", false, &conf_verify_string}, \ {"on-click", false, &conf_verify_string}, \
{"font", false, &conf_verify_font}, \
{"foreground", false, &conf_verify_color}, \
{"deco", false, &conf_verify_decoration}, \ {"deco", false, &conf_verify_decoration}, \
{NULL, false, NULL} {NULL, false, NULL}
@ -35,9 +33,12 @@ struct particle {
void *private; void *private;
int left_margin, right_margin; int left_margin, right_margin;
struct deco *deco;
char *on_click_template; char *on_click_template;
struct rgba foreground;
struct font *font;
struct deco *deco;
void (*destroy)(struct particle *particle); void (*destroy)(struct particle *particle);
struct exposable *(*instantiate)(const struct particle *particle, struct exposable *(*instantiate)(const struct particle *particle,
const struct tag_set *tags); const struct tag_set *tags);
@ -64,8 +65,10 @@ struct exposable {
enum mouse_event event, int x, int y); enum mouse_event event, int x, int y);
}; };
struct particle *particle_common_new(int left_margin, int right_margin, struct particle *particle_common_new(
const char *on_click_template); int left_margin, int right_margin, const char *on_click_template,
struct font *font, struct rgba foreground, struct deco *deco);
void particle_default_destroy(struct particle *particle); void particle_default_destroy(struct particle *particle);
struct exposable *exposable_common_new( struct exposable *exposable_common_new(

View file

@ -32,20 +32,17 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
} }
static struct particle * static struct particle *
empty_new(int left_margin, int right_margin, const char *on_click_template) empty_new(struct particle *common)
{ {
struct particle *particle = particle_common_new( common->destroy = &particle_default_destroy;
left_margin, right_margin, on_click_template); common->instantiate = &instantiate;
particle->destroy = &particle_default_destroy; return common;
particle->instantiate = &instantiate;
return particle;
} }
static struct particle * static struct particle *
from_conf(const struct yml_node *node, const struct font *parent_font, from_conf(const struct yml_node *node, struct particle *common)
int left_margin, int right_margin, const char *on_click_template)
{ {
return empty_new(left_margin, right_margin, on_click_template); return empty_new(common);
} }
static bool static bool

View file

@ -143,10 +143,9 @@ particle_destroy(struct particle *particle)
} }
struct particle * struct particle *
particle_list_new( particle_list_new(struct particle *common,
struct particle *particles[], size_t count, struct particle *particles[], size_t count,
int left_spacing, int right_spacing, int left_margin, int right_margin, int left_spacing, int right_spacing)
const char *on_click_template)
{ {
struct private *p = malloc(sizeof(*p)); struct private *p = malloc(sizeof(*p));
p->particles = malloc(count * sizeof(p->particles[0])); p->particles = malloc(count * sizeof(p->particles[0]));
@ -157,22 +156,16 @@ particle_list_new(
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
p->particles[i] = particles[i]; p->particles[i] = particles[i];
struct particle *particle = particle_common_new( common->private = p;
left_margin, right_margin, on_click_template); common->destroy = &particle_destroy;
common->instantiate = &instantiate;
particle->private = p; return common;
particle->destroy = &particle_destroy;
particle->instantiate = &instantiate;
return particle;
} }
static struct particle * static struct particle *
from_conf(const struct yml_node *node, const struct font *parent_font, from_conf(const struct yml_node *node, struct particle *common)
int left_margin, int right_margin, const char *on_click_template)
{ {
const struct yml_node *items = yml_get_value(node, "items"); const struct yml_node *items = yml_get_value(node, "items");
const struct yml_node *spacing = yml_get_value(node, "spacing"); const struct yml_node *spacing = yml_get_value(node, "spacing");
const struct yml_node *_left_spacing = yml_get_value(node, "left-spacing"); const struct yml_node *_left_spacing = yml_get_value(node, "left-spacing");
const struct yml_node *_right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *_right_spacing = yml_get_value(node, "right-spacing");
@ -190,12 +183,10 @@ from_conf(const struct yml_node *node, const struct font *parent_font,
it.node != NULL; it.node != NULL;
yml_list_next(&it), idx++) yml_list_next(&it), idx++)
{ {
parts[idx] = conf_to_particle(it.node, parent_font); parts[idx] = conf_to_particle(it.node, common->font);
} }
return particle_list_new( return particle_list_new(common, parts, count, left_spacing, right_spacing);
parts, count, left_spacing, right_spacing, left_margin, right_margin,
on_click_template);
} }
static bool static bool

View file

@ -2,8 +2,8 @@
#include "../particle.h" #include "../particle.h"
struct particle *particle_list_new( struct particle *particle_list_new(
struct particle *common,
struct particle *particles[], size_t count, struct particle *particles[], size_t count,
int left_spacing, int right_spacing, int left_margin, int right_margin, int left_spacing, int right_spacing);
const char *on_click_template);
extern const struct particle_info particle_list; extern const struct particle_info particle_list;

View file

@ -146,16 +146,10 @@ particle_destroy(struct particle *particle)
} }
static struct particle * static struct particle *
map_new(const char *tag, const struct particle_map *particle_map, map_new(struct particle *common, const char *tag,
size_t count, struct particle *default_particle, const struct particle_map particle_map[], size_t count,
int left_margin, int right_margin, struct particle *default_particle)
const char *on_click_template)
{ {
struct particle *particle = particle_common_new(
left_margin, right_margin, on_click_template);
particle->destroy = &particle_destroy;
particle->instantiate = &instantiate;
struct private *priv = malloc(sizeof(*priv)); struct private *priv = malloc(sizeof(*priv));
priv->tag = strdup(tag); priv->tag = strdup(tag);
priv->default_particle = default_particle; priv->default_particle = default_particle;
@ -167,8 +161,10 @@ map_new(const char *tag, const struct particle_map *particle_map,
priv->map[i].particle = particle_map[i].particle; priv->map[i].particle = particle_map[i].particle;
} }
particle->private = priv; common->private = priv;
return particle; common->destroy = &particle_destroy;
common->instantiate = &instantiate;
return common;
} }
static bool static bool
@ -201,8 +197,7 @@ verify_map_values(keychain_t *chain, const struct yml_node *node)
} }
static struct particle * static struct particle *
from_conf(const struct yml_node *node, const struct font *parent_font, from_conf(const struct yml_node *node, struct particle *common)
int left_margin, int right_margin, const char *on_click_template)
{ {
const struct yml_node *tag = yml_get_value(node, "tag"); const struct yml_node *tag = yml_get_value(node, "tag");
const struct yml_node *values = yml_get_value(node, "values"); const struct yml_node *values = yml_get_value(node, "values");
@ -216,16 +211,15 @@ from_conf(const struct yml_node *node, const struct font *parent_font,
yml_dict_next(&it), idx++) yml_dict_next(&it), idx++)
{ {
particle_map[idx].tag_value = yml_value_as_string(it.key); particle_map[idx].tag_value = yml_value_as_string(it.key);
particle_map[idx].particle = conf_to_particle(it.value, parent_font); particle_map[idx].particle = conf_to_particle(it.value, common->font);
} }
struct particle *default_particle = def != NULL struct particle *default_particle = def != NULL
? conf_to_particle(def, parent_font) ? conf_to_particle(def, common->font) : NULL;
: NULL;
return map_new( return map_new(
yml_value_as_string(tag), particle_map, yml_dict_length(values), common, yml_value_as_string(tag), particle_map, yml_dict_length(values),
default_particle, left_margin, right_margin, on_click_template); default_particle);
} }
static bool static bool

View file

@ -208,13 +208,10 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
} }
static struct particle * static struct particle *
progress_bar_new(const char *tag, int width, progress_bar_new(struct particle *common, const char *tag, int width,
struct particle *start_marker, struct particle *start_marker, struct particle *end_marker,
struct particle *end_marker,
struct particle *fill, struct particle *empty, struct particle *fill, struct particle *empty,
struct particle *indicator, struct particle *indicator)
int left_margin, int right_margin,
const char *on_click_template)
{ {
struct private *priv = malloc(sizeof(*priv)); struct private *priv = malloc(sizeof(*priv));
priv->tag = strdup(tag); priv->tag = strdup(tag);
@ -225,18 +222,14 @@ progress_bar_new(const char *tag, int width,
priv->empty = empty; priv->empty = empty;
priv->indicator = indicator; priv->indicator = indicator;
struct particle *particle = particle_common_new( common->private = priv;
left_margin, right_margin, on_click_template); common->destroy = &particle_destroy;
particle->private = priv; common->instantiate = &instantiate;
particle->destroy = &particle_destroy; return common;
particle->instantiate = &instantiate;
return particle;
} }
static struct particle * static struct particle *
from_conf(const struct yml_node *node, const struct font *parent_font, from_conf(const struct yml_node *node, struct particle *common)
int left_margin, int right_margin, const char *on_click_template)
{ {
const struct yml_node *tag = yml_get_value(node, "tag"); const struct yml_node *tag = yml_get_value(node, "tag");
const struct yml_node *length = yml_get_value(node, "length"); const struct yml_node *length = yml_get_value(node, "length");
@ -247,14 +240,14 @@ from_conf(const struct yml_node *node, const struct font *parent_font,
const struct yml_node *indicator = yml_get_value(node, "indicator"); const struct yml_node *indicator = yml_get_value(node, "indicator");
return progress_bar_new( return progress_bar_new(
common,
yml_value_as_string(tag), yml_value_as_string(tag),
yml_value_as_int(length), yml_value_as_int(length),
conf_to_particle(start, parent_font), conf_to_particle(start, common->font),
conf_to_particle(end, parent_font), conf_to_particle(end, common->font),
conf_to_particle(fill, parent_font), conf_to_particle(fill, common->font),
conf_to_particle(empty, parent_font), conf_to_particle(empty, common->font),
conf_to_particle(indicator, parent_font), conf_to_particle(indicator, common->font));
left_margin, right_margin, on_click_template);
} }
static bool static bool

View file

@ -135,13 +135,9 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
} }
static struct particle * static struct particle *
ramp_new(const char *tag, struct particle *particles[], size_t count, ramp_new(struct particle *common, const char *tag,
int left_margin, int right_margin, const char *on_click_template) struct particle *particles[], size_t count)
{ {
struct particle *particle = particle_common_new(
left_margin, right_margin, on_click_template);
particle->destroy = &particle_destroy;
particle->instantiate = &instantiate;
struct private *priv = malloc(sizeof(*priv)); struct private *priv = malloc(sizeof(*priv));
priv->tag = strdup(tag); priv->tag = strdup(tag);
@ -151,13 +147,14 @@ ramp_new(const char *tag, struct particle *particles[], size_t count,
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
priv->particles[i] = particles[i]; priv->particles[i] = particles[i];
particle->private = priv; common->private = priv;
return particle; common->destroy = &particle_destroy;
common->instantiate = &instantiate;
return common;
} }
static struct particle * static struct particle *
from_conf(const struct yml_node *node, const struct font *parent_font, from_conf(const struct yml_node *node, struct particle *common)
int left_margin, int right_margin, const char *on_click_template)
{ {
const struct yml_node *tag = yml_get_value(node, "tag"); const struct yml_node *tag = yml_get_value(node, "tag");
const struct yml_node *items = yml_get_value(node, "items"); const struct yml_node *items = yml_get_value(node, "items");
@ -170,12 +167,10 @@ from_conf(const struct yml_node *node, const struct font *parent_font,
it.node != NULL; it.node != NULL;
yml_list_next(&it), idx++) yml_list_next(&it), idx++)
{ {
parts[idx] = conf_to_particle(it.node, parent_font); parts[idx] = conf_to_particle(it.node, common->font);
} }
return ramp_new( return ramp_new(common, yml_value_as_string(tag), parts, count);
yml_value_as_string(tag), parts, count, left_margin, right_margin,
on_click_template);
} }
static bool static bool

View file

@ -12,17 +12,10 @@
struct private { struct private {
char *text; char *text;
size_t max_len; size_t max_len;
struct font *font;
struct rgba foreground;
}; };
struct eprivate { struct eprivate {
char *text; char *text;
const struct font *font;
struct rgba foreground;
cairo_text_extents_t extents; cairo_text_extents_t extents;
}; };
@ -40,7 +33,7 @@ begin_expose(struct exposable *exposable)
{ {
struct eprivate *e = exposable->private; struct eprivate *e = exposable->private;
cairo_scaled_font_t *scaled = font_scaled_font(e->font); cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
cairo_scaled_font_text_extents(scaled, e->text, &e->extents); cairo_scaled_font_text_extents(scaled, e->text, &e->extents);
exposable->width = (exposable->particle->left_margin + exposable->width = (exposable->particle->left_margin +
@ -58,7 +51,7 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
const struct eprivate *e = exposable->private; const struct eprivate *e = exposable->private;
const size_t text_len = strlen(e->text); const size_t text_len = strlen(e->text);
cairo_scaled_font_t *scaled = font_scaled_font(e->font); cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
cairo_glyph_t *glyphs = NULL; cairo_glyph_t *glyphs = NULL;
cairo_text_cluster_t *clusters = NULL; cairo_text_cluster_t *clusters = NULL;
@ -73,10 +66,10 @@ expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
cairo_set_scaled_font(cr, scaled); cairo_set_scaled_font(cr, scaled);
cairo_set_source_rgba(cr, cairo_set_source_rgba(cr,
e->foreground.red, exposable->particle->foreground.red,
e->foreground.green, exposable->particle->foreground.green,
e->foreground.blue, exposable->particle->foreground.blue,
e->foreground.alpha); exposable->particle->foreground.alpha);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_show_text_glyphs( cairo_show_text_glyphs(
@ -94,8 +87,6 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
struct eprivate *e = malloc(sizeof(*e)); struct eprivate *e = malloc(sizeof(*e));
e->text = tags_expand_template(p->text, tags); e->text = tags_expand_template(p->text, tags);
e->font = p->font;
e->foreground = p->foreground;
memset(&e->extents, 0, sizeof(e->extents)); memset(&e->extents, 0, sizeof(e->extents));
if (p->max_len > 0) { if (p->max_len > 0) {
@ -125,50 +116,34 @@ static void
particle_destroy(struct particle *particle) particle_destroy(struct particle *particle)
{ {
struct private *p = particle->private; struct private *p = particle->private;
font_destroy(p->font);
free(p->text); free(p->text);
free(p); free(p);
particle_default_destroy(particle); particle_default_destroy(particle);
} }
static struct particle * static struct particle *
string_new(const char *text, size_t max_len, struct font *font, string_new(struct particle *common, const char *text, size_t max_len)
struct rgba foreground, int left_margin, int right_margin,
const char *on_click_template)
{ {
struct private *p = malloc(sizeof(*p)); struct private *p = malloc(sizeof(*p));
p->text = strdup(text); p->text = strdup(text);
p->max_len = max_len; p->max_len = max_len;
p->font = font;
p->foreground = foreground;
struct particle *particle = particle_common_new( common->private = p;
left_margin, right_margin, on_click_template); common->destroy = &particle_destroy;
common->instantiate = &instantiate;
particle->private = p; return common;
particle->destroy = &particle_destroy;
particle->instantiate = &instantiate;
return particle;
} }
static struct particle * static struct particle *
from_conf(const struct yml_node *node, const struct font *parent_font, from_conf(const struct yml_node *node, struct particle *common)
int left_margin, int right_margin, const char *on_click_template)
{ {
const struct yml_node *text = yml_get_value(node, "text"); const struct yml_node *text = yml_get_value(node, "text");
const struct yml_node *max = yml_get_value(node, "max"); const struct yml_node *max = yml_get_value(node, "max");
const struct yml_node *font = yml_get_value(node, "font");
const struct yml_node *foreground = yml_get_value(node, "foreground");
struct rgba fg_color = foreground != NULL
? conf_to_color(foreground) : (struct rgba){1.0, 1.0, 1.0, 1.0};
return string_new( return string_new(
common,
yml_value_as_string(text), yml_value_as_string(text),
max != NULL ? yml_value_as_int(max) : 0, max != NULL ? yml_value_as_int(max) : 0);
font != NULL ? conf_to_font(font) : font_clone(parent_font),
fg_color, left_margin, right_margin, on_click_template);
} }
static bool static bool
@ -177,8 +152,6 @@ verify_conf(keychain_t *chain, const struct yml_node *node)
static const struct attr_info attrs[] = { static const struct attr_info attrs[] = {
{"text", true, &conf_verify_string}, {"text", true, &conf_verify_string},
{"max", false, &conf_verify_int}, {"max", false, &conf_verify_int},
{"font", false, &conf_verify_font},
{"foreground", false, &conf_verify_color},
PARTICLE_COMMON_ATTRS, PARTICLE_COMMON_ATTRS,
}; };