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);