diff options
-rw-r--r-- | gladeui/glade-preview-window.c | 208 | ||||
-rw-r--r-- | gladeui/glade-preview-window.h | 3 | ||||
-rw-r--r-- | gladeui/glade-previewer.c | 112 |
3 files changed, 248 insertions, 75 deletions
diff --git a/gladeui/glade-preview-window.c b/gladeui/glade-preview-window.c index 116ec857..c2fe7193 100644 --- a/gladeui/glade-preview-window.c +++ b/gladeui/glade-preview-window.c @@ -108,6 +108,14 @@ glade_preview_window_key_press_event (GtkWidget *widget, GdkEventKey *event) case GDK_KEY_F8: extension = priv->extension ? priv->extension : "png"; break; + case GDK_KEY_F11: + if (gdk_window_get_state (gtk_widget_get_window (widget)) & GDK_WINDOW_STATE_FULLSCREEN) + gtk_window_unfullscreen (GTK_WINDOW (widget)); + else + gtk_window_fullscreen (GTK_WINDOW (widget)); + + return TRUE; + break; default: return FALSE; break; @@ -334,7 +342,7 @@ check_for_draw (GdkEvent *event, gpointer loop) /* Taken from Gtk sources gtk-reftest.c */ static void -wait_for_drawing (GdkWindow *window) +glade_preview_wait_for_drawing (GdkWindow *window) { GMainLoop *loop; @@ -355,25 +363,70 @@ wait_for_drawing (GdkWindow *window) g_main_loop_run (loop); } -static inline gdouble -get_x_scale (GdkScreen *screen) +static const gchar * +glade_preview_get_extension (const gchar *filename) { - return 72.0 / (gdk_screen_get_width (screen) / (gdk_screen_get_width_mm (screen) * 0.03937008)); + gchar *extension; + + g_return_val_if_fail (filename != NULL, NULL); + + extension = g_strrstr (filename,"."); + + if (extension) + extension++; + + if (!extension) + { + g_warning ("%s has no extension!", filename); + return NULL; + } + return extension; } -static inline gdouble -get_y_scale (GdkScreen *screen) +static void +glade_preview_get_scale (GdkScreen *screen, gdouble *sx, gdouble *sy) { - return 72.0 / (gdk_screen_get_height (screen) / (gdk_screen_get_height_mm (screen) * 0.03937008)); + if (sx) + *sx = 72.0 / (gdk_screen_get_width (screen) / (gdk_screen_get_width_mm (screen) * 0.03937008)); + + if (sy) + *sy = 72.0 / (gdk_screen_get_height (screen) / (gdk_screen_get_height_mm (screen) * 0.03937008)); } -typedef enum +static cairo_surface_t * +glade_preview_surface_from_file (const gchar *filename, gdouble w, gdouble h) { - EXT_TYPE_SVG, - EXT_TYPE_PS, - EXT_TYPE_PDF, - EXT_TYPE_OTHER -} ExtTypeEnum; + cairo_surface_t *surface; + const gchar *extension; + + extension = glade_preview_get_extension (filename); + + if (extension == NULL) + return NULL; + + if (g_strcmp0 (extension, "svg") == 0) +#if CAIRO_HAS_SVG_SURFACE + surface = cairo_svg_surface_create (filename, w, h); +#else + g_warning ("PDF not supported by the cairo version used"); +#endif + else if (g_strcmp0 (extension, "ps") == 0) +#if CAIRO_HAS_PS_SURFACE + surface = cairo_ps_surface_create (filename, w, h); +#else + g_warning ("PS not supported by the cairo version used"); +#endif + else if (g_strcmp0 (extension, "pdf") == 0) +#if CAIRO_HAS_PDF_SURFACE + surface = cairo_pdf_surface_create (filename, w, h); +#else + g_warning ("PDF not supported by the cairo version used"); +#endif + else + return NULL; + + return surface; +} /** * glade_preview_window_screenshot: @@ -390,10 +443,10 @@ glade_preview_window_screenshot (GladePreviewWindow *window, const gchar *filename) { GladePreviewWindowPrivate *priv; + cairo_surface_t *surface; GdkWindow *gdkwindow; GdkScreen *screen; - gchar *extension; - ExtTypeEnum ext_type; + gdouble sx, sy; gint w, h; g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window)); @@ -403,74 +456,99 @@ glade_preview_window_screenshot (GladePreviewWindow *window, 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); + glade_preview_wait_for_drawing (gdkwindow); w = gtk_widget_get_allocated_width (priv->widget); h = gtk_widget_get_allocated_height (priv->widget); + glade_preview_get_scale (screen, &sx, &sy); + + surface = glade_preview_surface_from_file (filename, w*sx, h*sy); - 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; + if (surface) + { + cairo_t *cr = cairo_create (surface); + cairo_scale (cr, sx, sy); + gtk_widget_draw (priv->widget, cr); + cairo_destroy (cr); + cairo_surface_destroy(surface); + } 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); + const gchar *ext = glade_preview_get_extension (filename); + GError *error = NULL; + + if (gdk_pixbuf_save (pix, filename, ext ? ext : "png", &error, NULL)) + { + g_warning ("Could not save screenshot to %s because %s", filename, error->message); + g_error_free (error); + } g_object_unref (pix); } - else +} + +/** + * glade_preview_window_slideshow_save: + * @window: A GladePreviewWindow + * @filename: a filename to save the slideshow. + * + * Takes a screenshot of every widget GtkStack children and save it to @filename + * each in a different page + */ +void +glade_preview_window_slideshow_save (GladePreviewWindow *window, + const gchar *filename) +{ + GladePreviewWindowPrivate *priv; + cairo_surface_t *surface; + GdkWindow *gdkwindow; + GtkStack *stack; + gdouble sx, sy; + + g_return_if_fail (GLADE_IS_PREVIEW_WINDOW (window)); + g_return_if_fail (filename != NULL); + priv = window->priv; + + g_return_if_fail (priv->widget); + g_return_if_fail (GTK_IS_STACK (priv->widget)); + stack = GTK_STACK (priv->widget); + + gdkwindow = gtk_widget_get_window (priv->widget); + glade_preview_wait_for_drawing (gdkwindow); + + glade_preview_get_scale (gtk_widget_get_screen (GTK_WIDGET (window)), &sx, &sy); + surface = glade_preview_surface_from_file (filename, + gtk_widget_get_allocated_width (GTK_WIDGET (stack))*sx, + gtk_widget_get_allocated_height (GTK_WIDGET (stack))*sy); + + if (surface) { - cairo_surface_t *surface; - cairo_t *cr; - gdouble sx = get_x_scale (screen); - gdouble sy = get_y_scale (screen); + GList *l, *children = gtk_container_get_children (GTK_CONTAINER (stack)); + cairo_t *cr= cairo_create (surface); - 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); + + for (l = children; l; l = g_list_next (l)) + { + GtkWidget *child = l->data; + gtk_stack_set_visible_child (stack, child); + glade_preview_wait_for_drawing (gdkwindow); + gtk_widget_draw (child, cr); + cairo_show_page (cr); + } + + if (children) + gtk_stack_set_visible_child (stack, children->data); + + g_list_free (children); cairo_destroy (cr); cairo_surface_destroy(surface); - } + else + g_warning ("Could not save slideshow to %s", filename); } diff --git a/gladeui/glade-preview-window.h b/gladeui/glade-preview-window.h index 7ed54f89..0ff2bdcd 100644 --- a/gladeui/glade-preview-window.h +++ b/gladeui/glade-preview-window.h @@ -73,6 +73,9 @@ void glade_preview_window_screenshot (GladePreviewWindow *window, gboolean wait, const gchar *filename); +void glade_preview_window_slideshow_save (GladePreviewWindow *window, + const gchar *filename); + G_END_DECLS #endif /* _GLADE_PREVIEW_WINDOW_H_ */ diff --git a/gladeui/glade-previewer.c b/gladeui/glade-previewer.c index 4a428d0f..30f17263 100644 --- a/gladeui/glade-previewer.c +++ b/gladeui/glade-previewer.c @@ -45,12 +45,12 @@ get_toplevel (GtkBuilder *builder, gchar *name) if (name == NULL) { - GSList *objects; + GSList *l, *objects = gtk_builder_get_objects (builder); /* Iterate trough objects and search for a window or widget */ - for (objects = gtk_builder_get_objects (builder); objects; objects = g_slist_next (objects)) + for (l = objects; l; l = g_slist_next (l)) { - GObject *obj = objects->data; + GObject *obj = l->data; if (!GTK_IS_WIDGET (obj) || gtk_widget_get_parent (GTK_WIDGET (obj))) continue; @@ -289,8 +289,56 @@ glade_previewer_free (GladePreviewer *app) g_free (app); } +static gint +objects_cmp_func (gconstpointer a, gconstpointer b) +{ + const gchar *name_a, *name_b; + name_a = gtk_buildable_get_name (GTK_BUILDABLE (a)); + name_b = gtk_buildable_get_name (GTK_BUILDABLE (b)); + return g_strcmp0 (name_a, name_b); +} +static gboolean +glade_previewer_stack_key_press_event (GtkWidget *window, GdkEventKey *event, GtkWidget *widget) +{ + GtkWidget *child = gtk_stack_get_visible_child (GTK_STACK (widget)); + GList *children, *node; + gboolean retval; + + if (!child) + return FALSE; + + children = gtk_container_get_children (GTK_CONTAINER (widget)); + + node = g_list_find (children, child); + + if (node) + { + switch (event->keyval) + { + case GDK_KEY_Page_Up: + if (node->prev) + gtk_stack_set_visible_child (GTK_STACK (widget), node->prev->data); + retval = TRUE; + break; + case GDK_KEY_Page_Down: + if (node->next) + gtk_stack_set_visible_child (GTK_STACK (widget), node->next->data); + retval = TRUE; + break; + default: + retval = FALSE; + break; + } + } + + g_list_free (children); + return retval; +} + + static gboolean listen = FALSE; static gboolean version = FALSE; +static gboolean slideshow = FALSE; static gchar *file_name = NULL; static gchar *toplevel_name = NULL; static gchar *css_file_name = NULL; @@ -303,6 +351,7 @@ static GOptionEntry option_entries[] = {"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}, + {"slideshow", 0, 0, G_OPTION_ARG_NONE, &slideshow, N_("make a slideshow of every toplevel widget by adding them in a GtkStack"), NULL}, {"version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("Display previewer version"), NULL}, {NULL} }; @@ -373,7 +422,6 @@ main (int argc, char **argv) { GtkBuilder *builder = gtk_builder_new (); GError *error = NULL; - 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)) @@ -383,14 +431,58 @@ main (int argc, char **argv) return 1; } - widget = get_toplevel (builder, toplevel_name); - glade_preview_window_set_widget (app->window, widget); - gtk_widget_show (widget); + if (slideshow) + { + GSList *l, *objects = gtk_builder_get_objects (builder); + GtkStack *stack = GTK_STACK (gtk_stack_new ()); + + /* Add Page up and Page down key binding */ + g_signal_connect (app->window, "key-press-event", + G_CALLBACK (glade_previewer_stack_key_press_event), + stack); + + objects = g_slist_sort (objects, objects_cmp_func); + + for (l = objects; l; l = g_slist_next (l)) + { + GObject *obj = l->data; + + if (!GTK_IS_WIDGET (obj) || gtk_widget_get_parent (GTK_WIDGET (obj))) + continue; - if (screenshot_file_name) - glade_preview_window_screenshot (app->window, TRUE, screenshot_file_name); + /* TODO: make sure we can add a toplevel inside a stack */ + if (GTK_IS_WINDOW (obj)) + continue; + + gtk_stack_add_named (stack, GTK_WIDGET (obj), + gtk_buildable_get_name (GTK_BUILDABLE (obj))); + } + + glade_preview_window_set_widget (app->window, GTK_WIDGET (stack)); + gtk_widget_show (GTK_WIDGET (stack)); + + if (screenshot_file_name) + glade_preview_window_slideshow_save (app->window, screenshot_file_name); + else + { + gtk_stack_set_transition_type (stack, GTK_STACK_TRANSITION_TYPE_CROSSFADE); + + gtk_main (); + } + + g_slist_free (objects); + } else - gtk_main (); + { + GtkWidget *widget = get_toplevel (builder, toplevel_name); + glade_preview_window_set_widget (app->window, widget); + gtk_widget_show (widget); + + if (screenshot_file_name) + glade_preview_window_screenshot (app->window, TRUE, screenshot_file_name); + else + gtk_main (); + } g_object_unref (builder); } |