Index: thunar/thunar-statusbar.c =================================================================== --- thunar/thunar-statusbar.c (revision 19014) +++ thunar/thunar-statusbar.c (working copy) @@ -455,7 +455,7 @@ /* draw the icon if we have a file */ if (G_LIKELY (statusbar_icon->file != NULL)) { - icon = thunar_icon_factory_load_file_icon (statusbar_icon->icon_factory, statusbar_icon->file, THUNAR_FILE_ICON_STATE_DEFAULT, 16); + icon = thunar_icon_factory_load_file_icon (statusbar_icon->icon_factory, statusbar_icon->file, THUNAR_FILE_ICON_STATE_DEFAULT, 16, -1, -1); /* use the lucent variant if we're currently loading */ if (thunar_statusbar_icon_get_loading (statusbar_icon)) @@ -521,7 +521,7 @@ /* setup the drag source icon */ if (G_LIKELY (statusbar_icon->file != NULL)) { - icon = thunar_icon_factory_load_file_icon (statusbar_icon->icon_factory, statusbar_icon->file, THUNAR_FILE_ICON_STATE_DEFAULT, 24); + icon = thunar_icon_factory_load_file_icon (statusbar_icon->icon_factory, statusbar_icon->file, THUNAR_FILE_ICON_STATE_DEFAULT, 24, -1, -1); gtk_drag_source_set_icon_pixbuf (widget, icon); g_object_unref (G_OBJECT (icon)); } Index: thunar/thunar-shortcuts-model.c =================================================================== --- thunar/thunar-shortcuts-model.c (revision 19014) +++ thunar/thunar-shortcuts-model.c (working copy) @@ -509,7 +509,7 @@ } else if (G_LIKELY (shortcut->file != NULL)) { - icon = thunar_icon_factory_load_file_icon (icon_factory, shortcut->file, THUNAR_FILE_ICON_STATE_DEFAULT, 32); + icon = thunar_icon_factory_load_file_icon (icon_factory, shortcut->file, THUNAR_FILE_ICON_STATE_DEFAULT, 32, -1, -1); } if (G_LIKELY (icon != NULL)) g_value_take_object (value, icon); Index: thunar/thunar-location-buttons.c =================================================================== --- thunar/thunar-location-buttons.c (revision 19014) +++ thunar/thunar-location-buttons.c (working copy) @@ -755,7 +755,7 @@ { file = g_object_get_qdata (G_OBJECT (lp->data), thunar_file_quark); children = gtk_container_get_children (GTK_CONTAINER (GTK_BIN (lp->data)->child)); - icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, size); + icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, size, -1, -1); gtk_drag_source_set_icon_pixbuf (GTK_WIDGET (lp->data), icon); gtk_image_set_from_pixbuf (GTK_IMAGE (children->data), icon); g_object_unref (G_OBJECT (icon)); @@ -892,7 +892,7 @@ gtk_widget_show (image); icon_factory = thunar_icon_factory_get_default (); - icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, size); + icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, size, -1, -1); gtk_drag_source_set_icon_pixbuf (button, icon); gtk_image_set_from_pixbuf (GTK_IMAGE (image), icon); g_object_unref (G_OBJECT (icon_factory)); Index: thunar/thunar-icon-renderer.c =================================================================== --- thunar/thunar-icon-renderer.c (revision 19014) +++ thunar/thunar-icon-renderer.c (working copy) @@ -40,31 +40,43 @@ -static void thunar_icon_renderer_class_init (ThunarIconRendererClass *klass); -static void thunar_icon_renderer_init (ThunarIconRenderer *icon_renderer); -static void thunar_icon_renderer_finalize (GObject *object); -static void thunar_icon_renderer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_icon_renderer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void thunar_icon_renderer_get_size (GtkCellRenderer *renderer, - GtkWidget *widget, - GdkRectangle *rectangle, - gint *x_offset, - gint *y_offset, - gint *width, - gint *height); -static void thunar_icon_renderer_render (GtkCellRenderer *renderer, - GdkWindow *window, - GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, - GtkCellRendererState flags); +static void thunar_icon_renderer_class_init (ThunarIconRendererClass *klass); +static void thunar_icon_renderer_lazy_cell_renderer_init (ExoLazyCellRendererIface *iface); +static void thunar_icon_renderer_init (ThunarIconRenderer *icon_renderer); +static void thunar_icon_renderer_finalize (GObject *object); +static void thunar_icon_renderer_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_icon_renderer_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void thunar_icon_renderer_get_size (GtkCellRenderer *renderer, + GtkWidget *widget, + GdkRectangle *rectangle, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height); +static void thunar_icon_renderer_render (GtkCellRenderer *renderer, + GdkWindow *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags); +static gboolean thunar_icon_renderer_render_and_resize (ExoLazyCellRenderer *lazy_cell_renderer, + GdkWindow *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height); @@ -110,7 +122,15 @@ NULL, }; + static const GInterfaceInfo lazy_cell_renderer_info = + { + (GInterfaceInitFunc) thunar_icon_renderer_lazy_cell_renderer_init, + NULL, + NULL, + }; + type = g_type_register_static (GTK_TYPE_CELL_RENDERER, I_("ThunarIconRenderer"), &info, 0); + g_type_add_interface_static (type, EXO_TYPE_LAZY_CELL_RENDERER, &lazy_cell_renderer_info); } return type; @@ -196,6 +216,14 @@ static void +thunar_icon_renderer_lazy_cell_renderer_init (ExoLazyCellRendererIface *iface) +{ + iface->render_and_resize = thunar_icon_renderer_render_and_resize; +} + + + +static void thunar_icon_renderer_init (ThunarIconRenderer *icon_renderer) { icon_renderer->size = 24; @@ -349,9 +377,29 @@ GdkRectangle *expose_area, GtkCellRendererState flags) { + thunar_icon_renderer_render_and_resize (EXO_LAZY_CELL_RENDERER (renderer), window, + widget, background_area, cell_area, + expose_area, flags, NULL, NULL, NULL, NULL); +} + + + +static gboolean +thunar_icon_renderer_render_and_resize (ExoLazyCellRenderer *lazy_cell_renderer, + GdkWindow *window, + GtkWidget *widget, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *expose_area, + GtkCellRendererState flags, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) +{ ThunarClipboardManager *clipboard; ThunarFileIconState icon_state; - ThunarIconRenderer *icon_renderer = THUNAR_ICON_RENDERER (renderer); + ThunarIconRenderer *icon_renderer = THUNAR_ICON_RENDERER (lazy_cell_renderer); ThunarIconFactory *icon_factory; GtkIconTheme *icon_theme; GdkRectangle emblem_area; @@ -367,7 +415,7 @@ gint position; if (G_UNLIKELY (icon_renderer->file == NULL)) - return; + return FALSE; /* determine the icon state */ icon_state = (icon_renderer->drop_file != icon_renderer->file) @@ -377,11 +425,13 @@ /* load the main icon */ icon_theme = gtk_icon_theme_get_for_screen (gdk_drawable_get_screen (window)); icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); - icon = thunar_icon_factory_load_file_icon (icon_factory, icon_renderer->file, icon_state, icon_renderer->size); + icon = thunar_icon_factory_load_file_icon (icon_factory, icon_renderer->file, icon_state, icon_renderer->size, + cell_area->width - 2 * GTK_CELL_RENDERER (icon_renderer)->xpad, + cell_area->height - 2 * GTK_CELL_RENDERER (icon_renderer)->ypad); if (G_UNLIKELY (icon == NULL)) { g_object_unref (G_OBJECT (icon_factory)); - return; + return FALSE; } /* pre-light the item if we're dragging about it */ @@ -393,6 +443,8 @@ icon_area.height = gdk_pixbuf_get_height (icon); /* scale down the icon on-demand */ +#if 0 +#if 1 if (G_UNLIKELY (icon_area.width > cell_area->width || icon_area.height > cell_area->height)) { temp = exo_gdk_pixbuf_scale_ratio (icon, icon_renderer->size); @@ -402,10 +454,42 @@ icon_area.width = gdk_pixbuf_get_width (icon); icon_area.height = gdk_pixbuf_get_height (icon); } +#else + if (G_UNLIKELY (icon_area.width > cell_area->width - 2 * GTK_CELL_RENDERER (icon_renderer)->xpad + || icon_area.height > cell_area->height - 2 * GTK_CELL_RENDERER (icon_renderer)->ypad)) + { + if ((gdouble) icon_area.height * (cell_area->width - 2 * GTK_CELL_RENDERER (icon_renderer)->xpad) + > (gdouble) icon_area.width * (cell_area->height - 2 * GTK_CELL_RENDERER (icon_renderer)->ypad)) + { + icon_area.width = 0.5 + (gdouble) icon_area.width * (gdouble) (cell_area->height - 2 * GTK_CELL_RENDERER (icon_renderer)->ypad) / (gdouble) icon_area.height; + icon_area.height = cell_area->height - 2 * GTK_CELL_RENDERER (icon_renderer)->ypad; + } + else + { + icon_area.height = 0.5 + (gdouble) icon_area.height * (gdouble) (cell_area->width - 2 * GTK_CELL_RENDERER (icon_renderer)->ypad) / (gdouble) icon_area.width; + icon_area.width = cell_area->width - 2 * GTK_CELL_RENDERER (icon_renderer)->xpad; + } + temp = gdk_pixbuf_scale_simple (icon, icon_area.width, icon_area.height, GDK_INTERP_BILINEAR); + g_object_unref (G_OBJECT (icon)); + icon = temp; + } +#endif +#endif + icon_area.x = cell_area->x + (cell_area->width - icon_area.width) / 2; icon_area.y = cell_area->y + (cell_area->height - icon_area.height) / 2; + /* tell the view about the new dimensions */ + if (G_LIKELY (x_offset != NULL)) + *x_offset = icon_area.x - cell_area->x; + if (G_LIKELY (y_offset != NULL)) + *y_offset = icon_area.y - cell_area->y; + if (G_LIKELY (width != NULL)) + *width = icon_area.width + 2 * GTK_CELL_RENDERER (icon_renderer)->xpad; + if (G_LIKELY (height != NULL)) + *height = icon_area.height + 2 * GTK_CELL_RENDERER (icon_renderer)->ypad; + /* check whether the icon is affected by the expose event */ if (gdk_rectangle_intersect (expose_area, &icon_area, &draw_area)) { @@ -537,6 +621,8 @@ /* release our reference on the icon factory */ g_object_unref (G_OBJECT (icon_factory)); + + return TRUE; } Index: thunar/thunar-properties-dialog.c =================================================================== --- thunar/thunar-properties-dialog.c (revision 19014) +++ thunar/thunar-properties-dialog.c (working copy) @@ -589,7 +589,7 @@ icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); /* update the icon */ - icon = thunar_icon_factory_load_file_icon (icon_factory, dialog->file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); + icon = thunar_icon_factory_load_file_icon (icon_factory, dialog->file, THUNAR_FILE_ICON_STATE_DEFAULT, 48, -1, -1); gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->icon_image), icon); gtk_window_set_icon (GTK_WINDOW (dialog), icon); if (G_LIKELY (icon != NULL)) Index: thunar/thunar-icon-factory.c =================================================================== --- thunar/thunar-icon-factory.c (revision 19014) +++ thunar/thunar-icon-factory.c (working copy) @@ -78,10 +78,13 @@ static void thunar_icon_factory_sweep_timer_destroy (gpointer user_data); static GdkPixbuf *thunar_icon_factory_load_from_file (ThunarIconFactory *factory, const gchar *path, - gint size); + gint max_width, + gint max_height); static GdkPixbuf *thunar_icon_factory_lookup_icon (ThunarIconFactory *factory, const gchar *name, gint size, + gint max_width, + gint max_height, gboolean wants_default); static void thunar_icon_factory_mark_recently_used (ThunarIconFactory *factory, GdkPixbuf *pixbuf); @@ -453,13 +456,18 @@ static GdkPixbuf* thunar_icon_factory_load_from_file (ThunarIconFactory *factory, const gchar *path, - gint size) + gint max_width, + gint max_height) { GdkPixbuf *pixbuf; GdkPixbuf *tmp; + gboolean need_frame; gint width; gint height; + g_return_val_if_fail (max_width > 0, NULL); + g_return_val_if_fail (max_height > 0, NULL); + /* try to load the image from the file */ pixbuf = gdk_pixbuf_new_from_file (path, NULL); if (G_LIKELY (pixbuf != NULL)) @@ -468,27 +476,40 @@ width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); - /* add a frame around thumbnail (large) images */ - if (strstr (path, G_DIR_SEPARATOR_S ".thumbnails" G_DIR_SEPARATOR_S) != NULL - && thumbnail_needs_frame (pixbuf, width, height)) + /* check if we need to add a thumbnail frame (for large thumbnails only) */ + need_frame = (strstr (path, G_DIR_SEPARATOR_S ".thumbnails" G_DIR_SEPARATOR_S) != NULL + && thumbnail_needs_frame (pixbuf, width, height)); + + if (G_LIKELY (need_frame)) { - /* perform the scaling first (if required) */ - if (G_LIKELY (width > size || height > size)) + max_width = MAX (max_width - (3 + 6), 1); + max_height = MAX (max_height - (3 + 6), 1); + } + + /* perform the scaling first (if required) */ + if (G_LIKELY (width > max_width || height > max_height)) + { + if (height * max_width > width * max_height) { - tmp = exo_gdk_pixbuf_scale_ratio (pixbuf, size); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = tmp; + width = 0.5 + (width * max_height) / (gdouble) height; + height = max_height; } + else + { + width = max_width; + height = 0.5 + (height * max_width) / (gdouble) width; + } - /* add the frame */ - tmp = thunar_gdk_pixbuf_frame (pixbuf, factory->thumbnail_frame, 3, 3, 6, 6); + tmp = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR); g_object_unref (G_OBJECT (pixbuf)); pixbuf = tmp; } - else if (G_LIKELY (width > size || height > size)) + + /* add a frame around thumbnail (large) images */ + if (G_LIKELY (need_frame)) { - /* scale down the non-thumbnailed icon */ - tmp = exo_gdk_pixbuf_scale_ratio (pixbuf, size); + /* add the frame */ + tmp = thunar_gdk_pixbuf_frame (pixbuf, factory->thumbnail_frame, 3, 3, 6, 6); g_object_unref (G_OBJECT (pixbuf)); pixbuf = tmp; } @@ -503,6 +524,8 @@ thunar_icon_factory_lookup_icon (ThunarIconFactory *factory, const gchar *name, gint size, + gint max_width, + gint max_height, gboolean wants_default) { ThunarIconKey lookup_key; @@ -524,7 +547,9 @@ /* check if we have to load a file instead of a themed icon */ if (G_UNLIKELY (g_path_is_absolute (name))) { - pixbuf = thunar_icon_factory_load_from_file (factory, name, size); + pixbuf = thunar_icon_factory_load_from_file (factory, name, + (max_width < 0) ? size : max_width, + (max_height < 0) ? size : max_height); } else { @@ -683,7 +708,7 @@ * @icon_theme and returns it. * * You need to explicitly free the returned #ThunarIconFactory object - * using #g_object_unref() when you are done with it. + * using g_object_unref() when you are done with it. * * Return value: the #ThunarIconFactory for @icon_theme. **/ @@ -782,7 +807,7 @@ } /* lookup the icon */ - return thunar_icon_factory_lookup_icon (factory, name, size, wants_default); + return thunar_icon_factory_lookup_icon (factory, name, size, -1, -1, wants_default); } @@ -793,6 +818,8 @@ * @file : a #ThunarFile. * @icon_state : the desired icon state. * @icon_size : the desired icon size. + * @max_width : max thumbnail width or -1 to use @icon_size. + * @max_height : max thumbnail height or -1 to use @icon_size. * * The caller is responsible to free the returned object using * g_object_unref() when no longer needed. @@ -803,7 +830,9 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, ThunarFile *file, ThunarFileIconState icon_state, - gint icon_size) + gint icon_size, + gint max_width, + gint max_height) { ThunarFileThumbState thumb_state; ThunarVfsInfo *info; @@ -811,6 +840,8 @@ GdkPixbuf *icon; gchar *thumb_path; + g_return_val_if_fail (max_height == -1 || max_height > 0, NULL); + g_return_val_if_fail (max_width == -1 || max_width > 0, NULL); g_return_val_if_fail (THUNAR_IS_ICON_FACTORY (factory), NULL); g_return_val_if_fail (THUNAR_IS_FILE (file), NULL); g_return_val_if_fail (icon_size > 0, NULL); @@ -820,7 +851,7 @@ if (G_UNLIKELY (icon_name != NULL)) { /* try to load the icon */ - icon = thunar_icon_factory_lookup_icon (factory, icon_name, icon_size, FALSE); + icon = thunar_icon_factory_lookup_icon (factory, icon_name, icon_size, -1, -1, FALSE); if (G_LIKELY (icon != NULL)) return icon; } @@ -871,7 +902,7 @@ if (G_LIKELY (thumb_path != NULL)) { // FIXME: Check mtime and URI for the returned icon - icon = thunar_icon_factory_lookup_icon (factory, thumb_path, icon_size, FALSE); + icon = thunar_icon_factory_lookup_icon (factory, thumb_path, icon_size, max_width, max_height, FALSE); if (G_LIKELY (icon != NULL)) return icon; } @@ -881,7 +912,7 @@ if (G_UNLIKELY (thumb_state == THUNAR_FILE_THUMB_STATE_LOADING)) { /* check if the icon theme supports the loading icon */ - icon = thunar_icon_factory_lookup_icon (factory, "gnome-fs-loading-icon", icon_size, FALSE); + icon = thunar_icon_factory_lookup_icon (factory, "gnome-fs-loading-icon", icon_size, -1, -1, FALSE); if (G_LIKELY (icon != NULL)) return icon; } Index: thunar/thunar-icon-factory.h =================================================================== --- thunar/thunar-icon-factory.h (revision 19014) +++ thunar/thunar-icon-factory.h (working copy) @@ -78,7 +78,9 @@ GdkPixbuf *thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, ThunarFile *file, ThunarFileIconState icon_state, - gint icon_size); + gint icon_size, + gint max_width, + gint max_height); G_END_DECLS; Index: thunar/thunar-window.c =================================================================== --- thunar/thunar-window.c (revision 19014) +++ thunar/thunar-window.c (working copy) @@ -1066,7 +1066,7 @@ g_return_if_fail (window->current_directory == current_directory); /* set window title and icon */ - icon = thunar_icon_factory_load_file_icon (window->icon_factory, current_directory, THUNAR_FILE_ICON_STATE_DEFAULT, 48); + icon = thunar_icon_factory_load_file_icon (window->icon_factory, current_directory, THUNAR_FILE_ICON_STATE_DEFAULT, 48, -1, -1); gtk_window_set_title (GTK_WINDOW (window), thunar_file_get_special_name (current_directory)); gtk_window_set_icon (GTK_WINDOW (window), icon); g_object_unref (G_OBJECT (icon)); Index: thunar/thunar-standard-view.c =================================================================== --- thunar/thunar-standard-view.c (revision 19014) +++ thunar/thunar-standard-view.c (working copy) @@ -2051,7 +2051,7 @@ { /* generate an icon based on that file */ g_object_get (G_OBJECT (standard_view->icon_renderer), "size", &size, NULL); - icon = thunar_icon_factory_load_file_icon (standard_view->icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, size); + icon = thunar_icon_factory_load_file_icon (standard_view->icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, size, -1, -1); gtk_drag_set_icon_pixbuf (context, icon, 0, 0); g_object_unref (G_OBJECT (icon)); Index: thunar/Makefile.am =================================================================== --- thunar/Makefile.am (revision 19014) +++ thunar/Makefile.am (working copy) @@ -44,12 +44,6 @@ thunar-emblem-chooser.h \ thunar-fallback-icon.c \ thunar-fallback-icon.h \ - thunar-shortcuts-model.c \ - thunar-shortcuts-model.h \ - thunar-shortcuts-pane.c \ - thunar-shortcuts-pane.h \ - thunar-shortcuts-view.c \ - thunar-shortcuts-view.h \ thunar-file.c \ thunar-file.h \ thunar-folder.c \ @@ -97,6 +91,12 @@ thunar-progress-dialog.h \ thunar-properties-dialog.c \ thunar-properties-dialog.h \ + thunar-shortcuts-model.c \ + thunar-shortcuts-model.h \ + thunar-shortcuts-pane.c \ + thunar-shortcuts-pane.h \ + thunar-shortcuts-view.c \ + thunar-shortcuts-view.h \ thunar-side-pane.c \ thunar-side-pane.h \ thunar-standard-view.c \ Index: thunar/thunar-path-entry.c =================================================================== --- thunar/thunar-path-entry.c (revision 19014) +++ thunar/thunar-path-entry.c (working copy) @@ -477,7 +477,7 @@ if (path_entry->current_file == NULL) icon = gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_SMALL_TOOLBAR, "path_entry"); else - icon = thunar_icon_factory_load_file_icon (path_entry->icon_factory, path_entry->current_file, THUNAR_FILE_ICON_STATE_DEFAULT, icon_size); + icon = thunar_icon_factory_load_file_icon (path_entry->icon_factory, path_entry->current_file, THUNAR_FILE_ICON_STATE_DEFAULT, icon_size, -1, -1); if (G_LIKELY (icon != NULL)) { @@ -563,7 +563,8 @@ /* setup the drag icon (atleast 24px) */ gtk_widget_style_get (widget, "icon-size", &size, NULL); - icon = thunar_icon_factory_load_file_icon (path_entry->icon_factory, path_entry->current_file, THUNAR_FILE_ICON_STATE_DEFAULT, MAX (size, 24)); + icon = thunar_icon_factory_load_file_icon (path_entry->icon_factory, path_entry->current_file, + THUNAR_FILE_ICON_STATE_DEFAULT, MAX (size, 24), -1, -1); if (G_LIKELY (icon != NULL)) { gtk_drag_set_icon_pixbuf (context, icon, 0, 0);