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() Each widget as its own set of properties, described below, that can bet modified with the set()
method. 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 SEE ALSO
-------- --------
awesome(1) awesome-client(1) 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({ modkey }, 3, function (object, tag) awful.client.toggletag(tag) end))
mytaglist:mouse_add(mouse.new({ }, 4, awful.tag.viewnext)) mytaglist:mouse_add(mouse.new({ }, 4, awful.tag.viewnext))
mytaglist:mouse_add(mouse.new({ }, 5, awful.tag.viewprev)) 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 -- Create a tasklist widget
mytasklist = widget.new({ type = "tasklist", name = "mytasklist" }) 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({ }, 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({ }, 4, function () awful.client.focus(1) end))
mytasklist:mouse_add(mouse.new({ }, 5, 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 -- Create a textbox widget
mytextbox = widget.new({ type = "textbox", name = "mytextbox", align = "right" }) mytextbox = widget.new({ type = "textbox", name = "mytextbox", align = "right" })
-- Set the default text in textbox -- 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" }) mypromptbox = widget.new({ type = "textbox", name = "mypromptbox", align = "left" })
-- Create an iconbox widget -- Create an iconbox widget
myiconbox = widget.new({ type = "textbox", name = "myiconbox", align = "left" }) 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 -- Create a systray
mysystray = widget.new({ type = "systray", name = "mysystray", align = "right" }) 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({ }, 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({ }, 4, function () awful.layout.inc(layouts, 1) end))
mylayoutbox[s]:mouse_add(mouse.new({ }, 5, 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 end
-- Create a statusbar for each screen and add it -- Create a statusbar for each screen and add it
@ -334,7 +334,7 @@ end
-- (tag switch, new client, etc) -- (tag switch, new client, etc)
function hook_arrange(screen) function hook_arrange(screen)
local layout = awful.layout.get(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 -- Uncomment if you want mouse warping
--[[ --[[
@ -356,9 +356,9 @@ end
-- Hook called every second -- Hook called every second
function hook_timer () function hook_timer ()
-- For unix time_t lovers -- For unix time_t lovers
mytextbox:set("text", " " .. os.time() .. " time_t ") mytextbox:text_set(" " .. os.time() .. " time_t ")
-- Otherwise use: -- Otherwise use:
-- mytextbox:set("text", " " .. os.date() .. " ") -- mytextbox:text_set(" " .. os.date() .. " ")
end end
-- Set up some hooks -- Set up some hooks

View File

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

69
dbus.c
View File

@ -35,71 +35,6 @@ static DBusError err;
static DBusConnection *dbus_connection = NULL; static DBusConnection *dbus_connection = NULL;
ev_io dbusio = { .fd = -1 }; 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 static void
a_dbus_process_requests(EV_P_ ev_io *w, int revents) 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; break;
if(dbus_message_is_method_call(msg, "org.awesome.widget", "set")) if(dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
a_dbus_process_widget_set(msg);
else if(dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected"))
{ {
a_dbus_cleanup(); a_dbus_cleanup();
dbus_message_unref(msg); 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 void (widget_destructor_t)(widget_t *);
typedef struct awesome_t awesome_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 */ /** Mouse buttons bindings */
struct button_t struct button_t
{ {
@ -112,8 +100,8 @@ struct widget_t
widget_destructor_t *destructor; widget_destructor_t *destructor;
/** Draw function */ /** Draw function */
int (*draw)(draw_context_t *, int, widget_node_t *, int, int, void *); int (*draw)(draw_context_t *, int, widget_node_t *, int, int, void *);
/** Update function */ /** Index function */
widget_tell_status_t (*tell)(widget_t *, const char *, const char *); int (*index)(lua_State *);
/** ButtonPressedEvent handler */ /** ButtonPressedEvent handler */
void (*button_press)(widget_node_t *, xcb_button_press_event_t *, int, void *, awesome_type_t); void (*button_press)(widget_node_t *, xcb_button_press_event_t *, int, void *, awesome_type_t);
/** Alignement */ /** Alignement */

108
widget.c
View File

@ -2,7 +2,6 @@
* widget.c - widget managing * widget.c - widget managing
* *
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info> * 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 * 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 * 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; 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. /** Common function for button press event on widget.
* It will look into configuration to find the callback function to call. * It will look into configuration to find the callback function to call.
* \param w The widget node. * \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. /** Render a list of widgets.
* \param wnode The list of widgets. * \param wnode The list of widgets.
* \param ctx The draw context where to render. * \param ctx The draw context where to render.
@ -238,7 +201,6 @@ void
widget_common_new(widget_t *widget) widget_common_new(widget_t *widget)
{ {
widget->align = AlignLeft; widget->align = AlignLeft;
widget->tell = widget_common_tell;
widget->button_press = widget_common_button_press; widget->button_press = widget_common_button_press;
} }
@ -269,7 +231,7 @@ widget_invalidate_cache(int screen, int flags)
* \todo Probably needs more optimization. * \todo Probably needs more optimization.
* \param widget The widget to look for. * \param widget The widget to look for.
*/ */
static void void
widget_invalidate_bywidget(widget_t *widget) widget_invalidate_bywidget(widget_t *widget)
{ {
int screen; int screen;
@ -371,67 +333,6 @@ luaA_widget_mouse_remove(lua_State *L)
return 0; 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. /** Convert a widget into a printable string.
* \param L The Lua VM state. * \param L The Lua VM state.
* *
@ -513,6 +414,7 @@ luaA_widget_visible_get(lua_State *L)
static int static int
luaA_widget_index(lua_State *L) luaA_widget_index(lua_State *L)
{ {
widget_t **widget = luaA_checkudata(L, 1, "widget");
size_t len; size_t len;
const char *str = luaL_checklstring(L, 2, &len); const char *str = luaL_checklstring(L, 2, &len);
@ -524,9 +426,6 @@ luaA_widget_index(lua_State *L)
case A_TK_MOUSE_REMOVE: case A_TK_MOUSE_REMOVE:
lua_pushcfunction(L, luaA_widget_mouse_remove); lua_pushcfunction(L, luaA_widget_mouse_remove);
return 1; return 1;
case A_TK_SET:
lua_pushcfunction(L, luaA_widget_set);
return 1;
case A_TK_NAME_SET: case A_TK_NAME_SET:
lua_pushcfunction(L, luaA_widget_name_set); lua_pushcfunction(L, luaA_widget_name_set);
return 1; return 1;
@ -540,6 +439,8 @@ luaA_widget_index(lua_State *L)
lua_pushcfunction(L, luaA_widget_visible_get); lua_pushcfunction(L, luaA_widget_visible_get);
return 1; return 1;
default: default:
if((*widget)->index)
return (*widget)->index(L);
return 0; return 0;
} }
} }
@ -553,7 +454,6 @@ const struct luaL_reg awesome_widget_meta[] =
{ {
{ "mouse_add", luaA_widget_mouse_add }, { "mouse_add", luaA_widget_mouse_add },
{ "mouse_remove", luaA_widget_mouse_remove }, { "mouse_remove", luaA_widget_mouse_remove },
{ "set", luaA_widget_set },
{ "name_set", luaA_widget_name_set }, { "name_set", luaA_widget_name_set },
{ "name_get", luaA_widget_name_get }, { "name_get", luaA_widget_name_get },
{ "visible_set", luaA_widget_visible_set }, { "visible_set", luaA_widget_visible_set },

View File

@ -2,7 +2,6 @@
* widget.h - widget managing header * widget.h - widget managing header
* *
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info> * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -33,12 +32,12 @@
void widget_invalidate_cache(int, int); void widget_invalidate_cache(int, int);
int widget_calculate_offset(int, int, int, int); int widget_calculate_offset(int, int, int, int);
void widget_common_new(widget_t *); 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 *); 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 *); int luaA_widget_userdata_new(lua_State *, widget_t *);
void widget_invalidate_bywidget(widget_t *);
widget_constructor_t taglist_new; widget_constructor_t taglist_new;
widget_constructor_t textbox_new; widget_constructor_t textbox_new;
widget_constructor_t progressbar_new; widget_constructor_t progressbar_new;

View File

@ -34,13 +34,14 @@ typedef enum
Bottom_Style = 0, Bottom_Style = 0,
Top_Style, Top_Style,
Line_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; char *title;
/** Represents a full graph */ /** Represents a full graph */
float max_value; float max_value;
@ -55,7 +56,7 @@ struct graph_t
/** Pointer to current maximum value itself */ /** Pointer to current maximum value itself */
float current_max; float current_max;
/** Draw style of according index */ /** Draw style of according index */
draw_style_t draw_style; plot_style_t draw_style;
/** Keeps the calculated values (line-length); */ /** Keeps the calculated values (line-length); */
int *lines; int *lines;
/** Actual values */ /** Actual values */
@ -69,11 +70,11 @@ struct graph_t
/** Create a vertical color gradient */ /** Create a vertical color gradient */
bool vertical_gradient; bool vertical_gradient;
/** Next and previous graph */ /** Next and previous graph */
graph_t *next, *prev; plot_t *next, *prev;
}; };
static void static void
graph_delete(graph_t **g) plot_delete(plot_t **g)
{ {
p_delete(&(*g)->title); p_delete(&(*g)->title);
p_delete(&(*g)->lines); p_delete(&(*g)->lines);
@ -83,7 +84,7 @@ graph_delete(graph_t **g)
p_delete(g); p_delete(g);
} }
DO_SLIST(graph_t, graph, graph_delete) DO_SLIST(plot_t, plot, plot_delete)
typedef struct typedef struct
{ {
@ -106,12 +107,11 @@ typedef struct
/** Preparation/tmp array for draw_graph(); */ /** Preparation/tmp array for draw_graph(); */
int *draw_to; int *draw_to;
/** Graph list */ /** Graph list */
graph_t *graphs; plot_t *plots;
} graph_data_t; } graph_data_t;
/* the same as the progressbar_pcolor_set may use a common function */
static void static void
graph_pcolor_set(xcolor_t **ppcolor, char *new_color) plot_pcolor_set(xcolor_t **ppcolor, const char *new_color)
{ {
bool flag = false; bool flag = false;
if(!*ppcolor) if(!*ppcolor)
@ -126,22 +126,26 @@ graph_pcolor_set(xcolor_t **ppcolor, char *new_color)
p_delete(ppcolor); p_delete(ppcolor);
} }
static graph_t * /** Add a plot to a graph.
graph_data_add(graph_data_t *d, const char *new_data_title) * \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 */ plot->title = a_strdup(title);
graph->values = p_new(float, d->size); plot->values = p_new(float, d->size);
graph->lines = p_new(int, d->size); plot->lines = p_new(int, d->size);
graph->max_value = 100.0; plot->max_value = 100.0;
graph->title = a_strdup(new_data_title); plot->color_start = globalconf.colors.fg;
graph->color_start = globalconf.colors.fg; plot->vertical_gradient = true;
graph->vertical_gradient = true;
graph_list_append(&d->graphs, graph); plot_list_append(&d->plots, plot);
return graph; return plot;
} }
static int static int
@ -155,9 +159,9 @@ graph_draw(draw_context_t *ctx,
int margin_top, y; int margin_top, y;
graph_data_t *d = w->widget->data; graph_data_t *d = w->widget->data;
area_t rectangle, pattern_area; area_t rectangle, pattern_area;
graph_t *graph; plot_t *plot;
if(!d->graphs) if(!d->plots)
return 0; return 0;
w->area.x = widget_calculate_offset(ctx->width, w->area.x = widget_calculate_offset(ctx->width,
@ -165,7 +169,7 @@ graph_draw(draw_context_t *ctx,
w->widget->align); w->widget->align);
w->area.y = 0; w->area.y = 0;
/* box = the graph inside the rectangle */ /* box = the plot inside the rectangle */
if(!d->box_height) if(!d->box_height)
d->box_height = round(ctx->height * d->height) - 2; d->box_height = round(ctx->height * d->height) - 2;
@ -178,7 +182,7 @@ graph_draw(draw_context_t *ctx,
rectangle.height = d->box_height; rectangle.height = d->box_height;
draw_rectangle(ctx, rectangle, 1.0, true, d->bg); 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.y = margin_top + d->box_height + 1; /* bottom left corner as starting point */
rectangle.width = d->size; /* rectangle.height is not used */ rectangle.width = d->size; /* rectangle.height is not used */
@ -190,12 +194,12 @@ graph_draw(draw_context_t *ctx,
else else
pattern_area.x = rectangle.x; pattern_area.x = rectangle.x;
for(graph = d->graphs; graph; graph = graph->next) for(plot = d->plots; plot; plot = plot->next)
switch(graph->draw_style) switch(plot->draw_style)
{ {
case Top_Style: case Top_Style:
pattern_area.y = rectangle.y - rectangle.height; pattern_area.y = rectangle.y - rectangle.height;
if(graph->vertical_gradient) if(plot->vertical_gradient)
{ {
pattern_area.width = 0; pattern_area.width = 0;
pattern_area.height = rectangle.height; pattern_area.height = rectangle.height;
@ -214,14 +218,14 @@ graph_draw(draw_context_t *ctx,
{ {
/* reverse values (because drawing from top) */ /* reverse values (because drawing from top) */
d->draw_from[y] = d->box_height; /* i.e. no smaller value -> from top of box */ 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, draw_graph(ctx, rectangle , d->draw_from, d->draw_to, plot->index, d->grow, pattern_area,
&graph->color_start, graph->pcolor_center, graph->pcolor_end); &plot->color_start, plot->pcolor_center, plot->pcolor_end);
break; break;
case Bottom_Style: case Bottom_Style:
pattern_area.y = rectangle.y; pattern_area.y = rectangle.y;
if(graph->vertical_gradient) if(plot->vertical_gradient)
{ {
pattern_area.width = 0; pattern_area.width = 0;
pattern_area.height = - rectangle.height; pattern_area.height = - rectangle.height;
@ -237,12 +241,12 @@ graph_draw(draw_context_t *ctx,
} }
p_clear(d->draw_from, d->size); p_clear(d->draw_from, d->size);
draw_graph(ctx, rectangle, d->draw_from, graph->lines, graph->index, d->grow, pattern_area, draw_graph(ctx, rectangle, d->draw_from, plot->lines, plot->index, d->grow, pattern_area,
&graph->color_start, graph->pcolor_center, graph->pcolor_end); &plot->color_start, plot->pcolor_center, plot->pcolor_end);
break; break;
case Line_Style: case Line_Style:
pattern_area.y = rectangle.y; pattern_area.y = rectangle.y;
if(graph->vertical_gradient) if(plot->vertical_gradient)
{ {
pattern_area.width = 0; pattern_area.width = 0;
pattern_area.height = -rectangle.height; pattern_area.height = -rectangle.height;
@ -256,8 +260,8 @@ graph_draw(draw_context_t *ctx,
pattern_area.width = rectangle.width; pattern_area.width = rectangle.width;
} }
draw_graph_line(ctx, rectangle, graph->lines, graph->index, d->grow, pattern_area, draw_graph_line(ctx, rectangle, plot->lines, plot->index, d->grow, pattern_area,
&graph->color_start, graph->pcolor_center, graph->pcolor_end); &plot->color_start, plot->pcolor_center, plot->pcolor_end);
break; break;
} }
@ -273,191 +277,249 @@ graph_draw(draw_context_t *ctx,
return w->area.width; return w->area.width;
} }
static widget_tell_status_t /** Set various graph general properties.
graph_tell(widget_t *widget, const char *property, const char *new_value) * \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; widget_t **widget = luaA_checkudata(L, 1, "widget");
graph_t *graph; graph_data_t *d = (*widget)->data;
int i; plot_t *plot;
float value; int width;
char *title, *setting; const char *buf;
char *new_val; size_t len;
awesome_token_t prop = a_tokenize(property, -1); position_t pos;
if(!new_value) luaA_checktable(L, 2);
return WIDGET_ERROR_NOVALUE;
switch (prop) { d->height = luaA_getopt_number(L, 2, "height", d->height);
default:
return WIDGET_ERROR;
case A_TK_HEIGHT: width = luaA_getopt_number(L, 2, "width", d->width);
d->height = atof(new_value); if(width != d->width)
return WIDGET_NOERROR; {
case A_TK_WIDTH: d->width = width;
d->width = atoi(new_value);
d->size = d->width - 2; d->size = d->width - 2;
/* re-allocate/initialise necessary values */ for(plot = d->plots; plot; plot = plot->next)
for(graph = d->graphs; graph; graph = graph->next)
{ {
p_realloc(&graph->values, d->size); p_realloc(&plot->values, d->size);
p_realloc(&graph->lines, d->size); p_realloc(&plot->lines, d->size);
p_clear(graph->values, d->size); p_clear(plot->values, d->size);
p_clear(graph->lines, d->size); p_clear(plot->lines, d->size);
graph->index = 0; plot->index = 0;
graph->current_max = 0; plot->current_max = 0;
graph->max_index = 0; plot->max_index = 0;
} }
return WIDGET_NOERROR; }
case A_TK_BG:
if(!xcolor_new(globalconf.connection, if((buf = luaA_getopt_string(L, 2, "bg", NULL)))
globalconf.default_screen, xcolor_new(globalconf.connection, globalconf.default_screen, buf, &d->bg);
new_value, &d->bg)) if((buf = luaA_getopt_string(L, 2, "bordercolor", NULL)))
return WIDGET_ERROR_FORMAT_COLOR; xcolor_new(globalconf.connection, globalconf.default_screen, buf, &d->bordercolor);
return WIDGET_NOERROR;
case A_TK_BORDERCOLOR: if((buf = luaA_getopt_lstring(L, 2, "grow", NULL, &len)))
if(!xcolor_new(globalconf.connection, switch((pos = position_fromstr(buf, len)))
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)))
{ {
case Left: case Left:
case Right: case Right:
return WIDGET_NOERROR; d->grow = pos;
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;
break; break;
default: default:
warn("'error changing property %s of widget %s, must be 'bottom', 'top' or 'line'",
property, widget->name);
break; break;
} }
break;
default: widget_invalidate_bywidget(*widget);
break;
} return 0;
p_delete(&new_val);
return WIDGET_NOERROR;
} }
/** 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 static void
graph_destructor(widget_t *widget) graph_destructor(widget_t *widget)
{ {
graph_data_t *d = widget->data; 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_from);
p_delete(&d->draw_to); p_delete(&d->draw_to);
p_delete(&d); p_delete(&d);
} }
/** Create a brand new graph.
* \param align The widget alignment.
* \return A graph widget.
*/
widget_t * widget_t *
graph_new(alignment_t align) graph_new(alignment_t align)
{ {
@ -468,7 +530,7 @@ graph_new(alignment_t align)
widget_common_new(w); widget_common_new(w);
w->draw = graph_draw; w->draw = graph_draw;
w->tell = graph_tell; w->index = luaA_graph_index;
w->destructor = graph_destructor; w->destructor = graph_destructor;
w->align = align; w->align = align;
d = w->data = p_new(graph_data_t, 1); 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; typedef struct bar_t bar_t;
/** Progressbar bar data structure */
struct bar_t struct bar_t
{ {
/** Title of the data/bar */ /** Title of the data/bar */
@ -56,6 +57,9 @@ struct bar_t
bar_t *next, *prev; bar_t *next, *prev;
}; };
/** Delete a bar.
* \param bar The bar to annihilate.
*/
static void static void
bar_delete(bar_t **bar) bar_delete(bar_t **bar)
{ {
@ -67,6 +71,7 @@ bar_delete(bar_t **bar)
DO_SLIST(bar_t, bar, bar_delete) DO_SLIST(bar_t, bar, bar_delete)
/** Progressbar private data structure */
typedef struct typedef struct
{ {
/** Width of the data_items */ /** Width of the data_items */
@ -90,7 +95,7 @@ typedef struct
} progressbar_data_t; } progressbar_data_t;
static void static void
progressbar_pcolor_set(xcolor_t **ppcolor, char *new_color) progressbar_pcolor_set(xcolor_t **ppcolor, const char *new_color)
{ {
bool flag = false; bool flag = false;
if(!*ppcolor) if(!*ppcolor)
@ -105,13 +110,16 @@ progressbar_pcolor_set(xcolor_t **ppcolor, char *new_color)
p_delete(ppcolor); 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 * 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_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 = globalconf.colors.fg;
bar->fg_off = globalconf.colors.bg; bar->fg_off = globalconf.colors.bg;
bar->bg = 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; 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 static int
progressbar_draw(draw_context_t *ctx, progressbar_draw(draw_context_t *ctx,
int screen __attribute__ ((unused)), int screen __attribute__ ((unused)),
@ -399,132 +416,161 @@ progressbar_draw(draw_context_t *ctx,
return w->area.width; return w->area.width;
} }
static widget_tell_status_t /** Set various progressbar general properties:
progressbar_tell(widget_t *widget, const char *property, const char *new_value) * 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; widget_t **widget = luaA_checkudata(L, 1, "widget");
int value; progressbar_data_t *d = (*widget)->data;
char *title, *setting;
char *new_val;
bar_t *bar;
awesome_token_t prop = a_tokenize(property, -1);
if(!new_value) luaA_checktable(L, 2);
return WIDGET_ERROR_NOVALUE;
switch (prop) d->gap = luaA_getopt_number(L, 2, "gap", d->gap);
{ d->ticks_count = luaA_getopt_number(L, 2, "ticks_count", d->ticks_count);
case A_TK_GAP: d->ticks_gap = luaA_getopt_number(L, 2, "ticks_gap", d->ticks_gap);
d->gap = atoi(new_value); d->border_padding = luaA_getopt_number(L, 2, "border_padding", d->border_padding);
return WIDGET_NOERROR; d->border_width = luaA_getopt_number(L, 2, "border_width", d->border_width);
case A_TK_TICKS_COUNT: d->width = luaA_getopt_number(L, 2, "width", d->width);
d->ticks_count = atoi(new_value); d->height = luaA_getopt_number(L, 2, "height", d->height);
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;
/* following properties need a datasection */ d->vertical = luaA_getopt_boolean(L, 2, "vertical", d->vertical);
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;
/* no section found -> create one */ widget_invalidate_bywidget(*widget);
if(!bar)
bar = progressbar_data_add(d, title);
break;
default: return 0;
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;
} }
/** 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 static void
progressbar_destructor(widget_t *widget) progressbar_destructor(widget_t *widget)
{ {
@ -534,6 +580,10 @@ progressbar_destructor(widget_t *widget)
p_delete(&d); p_delete(&d);
} }
/** Create a new progressbar.
* \param align Alignment of the widget.
* \return A brand new progressbar.
*/
widget_t * widget_t *
progressbar_new(alignment_t align) progressbar_new(alignment_t align)
{ {
@ -544,7 +594,7 @@ progressbar_new(alignment_t align)
widget_common_new(w); widget_common_new(w);
w->align = align; w->align = align;
w->draw = progressbar_draw; w->draw = progressbar_draw;
w->tell = progressbar_tell; w->index = luaA_progressbar_index;
w->destructor = progressbar_destructor; w->destructor = progressbar_destructor;
d = w->data = p_new(progressbar_data_t, 1); d = w->data = p_new(progressbar_data_t, 1);

View File

@ -1,7 +1,7 @@
/* /*
* taglist.c - tag list widget * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -30,6 +30,9 @@
extern awesome_t globalconf; 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; typedef struct taglist_drawn_area_t taglist_drawn_area_t;
struct taglist_drawn_area_t struct taglist_drawn_area_t
{ {
@ -38,6 +41,9 @@ struct taglist_drawn_area_t
taglist_drawn_area_t *next, *prev; taglist_drawn_area_t *next, *prev;
}; };
/** Delete a taglist_drawn_area_t object.
* \param a The drawn area to delete.
*/
static void static void
taglist_drawn_area_delete(taglist_drawn_area_t **a) 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); DO_SLIST(taglist_drawn_area_t, taglist_drawn_area, taglist_drawn_area_delete);
/** Taglist widget private data */
typedef struct typedef struct
{ {
char *text_normal, *text_focus, *text_urgent; char *text_normal, *text_focus, *text_urgent;
bool show_empty; bool show_empty;
taglist_drawn_area_t *drawn_area; taglist_drawn_area_t *drawn_area;
} taglist_data_t; } 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 static void
tag_markup_on_elem(markup_parser_data_t *p, const char *elem, tag_markup_on_elem(markup_parser_data_t *p, const char *elem,
const char **names, const char **values) 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)); 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 * static char *
tag_markup_parse(tag_t *t, const char *str, ssize_t len) 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; return ret;
} }
/** Check if at least one client is tagged with tag number t and is on screen /** Check if at least one client is tagged with tag number t.
* screen * \param t The tag to check.
* \param t tag * \return True if the tag has a client, false otherwise.
* \return true or false
*/ */
static bool static bool
tag_isoccupied(tag_t *t) tag_isoccupied(tag_t *t)
@ -99,24 +116,33 @@ tag_isoccupied(tag_t *t)
client_t *c; client_t *c;
for(c = globalconf.clients; c; c = c->next) 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 true;
return false; 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 static bool
tag_isurgent(tag_t *t) tag_isurgent(tag_t *t)
{ {
client_t *c; client_t *c;
for(c = globalconf.clients; c; c = c->next) 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 true;
return false; 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 * static char *
taglist_text_get(tag_t *tag, taglist_data_t *data) 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; return data->text_focus;
else if(tag_isurgent(tag)) else if(tag_isurgent(tag))
return data->text_urgent; return data->text_urgent;
return data->text_normal; 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 static int
taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w, taglist_draw(draw_context_t *ctx, int screen, widget_node_t *w,
int offset, int offset,
@ -254,34 +288,92 @@ taglist_button_press(widget_node_t *w,
} }
} }
static widget_tell_status_t /** Set text format string in case of a tag is normal, has focused client
taglist_tell(widget_t *widget, const char *property, const char *new_value) * 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); p_delete(&d->text_normal);
d->text_normal = a_strdup(new_value); d->text_normal = a_strdup(buf);
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;
} }
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 static void
taglist_destructor(widget_t *widget) taglist_destructor(widget_t *widget)
{ {
@ -294,6 +386,10 @@ taglist_destructor(widget_t *widget)
p_delete(&d); p_delete(&d);
} }
/** Create a brand new taglist widget.
* \param align Widget alignment.
* \return A taglist widget.
*/
widget_t * widget_t *
taglist_new(alignment_t align) taglist_new(alignment_t align)
{ {
@ -302,10 +398,10 @@ taglist_new(alignment_t align)
w = p_new(widget_t, 1); w = p_new(widget_t, 1);
widget_common_new(w); widget_common_new(w);
w->index = luaA_taglist_index;
w->align = align; w->align = align;
w->draw = taglist_draw; w->draw = taglist_draw;
w->button_press = taglist_button_press; w->button_press = taglist_button_press;
w->tell = taglist_tell;
w->destructor = taglist_destructor; w->destructor = taglist_destructor;
w->data = d = p_new(taglist_data_t, 1); w->data = d = p_new(taglist_data_t, 1);

View File

@ -39,6 +39,7 @@ typedef enum
ShowAll, ShowAll,
} showclient_t; } showclient_t;
/** The tasklist private data structure. */
typedef struct typedef struct
{ {
showclient_t show; showclient_t show;
@ -46,6 +47,18 @@ typedef struct
char *text_normal, *text_urgent, *text_focus; char *text_normal, *text_urgent, *text_focus;
} tasklist_data_t; } 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 static inline bool
tasklist_isvisible(client_t *c, int screen, showclient_t show) 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; return false;
} }
struct tasklist_hook_data /** Called when a markup element is found.
{ * \param p The markup parser data.
draw_context_t *ctx; * \param elem The element name.
area_t *area; * \param names The attributes names.
}; * \param values The attributes values.
*/
static void static void
tasklist_markup_on_elem(markup_parser_data_t *p, const char *elem, tasklist_markup_on_elem(markup_parser_data_t *p, const char *elem,
const char **names, const char **values) 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 static int
tasklist_draw(draw_context_t *ctx, int screen, tasklist_draw(draw_context_t *ctx, int screen,
widget_node_t *w, widget_node_t *w,
int offset, int used, void *q __attribute__ ((unused))) int offset, int used, void *p __attribute__ ((unused)))
{ {
client_t *c; client_t *c;
tasklist_data_t *d = w->widget->data; 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 }; static char const * const elements[] = { "bg", NULL };
struct tasklist_hook_data data = { .ctx = ctx, .area = &area }; struct tasklist_hook_data data = { .ctx = ctx, .area = &area };
markup_parser_data_t p = markup_parser_data_t pdata =
{ {
.elements = elements, .elements = elements,
.on_element = &tasklist_markup_on_elem, .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 /* Actually look for the proper background color, since
* otherwise the background statusbar color is used instead */ * otherwise the background statusbar color is used instead */
markup_parser_data_init(&p); markup_parser_data_init(&pdata);
markup_parse(&p, text, a_strlen(text)); markup_parse(&pdata, text, a_strlen(text));
markup_parser_data_wipe(&p); markup_parser_data_wipe(&pdata);
if((image = draw_image_new(c->icon_path))) if((image = draw_image_new(c->icon_path)))
{ {
@ -257,50 +277,126 @@ tasklist_button_press(widget_node_t *w,
} }
} }
static widget_tell_status_t /** Set the tasklist show attribute.
tasklist_tell(widget_t *widget, const char *property, const char *new_value) * \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: case A_TK_TAGS:
p_delete(&d->text_normal); d->show = ShowTags;
d->text_normal = a_strdup(new_value);
break; break;
case A_TK_TEXT_FOCUS: case A_TK_FOCUS:
p_delete(&d->text_focus); d->show = ShowFocus;
d->text_focus = a_strdup(new_value);
break; break;
case A_TK_TEXT_URGENT: case A_TK_ALL:
p_delete(&d->text_urgent); d->show = ShowAll;
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;
}
break; break;
default: 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 static void
tasklist_destructor(widget_t *widget) tasklist_destructor(widget_t *widget)
{ {
@ -312,6 +408,10 @@ tasklist_destructor(widget_t *widget)
p_delete(&d); 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 * widget_t *
tasklist_new(alignment_t align __attribute__ ((unused))) tasklist_new(alignment_t align __attribute__ ((unused)))
{ {
@ -323,8 +423,8 @@ tasklist_new(alignment_t align __attribute__ ((unused)))
w->draw = tasklist_draw; w->draw = tasklist_draw;
w->button_press = tasklist_button_press; w->button_press = tasklist_button_press;
w->align = AlignFlex; w->align = AlignFlex;
w->index = luaA_tasklist_index;
w->data = d = p_new(tasklist_data_t, 1); w->data = d = p_new(tasklist_data_t, 1);
w->tell = tasklist_tell;
w->destructor = tasklist_destructor; w->destructor = tasklist_destructor;
d->text_normal = a_strdup(" <title/> "); d->text_normal = a_strdup(" <title/> ");

View File

@ -2,7 +2,6 @@
* textbox.c - text box widget * textbox.c - text box widget
* *
* Copyright © 2007-2008 Julien Danjou <julien@danjou.info> * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -28,12 +27,24 @@
extern awesome_t globalconf; extern awesome_t globalconf;
/** The textbox private data structure */
typedef struct typedef struct
{ {
/** Textbox text */
char *text; char *text;
/** Textbox width */
int width; int width;
} textbox_data_t; } 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 static int
textbox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)), textbox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)),
widget_node_t *w, widget_node_t *w,
@ -72,27 +83,9 @@ textbox_draw(draw_context_t *ctx, int screen __attribute__ ((unused)),
return w->area.width; return w->area.width;
} }
static widget_tell_status_t /** Delete a textbox widget.
textbox_tell(widget_t *widget, const char *property, const char *new_value) * \param w The widget to destroy.
{ */
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;
}
static void static void
textbox_destructor(widget_t *w) textbox_destructor(widget_t *w)
{ {
@ -101,6 +94,77 @@ textbox_destructor(widget_t *w)
p_delete(&d); 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 * widget_t *
textbox_new(alignment_t align) textbox_new(alignment_t align)
{ {
@ -111,7 +175,7 @@ textbox_new(alignment_t align)
widget_common_new(w); widget_common_new(w);
w->align = align; w->align = align;
w->draw = textbox_draw; w->draw = textbox_draw;
w->tell = textbox_tell; w->index = luaA_textbox_index;
w->destructor = textbox_destructor; w->destructor = textbox_destructor;
w->data = d = p_new(textbox_data_t, 1); w->data = d = p_new(textbox_data_t, 1);