[glade/css: 10/11] Made glade-previewer monitor css file and display parsing errors in a GtkInfoBar. Created new GladeP



commit 8873424c018e428baa30012a2fde16678c161cc3
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Wed Jul 24 17:10:42 2013 -0300

    Made glade-previewer monitor css file and display parsing errors in a GtkInfoBar.
    Created new GladePreviewWindow widget and lots of cleanups.
    Improved screenshot option, save screenshots in any GdkPixbuf supported format.
    Added options to take vector screenshots (F5 svg, F6 ps, F7 pdf) and F8 png

 gladeui/Makefile.am            |    4 +-
 gladeui/glade-preview-window.c |  476 +++++++++++++++++++++++++++++++++++++++
 gladeui/glade-preview-window.h |   78 +++++++
 gladeui/glade-preview.c        |   96 +++++----
 gladeui/glade-previewer.c      |  488 ++++++++++++++++------------------------
 5 files changed, 809 insertions(+), 333 deletions(-)
---
diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am
index 88b143b..9295881 100644
--- a/gladeui/Makefile.am
+++ b/gladeui/Makefile.am
@@ -22,7 +22,9 @@ glade_previewer_LDFLAGS = $(AM_LDFLAGS)
 glade_previewer_LDADD = libgladeui-2.la $(GTK_MAC_LIBS)
 
 glade_previewer_SOURCES = \
-       glade-previewer.c
+       glade-previewer.c \
+       glade-preview-window.c \
+       glade-preview-window.h
 
 if NATIVE_WIN32
 glade_previewer_LDADD += glade-win32-res.o
diff --git a/gladeui/glade-preview-window.c b/gladeui/glade-preview-window.c
new file mode 100644
index 0000000..116ec85
--- /dev/null
+++ b/gladeui/glade-preview-window.c
@@ -0,0 +1,476 @@
+/*
+ * glade-preview-window.c
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+   *
+ * Author: Juan Pablo Ugarte <juanpablougarte gmail com>
+ *
+ * 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.1 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 program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#include <config.h>
+
+#include "glade-preview-window.h"
+#include <glib/gi18n-lib.h>
+#include <cairo-pdf.h>
+#include <cairo-svg.h>
+#include <cairo-ps.h>
+
+struct _GladePreviewWindowPrivate
+{
+  GtkWidget *box;
+  GtkWidget *info;
+  GtkWidget *message_label;
+  GtkWidget *widget;
+
+  GtkCssProvider *css_provider;
+  GFileMonitor *css_monitor;
+  gchar *css_file;
+  gchar *extension;
+};
+
+#define GLADE_PREVIEW_WINDOW_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GLADE_TYPE_PREVIEW_WINDOW, 
GladePreviewWindowPrivate))
+
+G_DEFINE_TYPE (GladePreviewWindow, glade_preview_window, GTK_TYPE_WINDOW);
+
+static void
+glade_preview_window_init (GladePreviewWindow *window)
+{
+  GladePreviewWindowPrivate *priv = GLADE_PREVIEW_WINDOW_GET_PRIVATE (window);
+  GtkWidget *content_area;
+
+  window->priv = priv;
+
+  gtk_window_set_title (GTK_WINDOW (window), _("Preview"));
+  gtk_widget_add_events (GTK_WIDGET (window), GDK_KEY_PRESS_MASK);
+  
+  priv->box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  priv->info = gtk_info_bar_new ();
+  priv->message_label = gtk_label_new ("");
+  gtk_label_set_line_wrap (GTK_LABEL (priv->message_label), TRUE);
+
+  gtk_widget_set_valign (priv->info, GTK_ALIGN_END);
+  gtk_widget_set_vexpand (priv->info, FALSE);
+  content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (priv->info));
+  gtk_container_add (GTK_CONTAINER (content_area), priv->message_label);
+  
+  g_signal_connect (priv->info, "response", G_CALLBACK (gtk_widget_hide), NULL);
+  
+  gtk_box_pack_start (GTK_BOX (priv->box), priv->info, FALSE, FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (window), priv->box);
+  
+  gtk_widget_show (priv->message_label);
+  gtk_widget_show (priv->box);
+}
+
+static void
+glade_preview_window_finalize (GObject *object)
+{
+  GladePreviewWindowPrivate *priv = GLADE_PREVIEW_WINDOW_GET_PRIVATE (object);
+
+  g_free (priv->css_file);
+  g_clear_object (&priv->css_provider);
+  g_clear_object (&priv->css_monitor);
+
+  G_OBJECT_CLASS (glade_preview_window_parent_class)->finalize (object);
+}
+
+static gboolean 
+glade_preview_window_key_press_event (GtkWidget *widget, GdkEventKey *event)
+{
+  GladePreviewWindow *window = GLADE_PREVIEW_WINDOW (widget);
+  GladePreviewWindowPrivate *priv = window->priv;
+  gchar *extension;
+
+  switch (event->keyval)
+    {
+      case GDK_KEY_F5:
+        extension = "svg";
+      break;
+      case GDK_KEY_F6:
+        extension = "ps";
+      break;
+      case GDK_KEY_F7:
+        extension = "pdf";
+      break;
+      case GDK_KEY_F8:
+        extension = priv->extension ? priv->extension : "png";
+      break;
+      default:
+        return FALSE;
+      break;
+    }
+
+  if (extension)
+    {
+      gchar *tmp_file = g_strdup_printf ("glade-screenshot-XXXXXX.%s", extension); 
+
+      g_mkstemp (tmp_file);
+      glade_preview_window_screenshot (window, FALSE, tmp_file);
+      g_free (tmp_file);
+
+      return TRUE;
+    }
+  
+  return FALSE;
+}
+
+static void
+glade_preview_window_realize (GtkWidget *widget)
+{
+  GladePreviewWindowPrivate *priv = GLADE_PREVIEW_WINDOW (widget)->priv;
+
+  GTK_WIDGET_CLASS (glade_preview_window_parent_class)->realize (widget);
+  
+  if (priv->widget && gtk_widget_is_toplevel (priv->widget) &&
+      gtk_widget_get_parent (priv->widget) == NULL)
+    {
+      gtk_widget_set_parent_window (priv->widget, gtk_widget_get_window (widget));
+      gtk_box_pack_start (GTK_BOX (priv->box), priv->widget, TRUE, TRUE, 0);
+      gtk_widget_show (priv->widget);
+    }
+}
+
+static void
+glade_preview_window_class_init (GladePreviewWindowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (GladePreviewWindowPrivate));
+
+  object_class->finalize = glade_preview_window_finalize;
+
+  widget_class->realize = glade_preview_window_realize;
+  widget_class->key_press_event = glade_preview_window_key_press_event;
+}
+
+GtkWidget *
+glade_preview_window_new (void)
+{
+  return GTK_WIDGET (g_object_new (GLADE_TYPE_PREVIEW_WINDOW, NULL));
+}
+
+static void 
+glade_preview_window_set_css_provider_forall (GtkWidget *widget, gpointer data)
+{
+  gtk_style_context_add_provider (gtk_widget_get_style_context (widget),
+                                  GTK_STYLE_PROVIDER (data),
+                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+  
+  if (GTK_IS_CONTAINER (widget))
+    gtk_container_forall (GTK_CONTAINER (widget), glade_preview_window_set_css_provider_forall, data);
+}
+
+void
+glade_preview_window_set_widget (GladePreviewWindow *window, GtkWidget *widget)
+{
+  GladePreviewWindowPrivate *priv;
+  GdkWindow *gdkwindow;
+
+  g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  priv = window->priv;
+  
+  if (priv->widget)
+    gtk_container_remove (GTK_CONTAINER (priv->box), priv->widget);
+
+  priv->widget = widget;
+
+  if (priv->css_provider)
+    glade_preview_window_set_css_provider_forall (widget, priv->css_provider);
+    
+  if (gtk_widget_is_toplevel (widget))
+    {
+      /* Delay setting it until we have a window  */
+      if (!(gdkwindow = gtk_widget_get_window (priv->box)))
+        return;
+
+      gtk_widget_set_parent_window (widget, gdkwindow);
+    }
+
+  gtk_box_pack_start (GTK_BOX (priv->box), widget, TRUE, TRUE, 0);
+}
+
+void
+glade_preview_window_set_message (GladePreviewWindow *window, 
+                                  GtkMessageType      type,
+                                  const gchar        *message)
+{
+  GladePreviewWindowPrivate *priv;
+
+  g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
+  priv = window->priv;
+
+  gtk_info_bar_set_message_type (GTK_INFO_BAR (priv->info), type);
+  
+  if (message)
+    {
+      gtk_label_set_text (GTK_LABEL (priv->message_label), message);
+      gtk_widget_show (priv->info);
+    }
+  else
+    {
+      gtk_label_set_text (GTK_LABEL (priv->message_label), "");
+      gtk_widget_hide (priv->info);
+    }
+}
+
+static void 
+on_css_monitor_changed (GFileMonitor       *monitor,
+                        GFile              *file,
+                        GFile              *other_file,
+                        GFileMonitorEvent   event_type,
+                        GladePreviewWindow *window)
+{
+  GladePreviewWindowPrivate *priv = window->priv;
+  GError *error = NULL;
+
+  gtk_css_provider_load_from_file (priv->css_provider, file, &error);
+
+  if (error)
+    {
+      glade_preview_window_set_message (window, GTK_MESSAGE_WARNING, error->message);
+      g_error_free (error);
+    }
+  else
+    glade_preview_window_set_message (window, GTK_MESSAGE_OTHER, NULL);
+}
+
+void
+glade_preview_window_set_css_file (GladePreviewWindow *window,
+                                   const gchar        *css_file)
+{
+  GladePreviewWindowPrivate *priv;
+  GError *error = NULL;
+  GFile *file;
+
+  g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
+  priv = window->priv;
+
+  g_free (priv->css_file);
+  g_clear_object (&priv->css_provider);
+  g_clear_object (&priv->css_monitor);
+
+  priv->css_file = g_strdup (css_file);
+  
+  file = g_file_new_for_path (css_file);
+  priv->css_provider = gtk_css_provider_new ();
+  g_object_ref_sink (priv->css_provider);
+  
+  priv->css_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
+  if (error)
+    {
+      g_warning ("Cant monitor CSS file %s: %s", css_file, error->message);
+      g_error_free (error);
+    }
+  else
+    {
+      g_object_ref_sink (priv->css_monitor);
+      g_signal_connect (priv->css_monitor, "changed",
+                        G_CALLBACK (on_css_monitor_changed), window);
+    }
+
+  /* load CSS */
+  gtk_css_provider_load_from_file (priv->css_provider, file, &error);
+  if (error)
+    {
+      glade_preview_window_set_message (window, GTK_MESSAGE_INFO, error->message);
+      g_message ("%s CSS parsing failed: %s", css_file, error->message);
+      g_error_free (error);
+    }
+
+  if (priv->widget)
+    glade_preview_window_set_css_provider_forall (priv->widget, priv->css_provider);
+  
+  g_object_unref (file);
+}
+
+void
+glade_preview_window_set_screenshot_extension (GladePreviewWindow *window,
+                                               const gchar        *extension)
+{
+  GladePreviewWindowPrivate *priv;
+
+  g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
+  priv = window->priv;
+
+  g_free (priv->extension);
+  priv->extension = g_strdup (extension);
+}
+
+static gboolean
+quit_when_idle (gpointer loop)
+{
+  g_main_loop_quit (loop);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+check_for_draw (GdkEvent *event, gpointer loop)
+{
+  if (event->type == GDK_EXPOSE)
+    {
+      g_idle_add (quit_when_idle, loop);
+      gdk_event_handler_set ((GdkEventFunc) gtk_main_do_event, NULL, NULL);
+    }
+
+  gtk_main_do_event (event);
+}
+
+/* Taken from Gtk sources gtk-reftest.c  */
+static void
+wait_for_drawing (GdkWindow *window)
+{
+  GMainLoop *loop;
+
+  loop = g_main_loop_new (NULL, FALSE);
+  /* We wait until the widget is drawn for the first time.
+   * We can not wait for a GtkWidget::draw event, because that might not
+   * happen if the window is fully obscured by windowed child widgets.
+   * Alternatively, we could wait for an expose event on widget's window.
+   * Both of these are rather hairy, not sure what's best. */
+  gdk_event_handler_set (check_for_draw, loop, NULL);
+  g_main_loop_run (loop);
+
+  /* give the WM/server some time to sync. They need it.
+   * Also, do use popups instead of toplevls in your tests
+   * whenever you can. */
+  gdk_display_sync (gdk_window_get_display (window));
+  g_timeout_add (500, quit_when_idle, loop);
+  g_main_loop_run (loop);
+}
+
+static inline gdouble
+get_x_scale (GdkScreen *screen)
+{
+  return 72.0 / (gdk_screen_get_width (screen) / (gdk_screen_get_width_mm (screen) * 0.03937008));
+}
+
+static inline gdouble
+get_y_scale (GdkScreen *screen)
+{
+  return 72.0 / (gdk_screen_get_height (screen) / (gdk_screen_get_height_mm (screen) * 0.03937008));
+}
+
+typedef enum 
+{
+  EXT_TYPE_SVG,
+  EXT_TYPE_PS,
+  EXT_TYPE_PDF,
+  EXT_TYPE_OTHER
+} ExtTypeEnum;
+
+/**
+ * glade_preview_window_screenshot:
+ * @window: A GladePreviewWindow
+ * @wait: True if it should wait for widget to draw.
+ * @filename:  a filename to save the image.
+ * 
+ * Takes a screenshot of the current widget @window is showing and save it to @filename
+ * Supported extension are svg, ps, pdf and wahtever gdk-pixbuf supports 
+ */
+void
+glade_preview_window_screenshot (GladePreviewWindow *window,
+                                 gboolean wait,
+                                 const gchar *filename)
+{
+  GladePreviewWindowPrivate *priv;
+  GdkWindow *gdkwindow;
+  GdkScreen *screen;
+  gchar *extension;
+  ExtTypeEnum ext_type;
+  gint w, h;
+
+  g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window));
+  g_return_if_fail (filename != NULL);
+  priv = window->priv;
+
+  if (!priv->widget)
+    return;
+
+  extension = g_strrstr (filename,".");
+
+  if (extension)
+    extension++;
+
+  if (!extension)
+    {
+      g_warning ("%s has no extension!", filename);
+      return;
+    }
+
+  gdkwindow = gtk_widget_get_window (priv->widget);
+  screen = gdk_window_get_screen (gdkwindow);
+
+  if (wait)
+    wait_for_drawing (gdkwindow);
+
+  w = gtk_widget_get_allocated_width (priv->widget);
+  h = gtk_widget_get_allocated_height (priv->widget);
+
+  if (g_strcmp0 (extension, "svg") == 0)
+    ext_type = EXT_TYPE_SVG;
+  else if (g_strcmp0 (extension, "ps") == 0)
+    ext_type = EXT_TYPE_PS;
+  else if (g_strcmp0 (extension, "pdf") == 0)
+    ext_type = EXT_TYPE_PDF;
+  else
+    ext_type = EXT_TYPE_OTHER;
+
+  if (ext_type == EXT_TYPE_OTHER)
+    {
+      GdkPixbuf *pix = gdk_pixbuf_get_from_window (gdkwindow, 0, 0, w, h);
+
+      gdk_pixbuf_save (pix, filename, extension, NULL, NULL);
+
+      g_object_unref (pix);
+    }
+  else
+    {
+      cairo_surface_t *surface;
+      cairo_t *cr;
+      gdouble sx = get_x_scale (screen);
+      gdouble sy = get_y_scale (screen);
+
+      if (ext_type == EXT_TYPE_SVG)
+#if CAIRO_HAS_SVG_SURFACE
+        surface = cairo_svg_surface_create (filename, w*sx, h*sy);
+#else
+      g_warning ("PDF not supported by the cairo version used");
+#endif
+      else if (ext_type == EXT_TYPE_PS)
+#if CAIRO_HAS_PS_SURFACE
+        surface = cairo_ps_surface_create (filename, w*sx, h*sy);
+#else
+      g_warning ("PS not supported by the cairo version used");
+#endif
+      else if (ext_type == EXT_TYPE_PDF)
+#if CAIRO_HAS_PDF_SURFACE
+        surface = cairo_pdf_surface_create (filename, w*sx, h*sy);
+#else
+      g_warning ("PDF not supported by the cairo version used");
+#endif
+      
+      cr  = cairo_create (surface);
+      cairo_scale (cr, sx, sy);
+      gtk_widget_draw (priv->widget, cr);
+      cairo_destroy (cr);
+      cairo_surface_destroy(surface);
+
+    }
+}
diff --git a/gladeui/glade-preview-window.h b/gladeui/glade-preview-window.h
new file mode 100644
index 0000000..7ed54f8
--- /dev/null
+++ b/gladeui/glade-preview-window.h
@@ -0,0 +1,78 @@
+/*
+ * glade-preview-window.h
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+   *
+ * Author: Juan Pablo Ugarte <juanpablougarte gmail com>
+ *
+ * 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.1 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 program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _GLADE_PREVIEW_WINDOW_H_
+#define _GLADE_PREVIEW_WINDOW_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GLADE_TYPE_PREVIEW_WINDOW             (glade_preview_window_get_type ())
+#define GLADE_PREVIEW_WINDOW(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_PREVIEW_WINDOW, 
GladePreviewWindow))
+#define GLADE_PREVIEW_WINDOW_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_PREVIEW_WINDOW, 
GladePreviewWindowClass))
+#define GLADE_IS_PREVIEW_WINDOW(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_PREVIEW_WINDOW))
+#define GLADE_IS_PREVIEW_WINDOW_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_PREVIEW_WINDOW))
+#define GLADE_PREVIEW_WINDOW_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_TYPE_PREVIEW_WINDOW, 
GladePreviewWindowClass))
+
+typedef struct _GladePreviewWindowClass GladePreviewWindowClass;
+typedef struct _GladePreviewWindow GladePreviewWindow;
+typedef struct _GladePreviewWindowPrivate GladePreviewWindowPrivate;
+
+
+struct _GladePreviewWindowClass
+{
+  GtkWindowClass parent_class;
+};
+
+struct _GladePreviewWindow
+{
+  GtkWindow parent_instance;
+
+  GladePreviewWindowPrivate *priv; 
+};
+
+GType      glade_preview_window_get_type    (void) G_GNUC_CONST;
+
+GtkWidget *glade_preview_window_new         (void);
+
+void       glade_preview_window_set_widget  (GladePreviewWindow *window,
+                                             GtkWidget          *widget);
+
+void       glade_preview_window_set_message (GladePreviewWindow *window,
+                                             GtkMessageType      type,
+                                             const gchar        *message);
+
+void       glade_preview_window_set_css_file (GladePreviewWindow *window,
+                                              const gchar        *css_file);
+
+void       glade_preview_window_set_screenshot_extension (GladePreviewWindow *window,
+                                                          const gchar        *extension);
+
+void       glade_preview_window_screenshot  (GladePreviewWindow *window,
+                                             gboolean wait,
+                                             const gchar *filename);
+
+G_END_DECLS
+
+#endif /* _GLADE_PREVIEW_WINDOW_H_ */
diff --git a/gladeui/glade-preview.c b/gladeui/glade-preview.c
index 4a1bbd3..0d1acf8 100644
--- a/gladeui/glade-preview.c
+++ b/gladeui/glade-preview.c
@@ -47,6 +47,12 @@
 
 #include "glade-preview-tokens.h"
 
+#ifdef G_OS_WIN32
+#define GLADE_PREVIEWER "glade-previewer.exe"
+#else
+#define GLADE_PREVIEWER "glade-previewer"
+#endif
+
 /* Private data for glade-preview */
 struct _GladePreviewPrivate
 {
@@ -77,7 +83,7 @@ static guint glade_preview_signals[LAST_SIGNAL] = { 0 };
  *
  */
 static void
-glade_preview_kill (GladePreview * preview)
+glade_preview_kill (GladePreview *preview)
 {
   const gchar *quit = QUIT_TOKEN;
   GIOChannel *channel;
@@ -89,27 +95,27 @@ glade_preview_kill (GladePreview * preview)
 
   if (size != strlen (quit) && error != NULL)
     {
-      g_printerr ("Error passing quit signal trough pipe: %s", error->message);
+      g_warning ("Error passing quit signal trough pipe: %s", error->message);
       g_error_free (error);
     }
 
   g_io_channel_flush (channel, &error);
   if (error != NULL)
     {
-      g_printerr ("Error flushing channel: %s", error->message);
+      g_warning ("Error flushing channel: %s", error->message);
       g_error_free (error);
     }
 
   g_io_channel_shutdown (channel, TRUE, &error);
   if (error != NULL)
     {
-      g_printerr ("Error shutting down channel: %s", error->message);
+      g_warning ("Error shutting down channel: %s", error->message);
       g_error_free (error);
     }
 }
 
 static void
-glade_preview_dispose (GObject * gobject)
+glade_preview_dispose (GObject *gobject)
 {
   GladePreview *self = GLADE_PREVIEW (gobject);
 
@@ -130,13 +136,13 @@ glade_preview_dispose (GObject * gobject)
 
 /* We have to use finalize because of the signal that is sent in dispose */
 static void
-glade_preview_finalize (GObject * gobject)
+glade_preview_finalize (GObject *gobject)
 {
   G_OBJECT_CLASS (glade_preview_parent_class)->finalize (gobject);
 }
 
 static void
-glade_preview_class_init (GladePreviewClass * klass)
+glade_preview_class_init (GladePreviewClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
@@ -161,7 +167,7 @@ glade_preview_class_init (GladePreviewClass * klass)
 }
 
 static void
-glade_preview_init (GladePreview * self)
+glade_preview_init (GladePreview *self)
 {
   GladePreviewPrivate *priv;
 
@@ -191,47 +197,61 @@ glade_preview_internal_watch (GPid pid, gint status, gpointer data)
  * 
  */
 GladePreview *
-glade_preview_launch (GladeWidget * widget, 
-                     const gchar * buffer)
+glade_preview_launch (GladeWidget *widget, const gchar *buffer)
 {
   GPid pid;
   GError *error = NULL;
-  gchar *argv[4];
+  gchar *argv[9], *executable;
   gint child_stdin;
   gsize bytes_written;
   GIOChannel *output;
   GladePreview *preview = NULL;
+  const gchar *css_provider, *filename;
+  GladeProject *project;
+  gchar *name;
 
   g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
 
-#ifdef WINDOWS
-  argv[0] =
-      g_build_filename (glade_app_get_bin_dir (), "glade-previewer.exe", NULL);
-#else
-  argv[0] =
-      g_build_filename (glade_app_get_bin_dir (), "glade-previewer", NULL);
-#endif
+  executable = g_build_filename (glade_app_get_bin_dir (), GLADE_PREVIEWER, NULL);
 
+  project = glade_widget_get_project (widget);
+  filename = glade_project_get_path (project);
+  name = (filename) ? NULL : glade_project_get_name (project);
+  
+  argv[0] = executable;
   argv[1] = "--listen";
-  argv[2] = g_strdup_printf ("--toplevel=%s", glade_widget_get_name (widget));
-  argv[3] = NULL;
-
+  argv[2] = "--toplevel";
+  argv[3] = (gchar *) glade_widget_get_name (widget);
+  argv[4] = "--filename";
+  argv[5] = (filename) ? (gchar *) filename : name;
+  argv[6] = NULL;
+
+  css_provider = glade_project_get_css_provider_path (glade_widget_get_project (widget));
+  if (css_provider)
+    {
+      argv[6] = "--css";
+      argv[7] = (gchar *) css_provider;
+      argv[8] = NULL;
+    }
+  
   if (g_spawn_async_with_pipes (NULL,
                                 argv,
                                 NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
                                 &pid, &child_stdin, NULL, NULL,
                                 &error) == FALSE)
     {
-      g_printerr (_("Error launching previewer: %s\n"), error->message);
+      g_warning (_("Error launching previewer: %s\n"), error->message);
       glade_util_ui_message (glade_app_get_window (),
                              GLADE_UI_ERROR, NULL,
                              _("Failed to launch preview: %s.\n"),
                              error->message);
       g_error_free (error);
-      goto end;
+      g_free (executable);
+      g_free (name);
+      return NULL;
     }
 
-#ifdef WINDOWS
+#ifdef G_OS_WIN32
   output = g_io_channel_win32_new_fd (child_stdin);
 #else
   output = g_io_channel_unix_new (child_stdin);
@@ -242,20 +262,17 @@ glade_preview_launch (GladeWidget * widget,
 
   if (bytes_written != strlen (buffer) && error != NULL)
     {
-      g_printerr ("Error passing UI trough pipe: %s", error->message);
+      g_warning ("Error passing UI trough pipe: %s", error->message);
       g_error_free (error);
     }
 
   g_io_channel_flush (output, &error);
   if (error != NULL)
     {
-      g_printerr ("Error flushing UI trough pipe: %s", error->message);
+      g_warning ("Error flushing UI trough pipe: %s", error->message);
       g_error_free (error);
     }
 
-  if (widget != NULL)
-    g_free (argv[2]);
-
   /* Setting up preview data */
   preview                         = g_object_new (GLADE_TYPE_PREVIEW, NULL);
   preview->priv->channel          = output;
@@ -267,15 +284,14 @@ glade_preview_launch (GladeWidget * widget,
                       glade_preview_internal_watch,
                       preview);
 
-end:
-  g_free (argv[0]);
+  g_free (executable);
+  g_free (name);
 
   return preview;
 }
 
 void
-glade_preview_update (GladePreview *preview, 
-                     const gchar  *buffer)
+glade_preview_update (GladePreview *preview, const gchar  *buffer)
 {
   const gchar *update_token = UPDATE_TOKEN;
   gchar *update;
@@ -298,14 +314,14 @@ glade_preview_update (GladePreview *preview,
 
   if (size != strlen (update) && error != NULL)
     {
-      g_printerr ("Error passing quit signal trough pipe: %s", error->message);
+      g_warning ("Error passing quit signal trough pipe: %s", error->message);
       g_error_free (error);
     }
 
   g_io_channel_flush (channel, &error);
   if (error != NULL)
     {
-      g_printerr ("Error flushing channel: %s", error->message);
+      g_warning ("Error flushing channel: %s", error->message);
       g_error_free (error);
     }
 
@@ -315,14 +331,14 @@ glade_preview_update (GladePreview *preview,
 
   if (bytes_written != strlen (buffer) && error != NULL)
     {
-      g_printerr ("Error passing UI trough pipe: %s", error->message);
+      g_warning ("Error passing UI trough pipe: %s", error->message);
       g_error_free (error);
     }
 
   g_io_channel_flush (channel, &error);
   if (error != NULL)
     {
-      g_printerr ("Error flushing UI trough pipe: %s", error->message);
+      g_warning ("Error flushing UI trough pipe: %s", error->message);
       g_error_free (error);
     }
 
@@ -330,13 +346,15 @@ glade_preview_update (GladePreview *preview,
 }
 
 GladeWidget *
-glade_preview_get_widget (GladePreview * preview)
+glade_preview_get_widget (GladePreview *preview)
 {
+  g_return_val_if_fail (GLADE_IS_PREVIEW (preview), NULL);
   return preview->priv->previewed_widget;
 }
 
 GPid
-glade_preview_get_pid (GladePreview * preview)
+glade_preview_get_pid (GladePreview *preview)
 {
+  g_return_val_if_fail (GLADE_IS_PREVIEW (preview), 0);
   return preview->priv->pid;
 }
diff --git a/gladeui/glade-previewer.c b/gladeui/glade-previewer.c
index d5b270b..4a428d0 100644
--- a/gladeui/glade-previewer.c
+++ b/gladeui/glade-previewer.c
@@ -21,104 +21,28 @@
 
 #include <config.h>
 
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-
 #include <gladeui/glade.h>
 
 #include <stdlib.h>
 #include <locale.h>
 #include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
 
+#include "glade-preview-window.h"
 #include "glade-preview-tokens.h"
 
-static void
-display_help_and_quit (const GOptionEntry * entries)
-{
-  GOptionContext *context;
-  context = g_option_context_new (_("- previews a glade UI definition"));
-  g_option_context_add_main_entries (context, entries, NULL);
-  g_option_context_add_group (context, gtk_get_option_group (TRUE));
-
-  g_print ("%s\n", g_option_context_get_help (context, TRUE, NULL));
-
-  g_option_context_free (context);
-  exit (1);
-}
-
-static void
-parse_arguments (int argc, char **argv,
-                 gchar **toplevel_name,
-                 gchar **file_name,
-                 gchar **css_file_name,
-                 gchar **screenshot_file_name)
+typedef struct
 {
-  gboolean listen = FALSE;
-  gboolean version = FALSE;
-  GError *error = NULL;
-  GOptionEntry entries[] =
-    {
-        {"filename", 'f', G_OPTION_ARG_NONE, G_OPTION_ARG_FILENAME, file_name, _("Name of the file to 
preview"), "FILENAME"},
-        {"toplevel", 't', G_OPTION_ARG_NONE, G_OPTION_ARG_STRING, toplevel_name, _("Name of the toplevel to 
preview"), "TOPLEVELNAME"},
-        {"screenshot", 0, G_OPTION_ARG_NONE, G_OPTION_ARG_FILENAME, screenshot_file_name, _("File name to 
save a screenshot"), NULL},
-        {"css", 0, G_OPTION_ARG_NONE, G_OPTION_ARG_FILENAME, css_file_name, _("CSS file to use"), NULL},
-        {"listen", 'l', 0, G_OPTION_ARG_NONE, &listen, _("Listen standard input"), NULL},
-        {"version", 'v', 0, G_OPTION_ARG_NONE, &version, _("Display previewer version"), NULL},
-        {NULL}
-    };
-
-  *toplevel_name = NULL;
-  *file_name = NULL;
-  *css_file_name = NULL;
-  *screenshot_file_name = NULL;
-  
-  if (!gtk_init_with_args (&argc, &argv, _("- previews a glade UI definition"),
-                           entries, NULL, &error))
-    {
-      g_printerr (_
-                  ("%s\nRun '%s --help' to see a full list of available command line "
-                   "options.\n"), error->message, argv[0]);
-      g_error_free (error);
-      exit (1);
-    }
-
-  if (version)
-    {
-      g_print ("glade-previewer " VERSION "\n");
-      exit (0);
-    }
-
-  if (listen && *file_name != NULL)
-    {
-      g_printerr (_
-                  ("--listen and --filename must not be simultaneously specified.\n"));
-      display_help_and_quit (entries);
-    }
-
-  if (!listen && *file_name == NULL)
-    {
-      g_printerr (_("Either --listen or --filename must be specified.\n"));
-      display_help_and_quit (entries);
-    }
-}
+  GladePreviewWindow *window;
+  gchar *file_name, *toplevel;
+} GladePreviewer;
 
 static GtkWidget *
-get_toplevel (gchar *name, gchar *string, gsize length)
+get_toplevel (GtkBuilder *builder, gchar *name)
 {
-  GError *error = NULL;
   GtkWidget *toplevel = NULL;
-  GtkBuilder *builder;
   GObject *object;
 
-  builder = gtk_builder_new ();
-  if (!gtk_builder_add_from_string (builder, string, length, &error))
-    {
-      g_printerr (_("Couldn't load builder definition: %s"), error->message);
-      g_error_free (error);
-      exit (1);
-    }
-
   if (name == NULL)
     {
       GSList *objects;
@@ -163,127 +87,46 @@ get_toplevel (gchar *name, gchar *string, gsize length)
       toplevel = GTK_WIDGET (object);
     }
 
-  g_object_ref_sink (toplevel);
-  g_object_unref (builder);
-
-  return toplevel;
-}
-
-static gboolean 
-on_window_key_press_event (GtkWidget *widget, GdkEventKey *event)
-{
-  if (event->keyval == GDK_KEY_F12)
-    {
-      GdkPixbuf *pix = gdk_pixbuf_get_from_window (gtk_widget_get_window (widget), 0, 0, 
-                                                   gtk_widget_get_allocated_width (widget),
-                                                   gtk_widget_get_allocated_height (widget));
-      gchar tmp_file[] = "glade-screenshot-XXXXXX.png"; 
-
-      g_mkstemp (tmp_file);
-      gdk_pixbuf_save (pix, tmp_file, "png", NULL, NULL);
-      g_object_unref (pix);
-      return TRUE;
-    }
-  
-  return FALSE;
+  return g_object_ref_sink (toplevel);
 }
 
-static GtkWidget*
-show_widget (GtkWidget *widget)
+static GtkWidget *
+get_toplevel_from_string (GladePreviewer *app, gchar *name, gchar *string)
 {
-  GtkWidget *widget_parent;
-  GtkWidget *window;
+  GtkBuilder *builder = gtk_builder_new ();
+  GError *error = NULL;
+  GtkWidget *retval;
+  gchar *wd;
 
-  if (!GTK_IS_WINDOW (widget))
+  /* We need to change the working directory so builder get a chance to load resources */
+  if (app->file_name)
     {
-      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-      
-      gtk_window_set_title (GTK_WINDOW (window), _("Preview"));
-
-      /* Reparenting snippet */
-      g_object_ref (G_OBJECT (widget));
-      widget_parent = gtk_widget_get_parent (widget);
-      if (widget_parent != NULL)
-        gtk_container_remove (GTK_CONTAINER (widget_parent), widget);
-      gtk_container_add (GTK_CONTAINER (window), widget);
-      g_object_unref (widget);
+      gchar *dirname = g_path_get_dirname (app->file_name);
+      wd = g_get_current_dir ();
+      g_chdir (dirname);
+      g_free (dirname);
     }
   else
-    {
-      window = widget;
-    }
-
-  gtk_widget_add_events (window, GDK_KEY_PRESS_MASK);
-  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
-  g_signal_connect (window, "key-press-event", G_CALLBACK (on_window_key_press_event), NULL);
-  return window;
-}
-
-
-static gboolean
-quit_when_idle (gpointer loop)
-{
-  g_main_loop_quit (loop);
-
-  return G_SOURCE_REMOVE;
-}
+    wd = NULL;
 
-static void
-check_for_draw (GdkEvent *event, gpointer loop)
-{
-  if (event->type == GDK_EXPOSE)
+  if (!gtk_builder_add_from_string (builder, string, -1, &error))
     {
-      g_idle_add (quit_when_idle, loop);
-      gdk_event_handler_set ((GdkEventFunc) gtk_main_do_event, NULL, NULL);
+      g_printerr (_("Couldn't load builder definition: %s"), error->message);
+      g_error_free (error);
+      exit (1);
     }
 
-  gtk_main_do_event (event);
-}
-
-/* Taken from Gtk sources gtk-reftest.c  */
-static void
-wait_for_drawing (GdkWindow *window)
-{
-  GMainLoop *loop;
-
-  loop = g_main_loop_new (NULL, FALSE);
-  /* We wait until the widget is drawn for the first time.
-   * We can not wait for a GtkWidget::draw event, because that might not
-   * happen if the window is fully obscured by windowed child widgets.
-   * Alternatively, we could wait for an expose event on widget's window.
-   * Both of these are rather hairy, not sure what's best. */
-  gdk_event_handler_set (check_for_draw, loop, NULL);
-  g_main_loop_run (loop);
-
-  /* give the WM/server some time to sync. They need it.
-   * Also, do use popups instead of toplevls in your tests
-   * whenever you can. */
-  gdk_display_sync (gdk_window_get_display (window));
-  g_timeout_add (500, quit_when_idle, loop);
-  g_main_loop_run (loop);
-}
-
-static GtkWidget *
-preview_file (gchar *toplevel_name, gchar *file_name)
-{
-  GError *error = NULL;
-  gchar *buffer;
-  gsize length;
-
-  if (g_file_get_contents (file_name, &buffer, &length, &error))
-    {
-      GtkWidget *widget = get_toplevel (toplevel_name, buffer, length);
-      g_free (buffer);
+  retval = get_toplevel (builder, name);
+  g_object_unref (builder);
 
-      return show_widget (widget);
-    }
-  else
+  /* restore directory */
+  if (wd)
     {
-      g_printerr (_("Error: %s.\n"), error->message);
-      g_error_free (error);
+      g_chdir (wd);
+      g_free (wd);
     }
-
-  return NULL;
+  
+  return retval;
 }
 
 static gchar *
@@ -332,37 +175,47 @@ read_buffer (GIOChannel * source)
 }
 
 static void
-update_window (GtkWindow *old_window, GtkWidget *new_widget)
+glade_previewer_window_set_title (GtkWindow *window, 
+                                  gchar *filename,
+                                  gchar *toplevel)
 {
-  GtkWidget *old_window_child;
+  gchar *title, *pretty_path = NULL;
 
-  if (!old_window) return;
-
-  /* gtk_widget_destroy the *running preview's* window child */
-  old_window_child = gtk_bin_get_child (GTK_BIN (old_window));
-  if (old_window_child)
-    gtk_widget_destroy (old_window_child);
+  if (filename && g_path_is_absolute (filename))
+    {
+      gchar *canonical_path = glade_util_canonical_path (filename); 
+      filename = pretty_path = glade_utils_replace_home_dir_with_tilde (canonical_path);
+      g_free (canonical_path);      
+    }
 
-  /* add new widget as child to the old preview's window */
-  if (new_widget)
+  if (filename)
+    {
+      if (toplevel)
+        title = g_strdup_printf (_("Previewing %s (%s)"), filename, toplevel);
+      else
+        title = g_strdup_printf (_("Previewing %s"), filename);
+    }
+  else if (toplevel)
     {
-      gtk_widget_set_parent_window (new_widget, gtk_widget_get_window (GTK_WIDGET (old_window)));
-      gtk_container_add (GTK_CONTAINER (old_window), new_widget);
+      title = g_strdup_printf (_("Previewing %s"), toplevel);
+    }
+  else
+    {
+      gtk_window_set_title (window, _("Glade Preview"));
+      return;
     }
 
-  gtk_widget_show_all (GTK_WIDGET (old_window));
+  gtk_window_set_title (window, title);
+  g_free (pretty_path);
+  g_free (title);
 }
 
 static gboolean
-on_data_incoming (GIOChannel * source, GIOCondition condition, gpointer data)
+on_data_incoming (GIOChannel *source, GIOCondition condition, gpointer data)
 {
-  gchar *buffer;
-  gsize length;
-  static GtkWidget *preview_window = NULL;
+  GladePreviewer *app = data;
   GtkWidget *new_widget;
-  gchar **split_buffer = NULL;
-
-  gchar *toplevel_name = (gchar *) data;
+  gchar *buffer;
 
   buffer = read_buffer (source);
   if (buffer == NULL)
@@ -377,69 +230,89 @@ on_data_incoming (GIOChannel * source, GIOCondition condition, gpointer data)
       exit (1);
     }
 
-  length = strlen (buffer);
+  /* We have an update */
+  if (g_str_has_prefix (buffer, UPDATE_TOKEN))
+    {
+     gchar **split_buffer = g_strsplit_set (buffer + UPDATE_TOKEN_SIZE, "\n", 2);
 
-  /* if it is the first time this is called */
-  if (!preview_window)
-  {
-    new_widget = get_toplevel (toplevel_name, buffer, length);
-    preview_window = show_widget (new_widget);
-    gtk_widget_show_all (preview_window);
-  }
-  else
-  {
-    /* We have an update */
-    split_buffer = g_strsplit_set (buffer + UPDATE_TOKEN_SIZE, "\n", 2);
+      if (!split_buffer)
+        {
+          g_free (buffer);
+          return FALSE;
+        }
 
-    g_free (buffer);
-    if (!split_buffer) return FALSE;
+      new_widget = get_toplevel_from_string (app, split_buffer[0], split_buffer[1]);
+      glade_previewer_window_set_title (GTK_WINDOW (app->window), app->file_name,
+                                        split_buffer[0]);
 
-    toplevel_name = split_buffer[0];
-    buffer = split_buffer[1];
-    length = strlen (buffer);
+      g_strfreev (split_buffer);
+    }
+  else
+    {
+      new_widget = get_toplevel_from_string (app, app->toplevel, buffer);
+      glade_previewer_window_set_title (GTK_WINDOW (app->window), app->file_name, app->toplevel);
+    }
 
-    new_widget = get_toplevel (toplevel_name, buffer, length);
+  glade_preview_window_set_widget (app->window, new_widget);
 
-    update_window (GTK_WINDOW (preview_window), new_widget);
-  }
+  gtk_window_present (GTK_WINDOW (app->window));
+  gtk_widget_show (new_widget);
+  
+  g_free (buffer);
+  
+  return TRUE;
+}
 
-  if (!split_buffer)
-  {
-    /* This means we're not in an update, we should free the buffer. */
-    g_free (buffer);
-  }
-  else
-  {
-    /* This means we've had an update, buffer was already freed. */
-    g_free (split_buffer[0]);
-    g_free (split_buffer[1]);
-    g_free (split_buffer);
-  }
+static GladePreviewer *
+glade_previewer_new (gchar *filename, gchar *toplevel)
+{
+  GladePreviewer *app = g_new0 (GladePreviewer, 1);
 
-  return TRUE;
+  app->window = GLADE_PREVIEW_WINDOW (glade_preview_window_new ());
+  g_object_ref_sink (app->window);
+  
+  g_signal_connect (app->window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
+  glade_previewer_window_set_title (GTK_WINDOW (app->window), filename, toplevel);
+   
+  app->file_name = g_strdup (filename);
+  app->toplevel = g_strdup (toplevel);
+
+  return app;
 }
 
 static void
-start_listener (gchar * toplevel_name)
+glade_previewer_free (GladePreviewer *app)
 {
-  GIOChannel *input;
+  g_object_unref (app->window);
+  g_free (app->file_name);
+  g_free (app->toplevel);
+  g_free (app);
+}
 
-#ifdef WINDOWS
-  input = g_io_channel_win32_new_fd (fileno (stdin));
-#else
-  input = g_io_channel_unix_new (fileno (stdin));
-#endif
+static gboolean listen = FALSE;
+static gboolean version = FALSE;
+static gchar *file_name = NULL;
+static gchar *toplevel_name = NULL;
+static gchar *css_file_name = NULL;
+static gchar *screenshot_file_name = NULL;
 
-  g_io_add_watch (input, G_IO_IN | G_IO_HUP, on_data_incoming, toplevel_name);
-}
+static GOptionEntry option_entries[] =
+{
+    {"filename", 'f', 0, G_OPTION_ARG_FILENAME, &file_name, N_("Name of the file to preview"), "FILENAME"},
+    {"toplevel", 't', 0, G_OPTION_ARG_STRING, &toplevel_name, N_("Name of the toplevel to preview"), 
"TOPLEVELNAME"},
+    {"screenshot", 0, 0, G_OPTION_ARG_FILENAME, &screenshot_file_name, N_("File name to save a screenshot"), 
NULL},
+    {"css", 0, 0, G_OPTION_ARG_FILENAME, &css_file_name, N_("CSS file to use"), NULL},
+    {"listen", 'l', 0, G_OPTION_ARG_NONE, &listen, N_("Listen standard input"), NULL},
+    {"version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("Display previewer version"), NULL},
+    {NULL}
+};
 
 int
 main (int argc, char **argv)
 {
-  gchar *file_name;
-  gchar *toplevel_name;
-  gchar *css_file_name;
-  gchar *shot_file_name;
+  GladePreviewer *app;
+  GOptionContext *context;
+  GError *error = NULL;
 
 #ifdef ENABLE_NLS
   setlocale (LC_ALL, "");
@@ -448,57 +321,86 @@ main (int argc, char **argv)
   textdomain (GETTEXT_PACKAGE);
 #endif
 
-  parse_arguments (argc, argv, &toplevel_name, &file_name, &css_file_name, &shot_file_name);
+  context = g_option_context_new (_("- previews a glade UI definition"));
+  g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE);
+  g_option_context_add_group (context, gtk_get_option_group (TRUE));
+  
+  if (!g_option_context_parse (context, &argc, &argv, &error))
+    {
+      g_printerr (_("%s\nRun '%s --help' to see a full list of available command line "
+                   "options.\n"), error->message, argv[0]);
+      g_error_free (error);
+      g_option_context_free (context);
+      return 1;
+    }
+
+  g_option_context_free (context);
+
+  if (version)
+    {
+      g_print ("glade-previewer " VERSION "\n");
+      return 0;
+    }
+
+  if (!listen && !file_name)
+    {
+      g_printerr (_("Either --listen or --filename must be specified.\n"));
+      return 0;
+    }
 
   gtk_init (&argc, &argv);
   glade_app_get ();
 
+  app = glade_previewer_new (file_name, toplevel_name);
+  gtk_widget_show (GTK_WIDGET (app->window));
+  
   if (css_file_name)
+    glade_preview_window_set_css_file (app->window, css_file_name);
+
+  if (listen)
+    {
+#ifdef WINDOWS
+      GIOChannel *input = g_io_channel_win32_new_fd (fileno (stdin));
+#else
+      GIOChannel *input = g_io_channel_unix_new (fileno (stdin));
+#endif
+
+      g_io_add_watch (input, G_IO_IN | G_IO_HUP, on_data_incoming, app);
+
+      gtk_main ();
+    }
+  else if (app->file_name)
     {
-      GtkCssProvider *css = gtk_css_provider_new ();
+      GtkBuilder *builder = gtk_builder_new ();
       GError *error = NULL;
-      
-      gtk_css_provider_load_from_path (css, css_file_name, &error);
-      if (error)
+      GtkWidget *widget;
+
+      /* Use from_file() function gives builder a chance to know where to load resources from */
+      if (!gtk_builder_add_from_file (builder, app->file_name, &error))
         {
-          g_message ("CSS parsing failed: %s", error->message);
+          g_printerr (_("Couldn't load builder definition: %s"), error->message);
           g_error_free (error);
+          return 1;
         }
-      else
-        gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
-                                                   GTK_STYLE_PROVIDER (css),
-                                                   GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-    }
 
-  if (file_name != NULL)
-    {
-      GtkWidget *toplevel = preview_file (toplevel_name, file_name);
+      widget = get_toplevel (builder, toplevel_name);
+      glade_preview_window_set_widget (app->window, widget);
+      gtk_widget_show (widget);
 
-      gtk_widget_show_all (toplevel);
-      
-      if (shot_file_name)
-        {
-          gchar *tmp_file = g_strconcat (shot_file_name, ".png", NULL);
-          GdkWindow *window = gtk_widget_get_window (toplevel);
-          GdkPixbuf *pix;
-
-          wait_for_drawing (window);
-          pix = gdk_pixbuf_get_from_window (window, 0, 0, 
-                                            gtk_widget_get_allocated_width (toplevel),
-                                            gtk_widget_get_allocated_height (toplevel));
-          gdk_pixbuf_save (pix, tmp_file, "png", NULL, NULL);
-
-          g_object_unref (pix);
-          g_free (tmp_file);
-          return 0;
-        }
-    }
-  else
-    {
-      start_listener (toplevel_name);
+      if (screenshot_file_name)
+        glade_preview_window_screenshot (app->window, TRUE, screenshot_file_name);
+      else
+        gtk_main ();
+
+      g_object_unref (builder);
     }
 
-  gtk_main ();
+  /* free unused resources */
+  g_free (file_name);
+  g_free (toplevel_name);
+  g_free (css_file_name);
+  g_free (screenshot_file_name);
+  glade_previewer_free (app);
 
   return 0;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]