summaryrefslogtreecommitdiff
path: root/eel/eel-alert-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'eel/eel-alert-dialog.c')
-rw-r--r--eel/eel-alert-dialog.c490
1 files changed, 490 insertions, 0 deletions
diff --git a/eel/eel-alert-dialog.c b/eel/eel-alert-dialog.c
new file mode 100644
index 00000000..976c1227
--- /dev/null
+++ b/eel/eel-alert-dialog.c
@@ -0,0 +1,490 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* eel-alert-dialog.c: An HIG compliant alert dialog.
+
+ The Mate Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Mate Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Mate Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+#include <config.h>
+
+#include "eel-alert-dialog.h"
+#include "eel-i18n.h"
+#include "eel-gtk-macros.h"
+#include <gtk/gtk.h>
+#include <string.h>
+
+enum
+{
+ PROP_0,
+ PROP_ALERT_TYPE,
+ PROP_BUTTONS
+};
+
+struct _EelAlertDialogDetails
+{
+ GtkWidget *image;
+ GtkWidget *primary_label;
+ GtkWidget *secondary_label;
+ GtkWidget *details_expander;
+ GtkWidget *details_label;
+ GtkMessageType type;
+};
+
+
+static gpointer parent_class;
+
+static void eel_alert_dialog_finalize (GObject *object);
+static void eel_alert_dialog_class_init (EelAlertDialogClass *klass);
+static void eel_alert_dialog_init (EelAlertDialog *dialog);
+static void eel_alert_dialog_style_set (GtkWidget *widget,
+ GtkStyle *prev_style);
+static void eel_alert_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void eel_alert_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void eel_alert_dialog_add_buttons (EelAlertDialog *alert_dialog,
+ GtkButtonsType buttons);
+
+GType
+eel_alert_dialog_get_type (void)
+{
+ static GType dialog_type = 0;
+
+ if (!dialog_type)
+ {
+
+ const GTypeInfo dialog_info =
+ {
+ sizeof (EelAlertDialogClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) eel_alert_dialog_class_init,
+ NULL,
+ NULL,
+ sizeof (EelAlertDialog),
+ 0,
+ (GInstanceInitFunc) eel_alert_dialog_init,
+ };
+
+ dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "EelAlertDialog",
+ &dialog_info, 0);
+ }
+ return dialog_type;
+}
+
+static void
+eel_alert_dialog_class_init (EelAlertDialogClass *class)
+{
+ GtkWidgetClass *widget_class;
+ GObjectClass *gobject_class;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ gobject_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ G_OBJECT_CLASS (class)->finalize = eel_alert_dialog_finalize;
+
+ widget_class->style_set = eel_alert_dialog_style_set;
+
+ gobject_class->set_property = eel_alert_dialog_set_property;
+ gobject_class->get_property = eel_alert_dialog_get_property;
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_int ("alert_border",
+ _("Image/label border"),
+ _("Width of border around the label and image in the alert dialog"),
+ 0,
+ G_MAXINT,
+ 5,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_ALERT_TYPE,
+ g_param_spec_enum ("alert_type",
+ _("Alert Type"),
+ _("The type of alert"),
+ GTK_TYPE_MESSAGE_TYPE,
+ GTK_MESSAGE_INFO,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (gobject_class,
+ PROP_BUTTONS,
+ g_param_spec_enum ("buttons",
+ _("Alert Buttons"),
+ _("The buttons shown in the alert dialog"),
+ GTK_TYPE_BUTTONS_TYPE,
+ GTK_BUTTONS_NONE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+eel_alert_dialog_finalize (GObject *object)
+{
+ EelAlertDialog *dialog;
+
+ dialog = EEL_ALERT_DIALOG (object);
+
+ g_free (dialog->details);
+
+ EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
+}
+
+
+static void
+eel_alert_dialog_init (EelAlertDialog *dialog)
+{
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *expander;
+
+ dialog->details = g_new0 (EelAlertDialogDetails, 1);
+
+ dialog->details->primary_label = gtk_label_new (NULL);
+ dialog->details->secondary_label = gtk_label_new (NULL);
+ dialog->details->details_label = gtk_label_new (NULL);
+ dialog->details->image = gtk_image_new_from_stock (NULL, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (dialog->details->image), 0.5, 0.0);
+
+ gtk_label_set_line_wrap (GTK_LABEL (dialog->details->primary_label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (dialog->details->primary_label), TRUE);
+ gtk_label_set_use_markup (GTK_LABEL (dialog->details->primary_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (dialog->details->primary_label), 0.0, 0.5);
+
+ gtk_label_set_line_wrap (GTK_LABEL (dialog->details->secondary_label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (dialog->details->secondary_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (dialog->details->secondary_label), 0.0, 0.5);
+
+ gtk_label_set_line_wrap (GTK_LABEL (dialog->details->details_label), TRUE);
+ gtk_label_set_selectable (GTK_LABEL (dialog->details->details_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (dialog->details->details_label), 0.0, 0.5);
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+
+ gtk_box_pack_start (GTK_BOX (hbox), dialog->details->image,
+ FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+
+ gtk_box_pack_start (GTK_BOX (hbox), vbox,
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), dialog->details->primary_label,
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), dialog->details->secondary_label,
+ FALSE, FALSE, 0);
+
+ expander = gtk_expander_new_with_mnemonic (_("Show more _details"));
+ dialog->details->details_expander = expander;
+ gtk_expander_set_spacing (GTK_EXPANDER (expander), 6);
+ gtk_container_add (GTK_CONTAINER (expander), dialog->details->details_label);
+
+ gtk_box_pack_start (GTK_BOX (vbox), expander,
+ FALSE, FALSE, 0);
+
+
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox,
+ FALSE, FALSE, 0);
+
+ gtk_widget_show_all (hbox);
+ gtk_widget_hide (expander);
+
+}
+
+static void
+setup_type (EelAlertDialog *dialog,
+ GtkMessageType type)
+{
+ const gchar *stock_id = NULL;
+ GtkStockItem item;
+
+ switch (type)
+ {
+ case GTK_MESSAGE_INFO:
+ stock_id = GTK_STOCK_DIALOG_INFO;
+ break;
+ case GTK_MESSAGE_QUESTION:
+ stock_id = GTK_STOCK_DIALOG_QUESTION;
+ break;
+ case GTK_MESSAGE_WARNING:
+ stock_id = GTK_STOCK_DIALOG_WARNING;
+ break;
+ case GTK_MESSAGE_ERROR:
+ stock_id = GTK_STOCK_DIALOG_ERROR;
+ break;
+ default:
+ g_warning ("Unknown GtkMessageType %d", type);
+ break;
+ }
+
+ if (stock_id == NULL)
+ {
+ stock_id = GTK_STOCK_DIALOG_INFO;
+ }
+
+ if (gtk_stock_lookup (stock_id, &item))
+ {
+ gtk_image_set_from_stock (GTK_IMAGE (dialog->details->image), stock_id,
+ GTK_ICON_SIZE_DIALOG);
+ }
+ else
+ {
+ g_warning ("Stock dialog ID doesn't exist?");
+ }
+}
+
+static void
+eel_alert_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EelAlertDialog *dialog;
+
+ dialog = EEL_ALERT_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_ALERT_TYPE:
+ dialog->details->type = g_value_get_enum (value);
+ setup_type (dialog, dialog->details->type);
+ break;
+ case PROP_BUTTONS:
+ eel_alert_dialog_add_buttons (dialog, g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+eel_alert_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EelAlertDialog *dialog;
+
+ dialog = EEL_ALERT_DIALOG (object);
+
+ switch (prop_id)
+ {
+ case PROP_ALERT_TYPE:
+ g_value_set_enum (value, dialog->details->type);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+void
+eel_alert_dialog_set_primary_label (EelAlertDialog *dialog,
+ const gchar *message)
+{
+ gchar *markup_str;
+ char *escaped_message;
+
+ if (message != NULL)
+ {
+ escaped_message = g_markup_escape_text (message, -1);
+ markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", escaped_message, "</span>", NULL);
+ gtk_label_set_markup (GTK_LABEL (EEL_ALERT_DIALOG (dialog)->details->primary_label),
+ markup_str);
+ g_free (markup_str);
+ g_free (escaped_message);
+ }
+}
+
+void
+eel_alert_dialog_set_secondary_label (EelAlertDialog *dialog,
+ const gchar *message)
+{
+ if (message != NULL)
+ {
+ gtk_label_set_text (GTK_LABEL (EEL_ALERT_DIALOG (dialog)->details->secondary_label),
+ message);
+ }
+ else
+ {
+ gtk_widget_hide (EEL_ALERT_DIALOG (dialog)->details->secondary_label);
+ }
+}
+
+void
+eel_alert_dialog_set_details_label (EelAlertDialog *dialog,
+ const gchar *message)
+{
+ if (message != NULL)
+ {
+ gtk_widget_show (dialog->details->details_expander);
+ gtk_label_set_text (GTK_LABEL (dialog->details->details_label), message);
+ }
+ else
+ {
+ gtk_widget_hide (dialog->details->details_expander);
+ }
+}
+
+
+GtkWidget*
+eel_alert_dialog_new (GtkWindow *parent,
+ GtkDialogFlags flags,
+ GtkMessageType type,
+ GtkButtonsType buttons,
+ const gchar *primary_message,
+ const gchar *secondary_message)
+{
+ GtkWidget *widget;
+ GtkDialog *dialog;
+
+ g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
+
+ widget = g_object_new (EEL_TYPE_ALERT_DIALOG,
+ "alert_type", type,
+ "buttons", buttons,
+ NULL);
+ atk_object_set_role (gtk_widget_get_accessible (widget), ATK_ROLE_ALERT);
+
+ dialog = GTK_DIALOG (widget);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+ gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+ gtk_dialog_set_has_separator (dialog, FALSE);
+
+ /* Make sure we don't get a window title.
+ * HIG says that alert dialogs should not have window title
+ */
+ gtk_window_set_title (GTK_WINDOW (dialog), "");
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
+
+ eel_alert_dialog_set_primary_label (EEL_ALERT_DIALOG (dialog),
+ primary_message);
+
+ eel_alert_dialog_set_secondary_label (EEL_ALERT_DIALOG (dialog),
+ secondary_message);
+
+ if (parent != NULL)
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (widget),
+ GTK_WINDOW (parent));
+ }
+
+ if (flags & GTK_DIALOG_MODAL)
+ {
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ }
+
+ if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
+ {
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+ }
+ return widget;
+}
+
+static void
+eel_alert_dialog_add_buttons (EelAlertDialog* alert_dialog,
+ GtkButtonsType buttons)
+{
+ GtkDialog* dialog;
+
+ dialog = GTK_DIALOG (alert_dialog);
+
+ switch (buttons)
+ {
+ case GTK_BUTTONS_NONE:
+ break;
+ case GTK_BUTTONS_OK:
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (dialog,
+ GTK_RESPONSE_OK);
+ break;
+ case GTK_BUTTONS_CLOSE:
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE);
+ gtk_dialog_set_default_response (dialog,
+ GTK_RESPONSE_CLOSE);
+ break;
+ case GTK_BUTTONS_CANCEL:
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ gtk_dialog_set_default_response (dialog,
+ GTK_RESPONSE_CANCEL);
+ break;
+ case GTK_BUTTONS_YES_NO:
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_NO,
+ GTK_RESPONSE_NO);
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_YES,
+ GTK_RESPONSE_YES);
+ gtk_dialog_set_default_response (dialog,
+ GTK_RESPONSE_YES);
+ break;
+ case GTK_BUTTONS_OK_CANCEL:
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (dialog,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK);
+ gtk_dialog_set_default_response (dialog,
+ GTK_RESPONSE_OK);
+ break;
+ default:
+ g_warning ("Unknown GtkButtonsType");
+ break;
+ }
+ g_object_notify (G_OBJECT (alert_dialog), "buttons");
+}
+
+static void
+eel_alert_dialog_style_set (GtkWidget *widget,
+ GtkStyle *prev_style)
+{
+ GtkWidget *parent;
+ gint border_width;
+
+ border_width = 0;
+
+ parent = GTK_WIDGET (gtk_widget_get_parent (EEL_ALERT_DIALOG (widget)->details->image));
+
+ if (parent != NULL)
+ {
+ gtk_widget_style_get (widget, "alert_border",
+ &border_width, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (parent),
+ border_width);
+ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->style_set)
+ {
+ (GTK_WIDGET_CLASS (parent_class)->style_set) (widget, prev_style);
+ }
+}