Mercurial > pidgin
annotate src/gaim-disclosure.c @ 9251:45d2ad4ac1c1
[gaim-migrate @ 10050]
Stu Tomlinson has provided a nice patch to move the separation of IM
and Chat windows back into the core from the extplacement plugin.
It's awesome to have crazy patch writers, and even better to have
crazy patch writers who write what I want to write before I do it,
thus saving me the effort.
committer: Tailor Script <tailor@pidgin.im>
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Wed, 09 Jun 2004 20:47:07 +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 } |