From 3a88e5135374bd6508d58fa8b34104b98f82ecb9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 25 Aug 2009 12:55:39 -0400 Subject: [PATCH] [appearance] Make slideshows visually distinct The patch fixes the tooltips to not lie about the backgrounds, and adds a stacked frame decoration around slide shows. This patch adds two little buttons below the slide show that let you step through the frames of the slide show, to see whats in it. Fixes http://bugzilla.gnome.org/show_bug.cgi?id=591375 --- capplets/appearance/appearance-desktop.c | 187 +++++++++++++++++++++-- capplets/appearance/appearance.h | 1 + capplets/appearance/gnome-wp-item.c | 85 +++++++++-- capplets/appearance/gnome-wp-item.h | 3 + capplets/appearance/gnome-wp-xml.c | 2 +- 5 files changed, 255 insertions(+), 23 deletions(-) diff --git a/capplets/appearance/appearance-desktop.c b/capplets/appearance/appearance-desktop.c index 09ba7aae3..658033084 100644 --- a/capplets/appearance/appearance-desktop.c +++ b/capplets/appearance/appearance-desktop.c @@ -131,9 +131,7 @@ static void on_item_changed (GnomeBG *bg, AppearanceData *data) { pixbuf = gnome_wp_item_get_thumbnail (item, data->thumb_factory); if (pixbuf) { - gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter, - 0, pixbuf, - -1); + gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter, 0, pixbuf, -1); g_object_unref (pixbuf); } @@ -316,10 +314,7 @@ wp_scale_type_changed (GtkComboBox *combobox, item->options = gtk_combo_box_get_active (GTK_COMBO_BOX (data->wp_style_menu)); pixbuf = gnome_wp_item_get_thumbnail (item, data->thumb_factory); - gtk_list_store_set (GTK_LIST_STORE (data->wp_model), - &iter, - 0, pixbuf, - -1); + gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter, 0, pixbuf, -1); if (pixbuf != NULL) g_object_unref (pixbuf); @@ -344,9 +339,7 @@ wp_shade_type_changed (GtkWidget *combobox, item->shade_type = gtk_combo_box_get_active (GTK_COMBO_BOX (data->wp_color_menu)); pixbuf = gnome_wp_item_get_thumbnail (item, data->thumb_factory); - gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter, - 0, pixbuf, - -1); + gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter, 0, pixbuf, -1); if (pixbuf != NULL) g_object_unref (pixbuf); @@ -991,6 +984,162 @@ wp_select_after_realize (GtkWidget *widget, select_item (data, item, TRUE); } +static GdkPixbuf *buttons[3]; + +static void +create_button_images (AppearanceData *data) +{ + GtkWidget *widget = (GtkWidget*)data->wp_view; + GtkIconSet *icon_set; + GdkPixbuf *pixbuf, *pb, *pb2; + gint i, w, h; + + icon_set = gtk_style_lookup_icon_set (widget->style, "gtk-media-play"); + pb = gtk_icon_set_render_icon (icon_set, + widget->style, + GTK_TEXT_DIR_RTL, + GTK_STATE_NORMAL, + GTK_ICON_SIZE_MENU, + widget, + NULL); + pb2 = gtk_icon_set_render_icon (icon_set, + widget->style, + GTK_TEXT_DIR_LTR, + GTK_STATE_NORMAL, + GTK_ICON_SIZE_MENU, + widget, + NULL); + w = gdk_pixbuf_get_width (pb); + h = gdk_pixbuf_get_height (pb); + + for (i = 0; i < 3; i++) { + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 2 * w, h); + gdk_pixbuf_fill (pixbuf, 0); + if (i > 0) + gdk_pixbuf_composite (pb, pixbuf, 0, 0, w, h, 0, 0, 1, 1, GDK_INTERP_NEAREST, 255); + if (i < 2) + gdk_pixbuf_composite (pb2, pixbuf, w, 0, w, h, w, 0, 1, 1, GDK_INTERP_NEAREST, 255); + + buttons[i] = pixbuf; + } + + g_object_unref (pb); + g_object_unref (pb2); +} + +static gboolean +next_frame (AppearanceData *data, + GtkCellRenderer *cr, + gint direction) +{ + GnomeWPItem *item; + GtkTreeIter iter; + GdkPixbuf *pixbuf, *pb; + gint frame; + + pixbuf = NULL; + + frame = data->frame + direction; + item = get_selected_item (data, &iter); + + if (frame >= 0) + pixbuf = gnome_wp_item_get_frame_thumbnail (item, data->thumb_factory, frame); + if (pixbuf) { + gtk_list_store_set (GTK_LIST_STORE (data->wp_model), &iter, 0, pixbuf, -1); + g_object_unref (pixbuf); + data->frame = frame; + } + + pb = buttons[1]; + if (direction < 0) { + if (frame == 0) + pb = buttons[0]; + } + else { + pixbuf = gnome_wp_item_get_frame_thumbnail (item, data->thumb_factory, frame + 1); + if (pixbuf) + g_object_unref (pixbuf); + else + pb = buttons[2]; + } + g_object_set (cr, "pixbuf", pb, NULL); +} + +static gboolean +wp_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + AppearanceData *data) +{ + GtkCellRenderer *cell; + GdkEventButton *button_event = (GdkEventButton *) event; + + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + + if (gtk_icon_view_get_item_at_pos (GTK_ICON_VIEW (widget), + button_event->x, button_event->y, + NULL, &cell)) { + if (g_object_get_data (G_OBJECT (cell), "buttons")) { + gint w, h; + GtkCellRenderer *cell2 = NULL; + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h); + if (gtk_icon_view_get_item_at_pos (GTK_ICON_VIEW (widget), + button_event->x + w, button_event->y, + NULL, &cell2) && cell == cell2) + next_frame (data, cell, -1); + else + next_frame (data, cell, 1); + return TRUE; + } + } + + return FALSE; +} + +static void +wp_selected_changed_cb (GtkIconView *view, + AppearanceData *data) +{ + GtkCellRenderer *cr; + GList *cells, *l; + + data->frame = -1; + + cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (data->wp_view)); + for (l = cells; l; l = l->next) { + cr = l->data; + if (g_object_get_data (cr, "buttons")) + g_object_set (cr, "pixbuf", buttons[0], NULL); + } + g_list_free (cells); +} + +static void +buttons_cell_data_func (GtkCellLayout *layout, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + AppearanceData *data = user_data; + GtkTreePath *path; + GnomeWPItem *item; + gboolean visible; + + path = gtk_tree_model_get_path (model, iter); + + if (gtk_icon_view_path_is_selected (GTK_ICON_VIEW (layout), path)) { + item = get_selected_item (data, NULL); + visible = gnome_bg_changes_with_time (item->bg); + } + else + visible = FALSE; + + g_object_set (G_OBJECT (cell), "visible", visible, NULL); + + gtk_tree_path_free (path); +} + void desktop_init (AppearanceData *data, const gchar **uris) @@ -1067,6 +1216,24 @@ desktop_init (AppearanceData *data, "pixbuf", 0, NULL); + cr = gtk_cell_renderer_pixbuf_new (); + create_button_images (data); + g_object_set (cr, + "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, + "pixbuf", buttons[0], + NULL); + g_object_set_data (G_OBJECT (cr), "buttons", GINT_TO_POINTER (TRUE)); + + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (data->wp_view), cr, FALSE); + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (data->wp_view), cr, + buttons_cell_data_func, data, NULL); + g_signal_connect (data->wp_view, "selection-changed", + (GCallback) wp_selected_changed_cb, data); + g_signal_connect (data->wp_view, "button-press-event", + G_CALLBACK (wp_button_press_cb), data); + + data->frame = -1; + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (data->wp_model), 2, (GtkTreeIterCompareFunc) wp_list_sort, data, NULL); diff --git a/capplets/appearance/appearance.h b/capplets/appearance/appearance.h index b28e4d11b..5b4dd5910 100644 --- a/capplets/appearance/appearance.h +++ b/capplets/appearance/appearance.h @@ -50,6 +50,7 @@ typedef struct GtkFileChooser *wp_filesel; GtkWidget *wp_image; GSList *wp_uris; + gint frame; /* font */ GtkWidget *font_details; diff --git a/capplets/appearance/gnome-wp-item.c b/capplets/appearance/gnome-wp-item.c index 4e40b07a3..bf32c5188 100644 --- a/capplets/appearance/gnome-wp-item.c +++ b/capplets/appearance/gnome-wp-item.c @@ -140,9 +140,9 @@ GnomeWPItem * gnome_wp_item_new (const gchar * filename, item->name = g_filename_to_utf8 (item->fileinfo->name, -1, NULL, NULL, NULL); + gnome_wp_item_ensure_gnome_bg (item); gnome_wp_item_update (item); gnome_wp_item_update_description (item); - gnome_wp_item_ensure_gnome_bg (item); g_hash_table_insert (wallpapers, item->filename, item); } else { @@ -177,24 +177,71 @@ void gnome_wp_item_free (GnomeWPItem * item) { g_free (item); } +static GdkPixbuf * +add_slideshow_frame (GdkPixbuf *pixbuf) +{ + GdkPixbuf *sheet, *sheet2; + GdkPixbuf *tmp; + gint w, h; + + w = gdk_pixbuf_get_width (pixbuf); + h = gdk_pixbuf_get_height (pixbuf); + + sheet = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, w, h); + gdk_pixbuf_fill (sheet, 0x00000000); + sheet2 = gdk_pixbuf_new_subpixbuf (sheet, 1, 1, w - 2, h - 2); + gdk_pixbuf_fill (sheet2, 0xffffffff); + g_object_unref (sheet2); + + tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, w + 6, h + 6); + + gdk_pixbuf_fill (tmp, 0x00000000); + gdk_pixbuf_composite (sheet, tmp, 6, 6, w, h, 6.0, 6.0, 1.0, 1.0, GDK_INTERP_NEAREST, 255); + gdk_pixbuf_composite (sheet, tmp, 3, 3, w, h, 3.0, 3.0, 1.0, 1.0, GDK_INTERP_NEAREST, 255); + gdk_pixbuf_composite (pixbuf, tmp, 0, 0, w, h, 0.0, 0.0, 1.0, 1.0, GDK_INTERP_NEAREST, 255); + + g_object_unref (sheet); + + return tmp; +} + #define LIST_IMAGE_WIDTH 108 -GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item, - GnomeDesktopThumbnailFactory * thumbs) { - GdkPixbuf *pixbuf; +GdkPixbuf * gnome_wp_item_get_frame_thumbnail (GnomeWPItem * item, + GnomeDesktopThumbnailFactory * thumbs, + gint frame) { + GdkPixbuf *pixbuf = NULL; double aspect = (double)gdk_screen_get_height (gdk_screen_get_default()) / gdk_screen_get_width (gdk_screen_get_default()); set_bg_properties (item); - pixbuf = gnome_bg_create_thumbnail (item->bg, thumbs, gdk_screen_get_default(), LIST_IMAGE_WIDTH, LIST_IMAGE_WIDTH * aspect); + if (frame != -1) + pixbuf = gnome_bg_create_frame_thumbnail (item->bg, thumbs, gdk_screen_get_default (), LIST_IMAGE_WIDTH, LIST_IMAGE_WIDTH * aspect, frame); + else + pixbuf = gnome_bg_create_thumbnail (item->bg, thumbs, gdk_screen_get_default(), LIST_IMAGE_WIDTH, LIST_IMAGE_WIDTH * aspect); + + if (pixbuf && gnome_bg_changes_with_time (item->bg)) + { + GdkPixbuf *tmp; + + tmp = add_slideshow_frame (pixbuf); + g_object_unref (pixbuf); + pixbuf = tmp; + } gnome_bg_get_image_size (item->bg, thumbs, &item->width, &item->height); return pixbuf; } + +GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item, + GnomeDesktopThumbnailFactory * thumbs) { + return gnome_wp_item_get_frame_thumbnail (item, thumbs, -1); +} + void gnome_wp_item_update_description (GnomeWPItem * item) { g_free (item->description); @@ -202,27 +249,41 @@ void gnome_wp_item_update_description (GnomeWPItem * item) { item->description = g_strdup (item->name); } else { const gchar *description; + gchar *size; gchar *dirname = g_path_get_dirname (item->filename); if (strcmp (item->fileinfo->mime_type, "application/xml") == 0) - description = _("Slide Show"); + { + if (gnome_bg_changes_with_time (item->bg)) + description = _("Slide Show"); + else + description = _("Image"); + } else description = g_content_type_get_description (item->fileinfo->mime_type); + if (gnome_bg_changes_with_size (item->bg)) + size = g_strdup (_("multiple sizes")); + else + /* translators: x pixel(s) by y pixel(s) */ + size = g_strdup_printf ("%d %s by %d %s", + item->width, + ngettext ("pixel", "pixels", item->width), + item->height, + ngettext ("pixel", "pixels", item->height)); + /* translators: wallpaper name - * mime type, x pixel(s) by y pixel(s) + * mime type, size * Folder: /path/to/file */ item->description = g_markup_printf_escaped (_("%s\n" - "%s, %d %s by %d %s\n" + "%s, %s\n" "Folder: %s"), item->name, description, - item->width, - ngettext ("pixel", "pixels", item->width), - item->height, - ngettext ("pixel", "pixels", item->height), + size, dirname); + g_free (size); g_free (dirname); } } diff --git a/capplets/appearance/gnome-wp-item.h b/capplets/appearance/gnome-wp-item.h index 7a62cdb5f..63bdb69cb 100644 --- a/capplets/appearance/gnome-wp-item.h +++ b/capplets/appearance/gnome-wp-item.h @@ -72,6 +72,9 @@ GnomeWPItem * gnome_wp_item_new (const gchar *filename, void gnome_wp_item_free (GnomeWPItem *item); GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem *item, GnomeDesktopThumbnailFactory *thumbs); +GdkPixbuf * gnome_wp_item_get_frame_thumbnail (GnomeWPItem *item, + GnomeDesktopThumbnailFactory *thumbs, + gint frame); void gnome_wp_item_update (GnomeWPItem *item); void gnome_wp_item_update_description (GnomeWPItem *item); void gnome_wp_item_ensure_gnome_bg (GnomeWPItem *item); diff --git a/capplets/appearance/gnome-wp-xml.c b/capplets/appearance/gnome-wp-xml.c index 59d742b0e..9d2613d8a 100644 --- a/capplets/appearance/gnome-wp-xml.c +++ b/capplets/appearance/gnome-wp-xml.c @@ -237,9 +237,9 @@ static void gnome_wp_xml_load_xml (AppearanceData *data, wp->name = g_strdup (wp->fileinfo->name); } + gnome_wp_item_ensure_gnome_bg (wp); gnome_wp_item_update_description (wp); g_hash_table_insert (data->wp_hash, wp->filename, wp); - gnome_wp_item_ensure_gnome_bg (wp); } else { gnome_wp_item_free (wp); wp = NULL;