comparison src/gaim-disclosure.c @ 4553:d03fcb3f4be2

[gaim-migrate @ 4833] We have a brand new file transfer dialog! committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Fri, 07 Feb 2003 20:55:20 +0000
parents
children fa6395637e2c
comparison
equal deleted inserted replaced
4552:a2f2a717fdf2 4553:d03fcb3f4be2
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Authors: Iain Holmes <iain@ximian.com>
4 *
5 * Copyright 2002 Iain Holmes
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) {
191 g_source_remove(disclosure->priv->expand_id);
192 }
193
194 disclosure->priv->direction = opening ? 1 : -1;
195 disclosure->priv->expand_id = g_timeout_add (50, expand_collapse_timeout, disclosure);
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 }