| |
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 } |