]> Pileus Git - ~andy/gtk/blob - gtk/gtkmessagedialog.c
Remove unnused variable
[~andy/gtk] / gtk / gtkmessagedialog.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* GTK - The GIMP Toolkit
3  * Copyright (C) 2000 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This 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 this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2003.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29 #include <string.h>
30
31 #include "gtkmessagedialog.h"
32 #include "gtkaccessible.h"
33 #include "gtklabel.h"
34 #include "gtkhbox.h"
35 #include "gtkvbox.h"
36 #include "gtkimage.h"
37 #include "gtkstock.h"
38 #include "gtkiconfactory.h"
39 #include "gtkintl.h"
40 #include "gtkprivate.h"
41 #include "gtkalias.h"
42
43 /**
44  * SECTION:gtkmessagedialog
45  * @Short_description: A convenient message window
46  * @Title: GtkMessageDialog
47  * @See_also:#GtkDialog
48  *
49  * #GtkMessageDialog presents a dialog with an image representing the type of
50  * message (Error, Question, etc.) alongside some message text. It's simply a
51  * convenience widget; you could construct the equivalent of #GtkMessageDialog
52  * from #GtkDialog without too much effort, but #GtkMessageDialog saves typing.
53  *
54  * The easiest way to do a modal message dialog is to use gtk_dialog_run(), though
55  * you can also pass in the %GTK_DIALOG_MODAL flag, gtk_dialog_run() automatically
56  * makes the dialog modal and waits for the user to respond to it. gtk_dialog_run()
57  * returns when any dialog button is clicked.
58  * <example>
59  * <title>A modal dialog.</title>
60  * <programlisting>
61  *  dialog = gtk_message_dialog_new (main_application_window,
62  *                                   GTK_DIALOG_DESTROY_WITH_PARENT,
63  *                                   GTK_MESSAGE_ERROR,
64  *                                   GTK_BUTTONS_CLOSE,
65  *                                   "Error loading file '&percnt;s': &percnt;s",
66  *                                   filename, g_strerror (errno));
67  *  gtk_dialog_run (GTK_DIALOG (dialog));
68  *  gtk_widget_destroy (dialog);
69  * </programlisting>
70  * </example>
71  * You might do a non-modal #GtkMessageDialog as follows:
72  * <example>
73  * <title>A non-modal dialog.</title>
74  * <programlisting>
75  *  dialog = gtk_message_dialog_new (main_application_window,
76  *                                   GTK_DIALOG_DESTROY_WITH_PARENT,
77  *                                   GTK_MESSAGE_ERROR,
78  *                                   GTK_BUTTONS_CLOSE,
79  *                                   "Error loading file '&percnt;s': &percnt;s",
80  *                                   filename, g_strerror (errno));
81  *
82  *  /&ast; Destroy the dialog when the user responds to it (e.g. clicks a button) &ast;/
83  *  g_signal_connect_swapped (dialog, "response",
84  *                            G_CALLBACK (gtk_widget_destroy),
85  *                            dialog);
86  * </programlisting>
87  * </example>
88  */
89
90 #define GTK_MESSAGE_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_MESSAGE_DIALOG, GtkMessageDialogPrivate))
91
92 typedef struct _GtkMessageDialogPrivate GtkMessageDialogPrivate;
93
94 struct _GtkMessageDialogPrivate
95 {
96   GtkWidget *message_area; /* vbox for the primary and secondary labels, and any extra content from the caller */
97   GtkWidget *secondary_label;
98   guint message_type : 3;
99   guint has_primary_markup : 1;
100   guint has_secondary_text : 1;
101 };
102
103 static void gtk_message_dialog_style_set  (GtkWidget             *widget,
104                                            GtkStyle              *prev_style);
105
106 static void gtk_message_dialog_set_property (GObject          *object,
107                                              guint             prop_id,
108                                              const GValue     *value,
109                                              GParamSpec       *pspec);
110 static void gtk_message_dialog_get_property (GObject          *object,
111                                              guint             prop_id,
112                                              GValue           *value,
113                                              GParamSpec       *pspec);
114 static void gtk_message_dialog_add_buttons  (GtkMessageDialog *message_dialog,
115                                              GtkButtonsType    buttons);
116
117 enum {
118   PROP_0,
119   PROP_MESSAGE_TYPE,
120   PROP_BUTTONS,
121   PROP_TEXT,
122   PROP_USE_MARKUP,
123   PROP_SECONDARY_TEXT,
124   PROP_SECONDARY_USE_MARKUP,
125   PROP_IMAGE,
126   PROP_MESSAGE_AREA
127 };
128
129 G_DEFINE_TYPE (GtkMessageDialog, gtk_message_dialog, GTK_TYPE_DIALOG)
130
131 static void
132 gtk_message_dialog_class_init (GtkMessageDialogClass *class)
133 {
134   GtkWidgetClass *widget_class;
135   GObjectClass *gobject_class;
136
137   widget_class = GTK_WIDGET_CLASS (class);
138   gobject_class = G_OBJECT_CLASS (class);
139   
140   widget_class->style_set = gtk_message_dialog_style_set;
141
142   gobject_class->set_property = gtk_message_dialog_set_property;
143   gobject_class->get_property = gtk_message_dialog_get_property;
144   
145   gtk_widget_class_install_style_property (widget_class,
146                                            g_param_spec_int ("message-border",
147                                                              P_("Image/label border"),
148                                                              P_("Width of border around the label and image in the message dialog"),
149                                                              0,
150                                                              G_MAXINT,
151                                                              12,
152                                                              GTK_PARAM_READABLE));
153   /**
154    * GtkMessageDialog:use-separator:
155    *
156    * Whether to draw a separator line between the message label and the buttons
157    * in the dialog.
158    *
159    * Since: 2.4
160    */
161   gtk_widget_class_install_style_property (widget_class,
162                                            g_param_spec_boolean ("use-separator",
163                                                                  P_("Use separator"),
164                                                                  P_("Whether to put a separator between the message dialog's text and the buttons"),
165                                                                  FALSE,
166                                                                  GTK_PARAM_READABLE));
167   /**
168    * GtkMessageDialog:message-type:
169    *
170    * The type of the message. The type is used to determine
171    * the image that is shown in the dialog, unless the image is 
172    * explicitly set by the ::image property.
173    */
174   g_object_class_install_property (gobject_class,
175                                    PROP_MESSAGE_TYPE,
176                                    g_param_spec_enum ("message-type",
177                                                       P_("Message Type"),
178                                                       P_("The type of message"),
179                                                       GTK_TYPE_MESSAGE_TYPE,
180                                                       GTK_MESSAGE_INFO,
181                                                       GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
182   g_object_class_install_property (gobject_class,
183                                    PROP_BUTTONS,
184                                    g_param_spec_enum ("buttons",
185                                                       P_("Message Buttons"),
186                                                       P_("The buttons shown in the message dialog"),
187                                                       GTK_TYPE_BUTTONS_TYPE,
188                                                       GTK_BUTTONS_NONE,
189                                                       GTK_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
190
191   /**
192    * GtkMessageDialog:text:
193    * 
194    * The primary text of the message dialog. If the dialog has 
195    * a secondary text, this will appear as the title.
196    *
197    * Since: 2.10
198    */
199   g_object_class_install_property (gobject_class,
200                                    PROP_TEXT,
201                                    g_param_spec_string ("text",
202                                                         P_("Text"),
203                                                         P_("The primary text of the message dialog"),
204                                                         "",
205                                                         GTK_PARAM_READWRITE));
206
207   /**
208    * GtkMessageDialog:use-markup:
209    * 
210    * %TRUE if the primary text of the dialog includes Pango markup. 
211    * See pango_parse_markup(). 
212    *
213    * Since: 2.10
214    */
215   g_object_class_install_property (gobject_class,
216                                    PROP_USE_MARKUP,
217                                    g_param_spec_boolean ("use-markup",
218                                                          P_("Use Markup"),
219                                                          P_("The primary text of the title includes Pango markup."),
220                                                          FALSE,
221                                                          GTK_PARAM_READWRITE));
222   
223   /**
224    * GtkMessageDialog:secondary-text:
225    * 
226    * The secondary text of the message dialog. 
227    *
228    * Since: 2.10
229    */
230   g_object_class_install_property (gobject_class,
231                                    PROP_SECONDARY_TEXT,
232                                    g_param_spec_string ("secondary-text",
233                                                         P_("Secondary Text"),
234                                                         P_("The secondary text of the message dialog"),
235                                                         NULL,
236                                                         GTK_PARAM_READWRITE));
237
238   /**
239    * GtkMessageDialog:secondary-use-markup:
240    * 
241    * %TRUE if the secondary text of the dialog includes Pango markup. 
242    * See pango_parse_markup(). 
243    *
244    * Since: 2.10
245    */
246   g_object_class_install_property (gobject_class,
247                                    PROP_SECONDARY_USE_MARKUP,
248                                    g_param_spec_boolean ("secondary-use-markup",
249                                                          P_("Use Markup in secondary"),
250                                                          P_("The secondary text includes Pango markup."),
251                                                          FALSE,
252                                                          GTK_PARAM_READWRITE));
253
254   /**
255    * GtkMessageDialog:image:
256    * 
257    * The image for this dialog.
258    *
259    * Since: 2.10
260    */
261   g_object_class_install_property (gobject_class,
262                                    PROP_IMAGE,
263                                    g_param_spec_object ("image",
264                                                         P_("Image"),
265                                                         P_("The image"),
266                                                         GTK_TYPE_WIDGET,
267                                                         GTK_PARAM_READWRITE));
268
269   /**
270    * GtkMessageDialog:message-area
271    *
272    * The #GtkVBox that corresponds to the message area of this dialog.  See
273    * gtk_message_dialog_get_message_area() for a detailed description of this
274    * area.
275    *
276    * Since: 2.22
277    */
278   g_object_class_install_property (gobject_class,
279                                    PROP_MESSAGE_AREA,
280                                    g_param_spec_object ("message-area",
281                                                         P_("Message area"),
282                                                         P_("GtkVBox that holds the dialog's primary and secondary labels"),
283                                                         GTK_TYPE_WIDGET,
284                                                         GTK_PARAM_READABLE));
285
286   g_type_class_add_private (gobject_class,
287                             sizeof (GtkMessageDialogPrivate));
288 }
289
290 static void
291 gtk_message_dialog_init (GtkMessageDialog *dialog)
292 {
293   GtkWidget *hbox;
294   GtkMessageDialogPrivate *priv;
295
296   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
297
298   gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
299   gtk_window_set_title (GTK_WINDOW (dialog), "");
300   gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
301
302   priv->has_primary_markup = FALSE;
303   priv->has_secondary_text = FALSE;
304   priv->secondary_label = gtk_label_new (NULL);
305   gtk_widget_set_no_show_all (priv->secondary_label, TRUE);
306   
307   dialog->label = gtk_label_new (NULL);
308   dialog->image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG);
309   gtk_misc_set_alignment (GTK_MISC (dialog->image), 0.5, 0.0);
310   
311   gtk_label_set_line_wrap  (GTK_LABEL (dialog->label), TRUE);
312   gtk_label_set_selectable (GTK_LABEL (dialog->label), TRUE);
313   gtk_misc_set_alignment   (GTK_MISC  (dialog->label), 0.0, 0.0);
314   
315   gtk_label_set_line_wrap  (GTK_LABEL (priv->secondary_label), TRUE);
316   gtk_label_set_selectable (GTK_LABEL (priv->secondary_label), TRUE);
317   gtk_misc_set_alignment   (GTK_MISC  (priv->secondary_label), 0.0, 0.0);
318
319   hbox = gtk_hbox_new (FALSE, 12);
320   priv->message_area = gtk_vbox_new (FALSE, 12);
321
322   gtk_box_pack_start (GTK_BOX (priv->message_area), dialog->label,
323                       FALSE, FALSE, 0);
324
325   gtk_box_pack_start (GTK_BOX (priv->message_area), priv->secondary_label,
326                       TRUE, TRUE, 0);
327
328   gtk_box_pack_start (GTK_BOX (hbox), dialog->image,
329                       FALSE, FALSE, 0);
330
331   gtk_box_pack_start (GTK_BOX (hbox), priv->message_area,
332                       TRUE, TRUE, 0);
333
334   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
335                       hbox,
336                       FALSE, FALSE, 0);
337
338   gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
339   gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
340   gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14); /* 14 + 2 * 5 = 24 */
341   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 5);
342   gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
343
344   gtk_widget_show_all (hbox);
345
346   _gtk_dialog_set_ignore_separator (GTK_DIALOG (dialog), TRUE);
347 }
348
349 static void
350 setup_primary_label_font (GtkMessageDialog *dialog)
351 {
352   gint size;
353   PangoFontDescription *font_desc;
354   GtkMessageDialogPrivate *priv;
355
356   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
357
358   /* unset the font settings */
359   gtk_widget_modify_font (dialog->label, NULL);
360
361   if (priv->has_secondary_text && !priv->has_primary_markup)
362     {
363       size = pango_font_description_get_size (dialog->label->style->font_desc);
364       font_desc = pango_font_description_new ();
365       pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
366       pango_font_description_set_size (font_desc, size * PANGO_SCALE_LARGE);
367       gtk_widget_modify_font (dialog->label, font_desc);
368       pango_font_description_free (font_desc);
369     }
370 }
371
372 static void
373 setup_type (GtkMessageDialog *dialog,
374             GtkMessageType    type)
375 {
376   GtkMessageDialogPrivate *priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
377   const gchar *stock_id = NULL;
378   AtkObject *atk_obj;
379  
380   priv->message_type = type;
381
382   switch (type)
383     {
384     case GTK_MESSAGE_INFO:
385       stock_id = GTK_STOCK_DIALOG_INFO;
386       break;
387
388     case GTK_MESSAGE_QUESTION:
389       stock_id = GTK_STOCK_DIALOG_QUESTION;
390       break;
391
392     case GTK_MESSAGE_WARNING:
393       stock_id = GTK_STOCK_DIALOG_WARNING;
394       break;
395       
396     case GTK_MESSAGE_ERROR:
397       stock_id = GTK_STOCK_DIALOG_ERROR;
398       break;
399
400     case GTK_MESSAGE_OTHER:
401       break;
402
403     default:
404       g_warning ("Unknown GtkMessageType %u", type);
405       break;
406     }
407
408   if (stock_id)
409     gtk_image_set_from_stock (GTK_IMAGE (dialog->image), stock_id,
410                               GTK_ICON_SIZE_DIALOG);
411       
412   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (dialog));
413   if (GTK_IS_ACCESSIBLE (atk_obj))
414     {
415       atk_object_set_role (atk_obj, ATK_ROLE_ALERT);
416       if (stock_id)
417         {
418           GtkStockItem item;
419
420           gtk_stock_lookup (stock_id, &item);
421           atk_object_set_name (atk_obj, item.label);
422         }
423     }
424 }
425
426 static void 
427 gtk_message_dialog_set_property (GObject      *object,
428                                  guint         prop_id,
429                                  const GValue *value,
430                                  GParamSpec   *pspec)
431 {
432   GtkMessageDialog *dialog;
433   GtkMessageDialogPrivate *priv;
434
435   dialog = GTK_MESSAGE_DIALOG (object);
436   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
437   
438   switch (prop_id)
439     {
440     case PROP_MESSAGE_TYPE:
441       setup_type (dialog, g_value_get_enum (value));
442       break;
443     case PROP_BUTTONS:
444       gtk_message_dialog_add_buttons (dialog, g_value_get_enum (value));
445       break;
446     case PROP_TEXT:
447       if (priv->has_primary_markup)
448         gtk_label_set_markup (GTK_LABEL (dialog->label), 
449                               g_value_get_string (value));
450       else
451         gtk_label_set_text (GTK_LABEL (dialog->label), 
452                             g_value_get_string (value));
453       break;
454     case PROP_USE_MARKUP:
455       priv->has_primary_markup = g_value_get_boolean (value) != FALSE;
456       gtk_label_set_use_markup (GTK_LABEL (dialog->label), 
457                                 priv->has_primary_markup);
458       setup_primary_label_font (dialog);
459       break;
460     case PROP_SECONDARY_TEXT:
461       {
462         const gchar *txt = g_value_get_string (value);
463         
464         if (gtk_label_get_use_markup (GTK_LABEL (priv->secondary_label)))
465           gtk_label_set_markup (GTK_LABEL (priv->secondary_label), txt);
466         else
467           gtk_label_set_text (GTK_LABEL (priv->secondary_label), txt);
468
469         if (txt)
470           {
471             priv->has_secondary_text = TRUE;
472             gtk_widget_show (priv->secondary_label);
473           }
474         else
475           {
476             priv->has_secondary_text = FALSE;
477             gtk_widget_hide (priv->secondary_label);
478           }
479         setup_primary_label_font (dialog);
480       }
481       break;
482     case PROP_SECONDARY_USE_MARKUP:
483       gtk_label_set_use_markup (GTK_LABEL (priv->secondary_label), 
484                                 g_value_get_boolean (value));
485       break;
486     case PROP_IMAGE:
487       gtk_message_dialog_set_image (dialog, g_value_get_object (value));
488       break;
489
490     default:
491       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
492       break;
493     }
494 }
495
496 static void 
497 gtk_message_dialog_get_property (GObject     *object,
498                                  guint        prop_id,
499                                  GValue      *value,
500                                  GParamSpec  *pspec)
501 {
502   GtkMessageDialog *dialog;
503   GtkMessageDialogPrivate *priv;
504
505   dialog = GTK_MESSAGE_DIALOG (object);
506   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
507     
508   switch (prop_id)
509     {
510     case PROP_MESSAGE_TYPE:
511       g_value_set_enum (value, (GtkMessageType) priv->message_type);
512       break;
513     case PROP_TEXT:
514       g_value_set_string (value, gtk_label_get_label (GTK_LABEL (dialog->label)));
515       break;
516     case PROP_USE_MARKUP:
517       g_value_set_boolean (value, priv->has_primary_markup);
518       break;
519     case PROP_SECONDARY_TEXT:
520       if (priv->has_secondary_text)
521       g_value_set_string (value, 
522                           gtk_label_get_label (GTK_LABEL (priv->secondary_label)));
523       else
524         g_value_set_string (value, NULL);
525       break;
526     case PROP_SECONDARY_USE_MARKUP:
527       if (priv->has_secondary_text)
528         g_value_set_boolean (value, 
529                              gtk_label_get_use_markup (GTK_LABEL (priv->secondary_label)));
530       else
531         g_value_set_boolean (value, FALSE);
532       break;
533     case PROP_IMAGE:
534       g_value_set_object (value, dialog->image);
535       break;
536     case PROP_MESSAGE_AREA:
537       g_value_set_object (value, priv->message_area);
538       break;
539     default:
540       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
541       break;
542     }
543 }
544
545 /**
546  * gtk_message_dialog_new:
547  * @parent: (allow-none): transient parent, or %NULL for none
548  * @flags: flags
549  * @type: type of message
550  * @buttons: set of buttons to use
551  * @message_format: (allow-none): printf()-style format string, or %NULL
552  * @Varargs: arguments for @message_format
553  *
554  * Creates a new message dialog, which is a simple dialog with an icon
555  * indicating the dialog type (error, warning, etc.) and some text the
556  * user may want to see. When the user clicks a button a "response"
557  * signal is emitted with response IDs from #GtkResponseType. See
558  * #GtkDialog for more details.
559  *
560  * Return value: (transfer none): a new #GtkMessageDialog
561  **/
562 GtkWidget*
563 gtk_message_dialog_new (GtkWindow     *parent,
564                         GtkDialogFlags flags,
565                         GtkMessageType type,
566                         GtkButtonsType buttons,
567                         const gchar   *message_format,
568                         ...)
569 {
570   GtkWidget *widget;
571   GtkDialog *dialog;
572   gchar* msg = NULL;
573   va_list args;
574
575   g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
576
577   widget = g_object_new (GTK_TYPE_MESSAGE_DIALOG,
578                          "message-type", type,
579                          "buttons", buttons,
580                          NULL);
581   dialog = GTK_DIALOG (widget);
582
583   if (flags & GTK_DIALOG_NO_SEPARATOR)
584     {
585       g_warning ("The GTK_DIALOG_NO_SEPARATOR flag cannot be used for GtkMessageDialog");
586       flags &= ~GTK_DIALOG_NO_SEPARATOR;
587     }
588
589   if (message_format)
590     {
591       va_start (args, message_format);
592       msg = g_strdup_vprintf (message_format, args);
593       va_end (args);
594
595       gtk_label_set_text (GTK_LABEL (GTK_MESSAGE_DIALOG (widget)->label),
596                           msg);
597
598       g_free (msg);
599     }
600
601   if (parent != NULL)
602     gtk_window_set_transient_for (GTK_WINDOW (widget),
603                                   GTK_WINDOW (parent));
604   
605   if (flags & GTK_DIALOG_MODAL)
606     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
607
608   if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
609     gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
610
611   return widget;
612 }
613
614 /**
615  * gtk_message_dialog_new_with_markup:
616  * @parent: (allow-none): transient parent, or %NULL for none 
617  * @flags: flags
618  * @type: type of message
619  * @buttons: set of buttons to use
620  * @message_format: (allow-none): printf()-style format string, or %NULL
621  * @Varargs: arguments for @message_format
622  * 
623  * Creates a new message dialog, which is a simple dialog with an icon
624  * indicating the dialog type (error, warning, etc.) and some text which
625  * is marked up with the <link linkend="PangoMarkupFormat">Pango text markup language</link>.
626  * When the user clicks a button a "response" signal is emitted with
627  * response IDs from #GtkResponseType. See #GtkDialog for more details.
628  *
629  * Special XML characters in the printf() arguments passed to this
630  * function will automatically be escaped as necessary.
631  * (See g_markup_printf_escaped() for how this is implemented.)
632  * Usually this is what you want, but if you have an existing
633  * Pango markup string that you want to use literally as the
634  * label, then you need to use gtk_message_dialog_set_markup()
635  * instead, since you can't pass the markup string either
636  * as the format (it might contain '%' characters) or as a string
637  * argument.
638  * |[
639  *  GtkWidget *dialog;
640  *  dialog = gtk_message_dialog_new (main_application_window,
641  *                                   GTK_DIALOG_DESTROY_WITH_PARENT,
642  *                                   GTK_MESSAGE_ERROR,
643  *                                   GTK_BUTTONS_CLOSE,
644  *                                   NULL);
645  *  gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
646  *                                 markup);
647  * ]|
648  * 
649  * Return value: a new #GtkMessageDialog
650  *
651  * Since: 2.4
652  **/
653 GtkWidget*
654 gtk_message_dialog_new_with_markup (GtkWindow     *parent,
655                                     GtkDialogFlags flags,
656                                     GtkMessageType type,
657                                     GtkButtonsType buttons,
658                                     const gchar   *message_format,
659                                     ...)
660 {
661   GtkWidget *widget;
662   va_list args;
663   gchar *msg = NULL;
664
665   g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
666
667   widget = gtk_message_dialog_new (parent, flags, type, buttons, NULL);
668
669   if (message_format)
670     {
671       va_start (args, message_format);
672       msg = g_markup_vprintf_escaped (message_format, args);
673       va_end (args);
674
675       gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (widget), msg);
676
677       g_free (msg);
678     }
679
680   return widget;
681 }
682
683 /**
684  * gtk_message_dialog_set_image:
685  * @dialog: a #GtkMessageDialog
686  * @image: the image
687  * 
688  * Sets the dialog's image to @image.
689  *
690  * Since: 2.10
691  **/
692 void
693 gtk_message_dialog_set_image (GtkMessageDialog *dialog,
694                               GtkWidget        *image)
695 {
696   GtkMessageDialogPrivate *priv;
697   GtkWidget *parent;
698
699   g_return_if_fail (GTK_IS_MESSAGE_DIALOG (dialog));
700   g_return_if_fail (image == NULL || GTK_IS_WIDGET (image));
701
702   if (image == NULL)
703     {
704       image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG);
705       gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
706     }
707
708   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (dialog);
709
710   priv->message_type = GTK_MESSAGE_OTHER;
711   
712   parent = dialog->image->parent;
713   gtk_container_add (GTK_CONTAINER (parent), image);
714   gtk_container_remove (GTK_CONTAINER (parent), dialog->image);
715   gtk_box_reorder_child (GTK_BOX (parent), image, 0);
716
717   dialog->image = image;
718
719   g_object_notify (G_OBJECT (dialog), "image");
720 }
721
722 /**
723  * gtk_message_dialog_get_image:
724  * @dialog: a #GtkMessageDialog
725  *
726  * Gets the dialog's image.
727  *
728  * Return value: the dialog's image
729  *
730  * Since: 2.14
731  **/
732 GtkWidget *
733 gtk_message_dialog_get_image (GtkMessageDialog *dialog)
734 {
735   g_return_val_if_fail (GTK_IS_MESSAGE_DIALOG (dialog), NULL);
736
737   return dialog->image;
738 }
739
740 /**
741  * gtk_message_dialog_set_markup:
742  * @message_dialog: a #GtkMessageDialog
743  * @str: markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
744  * 
745  * Sets the text of the message dialog to be @str, which is marked
746  * up with the <link linkend="PangoMarkupFormat">Pango text markup
747  * language</link>.
748  *
749  * Since: 2.4
750  **/
751 void
752 gtk_message_dialog_set_markup (GtkMessageDialog *message_dialog,
753                                const gchar      *str)
754 {
755   GtkMessageDialogPrivate *priv;
756
757   g_return_if_fail (GTK_IS_MESSAGE_DIALOG (message_dialog));
758
759   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (message_dialog);
760   priv->has_primary_markup = TRUE;
761   gtk_label_set_markup (GTK_LABEL (message_dialog->label), str);
762 }
763
764 /**
765  * gtk_message_dialog_format_secondary_text:
766  * @message_dialog: a #GtkMessageDialog
767  * @message_format: (allow-none): printf()-style format string, or %NULL
768  * @Varargs: arguments for @message_format
769  * 
770  * Sets the secondary text of the message dialog to be @message_format 
771  * (with printf()-style).
772  *
773  * Note that setting a secondary text makes the primary text become
774  * bold, unless you have provided explicit markup.
775  *
776  * Since: 2.6
777  **/
778 void
779 gtk_message_dialog_format_secondary_text (GtkMessageDialog *message_dialog,
780                                           const gchar      *message_format,
781                                           ...)
782 {
783   va_list args;
784   gchar *msg = NULL;
785   GtkMessageDialogPrivate *priv;
786
787   g_return_if_fail (GTK_IS_MESSAGE_DIALOG (message_dialog));
788
789   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (message_dialog);
790
791   if (message_format)
792     {
793       priv->has_secondary_text = TRUE;
794
795       va_start (args, message_format);
796       msg = g_strdup_vprintf (message_format, args);
797       va_end (args);
798
799       gtk_widget_show (priv->secondary_label);
800       gtk_label_set_text (GTK_LABEL (priv->secondary_label), msg);
801
802       g_free (msg);
803     }
804   else
805     {
806       priv->has_secondary_text = FALSE;
807       gtk_widget_hide (priv->secondary_label);
808     }
809
810   setup_primary_label_font (message_dialog);
811 }
812
813 /**
814  * gtk_message_dialog_format_secondary_markup:
815  * @message_dialog: a #GtkMessageDialog
816  * @message_format: printf()-style markup string (see 
817      <link linkend="PangoMarkupFormat">Pango markup format</link>), or %NULL
818  * @Varargs: arguments for @message_format
819  * 
820  * Sets the secondary text of the message dialog to be @message_format (with 
821  * printf()-style), which is marked up with the 
822  * <link linkend="PangoMarkupFormat">Pango text markup language</link>.
823  *
824  * Note that setting a secondary text makes the primary text become
825  * bold, unless you have provided explicit markup.
826  *
827  * Due to an oversight, this function does not escape special XML characters
828  * like gtk_message_dialog_new_with_markup() does. Thus, if the arguments 
829  * may contain special XML characters, you should use g_markup_printf_escaped()
830  * to escape it.
831
832  * <informalexample><programlisting>
833  * gchar *msg;
834  *  
835  * msg = g_markup_printf_escaped (message_format, ...);
836  * gtk_message_dialog_format_secondary_markup (message_dialog, "&percnt;s", msg);
837  * g_free (msg);
838  * </programlisting></informalexample>
839  *
840  * Since: 2.6
841  **/
842 void
843 gtk_message_dialog_format_secondary_markup (GtkMessageDialog *message_dialog,
844                                             const gchar      *message_format,
845                                             ...)
846 {
847   va_list args;
848   gchar *msg = NULL;
849   GtkMessageDialogPrivate *priv;
850
851   g_return_if_fail (GTK_IS_MESSAGE_DIALOG (message_dialog));
852
853   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (message_dialog);
854
855   if (message_format)
856     {
857       priv->has_secondary_text = TRUE;
858
859       va_start (args, message_format);
860       msg = g_strdup_vprintf (message_format, args);
861       va_end (args);
862
863       gtk_widget_show (priv->secondary_label);
864       gtk_label_set_markup (GTK_LABEL (priv->secondary_label), msg);
865
866       g_free (msg);
867     }
868   else
869     {
870       priv->has_secondary_text = FALSE;
871       gtk_widget_hide (priv->secondary_label);
872     }
873
874   setup_primary_label_font (message_dialog);
875 }
876
877 /**
878  * gtk_message_dialog_get_message_area:
879  * @message_dialog: a #GtkMessageDialog
880  *
881  * Return value: A #GtkVBox corresponding to the "message area" in the
882  * @message_dialog.  This is the box where the dialog's primary and secondary
883  * labels are packed.  You can add your own extra content to that box and it
884  * will appear below those labels, on the right side of the dialog's image (or
885  * on the left for right-to-left languages).  See gtk_dialog_get_content_area()
886  * for the corresponding function in the parent #GtkDialog.
887  *
888  * Since: 2.22
889  **/
890 GtkWidget *
891 gtk_message_dialog_get_message_area (GtkMessageDialog *message_dialog)
892 {
893   GtkMessageDialogPrivate *priv;
894
895   g_return_val_if_fail (GTK_IS_MESSAGE_DIALOG (message_dialog), NULL);
896
897   priv = GTK_MESSAGE_DIALOG_GET_PRIVATE (message_dialog);
898
899   return priv->message_area;
900 }
901
902 static void
903 gtk_message_dialog_add_buttons (GtkMessageDialog* message_dialog,
904                                 GtkButtonsType buttons)
905 {
906   GtkDialog* dialog = GTK_DIALOG (message_dialog);
907
908   switch (buttons)
909     {
910     case GTK_BUTTONS_NONE:
911       /* nothing */
912       break;
913
914     case GTK_BUTTONS_OK:
915       gtk_dialog_add_button (dialog,
916                              GTK_STOCK_OK,
917                              GTK_RESPONSE_OK);
918       break;
919
920     case GTK_BUTTONS_CLOSE:
921       gtk_dialog_add_button (dialog,
922                              GTK_STOCK_CLOSE,
923                              GTK_RESPONSE_CLOSE);
924       break;
925
926     case GTK_BUTTONS_CANCEL:
927       gtk_dialog_add_button (dialog,
928                              GTK_STOCK_CANCEL,
929                              GTK_RESPONSE_CANCEL);
930       break;
931
932     case GTK_BUTTONS_YES_NO:
933       gtk_dialog_add_button (dialog,
934                              GTK_STOCK_NO,
935                              GTK_RESPONSE_NO);
936       gtk_dialog_add_button (dialog,
937                              GTK_STOCK_YES,
938                              GTK_RESPONSE_YES);
939       gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
940                                                GTK_RESPONSE_YES,
941                                                GTK_RESPONSE_NO,
942                                                -1);
943       break;
944
945     case GTK_BUTTONS_OK_CANCEL:
946       gtk_dialog_add_button (dialog,
947                              GTK_STOCK_CANCEL,
948                              GTK_RESPONSE_CANCEL);
949       gtk_dialog_add_button (dialog,
950                              GTK_STOCK_OK,
951                              GTK_RESPONSE_OK);
952       gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
953                                                GTK_RESPONSE_OK,
954                                                GTK_RESPONSE_CANCEL,
955                                                -1);
956       break;
957       
958     default:
959       g_warning ("Unknown GtkButtonsType");
960       break;
961     } 
962
963   g_object_notify (G_OBJECT (message_dialog), "buttons");
964 }
965
966 static void
967 gtk_message_dialog_style_set (GtkWidget *widget,
968                               GtkStyle  *prev_style)
969 {
970   GtkMessageDialog *dialog = GTK_MESSAGE_DIALOG (widget);
971   gboolean use_separator;
972   GtkWidget *parent;
973   gint border_width;
974
975   parent = GTK_WIDGET (GTK_MESSAGE_DIALOG (widget)->image->parent);
976
977   if (parent)
978     {
979       gtk_widget_style_get (widget, "message-border",
980                             &border_width, NULL);
981       
982       gtk_container_set_border_width (GTK_CONTAINER (parent),
983                                       MAX (0, border_width - 7));
984     }
985
986   gtk_widget_style_get (widget,
987                         "use-separator", &use_separator,
988                         NULL);
989
990   _gtk_dialog_set_ignore_separator (GTK_DIALOG (widget), FALSE);
991   gtk_dialog_set_has_separator (GTK_DIALOG (widget), use_separator);
992   _gtk_dialog_set_ignore_separator (GTK_DIALOG (widget), TRUE);
993
994   setup_primary_label_font (dialog);
995
996   GTK_WIDGET_CLASS (gtk_message_dialog_parent_class)->style_set (widget, prev_style);
997 }
998
999 #define __GTK_MESSAGE_DIALOG_C__
1000 #include "gtkaliasdef.c"