comparison gtk/gtkcellrendererexpander.c @ 14561:3ff55ec8203a

[gaim-migrate @ 17284] GtkCellRendererExpander draws an expander in a renderer to avoid a large, needless margin. The approach is a bit hacky, but it's a good job. - RTL fix in GtkStatusBox - Drag-and-drop image into the global buddy icon selector to set a buddy icon committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Fri, 15 Sep 2006 22:05:34 +0000
parents
children 4c14862f7fcc
comparison
equal deleted inserted replaced
14560:16bba6d02c2a 14561:3ff55ec8203a
1 /*
2 * @file gtkcellrendererexpander.c GTK+ Cell Renderer Expander
3 * @ingroup gtkui
4 *
5 * gaim
6 *
7 * Gaim is the legal property of its developers, whose names are too numerous
8 * to list here. Please refer to the COPYRIGHT file distributed with this
9 * source distribution.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27 /* This is taken largely from GtkCellRenderer[Text|Pixbuf|Toggle] by
28 * Jonathon Blandford <jrb@redhat.com> for RedHat, Inc.
29 */
30
31 #include <gtk/gtktreeview.h>
32 #include "gtkcellrendererexpander.h"
33
34 static void gaim_gtk_cell_renderer_expander_get_property (GObject *object,
35 guint param_id,
36 GValue *value,
37 GParamSpec *pspec);
38 static void gaim_gtk_cell_renderer_expander_set_property (GObject *object,
39 guint param_id,
40 const GValue *value,
41 GParamSpec *pspec);
42 static void gaim_gtk_cell_renderer_expander_init (GaimGtkCellRendererExpander *cellexpander);
43 static void gaim_gtk_cell_renderer_expander_class_init (GaimGtkCellRendererExpanderClass *class);
44 static void gaim_gtk_cell_renderer_expander_get_size (GtkCellRenderer *cell,
45 GtkWidget *widget,
46 GdkRectangle *cell_area,
47 gint *x_offset,
48 gint *y_offset,
49 gint *width,
50 gint *height);
51 static void gaim_gtk_cell_renderer_expander_render (GtkCellRenderer *cell,
52 GdkWindow *window,
53 GtkWidget *widget,
54 GdkRectangle *background_area,
55 GdkRectangle *cell_area,
56 GdkRectangle *expose_area,
57 guint flags);
58 static gboolean gaim_gtk_cell_renderer_expander_activate (GtkCellRenderer *cell,
59 GdkEvent *event,
60 GtkWidget *widget,
61 const gchar *path,
62 GdkRectangle *background_area,
63 GdkRectangle *cell_area,
64 guint flags);
65 static void gaim_gtk_cell_renderer_expander_finalize (GObject *gobject);
66
67 enum {
68 LAST_SIGNAL
69 };
70
71 enum {
72 PROP_0,
73 PROP_IS_EXPANDER
74 };
75
76 static gpointer parent_class;
77 /* static guint expander_cell_renderer_signals [LAST_SIGNAL]; */
78
79 GType gaim_gtk_cell_renderer_expander_get_type (void)
80 {
81 static GType cell_expander_type = 0;
82
83 if (!cell_expander_type)
84 {
85 static const GTypeInfo cell_expander_info =
86 {
87 sizeof (GaimGtkCellRendererExpanderClass),
88 NULL, /* base_init */
89 NULL, /* base_finalize */
90 (GClassInitFunc) gaim_gtk_cell_renderer_expander_class_init,
91 NULL, /* class_finalize */
92 NULL, /* class_data */
93 sizeof (GaimGtkCellRendererExpander),
94 0, /* n_preallocs */
95 (GInstanceInitFunc) gaim_gtk_cell_renderer_expander_init,
96 NULL /* value_table */
97 };
98
99 cell_expander_type =
100 g_type_register_static (GTK_TYPE_CELL_RENDERER,
101 "GaimGtkCellRendererExpander",
102 &cell_expander_info, 0);
103 }
104
105 return cell_expander_type;
106 }
107
108 static void gaim_gtk_cell_renderer_expander_init (GaimGtkCellRendererExpander *cellexpander)
109 {
110 GTK_CELL_RENDERER(cellexpander)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
111 GTK_CELL_RENDERER(cellexpander)->xpad = 2;
112 GTK_CELL_RENDERER(cellexpander)->ypad = 2;
113 }
114
115 static void gaim_gtk_cell_renderer_expander_class_init (GaimGtkCellRendererExpanderClass *class)
116 {
117 GObjectClass *object_class = G_OBJECT_CLASS(class);
118 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(class);
119
120 parent_class = g_type_class_peek_parent (class);
121 object_class->finalize = gaim_gtk_cell_renderer_expander_finalize;
122
123 object_class->get_property = gaim_gtk_cell_renderer_expander_get_property;
124 object_class->set_property = gaim_gtk_cell_renderer_expander_set_property;
125
126 cell_class->get_size = gaim_gtk_cell_renderer_expander_get_size;
127 cell_class->render = gaim_gtk_cell_renderer_expander_render;
128 cell_class->activate = gaim_gtk_cell_renderer_expander_activate;
129
130 g_object_class_install_property (object_class,
131 PROP_IS_EXPANDER,
132 g_param_spec_boolean ("expander-visible",
133 "Is Expander",
134 "True if the renderer should draw an expander",
135 FALSE,
136 G_PARAM_READWRITE));
137 }
138
139 static void gaim_gtk_cell_renderer_expander_finalize (GObject *object)
140 {
141 /*
142 GaimGtkCellRendererExpander *cellexpander = GAIM_GTK_CELL_RENDERER_EXPANDER(object);
143 */
144
145 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
146 }
147
148 static void gaim_gtk_cell_renderer_expander_get_property (GObject *object,
149 guint param_id,
150 GValue *value,
151 GParamSpec *psec)
152 {
153 GaimGtkCellRendererExpander *cellexpander = GAIM_GTK_CELL_RENDERER_EXPANDER(object);
154
155 switch (param_id)
156 {
157 case PROP_IS_EXPANDER:
158 g_value_set_boolean(value, cellexpander->is_expander);
159 break;
160 default:
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, psec);
162 break;
163
164 }
165 }
166
167 static void gaim_gtk_cell_renderer_expander_set_property (GObject *object,
168 guint param_id,
169 const GValue *value,
170 GParamSpec *pspec)
171 {
172 GaimGtkCellRendererExpander *cellexpander = GAIM_GTK_CELL_RENDERER_EXPANDER (object);
173
174 switch (param_id)
175 {
176 case PROP_IS_EXPANDER:
177 cellexpander->is_expander = g_value_get_boolean(value);
178 break;
179 default:
180 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
181 break;
182 }
183 }
184
185 GtkCellRenderer *gaim_gtk_cell_renderer_expander_new(void)
186 {
187 return g_object_new(GAIM_TYPE_GTK_CELL_RENDERER_EXPANDER, NULL);
188 }
189
190 static void gaim_gtk_cell_renderer_expander_get_size (GtkCellRenderer *cell,
191 GtkWidget *widget,
192 GdkRectangle *cell_area,
193 gint *x_offset,
194 gint *y_offset,
195 gint *width,
196 gint *height)
197 {
198 gint calc_width;
199 gint calc_height;
200 gint expander_size;
201
202 gtk_widget_style_get(widget, "expander-size", &expander_size, NULL);
203
204 calc_width = (gint) cell->xpad * 2 + expander_size;
205 calc_height = (gint) cell->ypad * 2 + expander_size;
206
207 if (width)
208 *width = calc_width;
209
210 if (height)
211 *height = calc_height;
212
213 if (cell_area)
214 {
215 if (x_offset)
216 {
217 *x_offset = cell->xalign * (cell_area->width - calc_width);
218 *x_offset = MAX (*x_offset, 0);
219 }
220 if (y_offset)
221 {
222 *y_offset = cell->yalign * (cell_area->height - calc_height);
223 *y_offset = MAX (*y_offset, 0);
224 }
225 }
226 }
227
228
229 static void gaim_gtk_cell_renderer_expander_render (GtkCellRenderer *cell,
230 GdkWindow *window,
231 GtkWidget *widget,
232 GdkRectangle *background_area,
233 GdkRectangle *cell_area,
234 GdkRectangle *expose_area,
235 guint flags)
236 {
237 GaimGtkCellRendererExpander *cellexpander = (GaimGtkCellRendererExpander *) cell;
238
239 gint width, height;
240 GtkStateType state;
241
242 if (!cellexpander->is_expander)
243 return;
244
245 width = cell_area->width;
246 height = cell_area->height;
247
248 if (!cell->sensitive)
249 state = GTK_STATE_INSENSITIVE;
250 else if (flags & GTK_CELL_RENDERER_PRELIT)
251 state = GTK_STATE_PRELIGHT;
252 else if (GTK_WIDGET_HAS_FOCUS (widget) && flags & GTK_CELL_RENDERER_SELECTED)
253 state = GTK_STATE_ACTIVE;
254 else
255 state = GTK_STATE_NORMAL;
256
257 width -= cell->xpad*2;
258 height -= cell->ypad*2;
259
260 gtk_paint_expander (widget->style,
261 window, state,
262 NULL, widget, "treeview",
263 cell_area->x + cell->xpad + (width / 2),
264 cell_area->y + cell->ypad + (height / 2),
265 cell->is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED);
266 }
267
268 static gint gaim_gtk_cell_renderer_expander_activate(GtkCellRenderer *r,
269 GdkEvent *event,
270 GtkWidget *widget,
271 const gchar *p,
272 GdkRectangle *bg,
273 GdkRectangle *cell,
274 GtkCellRendererState flags)
275 {
276 GtkTreePath *path = gtk_tree_path_new_from_string(p);
277 printf("!! Activated!\n");
278 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
279 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
280 else
281 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget),path,FALSE);
282 gtk_tree_path_free(path);
283 }