From 6216d25bc6dac3c6ace92a419e2760d909388acf Mon Sep 17 00:00:00 2001 From: marco candrian Date: Sun, 2 Mar 2008 13:13:12 +0100 Subject: [PATCH] new progressbar option for reversing the drawing inside a data section, with reverse= it's possible to reverse the drawing i.e instead of left to right, from right to left. etc. --- common/configopts.c | 1 + common/draw.c | 76 ++++++++++++++++++++++++------------------- common/draw.h | 6 ++-- widgets/graph.c | 6 ++-- widgets/progressbar.c | 26 ++++++++++++--- 5 files changed, 70 insertions(+), 45 deletions(-) diff --git a/common/configopts.c b/common/configopts.c index c894a7b52..baba8b8d9 100644 --- a/common/configopts.c +++ b/common/configopts.c @@ -197,6 +197,7 @@ cfg_opt_t widget_progressbar_data_opts[] = CFG_STR((char *) "fg_end", (char *) NULL, CFGF_NONE), CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), CFG_STR((char *) "bordercolor", (char *) NULL, CFGF_NONE), + CFG_BOOL((char *) "reverse", cfg_false, CFGF_NONE), CFG_AWESOME_END() }; cfg_opt_t widget_progressbar_opts[] = diff --git a/common/draw.c b/common/draw.c index c5e749c71..d3b539c65 100644 --- a/common/draw.c +++ b/common/draw.c @@ -213,40 +213,47 @@ draw_text(DrawCtx *ctx, /** Setup color-source for cairo (gradient or mono) * \param ctx Draw context - * \param x x-offset of widget + * \param x x-offset of pattern start * \param y y-offset of widget - * \param width width in pixels - * \param color color to use from 0% + * \param width pattern width + * \param color color to use at start (x) * \param pcolor_center color at 50% of width - * \param pcolor_end color at 100% of width + * \param pcolor_end color at pattern start (x) + pattern width (width) * \return pat pattern or NULL; needs to get cairo_pattern_destroy()'ed; */ static cairo_pattern_t * draw_setup_cairo_color_source(DrawCtx *ctx, int x, int y, int width, - XColor color, XColor *pcolor_center, XColor *pcolor_end) + XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end) { cairo_pattern_t *pat = NULL; - if(pcolor_center || pcolor_end) /* draw a gradient */ + /* no need for a real pattern on the next two: */ + if(!pcolor_end && !pcolor_center) + cairo_set_source_rgb(ctx->cr, pcolor->red / 65535.0, pcolor->green / 65535.0, pcolor->blue / 65535.0); + else if(!pcolor && !pcolor_center) + cairo_set_source_rgb(ctx->cr, pcolor_end->red / 65535.0, pcolor_end->green / 65535.0, pcolor_end->blue / 65535.0); + else { 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_center) - cairo_pattern_add_color_stop_rgb(pat, 0.5, pcolor_center->red / 65535.0, - pcolor_center->green / 65535.0, pcolor_center->blue / 65535.0); + /* use pcolor as pcolor_end (and vice versa) when one is not set */ + if(pcolor) + cairo_pattern_add_color_stop_rgb(pat, 0, pcolor->red / 65535.0, + pcolor->green / 65535.0, pcolor->blue / 65535.0); + else + cairo_pattern_add_color_stop_rgb(pat, 0, pcolor_end->red / 65535.0, + pcolor_end->green / 65535.0, pcolor_end->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_pattern_add_color_stop_rgb(pat, 1, pcolor->red / 65535.0, + pcolor->green / 65535.0, pcolor->blue / 65535.0); + if(pcolor_center) + cairo_pattern_add_color_stop_rgb(pat, 0.5, pcolor_center->red / 65535.0, + pcolor_center->green / 65535.0, pcolor_center->blue / 65535.0); cairo_set_source(ctx->cr, pat); } - else - cairo_set_source_rgb(ctx->cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0); - return pat; } @@ -276,23 +283,24 @@ draw_rectangle(DrawCtx *ctx, Area geometry, Bool filled, XColor color) /** Draw rectangle with gradient colors * \param ctx Draw context * \param geometry geometry - * \param fullwidth width of full bar in pixels * \param filled filled rectangle? - * \param color color to use from 0% - * \param pcolor_center color at 50% - * \param pcolor_end color at 100% + * \param pattern_start_x pattern start x coord + * \param pattern_width pattern width + * \param color color to use at start + * \param pcolor_center color at 50% of width + * \param pcolor_end color at pattern_start + pattern_width */ void -draw_rectangle_gradient(DrawCtx *ctx, Area geometry, int fullwidth, Bool filled, - XColor color, XColor *pcolor_center, XColor *pcolor_end) +draw_rectangle_gradient(DrawCtx *ctx, Area geometry, Bool filled, int pattern_start_x, int pattern_width, + XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end) { cairo_pattern_t *pat; cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width(ctx->cr, 1.0); - pat = draw_setup_cairo_color_source(ctx, geometry.x, geometry.y, fullwidth, - color, pcolor_center, pcolor_end); + pat = draw_setup_cairo_color_source(ctx, pattern_start_x, geometry.y, pattern_width, + pcolor, pcolor_center, pcolor_end); if(filled) { @@ -329,17 +337,17 @@ draw_graph_setup(DrawCtx *ctx) * \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_center color at 50% - * \param pcolor_end color at 100% + * \param pcolor color at the left + * \param pcolor_center color in the center + * \param pcolor_end color at the right */ void draw_graph(DrawCtx *ctx, int x, int y, int w, int *from, int *to, int cur_index, - XColor color, XColor *pcolor_center, XColor *pcolor_end) + XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end) { int i; cairo_pattern_t *pat; - pat = draw_setup_cairo_color_source(ctx, x, y, w, color, pcolor_center, pcolor_end); + pat = draw_setup_cairo_color_source(ctx, x, y, w, pcolor, pcolor_center, pcolor_end); i = -1; while(++i < w) @@ -365,19 +373,19 @@ draw_graph(DrawCtx *ctx, int x, int y, int w, int *from, int *to, int cur_index, * \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_center color at 50% - * \param pcolor_end color at 100% + * \param pcolor color at the left + * \param pcolor_center color in the center + * \param pcolor_end color at the right */ void draw_graph_line(DrawCtx *ctx, int x, int y, int w, int *to, int cur_index, - XColor color, XColor *pcolor_center, XColor *pcolor_end) + XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end) { int i; int flag = 0; /* used to prevent drawing a line from 0 to 0 values */ cairo_pattern_t *pat; - pat = draw_setup_cairo_color_source(ctx, x, y, w, color, pcolor_center, pcolor_end); + pat = draw_setup_cairo_color_source(ctx, x, y, w, pcolor, pcolor_center, pcolor_end); /* 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. */ diff --git a/common/draw.h b/common/draw.h index 6d27b1455..4fa152e9c 100644 --- a/common/draw.h +++ b/common/draw.h @@ -96,11 +96,11 @@ void draw_context_delete(DrawCtx *); void draw_text(DrawCtx *, Area, Alignment, int, XftFont *, char *, int, XColor fg, XColor bg); void draw_rectangle(DrawCtx *, Area, Bool, XColor); -void draw_rectangle_gradient(DrawCtx *, Area, int, Bool, XColor, XColor *, XColor *); +void draw_rectangle_gradient(DrawCtx *, Area, Bool, int, int, XColor *, XColor *, XColor *); void draw_graph_setup(DrawCtx *); -void draw_graph(DrawCtx *, int, int, int, int *, int *, int, XColor, XColor *, XColor *); -void draw_graph_line(DrawCtx *, int, int, int, int *, int, XColor, XColor *, 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 *, XColor *, XColor *); void draw_circle(DrawCtx *, int, int, int, Bool, XColor); void draw_image(DrawCtx *, int, int, int, const char *); void draw_image_from_argb_data(DrawCtx *, int, int, int, int, int, unsigned char *); diff --git a/widgets/graph.c b/widgets/graph.c index f7d74f0f7..f3858367c 100644 --- a/widgets/graph.c +++ b/widgets/graph.c @@ -135,7 +135,7 @@ graph_draw(Widget *widget, DrawCtx *ctx, int offset, draw_graph(ctx, left_offset + 2, margin_top + d->box_height + 1, d->size, d->draw_from, d->draw_to, *(d->filltop_index[z]), - d->filltop_color[z], d->filltop_pcolor_center[z], d->filltop_pcolor_end[z]); + &(d->filltop_color[z]), d->filltop_pcolor_center[z], d->filltop_pcolor_end[z]); } /* draw style = bottom */ @@ -157,7 +157,7 @@ graph_draw(Widget *widget, DrawCtx *ctx, int offset, draw_graph(ctx, left_offset + 2, margin_top + d->box_height + 1, d->size, d->draw_from, d->fillbottom[z], *(d->fillbottom_index[z]), - d->fillbottom_color[z], d->fillbottom_pcolor_center[z], d->fillbottom_pcolor_end[z]); + &(d->fillbottom_color[z]), d->fillbottom_pcolor_center[z], d->fillbottom_pcolor_end[z]); } /* draw style = line */ @@ -166,7 +166,7 @@ graph_draw(Widget *widget, DrawCtx *ctx, int offset, draw_graph_line(ctx, left_offset + 2, margin_top + d->box_height + 1, d->size, d->drawline[z], *(d->drawline_index[z]), - d->drawline_color[z], d->drawline_pcolor_center[z], d->drawline_pcolor_end[z]); + &(d->drawline_color[z]), d->drawline_pcolor_center[z], d->drawline_pcolor_end[z]); } widget->area.width = d->width; diff --git a/widgets/progressbar.c b/widgets/progressbar.c index 67f2be9e2..74c4f4346 100644 --- a/widgets/progressbar.c +++ b/widgets/progressbar.c @@ -38,6 +38,8 @@ typedef struct int padding; /** Pixel between data_items (bars) */ int gap; + /** reverse drawing */ + Bool *reverse; /** Number of data_items (bars) */ int data_items; /** Height 0-1, where 1 is height of statusbar */ @@ -83,7 +85,10 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, for(i = 0; i < d->data_items; i++) { - pwidth = (int) d->percent[i] ? ((width - 2) * d->percent[i]) / 100 : 0; + if(d->reverse[i]) + pwidth = (int)(((width - 2) * (100 - d->percent[i])) / 100); + else + pwidth = (int)(((width - 2) * d->percent[i]) / 100); rectangle.x = left_offset; rectangle.y = margin_top; @@ -92,14 +97,17 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, draw_rectangle(ctx, rectangle, False, d->bordercolor[i]); - if(pwidth > 0) + if(pwidth > 0) /* filled area */ { rectangle.x = left_offset + 1; rectangle.y = margin_top + 1; rectangle.width = pwidth; rectangle.height = pb_height - 2; - draw_rectangle_gradient(ctx, rectangle, width - 2, True, d->fg[i], - d->pfg_center[i], d->pfg_end[i]); + if(d->reverse[i]) + draw_rectangle(ctx, rectangle, True, d->bg[i]); + else + draw_rectangle_gradient(ctx, rectangle, True, left_offset + 1, width - 2, + &(d->fg[i]), d->pfg_center[i], d->pfg_end[i]); } if(width - 2 - pwidth > 0) /* not filled area */ @@ -108,7 +116,11 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, rectangle.y = margin_top + 1; rectangle.width = width - 2 - pwidth; rectangle.height = pb_height - 2; - draw_rectangle(ctx, rectangle, True, d->bg[i]); + if(d->reverse[i]) + draw_rectangle_gradient(ctx, rectangle, True, left_offset + 1, width - 2, + d->pfg_end[i], d->pfg_center[i], &(d->fg[i])); + else + draw_rectangle(ctx, rectangle, True, d->bg[i]); } margin_top += (pb_height + d->gap); @@ -322,6 +334,7 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) d->bg = p_new(XColor, d->data_items); d->bordercolor = p_new(XColor, d->data_items); d->percent = p_new(int, d->data_items); + d->reverse = p_new(Bool, d->data_items); d->data_title = p_new(char *, d->data_items); for(i = 0; i < d->data_items; i++) @@ -330,6 +343,9 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) d->data_title[i] = a_strdup(cfg_title(cfg)); + if(!(d->reverse[i] = cfg_getbool(cfg, "reverse"))) + d->reverse[i] = False; + if((color = cfg_getstr(cfg, "fg"))) draw_color_new(globalconf.display, phys_screen, color, &d->fg[i]); else