[f-spot] Move the Zooming to ImageView



commit 6f271b4020c163cadc6292aaf27bbe5d8144cb03
Author: Stephane Delcroix <stephane delcroix org>
Date:   Wed Jun 17 10:15:07 2009 +0200

    Move the Zooming to ImageView
    
    all the low level widgetry is now moved from PhotoImageView to Widgets/ImageView, making ImageView usefull on its own, and PhotoImageView more photo loading centric

 src/ImportCommand.cs     |    2 +-
 src/PhotoImageView.cs    |  208 +++++-----------------------------------------
 src/Widgets/ImageView.cs |  104 ++++++++++++++++--------
 3 files changed, 92 insertions(+), 222 deletions(-)
---
diff --git a/src/ImportCommand.cs b/src/ImportCommand.cs
index bcd0c27..b3c64c6 100644
--- a/src/ImportCommand.cs
+++ b/src/ImportCommand.cs
@@ -624,7 +624,7 @@ public class ImportCommand : GladeDialog
 		GtkUtil.ModifyColors (photo_view);
 
 		photo_view.Pixbuf = GtkUtil.TryLoadIcon (FSpot.Global.IconTheme, "f-spot", 48, (Gtk.IconLookupFlags)0);
-		photo_view.Fit = true;
+		photo_view.ZoomFit (true);
 			
 		tag_entry = new FSpot.Widgets.TagEntry (MainWindow.Toplevel.Database.Tags, false);
 		tag_entry.UpdateFromTagNames (new string []{});
diff --git a/src/PhotoImageView.cs b/src/PhotoImageView.cs
index 7c2b658..548a61a 100644
--- a/src/PhotoImageView.cs
+++ b/src/PhotoImageView.cs
@@ -39,7 +39,6 @@ namespace FSpot.Widgets {
 
 			Accelerometer.OrientationChanged += HandleOrientationChanged;
 
-			this.ScrollEvent += HandleScrollEvent;
 			this.item = item;
 			item.Changed += PhotoItemChanged;
 			this.Destroyed += HandleDestroyed;
@@ -186,44 +185,7 @@ namespace FSpot.Widgets {
 				return !(load_async != ProgressType.Full || !progressive_display);
 			}
 		}
-
-		private bool fit = true;
-		public bool Fit {
-			get {
-				return (Zoom == MIN_ZOOM);
-			}
-			set {
-				if (!fit && value)
-					ZoomFit ();
-				
-				fit = value;
-			}
-		}
-
-
-		public double Zoom {
-			get { return base.Zoom; }
-			set {
-				//Console.WriteLine ("Setting zoom to {0}, MIN = {1}", value, MIN_ZOOM);
-				value = System.Math.Min (value, MAX_ZOOM);
-				value = System.Math.Max (value, MIN_ZOOM);
-
-				double zoom = Zoom;
-				if (value == zoom)
-					return;
-
-				if (System.Math.Abs (zoom - value) < System.Double.Epsilon)
-					return;
-
-				if (value == MIN_ZOOM)
-					this.Fit = true;
-				else {
-					this.Fit = false;
-					base.Zoom = value;
-				}
-			}
-		}
-		
+	
 		// Zoom scaled between 0.0 and 1.0
 		public double NormalizedZoom {
 			get {
@@ -234,13 +196,6 @@ namespace FSpot.Widgets {
 			}
 		}
 		
-		protected override void OnSizeAllocated (Gdk.Rectangle allocation)
-		{
-			if (fit)
-				ZoomFit ();
-			base.OnSizeAllocated (allocation);
-		}
-
 		FSpot.AsyncPixbufLoader loader;
 
 		private void LoadErrorImage (System.Exception e)
@@ -315,65 +270,7 @@ namespace FSpot.Widgets {
 				PhotoChanged (this);
 		}
 		
-		public void ZoomIn ()
-		{
-			Zoom = Zoom * ZOOM_FACTOR;
-		}
-		
-		public void ZoomOut ()
-		{
-			Zoom = Zoom / ZOOM_FACTOR;
-		}
-		
-		bool upscale;
-		private void ZoomFit ()
-		{
-			ZoomFit (upscale);
-		}
-
-		public void ZoomFit (bool upscale)
-		{			
-			Gdk.Pixbuf pixbuf = this.Pixbuf;
-			Gtk.ScrolledWindow scrolled = this.Parent as Gtk.ScrolledWindow;
-			this.upscale = upscale;
-			
-			if (pixbuf == null)
-				return;
 
-			if (scrolled != null)
-				scrolled.SetPolicy (Gtk.PolicyType.Never, Gtk.PolicyType.Never);
-
-			int available_width = (scrolled != null) ? scrolled.Allocation.Width : this.Allocation.Width;
-			int available_height = (scrolled != null) ? scrolled.Allocation.Height : this.Allocation.Height;
-
-			double zoom_to_fit = FitToScale ((uint) available_width, 
-							(uint) available_height,
-							(uint) pixbuf.Width, 
-							(uint) pixbuf.Height, 
-							upscale);
-
-			double image_zoom = zoom_to_fit;
-
-			base.Zoom = image_zoom;
-			
-			if (scrolled != null)
-				scrolled.SetPolicy (Gtk.PolicyType.Automatic, Gtk.PolicyType.Automatic);
-		}
-
-		static double FitToScale (uint dest_width, uint dest_height, uint src_width, uint src_height, bool upscale_smaller)
-		{
-			if (src_width == 0 || src_height == 0)
-				return 1.0;
-	
-			if (dest_width == 0 || dest_height == 0)
-				return 0.0;
-	
-			if (src_width <= dest_width && src_height <= dest_height && !upscale_smaller)
-				return 1.0;
-	
-			return Math.Min ((double)dest_width / src_width, (double)dest_height / src_height);
-		}
-	
 		private void HandleLoupeDestroy (object sender, EventArgs args)
 		{
 			if (sender == loupe)
@@ -392,66 +289,27 @@ namespace FSpot.Widgets {
 			bool handled = true;
 		
 			// Scroll if image is zoomed in (scrollbars are visible)
-			Gtk.ScrolledWindow scrolled = this.Parent as Gtk.ScrolledWindow;
-			if (scrolled != null && !this.Fit) {
-				Gtk.Adjustment vadj = Vadjustment;
-				Gtk.Adjustment hadj = Hadjustment;
-				switch (evnt.Key) {					
-				case Gdk.Key.Up:
-				case Gdk.Key.KP_Up:
-				case Gdk.Key.k:
-				case Gdk.Key.K:
-					vadj.Value -= vadj.StepIncrement;
-					if (vadj.Value < vadj.Lower)
-						vadj.Value = vadj.Lower;
-					break;
-				case Gdk.Key.Left:
-				case Gdk.Key.KP_Left:
-				case Gdk.Key.h:
-					hadj.Value -= hadj.StepIncrement;
-					if (hadj.Value < hadj.Lower)
-						hadj.Value = hadj.Lower;
-					break;
-				case Gdk.Key.Down:
-				case Gdk.Key.KP_Down:
-				case Gdk.Key.j:
-				case Gdk.Key.J:
-					vadj.Value += vadj.StepIncrement;
-					if (vadj.Value > vadj.Upper - vadj.PageSize)
-						vadj.Value = vadj.Upper - vadj.PageSize;
-					break;
-				case Gdk.Key.Right:
-				case Gdk.Key.KP_Right:
-				case Gdk.Key.l:
-					hadj.Value += hadj.StepIncrement;
-					if (hadj.Value > hadj.Upper - hadj.PageSize)
-						hadj.Value = hadj.Upper - hadj.PageSize;
-					break;
-				default:
-					handled = false;
-					break;
-				}
-			} else
-				handled = false;
-
-			if (handled)
-				return true;
-
-			handled = true;
-			
+			Gtk.ScrolledWindow scrolled_w = this.Parent as Gtk.ScrolledWindow;
+			bool scrolled = scrolled_w != null && !this.Fit;
+		
 			// Go to the next/previous photo when not zoomed (no scrollbars)
 			switch (evnt.Key) {
 			case Gdk.Key.Up:
 			case Gdk.Key.KP_Up:
 			case Gdk.Key.Left:
 			case Gdk.Key.KP_Left:
-			case Gdk.Key.Page_Up:
-			case Gdk.Key.KP_Page_Up:
-			case Gdk.Key.BackSpace:
 			case Gdk.Key.h:
 			case Gdk.Key.H:
 			case Gdk.Key.k:
 			case Gdk.Key.K:
+				if (scrolled)
+					handled = false;
+				else
+					this.Item.MovePrevious ();
+				break;
+			case Gdk.Key.Page_Up:
+			case Gdk.Key.KP_Page_Up:
+			case Gdk.Key.BackSpace:
 			case Gdk.Key.b:
 			case Gdk.Key.B:
 				this.Item.MovePrevious ();
@@ -460,14 +318,19 @@ namespace FSpot.Widgets {
 			case Gdk.Key.KP_Down:
 			case Gdk.Key.Right:
 			case Gdk.Key.KP_Right:
-			case Gdk.Key.Page_Down:
-			case Gdk.Key.KP_Page_Down:
-			case Gdk.Key.space:
-			case Gdk.Key.KP_Space:
 			case Gdk.Key.j:
 			case Gdk.Key.J:
 			case Gdk.Key.l:
 			case Gdk.Key.L:
+				if (scrolled)
+					handled = false;
+				else
+					this.Item.MoveNext ();
+				break;
+			case Gdk.Key.Page_Down:
+			case Gdk.Key.KP_Page_Down:
+			case Gdk.Key.space:
+			case Gdk.Key.KP_Space:
 			case Gdk.Key.n:
 			case Gdk.Key.N:
 				this.Item.MoveNext ();
@@ -484,27 +347,6 @@ namespace FSpot.Widgets {
 			case Gdk.Key.KP_End:
 				this.Item.Index = this.Query.Count - 1;
 				break;
-			case Gdk.Key.Key_0:
-			case Gdk.Key.KP_0:
-				this.Fit = true;
-				break;
-			case Gdk.Key.Key_1:
-			case Gdk.Key.KP_1:
-				this.Zoom =  1.0;
-				break;
-			case Gdk.Key.Key_2:
-			case Gdk.Key.KP_2:
-				this.Zoom = 2.0;
-				break;
-			case Gdk.Key.minus:
-			case Gdk.Key.KP_Subtract:
-				ZoomOut ();
-				break;
-			case Gdk.Key.equal:
-			case Gdk.Key.plus:
-			case Gdk.Key.KP_Add:
-				ZoomIn ();
-				break;
 			default:
 				handled = false;
 				break;
@@ -535,14 +377,6 @@ namespace FSpot.Widgets {
 			sharpener.Show ();	
 		}
 		
-		[GLib.ConnectBefore]
-		private void HandleScrollEvent (object sender, Gtk.ScrollEventArgs args)
-		{
-			//For right now we just disable fit mode and let the parent event handlers deal
-			//with the real actions.
-			this.Fit = false;
-		}
-		
 		private void HandleDestroyed (object sender, System.EventArgs args)
 		{
 			//loader.AreaUpdated -= HandlePixbufAreaUpdated;
diff --git a/src/Widgets/ImageView.cs b/src/Widgets/ImageView.cs
index 557bbe7..d82fc04 100644
--- a/src/Widgets/ImageView.cs
+++ b/src/Widgets/ImageView.cs
@@ -18,7 +18,6 @@ namespace FSpot.Widgets
 {
 	public class ImageView : Container
 	{
-
 #region public API
 		public ImageView (Adjustment hadjustment, Adjustment vadjustment, bool can_select) : base ()
 		{
@@ -44,12 +43,7 @@ namespace FSpot.Widgets
 			get { return pixbuf; } 
 			set {
 				pixbuf = value;
-				if (pixbuf == null)
-					min_zoom = 0.1;
-				else
-					min_zoom = Math.Min (1.0,
-						Math.Min ((double)Allocation.Width / (double)Pixbuf.Width,
-						(double)Allocation.Height / (double)Pixbuf.Height));
+				min_zoom = ComputeMinZoom (upscale);
 
 				ComputeScaledSize ();
 				AdjustmentsChanged -= ScrollToAdjustments;
@@ -170,16 +164,40 @@ namespace FSpot.Widgets
 		}
 
 		double zoom = 1.0;
-		public virtual double Zoom {
+		public double Zoom {
 			get { return zoom; }
 			set { DoZoom (value, false, 0, 0); }
 		}
 
+		public void ZoomIn ()
+		{
+			Zoom *= ZOOM_FACTOR;
+		}
+
+		public void ZoomOut ()
+		{
+			Zoom *= 1.0/ZOOM_FACTOR;
+		}
+
 		public void ZoomAboutPoint (double zoom_increment, int x, int y)
 		{
 			DoZoom (zoom * zoom_increment, true, x, y);
 		}	
 
+		bool fit;
+		public bool Fit {
+			get { return fit; } 
+		}
+
+		public void ZoomFit (bool upscale)
+		{
+			if (this.upscale != upscale)
+				min_zoom = ComputeMinZoom (upscale);
+			this.upscale = upscale;
+			fit = true;
+			DoZoom (MIN_ZOOM, false, 0, 0);
+		}
+
 		public Point WindowCoordsToImage (Point win)
 		{
 			if (Pixbuf == null)
@@ -280,6 +298,11 @@ namespace FSpot.Widgets
 			get { return min_zoom; }
 		}
 
+		bool upscale;
+		protected void ZoomFit ()
+		{
+			ZoomFit (upscale);
+		}
 #endregion
 
 #region container
@@ -375,15 +398,10 @@ namespace FSpot.Widgets
 
 		protected override void OnSizeAllocated (Gdk.Rectangle allocation)
 		{
-			if (Pixbuf == null)
-				min_zoom = 0.1;
-			else
-				min_zoom = Math.Min (1.0,
-					Math.Min ((double)allocation.Width / (double)Pixbuf.Width,
-					(double)allocation.Height / (double)Pixbuf.Height));
+			min_zoom = ComputeMinZoom (upscale);
 
-			if (zoom < min_zoom)
-				zoom = min_zoom;
+			if (fit || zoom < MIN_ZOOM)
+				zoom = MIN_ZOOM;
 			// Since this affects the zoom_scale we should alert it
 			EventHandler eh = ZoomChanged;
 			if (eh != null)
@@ -577,47 +595,59 @@ namespace FSpot.Widgets
 			case Gdk.Key.Left:
 			case Gdk.Key.KP_Left:
 			case Gdk.Key.h:
+			case Gdk.Key.H:
 				ScrollBy (-Hadjustment.StepIncrement, 0);
 				break;
 			case Gdk.Key.Right:
 			case Gdk.Key.KP_Right:
 			case Gdk.Key.l:
+			case Gdk.Key.L:
 				ScrollBy (Hadjustment.StepIncrement, 0);
 				break;
+			case Gdk.Key.equal:
 			case Gdk.Key.plus:
 			case Gdk.Key.KP_Add:
-				GdkWindow.GetPointer (out x, out y, out type);
-				ZoomAboutPoint (ZOOM_FACTOR, x, y);
+				ZoomIn ();
 				break;
 			case Gdk.Key.minus:
 			case Gdk.Key.KP_Subtract:
-				GdkWindow.GetPointer (out x, out y, out type);
-				ZoomAboutPoint (1.0/ZOOM_FACTOR, x, y);
+				ZoomOut ();
 				break;
+			case Gdk.Key.Key_0:
+			case Gdk.Key.KP_0:
+				ZoomFit ();
+				break;
+			case Gdk.Key.KP_1:
 			case Gdk.Key.Key_1:
 				GdkWindow.GetPointer (out x, out y, out type);
 				DoZoom (1.0, true, x, y);
 				break;
-
+			case Gdk.Key.Key_2:
+			case Gdk.Key.KP_2:
+				GdkWindow.GetPointer (out x, out y, out type);
+				DoZoom (2.0, true, x, y);
+				break;
 			default:
 				handled = false;
 				break;
 			}
 			
-			if (handled)
-				return true;
-
-			return base.OnKeyPressEvent (evnt);
+			return handled || base.OnKeyPressEvent (evnt);
 		}
 
 #endregion
-#region private painting and misc 
+#region private painting, zooming and misc 
 		int XOffset { get; set;}
 		int YOffset { get; set;}
 		void DoZoom (double zoom, bool use_anchor, int x, int y)
 		{
+			fit = zoom == MIN_ZOOM;
+
 			if (zoom == this.zoom)
 				return;
+			
+			if (System.Math.Abs (this.zoom - zoom) < System.Double.Epsilon)
+				return;
 
 			if (zoom > MAX_ZOOM)
 				zoom = MAX_ZOOM;
@@ -745,14 +775,8 @@ namespace FSpot.Widgets
 
 		void ScrollTo (int x, int y, bool change_adjustments)
 		{
-			if (x < 0)
-				x = 0;
-			else if (x > Hadjustment.Upper - Hadjustment.PageSize) 
-				x = (int)(Hadjustment.Upper - Hadjustment.PageSize);
-			if (y < 0) 
-				y = 0;
-			else if (y > Vadjustment.Upper - Vadjustment.PageSize) 
-				y = (int)(Vadjustment.Upper - Vadjustment.PageSize);
+			x = Clamp (x, 0, (int)(Hadjustment.Upper - Hadjustment.PageSize));
+			y = Clamp (y, 0, (int)(Vadjustment.Upper - Vadjustment.PageSize));
 
 			int xof = x - XOffset;
 			int yof = y - YOffset;
@@ -781,6 +805,18 @@ namespace FSpot.Widgets
 		{
 			return Math.Min (Math.Max (value, min), max);
 		}
+
+		double ComputeMinZoom (bool upscale)
+		{
+			if (Pixbuf == null)
+				return 0.1;
+			if (upscale)
+				return Math.Min ((double)Allocation.Width / (double)Pixbuf.Width,
+						 (double)Allocation.Height / (double)Pixbuf.Height);
+			return Math.Min (1.0,
+					 Math.Min ((double)Allocation.Width / (double)Pixbuf.Width,
+						   (double)Allocation.Height / (double)Pixbuf.Height));
+		}
 #endregion
 
 #region children



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