From d406bf96d4bb1191b05f1ddb374c2f57138c8d45 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 6 May 2012 00:51:14 +0200 Subject: [PATCH] iconview: Reduce complexity of sizing code Always assume max-columns and min-rows. The old approach was kinda insane. As an example, try to write an algorithm that optimizes the minimum size for infinite (take a reasonably large number like 2520) word-wrapped Monospace text cells containing the text "XXXXX XXX XXX XXXXX" (keep in mind that this is the easy problem, because it's assuming equal cell renderers). There's 4 ways to reasonably lay out this text: 19 glyphs (19x1): XXXXX XXX XXX XXXXX 18 glyphs (9x2): XXXXX XXX XXX XXXXX 21 glyphs (7x3): XXXXX XXX XXX XXXXX 20 glyphs (5x4): XXXXX XXX XXX XXXXX The best thing to do usually is using the 9x2 approach, but that's neither the one using the natural nor the one using the minimum size. As a side note, this does not include spacing and padding, which might also influence the decision. Nor does it include height-for-width considerations. Look at this table (numbers given in glyphs, not pixels, as for pixel-sizes it gets even more interesting): given best solution width columns sizing glyphs per cell 6 1 6x4 20 7 1 7x3 21 8 1 7x3 24 9 1 9x2 18 10 1/2 9x2/5x4 20 11 1/2 9x2/5x4 22 12 1/2 9x2/5x4 24 13 1/2 9x2/5x4 26 14 2 7x3 21 15 3 5x4 20 16 3 5x4 21.3 17 3 5x4 22.7 18 2 9x2 18 19 1/2 19x1/8x2 19 20 1/2/4 19x1/8x2/5x4 20 21 1-4 any 21 22 1-4 any 22 23 1-4 any 23 24 1-4 any 24 25 5 5x4 20 26 5 5x4 20.8 27 3 9x2 18 28 3 9x2 18.7 29 3 9x2 19.3 30 3/6 9x2/5x4 20 Now of course, nobody wants the number of columns to randomly change in inexplicable ways while they enlarge or shrink an iconview, so we not only have to optimize for smallest or other size measurements, but we also have to optimize for "most pleasing to the eye". And last but not least, I'd like to once again remind you - if you kept up until now - that this discussion was for identically-sized cells only. --- gtk/gtkiconview.c | 68 ++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index aeead95a9..f4cfe9a37 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -1463,16 +1463,31 @@ static void gtk_icon_view_compute_n_items_for_size (GtkIconView *icon_view, GtkOrientation orientation, gint size, - gint *min_columns, - gint *max_columns) + gint *min_items, + gint *max_items) { GtkIconViewPrivate *priv = icon_view->priv; int minimum, natural; if (priv->columns > 0) { - *min_columns = priv->columns; - *max_columns = priv->columns; + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (min_items) + *min_items = priv->columns; + if (max_items) + *max_items = priv->columns; + } + else + { + int n_items = gtk_icon_view_get_n_items (icon_view); + + if (min_items) + *min_items = (n_items + priv->columns - 1) / priv->columns; + if (max_items) + *max_items = (n_items + priv->columns - 1) / priv->columns; + } + return; } @@ -1493,14 +1508,21 @@ gtk_icon_view_compute_n_items_for_size (GtkIconView *icon_view, natural += priv->row_spacing; } - if (size <= minimum) - *max_columns = 1; - else - *max_columns = size / minimum; - if (size <= natural) - *min_columns = 1; - else - *min_columns = size / natural; + if (max_items) + { + if (size <= minimum) + *max_items = 1; + else + *max_items = size / minimum; + } + + if (min_items) + { + if (size <= natural) + *min_items = 1; + else + *min_items = size / natural; + } } static GtkSizeRequestMode @@ -1545,17 +1567,16 @@ gtk_icon_view_get_preferred_width_for_height (GtkWidget *widget, { GtkIconView *icon_view = GTK_ICON_VIEW (widget); GtkIconViewPrivate *priv = icon_view->priv; - int item_min, item_nat, min_rows, max_rows, n_items; + int item_min, item_nat, rows, n_items; - gtk_icon_view_compute_n_items_for_size (icon_view, GTK_ORIENTATION_VERTICAL, height, &min_rows, &max_rows); + gtk_icon_view_compute_n_items_for_size (icon_view, GTK_ORIENTATION_VERTICAL, height, &rows, NULL); n_items = gtk_icon_view_get_n_items (icon_view); height = height + priv->row_spacing - 2 * priv->margin; - gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_HORIZONTAL, height / max_rows - priv->row_spacing, &item_min, NULL); - *minimum = item_min * ((n_items + max_rows - 1) / max_rows); - gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_HORIZONTAL, height / min_rows - priv->row_spacing, NULL, &item_nat); - *natural = item_nat * ((n_items + min_rows - 1) / min_rows); + gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_HORIZONTAL, height / rows - priv->row_spacing, &item_min, &item_nat); + *minimum = item_min * ((n_items + rows - 1) / rows); + *natural = item_nat * ((n_items + rows - 1) / rows); *minimum += 2 * priv->margin; *natural += 2 * priv->margin; @@ -1598,17 +1619,16 @@ gtk_icon_view_get_preferred_height_for_width (GtkWidget *widget, { GtkIconView *icon_view = GTK_ICON_VIEW (widget); GtkIconViewPrivate *priv = icon_view->priv; - int item_min, item_nat, min_columns, max_columns, n_items; + int item_min, item_nat, columns, n_items; - gtk_icon_view_compute_n_items_for_size (icon_view, GTK_ORIENTATION_HORIZONTAL, width, &min_columns, &max_columns); + gtk_icon_view_compute_n_items_for_size (icon_view, GTK_ORIENTATION_HORIZONTAL, width, NULL, &columns); n_items = gtk_icon_view_get_n_items (icon_view); width = width + priv->column_spacing - 2 * priv->margin; - gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_VERTICAL, width / max_columns - priv->column_spacing, &item_min, NULL); - *minimum = (item_min + priv->row_spacing) * ((n_items + max_columns - 1) / max_columns) - priv->row_spacing; - gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_VERTICAL, width / min_columns - priv->column_spacing, NULL, &item_nat); - *natural = (item_nat + priv->row_spacing) * ((n_items + min_columns - 1) / min_columns) - priv->row_spacing; + gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_VERTICAL, width / columns - priv->column_spacing, &item_min, &item_nat); + *minimum = (item_min + priv->row_spacing) * ((n_items + columns - 1) / columns) - priv->row_spacing; + *natural = (item_nat + priv->row_spacing) * ((n_items + columns - 1) / columns) - priv->row_spacing; *minimum += 2 * priv->margin; *natural += 2 * priv->margin; -- 2.43.2