| |
1 /* |
| |
2 * Pidgin - Internet Messenger |
| |
3 * Copyright (C) Pidgin Developers <devel@pidgin.im> |
| |
4 * |
| |
5 * Pidgin is the legal property of its developers, whose names are too numerous |
| |
6 * to list here. Please refer to the COPYRIGHT file distributed with this |
| |
7 * source distribution. |
| |
8 * |
| |
9 * This program is free software; you can redistribute it and/or modify |
| |
10 * it under the terms of the GNU General Public License as published by |
| |
11 * the Free Software Foundation; either version 2 of the License, or |
| |
12 * (at your option) any later version. |
| |
13 * |
| |
14 * This program is distributed in the hope that it will be useful, |
| |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| |
17 * GNU General Public License for more details. |
| |
18 * |
| |
19 * You should have received a copy of the GNU General Public License |
| |
20 * along with this program; if not, see <https://www.gnu.org/licenses/>. |
| |
21 */ |
| |
22 |
| |
23 #include "pidgin/pidgincellrendererexpander.h" |
| |
24 |
| |
25 struct _PidginCellRendererExpander { |
| |
26 GtkCellRenderer parent; |
| |
27 }; |
| |
28 |
| |
29 G_DEFINE_TYPE(PidginCellRendererExpander, pidgin_cell_renderer_expander, |
| |
30 GTK_TYPE_CELL_RENDERER) |
| |
31 |
| |
32 /****************************************************************************** |
| |
33 * GtkCellRenderer Implementation |
| |
34 *****************************************************************************/ |
| |
35 static void |
| |
36 pidgin_cell_renderer_expander_get_size(GtkCellRenderer *renderer, |
| |
37 GtkWidget *widget, |
| |
38 const GdkRectangle *cell_area, |
| |
39 gint *x_offset, gint *y_offset, |
| |
40 gint *width, gint *height) |
| |
41 { |
| |
42 gint calc_width = 0, calc_height = 0; |
| |
43 gint xpad = 0, ypad = 0; |
| |
44 gint expander_size = 0; |
| |
45 |
| |
46 gtk_widget_style_get(widget, "expander-size", &expander_size, NULL); |
| |
47 |
| |
48 gtk_cell_renderer_get_padding(renderer, &xpad, &ypad); |
| |
49 calc_width = (xpad * 2) + expander_size; |
| |
50 calc_height = (ypad * 2) + expander_size; |
| |
51 |
| |
52 if(width) { |
| |
53 *width = calc_width; |
| |
54 } |
| |
55 |
| |
56 if(height) { |
| |
57 *height = calc_height; |
| |
58 } |
| |
59 |
| |
60 if(cell_area) { |
| |
61 gfloat xalign = 0.0f, yalign = 0.0f; |
| |
62 |
| |
63 gtk_cell_renderer_get_alignment(renderer, &xalign, &yalign); |
| |
64 |
| |
65 if(x_offset) { |
| |
66 *x_offset = (gint)(xalign * (cell_area->width - calc_width)); |
| |
67 *x_offset = MAX (*x_offset, 0); |
| |
68 } |
| |
69 |
| |
70 if(y_offset) { |
| |
71 *y_offset = (gint)(yalign * (cell_area->height - calc_height)); |
| |
72 *y_offset = MAX (*y_offset, 0); |
| |
73 } |
| |
74 } |
| |
75 } |
| |
76 |
| |
77 static void |
| |
78 pidgin_cell_renderer_expander_render(GtkCellRenderer *renderer, cairo_t *cr, |
| |
79 GtkWidget *widget, |
| |
80 const GdkRectangle *background_area, |
| |
81 const GdkRectangle *cell_area, |
| |
82 GtkCellRendererState flags) |
| |
83 { |
| |
84 GtkStateFlags state; |
| |
85 GtkStyleContext *context = NULL; |
| |
86 gboolean is_expanded = FALSE, is_expander = FALSE; |
| |
87 gint xpad = 0, ypad = 0; |
| |
88 gint width = cell_area->width, height = cell_area->height; |
| |
89 |
| |
90 /* if the row doesn't have children, bail out. */ |
| |
91 g_object_get(G_OBJECT(renderer), "is-expander", &is_expander, NULL); |
| |
92 if(!is_expander) { |
| |
93 return; |
| |
94 } |
| |
95 |
| |
96 /* Figure out the state of the renderer. */ |
| |
97 if(!gtk_widget_get_sensitive(widget)) { |
| |
98 state = GTK_STATE_FLAG_INSENSITIVE; |
| |
99 } else if(flags & GTK_CELL_RENDERER_PRELIT) { |
| |
100 state = GTK_STATE_FLAG_PRELIGHT; |
| |
101 } else if(gtk_widget_has_focus(widget) && flags & GTK_CELL_RENDERER_SELECTED) { |
| |
102 state = GTK_STATE_FLAG_ACTIVE; |
| |
103 } else { |
| |
104 state = GTK_STATE_FLAG_NORMAL; |
| |
105 } |
| |
106 |
| |
107 g_object_get(G_OBJECT(renderer), "is-expanded", &is_expanded, NULL); |
| |
108 if(is_expanded) { |
| |
109 state |= GTK_STATE_FLAG_CHECKED; |
| |
110 } else { |
| |
111 state &= ~GTK_STATE_FLAG_CHECKED; |
| |
112 } |
| |
113 |
| |
114 /* Build our style context */ |
| |
115 context = gtk_widget_get_style_context(widget); |
| |
116 gtk_style_context_add_class(context, GTK_STYLE_CLASS_VIEW); |
| |
117 gtk_style_context_add_class(context, GTK_STYLE_CLASS_EXPANDER); |
| |
118 gtk_style_context_set_state(context, state); |
| |
119 |
| |
120 /* Adjust the width and height according to the padding. */ |
| |
121 gtk_cell_renderer_get_padding(renderer, &xpad, &ypad); |
| |
122 width -= xpad * 2; |
| |
123 height -= ypad * 2; |
| |
124 |
| |
125 /* Render the arrow. */ |
| |
126 gtk_render_expander(context, cr, |
| |
127 cell_area->x + xpad, cell_area->y + ypad, |
| |
128 width, height); |
| |
129 } |
| |
130 |
| |
131 static gboolean |
| |
132 pidgin_cell_renderer_expander_activate(GtkCellRenderer *r, GdkEvent *event, |
| |
133 GtkWidget *widget, const gchar *p, |
| |
134 const GdkRectangle *bg, |
| |
135 const GdkRectangle *cell, |
| |
136 GtkCellRendererState flags) |
| |
137 { |
| |
138 GtkTreePath *path = gtk_tree_path_new_from_string(p); |
| |
139 |
| |
140 if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path)) { |
| |
141 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path); |
| |
142 } else { |
| |
143 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget),path,FALSE); |
| |
144 } |
| |
145 |
| |
146 gtk_tree_path_free(path); |
| |
147 |
| |
148 return FALSE; |
| |
149 } |
| |
150 |
| |
151 /****************************************************************************** |
| |
152 * GObject Implementation |
| |
153 *****************************************************************************/ |
| |
154 static void |
| |
155 pidgin_cell_renderer_expander_init (PidginCellRendererExpander *renderer) { |
| |
156 /* there's no accessor for setting the mode, so we have to set the property |
| |
157 * explicitly. |
| |
158 */ |
| |
159 g_object_set(G_OBJECT(renderer), "mode", |
| |
160 GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); |
| |
161 |
| |
162 gtk_cell_renderer_set_padding(GTK_CELL_RENDERER(renderer), 0, 2); |
| |
163 } |
| |
164 |
| |
165 static void |
| |
166 pidgin_cell_renderer_expander_class_init(PidginCellRendererExpanderClass *klass) |
| |
167 { |
| |
168 GtkCellRendererClass *renderer_class = GTK_CELL_RENDERER_CLASS(klass); |
| |
169 |
| |
170 renderer_class->get_size = pidgin_cell_renderer_expander_get_size; |
| |
171 renderer_class->render = pidgin_cell_renderer_expander_render; |
| |
172 renderer_class->activate = pidgin_cell_renderer_expander_activate; |
| |
173 } |
| |
174 |
| |
175 /****************************************************************************** |
| |
176 * Public API |
| |
177 *****************************************************************************/ |
| |
178 GtkCellRenderer * |
| |
179 pidgin_cell_renderer_expander_new(void) { |
| |
180 return g_object_new(PIDGIN_TYPE_CELL_RENDERER_EXPANDER, NULL); |
| |
181 } |