graph, progressbar: remove

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-08-24 17:04:34 +02:00
parent 1128f67f5d
commit be09012c08
8 changed files with 0 additions and 1585 deletions

View file

@ -77,8 +77,6 @@ set(AWE_SRCS
${SOURCE_DIR}/common/backtrace.c
${SOURCE_DIR}/common/luaobject.c
${SOURCE_DIR}/common/luaclass.c
${SOURCE_DIR}/widgets/graph.c
${SOURCE_DIR}/widgets/progressbar.c
${SOURCE_DIR}/widgets/textbox.c
${SOURCE_DIR}/widgets/systray.c
${SOURCE_DIR}/widgets/imagebox.c)

View file

@ -35,7 +35,6 @@ font_height
fullscreen
gap
geometry
graph
group_window
grow
height
@ -77,7 +76,6 @@ pid
plot_data_add
plot_properties_set
position
progressbar
release
resize
right

246
draw.c
View file

@ -208,68 +208,6 @@ draw_text(draw_context_t *ctx, draw_text_context_t *data,
pango_cairo_show_layout(ctx->cr, ctx->layout);
}
/** Setup color-source for cairo (gradient or mono).
* \param ctx Draw context.
* \param gradient_vector x, y to x + x_offset, y + y_offset.
* \param pcolor Color to use at start of gradient_vector.
* \param pcolor_center Color at center of gradient_vector.
* \param pcolor_end Color at end of gradient_vector.
* \return pat Pattern or NULL, needs to get cairo_pattern_destroy()'ed.
*/
static cairo_pattern_t *
draw_setup_cairo_color_source(draw_context_t *ctx, vector_t gradient_vector,
const color_t *pcolor, const color_t *pcolor_center,
const color_t *pcolor_end)
{
cairo_pattern_t *pat = NULL;
bool has_center = pcolor_center->initialized;
bool has_end = pcolor_end->initialized;
/* no need for a real pattern: */
if(!has_end && !has_center)
cairo_set_source_rgba(ctx->cr,
pcolor->red / 255.0,
pcolor->green / 255.0,
pcolor->blue / 255.0,
pcolor->alpha / 255.0);
else
{
pat = cairo_pattern_create_linear(gradient_vector.x,
gradient_vector.y,
gradient_vector.x + gradient_vector.x_offset,
gradient_vector.y + gradient_vector.y_offset);
/* pcolor is always set (so far in awesome) */
cairo_pattern_add_color_stop_rgba(pat, 0.0,
pcolor->red / 255.0,
pcolor->green / 255.0,
pcolor->blue / 255.0,
pcolor->alpha / 255.0);
if(has_center)
cairo_pattern_add_color_stop_rgba(pat, 0.5,
pcolor_center->red / 255.0,
pcolor_center->green / 255.0,
pcolor_center->blue / 255.0,
pcolor_center->alpha / 255.0);
if(has_end)
cairo_pattern_add_color_stop_rgba(pat, 1.0,
pcolor_end->red / 255.0,
pcolor_end->green / 255.0,
pcolor_end->blue / 255.0,
pcolor_end->alpha / 255.0);
else
cairo_pattern_add_color_stop_rgba(pat, 1.0,
pcolor->red / 255.0,
pcolor->green / 255.0,
pcolor->blue / 255.0,
pcolor->alpha / 255.0);
cairo_set_source(ctx->cr, pat);
}
return pat;
}
/** Draw rectangle inside the coordinates
* \param ctx Draw context
* \param geometry geometry
@ -304,190 +242,6 @@ draw_rectangle(draw_context_t *ctx, area_t geometry,
}
}
/** Draw rectangle with gradient colors
* \param ctx Draw context.
* \param geometry Geometry.
* \param line_width Line width.
* \param filled Filled rectangle?
* \param gradient_vector Color-gradient course.
* \param pcolor Color at start of gradient_vector.
* \param pcolor_center Color in the center.
* \param pcolor_end Color at end of gradient_vector.
*/
void
draw_rectangle_gradient(draw_context_t *ctx, area_t geometry, float line_width, bool filled,
vector_t gradient_vector, const color_t *pcolor,
const color_t *pcolor_center, const color_t *pcolor_end)
{
cairo_pattern_t *pat;
cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_NONE);
cairo_set_line_width(ctx->cr, line_width);
cairo_set_miter_limit(ctx->cr, 10.0);
cairo_set_line_join(ctx->cr, CAIRO_LINE_JOIN_MITER);
pat = draw_setup_cairo_color_source(ctx, gradient_vector, pcolor, pcolor_center, pcolor_end);
if(filled)
{
cairo_rectangle(ctx->cr, geometry.x, geometry.y, geometry.width, geometry.height);
cairo_fill(ctx->cr);
}
else
{
cairo_rectangle(ctx->cr, geometry.x + 1, geometry.y, geometry.width - 1, geometry.height - 1);
cairo_stroke(ctx->cr);
}
if(pat)
cairo_pattern_destroy(pat);
}
/** Setup some cairo-things for drawing a graph
* \param ctx Draw context
*/
void
draw_graph_setup(draw_context_t *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 * (...graph_line) */
cairo_set_miter_limit(ctx->cr, 0.0);
cairo_set_line_join(ctx->cr, CAIRO_LINE_JOIN_MITER);
}
/** Draw a graph.
* \param ctx Draw context.
* \param rect The area to draw into.
* \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 grow Put new values to the left or to the right.
* \param gradient_vector Color-Gradient course.
* \param pcolor Color at start of gradient_vector.
* \param pcolor_center Color in the center.
* \param pcolor_end Color at end of gradient_vector.
*/
void
draw_graph(draw_context_t *ctx, area_t rect, int *from, int *to, int cur_index,
position_t grow, vector_t gradient_vector, const color_t *pcolor,
const color_t *pcolor_center, const color_t *pcolor_end)
{
int i = -1;
float x = rect.x + 0.5; /* middle of a pixel */
cairo_pattern_t *pat;
pat = draw_setup_cairo_color_source(ctx, gradient_vector,
pcolor, pcolor_center, pcolor_end);
if(grow == Right) /* draw from right to left */
{
x += rect.width - 1;
while(++i < rect.width)
{
cairo_move_to(ctx->cr, x, rect.y - from[cur_index]);
cairo_line_to(ctx->cr, x, rect.y - to[cur_index]);
x -= 1.0;
if(--cur_index < 0)
cur_index = rect.width - 1;
}
}
else /* draw from left to right */
while(++i < rect.width)
{
cairo_move_to(ctx->cr, x, rect.y - from[cur_index]);
cairo_line_to(ctx->cr, x, rect.y - to[cur_index]);
x += 1.0;
if(--cur_index < 0)
cur_index = rect.width - 1;
}
cairo_stroke(ctx->cr);
if(pat)
cairo_pattern_destroy(pat);
}
/** Draw a line into a graph-widget.
* \param ctx Draw context.
* \param rect The area to draw into.
* \param to array of offsets to draw the line through...
* \param cur_index current position in data-array (cycles around)
* \param grow put new values to the left or to the right
* \param gradient_vector Color-gradient course.
* \param pcolor Color at start of gradient_vector.
* \param pcolor_center Color in the center.
* \param pcolor_end Color at end of gradient_vector.
*/
void
draw_graph_line(draw_context_t *ctx, area_t rect, int *to, int cur_index,
position_t grow, vector_t gradient_vector, const color_t *pcolor,
const color_t *pcolor_center, const color_t *pcolor_end)
{
int i, w;
float x, y;
cairo_pattern_t *pat;
/* NOTE: without, it sometimes won't draw to some path (centered in a pixel)
* ... it won't fill some pixels! It also looks much nicer so.
* (since line-drawing is the last on the graph, no need to reset to _NONE) */
/* Not much difference to CAIRO_ANTIALIAS_DEFAULT, but recommend for LCD */
cairo_set_antialias(ctx->cr, CAIRO_ANTIALIAS_SUBPIXEL);
/* a nicer, better visible line compared to 1.0 */
cairo_set_line_width(ctx->cr, 1.25);
pat = draw_setup_cairo_color_source(ctx, gradient_vector, pcolor, pcolor_center, pcolor_end);
/* path through the centers of pixels */
x = rect.x + 0.5;
y = rect.y + 0.5;
w = rect.width;
if(grow == Right)
{
/* go through the values from old to new. Begin with the oldest. */
if(++cur_index > w - 1)
cur_index = 0;
cairo_move_to(ctx->cr, x, y - to[cur_index]);
}
else
/* on the left border: fills a pixel also when there's only one value */
cairo_move_to(ctx->cr, x - 1.0, y - to[cur_index]);
for(i = 0; i < w; i++)
{
cairo_line_to(ctx->cr, x, y - to[cur_index]);
x += 1.0;
/* cycles around the index */
if(grow == Right)
{
if(++cur_index > w - 1)
cur_index = 0;
}
else
{
if(--cur_index < 0)
cur_index = w - 1;
}
}
/* onto the right border: fills a pixel also when there's only one value */
if(grow == Right)
cairo_line_to(ctx->cr, x, y - to[(cur_index + (w - 1)) % w]);
cairo_stroke(ctx->cr);
if(pat)
cairo_pattern_destroy(pat);
/* reset line-width */
cairo_set_line_width(ctx->cr, 1.0);
}
/** Draw an image from ARGB data to a draw context.
* Data should be stored as an array of alpha, red, blue, green for each pixel
* and the array size should be w * h elements long.

19
draw.h
View file

@ -41,17 +41,6 @@ typedef enum
AlignMiddle = (1 << 5)
} alignment_t;
typedef struct vector_t vector_t;
struct vector_t
{
/** Co-ords of starting point */
int16_t x;
int16_t y;
/** Offset to starting point */
int16_t x_offset;
int16_t y_offset;
};
typedef struct area_t area_t;
struct area_t
{
@ -139,14 +128,6 @@ typedef struct
bool draw_text_context_init(draw_text_context_t *, const char *, ssize_t);
void draw_text(draw_context_t *, draw_text_context_t *, PangoEllipsizeMode, PangoWrapMode, alignment_t, alignment_t, area_t);
void draw_rectangle(draw_context_t *, area_t, float, bool, const color_t *);
void draw_rectangle_gradient(draw_context_t *, area_t, float, bool, vector_t,
const color_t *, const color_t *, const color_t *);
void draw_graph_setup(draw_context_t *);
void draw_graph(draw_context_t *, area_t, int *, int *, int, position_t, vector_t,
const color_t *, const color_t *, const color_t *);
void draw_graph_line(draw_context_t *, area_t, int *, int, position_t, vector_t,
const color_t *, const color_t *, const color_t *);
void draw_image(draw_context_t *, int, int, double, image_t *);
void draw_rotate(draw_context_t *, xcb_drawable_t, xcb_drawable_t, int, int, int, int, double, int, int);
area_t draw_text_extents(draw_text_context_t *);

View file

@ -518,12 +518,6 @@ luaA_widget_set_type(lua_State *L, widget_t *w)
case A_TK_TEXTBOX:
wc = widget_textbox;
break;
case A_TK_PROGRESSBAR:
wc = widget_progressbar;
break;
case A_TK_GRAPH:
wc = widget_graph;
break;
case A_TK_SYSTRAY:
wc = widget_systray;
break;

View file

@ -75,8 +75,6 @@ lua_class_t widget_class;
void widget_class_setup(lua_State *);
widget_constructor_t widget_textbox;
widget_constructor_t widget_progressbar;
widget_constructor_t widget_graph;
widget_constructor_t widget_systray;
widget_constructor_t widget_imagebox;

View file

@ -1,628 +0,0 @@
/*
* graph.c - a graph widget
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007-2008 Marco Candrian <mac@calmar.ws>
*
* 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 <math.h>
#include "widget.h"
#include "luaa.h"
#include "common/tokenize.h"
typedef enum
{
Bottom_Style = 0,
Top_Style,
Line_Style
} plot_style_t;
/** The plot data structure. */
typedef struct
{
/** Graph title of the plot sections */
char *title;
/** Represents a full graph */
float max_value;
/** Scale the graph */
bool scale;
/* markers... */
/** Index of current (new) value */
int index;
/** Index of the actual maximum value */
int max_index;
/** Pointer to current maximum value itself */
float current_max;
/** Draw style of according index */
plot_style_t draw_style;
/** Keeps the calculated values (line-length); */
int *lines;
/** Actual values */
float *values;
/** Color of them */
color_t color_start;
/** Color at middle of graph */
color_t pcolor_center;
/** Color at end of graph */
color_t pcolor_end;
/** Create a vertical color gradient */
bool vertical_gradient;
} plot_t;
static void
plot_delete(plot_t *g)
{
p_delete(&g->title);
p_delete(&g->lines);
p_delete(&g->values);
}
DO_ARRAY(plot_t, plot, plot_delete)
/** The private graph data structure */
typedef struct
{
/** Width of the widget */
int width;
/** Height of graph (0.0-1.0; 1.0 = height of bar) */
float height;
/** Height of the innerbox in pixels */
int box_height;
/** Size of lines-array (also innerbox-length) */
int size;
/** Background color */
color_t bg;
/** Border color */
color_t border_color;
/** Grow: Left or Right */
position_t grow;
/** Preparation/tmp array for draw_graph(); */
int *draw_from;
/** Preparation/tmp array for draw_graph(); */
int *draw_to;
/** Graph list */
plot_array_t plots;
} graph_data_t;
/** Add a plot to a graph.
* \param d The graph private data.
* \param title The plot title.
* \return A new plot.
*/
static plot_t *
graph_plot_add(graph_data_t *d, const char *title)
{
plot_t plot;
p_clear(&plot, 1);
plot.title = a_strdup(title);
plot.values = p_new(float, d->size);
plot.lines = p_new(int, d->size);
plot.max_value = 100.0;
plot.vertical_gradient = true;
xcolor_to_color(&globalconf.colors.fg, &plot.color_start);
plot_array_append(&d->plots, plot);
return &d->plots.tab[d->plots.len - 1];
}
/** Get the plot, and create one if it does not exist.
* \param d The graph private data.
* \param title The plot title.
* \return A maybe new plot.
*/
static plot_t *
graph_plot_get(graph_data_t *d, const char *title)
{
plot_t *plot;
/* check if this section is defined already */
for(int j = 0; j < d->plots.len; j++)
{
plot = &d->plots.tab[j];
if(!a_strcmp(title, plot->title))
return plot;
}
/* no plot found -> create one */
return graph_plot_add(d, title);
}
static area_t
graph_geometry(widget_t *widget, int screen)
{
area_t geometry;
graph_data_t *d = widget->data;
geometry.x = geometry.y = 0;
geometry.height = d->width;
geometry.width = d->width;
return geometry;
}
static area_t
graph_extents(lua_State *L, widget_t *widget)
{
return graph_geometry(widget, 0);
}
/** Draw a graph widget.
* \param ctx The draw context.
* \param w The widget node we are called from.
* \param offset The offset to draw at.
* \param used The already used width.
* \param p A pointer to the object we're drawing onto.
* \return The widget width.
*/
static void
graph_draw(widget_t *widget, draw_context_t *ctx,
area_t geometry, wibox_t *p)
{
int margin_top, y;
graph_data_t *d = widget->data;
area_t rectangle;
vector_t color_gradient;
if(!d->plots.len)
return;
/* box = the plot inside the rectangle */
if(!d->box_height)
d->box_height = round(ctx->height * d->height) - 2;
margin_top = round((ctx->height - (d->box_height + 2)) / 2) + geometry.y;
/* draw background */
rectangle.x = geometry.x + 1;
rectangle.y = margin_top + 1;
rectangle.width = d->size;
rectangle.height = d->box_height;
draw_rectangle(ctx, rectangle, 1.0, true, &d->bg);
/* for plot drawing */
rectangle.y = margin_top + d->box_height + 1; /* bottom left corner as starting point */
rectangle.width = d->size; /* rectangle.height is not used */
draw_graph_setup(ctx); /* setup some drawing options */
/* gradient begin either left or on the right of the rectangle */
if(d->grow == Right)
color_gradient.x = rectangle.x + rectangle.width;
else
color_gradient.x = rectangle.x;
for(int i = 0; i < d->plots.len; i++)
{
plot_t *plot = &d->plots.tab[i];
switch(plot->draw_style)
{
case Top_Style:
color_gradient.y = rectangle.y - rectangle.height;
if(plot->vertical_gradient)
{
color_gradient.x_offset = 0;
color_gradient.y_offset = rectangle.height;
}
else
{
color_gradient.y_offset = 0;
if(d->grow == Right)
color_gradient.x_offset = - rectangle.width;
else
color_gradient.x_offset = rectangle.width;
}
for(y = 0; y < d->size; y++)
{
/* reverse values (because drawing from top) */
d->draw_from[y] = d->box_height; /* i.e. no smaller value -> from top of box */
d->draw_to[y] = d->box_height - plot->lines[y]; /* i.e. on full plot -> 0 = bottom */
}
draw_graph(ctx, rectangle , d->draw_from, d->draw_to, plot->index, d->grow, color_gradient,
&plot->color_start, &plot->pcolor_center, &plot->pcolor_end);
break;
case Bottom_Style:
color_gradient.y = rectangle.y;
if(plot->vertical_gradient)
{
color_gradient.x_offset = 0;
color_gradient.y_offset = - rectangle.height;
}
else
{
color_gradient.y_offset = 0;
if(d->grow == Right)
color_gradient.x_offset = - rectangle.width;
else
color_gradient.x_offset = rectangle.width;
}
p_clear(d->draw_from, d->size);
draw_graph(ctx, rectangle, d->draw_from, plot->lines, plot->index, d->grow, color_gradient,
&plot->color_start, &plot->pcolor_center, &plot->pcolor_end);
break;
case Line_Style:
color_gradient.y = rectangle.y;
if(plot->vertical_gradient)
{
color_gradient.x_offset = 0;
color_gradient.y_offset = -rectangle.height;
}
else
{
color_gradient.y_offset = 0;
if(d->grow == Right)
color_gradient.x_offset = - rectangle.width;
else
color_gradient.x_offset = rectangle.width;
}
draw_graph_line(ctx, rectangle, plot->lines, plot->index, d->grow, color_gradient,
&plot->color_start, &plot->pcolor_center, &plot->pcolor_end);
break;
}
}
/* draw border (after line-drawing, what paints 0-values to the border) */
rectangle.x = geometry.x;
rectangle.y = margin_top;
rectangle.width = d->size + 2;
rectangle.height = d->box_height + 2;
draw_rectangle(ctx, rectangle, 1.0, false, &d->border_color);
}
/** Set various plot graph properties.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue A widget.
* \lparam A plot name.
* \lparam A table with various properties set.
*/
static int
luaA_graph_plot_properties_set(lua_State *L)
{
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
graph_data_t *d = widget->data;
float max_value;
const char *title, *buf;
size_t len;
plot_t *plot = NULL;
color_init_cookie_t reqs[3];
int i, reqs_nbr = -1;
title = luaL_checkstring(L, 2);
luaA_checktable(L, 3);
plot = graph_plot_get(d, title);
if((buf = luaA_getopt_lstring(L, 3, "fg", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&plot->color_start, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "fg_center", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&plot->pcolor_center, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "fg_end", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&plot->pcolor_end, buf, len);
plot->vertical_gradient = luaA_getopt_boolean(L, 3, "vertical_gradient", plot->vertical_gradient);
plot->scale = luaA_getopt_boolean(L, 3, "scale", plot->scale);
max_value = luaA_getopt_number(L, 3, "max_value", plot->max_value);
if(max_value != plot->max_value)
plot->max_value = plot->current_max = max_value;
if((buf = luaA_getopt_lstring(L, 3, "style", NULL, &len)))
switch (a_tokenize(buf, len))
{
case A_TK_BOTTOM:
plot->draw_style = Bottom_Style;
break;
case A_TK_LINE:
plot->draw_style = Line_Style;
break;
case A_TK_TOP:
plot->draw_style = Top_Style;
break;
default:
break;
}
for(i = 0; i <= reqs_nbr; i++)
color_init_reply(reqs[i]);
widget_invalidate_bywidget(widget);
return 0;
}
/** Add data to a plot.
* \param l The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue A widget.
* \lparam A plot name.
* \lparam A data value.
*/
static int
luaA_graph_plot_data_add(lua_State *L)
{
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
graph_data_t *d = widget->data;
plot_t *plot = NULL;
const char *title = luaL_checkstring(L, 2);
float value;
int i;
if(!d->size)
return 0;
plot = graph_plot_get(d, title);
/* assign incoming value */
value = MAX(luaL_checknumber(L, 3), 0);
if(++plot->index >= d->size) /* cycle inside the array */
plot->index = 0;
if(plot->scale) /* scale option is true */
{
plot->values[plot->index] = value;
if(value > plot->current_max) /* a new maximum value found */
{
plot->max_index = plot->index;
plot->current_max = value;
/* recalculate */
for (i = 0; i < d->size; i++)
plot->lines[i] = round(plot->values[i] * d->box_height / plot->current_max);
}
/* old max_index reached + current_max > normal, re-check/generate */
else if(plot->max_index == plot->index
&& plot->current_max > plot->max_value)
{
/* find the new max */
for(i = 0; i < d->size; i++)
if(plot->values[i] > plot->values[plot->max_index])
plot->max_index = i;
plot->current_max = MAX(plot->values[plot->max_index], plot->max_value);
/* recalculate */
for(i = 0; i < d->size; i++)
plot->lines[i] = round(plot->values[i] * d->box_height / plot->current_max);
}
else
plot->lines[plot->index] = round(value * d->box_height / plot->current_max);
}
else /* scale option is false - limit to d->box_height */
{
if(value < plot->max_value)
plot->lines[plot->index] = round(value * d->box_height / plot->max_value);
else
plot->lines[plot->index] = d->box_height;
}
widget_invalidate_bywidget(widget);
return 0;
}
/** Graph widget.
* DEPRECATED, see awful.widget.graph.
* \param L The Lua VM state.
* \param token The key token.
* \return The number of elements pushed on stack.
* \luastack
* \lfield plot_properties_set A function to set plot properties.
* \lfield plot_data_add A function to add data to a plot.
* \lfield height Graph height.
* \lfield widget Graph width.
* \lfield bg Background color.
* \lfield grow Direction to grow: left or right.
*/
static int
luaA_graph_index(lua_State *L, awesome_token_t token)
{
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
graph_data_t *d = widget->data;
switch(token)
{
case A_TK_PLOT_PROPERTIES_SET:
lua_pushcfunction(L, luaA_graph_plot_properties_set);
break;
case A_TK_PLOT_DATA_ADD:
lua_pushcfunction(L, luaA_graph_plot_data_add);
break;
case A_TK_HEIGHT:
lua_pushnumber(L, d->height);
break;
case A_TK_WIDTH:
lua_pushnumber(L, d->width);
break;
case A_TK_BORDER_COLOR:
luaA_pushcolor(L, &d->border_color);
break;
case A_TK_BG:
luaA_pushcolor(L, &d->bg);
break;
case A_TK_GROW:
switch(d->grow)
{
case Left:
lua_pushliteral(L, "left");
break;
case Right:
lua_pushliteral(L, "right");
break;
default:
return 0;
}
break;
default:
return 0;
}
return 1;
}
/** Newindex function for graph widget.
* \param L The Lua VM state.
* \param token The key token.
* \return The number of elements pushed on stack.
*/
static int
luaA_graph_newindex(lua_State *L, awesome_token_t token)
{
size_t len;
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
graph_data_t *d = widget->data;
const char *buf;
int width;
position_t pos;
color_t color;
switch(token)
{
case A_TK_HEIGHT:
d->height = luaL_checknumber(L, 3);
break;
case A_TK_WIDTH:
width = luaL_checknumber(L, 3);
if(width >= 2 && width != d->width)
{
d->width = width;
d->size = d->width - 2;
p_realloc(&d->draw_from, d->size);
p_realloc(&d->draw_to, d->size);
for(int i = 0; i < d->plots.len; i++)
{
plot_t *plot = &d->plots.tab[i];
p_realloc(&plot->values, d->size);
p_realloc(&plot->lines, d->size);
p_clear(plot->values, d->size);
p_clear(plot->lines, d->size);
plot->index = 0;
plot->current_max = 0;
plot->max_index = 0;
}
}
else
return 0;
break;
case A_TK_BG:
if((buf = luaL_checklstring(L, 3, &len)))
{
if(color_init_reply(color_init_unchecked(&color, buf, len)))
d->bg = color;
else
return 0;
}
break;
case A_TK_BORDER_COLOR:
if((buf = luaL_checklstring(L, 3, &len)))
{
if(color_init_reply(color_init_unchecked(&color, buf, len)))
d->border_color = color;
else
return 0;
}
break;
case A_TK_GROW:
buf = luaL_checklstring(L, 3, &len);
switch((pos = position_fromstr(buf, len)))
{
case Left:
case Right:
d->grow = pos;
break;
default:
return 0;
}
break;
default:
return 0;
}
widget_invalidate_bywidget(widget);
return 0;
}
/** Destroy definitively a graph widget.
* \param widget Who slay.
*/
static void
graph_destructor(widget_t *widget)
{
graph_data_t *d = widget->data;
plot_array_wipe(&d->plots);
p_delete(&d->draw_from);
p_delete(&d->draw_to);
p_delete(&d);
}
/** Create a brand new graph.
* \param w The widget to initialize.
* \return The same widget.
*/
widget_t *
widget_graph(widget_t *w)
{
luaA_deprecate(globalconf.L, "awful.widget.graph");
w->draw = graph_draw;
w->index = luaA_graph_index;
w->newindex = luaA_graph_newindex;
w->destructor = graph_destructor;
w->extents = graph_extents;
graph_data_t *d = w->data = p_new(graph_data_t, 1);
d->width = 80;
d->height = 0.80;
d->size = d->width - 2;
d->grow = Left;
d->draw_from = p_new(int, d->size);
d->draw_to = p_new(int, d->size);
xcolor_to_color(&globalconf.colors.bg, &d->bg);
xcolor_to_color(&globalconf.colors.fg, &d->border_color);
return w;
}
/* This is used for building documentation. */
static const struct luaL_reg awesome_graph_meta[] __attribute__ ((unused)) =
{
{ "plot_properties_set", luaA_graph_plot_properties_set },
{ "plot_data_add", luaA_graph_plot_data_add },
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80

View file

@ -1,680 +0,0 @@
/*
* progressbar.c - progressbar widget
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007-2008 Marco Candrian <mac@calmar.ws>
*
* 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 "widget.h"
#include "luaa.h"
#include "common/tokenize.h"
/** Progressbar bar data structure */
typedef struct
{
/** Title of the data/bar */
char *title;
/** These or lower values won't fill the bar at all*/
float min_value;
/** These or higher values fill the bar fully */
float max_value;
/** Pointer to value */
float value;
/** Reverse filling */
bool reverse;
/** Foreground color */
color_t fg;
/** Foreground color of turned-off ticks */
color_t fg_off;
/** Foreground color when bar is half-full */
color_t fg_center;
/** Foreground color when bar is full */
color_t fg_end;
/** Background color */
color_t bg;
/** Border color */
color_t border_color;
} bar_t;
/** Delete a bar.
* \param bar The bar to annihilate.
*/
static void
bar_delete(bar_t *bar)
{
p_delete(&bar->title);
}
DO_ARRAY(bar_t, bar, bar_delete)
/** Progressbar private data structure */
typedef struct
{
/** Width of the data_items */
int width;
/** 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;
/** 90 Degree's turned */
bool vertical;
/** Height 0-1, where 1.0 is height of bar */
float height;
/** The bars */
bar_array_t bars;
} progressbar_data_t;
/** Add a new bar to the progressbar private data structure.
* \param bars The bar array.
* \param title The bar title.
* \return The new bar.
*/
static bar_t *
progressbar_bar_add(bar_array_t *bars, const char *title)
{
bar_t bar;
p_clear(&bar, 1);
bar.title = a_strdup(title);
bar.max_value = 100.0;
xcolor_to_color(&globalconf.colors.fg, &bar.fg);
xcolor_to_color(&globalconf.colors.bg, &bar.bg);
xcolor_to_color(&globalconf.colors.bg, &bar.fg_off);
xcolor_to_color(&globalconf.colors.fg, &bar.border_color);
/* append the bar in the list */
bar_array_append(bars, bar);
return &bars->tab[bars->len - 1];
}
/** Get the bar, and create one if it does not exist.
* \param bars The bar array.
* \param title The bar title.
* \return A maybe new bar.
*/
static bar_t *
progressbar_bar_get(bar_array_t *bars, const char *title)
{
bar_t *bar;
/* check if this section is defined already */
for(int j = 0; j < bars->len; j++)
{
bar = &bars->tab[j];
if(!a_strcmp(title, bar->title))
return bar;
}
/* no bar found -> create one */
return progressbar_bar_add(bars, title);
}
static area_t
progressbar_geometry(widget_t *widget, int screen)
{
area_t geometry;
progressbar_data_t *d = widget->data;
if(d->vertical)
{
int pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->bars.len
- d->gap * (d->bars.len - 1)) / d->bars.len);
geometry.width = d->bars.len * (pb_width + 2 * (d->border_width + d->border_padding)
+ d->gap) - d->gap;
}
else
{
int pb_width = d->width - 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap)
{
int unit = (pb_width + d->ticks_gap) / d->ticks_count;
pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */
}
geometry.width = pb_width + 2 * (d->border_width + d->border_padding);
}
geometry.height = geometry.width;
geometry.x = geometry.y = 0;
return geometry;
}
static area_t
progressbar_extents(lua_State *L, widget_t *widget)
{
return progressbar_geometry(widget, 0);
}
/** Draw a progressbar.
* \param ctx The draw context.
* \param w The widget node we're drawing for.
* \param offset Offset to draw at.
* \param used Space already used.
* \param object The object pointer we're drawing onto.
* \return The width used.
*/
static void
progressbar_draw(widget_t *widget, draw_context_t *ctx, area_t geometry, wibox_t *p)
{
/* pb_.. values points to the widget inside a potential border */
int values_ticks, pb_x, pb_y, pb_height, pb_width, pb_progress, pb_offset;
int unit = 0; /* tick + gap */
area_t rectangle;
vector_t color_gradient;
progressbar_data_t *d = widget->data;
if(!d->bars.len)
return;
/* 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 is drawn with fg colors, the 'full' with bg-color
*
* ticks:
* 1. round the values to a full tick accordingly
* 2. finally draw the gaps
*/
pb_x = geometry.x + d->border_width + d->border_padding;
pb_offset = 0;
if(d->vertical)
{
pb_width = (int) ((d->width - 2 * (d->border_width + d->border_padding) * d->bars.len
- d->gap * (d->bars.len - 1)) / d->bars.len);
/** \todo maybe prevent to calculate that stuff below over and over again
* (->use static-values) */
pb_height = (int) (ctx->height * d->height + 0.5)
- 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap)
{
/* '+ d->ticks_gap' because a unit includes a ticks + ticks_gap */
unit = (pb_height + d->ticks_gap) / d->ticks_count;
pb_height = unit * d->ticks_count - d->ticks_gap;
}
pb_y = geometry.y + ((int) (ctx->height * (1 - d->height)) / 2)
+ d->border_width + d->border_padding;
for(int i = 0; i < d->bars.len; i++)
{
bar_t *bar = &d->bars.tab[i];
if(d->ticks_count && d->ticks_gap)
{
values_ticks = (int)(d->ticks_count * (bar->value - bar->min_value)
/ (bar->max_value - bar->min_value) + 0.5);
if(values_ticks)
pb_progress = values_ticks * unit - d->ticks_gap;
else
pb_progress = 0;
}
else
/* e.g.: min = 50; max = 56; 53 should show 50% graph
* (53(val) - 50(min) / (56(max) - 50(min) = 3 / 5 = 0.5 = 50%
* round that ( + 0.5 and (int)) and finally multiply with height
*/
pb_progress = (int) (pb_height * (bar->value - bar->min_value)
/ (bar->max_value - bar->min_value) + 0.5);
if(d->border_width)
{
/* border rectangle */
rectangle.x = pb_x + pb_offset - d->border_width - d->border_padding;
rectangle.y = pb_y - d->border_width - d->border_padding;
rectangle.width = pb_width + 2 * (d->border_padding + d->border_width);
rectangle.height = pb_height + 2 * (d->border_padding + d->border_width);
if(d->border_padding)
draw_rectangle(ctx, rectangle, 1.0, true, &bar->bg);
draw_rectangle(ctx, rectangle, d->border_width, false, &bar->border_color);
}
color_gradient.x = pb_x;
color_gradient.x_offset = 0;
color_gradient.y = pb_y;
/* new value/progress in px + pattern setup */
if(bar->reverse)
{
/* invert: top with bottom part */
pb_progress = pb_height - pb_progress;
color_gradient.y_offset = pb_height;
}
else
{
/* bottom to top */
color_gradient.y += pb_height;
color_gradient.y_offset = - pb_height;
}
/* bottom part */
if(pb_progress > 0)
{
rectangle.x = pb_x + pb_offset;
rectangle.y = pb_y + pb_height - pb_progress;
rectangle.width = pb_width;
rectangle.height = pb_progress;
/* fg color */
if(bar->reverse)
draw_rectangle(ctx, rectangle, 1.0, true, &bar->fg_off);
else
draw_rectangle_gradient(ctx, rectangle, 1.0, true, color_gradient,
&bar->fg, &bar->fg_center, &bar->fg_end);
}
/* top part */
if(pb_height - pb_progress > 0) /* not filled area */
{
rectangle.x = pb_x + pb_offset;
rectangle.y = pb_y;
rectangle.width = pb_width;
rectangle.height = pb_height - pb_progress;
/* bg color */
if(bar->reverse)
draw_rectangle_gradient(ctx, rectangle, 1.0, true, color_gradient,
&bar->fg, &bar->fg_center, &bar->fg_end);
else
draw_rectangle(ctx, rectangle, 1.0, true, &bar->fg_off);
}
/* 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, &bar->bg);
}
pb_offset += pb_width + d->gap + 2 * (d->border_width + d->border_padding);
}
}
else /* a horizontal progressbar */
{
pb_width = d->width - 2 * (d->border_width + d->border_padding);
if(d->ticks_count && d->ticks_gap)
{
unit = (pb_width + d->ticks_gap) / d->ticks_count;
pb_width = unit * d->ticks_count - d->ticks_gap; /* rounded to match ticks... */
}
pb_height = (int) ((ctx->height * d->height
- d->bars.len * 2 * (d->border_width + d->border_padding)
- (d->gap * (d->bars.len - 1))) / d->bars.len + 0.5);
pb_y = geometry.y + ((int) (ctx->height * (1 - d->height)) / 2)
+ d->border_width + d->border_padding;
for(int i = 0; i < d->bars.len; i++)
{
bar_t *bar = &d->bars.tab[i];
if(d->ticks_count && d->ticks_gap)
{
/* +0.5 rounds up ticks -> turn on a tick when half of it is reached */
values_ticks = (int)(d->ticks_count * (bar->value - bar->min_value)
/ (bar->max_value - bar->min_value) + 0.5);
if(values_ticks)
pb_progress = values_ticks * unit - d->ticks_gap;
else
pb_progress = 0;
}
else
pb_progress = (int) (pb_width * (bar->value - bar->min_value)
/ (bar->max_value - bar->min_value) + 0.5);
if(d->border_width)
{
/* border rectangle */
rectangle.x = pb_x - d->border_width - d->border_padding;
rectangle.y = pb_y + pb_offset - d->border_width - d->border_padding;
rectangle.width = pb_width + 2 * (d->border_padding + d->border_width);
rectangle.height = pb_height + 2 * (d->border_padding + d->border_width);
if(d->border_padding)
draw_rectangle(ctx, rectangle, 1.0, true, &bar->bg);
draw_rectangle(ctx, rectangle, d->border_width, false, &bar->border_color);
}
color_gradient.y = pb_y;
color_gradient.y_offset = 0;
color_gradient.x = pb_x;
/* new value/progress in px + pattern setup */
if(bar->reverse)
{
/* reverse: right to left */
pb_progress = pb_width - pb_progress;
color_gradient.x += pb_width;
color_gradient.x_offset = - pb_width;
}
else
/* left to right */
color_gradient.x_offset = pb_width;
/* left part */
if(pb_progress > 0)
{
rectangle.x = pb_x;
rectangle.y = pb_y + pb_offset;
rectangle.width = pb_progress;
rectangle.height = pb_height;
/* fg color */
if(bar->reverse)
draw_rectangle(ctx, rectangle, 1.0, true, &bar->fg_off);
else
draw_rectangle_gradient(ctx, rectangle, 1.0, true, color_gradient,
&bar->fg, &bar->fg_center, &bar->fg_end);
}
/* right part */
if(pb_width - pb_progress > 0)
{
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(bar->reverse)
draw_rectangle_gradient(ctx, rectangle, 1.0, true, color_gradient,
&bar->fg, &bar->fg_center, &bar->fg_end);
else
draw_rectangle(ctx, rectangle, 1.0, true, &bar->fg_off);
}
/* 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, &bar->bg);
}
pb_offset += pb_height + d->gap + 2 * (d->border_width + d->border_padding);
}
}
}
/** Set various progressbar bars properties:
* \param L The Lua VM state.
* \return The number of elements pushed on the stack.
* \luastack
* \lvalue A widget.
* \lparam A bar name.
* \lparam A table with keys as properties names.
*/
static int
luaA_progressbar_bar_properties_set(lua_State *L)
{
size_t len;
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
const char *buf, *title = luaL_checkstring(L, 2);
bar_t *bar;
progressbar_data_t *d = widget->data;
color_init_cookie_t reqs[6];
int i, reqs_nbr = -1;
luaA_checktable(L, 3);
bar = progressbar_bar_get(&d->bars, title);
if((buf = luaA_getopt_lstring(L, 3, "fg", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&bar->fg, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "fg_off", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&bar->fg_off, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "bg", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&bar->bg, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "border_color", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&bar->border_color, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "fg_center", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&bar->fg_center, buf, len);
if((buf = luaA_getopt_lstring(L, 3, "fg_end", NULL, &len)))
reqs[++reqs_nbr] = color_init_unchecked(&bar->fg_end, buf, len);
bar->min_value = luaA_getopt_number(L, 3, "min_value", bar->min_value);
/* hack to prevent max_value beeing less than min_value
* and also preventing a division by zero when both are equal */
if(bar->max_value <= bar->min_value)
bar->max_value = bar->max_value + 0.0001;
/* force a actual value into the newly possible range */
if(bar->value < bar->min_value)
bar->value = bar->min_value;
bar->max_value = luaA_getopt_number(L, 3, "max_value", bar->max_value);
if(bar->min_value >= bar->max_value)
bar->min_value = bar->max_value - 0.0001;
if(bar->value > bar->max_value)
bar->value = bar->max_value;
bar->reverse = luaA_getopt_boolean(L, 3, "reverse", bar->reverse);
for(i = 0; i <= reqs_nbr; i++)
color_init_reply(reqs[i]);
widget_invalidate_bywidget(widget);
return 0;
}
/** Add a value to a progressbar bar.
* \param L The Lua VM state.
* \return The number of elements pushed on the stack.
* \luastack
* \lvalue A widget.
* \lparam A bar name.
* \lparam A data value.
*/
static int
luaA_progressbar_bar_data_add(lua_State *L)
{
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
const char *title = luaL_checkstring(L, 2);
progressbar_data_t *d = widget->data;
bar_t *bar;
bar = progressbar_bar_get(&d->bars, title);
bar->value = luaL_checknumber(L, 3);
bar->value = MAX(bar->min_value, MIN(bar->max_value, bar->value));
widget_invalidate_bywidget(widget);
return 0;
}
/** Progressbar widget.
* DEPRECATED, see awful.widget.progressbar.
* \param L The Lua VM state.
* \param token The key token.
* \return The number of elements pushed on the stack.
* \luastack
* \lfield bar_properties_set Set the properties of a bar.
* \lfield bar_data_add Add data to a bar.
* \lfield gap Gap betweens bars.
* \lfield ticks_gap Gap between ticks.
* \lfield ticks_count Number of ticks.
* \lfield border_padding Border padding.
* \lfield border_width Border width.
* \lfield width Bars width.
* \lfield height Bars height.
* \lfield vertical True: draw bar vertically, false: horizontally.
*/
static int
luaA_progressbar_index(lua_State *L, awesome_token_t token)
{
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
progressbar_data_t *d = widget->data;
switch(token)
{
case A_TK_BAR_PROPERTIES_SET:
lua_pushcfunction(L, luaA_progressbar_bar_properties_set);
break;
case A_TK_BAR_DATA_ADD:
lua_pushcfunction(L, luaA_progressbar_bar_data_add);
break;
case A_TK_GAP:
lua_pushnumber(L, d->gap);
break;
case A_TK_TICKS_GAP:
lua_pushnumber(L, d->ticks_gap);
break;
case A_TK_TICKS_COUNT:
lua_pushnumber(L, d->ticks_count);
break;
case A_TK_BORDER_PADDING:
lua_pushnumber(L, d->border_padding);
break;
case A_TK_BORDER_WIDTH:
lua_pushnumber(L, d->border_width);
break;
case A_TK_WIDTH:
lua_pushnumber(L, d->width);
break;
case A_TK_HEIGHT:
lua_pushnumber(L, d->height);
break;
case A_TK_VERTICAL:
lua_pushboolean(L, d->vertical);
break;
default:
return 0;
}
return 1;
}
/** Newindex function for progressbar.
* \param L The Lua VM state.
* \param token The key token.
* \return The number of elements pushed on the stack.
*/
static int
luaA_progressbar_newindex(lua_State *L, awesome_token_t token)
{
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
progressbar_data_t *d = widget->data;
switch(token)
{
case A_TK_GAP:
d->gap = luaL_checknumber(L, 3);
break;
case A_TK_TICKS_COUNT:
d->ticks_count = luaL_checknumber(L, 3);
break;
case A_TK_TICKS_GAP:
d->ticks_gap = luaL_checknumber(L, 3);
break;
case A_TK_BORDER_PADDING:
d->border_padding = luaL_checknumber(L, 3);
break;
case A_TK_BORDER_WIDTH:
d->border_width = luaL_checknumber(L, 3);
break;
case A_TK_WIDTH:
d->width = luaL_checknumber(L, 3);
break;
case A_TK_HEIGHT:
d->height = luaL_checknumber(L, 3);
break;
case A_TK_VERTICAL:
d->vertical = luaA_checkboolean(L, 3);
break;
default:
return 0;
}
widget_invalidate_bywidget(widget);
return 0;
}
/** Destroy a progressbar.
* \param widget The widget to kill.
*/
static void
progressbar_destructor(widget_t *widget)
{
progressbar_data_t *d = widget->data;
bar_array_wipe(&d->bars);
p_delete(&d);
}
/** Create a new progressbar.
* \param w The widget to initialize.
* \return A brand new progressbar.
*/
widget_t *
widget_progressbar(widget_t *w)
{
luaA_deprecate(globalconf.L, "awful.widget.progressbar");
w->draw = progressbar_draw;
w->index = luaA_progressbar_index;
w->newindex = luaA_progressbar_newindex;
w->destructor = progressbar_destructor;
w->extents = progressbar_extents;
progressbar_data_t *d = w->data = p_new(progressbar_data_t, 1);
d->height = 0.80;
d->width = 80;
d->ticks_gap = 1;
d->border_width = 1;
d->gap = 2;
return w;
}
/* This is used for building documentation. */
static const struct luaL_reg awesome_progressbar_meta[] __attribute__ ((unused)) =
{
{ "bar_properties_set", luaA_progressbar_bar_properties_set },
{ "bar_data_add", luaA_progressbar_bar_data_add },
};
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80