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
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/>.
18 * Miguel de Icaza <miguel@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
28 #include <gdk/gdkkeysyms.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
{
53 G_DEFINE_TYPE (ECellToggle
, e_cell_toggle
, E_TYPE_CELL
)
61 cell_toggle_load_icons (ECellToggle
*cell_toggle
)
63 GtkIconTheme
*icon_theme
;
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
);
83 g_warning ("%s", error
->message
);
84 g_clear_error (&error
);
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
;
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
);
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
);
117 cell_toggle_finalize (GObject
*object
)
119 ECellTogglePrivate
*priv
;
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
);
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
;
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
);
171 cell_toggle_draw (ECellView
*ecell_view
,
182 ECellTogglePrivate
*priv
;
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
)
194 image
= g_ptr_array_index (priv
->pixbufs
, value
);
196 if ((x2
- x1
) < gdk_pixbuf_get_width (image
))
199 x
= x1
+ ((x2
- x1
) - gdk_pixbuf_get_width (image
)) / 2;
201 if ((y2
- y1
) < gdk_pixbuf_get_height (image
))
204 y
= y1
+ ((y2
- y1
) - gdk_pixbuf_get_height (image
)) / 2;
207 gdk_cairo_set_source_pixbuf (cr
, image
, x
, y
);
208 cairo_paint_with_alpha (cr
, 1);
213 etog_set_value (ECellToggleView
*toggle_view
,
219 ECellTogglePrivate
*priv
;
221 priv
= E_CELL_TOGGLE_GET_PRIVATE (toggle_view
->cell_view
.ecell
);
223 if (value
>= priv
->pixbufs
->len
)
226 e_table_model_set_value_at (
227 toggle_view
->cell_view
.e_table_model
,
228 model_col
, row
, GINT_TO_POINTER (value
));
232 cell_toggle_event (ECellView
*ecell_view
,
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
) {
247 if (event
->key
.keyval
!= GDK_KEY_space
)
250 case GDK_BUTTON_PRESS
:
251 if (!e_table_model_is_cell_editable (
252 ecell_view
->e_table_model
, model_col
, row
))
256 toggle_view
, model_col
, view_col
, row
, value
+ 1);
266 cell_toggle_height (ECellView
*ecell_view
,
271 ECellTogglePrivate
*priv
;
273 priv
= E_CELL_TOGGLE_GET_PRIVATE (ecell_view
->ecell
);
279 cell_toggle_print (ECellView
*ecell_view
,
280 GtkPrintContext
*context
,
287 ECellTogglePrivate
*priv
;
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
));
295 priv
= E_CELL_TOGGLE_GET_PRIVATE (ecell_view
->ecell
);
297 if (value
>= priv
->pixbufs
->len
)
300 image
= g_ptr_array_index (priv
->pixbufs
, value
);
302 cr
= gtk_print_context_get_cairo_context (context
);
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
);
312 image_width
- image_width
/ 4,
313 image_width
- image_height
/ 7);
315 gdk_cairo_set_source_pixbuf (cr
, image
, 0, image_height
/ 4);
322 cell_toggle_print_height (ECellView
*ecell_view
,
323 GtkPrintContext
*context
,
329 ECellTogglePrivate
*priv
;
331 priv
= E_CELL_TOGGLE_GET_PRIVATE (ecell_view
->ecell
);
337 cell_toggle_max_width (ECellView
*ecell_view
,
341 ECellTogglePrivate
*priv
;
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
++) {
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
));
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
);
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
412 e_cell_toggle_construct (ECellToggle
*cell_toggle
,
413 const gchar
**icon_names
,
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
);
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
444 * Returns: an ECell object that can be used to render multi-state
448 e_cell_toggle_new (const gchar
**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
;
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
;