Re: Polishing the icon stretching code



On Mon, 2005-10-24 at 13:21 -0400, Matthias Clasen wrote:
> On Mon, 2005-10-24 at 09:27 +0200, Alexander Larsson wrote:
> > On Sat, 2005-10-22 at 01:33 -0400, Matthias Clasen wrote:
> > > I have attached a patch to
> > > http://bugzilla.gnome.org/show_bug.cgi?id=157271
> > > which makes nautilus use the resize cursors when stretching 
> > > an icon. It also makes the knob image themable. 
> > > 
> > > There are some more things which could be improved here:
> > > 
> > >  - Add keynav for stretching icons (proposal: use Ctrl-+/-  to
> > >    stretch the icon while the stretch handles are displayed)
> > >  - Don't hardcode a line width of 1 for the focus-like rectangle
> > >    drawn with the stretch handles, but use a value derived from
> > >    focus-width.
> > > 
> > >  I also note that "note-indicator.png" is another icon that should
> > >  probably be made themable.
> > 
> > Looks good to commit to HEAD.
> 
> I attched another iteration of the patch, which adds keynav
> (C-+/C--/C-0 for growing, shrinking, or resetting) the icon which 
> is currently stretched. I also changed the drawing code to draw the 
> outline as black/white instead of black-over-background, since the
> latter tends to be poorly visible on a dark background image.

Alex pointed out that Ctrl-0 did not actually work for unstretching.
It took me a little while to figure out that it is because the 
zoom_to_normal action is made invisible, but not insensitive like 
the other zoom controls. Here is a patch which fixes this, and also
makes C-= works in the same way as C-+ (nautilus also does this for the
zoom controls).

Matthias

--- nautilus-2.12.1/src/nautilus-window-manage-views.c.stretch	2005-07-11 04:37:43.000000000 -0400
+++ nautilus-2.12.1/src/nautilus-window-manage-views.c	2005-10-27 14:35:29.000000000 -0400
@@ -1532,10 +1532,7 @@
 	action = gtk_action_group_get_action (window->details->main_action_group,
 					      NAUTILUS_ACTION_ZOOM_NORMAL);
 	gtk_action_set_visible (action, supports_zooming);
-	gtk_action_set_sensitive (action,
-				  TRUE);
-       
-	/* FIXME bugzilla.gnome.org 43442: Desensitize "Zoom Normal"? */
+	gtk_action_set_sensitive (action, supports_zooming);
 }
 
 static void
--- nautilus-2.12.1/libnautilus-private/nautilus-icon-canvas-item.h.stretch	2005-06-22 12:25:45.000000000 -0400
+++ nautilus-2.12.1/libnautilus-private/nautilus-icon-canvas-item.h	2005-10-27 14:35:29.000000000 -0400
@@ -84,7 +84,8 @@
 gboolean    nautilus_icon_canvas_item_hit_test_rectangle       (NautilusIconCanvasItem       *item,
 								ArtIRect                      canvas_rect);
 gboolean    nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem       *item,
-								ArtPoint                      world_point);
+								ArtPoint                      world_point,
+								GtkCornerType *corner);
 void        nautilus_icon_canvas_item_invalidate_label_size    (NautilusIconCanvasItem       *item);
 ArtDRect    nautilus_icon_canvas_item_get_icon_rectangle       (const NautilusIconCanvasItem *item);
 ArtDRect    nautilus_icon_canvas_item_get_text_rectangle       (const NautilusIconCanvasItem *item);
--- nautilus-2.12.1/libnautilus-private/nautilus-icon-container.c.stretch	2005-10-03 04:00:26.000000000 -0400
+++ nautilus-2.12.1/libnautilus-private/nautilus-icon-container.c	2005-10-27 14:45:53.000000000 -0400
@@ -3367,6 +3367,8 @@
 	NautilusIcon *icon;
 	ArtPoint world_point;
 	GtkWidget *toplevel;
+	GtkCornerType corner;
+	GdkCursor *cursor;
 
 	details = container->details;
 	icon = details->stretch_icon;
@@ -3374,11 +3376,27 @@
 	/* Check if we hit the stretch handles. */
 	world_point.x = details->drag_x;
 	world_point.y = details->drag_y;
-	if (!nautilus_icon_canvas_item_hit_test_stretch_handles
-	    (icon->item, world_point)) {
+	if (!nautilus_icon_canvas_item_hit_test_stretch_handles (icon->item, world_point, &corner)) {
 		return FALSE;
 	}
 
+	switch (corner) {
+	case GTK_CORNER_TOP_LEFT:
+		cursor = gdk_cursor_new (GDK_TOP_LEFT_CORNER);
+		break;
+	case GTK_CORNER_BOTTOM_LEFT:
+		cursor = gdk_cursor_new (GDK_BOTTOM_LEFT_CORNER);
+		break;
+	case GTK_CORNER_TOP_RIGHT:
+		cursor = gdk_cursor_new (GDK_TOP_RIGHT_CORNER);
+		break;
+	case GTK_CORNER_BOTTOM_RIGHT:
+		cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER);
+		break;
+	default: 
+		cursor = NULL;
+		break;
+	}
 	/* Set up the dragging. */
 	details->drag_state = DRAG_STATE_STRETCH;
 	eel_canvas_w2c (EEL_CANVAS (container),
@@ -3396,8 +3414,10 @@
 	eel_canvas_item_grab (EEL_CANVAS_ITEM (icon->item),
 				(GDK_POINTER_MOTION_MASK
 				 | GDK_BUTTON_RELEASE_MASK),
-				NULL,
+				cursor,
 				GDK_CURRENT_TIME);
+	if (cursor)
+		gdk_cursor_unref (cursor);
 
 	/* Ensure the window itself is focused.. */
 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container));
@@ -3458,6 +3478,43 @@
 	}
 }
 
+static gboolean
+keyboard_stretching (NautilusIconContainer *container,
+		     GdkEventKey           *event)
+{
+	NautilusIcon *icon;
+	guint size;
+
+	icon = container->details->stretch_icon;
+
+	if (icon == NULL || !icon->is_selected) {
+		return FALSE;
+	}
+
+	icon_get_size (container, icon, &size);
+
+	switch (event->keyval) {
+	case GDK_equal:
+	case GDK_plus:
+	case GDK_KP_Add:
+		icon_set_size (container, icon, size + 5, FALSE, FALSE);
+		break;
+	case GDK_minus:
+	case GDK_KP_Subtract:
+		icon_set_size (container, icon, size - 5, FALSE, FALSE);
+		break;
+	case GDK_0:
+	case GDK_KP_0:
+		nautilus_icon_container_move_icon (container, icon,
+						   icon->x, icon->y,
+						   1.0, 1.0,
+						   FALSE, TRUE, TRUE);
+		break;
+	}
+	
+	return TRUE;
+}
+
 static void
 ungrab_stretch_icon (NautilusIconContainer *container)
 {
@@ -3489,7 +3546,7 @@
 	redo_layout (container);
 }
 
-static void
+static gboolean
 undo_stretching (NautilusIconContainer *container)
 {
 	NautilusIcon *stretched_icon;
@@ -3497,7 +3554,7 @@
 	stretched_icon = container->details->stretch_icon;
 
 	if (stretched_icon == NULL) {
-		return;
+		return FALSE;
 	}
 
 	if (container->details->drag_state == DRAG_STATE_STRETCH) {
@@ -3519,6 +3576,8 @@
 	container->details->stretch_icon = NULL;				
 	emit_stretch_ended (container, stretched_icon);
 	redo_layout (container);
+
+	return TRUE;
 }
 
 static gboolean
@@ -3857,9 +3916,19 @@
 			
 			handled = TRUE;
 			break;
-		case GDK_Escape:
-			undo_stretching (container);
-			handled = TRUE;
+ 		case GDK_Escape:
+			handled = undo_stretching (container);
+			break;
+ 		case GDK_plus:
+ 		case GDK_minus:
+ 		case GDK_equal:
+ 		case GDK_KP_Add:
+ 		case GDK_KP_Subtract:
+ 		case GDK_0:
+ 		case GDK_KP_0:
+			if (event->state & GDK_CONTROL_MASK) {
+				handled = keyboard_stretching (container, event);
+			}
 			break;
 		case GDK_F10:
 			/* handle Ctrl+F10 because we want to display the
--- nautilus-2.12.1/libnautilus-private/nautilus-icon-canvas-item.c.stretch	2005-09-26 11:30:05.000000000 -0400
+++ nautilus-2.12.1/libnautilus-private/nautilus-icon-canvas-item.c	2005-10-27 14:35:29.000000000 -0400
@@ -44,6 +44,7 @@
 #include <eel/eel-accessibility.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gtk/gtksignal.h>
+#include <gdk/gdk.h>
 #include <libart_lgpl/art_rgb.h>
 #include <libart_lgpl/art_rgb_affine.h>
 #include <libart_lgpl/art_rgb_rgba_affine.h>
@@ -209,7 +210,8 @@
 						      GdkGC                         *gc);
 
 static gboolean hit_test_stretch_handle              (NautilusIconCanvasItem        *item,
-						      ArtIRect                       canvas_rect);
+						      ArtIRect                       canvas_rect,
+						      GtkCornerType *corner);
 static void     clear_rounded_corners                (GdkPixbuf                     *destination_pixbuf,
 						      GdkPixbuf                     *corner_pixbuf,
 						      int                            corner_size);
@@ -1152,12 +1154,30 @@
 	draw_or_measure_label_text (item, drawable, create_mask, icon_rect);
 }
 
+static GdkPixbuf *
+get_knob_pixbuf (void)
+{
+	GdkPixbuf *knob_pixbuf;
+	char *knob_filename;
+
+	knob_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+						"stock-nautilus-knob",
+						8, 0, NULL);
+	if (!knob_pixbuf) {
+		knob_filename = nautilus_pixmap_file ("knob.png");
+		knob_pixbuf = gdk_pixbuf_new_from_file (knob_filename, NULL);
+		g_free (knob_filename);
+	}
+
+	return knob_pixbuf;
+}
+
 static void
 draw_stretch_handles (NautilusIconCanvasItem *item, GdkDrawable *drawable,
 		      const ArtIRect *rect)
 {
+	GtkWidget *widget;
 	GdkGC *gc;
-	char *knob_filename;
 	GdkPixbuf *knob_pixbuf;
 	GdkBitmap *stipple;
 	int knob_width, knob_height;
@@ -1166,17 +1186,27 @@
 		return;
 	}
 
+	widget = GTK_WIDGET (EEL_CANVAS_ITEM (item)->canvas);
+
 	gc = gdk_gc_new (drawable);
 
-	knob_filename = nautilus_pixmap_file ("knob.png");
-	knob_pixbuf = gdk_pixbuf_new_from_file (knob_filename, NULL);
+	knob_pixbuf = get_knob_pixbuf ();
 	knob_width = gdk_pixbuf_get_width (knob_pixbuf);
 	knob_height = gdk_pixbuf_get_height (knob_pixbuf);
 
 	stipple = eel_stipple_bitmap_for_screen (
 			gdk_drawable_get_screen (GDK_DRAWABLE (drawable)));
 	
-	/* first draw the box */		
+	/* first draw the box */
+	gdk_gc_set_rgb_fg_color (gc, &widget->style->white);
+	gdk_draw_rectangle
+		(drawable, gc, FALSE,
+			    rect->x0,
+			    rect->y0,
+			    rect->x1 - rect->x0 - 1,
+			    rect->y1 - rect->y0 - 1);
+
+	gdk_gc_set_rgb_fg_color (gc, &widget->style->black);
 	gdk_gc_set_stipple (gc, stipple);
 	gdk_gc_set_fill (gc, GDK_STIPPLED);
 	gdk_draw_rectangle
@@ -1192,8 +1222,6 @@
 	draw_pixbuf (knob_pixbuf, drawable, rect->x0, rect->y1 - knob_height);
 	draw_pixbuf (knob_pixbuf, drawable, rect->x1 - knob_width, rect->y0);
 	draw_pixbuf (knob_pixbuf, drawable, rect->x1 - knob_width, rect->y1 - knob_height);
-	
-	g_free (knob_filename);
 	g_object_unref (knob_pixbuf);	
 
 	g_object_unref (gc);
@@ -1828,7 +1856,7 @@
 	}
 
 	/* Check for hits in the stretch handles. */
-	if (hit_test_stretch_handle (icon_item, canvas_rect)) {
+	if (hit_test_stretch_handle (icon_item, canvas_rect, NULL)) {
 		return TRUE;
 	}
 	
@@ -2055,12 +2083,13 @@
 /* Check if one of the stretch handles was hit. */
 static gboolean
 hit_test_stretch_handle (NautilusIconCanvasItem *item,
-			 ArtIRect probe_canvas_rect)
+			 ArtIRect probe_canvas_rect,
+			 GtkCornerType *corner)
 {
 	ArtIRect icon_rect;
-	char *knob_filename;
 	GdkPixbuf *knob_pixbuf;
 	int knob_width, knob_height;
+	int hit_corner;
 	
 	g_return_val_if_fail (NAUTILUS_IS_ICON_CANVAS_ITEM (item), FALSE);
 
@@ -2075,24 +2104,36 @@
 		return FALSE;
 	}
 
-	knob_filename = nautilus_pixmap_file ("knob.png");
-	knob_pixbuf = gdk_pixbuf_new_from_file (knob_filename, NULL);
+	
+	knob_pixbuf = get_knob_pixbuf ();
 	knob_width = gdk_pixbuf_get_width (knob_pixbuf);
 	knob_height = gdk_pixbuf_get_height (knob_pixbuf);
+	g_object_unref (knob_pixbuf);
 
-	g_free (knob_filename);
-	g_object_unref (knob_pixbuf);	
-	
 	/* Check for hits in the stretch handles. */
-	return (probe_canvas_rect.x0 < icon_rect.x0 + knob_width
-     		|| probe_canvas_rect.x1 >= icon_rect.x1 - knob_width)
-		&& (probe_canvas_rect.y0 < icon_rect.y0 + knob_height
-		    || probe_canvas_rect.y1 >= icon_rect.y1 - knob_height);
+	hit_corner = -1;
+	if (probe_canvas_rect.x0 < icon_rect.x0 + knob_width) {
+		if (probe_canvas_rect.y0 < icon_rect.y0 + knob_height)
+			hit_corner = GTK_CORNER_TOP_LEFT;
+		else if (probe_canvas_rect.y1 >= icon_rect.y1 - knob_height)
+			hit_corner = GTK_CORNER_BOTTOM_LEFT;
+	}
+	else if (probe_canvas_rect.x1 >= icon_rect.x1 - knob_width) {
+		if (probe_canvas_rect.y0 < icon_rect.y0 + knob_height)
+			hit_corner = GTK_CORNER_TOP_RIGHT;
+		else if (probe_canvas_rect.y1 >= icon_rect.y1 - knob_height)
+			hit_corner = GTK_CORNER_BOTTOM_RIGHT;
+	}
+	if (corner)
+		*corner = hit_corner;
+
+	return hit_corner != -1;
 }
 
 gboolean
 nautilus_icon_canvas_item_hit_test_stretch_handles (NautilusIconCanvasItem *item,
-						    ArtPoint world_point)
+						    ArtPoint world_point,
+						    GtkCornerType *corner)
 {
 	ArtIRect canvas_rect;
 
@@ -2105,7 +2146,7 @@
 			  &canvas_rect.y0);
 	canvas_rect.x1 = canvas_rect.x0 + 1;
 	canvas_rect.y1 = canvas_rect.y0 + 1;
-	return hit_test_stretch_handle (item, canvas_rect);
+	return hit_test_stretch_handle (item, canvas_rect, corner);
 }
 
 /* nautilus_icon_canvas_item_hit_test_rectangle


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