Mercurial > pidgin.yaz
annotate src/gaim-disclosure.c @ 8589:72a0759a37a2
[gaim-migrate @ 9340]
Paco-Paco got his 8space tab on earlier, and it makes me feel dirty.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Tue, 06 Apr 2004 01:06:45 +0000 |
parents | ef881489396e |
children |
rev | line source |
---|---|
4553 | 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ |
2 /* | |
8046 | 3 * Gaim 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 | |
5 * source distribution. | |
4553 | 6 * |
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. | |
11 * | |
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. | |
16 * | |
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., 59 Temple Street #330, Boston, MA 02111-1307, USA. | |
20 * | |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include <gtk/gtktogglebutton.h> | |
28 | |
29 #include "gaim-disclosure.h" | |
30 | |
31 #ifdef ENABLE_NLS | |
32 # include <libintl.h> | |
33 # define _(x) gettext(x) | |
34 # ifdef gettext_noop | |
35 # define N_(String) gettext_noop (String) | |
36 # else | |
37 # define N_(String) (String) | |
38 # endif | |
39 #else | |
40 # define N_(String) (String) | |
41 # define _(x) (x) | |
42 #endif | |
43 | |
44 static GtkCheckButtonClass *parent_class = NULL; | |
45 | |
46 struct _GaimDisclosurePrivate { | |
47 GtkWidget *container; | |
48 char *shown; | |
49 char *hidden; | |
50 | |
51 guint32 expand_id; | |
52 GtkExpanderStyle style; | |
53 | |
54 int expander_size; | |
55 int direction; | |
56 }; | |
57 | |
58 static void | |
59 finalize (GObject *object) | |
60 { | |
61 GaimDisclosure *disclosure; | |
62 | |
63 disclosure = GAIM_DISCLOSURE (object); | |
64 if (disclosure->priv == NULL) { | |
65 return; | |
66 } | |
67 | |
68 g_free (disclosure->priv->hidden); | |
69 g_free (disclosure->priv->shown); | |
70 | |
71 if (disclosure->priv->container != NULL) { | |
72 g_object_unref (G_OBJECT (disclosure->priv->container)); | |
73 } | |
74 | |
75 g_free (disclosure->priv); | |
76 disclosure->priv = NULL; | |
77 | |
78 G_OBJECT_CLASS (parent_class)->finalize (object); | |
79 } | |
80 | |
81 static void | |
82 get_x_y (GaimDisclosure *disclosure, | |
83 int *x, | |
84 int *y, | |
85 GtkStateType *state_type) | |
86 { | |
87 GtkCheckButton *check_button; | |
88 int indicator_size = 0; | |
89 int focus_width; | |
90 int focus_pad; | |
91 gboolean interior_focus; | |
92 GtkWidget *widget = GTK_WIDGET (disclosure); | |
93 GtkBin *bin = GTK_BIN (disclosure); | |
94 int width; | |
95 | |
96 if (GTK_WIDGET_VISIBLE (disclosure) && | |
97 GTK_WIDGET_MAPPED (disclosure)) { | |
98 check_button = GTK_CHECK_BUTTON (disclosure); | |
99 | |
100 gtk_widget_style_get (widget, | |
101 "interior_focus", &interior_focus, | |
102 "focus-line-width", &focus_width, | |
103 "focus-padding", &focus_pad, | |
104 NULL); | |
105 | |
106 *state_type = GTK_WIDGET_STATE (widget); | |
107 if ((*state_type != GTK_STATE_NORMAL) && | |
108 (*state_type != GTK_STATE_PRELIGHT)) { | |
109 *state_type = GTK_STATE_NORMAL; | |
110 } | |
111 | |
112 if (bin->child) { | |
113 width = bin->child->allocation.x - widget->allocation.x - (2 * GTK_CONTAINER (widget)->border_width); | |
114 } else { | |
115 width = widget->allocation.width; | |
116 } | |
117 | |
118 *x = widget->allocation.x + (width) / 2; | |
119 *y = widget->allocation.y + widget->allocation.height / 2; | |
120 | |
121 if (interior_focus == FALSE) { | |
122 *x += focus_width + focus_pad; | |
123 } | |
124 | |
125 *state_type = GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE ? GTK_STATE_NORMAL : GTK_WIDGET_STATE (widget); | |
126 | |
127 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) { | |
128 *x = widget->allocation.x + widget->allocation.width - (indicator_size + *x - widget->allocation.x); | |
129 } | |
130 } else { | |
131 *x = 0; | |
132 *y = 0; | |
133 *state_type = GTK_STATE_NORMAL; | |
134 } | |
135 } | |
136 | |
137 static gboolean | |
138 expand_collapse_timeout (gpointer data) | |
139 { | |
140 GtkWidget *widget = data; | |
141 GaimDisclosure *disclosure = data; | |
142 GtkStateType state_type; | |
143 int x, y; | |
144 | |
145 gdk_window_invalidate_rect (widget->window, &widget->allocation, TRUE); | |
146 get_x_y (disclosure, &x, &y, &state_type); | |
147 | |
148 gtk_paint_expander (widget->style, | |
149 widget->window, | |
150 state_type, | |
151 &widget->allocation, | |
152 widget, | |
153 "disclosure", | |
154 x, y, | |
155 disclosure->priv->style); | |
156 | |
157 disclosure->priv->style += disclosure->priv->direction; | |
158 if ((int) disclosure->priv->style > (int) GTK_EXPANDER_EXPANDED) { | |
159 disclosure->priv->style = GTK_EXPANDER_EXPANDED; | |
160 | |
161 if (disclosure->priv->container != NULL) { | |
162 gtk_widget_show (disclosure->priv->container); | |
163 } | |
164 | |
165 g_object_set (G_OBJECT (disclosure), | |
166 "label", disclosure->priv->hidden, | |
167 NULL); | |
168 return FALSE; | |
169 } else if ((int) disclosure->priv->style < (int) GTK_EXPANDER_COLLAPSED) { | |
170 disclosure->priv->style = GTK_EXPANDER_COLLAPSED; | |
171 | |
172 if (disclosure->priv->container != NULL) { | |
173 gtk_widget_hide (disclosure->priv->container); | |
174 } | |
175 | |
176 g_object_set (G_OBJECT (disclosure), | |
177 "label", disclosure->priv->shown, | |
178 NULL); | |
179 | |
180 return FALSE; | |
181 } else { | |
182 return TRUE; | |
183 } | |
184 } | |
185 | |
186 static void | |
187 do_animation (GaimDisclosure *disclosure, | |
188 gboolean opening) | |
189 { | |
190 if (disclosure->priv->expand_id > 0) { | |
8287
ef881489396e
[gaim-migrate @ 9011]
Christian Hammond <chipx86@chipx86.com>
parents:
8273
diff
changeset
|
191 gaim_timeout_remove(disclosure->priv->expand_id); |
4553 | 192 } |
193 | |
194 disclosure->priv->direction = opening ? 1 : -1; | |
8273
f24172f53650
[gaim-migrate @ 8997]
Christian Hammond <chipx86@chipx86.com>
parents:
8046
diff
changeset
|
195 disclosure->priv->expand_id = gaim_timeout_add (50, expand_collapse_timeout, disclosure); |
4553 | 196 } |
197 | |
198 static void | |
199 toggled (GtkToggleButton *tb) | |
200 { | |
201 GaimDisclosure *disclosure; | |
202 | |
203 disclosure = GAIM_DISCLOSURE (tb); | |
204 do_animation (disclosure, gtk_toggle_button_get_active (tb)); | |
205 | |
206 if (disclosure->priv->container == NULL) { | |
207 return; | |
208 } | |
209 } | |
210 | |
211 static void | |
212 draw_indicator (GtkCheckButton *check, | |
213 GdkRectangle *area) | |
214 { | |
215 GtkWidget *widget = GTK_WIDGET (check); | |
216 GaimDisclosure *disclosure = GAIM_DISCLOSURE (check); | |
217 GtkStateType state_type; | |
218 int x, y; | |
219 | |
220 get_x_y (disclosure, &x, &y, &state_type); | |
221 gtk_paint_expander (widget->style, | |
222 widget->window, | |
223 state_type, | |
224 area, | |
225 widget, | |
226 "treeview", | |
227 x, y, | |
228 disclosure->priv->style); | |
229 } | |
230 | |
231 static void | |
232 class_init (GaimDisclosureClass *klass) | |
233 { | |
234 GObjectClass *object_class; | |
235 GtkWidgetClass *widget_class; | |
236 GtkCheckButtonClass *button_class; | |
237 GtkToggleButtonClass *toggle_class; | |
238 | |
239 object_class = G_OBJECT_CLASS (klass); | |
240 widget_class = GTK_WIDGET_CLASS (klass); | |
241 button_class = GTK_CHECK_BUTTON_CLASS (klass); | |
242 toggle_class = GTK_TOGGLE_BUTTON_CLASS (klass); | |
243 | |
244 toggle_class->toggled = toggled; | |
245 button_class->draw_indicator = draw_indicator; | |
246 | |
247 object_class->finalize = finalize; | |
248 | |
249 parent_class = g_type_class_peek_parent (klass); | |
250 | |
251 gtk_widget_class_install_style_property (widget_class, | |
252 g_param_spec_int ("expander_size", | |
253 _("Expander Size"), | |
254 _("Size of the expander arrow"), | |
255 0, G_MAXINT, | |
256 10, G_PARAM_READABLE)); | |
257 } | |
258 | |
259 static void | |
260 init (GaimDisclosure *disclosure) | |
261 { | |
262 disclosure->priv = g_new0 (GaimDisclosurePrivate, 1); | |
263 disclosure->priv->expander_size = 10; | |
264 } | |
265 | |
266 GType | |
267 gaim_disclosure_get_type (void) | |
268 { | |
269 static GType type = 0; | |
270 | |
271 if (type == 0) { | |
272 GTypeInfo info = { | |
273 sizeof (GaimDisclosureClass), | |
274 NULL, NULL, (GClassInitFunc) class_init, NULL, NULL, | |
275 sizeof (GaimDisclosure), 0, (GInstanceInitFunc) init | |
276 }; | |
277 | |
278 type = g_type_register_static (GTK_TYPE_CHECK_BUTTON, "GaimDisclosure", &info, 0); | |
279 } | |
280 | |
281 return type; | |
282 } | |
283 | |
284 GtkWidget * | |
285 gaim_disclosure_new (const char *shown, | |
286 const char *hidden) | |
287 { | |
288 GaimDisclosure *disclosure; | |
289 | |
290 disclosure = g_object_new (gaim_disclosure_get_type (), "label", shown, NULL); | |
291 | |
292 disclosure->priv->shown = g_strdup (shown); | |
293 disclosure->priv->hidden = g_strdup (hidden); | |
294 return GTK_WIDGET (disclosure); | |
295 } | |
296 | |
297 void | |
298 gaim_disclosure_set_container (GaimDisclosure *disclosure, | |
299 GtkWidget *container) | |
300 { | |
301 g_object_ref (G_OBJECT (container)); | |
302 disclosure->priv->container = container; | |
303 } |