Index: exo/exo-icon-view.c =================================================================== --- exo/exo-icon-view.c (revision 22875) +++ exo/exo-icon-view.c (working copy) @@ -425,7 +425,7 @@ struct _ExoIconViewPrivate { gint width, height; - gint prev_width, prev_height; /* exo_icon_view_layout() contains a note about these ones */ + gint rows, cols; GtkSelectionMode selection_mode; @@ -1144,6 +1144,8 @@ icon_view->priv->width = 0; icon_view->priv->height = 0; + icon_view->priv->rows = 0; + icon_view->priv->cols = 0; icon_view->priv->selection_mode = GTK_SELECTION_SINGLE; icon_view->priv->pressed_button = -1; icon_view->priv->press_start_x = -1; @@ -2967,7 +2969,8 @@ gint item_width, gint row, gint *y, - gint *maximum_width) + gint *maximum_width, + gint max_cols) { ExoIconViewItem *item; gboolean rtl; @@ -3008,17 +3011,16 @@ item->area.width = colspan * item_width + (colspan - 1) * icon_view->priv->column_spacing; - current_width += item->area.width; + current_width += item->area.width + icon_view->priv->column_spacing + 2 * focus_width; if (G_LIKELY (items != first_item)) { if ((icon_view->priv->columns <= 0 && current_width > GTK_WIDGET (icon_view)->allocation.width) || - (icon_view->priv->columns > 0 && col >= icon_view->priv->columns)) + (icon_view->priv->columns > 0 && col >= icon_view->priv->columns) || + (max_cols > 0 && col >= max_cols)) break; } - current_width += icon_view->priv->column_spacing + 2 * focus_width; - item->area.y = *y + focus_width; item->area.x = rtl ? GTK_WIDGET (icon_view)->allocation.width - item->area.width - x : x; @@ -3067,7 +3069,8 @@ gint item_height, gint col, gint *x, - gint *maximum_height) + gint *maximum_height, + gint max_rows) { ExoIconViewItem *item; GList *items = first_item; @@ -3106,16 +3109,15 @@ item->area.height = rowspan * item_height + (rowspan - 1) * icon_view->priv->row_spacing; - current_height += item->area.height; + current_height += item->area.height + icon_view->priv->row_spacing + 2 * focus_width; if (G_LIKELY (items != first_item)) { - if (current_height >= GTK_WIDGET (icon_view)->allocation.height) + if (current_height >= GTK_WIDGET (icon_view)->allocation.height || + (max_rows > 0 && row >= max_rows)) break; } - current_height += icon_view->priv->row_spacing + 2 * focus_width; - item->area.y = y + focus_width; item->area.x = *x; @@ -3181,6 +3183,78 @@ +static gint +exo_icon_view_layout_rows (ExoIconView *icon_view, + gint item_width, + gint *y, + gint *maximum_width, + gint max_cols) +{ + GList *icons = icon_view->priv->items; + GList *items; + gint row = 0; + gint cols; + + *y = icon_view->priv->margin; + + do + { + icons = exo_icon_view_layout_single_row (icon_view, icons, + item_width, row, + y, maximum_width, max_cols); + + /* count the number of columns in the first row */ + if (row == 0) + for (items = icon_view->priv->items, cols = 0; items != icons; items = items->next, cols++); + + row++; + } + while (icons != NULL); + + *y += icon_view->priv->margin; + icon_view->priv->rows = row; + + return cols; +} + + + +static gint +exo_icon_view_layout_cols (ExoIconView *icon_view, + gint item_height, + gint *x, + gint *maximum_height, + gint max_rows) +{ + GList *icons = icon_view->priv->items; + GList *items; + gint col = 0; + gint rows; + + *x = icon_view->priv->margin; + + do + { + icons = exo_icon_view_layout_single_col (icon_view, icons, + item_height, col, + x, maximum_height, max_rows); + + /* count the number of rows in the first column */ + if (col == 0) + for (items = icon_view->priv->items, rows = 0; items != icons; items = items->next, rows++); + + col++; + } + while (icons != NULL); + + *x += icon_view->priv->margin; + icon_view->priv->cols = col; + + return rows; +} + + + static void exo_icon_view_layout (ExoIconView *icon_view) { @@ -3189,7 +3263,7 @@ gint maximum_width = 0; gint item_height; gint item_width; - gint row, col; + gint rows, cols; gint x, y; /* verify that we still have a valid model */ @@ -3210,26 +3284,20 @@ } } - icons = icon_view->priv->items; - y = icon_view->priv->margin; - row = 0; + cols = exo_icon_view_layout_rows (icon_view, item_width, &y, &maximum_width, 0); + + /* If, by adding another column, we increase the height of the icon view, thus forcing a + * vertical scrollbar to appear that would prevent the last column from being able to fit, + * we need to relayout the icons with one less column. + */ - do - { - icons = exo_icon_view_layout_single_row (icon_view, icons, - item_width, row, - &y, &maximum_width); - row++; - } - while (icons != NULL); - - if (maximum_width != icon_view->priv->width) - icon_view->priv->width = maximum_width; - - y += icon_view->priv->margin; - - if (y != icon_view->priv->height) - icon_view->priv->height = y; + if (cols == icon_view->priv->cols + 1 && y > GTK_WIDGET (icon_view)->allocation.height && + icon_view->priv->height <= GTK_WIDGET (icon_view)->allocation.height) + cols = exo_icon_view_layout_rows (icon_view, item_width, &y, &maximum_width, icon_view->priv->cols); + + icon_view->priv->width = maximum_width; + icon_view->priv->height = y; + icon_view->priv->cols = cols; } else { @@ -3241,42 +3309,20 @@ item_height = MAX (item_height, item->area.height); } - icons = icon_view->priv->items; - x = icon_view->priv->margin; - col = 0; + rows = exo_icon_view_layout_cols (icon_view, item_height, &x, &maximum_height, 0); - do - { - icons = exo_icon_view_layout_single_col (icon_view, icons, - item_height, col, - &x, &maximum_height); - col++; - } - while (icons != NULL); - - x += icon_view->priv->margin; - - /* We remember the previous height/width to make sure we don't run into an endless loop - * with GtkScrolledWindow trying to remove an automatic scrollbar, layouting the icons - * again, GtkScrolledWindow notices that the scrollbar is necessary, readds it, layouting - * again, GtkScrolledWindow tries to remove automatic scrollbar, and so on... GTK+ is really - * a mess sometimes. + /* If, by adding another row, we increase the width of the icon view, thus forcing a + * horizontal scrollbar to appear that would prevent the last row from being able to fit, + * we need to relayout the icons with one less row. */ - if ((maximum_height != icon_view->priv->height && maximum_height != icon_view->priv->prev_height) - || (x != icon_view->priv->width && x != icon_view->priv->prev_width)) - { - if (maximum_height != icon_view->priv->height) - { - icon_view->priv->prev_height = icon_view->priv->height; - icon_view->priv->height = maximum_height; - } - if (x != icon_view->priv->width) - { - icon_view->priv->prev_width = icon_view->priv->width; - icon_view->priv->width = x; - } - } + if (rows == icon_view->priv->rows + 1 && x > GTK_WIDGET (icon_view)->allocation.width && + icon_view->priv->width <= GTK_WIDGET (icon_view)->allocation.width) + rows = exo_icon_view_layout_cols (icon_view, item_height, &x, &maximum_height, icon_view->priv->rows); + + icon_view->priv->height = maximum_height; + icon_view->priv->width = x; + icon_view->priv->rows = rows; } exo_icon_view_set_adjustment_upper (icon_view->priv->hadjustment, icon_view->priv->width);