Adds fg_middle + fg_end color option for the graph widget

Draws a color-gradient beginning from fg and
if either fg_middle or fg_end is set, through them.

example config:

    graph gr_cpu
    {
      data { scale = false max = 100  style = bottom
             fg = "#cc6666" fg_half = "#cc6666" fg_full = "#998888"}
      ...
      ...
    }

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
marco candrian 2008-02-05 15:33:42 +01:00 committed by Julien Danjou
parent b7e379c2d0
commit ff753f1f14
4 changed files with 156 additions and 62 deletions

View File

@ -134,6 +134,8 @@ cfg_opt_t widget_graph_data_opts[] =
CFG_FLOAT((char *) "max", 100.0f, CFGF_NONE), CFG_FLOAT((char *) "max", 100.0f, CFGF_NONE),
CFG_BOOL((char *) "scale", cfg_false, CFGF_NONE), CFG_BOOL((char *) "scale", cfg_false, CFGF_NONE),
CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE),
CFG_STR((char *) "fg_middle", (char *) NULL, CFGF_NONE),
CFG_STR((char *) "fg_end", (char *) NULL, CFGF_NONE),
CFG_STR((char *) "style", (char *) "bottom", CFGF_NONE), CFG_STR((char *) "style", (char *) "bottom", CFGF_NONE),
CFG_END() CFG_END()
}; };

View File

@ -182,6 +182,47 @@ draw_text(DrawCtx *ctx,
cairo_font_face_destroy(font_face); cairo_font_face_destroy(font_face);
} }
/** Setup color-source for cairo (gradient or mono)
* \param ctx Draw context
* \param x x-offset of widget
* \param y y-offset of widget
* \param width width in pixels
* \param color color to use from 0%
* \param pcolor_middle color at 50% of width
* \param pcolor_end color at 100% of width
* \return pat pattern or NULL; needs to get cairo_pattern_destroy()'ed;
*/
cairo_pattern_t *
setup_cairo_color_source(DrawCtx *ctx, int x, int y, int width,
XColor color, XColor *pcolor_middle, XColor *pcolor_end)
{
cairo_pattern_t *pat;
if(pcolor_middle || pcolor_end) /* draw a gradient */
{
pat = cairo_pattern_create_linear(x, y, x + width, y);
cairo_pattern_add_color_stop_rgb(pat, 0, color.red / 65535.0,
color.green / 65535.0, color.blue / 65535.0);
if(pcolor_middle)
cairo_pattern_add_color_stop_rgb(pat, 0.5, pcolor_middle->red / 65535.0,
pcolor_middle->green / 65535.0, pcolor_middle->blue / 65535.0);
if(pcolor_end)
cairo_pattern_add_color_stop_rgb(pat, 1, pcolor_end->red / 65535.0,
pcolor_end->green / 65535.0, pcolor_end->blue / 65535.0);
else
cairo_pattern_add_color_stop_rgb(pat, 1, color.red / 65535.0,
color.green / 65535.0, color.blue / 65535.0);
cairo_set_source(ctx->cr, pat);
return pat;
}
else /* no gradient */
{
cairo_set_source_rgb(ctx->cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0);
return NULL;
}
}
/** Draw rectangle /** Draw rectangle
* \param ctx Draw context * \param ctx Draw context
* \param geometry geometry * \param geometry geometry
@ -205,39 +246,26 @@ draw_rectangle(DrawCtx *ctx, Area geometry, Bool filled, XColor color)
cairo_stroke(ctx->cr); cairo_stroke(ctx->cr);
} }
} }
/** Draw rectangle with gradient colors /** Draw rectangle with gradient colors
* \param ctx Draw context * \param ctx Draw context
* \param geometry geometry * \param geometry geometry
* \param fullwidth width of full bar in pixels * \param fullwidth width of full bar in pixels
* \param filled filled rectangle? * \param filled filled rectangle?
* \param color color to use from 0% * \param color color to use from 0%
* \param color_half color at 50% * \param pcolor_half color at 50%
* \param color_full color at 100% * \param pcolor_full color at 100%
*/ */
void void
draw_rectangle_gradient(DrawCtx *ctx, Area geometry, int fullwidth, Bool filled, draw_rectangle_gradient(DrawCtx *ctx, Area geometry, int fullwidth, Bool filled,
XColor color, XColor * color_half, XColor * color_full) XColor color, XColor *pcolor_half, XColor *pcolor_full)
{ {
cairo_pattern_t *pat; cairo_pattern_t *pat;
cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE); cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE);
cairo_set_line_width(ctx->cr, 1.0); cairo_set_line_width(ctx->cr, 1.0);
pat = cairo_pattern_create_linear(geometry.x, geometry.y, geometry.x + fullwidth, geometry.y); pat = setup_cairo_color_source(ctx, geometry.x, geometry.y, fullwidth,
cairo_pattern_add_color_stop_rgb(pat, 0, color.red / 65535.0, color, pcolor_half, pcolor_full);
color.green / 65535.0, color.blue / 65535.0);
if(color_half)
cairo_pattern_add_color_stop_rgb(pat, 0.5, color_half->red / 65535.0,
color_half->green / 65535.0, color_half->blue / 65535.0);
if(color_full)
cairo_pattern_add_color_stop_rgb(pat, 1, color_full->red / 65535.0,
color_full->green / 65535.0, color_full->blue / 65535.0);
else
cairo_pattern_add_color_stop_rgb(pat, 1, color.red / 65535.0,
color.green / 65535.0, color.blue / 65535.0);
cairo_set_source(ctx->cr, pat);
if(filled) if(filled)
{ {
@ -250,10 +278,13 @@ draw_rectangle_gradient(DrawCtx *ctx, Area geometry, int fullwidth, Bool filled,
cairo_stroke(ctx->cr); cairo_stroke(ctx->cr);
} }
cairo_pattern_destroy(pat); if(pat)
cairo_pattern_destroy(pat);
} }
/* draw_graph functions */ /** Setup some cairo-things for drawing a graph
* \param ctx Draw context
*/
void void
draw_graph_setup(DrawCtx *ctx) draw_graph_setup(DrawCtx *ctx)
{ {
@ -262,16 +293,25 @@ draw_graph_setup(DrawCtx *ctx)
/* without it, it can draw over the path on sharp angles (...too long lines) */ /* without it, it can draw over the path on sharp angles (...too long lines) */
cairo_set_line_join (ctx->cr, CAIRO_LINE_JOIN_ROUND); cairo_set_line_join (ctx->cr, CAIRO_LINE_JOIN_ROUND);
} }
/** Draw a graph
/* draws a graph; it takes the line-lengths from *from and *to. It cycles * \param ctx Draw context
* backwards through those arrays (what have the length of w), beginning at * \param x x-offset of widget
* position cur_index, until cur_index is reached again (wrapped around). */ * \param y y-offset of widget
* \param w width in pixels
* \param from array of starting-point offsets to draw a graph-lines
* \param to array of end-point offsets to draw a graph-lines
* \param cur_index current position in data-array (cycles around)
* \param color color to use from 0%
* \param pcolor_middle color at 50%
* \param pcolor_end color at 100%
*/
void void
draw_graph(DrawCtx *ctx, int x, int y, int w, int *from, int *to, int cur_index, XColor color) draw_graph(DrawCtx *ctx, int x, int y, int w, int *from, int *to, int cur_index,
XColor color, XColor *pcolor_middle, XColor *pcolor_end)
{ {
int i; int i;
cairo_pattern_t *pat;
cairo_set_source_rgb(ctx->cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0); pat = setup_cairo_color_source(ctx, x, y, w, color, pcolor_middle, pcolor_end);
i = -1; i = -1;
while(++i < w) while(++i < w)
@ -285,13 +325,30 @@ draw_graph(DrawCtx *ctx, int x, int y, int w, int *from, int *to, int cur_index,
} }
cairo_stroke(ctx->cr); cairo_stroke(ctx->cr);
if(pat)
cairo_pattern_destroy(pat);
} }
/** Draw a line into a graph-widget
* \param ctx Draw context
* \param x x-offset of widget
* \param y y-offset of widget
* \param w width in pixels
* \param to array of offsets to draw the line through...
* \param cur_index current position in data-array (cycles around)
* \param color color to use from 0%
* \param pcolor_middle color at 50%
* \param pcolor_end color at 100%
*/
void void
draw_graph_line(DrawCtx *ctx, int x, int y, int w, int *to, int cur_index, XColor color) draw_graph_line(DrawCtx *ctx, int x, int y, int w, int *to, int cur_index,
XColor color, XColor *pcolor_middle, XColor *pcolor_end)
{ {
int i; int i;
int flag = 0; /* used to prevent drawing a line from 0 to 0 values */ int flag = 0; /* used to prevent drawing a line from 0 to 0 values */
cairo_set_source_rgb(ctx->cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0); cairo_pattern_t *pat;
pat = setup_cairo_color_source(ctx, x, y, w, color, pcolor_middle, pcolor_end);
/* x-1 (on the border), paints *from* the last point (... not included itself) */ /* x-1 (on the border), paints *from* the last point (... not included itself) */
/* makes sense when you assume there is already some line drawn to it. */ /* makes sense when you assume there is already some line drawn to it. */
@ -320,6 +377,9 @@ draw_graph_line(DrawCtx *ctx, int x, int y, int w, int *to, int cur_index, XColo
x++; x++;
} }
cairo_stroke(ctx->cr); cairo_stroke(ctx->cr);
if(pat)
cairo_pattern_destroy(pat);
} }
void void

View File

@ -97,10 +97,10 @@ void draw_text(DrawCtx *, Area, Alignment, int, XftFont *, char *, XColor fg, XC
void draw_rectangle(DrawCtx *, Area, Bool, XColor); void draw_rectangle(DrawCtx *, Area, Bool, XColor);
void draw_rectangle_gradient(DrawCtx *, Area, int, Bool, XColor, XColor *, XColor *); void draw_rectangle_gradient(DrawCtx *, Area, int, Bool, XColor, XColor *, XColor *);
cairo_pattern_t * setup_cairo_color_source(DrawCtx *, int, int, int, XColor, XColor *, XColor *);
void draw_graph_setup(DrawCtx *); void draw_graph_setup(DrawCtx *);
void draw_graph(DrawCtx *, int, int, int, int *, int *, int, XColor); void draw_graph(DrawCtx *, int, int, int, int *, int *, int, XColor, XColor *, XColor *);
void draw_graph_line(DrawCtx *, int, int, int, int *, int, XColor); void draw_graph_line(DrawCtx *, int, int, int, int *, int, XColor, XColor *, XColor *);
void draw_circle(DrawCtx *, int, int, int, Bool, XColor); void draw_circle(DrawCtx *, int, int, int, Bool, XColor);
void draw_image(DrawCtx *, int, int, int, const char *); void draw_image(DrawCtx *, int, int, int, const char *);
void draw_image_from_argb_data(DrawCtx *, int, int, int, int, int, unsigned char *); void draw_image_from_argb_data(DrawCtx *, int, int, int, int, int, unsigned char *);

View File

@ -30,38 +30,44 @@ extern AwesomeConf globalconf;
typedef struct typedef struct
{ {
/* general layout */ /* general layout */
float *max; /* Represents a full graph */ float *max; /** Represents a full graph */
int width; /* Width of the widget */ int width; /** Width of the widget */
float height; /* Height of graph (0-1, where 1 is height of statusbar) */ float height; /** Height of graph (0-1; 1 = height of statusbar) */
int box_height; /* Height of the innerbox in pixels */ int box_height; /** Height of the innerbox in pixels */
int padding_left; /* Left padding */ int padding_left; /** Left padding */
int size; /* Size of lines-array (also innerbox-lenght) */ int size; /** Size of lines-array (also innerbox-lenght) */
XColor bg; /* Background color */ XColor bg; /** Background color */
XColor bordercolor; /* Border color */ XColor bordercolor; /** Border color */
/* markers... */ /* markers... */
int index; /* Index of current (new) value */ int index; /** Index of current (new) value */
int *max_index; /* Index of the actual maximum value */ int *max_index; /** Index of the actual maximum value */
float *current_max; /* Pointer to current maximum value itself */ float *current_max; /** Pointer to current maximum value itself */
/* all data is stored here */ /* all data is stored here */
int data_items; /* Number of data-input items */ int data_items; /** Number of data-input items */
int **lines; /* Keeps the calculated values (line-length); */ int **lines; /** Keeps the calculated values (line-length); */
float **values; /* Actual values */ float **values; /** Actual values */
/* additional data + a pointer to **lines accordingly */ /* additional data + a pointer to **lines accordingly */
int **fillbottom; /* datatypes holder (same as some **lines pointer) */ int **fillbottom; /** Datatypes holder (data equal to **lines) */
int fillbottom_total; /* total of them */ int fillbottom_total; /** Total of them */
XColor *fillbottom_color; /* color of them */ XColor *fillbottom_color; /** Color of them */
int **filltop; /* datatypes holder */ XColor **fillbottom_pcolor_middle; /** Color at middle of graph */
int filltop_total; /* total of them */ XColor **fillbottom_pcolor_end; /** Color at end of graph */
XColor *filltop_color; /* color of them */ int **filltop; /** Datatypes holder */
int **drawline; /* datatypes holder */ int filltop_total; /** Total of them */
int drawline_total; /* total of them */ XColor *filltop_color; /** Color of them */
XColor *drawline_color; /* color of them */ XColor **filltop_pcolor_middle; /** Color at middle of graph */
XColor **filltop_pcolor_end; /** Color at end of graph */
int **drawline; /** Datatypes holder */
int drawline_total; /** Total of them */
XColor *drawline_color; /** Color of them */
XColor **drawline_pcolor_middle; /** Color at middle of graph */
XColor **drawline_pcolor_end; /** Color at end of graph */
int *draw_from; /* Preparation/tmp array for draw_graph(); */ int *draw_from; /** Preparation/tmp array for draw_graph(); */
int *draw_to; /* Preparation/tmp array for draw_graph(); */ int *draw_to; /** Preparation/tmp array for draw_graph(); */
} Data; } Data;
@ -124,7 +130,7 @@ graph_draw(Widget *widget, DrawCtx *ctx, int offset,
draw_graph(ctx, draw_graph(ctx,
left_offset + 2, margin_top + d->box_height + 1, left_offset + 2, margin_top + d->box_height + 1,
d->size, d->draw_from, d->draw_to, d->index, d->size, d->draw_from, d->draw_to, d->index,
d->filltop_color[z]); d->filltop_color[z], d->filltop_pcolor_middle[z], d->filltop_pcolor_end[z]);
} }
/* draw style = bottom */ /* draw style = bottom */
@ -146,7 +152,7 @@ graph_draw(Widget *widget, DrawCtx *ctx, int offset,
draw_graph(ctx, draw_graph(ctx,
left_offset + 2, margin_top + d->box_height + 1, left_offset + 2, margin_top + d->box_height + 1,
d->size, d->draw_from, d->fillbottom[z], d->index, d->size, d->draw_from, d->fillbottom[z], d->index,
d->fillbottom_color[z]); d->fillbottom_color[z], d->fillbottom_pcolor_middle[z], d->fillbottom_pcolor_end[z]);
} }
/* draw style = line */ /* draw style = line */
@ -155,7 +161,7 @@ graph_draw(Widget *widget, DrawCtx *ctx, int offset,
draw_graph_line(ctx, draw_graph_line(ctx,
left_offset + 2, margin_top + d->box_height + 1, left_offset + 2, margin_top + d->box_height + 1,
d->size, d->drawline[z], d->index, d->size, d->drawline[z], d->index,
d->drawline_color[z]); d->drawline_color[z], d->drawline_pcolor_middle[z], d->drawline_pcolor_end[z]);
} }
widget->area.width = d->width; widget->area.width = d->width;
@ -236,6 +242,8 @@ graph_new(Statusbar *statusbar, cfg_t *config)
int i; int i;
char *type; char *type;
XColor tmp_color; XColor tmp_color;
XColor *ptmp_color_middle;
XColor *ptmp_color_end;
w = p_new(Widget, 1); w = p_new(Widget, 1);
widget_common_new(w, statusbar, config); widget_common_new(w, statusbar, config);
@ -272,18 +280,24 @@ graph_new(Statusbar *statusbar, cfg_t *config)
d->lines = p_new(int *, d->data_items); d->lines = p_new(int *, d->data_items);
d->filltop_color = p_new(XColor, d->data_items); d->filltop_color = p_new(XColor, d->data_items);
d->filltop_pcolor_middle = p_new(XColor *, d->data_items);
d->filltop_pcolor_end = p_new(XColor *, d->data_items);
d->fillbottom_color = p_new(XColor, d->data_items); d->fillbottom_color = p_new(XColor, d->data_items);
d->fillbottom_pcolor_middle = p_new(XColor *, d->data_items);
d->fillbottom_pcolor_end = p_new(XColor *, d->data_items);
d->drawline_color = p_new(XColor, d->data_items); d->drawline_color = p_new(XColor, d->data_items);
d->drawline_pcolor_middle = p_new(XColor *, d->data_items);
d->drawline_pcolor_end = p_new(XColor *, d->data_items);
d->max_index = p_new(int, d->data_items); d->max_index = p_new(int, d->data_items);
d->current_max = p_new(float, d->data_items); d->current_max = p_new(float, d->data_items);
d->max = p_new(float, d->data_items); d->max = p_new(float, d->data_items);
tmp_color = globalconf.screens[statusbar->screen].colors_normal[ColFG];
for(i = 0; i < d->data_items; i++) for(i = 0; i < d->data_items; i++)
{ {
ptmp_color_middle = ptmp_color_end = NULL;
cfg = cfg_getnsec(config, "data", i); cfg = cfg_getnsec(config, "data", i);
if((color = cfg_getstr(cfg, "fg"))) if((color = cfg_getstr(cfg, "fg")))
@ -291,6 +305,18 @@ graph_new(Statusbar *statusbar, cfg_t *config)
else else
tmp_color = globalconf.screens[statusbar->screen].colors_normal[ColFG]; tmp_color = globalconf.screens[statusbar->screen].colors_normal[ColFG];
if((color = cfg_getstr(cfg, "fg_middle")))
{
ptmp_color_middle = p_new(XColor, 1);
*ptmp_color_middle = draw_color_new(globalconf.display, phys_screen, color);
}
if((color = cfg_getstr(cfg, "fg_end")))
{
ptmp_color_end = p_new(XColor, 1);
*ptmp_color_end = draw_color_new(globalconf.display, phys_screen, color);
}
if (cfg_getbool(cfg, "scale")) if (cfg_getbool(cfg, "scale"))
d->values[i] = p_new(float, d->size); /* not null -> scale = true */ d->values[i] = p_new(float, d->size); /* not null -> scale = true */
@ -313,18 +339,24 @@ graph_new(Statusbar *statusbar, cfg_t *config)
{ {
d->fillbottom[d->fillbottom_total] = d->lines[i]; d->fillbottom[d->fillbottom_total] = d->lines[i];
d->fillbottom_color[d->fillbottom_total] = tmp_color; d->fillbottom_color[d->fillbottom_total] = tmp_color;
d->fillbottom_pcolor_middle[d->fillbottom_total] = ptmp_color_middle;
d->fillbottom_pcolor_end[d->fillbottom_total] = ptmp_color_end;
d->fillbottom_total++; d->fillbottom_total++;
} }
else if (!a_strncmp(type, "top", sizeof("top"))) else if (!a_strncmp(type, "top", sizeof("top")))
{ {
d->filltop[d->filltop_total] = d->lines[i]; d->filltop[d->filltop_total] = d->lines[i];
d->filltop_color[d->filltop_total] = tmp_color; d->filltop_color[d->filltop_total] = tmp_color;
d->filltop_pcolor_middle[d->fillbottom_total] = ptmp_color_middle;
d->filltop_pcolor_end[d->fillbottom_total] = ptmp_color_end;
d->filltop_total++; d->filltop_total++;
} }
else if (!a_strncmp(type, "line", sizeof("line"))) else if (!a_strncmp(type, "line", sizeof("line")))
{ {
d->drawline[d->drawline_total] = d->lines[i]; d->drawline[d->drawline_total] = d->lines[i];
d->drawline_color[d->drawline_total] = tmp_color; d->drawline_color[d->drawline_total] = tmp_color;
d->drawline_pcolor_middle[d->fillbottom_total] = ptmp_color_middle;
d->drawline_pcolor_end[d->fillbottom_total] = ptmp_color_end;
d->drawline_total++; d->drawline_total++;
} }
} }