New progressbar option: vertical=<boolean>

if 'true', draws the whole progressbar-block vertically
instead of horizontally.
This commit is contained in:
marco candrian 2008-03-02 21:53:18 +01:00 committed by Julien Danjou
parent f4447f0026
commit 04ff373a63
4 changed files with 185 additions and 69 deletions

View File

@ -211,6 +211,7 @@ cfg_opt_t widget_progressbar_opts[] =
CFG_INT((char *) "gap", 2, CFGF_NONE), CFG_INT((char *) "gap", 2, CFGF_NONE),
CFG_INT((char *) "padding", 0, CFGF_NONE), CFG_INT((char *) "padding", 0, CFGF_NONE),
CFG_FLOAT((char *) "height", 0.67, CFGF_NONE), CFG_FLOAT((char *) "height", 0.67, CFGF_NONE),
CFG_BOOL((char *) "vertical", cfg_false, CFGF_NONE),
CFG_AWESOME_END() CFG_AWESOME_END()
}; };
cfg_opt_t statusbar_opts[] = cfg_opt_t statusbar_opts[] =

View File

@ -213,45 +213,39 @@ draw_text(DrawCtx *ctx,
/** Setup color-source for cairo (gradient or mono) /** Setup color-source for cairo (gradient or mono)
* \param ctx Draw context * \param ctx Draw context
* \param x x-offset of pattern start * \param rect x,y to x+x_offset,y+y_offset
* \param y y-offset of widget * \param color color to use at start (x,y)
* \param width pattern width
* \param color color to use at start (x)
* \param pcolor_center color at 50% of width * \param pcolor_center color at 50% of width
* \param pcolor_end color at pattern start (x) + pattern width (width) * \param pcolor_end color at pattern end (x + x_offset, y + y_offset)
* \return pat pattern or NULL; needs to get cairo_pattern_destroy()'ed; * \return pat pattern or NULL; needs to get cairo_pattern_destroy()'ed;
*/ */
static cairo_pattern_t * static cairo_pattern_t *
draw_setup_cairo_color_source(DrawCtx *ctx, int x, int y, int width, draw_setup_cairo_color_source(DrawCtx *ctx, Area rect,
XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end) XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end)
{ {
cairo_pattern_t *pat = NULL; cairo_pattern_t *pat = NULL;
/* no need for a real pattern on the next two: */ /* no need for a real pattern: */
if(!pcolor_end && !pcolor_center) if(!pcolor_end && !pcolor_center)
cairo_set_source_rgb(ctx->cr, pcolor->red / 65535.0, pcolor->green / 65535.0, pcolor->blue / 65535.0); 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 else
{ {
pat = cairo_pattern_create_linear(x, y, x + width, y); pat = cairo_pattern_create_linear(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
/* use pcolor as pcolor_end (and vice versa) when one is not set */ /* pcolor is always set (so far in awesome) */
if(pcolor) cairo_pattern_add_color_stop_rgb(pat, 0, pcolor->red / 65535.0,
cairo_pattern_add_color_stop_rgb(pat, 0, pcolor->red / 65535.0,
pcolor->green / 65535.0, pcolor->blue / 65535.0); pcolor->green / 65535.0, pcolor->blue / 65535.0);
else
cairo_pattern_add_color_stop_rgb(pat, 0, pcolor_end->red / 65535.0, if(pcolor_center)
pcolor_end->green / 65535.0, pcolor_end->blue / 65535.0); cairo_pattern_add_color_stop_rgb(pat, 0.5, pcolor_center->red / 65535.0,
pcolor_center->green / 65535.0, pcolor_center->blue / 65535.0);
if(pcolor_end) if(pcolor_end)
cairo_pattern_add_color_stop_rgb(pat, 1, pcolor_end->red / 65535.0, cairo_pattern_add_color_stop_rgb(pat, 1, pcolor_end->red / 65535.0,
pcolor_end->green / 65535.0, pcolor_end->blue / 65535.0); pcolor_end->green / 65535.0, pcolor_end->blue / 65535.0);
else else
cairo_pattern_add_color_stop_rgb(pat, 1, pcolor->red / 65535.0, cairo_pattern_add_color_stop_rgb(pat, 1, pcolor->red / 65535.0,
pcolor->green / 65535.0, pcolor->blue / 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); cairo_set_source(ctx->cr, pat);
} }
return pat; return pat;
@ -284,23 +278,22 @@ draw_rectangle(DrawCtx *ctx, Area geometry, Bool filled, XColor color)
* \param ctx Draw context * \param ctx Draw context
* \param geometry geometry * \param geometry geometry
* \param filled filled rectangle? * \param filled filled rectangle?
* \param pattern_start_x pattern start x coord * \param pattern__x pattern start x coord
* \param pattern_width pattern width * \param pattern_width pattern width
* \param color color to use at start * \param color color to use at start
* \param pcolor_center color at 50% of width * \param pcolor_center color at 50% of width
* \param pcolor_end color at pattern_start + pattern_width * \param pcolor_end color at pattern_start + pattern_width
*/ */
void void
draw_rectangle_gradient(DrawCtx *ctx, Area geometry, Bool filled, int pattern_start_x, int pattern_width, draw_rectangle_gradient(DrawCtx *ctx, Area geometry, Bool filled,
XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end) Area pattern_rect, XColor *pcolor, XColor *pcolor_center, XColor *pcolor_end)
{ {
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 = draw_setup_cairo_color_source(ctx, pattern_start_x, geometry.y, pattern_width, pat = draw_setup_cairo_color_source(ctx, pattern_rect, pcolor, pcolor_center, pcolor_end);
pcolor, pcolor_center, pcolor_end);
if(filled) if(filled)
{ {
@ -347,7 +340,13 @@ draw_graph(DrawCtx *ctx, int x, int y, int w, int *from, int *to, int cur_index,
{ {
int i; int i;
cairo_pattern_t *pat; cairo_pattern_t *pat;
pat = draw_setup_cairo_color_source(ctx, x, y, w, pcolor, pcolor_center, pcolor_end); Area rect;
rect.x = x;
rect.y = y;
rect.width = w;
rect.height = 0;
pat = draw_setup_cairo_color_source(ctx, rect, pcolor, pcolor_center, pcolor_end);
i = -1; i = -1;
while(++i < w) while(++i < w)
@ -385,7 +384,13 @@ draw_graph_line(DrawCtx *ctx, int x, int y, int w, int *to, int cur_index,
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_pattern_t *pat; cairo_pattern_t *pat;
pat = draw_setup_cairo_color_source(ctx, x, y, w, pcolor, pcolor_center, pcolor_end); Area rect;
rect.x = x;
rect.y = y;
rect.width = w;
rect.height = 0;
pat = draw_setup_cairo_color_source(ctx, rect, pcolor, pcolor_center, 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. */

View File

@ -96,7 +96,7 @@ void draw_context_delete(DrawCtx *);
void draw_text(DrawCtx *, Area, Alignment, int, XftFont *, char *, int, XColor fg, XColor bg); void draw_text(DrawCtx *, Area, Alignment, int, XftFont *, char *, int, XColor fg, XColor bg);
void draw_rectangle(DrawCtx *, Area, Bool, XColor); void draw_rectangle(DrawCtx *, Area, Bool, XColor);
void draw_rectangle_gradient(DrawCtx *, Area, Bool, int, int, XColor *, XColor *, XColor *); void draw_rectangle_gradient(DrawCtx *, Area, Bool, Area, XColor *, XColor *, XColor *);
void draw_graph_setup(DrawCtx *); void draw_graph_setup(DrawCtx *);
void draw_graph(DrawCtx *, int, int, int, int *, int *, int, XColor *, XColor *, XColor *); void draw_graph(DrawCtx *, int, int, int, int *, int *, int, XColor *, XColor *, XColor *);

View File

@ -40,6 +40,8 @@ typedef struct
int gap; int gap;
/** reverse drawing */ /** reverse drawing */
Bool *reverse; Bool *reverse;
/** 90 Degree's turned */
Bool vertical;
/** Number of data_items (bars) */ /** Number of data_items (bars) */
int data_items; int data_items;
/** Height 0-1, where 1 is height of statusbar */ /** Height 0-1, where 1 is height of statusbar */
@ -60,16 +62,14 @@ static int
progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, progressbar_draw(Widget *widget, DrawCtx *ctx, int offset,
int used __attribute__ ((unused))) int used __attribute__ ((unused)))
{ {
int i, width, pwidth, margin_top, pb_height, left_offset; int i, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset = 0;
Area rectangle; Area rectangle, pattern_rect;
Data *d = widget->data; Data *d = widget->data;
if (!d->data_items) if (!d->data_items)
return 0; return 0;
width = d->width - 2 * d->padding;
if(!widget->user_supplied_x) if(!widget->user_supplied_x)
widget->area.x = widget_calculate_offset(widget->statusbar->width, widget->area.x = widget_calculate_offset(widget->statusbar->width,
d->width, d->width,
@ -79,51 +79,158 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset,
if(!widget->user_supplied_y) if(!widget->user_supplied_y)
widget->area.y = 0; widget->area.y = 0;
margin_top = (int) (widget->statusbar->height * (1 - d->height)) / 2 + 0.5 + widget->area.y; /* data for the first rectangle (data-bar) to draw */
pb_height = (int) ((widget->statusbar->height * d->height - (d->gap * (d->data_items - 1))) / d->data_items + 0.5); if(d->vertical)
left_offset = widget->area.x + d->padding;
for(i = 0; i < d->data_items; i++)
{ {
if(d->reverse[i]) pb_width = (int) ((d->width - d->padding - (d->gap * (d->data_items - 1))) / d->data_items + 0.5);
pwidth = (int)(((width - 2) * (100 - d->percent[i])) / 100); pb_height = (int) (widget->statusbar->height * d->height);
else pb_y = widget->area.y + (int)((widget->statusbar->height - pb_height) / 2 + 0.5);
pwidth = (int)(((width - 2) * d->percent[i]) / 100); }
else /* horizontal */
{
pb_width = d->width - d->padding;
pb_height = (int) ((widget->statusbar->height * d->height - (d->gap * (d->data_items - 1))) / d->data_items + 0.5);
pb_y = widget->area.y + (int)((widget->statusbar->height - widget->statusbar->height * d->height) / 2 + 0.5);
}
rectangle.x = left_offset; pb_x = widget->area.x + d->padding;
rectangle.y = margin_top;
rectangle.width = width;
rectangle.height = pb_height;
draw_rectangle(ctx, rectangle, False, d->bordercolor[i]); /* for a 'reversed' progressbar:
* 1. the full space gets the size of the formerly empty one
if(pwidth > 0) /* filled area */ * 2. the pattern must be mirrored
* 3. the formerly 'empty' side gets drawed with fg colors, the 'full' with bg-color
*
* Might could be put into a single function (removing same/similar code) - feel free
*/
if(d->vertical)
{
for(i = 0; i < d->data_items; i++)
{ {
rectangle.x = left_offset + 1; /* border rectangle */
rectangle.y = margin_top + 1; rectangle.x = pb_x + pb_offset;
rectangle.width = pwidth; rectangle.y = pb_y;
rectangle.height = pb_height - 2; rectangle.width = pb_width;
if(d->reverse[i]) rectangle.height = pb_height;
draw_rectangle(ctx, rectangle, True, d->bg[i]); draw_rectangle(ctx, rectangle, False, d->bordercolor[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 */ /* new value/progress in px + pattern setup */
if(!d->reverse[i])
{
pb_progress = (int)(((pb_height - 2) * d->percent[i]) / 100 + 0.5);
/* bottom to top */
pattern_rect.x = pb_x;
pattern_rect.y = pb_y + 1 + pb_height ;
pattern_rect.width = 0;
pattern_rect.height = -pb_height;
}
else
{
pb_progress = (int)(((pb_height - 2) * (100 - d->percent[i])) / 100 + 0.5);
/* top to bottom */
pattern_rect.x = pb_x + 1;
pattern_rect.y = pb_y + 1;
pattern_rect.width = 0;
pattern_rect.height = pb_height;
}
/* bottom part */
if(pb_progress > 0)
{
rectangle.x = pb_x + pb_offset + 1;
rectangle.y = pb_y + 1 + (pb_height - 2) - pb_progress;
rectangle.width = pb_width - 2;
rectangle.height = pb_progress;
/* fg color */
if(!d->reverse[i])
draw_rectangle_gradient(ctx, rectangle, True, pattern_rect,
&(d->fg[i]), d->pfg_center[i], d->pfg_end[i]);
else /*REV: bg */
draw_rectangle(ctx, rectangle, True, d->bg[i]);
}
/* top part */
if((pb_height - 2) - pb_progress > 0) /* not filled area */
{
rectangle.x = pb_x + 1 + pb_offset;
rectangle.y = pb_y + 1;
rectangle.width = pb_width - 2;
rectangle.height = pb_height - 2 - pb_progress;
/* bg color */
if(!d->reverse[i])
draw_rectangle(ctx, rectangle, True, d->bg[i]);
else /* REV: bg */
draw_rectangle_gradient(ctx, rectangle, True, pattern_rect,
&(d->fg[i]), d->pfg_center[i], d->pfg_end[i]);
}
pb_offset += pb_width + d->gap;
}
}
else /* a horizontal progressbar */
{
for(i = 0; i < d->data_items; i++)
{ {
rectangle.x = left_offset + 1 + pwidth; /* border rectangle */
rectangle.y = margin_top + 1; rectangle.x = pb_x;
rectangle.width = width - 2 - pwidth; rectangle.y = pb_y + pb_offset;
rectangle.height = pb_height - 2; rectangle.width = pb_width;
if(d->reverse[i]) rectangle.height = pb_height;
draw_rectangle_gradient(ctx, rectangle, True, left_offset + 1, width - 2, draw_rectangle(ctx, rectangle, False, d->bordercolor[i]);
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); /* new value/progress in px + pattern setup */
if(!d->reverse[i])
{
pb_progress = (int)(((pb_width - 2) * d->percent[i]) / 100 + 0.5);
/* left to right */
pattern_rect.x = pb_x + 1;
pattern_rect.y = pb_y + 1;
pattern_rect.width = pb_width;
pattern_rect.height = 0;
}
else
{
pb_progress = (int)(((pb_width - 2) * (100 - d->percent[i])) / 100 + 0.5);
/* REV: right to left */
pattern_rect.x = pb_x + 1 + pb_width;
pattern_rect.y = pb_y + 1;
pattern_rect.width = -pb_width;
pattern_rect.height = 0;
}
/* left part */
if(pb_progress > 0)
{
rectangle.x = pb_x + 1;
rectangle.y = pb_y + 1 + pb_offset;
rectangle.width = pb_progress;
rectangle.height = pb_height - 2;
/* fg color */
if(!d->reverse[i])
draw_rectangle_gradient(ctx, rectangle, True, pattern_rect,
&(d->fg[i]), d->pfg_center[i], d->pfg_end[i]);
else /* REV: bg */
draw_rectangle(ctx, rectangle, True, d->bg[i]);
}
/* right part */
if(pb_width - 2 - pb_progress > 0)
{
rectangle.x = pb_x + 1 + pb_progress;
rectangle.y = pb_y + 1 + pb_offset;
rectangle.width = pb_width - 2 - pb_progress;
rectangle.height = pb_height - 2;
/* bg color */
if(!d->reverse[i])
draw_rectangle(ctx, rectangle, True, d->bg[i]);
else /* REV: fg */
draw_rectangle_gradient(ctx, rectangle, True, pattern_rect,
&(d->fg[i]), d->pfg_center[i], d->pfg_end[i]);
}
pb_offset += pb_height + d->gap;
}
} }
widget->area.width = d->width; widget->area.width = d->width;
@ -319,6 +426,9 @@ progressbar_new(Statusbar *statusbar, cfg_t *config)
d->height = cfg_getfloat(config, "height"); d->height = cfg_getfloat(config, "height");
d->gap = cfg_getint(config, "gap"); d->gap = cfg_getint(config, "gap");
d->padding = cfg_getint(config, "padding");
if(!(d->vertical = cfg_getbool(config, "vertical")))
d->vertical = False;
w->alignment = draw_get_align(cfg_getstr(config, "align")); w->alignment = draw_get_align(cfg_getstr(config, "align"));