Updated Hungarian translation
[evolution.git] / e-util / e-cell-toggle.c
blob716e70cb882a2d4809da22d791167898bf102956
1 /*
2 * e-cell-toggle.c - Multi-state image toggle cell object.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Authors:
18 * Miguel de Icaza <miguel@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <gdk/gdkkeysyms.h>
29 #include <gtk/gtk.h>
30 #include <libgnomecanvas/libgnomecanvas.h>
32 #include "art/empty.xpm"
34 #include "gal-a11y-e-cell-toggle.h"
35 #include "gal-a11y-e-cell-registry.h"
37 #include "e-cell-toggle.h"
38 #include "e-table-item.h"
40 #define E_CELL_TOGGLE_GET_PRIVATE(obj) \
41 (G_TYPE_INSTANCE_GET_PRIVATE \
42 ((obj), E_TYPE_CELL_TOGGLE, ECellTogglePrivate))
44 struct _ECellTogglePrivate {
45 gchar **icon_names;
46 guint n_icon_names;
48 GdkPixbuf *empty;
49 GPtrArray *pixbufs;
50 gint height;
53 G_DEFINE_TYPE (ECellToggle, e_cell_toggle, E_TYPE_CELL)
55 typedef struct {
56 ECellView cell_view;
57 GnomeCanvas *canvas;
58 } ECellToggleView;
60 static void
61 cell_toggle_load_icons (ECellToggle *cell_toggle)
63 GtkIconTheme *icon_theme;
64 gint width, height;
65 gint max_height = 0;
66 guint ii;
67 GError *error = NULL;
69 icon_theme = gtk_icon_theme_get_default ();
70 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
72 g_ptr_array_set_size (cell_toggle->priv->pixbufs, 0);
74 for (ii = 0; ii < cell_toggle->priv->n_icon_names; ii++) {
75 const gchar *icon_name = cell_toggle->priv->icon_names[ii];
76 GdkPixbuf *pixbuf = NULL;
78 if (icon_name != NULL)
79 pixbuf = gtk_icon_theme_load_icon (
80 icon_theme, icon_name, height, GTK_ICON_LOOKUP_FORCE_SIZE, &error);
82 if (error != NULL) {
83 g_warning ("%s", error->message);
84 g_clear_error (&error);
87 if (pixbuf == NULL)
88 pixbuf = g_object_ref (cell_toggle->priv->empty);
90 g_ptr_array_add (cell_toggle->priv->pixbufs, pixbuf);
91 max_height = MAX (max_height, gdk_pixbuf_get_height (pixbuf));
94 cell_toggle->priv->height = max_height;
97 static void
98 cell_toggle_dispose (GObject *object)
100 ECellTogglePrivate *priv;
102 priv = E_CELL_TOGGLE_GET_PRIVATE (object);
104 if (priv->empty != NULL) {
105 g_object_unref (priv->empty);
106 priv->empty = NULL;
109 /* This unrefs all the elements. */
110 g_ptr_array_set_size (priv->pixbufs, 0);
112 /* Chain up to parent's dispose() method. */
113 G_OBJECT_CLASS (e_cell_toggle_parent_class)->dispose (object);
116 static void
117 cell_toggle_finalize (GObject *object)
119 ECellTogglePrivate *priv;
120 guint ii;
122 priv = E_CELL_TOGGLE_GET_PRIVATE (object);
124 /* The array is not NULL-terminated,
125 * so g_strfreev() will not work. */
126 for (ii = 0; ii < priv->n_icon_names; ii++)
127 g_free (priv->icon_names[ii]);
128 g_free (priv->icon_names);
130 g_ptr_array_free (priv->pixbufs, TRUE);
132 /* Chain up to parent's finalize() method. */
133 G_OBJECT_CLASS (e_cell_toggle_parent_class)->finalize (object);
136 static ECellView *
137 cell_toggle_new_view (ECell *ecell,
138 ETableModel *table_model,
139 gpointer e_table_item_view)
141 ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1);
142 ETableItem *eti = E_TABLE_ITEM (e_table_item_view);
143 GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
145 toggle_view->cell_view.ecell = ecell;
146 toggle_view->cell_view.e_table_model = table_model;
147 toggle_view->cell_view.e_table_item_view = e_table_item_view;
148 toggle_view->cell_view.kill_view_cb = NULL;
149 toggle_view->cell_view.kill_view_cb_data = NULL;
150 toggle_view->canvas = canvas;
152 return (ECellView *) toggle_view;
155 static void
156 cell_toggle_kill_view (ECellView *ecell_view)
158 ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
160 if (toggle_view->cell_view.kill_view_cb)
161 toggle_view->cell_view.kill_view_cb (
162 ecell_view, toggle_view->cell_view.kill_view_cb_data);
164 if (toggle_view->cell_view.kill_view_cb_data)
165 g_list_free (toggle_view->cell_view.kill_view_cb_data);
167 g_free (ecell_view);
170 static void
171 cell_toggle_draw (ECellView *ecell_view,
172 cairo_t *cr,
173 gint model_col,
174 gint view_col,
175 gint row,
176 ECellFlags flags,
177 gint x1,
178 gint y1,
179 gint x2,
180 gint y2)
182 ECellTogglePrivate *priv;
183 GdkPixbuf *image;
184 gint x, y;
186 const gint value = GPOINTER_TO_INT (
187 e_table_model_value_at (ecell_view->e_table_model, model_col, row));
189 priv = E_CELL_TOGGLE_GET_PRIVATE (ecell_view->ecell);
191 if (value < 0 || value >= priv->pixbufs->len)
192 return;
194 image = g_ptr_array_index (priv->pixbufs, value);
196 if ((x2 - x1) < gdk_pixbuf_get_width (image))
197 x = x1;
198 else
199 x = x1 + ((x2 - x1) - gdk_pixbuf_get_width (image)) / 2;
201 if ((y2 - y1) < gdk_pixbuf_get_height (image))
202 y = y1;
203 else
204 y = y1 + ((y2 - y1) - gdk_pixbuf_get_height (image)) / 2;
206 cairo_save (cr);
207 gdk_cairo_set_source_pixbuf (cr, image, x, y);
208 cairo_paint_with_alpha (cr, 1);
209 cairo_restore (cr);
212 static void
213 etog_set_value (ECellToggleView *toggle_view,
214 gint model_col,
215 gint view_col,
216 gint row,
217 gint value)
219 ECellTogglePrivate *priv;
221 priv = E_CELL_TOGGLE_GET_PRIVATE (toggle_view->cell_view.ecell);
223 if (value >= priv->pixbufs->len)
224 value = 0;
226 e_table_model_set_value_at (
227 toggle_view->cell_view.e_table_model,
228 model_col, row, GINT_TO_POINTER (value));
231 static gint
232 cell_toggle_event (ECellView *ecell_view,
233 GdkEvent *event,
234 gint model_col,
235 gint view_col,
236 gint row,
237 ECellFlags flags,
238 ECellActions *actions)
240 ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
241 gpointer _value = e_table_model_value_at (
242 ecell_view->e_table_model, model_col, row);
243 const gint value = GPOINTER_TO_INT (_value);
245 switch (event->type) {
246 case GDK_KEY_PRESS:
247 if (event->key.keyval != GDK_KEY_space)
248 return FALSE;
249 /* Fall through */
250 case GDK_BUTTON_PRESS:
251 if (!e_table_model_is_cell_editable (
252 ecell_view->e_table_model, model_col, row))
253 return FALSE;
255 etog_set_value (
256 toggle_view, model_col, view_col, row, value + 1);
258 return TRUE;
260 default:
261 return FALSE;
265 static gint
266 cell_toggle_height (ECellView *ecell_view,
267 gint model_col,
268 gint view_col,
269 gint row)
271 ECellTogglePrivate *priv;
273 priv = E_CELL_TOGGLE_GET_PRIVATE (ecell_view->ecell);
275 return priv->height;
278 static void
279 cell_toggle_print (ECellView *ecell_view,
280 GtkPrintContext *context,
281 gint model_col,
282 gint view_col,
283 gint row,
284 gdouble width,
285 gdouble height)
287 ECellTogglePrivate *priv;
288 GdkPixbuf *image;
289 gdouble image_width, image_height;
290 const gint value = GPOINTER_TO_INT (
291 e_table_model_value_at (ecell_view->e_table_model, model_col, row));
293 cairo_t *cr;
295 priv = E_CELL_TOGGLE_GET_PRIVATE (ecell_view->ecell);
297 if (value >= priv->pixbufs->len)
298 return;
300 image = g_ptr_array_index (priv->pixbufs, value);
301 if (image) {
302 cr = gtk_print_context_get_cairo_context (context);
303 cairo_save (cr);
304 cairo_translate (cr, 0 , 0);
305 image = gdk_pixbuf_add_alpha (image, TRUE, 255, 255, 255);
306 image_width = (gdouble) gdk_pixbuf_get_width (image);
307 image_height = (gdouble) gdk_pixbuf_get_height (image);
308 cairo_rectangle (
310 image_width / 7,
311 image_height / 3,
312 image_width - image_width / 4,
313 image_width - image_height / 7);
314 cairo_clip (cr);
315 gdk_cairo_set_source_pixbuf (cr, image, 0, image_height / 4);
316 cairo_paint (cr);
317 cairo_restore (cr);
321 static gdouble
322 cell_toggle_print_height (ECellView *ecell_view,
323 GtkPrintContext *context,
324 gint model_col,
325 gint view_col,
326 gint row,
327 gdouble width)
329 ECellTogglePrivate *priv;
331 priv = E_CELL_TOGGLE_GET_PRIVATE (ecell_view->ecell);
333 return priv->height;
336 static gint
337 cell_toggle_max_width (ECellView *ecell_view,
338 gint model_col,
339 gint view_col)
341 ECellTogglePrivate *priv;
342 gint max_width = 0;
343 gint number_of_rows;
344 gint row;
346 priv = E_CELL_TOGGLE_GET_PRIVATE (ecell_view->ecell);
348 number_of_rows = e_table_model_row_count (ecell_view->e_table_model);
349 for (row = 0; row < number_of_rows; row++) {
350 GdkPixbuf *pixbuf;
351 gpointer value;
353 value = e_table_model_value_at (
354 ecell_view->e_table_model, model_col, row);
355 pixbuf = g_ptr_array_index (
356 priv->pixbufs, GPOINTER_TO_INT (value));
358 max_width = MAX (max_width, gdk_pixbuf_get_width (pixbuf));
361 return max_width;
364 static void
365 e_cell_toggle_class_init (ECellToggleClass *class)
367 GObjectClass *object_class;
368 ECellClass *cell_class;
370 g_type_class_add_private (class, sizeof (ECellTogglePrivate));
372 object_class = G_OBJECT_CLASS (class);
373 object_class->dispose = cell_toggle_dispose;
374 object_class->finalize = cell_toggle_finalize;
376 cell_class = E_CELL_CLASS (class);
377 cell_class->new_view = cell_toggle_new_view;
378 cell_class->kill_view = cell_toggle_kill_view;
379 cell_class->draw = cell_toggle_draw;
380 cell_class->event = cell_toggle_event;
381 cell_class->height = cell_toggle_height;
382 cell_class->print = cell_toggle_print;
383 cell_class->print_height = cell_toggle_print_height;
384 cell_class->max_width = cell_toggle_max_width;
386 gal_a11y_e_cell_registry_add_cell_type (
387 NULL, E_TYPE_CELL_TOGGLE, gal_a11y_e_cell_toggle_new);
390 static void
391 e_cell_toggle_init (ECellToggle *cell_toggle)
393 cell_toggle->priv = E_CELL_TOGGLE_GET_PRIVATE (cell_toggle);
395 cell_toggle->priv->empty =
396 gdk_pixbuf_new_from_xpm_data (empty_xpm);
398 cell_toggle->priv->pixbufs =
399 g_ptr_array_new_with_free_func (g_object_unref);
403 * e_cell_toggle_construct:
404 * @cell_toggle: a fresh ECellToggle object
405 * @icon_names: array of icon names, some of which may be %NULL
406 * @n_icon_names: length of the @icon_names array
408 * Constructs the @cell_toggle object with the @icon_names and @n_icon_names
409 * arguments.
411 void
412 e_cell_toggle_construct (ECellToggle *cell_toggle,
413 const gchar **icon_names,
414 guint n_icon_names)
416 guint ii;
418 g_return_if_fail (E_IS_CELL_TOGGLE (cell_toggle));
419 g_return_if_fail (icon_names != NULL);
420 g_return_if_fail (n_icon_names > 0);
422 cell_toggle->priv->icon_names = g_new (gchar *, n_icon_names);
423 cell_toggle->priv->n_icon_names = n_icon_names;
425 for (ii = 0; ii < n_icon_names; ii++)
426 cell_toggle->priv->icon_names[ii] = g_strdup (icon_names[ii]);
428 cell_toggle_load_icons (cell_toggle);
432 * e_cell_toggle_new:
433 * @icon_names: array of icon names, some of which may be %NULL
434 * @n_icon_names: length of the @icon_names array
436 * Creates a new ECell renderer that can be used to render toggle
437 * buttons with the icons specified in @icon_names. The value returned
438 * by ETableModel::get_value is typecast into an integer and clamped
439 * to the [0..n_icon_names) range. That will select the image rendered.
441 * %NULL elements in @icon_names will show no icon for the corresponding
442 * integer value.
444 * Returns: an ECell object that can be used to render multi-state
445 * toggle cells.
447 ECell *
448 e_cell_toggle_new (const gchar **icon_names,
449 guint n_icon_names)
451 ECellToggle *cell_toggle;
453 g_return_val_if_fail (icon_names != NULL, NULL);
454 g_return_val_if_fail (n_icon_names > 0, NULL);
456 cell_toggle = g_object_new (E_TYPE_CELL_TOGGLE, NULL);
457 e_cell_toggle_construct (cell_toggle, icon_names, n_icon_names);
459 return (ECell *) cell_toggle;
462 GPtrArray *
463 e_cell_toggle_get_pixbufs (ECellToggle *cell_toggle)
465 g_return_val_if_fail (E_IS_CELL_TOGGLE (cell_toggle), NULL);
467 return cell_toggle->priv->pixbufs;