/* moko-message-dialog.c * * Authored (in part) by Rob Bradford * * Copyright (C) 2007 OpenMoko Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser Public License as published by * the Free Software Foundation; version 2 of the license. * * This program 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 Lesser Public License for more details. * * Also contains code directly derived from GTK+ (gtk/gtkdialog.c) with the * following Copyright notice: * * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. * * Derivation Copyright (C) 2007 OpenMoko Inc. * Derivation Authored by Rob Bradford #include G_DEFINE_TYPE (MokoMessageDialog, moko_message_dialog, GTK_TYPE_DIALOG) #define MESSAGE_DIALOG_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), MOKO_TYPE_MESSAGE_DIALOG, MokoMessageDialogPrivate)) typedef struct _MokoMessageDialogPrivate MokoMessageDialogPrivate; struct _MokoMessageDialogPrivate { gchar *message; GtkWidget *label; GtkWidget *image; GtkWidget *image_alignment; gboolean window_shaped; GdkPixbuf *background_pixbuf; GdkPixbuf *root_pixbuf; GdkPixbuf *pixbuf; }; static void moko_message_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void moko_message_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void moko_message_dialog_dispose (GObject *object) { if (G_OBJECT_CLASS (moko_message_dialog_parent_class)->dispose) G_OBJECT_CLASS (moko_message_dialog_parent_class)->dispose (object); } static void moko_message_dialog_finalize (GObject *object) { G_OBJECT_CLASS (moko_message_dialog_parent_class)->finalize (object); } /* * We need to override the map event handling to grab the root window before * our widget gets drawn onto it. */ static void moko_message_dialog_map (GtkWidget *object) { MokoMessageDialogPrivate *priv = MESSAGE_DIALOG_PRIVATE (object); MokoMessageDialog *dialog = MOKO_MESSAGE_DIALOG (object); gint w, h; GdkWindow *root_window; GdkPixbuf *root_pixbuf; GdkPixbuf *old_pixbuf; /* Grab the root window and its dimensions */ root_window = gtk_widget_get_root_window (GTK_WIDGET(dialog)); gdk_drawable_get_size (root_window, &w, &h); /* Generate a pixbuf from this root window */ root_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w, h); gdk_pixbuf_get_from_drawable (root_pixbuf, root_window, NULL, 0, 0, 0, 0, w, h); old_pixbuf = priv->root_pixbuf; priv->root_pixbuf = root_pixbuf; if (old_pixbuf) g_object_unref (old_pixbuf); if (priv->pixbuf) { g_object_unref (priv->pixbuf); priv->pixbuf = NULL; } if (GTK_WIDGET_CLASS (moko_message_dialog_parent_class)->map) GTK_WIDGET_CLASS (moko_message_dialog_parent_class)->map (object); } static void moko_message_dialog_class_init (MokoMessageDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); g_type_class_add_private (klass, sizeof (MokoMessageDialogPrivate)); object_class->get_property = moko_message_dialog_get_property; object_class->set_property = moko_message_dialog_set_property; object_class->dispose = moko_message_dialog_dispose; object_class->finalize = moko_message_dialog_finalize; widget_class->map = moko_message_dialog_map; } /* static void moko_message_dialog_shape_window (GtkWidget *widget) { GtkRcStyle *rc_style; GdkPixbuf *pixbuf; GError *error = NULL; GdkBitmap *mask; MokoMessageDialogPrivate* priv = MESSAGE_DIALOG_PRIVATE (widget); rc_style = widget->style->rc_style; pixbuf = gdk_pixbuf_new_from_file (rc_style->bg_pixmap_name[GTK_STATE_NORMAL], &error); if (pixbuf == NULL) { g_warning ("Error loading background pixbuf: %s", error->message); g_clear_error (&error); return; } mask = gdk_pixmap_new (NULL, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), 1); gdk_pixbuf_render_threshold_alpha (pixbuf, mask, 0, 0, 0, 0, -1, -1, 100); g_object_unref (pixbuf); gdk_window_shape_combine_mask (widget->window, mask, 0, 0); g_object_unref (mask); priv->window_shaped = TRUE; } */ /* * Need to grab the pixbuf for background in the realize callback since we * need to have the style setup */ static void moko_message_dialog_realize_cb (GtkWidget *widget, gpointer user_data) { MokoMessageDialogPrivate* priv = MESSAGE_DIALOG_PRIVATE (widget); GtkRcStyle *rc_style; GError *error = NULL; if (!priv->background_pixbuf) { rc_style = widget->style->rc_style; g_return_if_fail(rc_style != NULL); priv->background_pixbuf = gdk_pixbuf_new_from_file (rc_style->bg_pixmap_name[GTK_STATE_NORMAL], &error); if (priv->background_pixbuf == NULL) { if (error) { g_warning ("Error loading background pixbuf: %s", error->message); g_clear_error (&error); } else { g_warning ("Error loading background pixbuf"); } return; } } } static gboolean moko_message_dialog_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { MokoMessageDialogPrivate *priv = MESSAGE_DIALOG_PRIVATE (widget); int x, y, w, h; gdk_drawable_get_size (widget->window, &w, &h); if (!priv->pixbuf) { gdk_window_get_origin (widget->window, &x, &y); /* * Extract a sub pixbuf for the area of the root window which the window * now covers */ priv->pixbuf = gdk_pixbuf_new_subpixbuf (priv->root_pixbuf, x, y, w, h); /* Composite the background pixbuf over said subpixbuf */ gdk_pixbuf_composite (priv->background_pixbuf, priv->pixbuf, 0, 0, w, h, 0, 0, 1, 1, GDK_INTERP_BILINEAR, 255); } /* Draw our pixbuf onto the window */ gdk_draw_pixbuf (widget->window, NULL, priv->pixbuf, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0); return FALSE; } static void moko_message_dialog_init (MokoMessageDialog *self) { MokoMessageDialogPrivate* priv = MESSAGE_DIALOG_PRIVATE(self); GtkWidget *vbox; GtkWidget *label; GtkWidget *alignment; GtkWidget *image_alignment; priv->message = NULL; vbox = gtk_vbox_new (FALSE, 6); alignment = gtk_alignment_new (0.5, 0.5, 1, 1); image_alignment = gtk_alignment_new (0.5, 0.5, 1, 1); gtk_container_add (GTK_CONTAINER (alignment), vbox); gtk_box_pack_start (GTK_BOX(GTK_DIALOG (self)->vbox), alignment, TRUE, TRUE, 6); gtk_button_box_set_layout (GTK_BUTTON_BOX(GTK_DIALOG (self)->action_area), GTK_BUTTONBOX_SPREAD); label = gtk_label_new (NULL); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_misc_set_padding (GTK_MISC (label), 12, 12); gtk_box_pack_end (GTK_BOX (vbox), label, TRUE, TRUE, 6); gtk_widget_show_all (GTK_WIDGET (GTK_DIALOG (self)->vbox)); gtk_window_set_modal (GTK_WINDOW (self), TRUE); gtk_box_pack_start (GTK_BOX (vbox), image_alignment, TRUE, TRUE, 0); gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE); gtk_widget_set_size_request (GTK_WIDGET (self), 480, 560); gtk_window_set_decorated (GTK_WINDOW (self), FALSE); gtk_window_set_resizable (GTK_WINDOW (self), FALSE); gtk_container_set_border_width (GTK_CONTAINER (self), 85); /* Indicate that we want to paint this ourselves */ gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE); g_signal_connect (self, "realize", G_CALLBACK (moko_message_dialog_realize_cb), NULL); g_signal_connect (self, "expose-event", G_CALLBACK (moko_message_dialog_expose_event_cb), NULL); priv->image_alignment = image_alignment; priv->label = label; priv->root_pixbuf = NULL; priv->background_pixbuf = NULL; priv->pixbuf = NULL; } void moko_message_dialog_set_message (MokoMessageDialog *dialog, const gchar *message_format, ...) { MokoMessageDialogPrivate* priv = MESSAGE_DIALOG_PRIVATE(dialog); va_list args; g_free (priv->message); va_start (args, message_format); priv->message = g_strdup_vprintf (message_format, args); va_end (args); gtk_label_set_text (GTK_LABEL (priv->label), priv->message); } void moko_message_dialog_set_image_from_stock (MokoMessageDialog *dialog, const gchar *stock_id) { MokoMessageDialogPrivate* priv = MESSAGE_DIALOG_PRIVATE(dialog); GtkWidget *old_image = priv->image; priv->image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_DIALOG); if (old_image != NULL) gtk_container_remove (GTK_CONTAINER (priv->image_alignment), old_image); gtk_container_add (GTK_CONTAINER (priv->image_alignment), priv->image); gtk_widget_show_all (GTK_WIDGET (priv->image_alignment)); if (old_image !=NULL) g_object_unref (old_image); } void moko_message_dialog_set_image (MokoMessageDialog *dialog, GtkWidget *image) { MokoMessageDialogPrivate* priv = MESSAGE_DIALOG_PRIVATE(dialog); GtkWidget *old_image = priv->image; priv->image = image; if (old_image != NULL) gtk_container_remove (GTK_CONTAINER (priv->image_alignment), old_image); gtk_container_add (GTK_CONTAINER (priv->image_alignment), priv->image); gtk_widget_show_all (GTK_WIDGET (priv->image_alignment)); if (old_image !=NULL) g_object_unref (old_image); } GtkWidget* moko_message_dialog_new (void) { return g_object_new (MOKO_TYPE_MESSAGE_DIALOG, NULL); }