hythmbox-2.98/widgets/rb-alert-dialog.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /* rb-alert-dialog.c: An HIG compliant alert dialog.
  4 
  5    The Gnome Library is free software; you can redistribute it and/or
  6    modify it under the terms of the GNU Library General Public License as
  7    published by the Free Software Foundation; either version 2 of the
  8    License, or (at your option) any later version.
  9 
 10    The Gnome Library is distributed in the hope that it will be useful,
 11    but WITHOUT ANY WARRANTY; without even the implied warranty of
 12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13    Library General Public License for more details.
 14 
 15    You should have received a copy of the GNU Library General Public
 16    License along with the Gnome Library; see the file COPYING.LIB.  If not,
 17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 18    Boston, MA 02111-1307, USA.
 19 
 20 */
 21 
 22 /* this was originally nautilus/eel/eel-alert-dialog.c */
 23 
 24 #include <config.h>
 25 
 26 #include "rb-alert-dialog.h"
 27 #include <glib/gi18n.h>
 28 #include <gtk/gtk.h>
 29 #include <string.h>
 30 
 31 enum {
 32   PROP_0,
 33   PROP_ALERT_TYPE,
 34   PROP_BUTTONS
 35 };
 36 
 37 struct _RBAlertDialogDetails {
 38 	GtkWidget *image;
 39 	GtkWidget *primary_label;
 40 	GtkWidget *secondary_label;
 41 	GtkWidget *details_expander;
 42 	GtkWidget *details_label;
 43 	GtkMessageType type;
 44 };
 45 
 46 
 47 static gpointer parent_class;
 48 
 49 static void rb_alert_dialog_finalize     (GObject             *object);
 50 static void rb_alert_dialog_class_init   (RBAlertDialogClass *klass);
 51 static void rb_alert_dialog_init         (RBAlertDialog      *dialog);
 52 static void rb_alert_dialog_style_set    (GtkWidget           *widget,
 53 					  GtkStyle            *prev_style);
 54 static void rb_alert_dialog_set_property (GObject             *object,
 55 					  guint                prop_id,
 56 					  const GValue        *value,
 57 					  GParamSpec          *pspec);
 58 static void rb_alert_dialog_get_property (GObject             *object,
 59 					  guint                prop_id,
 60 					  GValue              *value,
 61 					  GParamSpec          *pspec);
 62 static void rb_alert_dialog_add_buttons  (RBAlertDialog      *alert_dialog,
 63 					  GtkButtonsType       buttons);
 64 
 65 G_DEFINE_TYPE (RBAlertDialog, rb_alert_dialog, GTK_TYPE_DIALOG)
 66 
 67 static void
 68 rb_alert_dialog_class_init (RBAlertDialogClass *class)
 69 {
 70 	GtkWidgetClass *widget_class;
 71 	GObjectClass   *gobject_class;
 72 
 73 	widget_class = GTK_WIDGET_CLASS (class);
 74 	gobject_class = G_OBJECT_CLASS (class);
 75 
 76 	parent_class = g_type_class_peek_parent (class);
 77 
 78 	G_OBJECT_CLASS (class)->finalize = rb_alert_dialog_finalize;
 79 
 80 	widget_class->style_set = rb_alert_dialog_style_set;
 81 
 82 	gobject_class->set_property = rb_alert_dialog_set_property;
 83 	gobject_class->get_property = rb_alert_dialog_get_property;
 84 
 85 	gtk_widget_class_install_style_property (widget_class,
 86 	                                         g_param_spec_int ("alert_border",
 87 	                                         _("Image/label border"),
 88 	                                         _("Width of border around the label and image in the alert dialog"),
 89 	                                         0,
 90 	                                         G_MAXINT,
 91 	                                         5,
 92 	                                         G_PARAM_READABLE));
 93 
 94 	g_object_class_install_property (gobject_class,
 95 	                                 PROP_ALERT_TYPE,
 96 	                                 g_param_spec_enum ("alert_type",
 97 	                                 _("Alert Type"),
 98 	                                 _("The type of alert"),
 99 	                                 GTK_TYPE_MESSAGE_TYPE,
100 	                                 GTK_MESSAGE_INFO,
101 	                                 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
102 
103 	g_object_class_install_property (gobject_class,
104 	                                 PROP_BUTTONS,
105 	                                 g_param_spec_enum ("buttons",
106 	                                 _("Alert Buttons"),
107 	                                 _("The buttons shown in the alert dialog"),
108 	                                 GTK_TYPE_BUTTONS_TYPE,
109 	                                 GTK_BUTTONS_NONE,
110 	                                 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
111 }
112 
113 static void
114 rb_alert_dialog_finalize (GObject *object)
115 {
116 	RBAlertDialog *dialog;
117 
118 	dialog = RB_ALERT_DIALOG (object);
119 
120 	g_free (dialog->details);
121 
122 	G_OBJECT_CLASS (rb_alert_dialog_parent_class)->finalize (object);
123 }
124 
125 
126 static void
127 rb_alert_dialog_init (RBAlertDialog *dialog)
128 {
129 	GtkWidget *hbox;
130 	GtkWidget *vbox;
131 	GtkWidget *expander;
132 	GtkWidget *content;
133 
134 	dialog->details = g_new0 (RBAlertDialogDetails, 1);
135 
136 	dialog->details->primary_label = gtk_label_new (NULL);
137 	dialog->details->secondary_label = gtk_label_new (NULL);
138 	dialog->details->details_label = gtk_label_new (NULL);
139 	dialog->details->image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG);
140 	gtk_misc_set_alignment (GTK_MISC (dialog->details->image), 0.5, 0.0);
141 
142 	gtk_label_set_line_wrap (GTK_LABEL (dialog->details->primary_label), TRUE);
143 	gtk_label_set_selectable (GTK_LABEL (dialog->details->primary_label), TRUE);
144 	gtk_label_set_use_markup (GTK_LABEL (dialog->details->primary_label), TRUE);
145 	gtk_misc_set_alignment (GTK_MISC (dialog->details->primary_label), 0.0, 0.5);
146 
147 	gtk_label_set_line_wrap (GTK_LABEL (dialog->details->secondary_label), TRUE);
148 	gtk_label_set_selectable (GTK_LABEL (dialog->details->secondary_label), TRUE);
149 	gtk_misc_set_alignment (GTK_MISC (dialog->details->secondary_label), 0.0, 0.5);
150 
151 	gtk_label_set_line_wrap (GTK_LABEL (dialog->details->details_label), TRUE);
152 	gtk_label_set_selectable (GTK_LABEL (dialog->details->details_label), TRUE);
153 	gtk_misc_set_alignment (GTK_MISC (dialog->details->details_label), 0.0, 0.5);
154 
155 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
156 	gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
157 
158 	gtk_box_pack_start (GTK_BOX (hbox), dialog->details->image,
159 	                    FALSE, FALSE, 0);
160 
161 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
162 
163 	gtk_box_pack_start (GTK_BOX (hbox), vbox,
164 	                    FALSE, FALSE, 0);
165 
166 	gtk_box_pack_start (GTK_BOX (vbox), dialog->details->primary_label,
167 	                    FALSE, FALSE, 0);
168 
169 	gtk_box_pack_start (GTK_BOX (vbox), dialog->details->secondary_label,
170 	                    FALSE, FALSE, 0);
171 
172 	expander = gtk_expander_new_with_mnemonic (_("Show more _details"));
173 	dialog->details->details_expander = expander;
174 	gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
175 	gtk_container_add (GTK_CONTAINER (expander), dialog->details->details_label);
176 
177 	gtk_box_pack_start (GTK_BOX (vbox), expander,
178 			    FALSE, FALSE, 0);
179 
180 	content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
181 	gtk_box_pack_start (GTK_BOX (content), hbox, FALSE, FALSE, 0);
182 
183 	gtk_widget_show_all (hbox);
184 	gtk_widget_hide (expander);
185 
186 }
187 
188 static void
189 setup_type (RBAlertDialog *dialog,
190 	    GtkMessageType  type)
191 {
192 	const gchar *stock_id = NULL;
193 	GtkStockItem item;
194 
195 	switch (type) {
196 		case GTK_MESSAGE_INFO:
197 			stock_id = GTK_STOCK_DIALOG_INFO;
198 			break;
199 		case GTK_MESSAGE_QUESTION:
200 			stock_id = GTK_STOCK_DIALOG_QUESTION;
201 			break;
202 		case GTK_MESSAGE_WARNING:
203 			stock_id = GTK_STOCK_DIALOG_WARNING;
204 			break;
205 		case GTK_MESSAGE_ERROR:
206 			stock_id = GTK_STOCK_DIALOG_ERROR;
207 			break;
208 		default:
209 			g_warning ("Unknown GtkMessageType %d", type);
210 			break;
211 	}
212 
213 	if (stock_id == NULL) {
214 		stock_id = GTK_STOCK_DIALOG_INFO;
215 	}
216 
217 	if (gtk_stock_lookup (stock_id, &item)) {
218 		gtk_image_set_from_stock (GTK_IMAGE (dialog->details->image), stock_id,
219 		                          GTK_ICON_SIZE_DIALOG);
220 	} else {
221 		g_warning ("Stock dialog ID doesn't exist?");
222 	}
223 }
224 
225 static void
226 rb_alert_dialog_set_property (GObject      *object,
227                                guint         prop_id,
228                                const GValue *value,
229                                GParamSpec   *pspec)
230 {
231 	RBAlertDialog *dialog;
232 
233 	dialog = RB_ALERT_DIALOG (object);
234 
235 	switch (prop_id) {
236 		case PROP_ALERT_TYPE:
237 			dialog->details->type = g_value_get_enum (value);
238 			setup_type (dialog, dialog->details->type);
239 			break;
240 		case PROP_BUTTONS:
241 			rb_alert_dialog_add_buttons (dialog, g_value_get_enum (value));
242 			break;
243 		default:
244 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
245 			break;
246 	}
247 }
248 
249 static void
250 rb_alert_dialog_get_property (GObject     *object,
251                                guint        prop_id,
252                                GValue      *value,
253                                GParamSpec  *pspec)
254 {
255 	RBAlertDialog *dialog;
256 
257 	dialog = RB_ALERT_DIALOG (object);
258 
259 	switch (prop_id) {
260 		case PROP_ALERT_TYPE:
261 			g_value_set_enum (value, dialog->details->type);
262 			break;
263 		default:
264 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
265 			break;
266 	}
267 }
268 
269 void
270 rb_alert_dialog_set_primary_label (RBAlertDialog *dialog,
271                                     const gchar *message)
272 {
273 	gchar *markup_str;
274 	char *escaped_message;
275 
276 	if (message != NULL) {
277 		escaped_message = g_markup_escape_text (message, -1);
278 		markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", escaped_message, "</span>", NULL);
279 		gtk_label_set_markup (GTK_LABEL (RB_ALERT_DIALOG (dialog)->details->primary_label),
280 		                      markup_str);
281 		g_free (markup_str);
282 		g_free (escaped_message);
283 	}
284 }
285 
286 void
287 rb_alert_dialog_set_secondary_label (RBAlertDialog *dialog,
288                                       const gchar *message)
289 {
290 	if (message != NULL) {
291 		gtk_label_set_text (GTK_LABEL (RB_ALERT_DIALOG (dialog)->details->secondary_label),
292 		                    message);
293 	} else {
294 		gtk_widget_hide (RB_ALERT_DIALOG (dialog)->details->secondary_label);
295 	}
296 }
297 
298 void
299 rb_alert_dialog_set_details_label (RBAlertDialog *dialog,
300 				    const gchar    *message)
301 {
302 	if (message != NULL) {
303 		gtk_widget_show (dialog->details->details_expander);
304 		gtk_label_set_text (GTK_LABEL (dialog->details->details_label), message);
305 	} else {
306 		gtk_widget_hide (dialog->details->details_expander);
307 	}
308 }
309 
310 
311 GtkWidget*
312 rb_alert_dialog_new (GtkWindow     *parent,
313                       GtkDialogFlags flags,
314                       GtkMessageType type,
315                       GtkButtonsType buttons,
316                       const gchar   *primary_message,
317                       const gchar   *secondary_message)
318 {
319 	GtkWidget *widget;
320 	GtkDialog *dialog;
321 	GtkWidget *content;
322 
323 	g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
324 
325 	widget = g_object_new (RB_TYPE_ALERT_DIALOG,
326 	                       "alert_type", type,
327 	                       "buttons", buttons,
328 	                       NULL);
329 	atk_object_set_role (gtk_widget_get_accessible (widget), ATK_ROLE_ALERT);
330 
331 	dialog = GTK_DIALOG (widget);
332 
333 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
334 	content = gtk_dialog_get_content_area (dialog);
335 	gtk_box_set_spacing (GTK_BOX (content), 14);
336 	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
337 
338 	/* Make sure we don't get a window title.
339          * HIG says that alert dialogs should not have window title
340          */
341 	gtk_window_set_title (GTK_WINDOW (dialog), "");
342 	gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
343 
344 	rb_alert_dialog_set_primary_label (RB_ALERT_DIALOG (dialog),
345 	                                    primary_message);
346 
347 	rb_alert_dialog_set_secondary_label (RB_ALERT_DIALOG (dialog),
348 	                                      secondary_message);
349 
350 	if (parent != NULL) {
351 		gtk_window_set_transient_for (GTK_WINDOW (widget),
352 		                              GTK_WINDOW (parent));
353 	}
354 
355 	if (flags & GTK_DIALOG_MODAL) {
356 		gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
357 	}
358 
359 	if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) {
360 		gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
361 	}
362 	return widget;
363 }
364 
365 static void
366 rb_alert_dialog_add_buttons (RBAlertDialog* alert_dialog,
367                               GtkButtonsType  buttons)
368 {
369 	GtkDialog* dialog;
370 
371 	dialog = GTK_DIALOG (alert_dialog);
372 
373 	switch (buttons) {
374 		case GTK_BUTTONS_NONE:
375 			break;
376 		case GTK_BUTTONS_OK:
377 			gtk_dialog_add_button (dialog,
378 		                               GTK_STOCK_OK,
379 			                       GTK_RESPONSE_OK);
380 			gtk_dialog_set_default_response (dialog,
381 			                                GTK_RESPONSE_OK);
382 			break;
383 		case GTK_BUTTONS_CLOSE:
384 			gtk_dialog_add_button (dialog,
385 		                               GTK_STOCK_CLOSE,
386 			                      GTK_RESPONSE_CLOSE);
387 			gtk_dialog_set_default_response (dialog,
388 			                                 GTK_RESPONSE_CLOSE);
389 			break;
390 		case GTK_BUTTONS_CANCEL:
391 			gtk_dialog_add_button (dialog,
392 			                       GTK_STOCK_CANCEL,
393 			                       GTK_RESPONSE_CANCEL);
394 			gtk_dialog_set_default_response (dialog,
395 			                                 GTK_RESPONSE_CANCEL);
396 			break;
397 		case GTK_BUTTONS_YES_NO:
398 			gtk_dialog_add_button (dialog,
399 			                       GTK_STOCK_NO,
400 			                       GTK_RESPONSE_NO);
401 			gtk_dialog_add_button (dialog,
402 			                       GTK_STOCK_YES,
403 			                       GTK_RESPONSE_YES);
404 			gtk_dialog_set_default_response (dialog,
405 			                                 GTK_RESPONSE_YES);
406 			break;
407 		case GTK_BUTTONS_OK_CANCEL:
408 			gtk_dialog_add_button (dialog,
409 			                       GTK_STOCK_CANCEL,
410 			                       GTK_RESPONSE_CANCEL);
411 			gtk_dialog_add_button (dialog,
412 			                       GTK_STOCK_OK,
413 			                       GTK_RESPONSE_OK);
414 			gtk_dialog_set_default_response (dialog,
415 			                                 GTK_RESPONSE_OK);
416 			break;
417 		default:
418 			g_warning ("Unknown GtkButtonsType");
419 			break;
420 	}
421 	g_object_notify (G_OBJECT (alert_dialog), "buttons");
422 }
423 
424 static void
425 rb_alert_dialog_style_set (GtkWidget *widget,
426                             GtkStyle  *prev_style)
427 {
428 	GtkWidget *parent;
429 	gint border_width;
430 
431 	border_width = 0;
432 
433 	parent = gtk_widget_get_parent (RB_ALERT_DIALOG (widget)->details->image);
434 
435 	if (parent != NULL) {
436 		gtk_widget_style_get (widget, "alert_border",
437 		                      &border_width, NULL);
438 
439 		gtk_container_set_border_width (GTK_CONTAINER (parent),
440 		                                border_width);
441 	}
442 
443 	if (GTK_WIDGET_CLASS (parent_class)->style_set) {
444 		(GTK_WIDGET_CLASS (parent_class)->style_set) (widget, prev_style);
445 	}
446 }