Re: align layout patch



Hello,

Here is an updated version of this patch.  The previous version did not
handle the case where the canvas width was smaller than at least one
icon width. 

-- 
 "There has grown in the minds of certain groups in this country the
idea that just because
a man or corporation has made a profit out of the public for a number of
years, the
government and the courts are charged with guaranteeing such profit in
the future, even in
the face of changing circumstances and contrary to public interest. This
strange doctrine
is supported by neither statue or common law. Neither corporations or
individuals have the
right to come into court and ask that the clock of history be stopped,
or turned back."

-Robert Heinlein, Life Line, 1939
Index: nautilus/libnautilus-private/nautilus-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-container.c,v
retrieving revision 1.294
diff -u -b -B -p -u -r1.294 nautilus-icon-container.c
--- nautilus/libnautilus-private/nautilus-icon-container.c	15 Aug 2002 14:47:25 -0000	1.294
+++ nautilus/libnautilus-private/nautilus-icon-container.c	28 Aug 2002 00:51:36 -0000
@@ -797,78 +797,107 @@ get_icon_space_width (NautilusIconContai
 
 typedef struct {
 	double width;
+	double height_above;
+	double height_below;
 	double x_offset;
 	double y_offset;
-} IconPositions;
+} IconPositionInfo;
 
 static void
-lay_down_one_line (NautilusIconContainer *container,
-		   GList *line_start,
-		   GList *line_end,
-		   double y,
-		   GArray *positions)
+lay_down_all_lines (GList *icons,
+		    GQueue *positions,
+		    GQueue *rows,
+		    GArray *columns,
+		    double extra_columns_width)
 {
-	GList *p;
-	NautilusIcon *icon;
-	double x;
-	IconPositions *position;
-	int i;
+	GList *icons_list, *positions_list, *rows_list;
+	IconPositionInfo *position;
+	double line_width, *column_width, *baseline;
+	unsigned int columns_index;
 
 	/* FIXME: Should layout differently when in RTL base mode */
 
-	/* Lay out the icons along the baseline. */
-	x = 0;
-	i = 0;
-	for (p = line_start; p != line_end; p = p->next) {
-		icon = p->data;
+	/* Lay out the icons along the baseline and columns's centers. */
+	icons_list = icons;
+	while ((rows_list = g_queue_pop_head_link (rows)) != NULL) {
+		baseline = rows_list->data;
 
-		position = &g_array_index (positions, IconPositions, i++);
+		line_width    = 0;
+		columns_index = 0;
+		while (icons_list != NULL && columns_index < columns->len) {
+			positions_list = g_queue_pop_head_link (positions);
+			position       = positions_list->data;
+			column_width   = &g_array_index (columns, double, columns_index);		
 
 		icon_set_position
-			(icon,
-			 x + position->x_offset,
-			 y + position->y_offset);
+				((NautilusIcon*) icons_list->data,
+				 (*column_width + extra_columns_width) / 2 
+				 - position->x_offset + line_width,
+				 *baseline + position->y_offset);
+			
+			/* next column and icon */
+			line_width += *column_width + extra_columns_width;	
+			++columns_index;
+			icons_list = icons_list->next;	
 
-		x += position->width;
+			g_list_free_1 (positions_list);
+			g_free (position);
+		}
+		g_list_free_1 (rows_list);
+		g_free (baseline);
 	}
 }
 
 
 static void
-lay_down_icons_horizontal (NautilusIconContainer *container,
+lay_down_icons_align (NautilusIconContainer *container,
 			   GList *icons,
 			   double start_y)
 {
-	GList *p, *line_start;
+	GList *icons_list, *positions_list, *rows_list;
+	GQueue *positions, *rows;
+	GArray *columns;
+	IconPositionInfo *position;
 	NautilusIcon *icon;
-	double canvas_width, line_width, space_width, y;
-	GArray *positions;
-	IconPositions *position;
+	GnomeCanvasItem *item;
 	ArtDRect bounds;
 	ArtDRect icon_bounds;
-	GnomeCanvasItem *item;
-	double max_height_above, max_height_below;
+	double canvas_width, line_width, space_width,  extra_columns_width;
+	double  y, *baseline; 	
 	double height_above, height_below;
-	int i;
+	double max_height_above, max_height_below, *max_column_width;
+	unsigned int columns_index, rows_index, positions_index;
+	gboolean find_max_number_of_columns = TRUE;
 
+	g_return_if_fail (icons != NULL);
 	g_assert (NAUTILUS_IS_ICON_CONTAINER (container));
 
-	positions = g_array_new (FALSE, FALSE, sizeof (IconPositions));
+	positions = g_queue_new ();
+	rows      = g_queue_new ();
+	columns   = g_array_new (FALSE, TRUE, sizeof (double));
+
 	
-	/* Lay out icons a line at a time. */
 	canvas_width = (GTK_WIDGET (container)->allocation.width
 			- container->details->left_margin
 			- container->details->right_margin)
 		/ GNOME_CANVAS (container)->pixels_per_unit;
-	line_width = 0;
-	line_start = icons;
+	
+	rows_index      = 0;
+	columns_index   = 0;
+	positions_index = 0;
+	
 	y = start_y;
-	i = 0;
+	line_width       = 0;
 	max_height_above = 0;
 	max_height_below = 0;
-	for (p = icons; p != NULL; p = p->next) {
-		icon = p->data;
 
+	icons_list     = icons;
+	positions_list = positions->head;
+	rows_list      = rows->head;
+	while (icons_list != NULL) {
+		/* Calculates necessary icons dimensions only once */
+		if (positions_index++ == positions->length) {
+			icon = icons_list->data;
 		/* Get the width of the icon. */
 		item = GNOME_CANVAS_ITEM (icon->item);
 		
@@ -878,65 +907,162 @@ lay_down_icons_horizontal (NautilusIconC
 					      &bounds.x1, &bounds.y1);
 		
 		space_width = get_icon_space_width (container, &bounds);
-		
 		icon_bounds = nautilus_icon_canvas_item_get_icon_rectangle (icon->item);
 
 		/* Calculate size above/below baseline */
 		height_above = icon_bounds.y1 - bounds.y0;
 		height_below = bounds.y1 - icon_bounds.y1;
 
-		/* If this icon doesn't fit, it's time to lay out the line that's queued up. */
+			position = g_new0 (IconPositionInfo, 1);
+			position->width = space_width;
+			position->height_above = height_above;
+			position->height_below = height_below;
+			position->y_offset = icon_bounds.y0 - icon_bounds.y1;
+			position->x_offset = (icon_bounds.x1 - icon_bounds.x0) / 2;
+			g_queue_push_tail (positions, position);
+		} else {
+			/* Avoids recalculations */
+			position     = positions_list->data;
+			space_width  = position->width;
+			height_above = position->height_above;  
+			height_below = position->height_below;
+			
+			/* next position info */
+			positions_list = positions_list->next;
+		}
+
+		/* repeat until maximum possible number of columns is reached 
+		   for current canvas width */
+		if (find_max_number_of_columns == TRUE) {
+			/* add one column */
+			++columns_index;
+			line_width += space_width;
+			
+			/* checks if end of line is reach or for incomplete first line */
+			if (icons_list->next != NULL && line_width - ICON_PAD_RIGHT <= canvas_width) {
+				/* next icon */
+				icons_list = icons_list->next;
+				continue;
+			} else {
+				/* sizes columns to maximum possible number
+				   of columns for the current canvas width */
+				g_array_set_size (columns, columns_index);
+				
+				line_width      = 0;
+				columns_index   = 0;
+				positions_index = 0;
 		
+				icons_list     = icons;
+				positions_list = positions->head;
+				
+				find_max_number_of_columns = FALSE;
+				continue;
+			}
+		}
+				
+		/* finds maximum widths for columns */
+		max_column_width = &g_array_index (columns, double, columns_index);
+		if(space_width > *max_column_width) {
 		/* FIXME: why don't we want to guarantee a small white space to the right of
 		 * the last column just like we guarantee a small white space to the left of
 		 * the first column?
 		 */
-		if (line_start != p && line_width + space_width - ICON_PAD_RIGHT > canvas_width) {
-			/* Advance to the baseline. */
-			y += ICON_PAD_TOP + max_height_above;
+			if (columns->len > 1 && line_width + space_width - *max_column_width
+			    - ICON_PAD_RIGHT > canvas_width) {
+				/* new line width exceeds canvas width */
 			
-			lay_down_one_line (container, line_start, p, y, positions);
+				/* discard last column */
+				g_array_set_size (columns, columns->len - 1);
 			
-			/* Advance to next line. */
-			y += max_height_below + ICON_PAD_BOTTOM;
+				/* reset all columns's widths */
+				for (columns_index = 0; columns_index < columns->len; columns_index++) {
+					max_column_width  = &g_array_index (columns, double, columns_index);
+					*max_column_width = 0;
+				}	
 
+				/* start over */
+				y                = start_y;
 			line_width = 0;
-			line_start = p;
-			i = 0;
+				max_height_above = 0;
+				max_height_below = 0;
 			
-			max_height_above = height_above;
-			max_height_below = height_below;
+				rows_index      = 0;
+				columns_index   = 0;
+				positions_index = 0;
+			
+				
+				icons_list     = icons;
+				positions_list = positions->head;
+				rows_list      = rows->head;
+				continue;
 		} else {
+				line_width = line_width + space_width - *max_column_width;
+				*max_column_width = space_width;
+			}
+		}	
+	
+		/* find maximum heights for rows */
 			if (height_above > max_height_above) {
 				max_height_above = height_above;
 			}
 			if (height_below > max_height_below) {
 				max_height_below = height_below;
 			}
-		}
-		
-		g_array_set_size (positions, i + 1);
-		position = &g_array_index (positions, IconPositions, i++);
-		position->width = space_width;
-		position->x_offset = (space_width - (icon_bounds.x1 - icon_bounds.x0)) / 2;
-		position->y_offset = icon_bounds.y0 - icon_bounds.y1;
-
-		/* Add this icon. */
-		line_width += space_width;
-	}
 
-	/* Lay down that last line of icons. */
-	if (line_start != NULL) {
+		if (columns_index == columns->len - 1) {
 		/* Advance to the baseline. */
 		y += ICON_PAD_TOP + max_height_above;
 		
-		lay_down_one_line (container, line_start, NULL, y, positions);
+			/* Allocates space for nth row only once */ 
+			if (rows_index++ == rows->length) {
+				baseline  = g_new0 (double, 1);
+				*baseline = y;
+				g_queue_push_tail (rows, baseline);
+			} else {
+				baseline  = rows_list->data;
+				*baseline = y;
+				
+				/* next line */
+				rows_list = rows_list->next;
+			}
 		
 		/* Advance to next line. */
 		y += max_height_below + ICON_PAD_BOTTOM;
+			
+			/* go back to first column */
+			columns_index = 0;
+			
+			max_height_above = 0;
+			max_height_below = 0;
+		} else {
+			/* next column */
+			++columns_index;
+		}
+		
+		/* next icon */
+		icons_list = icons_list->next;
+	}
+
+	/* get baseline for possible incomplete
+	   last line */
+	if (positions->length % columns->len) {
+		/* Advance to the baseline. */
+		y += ICON_PAD_TOP + max_height_above;
+		baseline  = g_new0 (double, 1);
+		*baseline = y;
+		g_queue_push_tail (rows, baseline);
 	}
 
-	g_array_free (positions, TRUE);
+	extra_columns_width = (canvas_width - line_width) / columns->len;
+	lay_down_all_lines (icons, 
+			    positions,
+			    rows, 
+			    columns, 
+			    extra_columns_width);
+   
+	g_queue_free (positions);
+	g_queue_free (rows);
+	g_array_free (columns, TRUE);
 }
 
 /* Search for available space at location */
@@ -1206,7 +1332,7 @@ lay_down_icons (NautilusIconContainer *c
 	switch (container->details->layout_mode)
 	{
 	case NAUTILUS_ICON_LAYOUT_L_R_T_B:
-		lay_down_icons_horizontal (container, icons, start_y);
+		lay_down_icons_align (container, icons, start_y);
 		break;
 		
 	case NAUTILUS_ICON_LAYOUT_T_B_L_R:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]