Re: [PATCH] Fix shift-select in manual icon layout mode



Am Freitag, den 15.07.2005, 11:40 +0200 schrieb Alexander Larsson:
> On Thu, 2005-07-14 at 22:41 +0200, Christian Neumair wrote:
> > Am Donnerstag, den 14.07.2005, 10:50 +0200 schrieb Alexander Larsson:
> > > On Thu, 2005-07-14 at 10:34 +0200, Christian Neumair wrote:
> > > > Am Mittwoch, den 13.07.2005, 14:09 +0200 schrieb Alexander Larsson:
> > > > > On Wed, 2005-07-13 at 13:51 +0200, Christian Neumair wrote:
> > > > > > Am Mittwoch, den 13.07.2005, 13:45 +0200 schrieb Alexander Larsson:
> > > > > > > On Tue, 2005-07-12 at 18:19 +0200, Christian Neumair wrote:
> > > > > > > > From bug 150116 [1]:
> > > > > > > > 
> > > > > > > > "When trying to select a range of files if ordering is set to manual,
> > > > > > > > the range of files is determined by file names instead of spatial
> > > > > > > > location.
> > > > > > > > 
> > > > > > > > This is especially obvious on the desktop where there is no auto-sort."
> > > > > > > > 
> > > > > > > > Proposed patch attached.
> > > > > > > > 
> > > > > > > > [1] http://bugzilla.gnome.org/show_bug.cgi?id=150116
> > > > > > > > 
> > > > > > > 
> > > > > > > +		x0 = MIN (icon1->x, icon2->x);
> > > > > > > +		x1 = MAX (icon1->x, icon2->x);
> > > > > > > +		y0 = MIN (icon1->y, icon2->y);
> > > > > > > +		y1 = MAX (icon1->y, icon2->y);
> > > > > > > 
> > > > > > > This doesn't look entierly right. Surely you want the whole part of the
> > > > > > > icons, not just its position (which i think is the corner? don't
> > > > > > > remember exactly).
> > > > > > 
> > > > > > Yes, as far as I know it's the upper-left corner. What's wrong with it?
> > > > > > You think we should also select items which just "touch"/intersect the
> > > > > > range to be selected instead of matching only those that are actually
> > > > > > contained within the range?
> > > > > 
> > > > > consider this case:
> > > > > 
> > > > >  a 
> > > > >   bc
> > > > >   
> > > > > where b and c really overlap vertically, except c is one pixel above b.
> > > > > [...]
> > 
> > > [...]
> > > 
> > > In the attached image of my desktop, your range select algorithm doesn't
> > > include the middle icon. I'm pretty sure this is not what most people
> > > expect.
> > 
> > The attached patch produces acceptable results at least on my desktop,
> > since the vertical grid space is 20 px. 25 px should also be enough to
> > handle some additional icon height-related displacement.
> 
> Its still extremely weird. It allows 25 pixel above the highest icon,
> but only the top 25 pixels of the lowest icon. Just either use the full
> extent of both icons to calculate the max/min position, or use the
> middle of the icon.

New proposed patch which takes into account the center of all selection
candidates. I also tried to only use the image rectangle but throwed
away this idea since it proved to feel a bit weird.

-- 
Christian Neumair <chris gnome-de org>
Index: libnautilus-private/nautilus-icon-container.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-container.c,v
retrieving revision 1.393
diff -u -p -r1.393 nautilus-icon-container.c
--- libnautilus-private/nautilus-icon-container.c	12 Aug 2005 18:11:29 -0000	1.393
+++ libnautilus-private/nautilus-icon-container.c	26 Aug 2005 21:12:26 -0000
@@ -1771,26 +1778,63 @@ select_range (NautilusIconContainer *con
 
 	unmatched_icon = NULL;
 	select = FALSE;
-	for (p = container->details->icons; p != NULL; p = p->next) {
-		icon = p->data;
+	if (container->details->auto_layout) {
+		for (p = container->details->icons; p != NULL; p = p->next) {
+			icon = p->data;
+
+			if (unmatched_icon == NULL) {
+				if (icon == icon1) {
+					unmatched_icon = icon2;
+					select = TRUE;
+				} else if (icon == icon2) {
+					unmatched_icon = icon1;
+					select = TRUE;
+				}
+			}
+			
+			selection_changed |= icon_set_selected
+				(container, icon, select);
 
-		if (unmatched_icon == NULL) {
-			if (icon == icon1) {
-				unmatched_icon = icon2;
-				select = TRUE;
-			} else if (icon == icon2) {
-				unmatched_icon = icon1;
-				select = TRUE;
+			if (unmatched_icon != NULL && icon == unmatched_icon) {
+				select = FALSE;
 			}
+			
 		}
-		
-		selection_changed |= icon_set_selected
-			(container, icon, select);
+	} else {
+		ArtIRect icon1_rect, icon2_rect;
+		ArtIRect icon_rect;
+		int x0, x1, y0, y1;
+		int x, y;
+
+		icon_get_bounding_box (icon1,
+				       &icon1_rect.x0, &icon1_rect.y0, 
+				       &icon1_rect.x1, &icon1_rect.y1);
+		icon_get_bounding_box (icon2,
+				       &icon2_rect.x0, &icon2_rect.y0, 
+				       &icon2_rect.x1, &icon2_rect.y1);
+
+		x0 = MIN (icon1_rect.x0, icon2_rect.x0);
+		x1 = MAX (icon1_rect.x1, icon2_rect.x1);
+		y0 = MIN (icon1_rect.y0, icon2_rect.y0);
+		y1 = MAX (icon1_rect.y1, icon2_rect.y1);
+
 
-		if (unmatched_icon != NULL && icon == unmatched_icon) {
-			select = FALSE;
+		for (p = container->details->icons; p != NULL; p = p->next) {
+			icon = p->data;
+
+			/* select all items whose center is inside the selection rectangle */
+			icon_get_bounding_box (icon,
+					       &icon_rect.x0, &icon_rect.y0, 
+					       &icon_rect.x1, &icon_rect.y1);
+
+			x = (icon_rect.x0 + icon_rect.x1) / 2;
+			y = (icon_rect.y0 + icon_rect.y1) / 2;
+
+			select = (x > x0 && x < x1 && y > y0 && y < y1);
+			selection_changed |= icon_set_selected
+				(container, icon, select);
 		}
-		
+
 	}
 	
 	if (selection_changed && icon2 != NULL) {
@@ -4635,10 +4679,11 @@ NautilusIconData *
 nautilus_icon_container_get_first_visible_icon (NautilusIconContainer *container)
 {
 	GList *l;
-	NautilusIcon *icon;
+	NautilusIcon *icon, *best_icon;
 	GtkAdjustment *vadj;
 	double x, y;
 	double x1, y1, x2, y2;
+	double best_y1;
 
 	vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (container));
 
@@ -4647,6 +4692,8 @@ nautilus_icon_container_get_first_visibl
 			&x, &y);
 
 	l = container->details->icons;
+	best_icon = NULL;
+	best_y1 = 0;
 	while (l != NULL) {
 		icon = l->data;
 
@@ -4654,13 +4701,22 @@ nautilus_icon_container_get_first_visibl
 			eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item),
 						    &x1, &y1, &x2, &y2);
 			if (y2 > y) {
-				return icon->data;
+				if (best_icon != NULL) {
+					if (best_y1 > y1) {
+						best_icon = icon;
+						best_y1 = y1;
+					}
+				} else {
+					best_icon = icon;
+					best_y1 = y1;
+				}
 			}
 		}
 		
 		l = l->next;
 	}
-	return NULL;
+
+	return best_icon->data;
 }
 
 /* puts the icon at the top of the screen */
@@ -5152,7 +5208,7 @@ finish_adding_icon (NautilusIconContaine
 static void
 finish_adding_new_icons (NautilusIconContainer *container)
 {
-	GList *p, *new_icons, *no_position_icons;
+	GList *p, *new_icons, *no_position_icons, *semi_position_icons;
 	NautilusIcon *icon;
 	double bottom;
 
@@ -5161,16 +5217,61 @@ finish_adding_new_icons (NautilusIconCon
 
 	/* Position most icons (not unpositioned manual-layout icons). */
 	new_icons = g_list_reverse (new_icons);
-	no_position_icons = NULL;
+	no_position_icons = semi_position_icons = NULL;
 	for (p = new_icons; p != NULL; p = p->next) {
 		icon = p->data;
 		if (!assign_icon_position (container, icon)) {
 			no_position_icons = g_list_prepend (no_position_icons, icon);
+		} else if (!container->details->auto_layout &&
+			   icon->has_lazy_position) {
+			semi_position_icons = g_list_prepend (semi_position_icons, icon);
 		}
 		finish_adding_icon (container, icon);
 	}
 	g_list_free (new_icons);
 
+	if (semi_position_icons != NULL) {
+		PlacementGrid *grid;
+
+		g_assert (!container->details->auto_layout);
+
+		semi_position_icons = g_list_reverse (semi_position_icons);
+
+		grid = placement_grid_new (container, TRUE);
+
+		for (p = container->details->icons; p != NULL; p = p->next) {
+			icon = p->data;
+
+			if (icon_is_positioned (icon) && !icon->has_lazy_position) {
+				placement_grid_mark_icon (grid, icon);
+			}
+		}
+
+		for (p = semi_position_icons; p != NULL; p = p->next) {
+			NautilusIcon *icon;
+			int x, y;
+
+			icon = p->data;
+			x = icon->x;
+			y = icon->y;
+
+			find_empty_location (container, grid, 
+					     icon, x, y, &x, &y);
+
+			icon_set_position (icon, x, y);
+
+			placement_grid_mark_icon (grid, icon);
+
+			/* ensure that next time we run this code, the formerly semi-positioned
+			 * icons are treated as being positioned. */
+			icon->has_lazy_position = FALSE;
+		}
+
+		placement_grid_free (grid);
+
+		g_list_free (semi_position_icons);
+	}
+
 	/* Position the unpositioned manual layout icons. */
 	if (no_position_icons != NULL) {
 		g_assert (!container->details->auto_layout);
@@ -5186,13 +5287,18 @@ finish_adding_new_icons (NautilusIconCon
  * nautilus_icon_container_add:
  * @container: A NautilusIconContainer
  * @data: Icon data.
+ * @has_lazy_position: Whether the saved icon position should only be used
+ * 		       if the previous icon position is free. If the position
+ * 		       is occupied, another position near the last one will
+ * 		       be used.
  * 
  * Add icon to represent @data to container.
  * Returns FALSE if there was already such an icon.
  **/
 gboolean
 nautilus_icon_container_add (NautilusIconContainer *container,
-			     NautilusIconData *data)
+			     NautilusIconData *data,
+			     gboolean has_lazy_position)
 {
 	NautilusIconContainerDetails *details;
 	NautilusIcon *icon;
@@ -5212,6 +5318,7 @@ nautilus_icon_container_add (NautilusIco
 	icon->data = data;
 	icon->x = ICON_UNPOSITIONED_VALUE;
 	icon->y = ICON_UNPOSITIONED_VALUE;
+	icon->has_lazy_position = has_lazy_position;
 	icon->scale_x = 1.0;
 	icon->scale_y = 1.0;
  	icon->item = NAUTILUS_ICON_CANVAS_ITEM

Attachment: signature.asc
Description: This is a digitally signed message part



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