From 89f4e22255a0c9a4ac0845f56508e551fecb386d Mon Sep 17 00:00:00 2001 From: marco candrian Date: Wed, 26 Mar 2008 03:18:21 +0100 Subject: [PATCH] [widgets] new progressbar options if a ticks_count is defined (!= 0), round the value to them ('ticks') and draw finally some gaps. Also an important issue: since the bar needs to be 'homogenous', they may won't match a given height. Some value tweaking will be necessary then. An alternative would be a not homogenous bar, what is worse I think. The values, when there are 'ticks', get rounded up somebit. So they get turned on, when half of them is reached - or so. new options (see awesomerc.5.txt for a more detailed description): border_width border_padding fg_off ticks_count ticks_gap Signed-off-by: Julien Danjou --- Makefile.am | 1 + awesomerc.5.txt | 20 +- common/configopts.c | 5 + common/draw.c | 7 +- widgets/common.c | 81 ++++++++ widgets/common.h | 31 +++ widgets/progressbar.c | 452 ++++++++++++++++++++++++------------------ 7 files changed, 398 insertions(+), 199 deletions(-) create mode 100644 widgets/common.c create mode 100644 widgets/common.h diff --git a/Makefile.am b/Makefile.am index 0c462acb..c6135956 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,6 +34,7 @@ WIDGETS += widgets/focusicon.c WIDGETS += widgets/progressbar.c WIDGETS += widgets/tasklist.c WIDGETS += widgets/graph.c +WIDGETS += widgets/common.c doc_DATA += README diff --git a/awesomerc.5.txt b/awesomerc.5.txt index 9002c1b1..c1f0f229 100644 --- a/awesomerc.5.txt +++ b/awesomerc.5.txt @@ -448,7 +448,7 @@ This widget shows one or more progress-bars. *data*:: Draws a bar for each data section; - Options: reverse, fg, fg_center, fg_end, bg, bordercolor. + Options: reverse, fg, fg_center, fg_end, fg_off, bg, bordercolor. *reverse*:: Reverse/mirror the bar. *fg*:: @@ -457,8 +457,10 @@ This widget shows one or more progress-bars. Foreground color in the center of the bar (as gradient). *fg_end*:: Foreground color at the end of a bar (as gradient). +*fg_end*:: + Foreground color of not filled bar. *bg*:: - Background color. + Background color (between bar and border). *bordercolor*:: Border color. *mouse*:: @@ -471,6 +473,14 @@ This widget shows one or more progress-bars. Empty space on both sides. *vertical*:: Draw the bar(s) vertically/standing up. +*ticks_count*:: + Number of 'ticks' to draw. +*ticks_gap*:: + Distance between the ticks. +*border_width*:: + Border width in pixels. +*border_padding*:: + Padding between border and ticks/bar. *x*:: Horizontal offset (auto-alignment if not set). *y*:: @@ -689,13 +699,17 @@ screen [MULTI] data [MULTI] { reverse = bg = bordercolor = - fg = fg_center = fg_end = + fg = fg_center = fg_end = fg_off = } gap = width = height = padding = vertical = + ticks_count = + ticks_gap = + border_width = + border_padding = x = y = align = <{auto,right,left}> mouse [MULTI] diff --git a/common/configopts.c b/common/configopts.c index 51898ece..3f54fa14 100644 --- a/common/configopts.c +++ b/common/configopts.c @@ -293,6 +293,7 @@ cfg_opt_t widget_progressbar_data_opts[] = CFG_STR((char *) "fg", NULL, CFGF_NONE), CFG_STR((char *) "fg_center", NULL, CFGF_NONE), CFG_STR((char *) "fg_end", NULL, CFGF_NONE), + CFG_STR((char *) "fg_off", NULL, CFGF_NONE), CFG_STR((char *) "bg", NULL, CFGF_NONE), CFG_STR((char *) "bordercolor", NULL, CFGF_NONE), CFG_BOOL((char *) "reverse", cfg_false, CFGF_NONE), @@ -307,6 +308,10 @@ cfg_opt_t widget_progressbar_opts[] = CFG_SEC((char *) "data", widget_progressbar_data_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_INT((char *) "width", 100, CFGF_NONE), CFG_INT((char *) "gap", 2, CFGF_NONE), + CFG_INT((char *) "border_width", 1, CFGF_NONE), + CFG_INT((char *) "border_padding", 0, CFGF_NONE), + CFG_INT((char *) "ticks_gap", 1, CFGF_NONE), + CFG_INT((char *) "ticks_count", 0, CFGF_NONE), CFG_INT((char *) "padding", 0, CFGF_NONE), CFG_FLOAT((char *) "height", 0.67, CFGF_NONE), CFG_BOOL((char *) "vertical", cfg_false, CFGF_NONE), diff --git a/common/draw.c b/common/draw.c index 3fc4b766..c338cdb0 100644 --- a/common/draw.c +++ b/common/draw.c @@ -333,6 +333,8 @@ draw_rectangle(DrawCtx *ctx, area_t geometry, float line_width, Bool filled, XCo { cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width(ctx->cr, line_width); + cairo_set_miter_limit(ctx->cr, 0.0); + cairo_set_line_join(ctx->cr, CAIRO_LINE_JOIN_MITER); cairo_set_source_rgb(ctx->cr, color.red / 65535.0, color.green / 65535.0, @@ -371,6 +373,8 @@ draw_rectangle_gradient(DrawCtx *ctx, area_t geometry, float line_width, Bool fi cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width(ctx->cr, line_width); + cairo_set_miter_limit(ctx->cr, 0.0); + cairo_set_line_join(ctx->cr, CAIRO_LINE_JOIN_MITER); pat = draw_setup_cairo_color_source(ctx, pattern_rect, pcolor, pcolor_center, pcolor_end); @@ -398,7 +402,8 @@ draw_graph_setup(DrawCtx *ctx) cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width(ctx->cr, 1.0); /* 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_miter_limit(ctx->cr, 0.0); + cairo_set_line_join(ctx->cr, CAIRO_LINE_JOIN_MITER); } /** Draw a graph diff --git a/widgets/common.c b/widgets/common.c new file mode 100644 index 00000000..5d83b220 --- /dev/null +++ b/widgets/common.c @@ -0,0 +1,81 @@ +/* + * widgets/common.c - some functions used by widgets + * + * Copyright © 2008 Julien Danjou + * Copyright © 2008 Marco Candrian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "widgets/common.h" + +extern AwesomeConf globalconf; + +widget_tell_status_t +widget_set_color_for_data(Widget *widget, XColor *color, char *command, int data_items, char ** data_title) +{ + char *title, *setting; + int i; + title = strtok(command, " "); + if(!(setting = strtok(NULL, " "))) + return WIDGET_ERROR_NOVALUE; + for(i = 0; i < data_items; i++) + if(!a_strcmp(title, data_title[i])) + { + if(draw_color_new(globalconf.display, + widget->statusbar->phys_screen, + setting, &color[i])) + return WIDGET_NOERROR; + else + return WIDGET_ERROR_FORMAT_COLOR; + } + return WIDGET_ERROR_FORMAT_SECTION; +} +widget_tell_status_t +widget_set_color_pointer_for_data(Widget *widget, XColor **color, char *command, int data_items, char ** data_title) +{ + char *title, *setting; + int i; + Bool flag; + title = strtok(command, " "); + if(!(setting = strtok(NULL, " "))) + return WIDGET_ERROR_NOVALUE; + for(i = 0; i < data_items; i++) + if(!a_strcmp(title, data_title[i])) + { + flag = False; + if(!color[i]) + { + flag = True; /* p_delete && restore to NULL, if draw_color_new unsuccessful */ + color[i] = p_new(XColor, 1); + } + if(!(draw_color_new(globalconf.display, + widget->statusbar->phys_screen, + setting, color[i]))) + { + if(flag) /* restore */ + { + p_delete(&color[i]); + color[i] = NULL; + } + return WIDGET_ERROR_FORMAT_COLOR; + } + return WIDGET_NOERROR; + } + return WIDGET_ERROR_FORMAT_SECTION; +} + +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/common.h b/widgets/common.h new file mode 100644 index 00000000..978619bc --- /dev/null +++ b/widgets/common.h @@ -0,0 +1,31 @@ +/* + * widgets/common.h - some functions headers used by widgets + * + * Copyright © 2008 Julien Danjou + * Copyright © 2008 Marco Candrian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef AWESOME_WIDGETS_COMMON_H +#define AWESOME_WIDGETS_COMMON_H +#include "widget.h" + +widget_tell_status_t widget_set_color_for_data(Widget *, XColor *, char *, int, char **); +widget_tell_status_t widget_set_color_pointer_for_data(Widget *, XColor **, char *, int, char **); + +#endif +// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/widgets/progressbar.c b/widgets/progressbar.c index 4e959179..fc813e59 100644 --- a/widgets/progressbar.c +++ b/widgets/progressbar.c @@ -1,7 +1,8 @@ /* - * progressbar.c - progress bar widget + * progressbar.c - progressbar widget * * Copyright © 2007-2008 Julien Danjou + * Copyright © 2007-2008 Marco Candrian * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,10 +23,12 @@ #include #include "widget.h" +#include "widgets/common.h" #include "screen.h" #include "common/util.h" #include "common/configopts.h" + extern AwesomeConf globalconf; typedef struct @@ -38,8 +41,16 @@ typedef struct int width; /** Padding */ int padding; - /** Pixel between data_items (bars) */ + /** Pixel between data items (bars) */ int gap; + /** border width in pixels */ + int border_width; + /** padding between border and ticks/bar */ + int border_padding; + /** gap/distance between the individual ticks */ + int ticks_gap; + /** total number of ticks */ + int ticks_count; /** reverse drawing */ Bool *reverse; /** 90 Degree's turned */ @@ -50,6 +61,8 @@ typedef struct float height; /** Foreground color */ XColor *fg; + /** Foreground color of turned-off ticks */ + XColor *fg_off; /** Foreground color when bar is half-full */ XColor **pfg_center; /** Foreground color when bar is full */ @@ -60,11 +73,60 @@ typedef struct XColor *bordercolor; } Data; +Bool check_settings(Data *, int); + +Bool +check_settings(Data *d, int status_height) +{ + int simple, h_total, v_total; + + v_total = d->width - d->padding; + h_total = (int)(status_height * d->height + 0.5); + + if(!d->vertical) /* horizontal */ + { + simple = v_total - 2 * (d->border_width + d->border_padding) - 1; + if((d->ticks_count && simple - (d->ticks_count - 1) * d->ticks_gap - d->ticks_count + 1 < 0) || + (!d->ticks_count && simple < 0)) + { + warn("progressbar's 'width' is too small for the given configuration options\n"); + return False; + } + simple = h_total - d->data_items * (d->border_width + d->border_padding + 1) - (d->data_items - 1) * d->gap; + if(simple < 0) + { + warn("progressbar's 'height' is too small for the given configuration options\n"); + return False; + } + } + else /* vertical / standing up */ + { + simple = h_total - 2 * (d->border_width + d->border_padding) - 1; + if((d->ticks_count && simple - (d->ticks_count - 1) * d->ticks_gap - d->ticks_count + 1 < 0) || + (!d->ticks_count && simple < 0)) + { + warn("progressbar's 'height' is too small for the given configuration options\n"); + return False; + } + simple = v_total - d->data_items * (d->border_width + d->border_padding + 1) - (d->data_items - 1) * d->gap; + if(simple < 0) + { + warn("progressbar's 'width' is too small for the given configuration options\n"); + return False; + } + } + return True; +} + + static int progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, int used __attribute__ ((unused))) { - int i, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset = 0; + /* pb_.. values points to the widget inside a potential border */ + int i, percent_ticks, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset; + int unit; /* tick + gap */ + int border_offset; area_t rectangle, pattern_rect; Data *d = widget->data; @@ -80,57 +142,78 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, if(!widget->user_supplied_y) widget->area.y = 0; - /* TODO: maybe prevent (use Data-values) to calculate that stuff below over and over again */ - /* data for the first rectangle (data-bar) to draw */ - if(d->vertical) - { - pb_width = (int) ((d->width - d->padding - (d->gap * (d->data_items - 1))) / d->data_items + 0.5); - pb_height = (int) (widget->statusbar->height * d->height + 0.5); - pb_y = widget->area.y + (int)((widget->statusbar->height - pb_height) / 2 + 0.5); - } - 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); - } - - pb_x = widget->area.x + d->padding; - /* for a 'reversed' progressbar: + * basic progressbar: * 1. the full space gets the size of the formerly empty one * 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 + * ticks special: + * round the values to a full tick accordingly + * 4. finally draw the gaps */ + + pb_x = widget->area.x + d->padding; + border_offset = d->border_width / 2; + pb_offset = 0; + if(d->vertical) { + /* TODO: maybe prevent to calculate that stuff below over and over again (->use Data-values) */ + pb_height = (int) (widget->statusbar->height * d->height + 0.5) - 2 * (d->border_width + d->border_padding); + if(d->ticks_count && d->ticks_gap) + { + unit = (pb_height + d->ticks_gap) / d->ticks_count; + pb_height = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */ + } + + pb_width = (int) ((d->width - d->padding - (d->border_width + d->border_padding) * 2 * d->data_items - + d->gap * (d->data_items - 1)) / d->data_items + 0.5); + + pb_y = widget->area.y + ((int) (widget->statusbar->height * (1 - d->height)) / 2) + d->border_width + d->border_padding; + for(i = 0; i < d->data_items; i++) { - /* border rectangle */ - rectangle.x = pb_x + pb_offset; - rectangle.y = pb_y; - rectangle.width = pb_width; - rectangle.height = pb_height; - draw_rectangle(ctx, rectangle, 1.0, False, d->bordercolor[i]); + if(d->ticks_count && d->ticks_gap) + { + percent_ticks = (int)(d->ticks_count * (float)d->percent[i] / 100 + 0.5); + if(percent_ticks) + pb_progress = percent_ticks * unit - d->ticks_gap; + else + pb_progress = 0; + } + else + pb_progress = (int)(pb_height * d->percent[i] / 100.0 + 0.5); + + if(d->border_width) + { + /* border rectangle */ + rectangle.x = pb_x + pb_offset - border_offset - d->border_padding - 1; + + if(2 * border_offset == d->border_width) + rectangle.y = pb_y - border_offset - d->border_padding; + else + rectangle.y = pb_y - border_offset - d->border_padding - 1; + + rectangle.width = pb_width + d->border_width + 2 * d->border_padding - 1 + 2; + rectangle.height = pb_height + d->border_width + 2 * d->border_padding + 1; + draw_rectangle(ctx, rectangle, d->border_width, False, d->bordercolor[i]); + } /* 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.y = pb_y + 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; + pb_progress = pb_width - pb_progress; + pattern_rect.x = pb_x ; + pattern_rect.y = pb_y ; pattern_rect.width = 0; pattern_rect.height = pb_height; } @@ -138,9 +221,9 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, /* 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.x = pb_x + pb_offset; + rectangle.y = pb_y + pb_height - pb_progress; + rectangle.width = pb_width; rectangle.height = pb_progress; /* fg color */ @@ -148,54 +231,96 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, draw_rectangle_gradient(ctx, rectangle, 1.0, True, pattern_rect, &(d->fg[i]), d->pfg_center[i], d->pfg_end[i]); else /*REV: bg */ - draw_rectangle(ctx, rectangle, 1.0, True, d->bg[i]); + draw_rectangle(ctx, rectangle, 1.0, True, d->fg_off[i]); } /* top part */ - if((pb_height - 2) - pb_progress > 0) /* not filled area */ + if(pb_height - 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; + rectangle.x = pb_x + pb_offset; + rectangle.y = pb_y; + rectangle.width = pb_width; + rectangle.height = pb_height - pb_progress; /* bg color */ if(!d->reverse[i]) - draw_rectangle(ctx, rectangle, 1.0, True, d->bg[i]); + draw_rectangle(ctx, rectangle, 1.0, True, d->fg_off[i]); else /* REV: bg */ draw_rectangle_gradient(ctx, rectangle, 1.0, True, pattern_rect, &(d->fg[i]), d->pfg_center[i], d->pfg_end[i]); } - pb_offset += pb_width + d->gap; + /* draw gaps TODO: improve e.g all in one */ + if(d->ticks_count && d->ticks_gap) + { + rectangle.width = pb_width; + rectangle.height = d->ticks_gap; + rectangle.x = pb_x + pb_offset; + for(rectangle.y = pb_y + (unit - d->ticks_gap); + pb_y + pb_height - d->ticks_gap >= rectangle.y; + rectangle.y += unit) + { + draw_rectangle(ctx, rectangle, 1.0, True, d->bg[i]); + } + } + pb_offset += pb_width + d->gap + 2 * (d->border_width + d->border_padding); } } else /* a horizontal progressbar */ { + pb_width = d->width - d->padding - d->border_width - 2 * d->border_padding; + if(d->ticks_count && d->ticks_gap) + { + unit = (pb_width + d->ticks_gap) / d->ticks_count; + pb_width = (int)unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */ + } + + pb_height = (int) ((widget->statusbar->height * d->height - d->data_items * 2 * (d->border_width + d->border_padding) - + (d->gap * (d->data_items - 1))) / d->data_items + 0.5); + pb_y = widget->area.y + ((int) (widget->statusbar->height * (1 - d->height)) / 2) + d->border_width + d->border_padding; + for(i = 0; i < d->data_items; i++) { - /* border rectangle */ - rectangle.x = pb_x; - rectangle.y = pb_y + pb_offset; - rectangle.width = pb_width; - rectangle.height = pb_height; - draw_rectangle(ctx, rectangle, 1.0, False, d->bordercolor[i]); + if(d->ticks_count && d->ticks_gap) + { + /* +0.5 rounds up ticks -> turn on a tick when half of it is reached */ + percent_ticks = (int)(d->ticks_count * (float)d->percent[i] / 100 + 0.5); + if(percent_ticks) + pb_progress = (int)(percent_ticks * unit - d->ticks_gap + 0.5); + else + pb_progress = 0; + } + else + pb_progress = (int)(pb_width * d->percent[i] / 100.0 + 0.5); + if(d->border_width) + { + /* border rectangle */ + rectangle.x = pb_x - border_offset - d->border_padding - 1; + + if(2 * border_offset == d->border_width) + rectangle.y = pb_y + pb_offset - border_offset - d->border_padding; + else + rectangle.y = pb_y + pb_offset - border_offset - d->border_padding - 1; + + rectangle.width = pb_width + d->border_width + 2 * d->border_padding - 1 + 2; + rectangle.height = pb_height + d->border_width + 2 * d->border_padding + 1; + draw_rectangle(ctx, rectangle, d->border_width, False, d->bordercolor[i]); + } /* 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.x = pb_x; + pattern_rect.y = pb_y; 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; + /* reverse: right to left */ + pb_progress = pb_width - pb_progress; + pattern_rect.x = pb_x + pb_width; + pattern_rect.y = pb_y; pattern_rect.width = -pb_width; pattern_rect.height = 0; } @@ -203,35 +328,49 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, /* left part */ if(pb_progress > 0) { - rectangle.x = pb_x + 1; - rectangle.y = pb_y + 1 + pb_offset; + rectangle.x = pb_x; + rectangle.y = pb_y + pb_offset; rectangle.width = pb_progress; - rectangle.height = pb_height - 2; + rectangle.height = pb_height; /* fg color */ if(!d->reverse[i]) draw_rectangle_gradient(ctx, rectangle, 1.0, True, pattern_rect, &(d->fg[i]), d->pfg_center[i], d->pfg_end[i]); - else /* REV: bg */ - draw_rectangle(ctx, rectangle, 1.0, True, d->bg[i]); + else /* reverse: bg */ + draw_rectangle(ctx, rectangle, 1.0, True, d->fg_off[i]); } /* right part */ - if(pb_width - 2 - pb_progress > 0) + if(pb_width - 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; + rectangle.x = pb_x + pb_progress; + rectangle.y = pb_y + pb_offset; + rectangle.width = pb_width - pb_progress; + rectangle.height = pb_height; /* bg color */ if(!d->reverse[i]) - draw_rectangle(ctx, rectangle, 1.0, True, d->bg[i]); - else /* REV: fg */ + draw_rectangle(ctx, rectangle, 1.0, True, d->fg_off[i]); + else /* reverse: fg */ draw_rectangle_gradient(ctx, rectangle, 1.0, True, pattern_rect, &(d->fg[i]), d->pfg_center[i], d->pfg_end[i]); } - pb_offset += pb_height + d->gap; + /* draw gaps TODO: improve e.g all in one */ + if(d->ticks_count && d->ticks_gap) + { + rectangle.width = d->ticks_gap; + rectangle.height = pb_height; + rectangle.y = pb_y + pb_offset; + for(rectangle.x = pb_x + (unit - d->ticks_gap); + pb_x + pb_width - d->ticks_gap >= rectangle.x; + rectangle.x += unit) + { + draw_rectangle(ctx, rectangle, 1.0, True, d->bg[i]); + } + } + + pb_offset += pb_height + d->gap + 2 * (d->border_width + d->border_padding); } } @@ -245,8 +384,8 @@ progressbar_tell(Widget *widget, char *property, char *command) { Data *d = widget->data; int i = 0, percent, tmp; - Bool flag; char *title, *setting; + float tmpf; if(!d->data_items) return WIDGET_ERROR_CUSTOM; /* error already printed on _new */ @@ -269,138 +408,49 @@ progressbar_tell(Widget *widget, char *property, char *command) return WIDGET_ERROR_FORMAT_SECTION; } else if(!a_strcmp(property, "fg")) - { - title = strtok(command, " "); - if(!(setting = strtok(NULL, " "))) - return WIDGET_ERROR_NOVALUE; - for(i = 0; i < d->data_items; i++) - if(!a_strcmp(title, d->data_title[i])) - { - if(draw_color_new(globalconf.display, - widget->statusbar->phys_screen, - setting, &d->fg[i])) - return WIDGET_NOERROR; - else - return WIDGET_ERROR_FORMAT_COLOR; - } - return WIDGET_ERROR_FORMAT_SECTION; - } + return widget_set_color_for_data(widget, d->fg, command, d->data_items, d->data_title); + else if(!a_strcmp(property, "fg_off")) + return widget_set_color_for_data(widget, d->fg_off, command, d->data_items, d->data_title); else if(!a_strcmp(property, "bg")) - { - title = strtok(command, " "); - if(!(setting = strtok(NULL, " "))) - return WIDGET_ERROR_NOVALUE; - for(i = 0; i < d->data_items; i++) - if(!a_strcmp(title, d->data_title[i])) - { - if(draw_color_new(globalconf.display, - widget->statusbar->phys_screen, - setting, &d->bg[i])) - return WIDGET_NOERROR; - else - return WIDGET_ERROR_FORMAT_COLOR; - } - return WIDGET_ERROR_FORMAT_SECTION; - } - else if(!a_strcmp(property, "fg_center")) - { - title = strtok(command, " "); - if(!(setting = strtok(NULL, " "))) - return WIDGET_ERROR_NOVALUE; - for(i = 0; i < d->data_items; i++) - if(!a_strcmp(title, d->data_title[i])) - { - flag = False; - if(!d->pfg_center[i]) - { - flag = True; /* p_delete && restore to NULL, if draw_color_new unsuccessful */ - d->pfg_center[i] = p_new(XColor, 1); - } - if(!(draw_color_new(globalconf.display, - widget->statusbar->phys_screen, - setting, d->pfg_center[i]))) - { - if(flag) /* restore */ - { - p_delete(&d->pfg_center[i]); - d->pfg_center[i] = NULL; - } - return WIDGET_ERROR_FORMAT_COLOR; - } - return WIDGET_NOERROR; - } - return WIDGET_ERROR_FORMAT_SECTION; - } - else if(!a_strcmp(property, "fg_end")) - { - title = strtok(command, " "); - if(!(setting = strtok(NULL, " "))) - return WIDGET_ERROR_NOVALUE; - for(i = 0; i < d->data_items; i++) - if(!a_strcmp(title, d->data_title[i])) - { - flag = False; - if(!d->pfg_end[i]) - { - flag = True; - d->pfg_end[i] = p_new(XColor, 1); - } - if(!(draw_color_new(globalconf.display, - widget->statusbar->phys_screen, - setting, d->pfg_end[i]))) - { - if(flag) /* restore */ - { - p_delete(&d->pfg_end[i]); - d->pfg_end[i] = NULL; - } - return WIDGET_ERROR_FORMAT_COLOR; - } - return WIDGET_NOERROR; - } - } + return widget_set_color_for_data(widget, d->bg, command, d->data_items, d->data_title); else if(!a_strcmp(property, "bordercolor")) - { - title = strtok(command, " "); - if(!(setting = strtok(NULL, " "))) - return WIDGET_ERROR_NOVALUE; - for(i = 0; i < d->data_items; i++) - if(!a_strcmp(title, d->data_title[i])) - { - if(draw_color_new(globalconf.display, - widget->statusbar->phys_screen, - setting, &d->bordercolor[i])) - return WIDGET_NOERROR; - else - return WIDGET_ERROR_FORMAT_COLOR; - } - return WIDGET_ERROR_FORMAT_SECTION; - } + return widget_set_color_for_data(widget, d->bordercolor, command, d->data_items, d->data_title); + else if(!a_strcmp(property, "fg_center")) + return widget_set_color_pointer_for_data(widget, d->pfg_center, command, d->data_items, d->data_title); + else if(!a_strcmp(property, "fg_end")) + return widget_set_color_pointer_for_data(widget, d->pfg_end, command, d->data_items, d->data_title); else if(!a_strcmp(property, "gap")) d->gap = atoi(command); else if(!a_strcmp(property, "width")) { - tmp = atoi(command); - if(tmp - d->padding < 3) + tmp = d->width; + d->width = atoi(command); + if(!check_settings(d, widget->statusbar->height)) { - warn("progressbar widget needs: (width - padding) >= 3. Ignoring command.\n"); + d->width = tmp; /* restore */ return WIDGET_ERROR_CUSTOM; } - else - d->width = tmp; } else if(!a_strcmp(property, "height")) - d->height = atof(command); - else if(!a_strcmp(property, "padding")) { - tmp = atoi(command); - if(d->width - tmp < 3) + tmpf = d->height; + d->height = atof(command); + if(!check_settings(d, widget->statusbar->height)) { - warn("progressbar widget needs: (width - padding) >= 3. Ignoring command.\n"); + d->height = tmpf; /* restore */ return WIDGET_ERROR_CUSTOM; } - else + } + else if(!a_strcmp(property, "border_padding")) + { + tmp = d->padding; + d->padding = atoi(command); + if(!check_settings(d, widget->statusbar->height)) + { d->padding = tmp; + return WIDGET_ERROR_CUSTOM; + } + } else return WIDGET_ERROR; @@ -417,26 +467,32 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) int i; cfg_t *cfg; + w = p_new(Widget, 1); widget_common_new(w, statusbar, config); w->draw = progressbar_draw; w->tell = progressbar_tell; d = w->data = p_new(Data, 1); + + d->data_items = 0; /* XXX: need to initialise or for sure 0? */ + + d->height = cfg_getfloat(config, "height"); d->width = cfg_getint(config, "width"); d->padding = cfg_getint(config, "padding"); - if(d->width - d->padding < 3) - { - warn("progressbar widget needs: (width - padding) >= 3\n"); - return w; - } + d->border_padding = cfg_getint(config, "border_padding"); + d->ticks_gap = cfg_getint(config, "ticks_gap"); + d->ticks_count = cfg_getint(config, "ticks_count"); + d->border_width = cfg_getint(config, "border_width"); - d->height = cfg_getfloat(config, "height"); - d->gap = cfg_getint(config, "gap"); - d->padding = cfg_getint(config, "padding"); if(!(d->vertical = cfg_getbool(config, "vertical"))) d->vertical = False; + if(!check_settings(d, statusbar->height)) + return w; + + d->gap = cfg_getint(config, "gap"); + w->alignment = cfg_getalignment(config, "align"); if(!(d->data_items = cfg_size(config, "data"))) @@ -448,6 +504,7 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) d->fg = p_new(XColor, d->data_items); d->pfg_end = p_new(XColor *, d->data_items); d->pfg_center = p_new(XColor *, d->data_items); + d->fg_off = p_new(XColor, d->data_items); d->bg = p_new(XColor, d->data_items); d->bordercolor = p_new(XColor, d->data_items); d->percent = p_new(int, d->data_items); @@ -480,6 +537,11 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) draw_color_new(globalconf.display, statusbar->phys_screen, color, d->pfg_end[i]); } + if((color = cfg_getstr(cfg, "fg_off"))) + draw_color_new(globalconf.display, statusbar->phys_screen, color, &d->fg_off[i]); + else + d->fg_off[i] = globalconf.screens[statusbar->screen].styles.normal.bg; + if((color = cfg_getstr(cfg, "bg"))) draw_color_new(globalconf.display, statusbar->phys_screen, color, &d->bg[i]); else