imagebox: don't draw anything is not enough space (FS#368)
[awesome.git] / widgets / imagebox.c
blob046d4dfef7b0609971f2b44f7b3aa8071ce09827
1 /*
2 * imagebox.c - imagebox widget
4 * Copyright © 2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "widget.h"
23 #include "titlebar.h"
25 extern awesome_t globalconf;
27 /** The imagebox private data structure */
28 typedef struct
30 /** Imagebox image */
31 image_t *image;
32 xcolor_t bg;
33 alignment_t valign;
34 bool resize;
35 } imagebox_data_t;
37 static area_t
38 imagebox_geometry(widget_t *widget, int screen, int height, int width)
40 area_t geometry;
41 imagebox_data_t *d = widget->data;
43 if(d->image)
45 if(d->resize)
47 geometry.width = ((double) height / (double) d->image->height) * d->image->width;
48 geometry.height = height;
49 if(geometry.width > width)
51 geometry.width = 0;
52 geometry.height = 0;
55 else if(d->image->width <= width)
57 geometry.width = d->image->width;
58 geometry.height = height;
60 else
62 geometry.width = 0;
63 geometry.height = 0;
66 else
68 geometry.width = 0;
69 geometry.height = 0;
72 return geometry;
75 /** Draw an image.
76 * \param widget The widget.
77 * \param ctx The draw context.
78 * \param geometry The geometry we draw in.
79 * \param screen The screen.
80 * \param p A pointer to the object we're draw onto.
82 static void
83 imagebox_draw(widget_t *widget, draw_context_t *ctx, area_t geometry,
84 int screen, wibox_t *p)
86 imagebox_data_t *d = widget->data;
88 if(d->image && geometry.width && geometry.height)
90 if(d->bg.initialized)
91 draw_rectangle(ctx, geometry, 1.0, true, &d->bg);
93 int y = geometry.y;
94 switch(d->valign)
96 case AlignBottom:
97 y += geometry.height - d->image->height;
98 break;
99 case AlignCenter:
100 y += (geometry.height - d->image->height) / 2;
101 break;
102 default:
103 break;
106 draw_image(ctx, geometry.x, y, d->resize ? ctx->height : 0, d->image);
110 /** Delete a imagebox widget.
111 * \param w The widget to destroy.
113 static void
114 imagebox_destructor(widget_t *w)
116 imagebox_data_t *d = w->data;
117 image_unref(&d->image);
118 p_delete(&d);
121 /** Imagebox widget.
122 * \param L The Lua VM state.
123 * \param token The key token.
124 * \param resize Resize image.
125 * \param valign Vertical alignment, top, bottom or center.
126 * \return The number of elements pushed on stack.
127 * \luastack
128 * \lfield image The image to display.
129 * \lfield bg The background color to use.
131 static int
132 luaA_imagebox_index(lua_State *L, awesome_token_t token)
134 widget_t **widget = luaA_checkudata(L, 1, "widget");
135 imagebox_data_t *d = (*widget)->data;
137 switch(token)
139 case A_TK_IMAGE:
140 if(d->image)
141 return luaA_image_userdata_new(L, d->image);
142 else
143 return 0;
144 case A_TK_BG:
145 luaA_pushcolor(L, &d->bg);
146 break;
147 case A_TK_RESIZE:
148 lua_pushboolean(L, d->resize);
149 break;
150 case A_TK_VALIGN:
151 lua_pushstring(L, draw_align_tostr(d->valign));
152 break;
153 default:
154 return 0;
157 return 1;
160 /** The __newindex method for a imagebox object.
161 * \param L The Lua VM state.
162 * \param token The key token.
163 * \return The number of elements pushed on stack.
165 static int
166 luaA_imagebox_newindex(lua_State *L, awesome_token_t token)
168 widget_t **widget = luaA_checkudata(L, 1, "widget");
169 image_t **image = NULL;
170 imagebox_data_t *d = (*widget)->data;
172 switch(token)
174 const char *buf;
175 size_t len;
177 case A_TK_IMAGE:
178 if(lua_isnil(L, 3)
179 || (image = luaA_checkudata(L, 3, "image")))
181 /* unref image */
182 image_unref(&d->image);
183 if(image)
184 d->image = image_ref(image);
185 else
186 d->image = NULL;
188 break;
189 case A_TK_BG:
190 if(lua_isnil(L, 3))
191 p_clear(&d->bg, 1);
192 else if((buf = luaL_checklstring(L, 3, &len)))
193 xcolor_init_reply(xcolor_init_unchecked(&d->bg, buf, len));
194 break;
195 case A_TK_RESIZE:
196 d->resize = luaA_checkboolean(L, 3);
197 break;
198 case A_TK_VALIGN:
199 if((buf = luaL_checklstring(L, 3, &len)))
200 d->valign = draw_align_fromstr(buf, len);
201 break;
202 default:
203 return 0;
206 widget_invalidate_bywidget(*widget);
208 return 0;
212 /** Create a new imagebox widget.
213 * \param align Widget alignment.
214 * \return A brand new widget.
216 widget_t *
217 imagebox_new(alignment_t align)
219 widget_t *w = p_new(widget_t, 1);
220 imagebox_data_t *d;
221 widget_common_new(w);
222 w->align = align;
223 w->draw = imagebox_draw;
224 w->index = luaA_imagebox_index;
225 w->newindex = luaA_imagebox_newindex;
226 w->destructor = imagebox_destructor;
227 w->geometry = imagebox_geometry;
228 w->data = d = p_new(imagebox_data_t, 1);
229 d->resize = true;
230 d->valign = AlignTop;
232 return w;
235 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80