From 37da7d0d018ed15ada7314f98f27c0cca3e851dc Mon Sep 17 00:00:00 2001 From: marco candrian Date: Sun, 6 Jan 2008 18:23:56 +0100 Subject: [PATCH] graph widget added example config: graph gr_cpu { width = 80 height = "0.8" fg = "#336633" bg = "#000000" bordercolor = "#669966" padding_left = 0 mouse = {...} x = ... y = ... } Looks like here: http://www.calmar.ws/tmp/112-Sun-screen.png I renamed lpadding to padding_left, and bcolor to bordercolor also on the progressbar widget. The awesomerc page would still be to write, when this patch will get accepted. Hints are always welcomed. --- Makefile.am | 1 + config.c | 18 ++++- draw.c | 36 ++++++++++ draw.h | 1 + widget.c | 1 + widget.h | 1 + widgets/graph.c | 160 ++++++++++++++++++++++++++++++++++++++++++ widgets/progressbar.c | 20 +++--- 8 files changed, 226 insertions(+), 12 deletions(-) create mode 100644 widgets/graph.c diff --git a/Makefile.am b/Makefile.am index da13da4a..0cd9f4b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ WIDGETS += widgets/iconbox.c WIDGETS += widgets/netwmicon.c WIDGETS += widgets/progressbar.c WIDGETS += widgets/tasklist.c +WIDGETS += widgets/graph.c EXTRA_DIST += awesomerc diff --git a/config.c b/config.c index 92106e41..918d349e 100644 --- a/config.c +++ b/config.c @@ -573,11 +573,24 @@ config_parse(const char *confpatharg) CFG_BOOL((char *) "show_icons", cfg_true, CFGF_NONE), CFG_END() }; + static cfg_opt_t widget_graph_opts[] = + { + CFG_INT((char *) "x", 0xffffffff, CFGF_NONE), + CFG_INT((char *) "y", 0xffffffff, CFGF_NONE), + CFG_SEC((char *) "mouse", mouse_generic_opts, CFGF_MULTI), + CFG_INT((char *) "width", 100, CFGF_NONE), + CFG_INT((char *) "padding_left", 3, CFGF_NONE), + CFG_FLOAT((char *) "height", 0.67, CFGF_NONE), + CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "bordercolor", (char *) NULL, CFGF_NONE), + CFG_END() + }; static cfg_opt_t widget_progressbar_bar_opts[] = { CFG_STR((char *) "fg", (char *) NULL, CFGF_NONE), CFG_STR((char *) "bg", (char *) NULL, CFGF_NONE), - CFG_STR((char *) "bcolor", (char *) NULL, CFGF_NONE), + CFG_STR((char *) "bordercolor", (char *) NULL, CFGF_NONE), }; static cfg_opt_t widget_progressbar_opts[] = { @@ -587,7 +600,7 @@ config_parse(const char *confpatharg) CFG_SEC((char *) "bar", widget_progressbar_bar_opts, CFGF_MULTI), CFG_INT((char *) "width", 100, CFGF_NONE), CFG_INT((char *) "gap", 2, CFGF_NONE), - CFG_INT((char *) "lpadding", 3, CFGF_NONE), + CFG_INT((char *) "padding_left", 3, CFGF_NONE), CFG_FLOAT((char *) "height", 0.67, CFGF_NONE), CFG_END() }; @@ -603,6 +616,7 @@ config_parse(const char *confpatharg) CFG_SEC((char *) "iconbox", widget_iconbox_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "netwmicon", widget_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "progressbar", widget_progressbar_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), + CFG_SEC((char *) "graph", widget_graph_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_SEC((char *) "tasklist", widget_tasklist_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES), CFG_END() }; diff --git a/draw.c b/draw.c index cf64daed..20d095b2 100644 --- a/draw.c +++ b/draw.c @@ -166,6 +166,42 @@ draw_rectangle(DrawCtx *ctx, int x, int y, int w, int h, Bool filled, XColor col cairo_surface_destroy(surface); } +/* draws a graph; it takes the line-lengths from 'h' (w = size of h) + * It cycles backwards through it, beginning at position h_index, until + * h_index is reached again (wrapped around). */ + +void +draw_graph(DrawCtx *ctx, int x, int y, int w, int *h, int h_index, XColor color) +{ + cairo_surface_t *surface; + cairo_t *cr; + int i, i_tmp; + + surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height); + cr = cairo_create (surface); + + cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); + cairo_set_line_width(cr, 1.0); + cairo_set_source_rgb(cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0); + + i_tmp = h_index; + i = -1; + while(++i < w) + { + cairo_move_to(cr, x, y); + cairo_line_to(cr, x, y - h[i_tmp]); + x++; + + if (--i_tmp < 0) + i_tmp = w - 1; + } + + cairo_stroke(cr); + + cairo_destroy(cr); + cairo_surface_destroy(surface); +} + void draw_circle(DrawCtx *ctx, int x, int y, int r, Bool filled, XColor color) { diff --git a/draw.h b/draw.h index 7bb43775..798d988d 100644 --- a/draw.h +++ b/draw.h @@ -56,6 +56,7 @@ DrawCtx *draw_get_context(int, int, int); void draw_free_context(DrawCtx *); void draw_text(DrawCtx *, int, int, int, int, int, int, XftFont *, const char *, XColor fg, XColor bg); void draw_rectangle(DrawCtx *, int, int, int, int, Bool, XColor); +void draw_graph(DrawCtx *, int, int, int, int *, int, 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/widget.c b/widget.c index f5697533..9a54d68a 100644 --- a/widget.c +++ b/widget.c @@ -36,6 +36,7 @@ const NameFuncLink WidgetList[] = {"iconbox", iconbox_new}, {"netwmicon", netwmicon_new}, {"progressbar", progressbar_new}, + {"graph", graph_new}, {"tasklist", tasklist_new}, {NULL, NULL} }; diff --git a/widget.h b/widget.h index f5f243bd..2e679a41 100644 --- a/widget.h +++ b/widget.h @@ -40,6 +40,7 @@ WidgetConstructor focustitle_new; WidgetConstructor iconbox_new; WidgetConstructor netwmicon_new; WidgetConstructor progressbar_new; +WidgetConstructor graph_new; WidgetConstructor tasklist_new; Uicb uicb_widget_tell; diff --git a/widgets/graph.c b/widgets/graph.c new file mode 100644 index 00000000..16ed9b2b --- /dev/null +++ b/widgets/graph.c @@ -0,0 +1,160 @@ +/* + * graph.c - a graph 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 + * 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 "util.h" +#include "draw.h" +#include "widget.h" +#include "xutil.h" +#include "screen.h" + +extern AwesomeConf globalconf; + +typedef struct +{ + int percent; /* Percent 0 to 100 */ + int width; /* Width of the widget */ + int padding_left; /* Left padding */ + float height; /* Height 0-1, where 1 is height of statusbar */ + XColor fg; /* Foreground color */ + XColor bg; /* Background color */ + XColor bordercolor; /* Border color */ + + int *lines; /* keeps the calculated values (line-length); */ + int lines_index; /* pointer to current val */ + int lines_size; /* size of lines-array */ +} Data; + + + +static int +graph_draw(Widget *widget, DrawCtx *ctx, int offset, + int used __attribute__ ((unused))) +{ + int width, height; /* width/height (pixel) to draw the outer box */ + int margin_top, left_offset; + Data *d = widget->data; + + width = d->lines_size + 2; + + if(!widget->user_supplied_x) + widget->area.x = widget_calculate_offset(widget->statusbar->width, + d->width, + offset, + widget->alignment); + if(!widget->user_supplied_y) + widget->area.y = 0; + + margin_top = (int) (widget->statusbar->height * (1 - d->height)) / 2 + 0.5 + widget->area.y; + height = (int) (widget->statusbar->height * d->height + 0.5); + left_offset = widget->area.x + d->padding_left; + + draw_rectangle(ctx, + left_offset, margin_top, + width, height, + False, d->bordercolor); + + draw_rectangle(ctx, + left_offset + 1, margin_top + 1, + width - 2, height - 2, + True, d->bg); + + /* computes line-length to draw and store into lines[] */ + d->lines[d->lines_index] = (int) (d->percent) * (height - 2 ) / 100 + 0.5; + + if(d->lines[d->lines_index] < 0) + d->lines[d->lines_index] = 0; + + draw_graph(ctx, + left_offset + 2, margin_top + height - 1, + d->lines_size, d->lines, d->lines_index, + d->fg); + + widget->area.width = d->width; + widget->area.height = widget->statusbar->height; + return widget->area.width; +} + +static void +graph_tell(Widget *widget, char *command) +{ + Data *d = widget->data; + int percent; + + if(!command || d->width < 1) + return; + + if(++d->lines_index >= d->lines_size) /* cycle inside the array */ + d->lines_index = 0; + + percent = atoi(command); + if(percent <= 100 && percent >= 0) + d->percent = percent; +} + +Widget * +graph_new(Statusbar *statusbar, cfg_t *config) +{ + Widget *w; + Data *d; + char *color; + int phys_screen = get_phys_screen(statusbar->screen); + + w = p_new(Widget, 1); + widget_common_new(w, statusbar, config); + + w->draw = graph_draw; + w->tell = graph_tell; + d = w->data = p_new(Data, 1); + + d->height = cfg_getfloat(config, "height"); + d->width = cfg_getint(config, "width"); + d->padding_left = cfg_getint(config, "padding_left"); + + d->lines_size = d->width - d->padding_left - 2; + d->lines_index = -1; /* graph_tell will increment it to 0 (to begin with...) */ + + if(d->lines_size < 1) + { + warn("graph widget needs: (width - padding_left) >= 3\n"); + return w; + } + + d->lines = p_new(int, d->lines_size); + + if((color = cfg_getstr(config, "fg"))) + d->fg = initxcolor(phys_screen, color); + else + d->fg = globalconf.screens[statusbar->screen].colors_normal[ColFG]; + + if((color = cfg_getstr(config, "bg"))) + d->bg = initxcolor(phys_screen, color); + else + d->bg = globalconf.screens[statusbar->screen].colors_normal[ColBG]; + + if((color = cfg_getstr(config, "bordercolor"))) + d->bordercolor = initxcolor(phys_screen, color); + else + d->bordercolor = d->fg; + + return w; +} +// 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 139eb9c8..731db2b1 100644 --- a/widgets/progressbar.c +++ b/widgets/progressbar.c @@ -35,7 +35,7 @@ typedef struct /** Width of the bars */ int width; /** Left padding */ - int lpadding; + int padding_left; /** Pixel between bars */ int gap; /** Number of bars */ @@ -47,7 +47,7 @@ typedef struct /** Background color */ XColor *bg; /** Border color */ - XColor *bcolor; + XColor *bordercolor; } Data; static int @@ -61,7 +61,7 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, if (!(d->bars)) return 0; - width = d->width - d->lpadding; + width = d->width - d->padding_left; if(!widget->user_supplied_x) widget->area.x = widget_calculate_offset(widget->statusbar->width, @@ -74,7 +74,7 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, margin_top = (int) (widget->statusbar->height * (1 - d->height)) / 2 + 0.5 + widget->area.y; pb_height = (int) (widget->statusbar->height * d->height - (d->gap * (d->bars - 1))) / d->bars + 0.5; - left_offset = widget->area.x + d->lpadding; + left_offset = widget->area.x + d->padding_left; for(i = 0; i < d->bars; i++) { @@ -83,7 +83,7 @@ progressbar_draw(Widget *widget, DrawCtx *ctx, int offset, draw_rectangle(ctx, left_offset, margin_top, width, pb_height, - False, d->bcolor[i]); + False, d->bordercolor[i]); if(pwidth > 0) draw_rectangle(ctx, @@ -148,7 +148,7 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) d->bg = p_new(XColor, d->bars); d->fg = p_new(XColor, d->bars); - d->bcolor = p_new(XColor, d->bars); + d->bordercolor = p_new(XColor, d->bars); d->percent = p_new(int, d->bars); for(i = 0; i < d->bars; i++) @@ -165,17 +165,17 @@ progressbar_new(Statusbar *statusbar, cfg_t *config) else d->bg[i] = globalconf.screens[statusbar->screen].colors_normal[ColBG]; - if((color = cfg_getstr(cfg, "bcolor"))) - d->bcolor[i] = initxcolor(phys_screen, color); + if((color = cfg_getstr(cfg, "bordercolor"))) + d->bordercolor[i] = initxcolor(phys_screen, color); else - d->bcolor[i] = d->fg[i]; + d->bordercolor[i] = d->fg[i]; } d->height = cfg_getfloat(config, "height"); d->gap = cfg_getint(config, "gap"); - d->lpadding = cfg_getint(config, "lpadding"); + d->padding_left = cfg_getint(config, "padding_left"); return w; }