I dediced to do some balancing computer hacking between two written tests. I'm attaching the results, namely a "compact icon view" - I'm not sure whether that name is verbose enough. It provides a column-wise icon layout with tiny icons and one-lined text descriptions next to the icons. It allows to display a few dozen icons at the same time, which may make it interesting for people with much data (like myself). To make review a little bit easier (it's a nightmare anyway), I made a patchset with 3 single patches: * nautilus-forced-icon-size.diff Actually force a particular size for the icons displayed in the icon container. * nautilus-compact-icon-layout.diff The heart of the vertical layout code. Copied from horizontal layout code, but simplified. * nautilus-compact-icon-non-core.diff [gzipped] changes to preferences, changes to FMIconView. Addition of new view IIDs, a new preferences dialog section (yet another "default zoom" preference for the new view). Caveats: The "Tight layout" (shorter labels) setting is currently shared with the old icon view, but I assume we won't need it anymore for the old view. It also made icons non grid-aligned which looks horrible. RTL is probably not supported properly ATM. Feedback appreciated. best regards, Christian Neumair -- Christian Neumair <cneumair gnome org>
Index: src/file-manager/fm-icon-container.c =================================================================== --- src/file-manager/fm-icon-container.c (Revision 13749) +++ src/file-manager/fm-icon-container.c (Arbeitskopie) @@ -82,14 +83,18 @@ fm_icon_container_get_icon_images (Nauti if (emblem_pixbufs != NULL) { emblem_size = nautilus_icon_get_emblem_size_for_icon_size (size); - - emblems_to_ignore = fm_directory_view_get_emblem_names_to_exclude - (FM_DIRECTORY_VIEW (icon_view)); - *emblem_pixbufs = nautilus_file_get_emblem_pixbufs (file, - emblem_size, - FALSE, - emblems_to_ignore); - g_strfreev (emblems_to_ignore); + /* don't return images larger than the actual icon size */ + emblem_size = MIN (emblem_size, size); + + if (emblem_size > 0) { + emblems_to_ignore = fm_directory_view_get_emblem_names_to_exclude + (FM_DIRECTORY_VIEW (icon_view)); + *emblem_pixbufs = nautilus_file_get_emblem_pixbufs (file, + emblem_size, + FALSE, + emblems_to_ignore); + g_strfreev (emblems_to_ignore); + } } *has_window_open = nautilus_file_has_open_window (file); @@ -321,6 +326,11 @@ fm_icon_container_get_icon_text (Nautilu *editable_text = nautilus_file_get_display_name (file); } + if (fm_icon_view_is_compact (icon_view)) { + *additional_text = NULL; + return; + } + if (NAUTILUS_IS_DESKTOP_ICON_FILE (file)) { /* Don't show the normal extra information for desktop icons, it doesn't * make sense. */ Index: libnautilus-private/nautilus-icon-canvas-item.c =================================================================== --- libnautilus-private/nautilus-icon-canvas-item.c (Revision 13749) +++ libnautilus-private/nautilus-icon-canvas-item.c (Arbeitskopie) @@ -62,6 +62,7 @@ #define MAX_TEXT_WIDTH_STANDARD 135 #define MAX_TEXT_WIDTH_TIGHTER 80 #define MAX_TEXT_WIDTH_BESIDE 90 +#define MAX_TEXT_WIDTH_BESIDE_TOP_TO_BOTTOM 300 /* Private part of the NautilusIconCanvasItem structure. */ struct NautilusIconCanvasItemDetails { @@ -1816,6 +1817,11 @@ nautilus_icon_canvas_item_draw (EelCanva (g_ascii_isdigit (*(p+1)) && \ g_ascii_isdigit (*(p+2)))) +#define IS_COMPACT_VIEW(container) \ + container->details->layout_mode == NAUTILUS_ICON_LAYOUT_T_B_L_R && \ + container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE + + static PangoLayout * create_label_layout (NautilusIconCanvasItem *item, const char *text) @@ -1872,6 +1878,9 @@ create_label_layout (NautilusIconCanvasI pango_layout_set_spacing (layout, LABEL_LINE_SPACING); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); + if (IS_COMPACT_VIEW (container)) { + pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); + } /* Create a font description */ if (container->details->font) { @@ -2424,14 +2433,19 @@ double nautilus_icon_canvas_item_get_max_text_width (NautilusIconCanvasItem *item) { EelCanvasItem *canvas_item; - + canvas_item = EEL_CANVAS_ITEM (item); if (nautilus_icon_container_is_tighter_layout (NAUTILUS_ICON_CONTAINER (canvas_item->canvas))) { return MAX_TEXT_WIDTH_TIGHTER * canvas_item->canvas->pixels_per_unit; } else { if (NAUTILUS_ICON_CONTAINER (canvas_item->canvas)->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) { - return MAX_TEXT_WIDTH_BESIDE * canvas_item->canvas->pixels_per_unit; + if (NAUTILUS_ICON_CONTAINER (canvas_item->canvas)->details->layout_mode == NAUTILUS_ICON_LAYOUT_T_B_L_R || + NAUTILUS_ICON_CONTAINER (canvas_item->canvas)->details->layout_mode == NAUTILUS_ICON_LAYOUT_T_B_R_L) { + return MAX_TEXT_WIDTH_BESIDE_TOP_TO_BOTTOM * canvas_item->canvas->pixels_per_unit; + } else { + return MAX_TEXT_WIDTH_BESIDE * canvas_item->canvas->pixels_per_unit; + } } else { return MAX_TEXT_WIDTH_STANDARD * canvas_item->canvas->pixels_per_unit; } Index: libnautilus-private/nautilus-icon-container.c =================================================================== --- libnautilus-private/nautilus-icon-container.c (Revision 13749) +++ libnautilus-private/nautilus-icon-container.c (Arbeitskopie) @@ -1000,6 +1000,40 @@ lay_down_one_line (NautilusIconContainer } static void +lay_down_one_column (NautilusIconContainer *container, + GList *line_start, + GList *line_end, + double x, + double y_start, + double y_iter, + GArray *positions) +{ + GList *p; + NautilusIcon *icon; + double y; + IconPositions *position; + int i; + + /* FIXME: Should layout differently when in RTL base mode */ + + /* Lay out the icons along the baseline. */ + y = y_start; + i = 0; + for (p = line_start; p != line_end; p = p->next) { + icon = p->data; + + position = &g_array_index (positions, IconPositions, i++); + + icon_set_position + (icon, + x + position->x_offset, + y + position->y_offset); + + y += y_iter; + } +} + +static void lay_down_icons_horizontal (NautilusIconContainer *container, GList *icons, double start_y) @@ -1160,6 +1194,118 @@ lay_down_icons_horizontal (NautilusIconC g_array_free (positions, TRUE); } +/* column-wise layout. At the moment, this only works with label-beside-icon (used by "Compact Icon View"). */ +static void +lay_down_icons_vertical (NautilusIconContainer *container, + GList *icons, + double start_y) +{ + GList *p, *line_start; + NautilusIcon *icon; + double canvas_width, x, canvas_height; + GArray *positions; + IconPositions *position; + EelDRect icon_bounds; + EelDRect text_bounds; + EelCanvasItem *item; + + double line_height; + + double max_height; + double max_height_with_borders; + double max_width; + + double max_text_width, max_icon_width; + double max_text_height, max_icon_height; + int height; + int i; + + g_assert (NAUTILUS_IS_ICON_CONTAINER (container)); + g_assert (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE); + + if (icons == NULL) { + return; + } + + positions = g_array_new (FALSE, FALSE, sizeof (IconPositions)); + + /* Lay out icons a column at a time. */ + canvas_width = CANVAS_WIDTH(container); + canvas_height = CANVAS_HEIGHT(container); + + max_icon_width = max_text_width = 0.0; + max_icon_height = max_text_height = 0.0; + + /* Would it be worth caching these bounds for the next loop? */ + for (p = icons; p != NULL; p = p->next) { + icon = p->data; + + icon_bounds = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); + max_icon_width = MAX (max_icon_width, ceil (icon_bounds.x1 - icon_bounds.x0)); + max_icon_height = MAX (max_icon_height, ceil (icon_bounds.y1 - icon_bounds.y0)); + + text_bounds = nautilus_icon_canvas_item_get_text_rectangle (icon->item); + max_text_width = MAX (max_text_width, ceil (text_bounds.x1 - text_bounds.x0)); + max_text_height = MAX (max_text_height, ceil (text_bounds.y1 - text_bounds.y0)); + } + + max_width = max_icon_width + max_text_width; + max_height = MAX (max_icon_height, max_text_height); + max_height_with_borders = ICON_PAD_TOP + max_height + ICON_PAD_BOTTOM; + + line_height = ICON_PAD_TOP; + line_start = icons; + x = 0; + i = 0; + + for (p = icons; p != NULL; p = p->next) { + icon = p->data; + + /* Get the width of the icon. */ + item = EEL_CANVAS_ITEM (icon->item); + + /* If this icon doesn't fit, it's time to lay out the column that's queued up. */ + if (line_start != p && line_height + max_height_with_borders + ICON_PAD_BOTTOM > canvas_height ) { + x += ICON_PAD_LEFT; + + lay_down_one_column (container, line_start, p, x, CONTAINER_PAD_TOP, max_height_with_borders, positions); + + /* Advance to next column. */ + x += max_width + ICON_PAD_RIGHT; + + line_height = ICON_PAD_TOP; + line_start = p; + i = 0; + } + + g_array_set_size (positions, i + 1); + position = &g_array_index (positions, IconPositions, i++); + position->width = max_width; + position->height = max_height; + position->y_offset = ICON_PAD_TOP; + position->x_offset = ICON_PAD_LEFT; + + icon_bounds = nautilus_icon_canvas_item_get_icon_rectangle (icon->item); + text_bounds = nautilus_icon_canvas_item_get_text_rectangle (icon->item); + + position->x_offset += max_icon_width - ceil (icon_bounds.x1 - icon_bounds.x0); + + height = MAX (ceil (icon_bounds.y1 - icon_bounds.y0), ceil(text_bounds.y1 - text_bounds.y0)); + position->y_offset += (max_height - height) / 2; + + /* Add this icon. */ + line_height += max_height_with_borders; + } + + /* Lay down that last column of icons. */ + if (line_start != NULL) { + x += ICON_PAD_LEFT; + lay_down_one_column (container, line_start, NULL, x, CONTAINER_PAD_TOP, max_height_with_borders, positions); + } + + g_array_free (positions, TRUE); +} + static void snap_position (NautilusIconContainer *container, NautilusIcon *icon, @@ -1487,7 +1633,7 @@ nautilus_icon_container_set_rtl_position } static void -lay_down_icons_vertical (NautilusIconContainer *container, GList *icons) +lay_down_icons_vertical_desktop (NautilusIconContainer *container, GList *icons) { GList *p, *placed_icons, *unplaced_icons; int total, new_length, placed; @@ -1668,7 +1814,11 @@ lay_down_icons (NautilusIconContainer *c case NAUTILUS_ICON_LAYOUT_T_B_L_R: case NAUTILUS_ICON_LAYOUT_T_B_R_L: - lay_down_icons_vertical (container, icons); + if (nautilus_icon_container_get_is_desktop (container)) { + lay_down_icons_vertical_desktop (container, icons); + } else { + lay_down_icons_vertical (container, icons, start_y); + } break; default: @@ -3147,6 +3297,10 @@ size_allocate (GtkWidget *widget, need_layout_redone = TRUE; } + if (allocation->height != widget->allocation.height) { + need_layout_redone = TRUE; + } + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); container->details->has_been_allocated = TRUE; @@ -5758,9 +5912,14 @@ nautilus_icon_container_update_icon (Nau /* compute the maximum size based on the scale factor */ min_image_size = MINIMUM_IMAGE_SIZE * EEL_CANVAS (container)->pixels_per_unit; max_image_size = MAX (MAXIMUM_IMAGE_SIZE * EEL_CANVAS (container)->pixels_per_unit, NAUTILUS_ICON_MAXIMUM_SIZE); - + /* Get the appropriate images for the file. */ - icon_get_size (container, icon, &icon_size); + if (container->details->forced_icon_size > 0) { + icon_size = container->details->forced_icon_size; + } else { + icon_get_size (container, icon, &icon_size); + } + icon_size = MAX (icon_size, min_image_size); icon_size = MIN (icon_size, max_image_size); @@ -6762,6 +6924,7 @@ nautilus_icon_container_set_layout_mode g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); container->details->layout_mode = mode; + invalidate_label_sizes (container); redo_layout (container); @@ -6981,7 +7144,11 @@ nautilus_icon_container_start_renaming_s eel_editable_label_set_line_wrap (EEL_EDITABLE_LABEL (details->rename_widget), TRUE); eel_editable_label_set_line_wrap_mode (EEL_EDITABLE_LABEL (details->rename_widget), PANGO_WRAP_WORD_CHAR); eel_editable_label_set_draw_outline (EEL_EDITABLE_LABEL (details->rename_widget), TRUE); - eel_editable_label_set_justify (EEL_EDITABLE_LABEL (details->rename_widget), GTK_JUSTIFY_CENTER); + + if (details->label_position != NAUTILUS_ICON_LABEL_POSITION_BESIDE) { + eel_editable_label_set_justify (EEL_EDITABLE_LABEL (details->rename_widget), GTK_JUSTIFY_CENTER); + } + gtk_misc_set_padding (GTK_MISC (details->rename_widget), 1, 1); gtk_layout_put (GTK_LAYOUT (container), details->rename_widget, 0, 0);
Attachment:
nautilus-compact-icon-non-core.diff.gz
Description: GNU Zip compressed data
Index: libnautilus-private/nautilus-icon-private.h =================================================================== --- libnautilus-private/nautilus-icon-private.h (Revision 13749) +++ libnautilus-private/nautilus-icon-private.h (Arbeitskopie) @@ -231,6 +231,9 @@ struct NautilusIconContainerDetails { /* Label position */ NautilusIconLabelPosition label_position; + /* Forced icon size, iff greater than 0 */ + int forced_icon_size; + /* Should the container keep icons aligned to a grid */ gboolean keep_aligned; Index: libnautilus-private/nautilus-icon-container.c =================================================================== --- libnautilus-private/nautilus-icon-container.c (Revision 13749) +++ libnautilus-private/nautilus-icon-container.c (Arbeitskopie) @@ -5777,7 +5777,10 @@ nautilus_icon_container_update_icon (Nau &has_open_window); - pixbuf = nautilus_icon_info_get_pixbuf (icon_info); + if (container->details->forced_icon_size > 0) + pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size); + else + pixbuf = nautilus_icon_info_get_pixbuf (icon_info); nautilus_icon_info_get_attach_points (icon_info, &attach_points, &n_attach_points); has_embedded_text_rect = nautilus_icon_info_get_embedded_rect (icon_info, &embedded_text_rect); @@ -7550,6 +7553,15 @@ nautilus_icon_container_set_allow_moves container->details->drag_allow_moves = allow_moves; } +void +nautilus_icon_container_set_forced_icon_size (NautilusIconContainer *container, + int forced_icon_size) +{ + g_return_if_fail (NAUTILUS_IS_ICON_CONTAINER (container)); + + container->details->forced_icon_size = forced_icon_size; +} + /* NautilusIconContainerAccessible */ static NautilusIconContainerAccessiblePrivate * Index: libnautilus-private/nautilus-icon-container.h =================================================================== --- libnautilus-private/nautilus-icon-container.h (Revision 13749) +++ libnautilus-private/nautilus-icon-container.h (Arbeitskopie) @@ -301,6 +301,8 @@ char* nautilus_icon_containe gboolean nautilus_icon_container_get_allow_moves (NautilusIconContainer *container); void nautilus_icon_container_set_allow_moves (NautilusIconContainer *container, gboolean allow_moves); +void nautilus_icon_container_set_forced_icon_size (NautilusIconContainer *container, + int forced_icon_size); gboolean nautilus_icon_container_is_layout_rtl (NautilusIconContainer *container);