comparison pidgin/minidialog.c @ 21402:9fef5d307a27

Create a PidginMiniDialog widget; make pidgin_make_mini_dialog() in gtkutils.c a relatively thin wrapper around it.
author Will Thompson <will.thompson@collabora.co.uk>
date Sun, 04 Nov 2007 14:43:45 +0000
parents
children 0f029f9a75e1
comparison
equal deleted inserted replaced
21401:c1c7e28223f8 21402:9fef5d307a27
1 /**
2 * @file minidialog.c Implementation of the #PidginMiniDialog Gtk widget.
3 * @ingroup pidgin
4 */
5
6 /* pidgin
7 *
8 * Pidgin is the legal property of its developers, whose names are too numerous
9 * to list here. Please refer to the COPYRIGHT file distributed with this
10 * source distribution.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 */
26
27 #include <gtk/gtkhbox.h>
28 #include <gtk/gtkbutton.h>
29
30 #include "libpurple/prefs.h"
31
32 #include "pidgin/minidialog.h"
33 #include "pidgin/pidgin.h"
34 #include "pidgin/pidginstock.h"
35
36 G_DEFINE_TYPE (PidginMiniDialog, pidgin_mini_dialog, GTK_TYPE_VBOX)
37
38 enum
39 {
40 PROP_TITLE = 1,
41 PROP_DESCRIPTION,
42 PROP_ICON_NAME,
43
44 LAST_PROPERTY
45 } HazeConnectionProperties;
46
47 typedef struct _PidginMiniDialogPrivate
48 {
49 GtkImage *icon;
50 GtkBox *label_box;
51 GtkLabel *title;
52 GtkLabel *description;
53 GtkBox *buttons;
54 } PidginMiniDialogPrivate;
55
56 #define PIDGIN_MINI_DIALOG_GET_PRIVATE(dialog) \
57 ((PidginMiniDialogPrivate *) ((dialog)->priv))
58
59 PidginMiniDialog *
60 pidgin_mini_dialog_new(const gchar *title,
61 const gchar *description,
62 const gchar *icon_name)
63 {
64 PidginMiniDialog *mini_dialog = g_object_new(PIDGIN_TYPE_MINI_DIALOG,
65 "title", title,
66 "description", description,
67 "icon-name", icon_name,
68 NULL);
69
70 return mini_dialog;
71 }
72
73 void
74 pidgin_mini_dialog_set_title(PidginMiniDialog *mini_dialog,
75 const char *title)
76 {
77 g_object_set(G_OBJECT(mini_dialog), "title", title, NULL);
78 }
79
80 void
81 pidgin_mini_dialog_set_description(PidginMiniDialog *mini_dialog,
82 const char *description)
83 {
84 g_object_set(G_OBJECT(mini_dialog), "description", description, NULL);
85 }
86
87 void
88 pidgin_mini_dialog_set_icon_name(PidginMiniDialog *mini_dialog,
89 const char *icon_name)
90 {
91 g_object_set(G_OBJECT(mini_dialog), "icon_name", icon_name, NULL);
92 }
93
94 struct _mini_dialog_button_clicked_cb_data
95 {
96 PidginMiniDialog *mini_dialog;
97 PidginMiniDialogCallback callback;
98 gpointer user_data;
99 };
100
101 static void
102 mini_dialog_button_clicked_cb(GtkButton *button,
103 gpointer user_data)
104 {
105 struct _mini_dialog_button_clicked_cb_data *data = user_data;
106
107 data->callback(data->mini_dialog, button, data->user_data);
108
109 gtk_widget_destroy(GTK_WIDGET(data->mini_dialog));
110 }
111
112 static void
113 mini_dialog_button_destroy_cb(GtkButton *button,
114 gpointer user_data)
115 {
116 struct _mini_dialog_button_clicked_cb_data *data = user_data;
117 g_free(data);
118 }
119
120 void
121 pidgin_mini_dialog_add_button(PidginMiniDialog *self,
122 const char *text,
123 PidginMiniDialogCallback clicked_cb,
124 gpointer user_data)
125 {
126 PidginMiniDialogPrivate *priv = PIDGIN_MINI_DIALOG_GET_PRIVATE(self);
127 struct _mini_dialog_button_clicked_cb_data *callback_data
128 = g_new0(struct _mini_dialog_button_clicked_cb_data, 1);
129 GtkWidget *button = gtk_button_new();
130 GtkWidget *label = gtk_label_new(NULL);
131 char *button_text =
132 g_strdup_printf("<span size=\"smaller\">%s</span>", text);
133
134 gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), button_text);
135 g_free(button_text);
136
137 callback_data->mini_dialog = self;
138 callback_data->callback = clicked_cb;
139 callback_data->user_data = user_data;
140 g_signal_connect(G_OBJECT(button), "clicked",
141 (GCallback) mini_dialog_button_clicked_cb, callback_data);
142 g_signal_connect(G_OBJECT(button), "destroy",
143 (GCallback) mini_dialog_button_destroy_cb, callback_data);
144
145 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
146 gtk_container_add(GTK_CONTAINER(button), label);
147
148 gtk_box_pack_end(GTK_BOX(priv->buttons), button, FALSE, FALSE,
149 0);
150 gtk_widget_show(GTK_WIDGET(button));
151 }
152
153 static void
154 pidgin_mini_dialog_get_property(GObject *object,
155 guint property_id,
156 GValue *value,
157 GParamSpec *pspec)
158 {
159 PidginMiniDialog *self = PIDGIN_MINI_DIALOG(object);
160 PidginMiniDialogPrivate *priv = PIDGIN_MINI_DIALOG_GET_PRIVATE(self);
161
162 switch (property_id) {
163 case PROP_TITLE:
164 g_value_set_string(value, gtk_label_get_text(priv->title));
165 break;
166 case PROP_DESCRIPTION:
167 g_value_set_string(value, gtk_label_get_text(priv->description));
168 break;
169 case PROP_ICON_NAME:
170 {
171 gchar *icon_name = NULL;
172 GtkIconSize size;
173 gtk_image_get_stock(priv->icon, &icon_name, &size);
174 g_value_set_string(value, icon_name);
175 break;
176 }
177 default:
178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
179 }
180 }
181
182 static void
183 mini_dialog_set_title(PidginMiniDialog *self,
184 const char *title)
185 {
186 PidginMiniDialogPrivate *priv = PIDGIN_MINI_DIALOG_GET_PRIVATE(self);
187
188 char *title_esc = g_markup_escape_text(title, -1);
189 char *title_markup = g_strdup_printf(
190 "<span weight=\"bold\" size=\"smaller\">%s</span>",
191 title_esc ? title_esc : "");
192
193 gtk_label_set_markup(priv->title, title_markup);
194
195 g_free(title_esc);
196 g_free(title_markup);
197 }
198
199 static void
200 mini_dialog_set_description(PidginMiniDialog *self,
201 const char *description)
202 {
203 PidginMiniDialogPrivate *priv = PIDGIN_MINI_DIALOG_GET_PRIVATE(self);
204 if(description)
205 {
206 char *desc_esc = g_markup_escape_text(description, -1);
207 char *desc_markup = g_strdup_printf(
208 "<span size=\"smaller\">%s</span>", desc_esc);
209
210 gtk_label_set_markup(priv->description, desc_markup);
211
212 g_free(desc_esc);
213 g_free(desc_markup);
214
215 gtk_widget_show(GTK_WIDGET(priv->description));
216 }
217 else
218 {
219 gtk_label_set_text(priv->description, NULL);
220 gtk_widget_hide(GTK_WIDGET(priv->description));
221 }
222 }
223
224 static void
225 pidgin_mini_dialog_set_property(GObject *object,
226 guint property_id,
227 const GValue *value,
228 GParamSpec *pspec)
229 {
230 PidginMiniDialog *self = PIDGIN_MINI_DIALOG(object);
231 PidginMiniDialogPrivate *priv = PIDGIN_MINI_DIALOG_GET_PRIVATE(self);
232
233 switch (property_id) {
234 case PROP_TITLE:
235 mini_dialog_set_title(self, g_value_get_string(value));
236 break;
237 case PROP_DESCRIPTION:
238 mini_dialog_set_description(self, g_value_get_string(value));
239 break;
240 case PROP_ICON_NAME:
241 gtk_image_set_from_stock(priv->icon, g_value_get_string(value),
242 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL));
243 break;
244 default:
245 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
246 }
247 }
248
249 static void
250 pidgin_mini_dialog_finalize(GObject *object)
251 {
252 PidginMiniDialog *self = PIDGIN_MINI_DIALOG(object);
253 PidginMiniDialogPrivate *priv = PIDGIN_MINI_DIALOG_GET_PRIVATE(self);
254
255 g_free(priv);
256 self->priv = NULL;
257
258 G_OBJECT_CLASS (pidgin_mini_dialog_parent_class)->finalize (object);
259 }
260
261 static void
262 pidgin_mini_dialog_class_init(PidginMiniDialogClass *klass)
263 {
264 GObjectClass *object_class = G_OBJECT_CLASS(klass);
265 GParamSpec *param_spec;
266
267 object_class->get_property = pidgin_mini_dialog_get_property;
268 object_class->set_property = pidgin_mini_dialog_set_property;
269 object_class->finalize = pidgin_mini_dialog_finalize;
270
271 param_spec = g_param_spec_string("title", "title",
272 "String specifying the mini-dialog's title", NULL,
273 #if GTK_CHECK_VERSION(2,8,0)
274 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
275 #endif
276 G_PARAM_READWRITE);
277 g_object_class_install_property (object_class, PROP_TITLE, param_spec);
278
279 param_spec = g_param_spec_string("description", "description",
280 "Description text for the mini-dialog, if desired", NULL,
281 #if GTK_CHECK_VERSION(2,8,0)
282 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
283 #endif
284 G_PARAM_READWRITE);
285 g_object_class_install_property (object_class, PROP_DESCRIPTION, param_spec);
286
287 param_spec = g_param_spec_string("icon-name", "icon-name",
288 "String specifying the Gtk stock name of the dialog's icon",
289 NULL,
290 #if GTK_CHECK_VERSION(2,8,0)
291 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
292 #endif
293 G_PARAM_READWRITE);
294 g_object_class_install_property (object_class, PROP_ICON_NAME, param_spec);
295 }
296
297 static void
298 pidgin_mini_dialog_init(PidginMiniDialog *self)
299 {
300 GtkBox *self_box = GTK_BOX(self);
301 PidginMiniDialogPrivate *priv = g_new0(PidginMiniDialogPrivate, 1);
302 self->priv = priv;
303
304 gtk_container_set_border_width(GTK_CONTAINER(self), PIDGIN_HIG_BOX_SPACE);
305
306 priv->label_box = GTK_BOX(gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE));
307
308 priv->icon = GTK_IMAGE(gtk_image_new());
309 gtk_misc_set_alignment(GTK_MISC(priv->icon), 0, 0);
310
311 priv->title = GTK_LABEL(gtk_label_new(""));
312 /* TODO: update this request when /blist/width updates. Also, 25 is
313 * magic.
314 */
315 gtk_widget_set_size_request(GTK_WIDGET(priv->title),
316 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25, -1);
317 gtk_label_set_line_wrap(priv->title, TRUE);
318 gtk_misc_set_alignment(GTK_MISC(priv->title), 0, 0);
319
320 gtk_box_pack_start(priv->label_box, GTK_WIDGET(priv->icon), FALSE, FALSE, 0);
321 gtk_box_pack_start(priv->label_box, GTK_WIDGET(priv->title), TRUE, TRUE, 0);
322
323 priv->description = GTK_LABEL(gtk_label_new(""));
324 /* TODO: update this request when /blist/width updates. Also, 25 is
325 * magic.
326 */
327 gtk_widget_set_size_request(GTK_WIDGET(priv->description),
328 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25, -1);
329 gtk_label_set_line_wrap(priv->description, TRUE);
330 gtk_misc_set_alignment(GTK_MISC(priv->description), 0, 0);
331
332 self->contents = GTK_BOX(gtk_vbox_new(FALSE, 0));
333 priv->buttons = GTK_BOX(gtk_hbox_new(FALSE, 0));
334
335 gtk_box_pack_start(self_box, GTK_WIDGET(priv->label_box), FALSE, FALSE, 0);
336 gtk_box_pack_start(self_box, GTK_WIDGET(priv->description), FALSE, FALSE, 0);
337 gtk_box_pack_start(self_box, GTK_WIDGET(self->contents), TRUE, TRUE, 0);
338 gtk_box_pack_start(self_box, GTK_WIDGET(priv->buttons), FALSE, FALSE, 0);
339
340 gtk_widget_show_all(GTK_WIDGET(self));
341 gtk_widget_hide(GTK_WIDGET(priv->description));
342 }