3 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 /* This is taken largely from GtkCellRenderer[Text|Pixbuf|Toggle] by
24 * Jonathon Blandford <jrb@redhat.com> for RedHat, Inc.
27 #include "gtkcellrendererexpander.h"
29 #include "gtk3compat.h"
31 static void pidgin_cell_renderer_expander_get_property (GObject
*object
,
35 static void pidgin_cell_renderer_expander_set_property (GObject
*object
,
39 static void pidgin_cell_renderer_expander_init (PidginCellRendererExpander
*cellexpander
);
40 static void pidgin_cell_renderer_expander_class_init (PidginCellRendererExpanderClass
*class);
41 static void pidgin_cell_renderer_expander_get_size (GtkCellRenderer
*cell
,
43 const GdkRectangle
*cell_area
,
48 static void pidgin_cell_renderer_expander_render (GtkCellRenderer
*cell
,
51 const GdkRectangle
*background_area
,
52 const GdkRectangle
*cell_area
,
53 GtkCellRendererState flags
);
54 static gboolean
pidgin_cell_renderer_expander_activate (GtkCellRenderer
*r
,
58 const GdkRectangle
*bg
,
59 const GdkRectangle
*cell
,
60 GtkCellRendererState flags
);
61 static void pidgin_cell_renderer_expander_finalize (GObject
*gobject
);
72 static gpointer parent_class
;
73 /* static guint expander_cell_renderer_signals [LAST_SIGNAL]; */
75 GType
pidgin_cell_renderer_expander_get_type (void)
77 static GType cell_expander_type
= 0;
79 if (!cell_expander_type
)
81 static const GTypeInfo cell_expander_info
=
83 sizeof (PidginCellRendererExpanderClass
),
85 NULL
, /* base_finalize */
86 (GClassInitFunc
) pidgin_cell_renderer_expander_class_init
,
87 NULL
, /* class_finalize */
88 NULL
, /* class_data */
89 sizeof (PidginCellRendererExpander
),
91 (GInstanceInitFunc
) pidgin_cell_renderer_expander_init
,
92 NULL
/* value_table */
96 g_type_register_static (GTK_TYPE_CELL_RENDERER
,
97 "PidginCellRendererExpander",
98 &cell_expander_info
, 0);
101 return cell_expander_type
;
104 static void pidgin_cell_renderer_expander_init (PidginCellRendererExpander
*cellexpander
)
106 g_object_set(G_OBJECT(cellexpander
), "mode",
107 GTK_CELL_RENDERER_MODE_ACTIVATABLE
, NULL
);
108 gtk_cell_renderer_set_padding(GTK_CELL_RENDERER(cellexpander
), 0, 2);
111 static void pidgin_cell_renderer_expander_class_init (PidginCellRendererExpanderClass
*class)
113 GObjectClass
*object_class
= G_OBJECT_CLASS(class);
114 GtkCellRendererClass
*cell_class
= GTK_CELL_RENDERER_CLASS(class);
116 parent_class
= g_type_class_peek_parent (class);
117 object_class
->finalize
= pidgin_cell_renderer_expander_finalize
;
119 object_class
->get_property
= pidgin_cell_renderer_expander_get_property
;
120 object_class
->set_property
= pidgin_cell_renderer_expander_set_property
;
122 cell_class
->get_size
= pidgin_cell_renderer_expander_get_size
;
123 cell_class
->render
= pidgin_cell_renderer_expander_render
;
124 cell_class
->activate
= pidgin_cell_renderer_expander_activate
;
126 g_object_class_install_property (object_class
,
128 g_param_spec_boolean ("expander-visible",
130 "True if the renderer should draw an expander",
132 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
));
135 static void pidgin_cell_renderer_expander_finalize (GObject
*object
)
138 PidginCellRendererExpander *cellexpander = PIDGIN_CELL_RENDERER_EXPANDER(object);
141 (* G_OBJECT_CLASS (parent_class
)->finalize
) (object
);
144 static void pidgin_cell_renderer_expander_get_property (GObject
*object
,
149 PidginCellRendererExpander
*cellexpander
= PIDGIN_CELL_RENDERER_EXPANDER(object
);
153 case PROP_IS_EXPANDER
:
154 g_value_set_boolean(value
, cellexpander
->is_expander
);
157 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, psec
);
163 static void pidgin_cell_renderer_expander_set_property (GObject
*object
,
168 PidginCellRendererExpander
*cellexpander
= PIDGIN_CELL_RENDERER_EXPANDER (object
);
172 case PROP_IS_EXPANDER
:
173 cellexpander
->is_expander
= g_value_get_boolean(value
);
176 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, param_id
, pspec
);
181 GtkCellRenderer
*pidgin_cell_renderer_expander_new(void)
183 return g_object_new(PIDGIN_TYPE_CELL_RENDERER_EXPANDER
, NULL
);
187 pidgin_cell_renderer_expander_get_size (GtkCellRenderer
*cell
,
189 const GdkRectangle
*cell_area
,
203 gtk_widget_style_get(widget
, "expander-size", &expander_size
, NULL
);
205 gtk_cell_renderer_get_padding(cell
, &xpad
, &ypad
);
206 gtk_cell_renderer_get_alignment(cell
, &xalign
, &yalign
);
207 calc_width
= (gint
) xpad
* 2 + expander_size
;
208 calc_height
= (gint
) ypad
* 2 + expander_size
;
214 *height
= calc_height
;
220 *x_offset
= xalign
* (cell_area
->width
- calc_width
);
221 *x_offset
= MAX (*x_offset
, 0);
225 *y_offset
= yalign
* (cell_area
->height
- calc_height
);
226 *y_offset
= MAX (*y_offset
, 0);
233 pidgin_cell_renderer_expander_render(GtkCellRenderer
*cell
,
236 const GdkRectangle
*background_area
,
237 const GdkRectangle
*cell_area
,
238 GtkCellRendererState flags
)
240 PidginCellRendererExpander
*cellexpander
= (PidginCellRendererExpander
*) cell
;
246 gboolean is_expanded
;
247 GtkAllocation allocation
;
248 GtkStyleContext
*context
;
250 if (!cellexpander
->is_expander
)
253 gtk_cell_renderer_get_padding(cell
, &xpad
, &ypad
);
254 g_object_get(G_OBJECT(cell
), "is-expanded", &is_expanded
, NULL
);
256 width
= cell_area
->width
;
257 height
= cell_area
->height
;
259 if (!gtk_widget_get_sensitive(widget
))
260 state
= GTK_STATE_FLAG_INSENSITIVE
;
261 else if (flags
& GTK_CELL_RENDERER_PRELIT
)
262 state
= GTK_STATE_FLAG_PRELIGHT
;
263 else if (gtk_widget_has_focus(widget
) && flags
& GTK_CELL_RENDERER_SELECTED
)
264 state
= GTK_STATE_FLAG_ACTIVE
;
266 state
= GTK_STATE_FLAG_NORMAL
;
271 #if GTK_CHECK_VERSION(3,14,0)
273 state
|= GTK_STATE_FLAG_CHECKED
;
275 state
&= ~GTK_STATE_FLAG_CHECKED
;
278 state
|= GTK_STATE_FLAG_ACTIVE
;
280 state
&= ~GTK_STATE_FLAG_ACTIVE
;
283 context
= gtk_widget_get_style_context(widget
);
284 gtk_style_context_add_class(context
, GTK_STYLE_CLASS_VIEW
);
285 gtk_style_context_add_class(context
, GTK_STYLE_CLASS_EXPANDER
);
286 gtk_style_context_set_state(context
, state
);
287 gtk_render_expander(context
, cr
,
288 cell_area
->x
+ xpad
, cell_area
->y
+ ypad
,
291 /* only draw the line if the color isn't set - this prevents a bug where the hline appears only under the expander */
292 g_object_get(cellexpander
, "cell-background-set", &set
, NULL
);
293 gtk_widget_get_allocation(widget
, &allocation
);
295 if (is_expanded
&& !set
)
296 gtk_render_line(context
, cr
, 0, cell_area
->y
+ cell_area
->height
,
297 allocation
.width
, cell_area
->y
+ cell_area
->height
);
301 pidgin_cell_renderer_expander_activate(GtkCellRenderer
*r
,
305 const GdkRectangle
*bg
,
306 const GdkRectangle
*cell
,
307 GtkCellRendererState flags
)
309 GtkTreePath
*path
= gtk_tree_path_new_from_string(p
);
310 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget
), path
))
311 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget
), path
);
313 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget
),path
,FALSE
);
314 gtk_tree_path_free(path
);