yambar/particles/string.c
Daniel Eklöf 07b1615a41 particles: get rid of struct particle_info
Since this struct only contained function pointers, make all particles
export those functions directly.

The plugin manager now defines a particle interface struct, and fills
it it by dlsym:ing the functions that used to be in particle_info.
2019-01-13 17:03:35 +01:00

158 lines
4.3 KiB
C

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define LOG_MODULE "string"
#define LOG_ENABLE_DBG 1
#include "../log.h"
#include "../config.h"
#include "../particle.h"
struct private {
char *text;
size_t max_len;
};
struct eprivate {
char *text;
cairo_text_extents_t extents;
};
static void
exposable_destroy(struct exposable *exposable)
{
struct eprivate *e = exposable->private;
free(e->text);
free(e);
exposable_default_destroy(exposable);
}
static int
begin_expose(struct exposable *exposable)
{
struct eprivate *e = exposable->private;
cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
cairo_scaled_font_text_extents(scaled, e->text, &e->extents);
exposable->width = (exposable->particle->left_margin +
e->extents.x_advance +
exposable->particle->right_margin);
return exposable->width;
}
static void
expose(const struct exposable *exposable, cairo_t *cr, int x, int y, int height)
{
exposable_render_deco(exposable, cr, x, y, height);
const struct eprivate *e = exposable->private;
const size_t text_len = strlen(e->text);
cairo_scaled_font_t *scaled = font_scaled_font(exposable->particle->font);
cairo_glyph_t *glyphs = NULL;
cairo_text_cluster_t *clusters = NULL;
cairo_text_cluster_flags_t cluster_flags;
int num_glyphs, num_clusters;
cairo_scaled_font_text_to_glyphs(
scaled,
x + exposable->particle->left_margin,
(double)y + ((double)height - e->extents.height) / 2 - e->extents.y_bearing,
e->text, text_len, &glyphs, &num_glyphs,
&clusters, &num_clusters, &cluster_flags);
cairo_set_scaled_font(cr, scaled);
cairo_set_source_rgba(cr,
exposable->particle->foreground.red,
exposable->particle->foreground.green,
exposable->particle->foreground.blue,
exposable->particle->foreground.alpha);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_show_text_glyphs(
cr, e->text, text_len, glyphs, num_glyphs,
clusters, num_clusters, cluster_flags);
cairo_glyph_free(glyphs);
cairo_text_cluster_free(clusters);
}
static struct exposable *
instantiate(const struct particle *particle, const struct tag_set *tags)
{
const struct private *p = particle->private;
struct eprivate *e = malloc(sizeof(*e));
e->text = tags_expand_template(p->text, tags);
memset(&e->extents, 0, sizeof(e->extents));
if (p->max_len > 0) {
size_t len = strlen(e->text);
if (len > p->max_len) {
if (p->max_len >= 3) {
for (size_t i = 0; i < 3; i++)
e->text[p->max_len - 3 + i] = '.';
}
e->text[p->max_len] = '\0';
}
}
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
particle_destroy(struct particle *particle)
{
struct private *p = particle->private;
free(p->text);
free(p);
particle_default_destroy(particle);
}
static struct particle *
string_new(struct particle *common, const char *text, size_t max_len)
{
struct private *p = malloc(sizeof(*p));
p->text = strdup(text);
p->max_len = max_len;
common->private = p;
common->destroy = &particle_destroy;
common->instantiate = &instantiate;
return common;
}
struct particle *
from_conf(const struct yml_node *node, struct particle *common)
{
const struct yml_node *text = yml_get_value(node, "text");
const struct yml_node *max = yml_get_value(node, "max");
return string_new(
common,
yml_value_as_string(text),
max != NULL ? yml_value_as_int(max) : 0);
}
bool
verify_conf(keychain_t *chain, const struct yml_node *node)
{
static const struct attr_info attrs[] = {
{"text", true, &conf_verify_string},
{"max", false, &conf_verify_int},
PARTICLE_COMMON_ATTRS,
};
return conf_verify_dict(chain, node, attrs);
}