widget: new widget index method

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2008-06-25 17:47:51 +02:00
parent 4508836133
commit 094d0ebc50
12 changed files with 829 additions and 820 deletions

View File

@ -51,172 +51,6 @@ The current list of available widget is:
Each widget as its own set of properties, described below, that can bet modified with the set()
method.
PROGRESSBAR
~~~~~~~~~~~
A progressbar widget can contain several bars, so some properties need a data section,
that means a title for the bar. For example, if you want to feed data to the `memory' bar
you want to do mywidget:set("data", "memory 100"), where memory will be the data section.
Using a new data section name will automatically create a new bar.
The following properties require a data section before the value:
*data*::
Feed with data.
*fg*::
Foreground color.
*fg_off*::
Color of unfilled area of bar.
*bg*::
Background color (between ticks; border_padding space).
*bordercolor*::
Border color.
*fg_center*::
Foreground center color.
*fg_end*::
Foreground end color.
*min_value*::
Minimum value. This or lower values, draw a 0% bar.
*max_value*::
Maximum value. This or higher values, draw a 100% bar.
*reverse*::
True to draw reverse.
The following properties do not require a data section before the value and applies to all bars inside
the widget:
*gap*::
Gap between borders.
*ticks_count*::
The number of ticks.
*ticks_gap*::
The gap between ticks.
*border_padding*::
The padding inside the border.
*border_width*::
The border width.
*width*::
The widget width.
*height*::
The widget height.
*vertical*::
If \'true\', bars are vertically aligned. If \'false\', horizontally.
GRAPH
~~~~~
A graph widget can display several data-graphs inside its widget-border. Some
properties need a data section, that means a title for the incoming data. For
example, if you want to feed \'mymemory\' data, you want to do
mywidget:set("data", "mymemory 100").
The following properties require a data section before the value:
*data*::
Feed with data.
*fg*::
Foreground color.
*fg_center*::
Foreground center color.
*fg_end*::
Foreground end color.
*vertical_gradient*::
If \'true\', colorgradient shall be applied vertically.
*max_value*::
Maximum value. Bigger values gets truncated, unless \'scale\' is true.
*scale*::
Scales the graph acccording to incoming values bigger than \'max_value\'.
*draw_style*::
\'bottom\', \'top\' or \'line\'.
The following properties do not require a data section before the value:
*width*::
The widget width.
*height*::
The widget height.
*bg*::
Background color.
*bordercolor*::
Border color.
*grow*::
\'left\' or \'right\'. E.g. \'right\' means new values get added on the right of the widget.
TAGLIST
~~~~~~~
A taglist widget displays available tags and their state.
*text_normal*::
Text to display on normal clients. \'<title/>\' substitutes the tag's title.
*text_focus*::
Text to display on the focused client. \'<title/>\' gets substituted by the tag's title.
*text_urgent*::
Text to display on urgent clients. \'<title/>\' gets substituted by the tag's title.
*show_empty*::
\'true\' or \'false\'. If \'false\', empty tags won't get displayed. Selected tags are always displayed so.
TASKLIST
~~~~~~~~
A tasklist widget displays the titles of clients according to the \'show\' setting.
*show*::
\'tags\', \'focus\' or \'all\'. E.g. \'tags\' shows only clients of currently selected tags.
*text_normal*::
Text to display on normal clients. \'<title/>\' gets substituted by the client's title.
*text_focus*::
Text to display on the focused client. \'<title/>\' gets substituted by the client's title.
*text_urgent*::
Text to display on urgent clients. \'<title/>\' gets substituted by the client's title.
*show_icons*::
\'true\' or \'false\'. Set to \'true\' if client's icon (if one is avaiable) shall be displayed.
TEXTBOX
~~~~~~~
A textbox displays text.
*width*::
Width of the widget.
*text*::
Text to display.
SEE ALSO
--------
awesome(1) awesome-client(1)

View File

@ -84,24 +84,24 @@ mytaglist:mouse_add(mouse.new({}, 3, function (object, tag) tag:view(not tag:iss
mytaglist:mouse_add(mouse.new({ modkey }, 3, function (object, tag) awful.client.toggletag(tag) end))
mytaglist:mouse_add(mouse.new({ }, 4, awful.tag.viewnext))
mytaglist:mouse_add(mouse.new({ }, 5, awful.tag.viewprev))
mytaglist:set("text_focus", "<bg color='"..bg_focus.."'/> <span color='"..fg_focus.."'><title/></span> ")
mytaglist:text_set({ ["focus"] = "<bg color='"..bg_focus.."'/> <span color='"..fg_focus.."'><title/></span> " })
-- Create a tasklist widget
mytasklist = widget.new({ type = "tasklist", name = "mytasklist" })
mytasklist:mouse_add(mouse.new({ }, 1, function (object, c) c:focus_set(); c:raise() end))
mytasklist:mouse_add(mouse.new({ }, 4, function () awful.client.focus(1) end))
mytasklist:mouse_add(mouse.new({ }, 5, function () awful.client.focus(-1) end))
mytasklist:set("text_focus", "<bg color='"..bg_focus.."'/> <span color='"..fg_focus.."'><title/></span> ")
mytasklist:text_set({ ["focus"] = "<bg color='"..bg_focus.."'/> <span color='"..fg_focus.."'><title/></span> " })
-- Create a textbox widget
mytextbox = widget.new({ type = "textbox", name = "mytextbox", align = "right" })
-- Set the default text in textbox
mytextbox:set("text", "<b><small> awesome " .. AWESOME_VERSION .. " </small></b>")
mytextbox:text_set("<b><small> awesome " .. AWESOME_VERSION .. " </small></b>")
mypromptbox = widget.new({ type = "textbox", name = "mypromptbox", align = "left" })
-- Create an iconbox widget
myiconbox = widget.new({ type = "textbox", name = "myiconbox", align = "left" })
myiconbox:set("text", "<bg image=\"@AWESOME_ICON_PATH@/awesome16.png\" resize=\"true\"/>")
myiconbox:text_set("<bg image=\"@AWESOME_ICON_PATH@/awesome16.png\" resize=\"true\"/>")
-- Create a systray
mysystray = widget.new({ type = "systray", name = "mysystray", align = "right" })
@ -115,7 +115,7 @@ for s = 1, screen.count() do
mylayoutbox[s]:mouse_add(mouse.new({ }, 3, function () awful.layout.inc(layouts, -1) end))
mylayoutbox[s]:mouse_add(mouse.new({ }, 4, function () awful.layout.inc(layouts, 1) end))
mylayoutbox[s]:mouse_add(mouse.new({ }, 5, function () awful.layout.inc(layouts, -1) end))
mylayoutbox[s]:set("text", "<bg image=\"@AWESOME_ICON_PATH@/layouts/tilew.png\" resize=\"true\"/>")
mylayoutbox[s]:text_set("<bg image=\"@AWESOME_ICON_PATH@/layouts/tilew.png\" resize=\"true\"/>")
end
-- Create a statusbar for each screen and add it
@ -334,7 +334,7 @@ end
-- (tag switch, new client, etc)
function hook_arrange(screen)
local layout = awful.layout.get(screen)
mylayoutbox[screen]:set("text", "<bg image=\"@AWESOME_ICON_PATH@/layouts/" .. layout .. "w.png\" resize=\"true\"/>")
mylayoutbox[screen]:text_set("<bg image=\"@AWESOME_ICON_PATH@/layouts/" .. layout .. "w.png\" resize=\"true\"/>")
-- Uncomment if you want mouse warping
--[[
@ -356,9 +356,9 @@ end
-- Hook called every second
function hook_timer ()
-- For unix time_t lovers
mytextbox:set("text", " " .. os.time() .. " time_t ")
mytextbox:text_set(" " .. os.time() .. " time_t ")
-- Otherwise use:
-- mytextbox:set("text", " " .. os.date() .. " ")
-- mytextbox:text_set(" " .. os.date() .. " ")
end
-- Set up some hooks

View File

@ -2,60 +2,43 @@
align
all
auto
bg
border_padding
border_width
bordercolor
bar_data_add
bar_properties_set
bottom
bottomleft
bottomright
center
color
data
draw_style
fg
fg_center
fg_end
fg_off
flex
focus
gap
grow
height
image
left
line
max_value
min_value
mouse_add
mouse_remove
name_get
name_set
on
plot_data_add
plot_properties_set
properties_set
resize
reverse
right
scale
set
shadow
shadow_offset
show
show_empty
show_icons
show_set
showempty_set
showicons_set
tags
text
text_focus
text_normal
text_urgent
ticks_count
ticks_gap
text_set
top
topleft
topright
true
vertical
vertical_gradient
visible_get
visible_set
width
width_set
yes

69
dbus.c
View File

@ -35,71 +35,6 @@ static DBusError err;
static DBusConnection *dbus_connection = NULL;
ev_io dbusio = { .fd = -1 };
/** Check a dbus object path format and its number of element.
* \param path The path.
* \param nelem The number of element it should have.
* \return true if the path is ok, false otherwise.
*/
static bool
a_dbus_path_check(char **path, int nelem)
{
int i;
for(i = 0; path[i]; i++);
if(i != nelem)
return false;
return (!a_strcmp(path[0], "org")&& !a_strcmp(path[1], "awesome"));
}
/** Process widget.set method call.
* \param req The dbus message.
*/
static void
a_dbus_process_widget_set(DBusMessage *req)
{
char *arg, **path;
int i;
DBusMessageIter iter;
widget_t *widget;
widget_tell_status_t status;
if(!dbus_message_get_path_decomposed(req, &path)
|| !a_dbus_path_check(path, 6)
|| a_strcmp(path[2], "widget")
|| a_strcmp(path[4], "property"))
{
warn("invalid object path.");
dbus_error_free(&err);
return;
}
if(!dbus_message_iter_init(req, &iter))
{
warn("message has no argument: %s", err.message);
dbus_error_free(&err);
return;
}
else if(DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&iter))
{
warn("argument must be a string");
dbus_error_free(&err);
return;
}
else
dbus_message_iter_get_basic(&iter, &arg);
if(!(widget = widget_getbyname(path[3])))
return warn("no such widget: %s.", path[3]);
status = widget->tell(widget, path[5], arg);
widget_tell_managestatus(widget, status, path[5]);
for(i = 0; path[i]; i++)
p_delete(&path[i]);
p_delete(&path);
}
static void
a_dbus_process_requests(EV_P_ ev_io *w, int revents)
{
@ -117,9 +52,7 @@ a_dbus_process_requests(EV_P_ ev_io *w, int revents)
break;
if(dbus_message_is_method_call(msg, "org.awesome.widget", "set"))
a_dbus_process_widget_set(msg);
else if(dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
if(dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
{
a_dbus_cleanup();
dbus_message_unref(msg);

View File

@ -69,18 +69,6 @@ typedef widget_t *(widget_constructor_t)(alignment_t);
typedef void (widget_destructor_t)(widget_t *);
typedef struct awesome_t awesome_t;
/** Widget tell status code */
typedef enum
{
WIDGET_NOERROR = 0,
WIDGET_ERROR,
WIDGET_ERROR_NOVALUE,
WIDGET_ERROR_CUSTOM,
WIDGET_ERROR_FORMAT_FONT,
WIDGET_ERROR_FORMAT_COLOR,
WIDGET_ERROR_FORMAT_SECTION
} widget_tell_status_t;
/** Mouse buttons bindings */
struct button_t
{
@ -112,8 +100,8 @@ struct widget_t
widget_destructor_t *destructor;
/** Draw function */
int (*draw)(draw_context_t *, int, widget_node_t *, int, int, void *);
/** Update function */
widget_tell_status_t (*tell)(widget_t *, const char *, const char *);
/** Index function */
int (*index)(lua_State *);
/** ButtonPressedEvent handler */
void (*button_press)(widget_node_t *, xcb_button_press_event_t *, int, void *, awesome_type_t);
/** Alignement */

108
widget.c
View File

@ -2,7 +2,6 @@
* widget.c - widget managing
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
*
* 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
@ -58,26 +57,6 @@ widget_calculate_offset(int barwidth, int widgetwidth, int offset, int alignment
return barwidth - offset - widgetwidth;
}
/** Find a widget on a screen by its name.
* \param name The widget name.
* \return A widget pointer.
*/
widget_t *
widget_getbyname(const char *name)
{
widget_node_t *widget;
statusbar_t *sb;
int screen;
for(screen = 0; screen < globalconf.screens_info->nscreen; screen++)
for(sb = globalconf.screens[screen].statusbar; sb; sb = sb->next)
for(widget = sb->widgets; widget; widget = widget->next)
if(!a_strcmp(name, widget->widget->name))
return widget->widget;
return NULL;
}
/** Common function for button press event on widget.
* It will look into configuration to find the callback function to call.
* \param w The widget node.
@ -103,22 +82,6 @@ widget_common_button_press(widget_node_t *w,
}
}
/** Common tell function for widget, which only warn user that widget
* cannot be told anything.
* \param widget The widget.
* \param property Unused argument.
* \param new_value Unused argument.
* \return The status of the command, which is always an error in this case.
*/
static widget_tell_status_t
widget_common_tell(widget_t *widget,
const char *property __attribute__ ((unused)),
const char *new_value __attribute__ ((unused)))
{
warn("%s widget does not accept commands.", widget->name);
return WIDGET_ERROR_CUSTOM;
}
/** Render a list of widgets.
* \param wnode The list of widgets.
* \param ctx The draw context where to render.
@ -238,7 +201,6 @@ void
widget_common_new(widget_t *widget)
{
widget->align = AlignLeft;
widget->tell = widget_common_tell;
widget->button_press = widget_common_button_press;
}
@ -269,7 +231,7 @@ widget_invalidate_cache(int screen, int flags)
* \todo Probably needs more optimization.
* \param widget The widget to look for.
*/
static void
void
widget_invalidate_bywidget(widget_t *widget)
{
int screen;
@ -371,67 +333,6 @@ luaA_widget_mouse_remove(lua_State *L)
return 0;
}
/** Do what should be done with a widget_tell_status_t for a widget.
* \param widget The widget.
* \param status The status returned by the tell function of the widget.
* \param property The property updated.
*/
void
widget_tell_managestatus(widget_t *widget, widget_tell_status_t status, const char *property)
{
switch(status)
{
case WIDGET_ERROR:
warn("error changing property %s of widget %s",
property, widget->name);
break;
case WIDGET_ERROR_NOVALUE:
warn("error changing property %s of widget %s, no value given",
property, widget->name);
break;
case WIDGET_ERROR_FORMAT_FONT:
warn("error changing property %s of widget %s, must be a valid font",
property, widget->name);
break;
case WIDGET_ERROR_FORMAT_COLOR:
warn("error changing property %s of widget %s, must be a valid color",
property, widget->name);
break;
case WIDGET_ERROR_FORMAT_SECTION:
warn("error changing property %s of widget %s, section/title not found",
property, widget->name);
break;
case WIDGET_NOERROR:
widget_invalidate_bywidget(widget);
break;
case WIDGET_ERROR_CUSTOM:
break;
}
}
/** Set a widget property. Each widget type has its own set of property.
* \param L The Lua VM state.
*
* \luastack
* \lvalue A widget.
* \lparam The property name.
* \lparam The property value.
*/
static int
luaA_widget_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
const char *property, *value;
widget_tell_status_t status;
property = luaL_checkstring(L, 2);
value = luaL_checkstring(L, 3);
status = (*widget)->tell(*widget, property, value);
widget_tell_managestatus(*widget, status, property);
return 0;
}
/** Convert a widget into a printable string.
* \param L The Lua VM state.
*
@ -513,6 +414,7 @@ luaA_widget_visible_get(lua_State *L)
static int
luaA_widget_index(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
size_t len;
const char *str = luaL_checklstring(L, 2, &len);
@ -524,9 +426,6 @@ luaA_widget_index(lua_State *L)
case A_TK_MOUSE_REMOVE:
lua_pushcfunction(L, luaA_widget_mouse_remove);
return 1;
case A_TK_SET:
lua_pushcfunction(L, luaA_widget_set);
return 1;
case A_TK_NAME_SET:
lua_pushcfunction(L, luaA_widget_name_set);
return 1;
@ -540,6 +439,8 @@ luaA_widget_index(lua_State *L)
lua_pushcfunction(L, luaA_widget_visible_get);
return 1;
default:
if((*widget)->index)
return (*widget)->index(L);
return 0;
}
}
@ -553,7 +454,6 @@ const struct luaL_reg awesome_widget_meta[] =
{
{ "mouse_add", luaA_widget_mouse_add },
{ "mouse_remove", luaA_widget_mouse_remove },
{ "set", luaA_widget_set },
{ "name_set", luaA_widget_name_set },
{ "name_get", luaA_widget_name_get },
{ "visible_set", luaA_widget_visible_set },

View File

@ -2,7 +2,6 @@
* widget.h - widget managing header
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
*
* 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
@ -33,12 +32,12 @@
void widget_invalidate_cache(int, int);
int widget_calculate_offset(int, int, int, int);
void widget_common_new(widget_t *);
widget_t * widget_getbyname(const char *);
void widget_tell_managestatus(widget_t *, widget_tell_status_t, const char *);
void widget_render(widget_node_t *, draw_context_t *, xcb_gcontext_t, xcb_drawable_t, int, position_t, int, int, void *);
int luaA_widget_userdata_new(lua_State *, widget_t *);
void widget_invalidate_bywidget(widget_t *);
widget_constructor_t taglist_new;
widget_constructor_t textbox_new;
widget_constructor_t progressbar_new;

View File

@ -34,13 +34,14 @@ typedef enum
Bottom_Style = 0,
Top_Style,
Line_Style
} draw_style_t;
} plot_style_t;
typedef struct graph_t graph_t;
typedef struct plot_t plot_t;
struct graph_t
/** The plot data structure. */
struct plot_t
{
/** Grapht title of the data sections */
/** Grapht title of the plot sections */
char *title;
/** Represents a full graph */
float max_value;
@ -55,7 +56,7 @@ struct graph_t
/** Pointer to current maximum value itself */
float current_max;
/** Draw style of according index */
draw_style_t draw_style;
plot_style_t draw_style;
/** Keeps the calculated values (line-length); */
int *lines;
/** Actual values */
@ -69,11 +70,11 @@ struct graph_t
/** Create a vertical color gradient */
bool vertical_gradient;
/** Next and previous graph */
graph_t *next, *prev;
plot_t *next, *prev;
};
static void
graph_delete(graph_t **g)
plot_delete(plot_t **g)
{
p_delete(&(*g)->title);
p_delete(&(*g)->lines);
@ -83,7 +84,7 @@ graph_delete(graph_t **g)
p_delete(g);
}
DO_SLIST(graph_t, graph, graph_delete)
DO_SLIST(plot_t, plot, plot_delete)
typedef struct
{
@ -106,12 +107,11 @@ typedef struct
/** Preparation/tmp array for draw_graph(); */
int *draw_to;
/** Graph list */
graph_t *graphs;
plot_t *plots;
} graph_data_t;
/* the same as the progressbar_pcolor_set may use a common function */
static void
graph_pcolor_set(xcolor_t **ppcolor, char *new_color)
plot_pcolor_set(xcolor_t **ppcolor, const char *new_color)
{
bool flag = false;
if(!*ppcolor)
@ -126,22 +126,26 @@ graph_pcolor_set(xcolor_t **ppcolor, char *new_color)
p_delete(ppcolor);
}
static graph_t *
graph_data_add(graph_data_t *d, const char *new_data_title)
/** 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)
{
graph_t *graph = p_new(graph_t, 1);
plot_t *plot = p_new(plot_t, 1);
/* memory (re-)allocating + initialising */
graph->values = p_new(float, d->size);
graph->lines = p_new(int, d->size);
graph->max_value = 100.0;
graph->title = a_strdup(new_data_title);
graph->color_start = globalconf.colors.fg;
graph->vertical_gradient = true;
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->color_start = globalconf.colors.fg;
plot->vertical_gradient = true;
graph_list_append(&d->graphs, graph);
plot_list_append(&d->plots, plot);
return graph;
return plot;
}
static int
@ -155,9 +159,9 @@ graph_draw(draw_context_t *ctx,
int margin_top, y;
graph_data_t *d = w->widget->data;
area_t rectangle, pattern_area;
graph_t *graph;
plot_t *plot;
if(!d->graphs)
if(!d->plots)
return 0;
w->area.x = widget_calculate_offset(ctx->width,
@ -165,7 +169,7 @@ graph_draw(draw_context_t *ctx,
w->widget->align);
w->area.y = 0;
/* box = the graph inside the rectangle */
/* box = the plot inside the rectangle */
if(!d->box_height)
d->box_height = round(ctx->height * d->height) - 2;
@ -178,7 +182,7 @@ graph_draw(draw_context_t *ctx,
rectangle.height = d->box_height;
draw_rectangle(ctx, rectangle, 1.0, true, d->bg);
/* for graph drawing */
/* 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 */
@ -190,12 +194,12 @@ graph_draw(draw_context_t *ctx,
else
pattern_area.x = rectangle.x;
for(graph = d->graphs; graph; graph = graph->next)
switch(graph->draw_style)
for(plot = d->plots; plot; plot = plot->next)
switch(plot->draw_style)
{
case Top_Style:
pattern_area.y = rectangle.y - rectangle.height;
if(graph->vertical_gradient)
if(plot->vertical_gradient)
{
pattern_area.width = 0;
pattern_area.height = rectangle.height;
@ -203,25 +207,25 @@ graph_draw(draw_context_t *ctx,
else
{
pattern_area.height = 0;
if(d->grow == Right)
pattern_area.width = - rectangle.width;
else
pattern_area.width = 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 - graph->lines[y]; /* i.e. on full graph -> 0 = bottom */
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, graph->index, d->grow, pattern_area,
&graph->color_start, graph->pcolor_center, graph->pcolor_end);
draw_graph(ctx, rectangle , d->draw_from, d->draw_to, plot->index, d->grow, pattern_area,
&plot->color_start, plot->pcolor_center, plot->pcolor_end);
break;
case Bottom_Style:
pattern_area.y = rectangle.y;
if(graph->vertical_gradient)
if(plot->vertical_gradient)
{
pattern_area.width = 0;
pattern_area.height = - rectangle.height;
@ -229,20 +233,20 @@ graph_draw(draw_context_t *ctx,
else
{
pattern_area.height = 0;
if(d->grow == Right)
pattern_area.width = - rectangle.width;
else
pattern_area.width = rectangle.width;
}
p_clear(d->draw_from, d->size);
draw_graph(ctx, rectangle, d->draw_from, graph->lines, graph->index, d->grow, pattern_area,
&graph->color_start, graph->pcolor_center, graph->pcolor_end);
draw_graph(ctx, rectangle, d->draw_from, plot->lines, plot->index, d->grow, pattern_area,
&plot->color_start, plot->pcolor_center, plot->pcolor_end);
break;
case Line_Style:
pattern_area.y = rectangle.y;
if(graph->vertical_gradient)
if(plot->vertical_gradient)
{
pattern_area.width = 0;
pattern_area.height = -rectangle.height;
@ -255,9 +259,9 @@ graph_draw(draw_context_t *ctx,
else
pattern_area.width = rectangle.width;
}
draw_graph_line(ctx, rectangle, graph->lines, graph->index, d->grow, pattern_area,
&graph->color_start, graph->pcolor_center, graph->pcolor_end);
draw_graph_line(ctx, rectangle, plot->lines, plot->index, d->grow, pattern_area,
&plot->color_start, plot->pcolor_center, plot->pcolor_end);
break;
}
@ -273,191 +277,249 @@ graph_draw(draw_context_t *ctx,
return w->area.width;
}
static widget_tell_status_t
graph_tell(widget_t *widget, const char *property, const char *new_value)
/** Set various graph general properties.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam A table with various properties set.
*/
static int
luaA_graph_properties_set(lua_State *L)
{
graph_data_t *d = widget->data;
graph_t *graph;
int i;
float value;
char *title, *setting;
char *new_val;
awesome_token_t prop = a_tokenize(property, -1);
widget_t **widget = luaA_checkudata(L, 1, "widget");
graph_data_t *d = (*widget)->data;
plot_t *plot;
int width;
const char *buf;
size_t len;
position_t pos;
if(!new_value)
return WIDGET_ERROR_NOVALUE;
luaA_checktable(L, 2);
switch (prop) {
default:
return WIDGET_ERROR;
d->height = luaA_getopt_number(L, 2, "height", d->height);
case A_TK_HEIGHT:
d->height = atof(new_value);
return WIDGET_NOERROR;
case A_TK_WIDTH:
d->width = atoi(new_value);
width = luaA_getopt_number(L, 2, "width", d->width);
if(width != d->width)
{
d->width = width;
d->size = d->width - 2;
/* re-allocate/initialise necessary values */
for(graph = d->graphs; graph; graph = graph->next)
for(plot = d->plots; plot; plot = plot->next)
{
p_realloc(&graph->values, d->size);
p_realloc(&graph->lines, d->size);
p_clear(graph->values, d->size);
p_clear(graph->lines, d->size);
graph->index = 0;
graph->current_max = 0;
graph->max_index = 0;
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;
}
return WIDGET_NOERROR;
case A_TK_BG:
if(!xcolor_new(globalconf.connection,
globalconf.default_screen,
new_value, &d->bg))
return WIDGET_ERROR_FORMAT_COLOR;
return WIDGET_NOERROR;
case A_TK_BORDERCOLOR:
if(!xcolor_new(globalconf.connection,
globalconf.default_screen,
new_value, &d->bordercolor))
return WIDGET_ERROR_FORMAT_COLOR;
return WIDGET_NOERROR;
case A_TK_GROW:
switch((d->grow = position_fromstr(new_value, -1)))
}
if((buf = luaA_getopt_string(L, 2, "bg", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &d->bg);
if((buf = luaA_getopt_string(L, 2, "bordercolor", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &d->bordercolor);
if((buf = luaA_getopt_lstring(L, 2, "grow", NULL, &len)))
switch((pos = position_fromstr(buf, len)))
{
case Left:
case Right:
return WIDGET_NOERROR;
default:
warn("error changing property %s of widget %s, must be 'left' or 'right'",
property, widget->name);
return WIDGET_ERROR_CUSTOM;
}
case A_TK_DATA:
case A_TK_FG:
case A_TK_FG_CENTER:
case A_TK_FG_END:
case A_TK_VERTICAL_GRADIENT:
case A_TK_SCALE:
case A_TK_MAX_VALUE:
case A_TK_DRAW_STYLE:
/* check if this section is defined already */
new_val = a_strdup(new_value);
title = strtok(new_val, " ");
if(!(setting = strtok(NULL, " ")))
{
p_delete(&new_val);
return WIDGET_ERROR_NOVALUE;
}
for(graph = d->graphs; graph; graph = graph->next)
if(!a_strcmp(title, graph->title))
break;
/* no section found -> create one */
if(!graph)
graph = graph_data_add(d, title);
break;
}
switch (prop) {
case A_TK_DATA:
/* assign incoming value */
value = MAX(atof(setting), 0);
if(++graph->index >= d->size) /* cycle inside the array */
graph->index = 0;
if(graph->scale) /* scale option is true */
{
graph->values[graph->index] = value;
if(value > graph->current_max) /* a new maximum value found */
{
graph->max_index = graph->index;
graph->current_max = value;
/* recalculate */
for (i = 0; i < d->size; i++)
graph->lines[i] = round(graph->values[i] * d->box_height / graph->current_max);
}
/* old max_index reached + current_max > normal, re-check/generate */
else if(graph->max_index == graph->index
&& graph->current_max > graph->max_value)
{
/* find the new max */
for(i = 0; i < d->size; i++)
if(graph->values[i] > graph->values[graph->max_index])
graph->max_index = i;
graph->current_max = MAX(graph->values[graph->max_index], graph->max_value);
/* recalculate */
for(i = 0; i < d->size; i++)
graph->lines[i] = round(graph->values[i] * d->box_height / graph->current_max);
}
else
graph->lines[graph->index] = round(value * d->box_height / graph->current_max);
}
else /* scale option is false - limit to d->box_height */
{
if(value < graph->max_value)
graph->lines[graph->index] = round(value * d->box_height / graph->max_value);
else
graph->lines[graph->index] = d->box_height;
}
break;
case A_TK_FG:
xcolor_new(globalconf.connection, globalconf.default_screen, setting, &graph->color_start);
break;
case A_TK_FG_CENTER:
graph_pcolor_set(&graph->pcolor_center, setting);
break;
case A_TK_FG_END:
graph_pcolor_set(&graph->pcolor_end, setting);
break;
case A_TK_VERTICAL_GRADIENT:
graph->vertical_gradient = a_strtobool(setting, -1);
break;
case A_TK_SCALE:
graph->scale = a_strtobool(setting, -1);
break;
case A_TK_MAX_VALUE:
graph->max_value = atof(setting);
graph->current_max = graph->max_value;
break;
case A_TK_DRAW_STYLE:
switch (a_tokenize(setting, -1)) {
case A_TK_BOTTOM:
graph->draw_style = Bottom_Style;
break;
case A_TK_LINE:
graph->draw_style = Line_Style;
break;
case A_TK_TOP:
graph->draw_style = Top_Style;
d->grow = pos;
break;
default:
warn("'error changing property %s of widget %s, must be 'bottom', 'top' or 'line'",
property, widget->name);
break;
}
break;
default:
break;
}
p_delete(&new_val);
return WIDGET_NOERROR;
widget_invalidate_bywidget(*widget);
return 0;
}
/** Set various plot graph properties.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \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");
graph_data_t *d = (*widget)->data;
float max_value;
const char *title, *buf;
size_t len;
plot_t *plot;
title = luaL_checkstring(L, 2);
luaA_checktable(L, 3);
for(plot = d->plots; plot; plot = plot->next)
if(!a_strcmp(title, plot->title))
break;
/* no plot found -> create one */
if(!plot)
plot = graph_plot_add(d, title);
if((buf = luaA_getopt_string(L, 3, "fg", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &plot->color_start);
if((buf = luaA_getopt_string(L, 3, "fg_center", NULL)))
plot_pcolor_set(&plot->pcolor_center, buf);
if((buf = luaA_getopt_string(L, 3, "fg_end", NULL)))
plot_pcolor_set(&plot->pcolor_end, buf);
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;
}
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.
* \lstack
* \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");
graph_data_t *d = (*widget)->data;
plot_t *plot;
const char *title = luaL_checkstring(L, 2);
float value;
int i;
for(plot = d->plots; plot; plot = plot->next)
if(!a_strcmp(title, plot->title))
break;
/* no plot found -> create one */
if(!plot)
plot = graph_plot_add(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;
}
/** Index function for graph widget.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
*/
static int
luaA_graph_index(lua_State *L)
{
size_t len;
const char *attr = luaL_checklstring(L, 2, &len);
switch(a_tokenize(attr, len))
{
case A_TK_PROPERTIES_SET:
lua_pushcfunction(L, luaA_graph_properties_set);
return 1;
case A_TK_PLOT_PROPERTIES_SET:
lua_pushcfunction(L, luaA_graph_plot_properties_set);
return 1;
case A_TK_PLOT_DATA_ADD:
lua_pushcfunction(L, luaA_graph_plot_data_add);
return 1;
default:
return 0;
}
}
/** Destroy definitively a graph widget.
* \param widget Who slay.
*/
static void
graph_destructor(widget_t *widget)
{
graph_data_t *d = widget->data;
graph_list_wipe(&d->graphs);
plot_list_wipe(&d->plots);
p_delete(&d->draw_from);
p_delete(&d->draw_to);
p_delete(&d);
}
/** Create a brand new graph.
* \param align The widget alignment.
* \return A graph widget.
*/
widget_t *
graph_new(alignment_t align)
{
@ -468,7 +530,7 @@ graph_new(alignment_t align)
widget_common_new(w);
w->draw = graph_draw;
w->tell = graph_tell;
w->index = luaA_graph_index;
w->destructor = graph_destructor;
w->align = align;
d = w->data = p_new(graph_data_t, 1);

View File

@ -28,6 +28,7 @@ extern awesome_t globalconf;
typedef struct bar_t bar_t;
/** Progressbar bar data structure */
struct bar_t
{
/** Title of the data/bar */
@ -56,6 +57,9 @@ struct bar_t
bar_t *next, *prev;
};
/** Delete a bar.
* \param bar The bar to annihilate.
*/
static void
bar_delete(bar_t **bar)
{
@ -67,6 +71,7 @@ bar_delete(bar_t **bar)
DO_SLIST(bar_t, bar, bar_delete)
/** Progressbar private data structure */
typedef struct
{
/** Width of the data_items */
@ -90,7 +95,7 @@ typedef struct
} progressbar_data_t;
static void
progressbar_pcolor_set(xcolor_t **ppcolor, char *new_color)
progressbar_pcolor_set(xcolor_t **ppcolor, const char *new_color)
{
bool flag = false;
if(!*ppcolor)
@ -105,13 +110,16 @@ progressbar_pcolor_set(xcolor_t **ppcolor, char *new_color)
p_delete(ppcolor);
}
/** Add a new bar to the progressbar private data structure.
* \param d The private data structure.
* \param title The graph title.
*/
static bar_t *
progressbar_data_add(progressbar_data_t *d, const char *new_data_title)
progressbar_bar_add(progressbar_data_t *d, const char *title)
{
bar_t *bar = p_new(bar_t, 1);
bar->title = a_strdup(new_data_title);
bar->title = a_strdup(title);
bar->fg = globalconf.colors.fg;
bar->fg_off = globalconf.colors.bg;
bar->bg = globalconf.colors.bg;
@ -124,6 +132,15 @@ progressbar_data_add(progressbar_data_t *d, const char *new_data_title)
return bar;
}
/** Draw a progressbar.
* \param ctx The draw context.
* \param screen The screen we're drawing for.
* \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 int
progressbar_draw(draw_context_t *ctx,
int screen __attribute__ ((unused)),
@ -399,132 +416,161 @@ progressbar_draw(draw_context_t *ctx,
return w->area.width;
}
static widget_tell_status_t
progressbar_tell(widget_t *widget, const char *property, const char *new_value)
/** Set various progressbar general properties:
* gap, ticks_count, ticks_gap, border_padding, border_width, width, height and
* vertical.
* \param L The Lua VM state.
* \return The number of elements pushed on the stack.
* \lstack
* \lvalue A widget.
* \lparam A table with keys as properties names.
*/
int
luaA_progressbar_properties_set(lua_State *L)
{
progressbar_data_t *d = widget->data;
int value;
char *title, *setting;
char *new_val;
bar_t *bar;
awesome_token_t prop = a_tokenize(property, -1);
widget_t **widget = luaA_checkudata(L, 1, "widget");
progressbar_data_t *d = (*widget)->data;
if(!new_value)
return WIDGET_ERROR_NOVALUE;
luaA_checktable(L, 2);
switch (prop)
{
case A_TK_GAP:
d->gap = atoi(new_value);
return WIDGET_NOERROR;
case A_TK_TICKS_COUNT:
d->ticks_count = atoi(new_value);
return WIDGET_NOERROR;
case A_TK_TICKS_GAP:
d->ticks_gap = atoi(new_value);
return WIDGET_NOERROR;
case A_TK_BORDER_PADDING:
d->border_padding = atoi(new_value);
return WIDGET_NOERROR;
case A_TK_BORDER_WIDTH:
d->border_width = atoi(new_value);
return WIDGET_NOERROR;
case A_TK_WIDTH:
d->width = atoi(new_value);
return WIDGET_NOERROR;
case A_TK_HEIGHT:
d->height = atof(new_value);
return WIDGET_NOERROR;
case A_TK_VERTICAL:
d->vertical = a_strtobool(new_value, -1);
return WIDGET_NOERROR;
d->gap = luaA_getopt_number(L, 2, "gap", d->gap);
d->ticks_count = luaA_getopt_number(L, 2, "ticks_count", d->ticks_count);
d->ticks_gap = luaA_getopt_number(L, 2, "ticks_gap", d->ticks_gap);
d->border_padding = luaA_getopt_number(L, 2, "border_padding", d->border_padding);
d->border_width = luaA_getopt_number(L, 2, "border_width", d->border_width);
d->width = luaA_getopt_number(L, 2, "width", d->width);
d->height = luaA_getopt_number(L, 2, "height", d->height);
/* following properties need a datasection */
case A_TK_FG:
case A_TK_DATA:
case A_TK_FG_OFF:
case A_TK_BG:
case A_TK_BORDERCOLOR:
case A_TK_FG_CENTER:
case A_TK_FG_END:
case A_TK_MIN_VALUE:
case A_TK_MAX_VALUE:
case A_TK_REVERSE:
/* check if this section is defined already */
new_val = a_strdup(new_value);
title = strtok(new_val, " ");
if(!(setting = strtok(NULL, " ")))
{
p_delete(&new_val);
return WIDGET_ERROR_NOVALUE;
}
for(bar = d->bars; bar; bar = bar->next)
if(!a_strcmp(title, bar->title))
break;
d->vertical = luaA_getopt_boolean(L, 2, "vertical", d->vertical);
/* no section found -> create one */
if(!bar)
bar = progressbar_data_add(d, title);
break;
widget_invalidate_bywidget(*widget);
default:
return WIDGET_ERROR;
}
switch (prop)
{
case A_TK_DATA:
value = atof(setting);
bar->value = (value < bar->min_value ? bar->min_value :
(value > bar->max_value ? bar->max_value : value));
break;
case A_TK_FG:
xcolor_new(globalconf.connection, globalconf.default_screen, setting, &bar->fg);
break;
case A_TK_BG:
xcolor_new(globalconf.connection, globalconf.default_screen, setting, &bar->bg);
break;
case A_TK_FG_OFF:
xcolor_new(globalconf.connection, globalconf.default_screen, setting, &bar->fg_off);
break;
case A_TK_BORDERCOLOR:
xcolor_new(globalconf.connection, globalconf.default_screen, setting, &bar->bordercolor);
break;
case A_TK_FG_CENTER:
progressbar_pcolor_set(&bar->pfg_center, setting);
break;
case A_TK_FG_END:
progressbar_pcolor_set(&bar->pfg_end, setting);
break;
case A_TK_MIN_VALUE:
bar->min_value = atof(setting);
/* 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;
break;
case A_TK_MAX_VALUE:
bar->max_value = atof(setting);
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;
break;
case A_TK_REVERSE:
bar->reverse = a_strtobool(setting, -1);
break;
default:
return WIDGET_ERROR;
}
p_delete(&new_val);
return WIDGET_NOERROR;
return 0;
}
/** Set various progressbar bars properties:
* \param L The Lua VM state.
* \return The number of elements pushed on the stack.
* \lstack
* \lvalue A widget.
* \lparam A bar name.
* \lparam A table with keys as properties names.
*/
int
luaA_progressbar_bar_properties_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
const char *buf, *title = luaL_checkstring(L, 2);
bar_t *bar;
progressbar_data_t *d = (*widget)->data;
luaA_checktable(L, 3);
/* check if this section is defined already */
for(bar = d->bars; bar; bar = bar->next)
if(!a_strcmp(title, bar->title))
break;
/* no bar found -> create one */
if(!bar)
bar = progressbar_bar_add(d, title);
if((buf = luaA_getopt_string(L, 3, "fg", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &bar->fg);
if((buf = luaA_getopt_string(L, 3, "bg", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &bar->bg);
if((buf = luaA_getopt_string(L, 3, "fg_off", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &bar->fg_off);
if((buf = luaA_getopt_string(L, 3, "border_color", NULL)))
xcolor_new(globalconf.connection, globalconf.default_screen, buf, &bar->bordercolor);
if((buf = luaA_getopt_string(L, 3, "fg_center", NULL)))
progressbar_pcolor_set(&bar->pfg_center, buf);
if((buf = luaA_getopt_string(L, 3, "fg_end", NULL)))
progressbar_pcolor_set(&bar->pfg_end, buf);
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);
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.
* \lstack
* \lvalue A widget.
* \lparam A bar name.
* \lparam A data value.
*/
int
luaA_progressbar_bar_data_add(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
const char *title = luaL_checkstring(L, 2);
progressbar_data_t *d = (*widget)->data;
bar_t *bar;
/* check if this section is defined already */
for(bar = d->bars; bar; bar = bar->next)
if(!a_strcmp(title, bar->title))
break;
/* no bar found -> create one */
if(!bar)
bar = progressbar_bar_add(d, title);
bar->value = MAX(bar->min_value, MIN(bar->max_value, luaL_checknumber(L, 3)));
widget_invalidate_bywidget(*widget);
return 0;
}
/** Index function for progressbar.
* \param L The Lua VM state.
* \return The number of elements pushed on the stack.
*/
static int
luaA_progressbar_index(lua_State *L)
{
size_t len;
const char *attr = luaL_checklstring(L, 2, &len);
switch(a_tokenize(attr, len))
{
case A_TK_PROPERTIES_SET:
lua_pushcfunction(L, luaA_progressbar_properties_set);
return 1;
case A_TK_BAR_PROPERTIES_SET:
lua_pushcfunction(L, luaA_progressbar_bar_properties_set);
return 1;
case A_TK_BAR_DATA_ADD:
lua_pushcfunction(L, luaA_progressbar_bar_data_add);
return 1;
default:
return 0;
}
}
/** Destroy a progressbar.
* \param widget The widget to kill.
*/
static void
progressbar_destructor(widget_t *widget)
{
@ -534,6 +580,10 @@ progressbar_destructor(widget_t *widget)
p_delete(&d);
}
/** Create a new progressbar.
* \param align Alignment of the widget.
* \return A brand new progressbar.
*/
widget_t *
progressbar_new(alignment_t align)
{
@ -544,7 +594,7 @@ progressbar_new(alignment_t align)
widget_common_new(w);
w->align = align;
w->draw = progressbar_draw;
w->tell = progressbar_tell;
w->index = luaA_progressbar_index;
w->destructor = progressbar_destructor;
d = w->data = p_new(progressbar_data_t, 1);

View File

@ -1,7 +1,7 @@
/*
* taglist.c - tag list widget
*
* Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
* Copyright © 2008 Julien Danjou <julien@danjou.info>
*
* 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
@ -30,6 +30,9 @@
extern awesome_t globalconf;
/** Data type used to store where we draw the taglist for a particular object.
* This is filled in the draw function, and use later when we get a click.
*/
typedef struct taglist_drawn_area_t taglist_drawn_area_t;
struct taglist_drawn_area_t
{
@ -38,6 +41,9 @@ struct taglist_drawn_area_t
taglist_drawn_area_t *next, *prev;
};
/** Delete a taglist_drawn_area_t object.
* \param a The drawn area to delete.
*/
static void
taglist_drawn_area_delete(taglist_drawn_area_t **a)
{
@ -47,14 +53,21 @@ taglist_drawn_area_delete(taglist_drawn_area_t **a)
DO_SLIST(taglist_drawn_area_t, taglist_drawn_area, taglist_drawn_area_delete);
/** Taglist widget private data */
typedef struct
{
char *text_normal, *text_focus, *text_urgent;
bool show_empty;
taglist_drawn_area_t *drawn_area;
} taglist_data_t;
/** Called when a markup element is encountered.
* \param p The parser data.
* \param elem The element.
* \param names The element attributes names.
* \param values The element attributes values.
*/
static void
tag_markup_on_elem(markup_parser_data_t *p, const char *elem,
const char **names, const char **values)
@ -63,7 +76,12 @@ tag_markup_on_elem(markup_parser_data_t *p, const char *elem,
buffer_add_xmlescaped(&p->text, NONULL(p->priv));
}
/** Parse a markup string.
* \param t The tag we're parsing for.
* \param str The string we're parsing.
* \param len The string length.
* \return The parsed string.
*/
static char *
tag_markup_parse(tag_t *t, const char *str, ssize_t len)
{
@ -88,10 +106,9 @@ tag_markup_parse(tag_t *t, const char *str, ssize_t len)
return ret;
}
/** Check if at least one client is tagged with tag number t and is on screen
* screen
* \param t tag
* \return true or false
/** Check if at least one client is tagged with tag number t.
* \param t The tag to check.
* \return True if the tag has a client, false otherwise.
*/
static bool
tag_isoccupied(tag_t *t)
@ -99,24 +116,33 @@ tag_isoccupied(tag_t *t)
client_t *c;
for(c = globalconf.clients; c; c = c->next)
if(is_client_tagged(c, t) && !c->skip)
if(!c->skip && is_client_tagged(c, t))
return true;
return false;
}
/** Check if a tag has at least one client with urgency hint.
* \param t The tag.
* \return True if the tag has a client with urgency set, false otherwise.
*/
static bool
tag_isurgent(tag_t *t)
{
client_t *c;
for(c = globalconf.clients; c; c = c->next)
if(is_client_tagged(c, t) && c->isurgent)
if(c->isurgent && is_client_tagged(c, t))
return true;
return false;
}
/** Get the string to use for drawing the tag.
* \param tag The tag.
* \param data The taglist private data.
* \return The string to use.
*/
static char *
taglist_text_get(tag_t *tag, taglist_data_t *data)
{
@ -124,10 +150,18 @@ taglist_text_get(tag_t *tag, taglist_data_t *data)
return data->text_focus;
else if(tag_isurgent(tag))
return data->text_urgent;
return data->text_normal;
}
/** Draw a taglist.
* \param ctx The draw context.
* \param screen The screen we're drawing for.
* \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 int
taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
int offset,
@ -180,7 +214,7 @@ taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
/* Now that we have widget width we can compute widget x coordinate */
w->area.x = widget_calculate_offset(ctx->width, w->area.width,
offset, w->widget->align);
offset, w->widget->align);
for(int i = 0; i < tags->len; i++)
{
@ -254,34 +288,92 @@ taglist_button_press(widget_node_t *w,
}
}
static widget_tell_status_t
taglist_tell(widget_t *widget, const char *property, const char *new_value)
/** Set text format string in case of a tag is normal, has focused client
* or has a client with urgency hint.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam A table with keys to change: `normal', `focus' and `urgent'.
*/
static int
luaA_taglist_text_set(lua_State *L)
{
taglist_data_t *d = widget->data;
widget_t **widget = luaA_checkudata(L, 1, "widget");
taglist_data_t *d = (*widget)->data;
const char *buf;
switch(a_tokenize(property, -1))
luaA_checktable(L, 2);
if((buf = luaA_getopt_string(L, 2, "normal", NULL)))
{
case A_TK_TEXT_NORMAL:
p_delete(&d->text_normal);
d->text_normal = a_strdup(new_value);
break;
case A_TK_TEXT_FOCUS:
p_delete(&d->text_focus);
d->text_focus = a_strdup(new_value);
break;
case A_TK_TEXT_URGENT:
p_delete(&d->text_urgent);
d->text_urgent = a_strdup(new_value);
break;
case A_TK_SHOW_EMPTY:
d->show_empty = a_strtobool(new_value, -1);
break;
default:
return WIDGET_ERROR;
d->text_normal = a_strdup(buf);
}
return WIDGET_NOERROR;
if((buf = luaA_getopt_string(L, 2, "focus", NULL)))
{
p_delete(&d->text_focus);
d->text_focus = a_strdup(buf);
}
if((buf = luaA_getopt_string(L, 2, "urgent", NULL)))
{
p_delete(&d->text_urgent);
d->text_urgent = a_strdup(buf);
}
widget_invalidate_bywidget(*widget);
return 0;
}
/** Set if the taglist must show the tags which have no client.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam A boolean value, true to show empty tags, false otherwise.
*/
static int
luaA_taglist_showempty_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
taglist_data_t *d = (*widget)->data;
d->show_empty = luaA_checkboolean(L, 2);
widget_invalidate_bywidget(*widget);
return 0;
}
/** Index function for taglist.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
*/
int
luaA_taglist_index(lua_State *L)
{
size_t len;
const char *attr = luaL_checklstring(L, 2, &len);
switch(a_tokenize(attr, len))
{
case A_TK_TEXT_SET:
lua_pushcfunction(L, luaA_taglist_text_set);
return 1;
case A_TK_SHOWEMPTY_SET:
lua_pushcfunction(L, luaA_taglist_showempty_set);
return 1;
default:
return 0;
}
}
/** Taglist destructor.
* \param widget The widget to destroy.
*/
static void
taglist_destructor(widget_t *widget)
{
@ -294,6 +386,10 @@ taglist_destructor(widget_t *widget)
p_delete(&d);
}
/** Create a brand new taglist widget.
* \param align Widget alignment.
* \return A taglist widget.
*/
widget_t *
taglist_new(alignment_t align)
{
@ -302,10 +398,10 @@ taglist_new(alignment_t align)
w = p_new(widget_t, 1);
widget_common_new(w);
w->index = luaA_taglist_index;
w->align = align;
w->draw = taglist_draw;
w->button_press = taglist_button_press;
w->tell = taglist_tell;
w->destructor = taglist_destructor;
w->data = d = p_new(taglist_data_t, 1);

View File

@ -39,6 +39,7 @@ typedef enum
ShowAll,
} showclient_t;
/** The tasklist private data structure. */
typedef struct
{
showclient_t show;
@ -46,6 +47,18 @@ typedef struct
char *text_normal, *text_urgent, *text_focus;
} tasklist_data_t;
struct tasklist_hook_data
{
draw_context_t *ctx;
area_t *area;
};
/** Check if a client is visible according to the showclient type paramater.
* \param c The client.
* \param screen The screen number.
* \param show The show parameters.
* \return True if the client is visible, false otherwise.
*/
static inline bool
tasklist_isvisible(client_t *c, int screen, showclient_t show)
{
@ -64,12 +77,12 @@ tasklist_isvisible(client_t *c, int screen, showclient_t show)
return false;
}
struct tasklist_hook_data
{
draw_context_t *ctx;
area_t *area;
};
/** Called when a markup element is found.
* \param p The markup parser data.
* \param elem The element name.
* \param names The attributes names.
* \param values The attributes values.
*/
static void
tasklist_markup_on_elem(markup_parser_data_t *p, const char *elem,
const char **names, const char **values)
@ -88,11 +101,18 @@ tasklist_markup_on_elem(markup_parser_data_t *p, const char *elem,
}
}
/** Draw a tasklist widget.
* \param ctx The draw context.
* \param screen The screen number.
* \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.
*/
static int
tasklist_draw(draw_context_t *ctx, int screen,
widget_node_t *w,
int offset, int used, void *q __attribute__ ((unused)))
int offset, int used, void *p __attribute__ ((unused)))
{
client_t *c;
tasklist_data_t *d = w->widget->data;
@ -139,7 +159,7 @@ tasklist_draw(draw_context_t *ctx, int screen,
{
static char const * const elements[] = { "bg", NULL };
struct tasklist_hook_data data = { .ctx = ctx, .area = &area };
markup_parser_data_t p =
markup_parser_data_t pdata =
{
.elements = elements,
.on_element = &tasklist_markup_on_elem,
@ -154,9 +174,9 @@ tasklist_draw(draw_context_t *ctx, int screen,
/* Actually look for the proper background color, since
* otherwise the background statusbar color is used instead */
markup_parser_data_init(&p);
markup_parse(&p, text, a_strlen(text));
markup_parser_data_wipe(&p);
markup_parser_data_init(&pdata);
markup_parse(&pdata, text, a_strlen(text));
markup_parser_data_wipe(&pdata);
if((image = draw_image_new(c->icon_path)))
{
@ -257,50 +277,126 @@ tasklist_button_press(widget_node_t *w,
}
}
static widget_tell_status_t
tasklist_tell(widget_t *widget, const char *property, const char *new_value)
/** Set the tasklist show attribute.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam A string: tags, focus or all.
*/
static int
luaA_tasklist_show_set(lua_State *L)
{
tasklist_data_t *d = widget->data;
size_t len;
widget_t **widget = luaA_checkudata(L, 1, "widget");
tasklist_data_t *d = (*widget)->data;
const char *buf = luaL_checklstring(L, 2, &len);
switch(a_tokenize(property, -1))
switch(a_tokenize(buf, len))
{
case A_TK_TEXT_NORMAL:
p_delete(&d->text_normal);
d->text_normal = a_strdup(new_value);
case A_TK_TAGS:
d->show = ShowTags;
break;
case A_TK_TEXT_FOCUS:
p_delete(&d->text_focus);
d->text_focus = a_strdup(new_value);
case A_TK_FOCUS:
d->show = ShowFocus;
break;
case A_TK_TEXT_URGENT:
p_delete(&d->text_urgent);
d->text_urgent = a_strdup(new_value);
break;
case A_TK_SHOW_ICONS:
d->show_icons = a_strtobool(new_value, -1);
break;
case A_TK_SHOW:
switch(a_tokenize(new_value, -1))
{
case A_TK_TAGS:
d->show = ShowTags;
break;
case A_TK_FOCUS:
d->show = ShowFocus;
break;
case A_TK_ALL:
d->show = ShowAll;
break;
default:
return WIDGET_ERROR;
}
case A_TK_ALL:
d->show = ShowAll;
break;
default:
return WIDGET_ERROR;
break;
}
return WIDGET_NOERROR;
widget_invalidate_bywidget(*widget);
return 0;
}
/** Select if icons must be shown.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \luastack
* \lvalue A widget.
* \lparam A boolean, true to see icons, false otherwise.
*/
static int
luaA_tasklist_showicons_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
tasklist_data_t *d = (*widget)->data;
d->show_icons = luaA_checkboolean(L, 2);
return 0;
}
/** Set text format string in case of a client is either normal, focused or has
* urgency hint.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam A table with keys to change: `normal', `focus' and `urgent'.
*/
static int
luaA_tasklist_text_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
tasklist_data_t *d = (*widget)->data;
const char *buf;
luaA_checktable(L, 2);
if((buf = luaA_getopt_string(L, 2, "normal", NULL)))
{
p_delete(&d->text_normal);
d->text_normal = a_strdup(buf);
}
if((buf = luaA_getopt_string(L, 2, "focus", NULL)))
{
p_delete(&d->text_focus);
d->text_focus = a_strdup(buf);
}
if((buf = luaA_getopt_string(L, 2, "urgent", NULL)))
{
p_delete(&d->text_urgent);
d->text_urgent = a_strdup(buf);
}
widget_invalidate_bywidget(*widget);
return 0;
}
/** Index function for tasklist widget.
* \lparam L The Lua VM state.
* \return The number of elements pushed on stack.
*/
static int
luaA_tasklist_index(lua_State *L)
{
size_t len;
const char *attr = luaL_checklstring(L, 2, &len);
switch(a_tokenize(attr, len))
{
case A_TK_TEXT_SET:
lua_pushcfunction(L, luaA_tasklist_text_set);
return 1;
case A_TK_SHOWICONS_SET:
lua_pushcfunction(L, luaA_tasklist_showicons_set);
case A_TK_SHOW_SET:
lua_pushcfunction(L, luaA_tasklist_show_set);
default:
return 0;
}
}
/** Destructor for the tasklist widget.
* \param widget The widget to destroy.
*/
static void
tasklist_destructor(widget_t *widget)
{
@ -312,6 +408,10 @@ tasklist_destructor(widget_t *widget)
p_delete(&d);
}
/** Create a new widget tasklist.
* \param align The widget alignment, which is flex anyway.
* \return A brand new tasklist widget.
*/
widget_t *
tasklist_new(alignment_t align __attribute__ ((unused)))
{
@ -323,8 +423,8 @@ tasklist_new(alignment_t align __attribute__ ((unused)))
w->draw = tasklist_draw;
w->button_press = tasklist_button_press;
w->align = AlignFlex;
w->index = luaA_tasklist_index;
w->data = d = p_new(tasklist_data_t, 1);
w->tell = tasklist_tell;
w->destructor = tasklist_destructor;
d->text_normal = a_strdup(" <title/> ");

View File

@ -2,7 +2,6 @@
* textbox.c - text box widget
*
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
* Copyright © 2007 Aldo Cortesi <aldo@nullcube.com>
*
* 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
@ -28,12 +27,24 @@
extern awesome_t globalconf;
/** The textbox private data structure */
typedef struct
{
/** Textbox text */
char *text;
/** Textbox width */
int width;
} textbox_data_t;
/** Draw a textbox widget.
* \param ctx The draw context.
* \param screen The screen.
* \param w The widget node we are linked from.
* \param offset Offset to draw at.
* \param used The size used on the element.
* \param p A pointer to the object we're draw onto.
* \return The width used.
*/
static int
textbox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)),
widget_node_t *w,
@ -72,27 +83,9 @@ textbox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)),
return w->area.width;
}
static widget_tell_status_t
textbox_tell(widget_t *widget, const char *property, const char *new_value)
{
textbox_data_t *d = widget->data;
switch(a_tokenize(property, -1))
{
case A_TK_TEXT:
p_delete(&d->text);
a_iso2utf8(new_value, &d->text);
break;
case A_TK_WIDTH:
d->width = atoi(new_value);
break;
default:
return WIDGET_ERROR;
}
return WIDGET_NOERROR;
}
/** Delete a textbox widget.
* \param w The widget to destroy.
*/
static void
textbox_destructor(widget_t *w)
{
@ -101,6 +94,77 @@ textbox_destructor(widget_t *w)
p_delete(&d);
}
/** Set the text of a textbox.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam The text to set.
*/
static int
luaA_textbox_text_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
const char *text = luaL_checkstring(L, 2);
textbox_data_t *d = (*widget)->data;
p_delete(&d->text);
a_iso2utf8(text, &d->text);
widget_invalidate_bywidget(*widget);
return 0;
}
/** Set the width of a textbox.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \lstack
* \lvalue A widget.
* \lparam The width to set.
*/
static int
luaA_textbox_width_set(lua_State *L)
{
widget_t **widget = luaA_checkudata(L, 1, "widget");
int width = luaL_checknumber(L, 2);
textbox_data_t *d = (*widget)->data;
d->width = width;
widget_invalidate_bywidget(*widget);
return 0;
}
/** The __index method for a textbox object.
* \param L The Lua VM state.
* \return The number of elements pushed on stack.
* \param The numbre of elements return on the stack.
*/
static int
luaA_textbox_index(lua_State *L)
{
size_t len;
const char *attr = luaL_checklstring(L, 2, &len);
switch(a_tokenize(attr, len))
{
case A_TK_TEXT_SET:
lua_pushcfunction(L, luaA_textbox_text_set);
return 1;
case A_TK_WIDTH_SET:
lua_pushcfunction(L, luaA_textbox_width_set);
return 1;
default:
return 0;
}
}
/** Create a new textbox widget.
* \param align Widget alignment.
* \return A brand new widget.
*/
widget_t *
textbox_new(alignment_t align)
{
@ -111,7 +175,7 @@ textbox_new(alignment_t align)
widget_common_new(w);
w->align = align;
w->draw = textbox_draw;
w->tell = textbox_tell;
w->index = luaA_textbox_index;
w->destructor = textbox_destructor;
w->data = d = p_new(textbox_data_t, 1);