From 748344d2a941dd1403614870b18a41b2e5e4497a Mon Sep 17 00:00:00 2001
From: Daniel Grunwald <daniel@danielgrunwald.de>
Date: Wed, 4 Nov 2009 15:21:10 +0000
Subject: [PATCH] Remove PixelSnapper; use WPF layout rounding instead.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5203 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
---
 src/Libraries/AvalonDock/AlignedImage.cs      |   4 +-
 .../Project/Src/Commands/MenuItemBuilders.cs  |   2 +-
 src/Main/Base/Project/Src/Gui/App.xaml        |   1 +
 .../Gui/Workbench/Layouts/AvalonPadContent.cs |   2 +-
 .../Layouts/AvalonWorkbenchWindow.cs          |   2 +-
 .../Src/Gui/Workbench/WpfWorkbench.xaml       |   1 +
 .../Base/Project/Src/Util/ExtensionMethods.cs |   3 +-
 .../ICSharpCode.Core.Presentation.csproj      |   4 +-
 .../Menu/CoreMenuItem.cs                      |   2 +-
 .../PixelSnapper.cs                           | 174 ------------------
 .../PresentationResourceService.cs            |   8 +-
 .../ToolBar/ToolBarButton.cs                  |   2 +-
 .../ToolBar/ToolBarCheckBox.cs                |   2 +-
 .../ToolBar/ToolBarDropDownButton.cs          |   2 +-
 .../ToolBar/ToolBarSplitButton.cs             |   2 +-
 15 files changed, 23 insertions(+), 188 deletions(-)
 delete mode 100644 src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs

diff --git a/src/Libraries/AvalonDock/AlignedImage.cs b/src/Libraries/AvalonDock/AlignedImage.cs
index 9c322bbccf..a41303b2d9 100644
--- a/src/Libraries/AvalonDock/AlignedImage.cs
+++ b/src/Libraries/AvalonDock/AlignedImage.cs
@@ -36,6 +36,8 @@ namespace AvalonDock
 {
     public class AlignedImage : Decorator
     {
+    	/*
+    	 * Disabled because we use WPF 4.0 layout rounding instead.
         public AlignedImage()
         {
             this.LayoutUpdated += new EventHandler(OnLayoutUpdated);
@@ -183,6 +185,6 @@ namespace AvalonDock
             double delta = value1 - value2;
             return ((delta < 1.53E-06) && (delta > -1.53E-06));
         }
-
+	*/
     }
 }
diff --git a/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs b/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
index b0f7403433..2668e842f2 100644
--- a/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
+++ b/src/Main/Base/Project/Src/Commands/MenuItemBuilders.cs
@@ -463,7 +463,7 @@ namespace ICSharpCode.SharpDevelop.Commands
 					var item = new System.Windows.Controls.MenuItem();
 					item.Header = ICSharpCode.Core.Presentation.MenuService.ConvertLabel(StringParser.Parse(padContent.Title));
 					if (!string.IsNullOrEmpty(padContent.Icon)) {
-						item.Icon = PresentationResourceService.GetPixelSnappedImage(padContent.Icon);
+						item.Icon = PresentationResourceService.GetImage(padContent.Icon);
 					}
 					item.Command = new BringPadToFrontCommand(padContent);
 					if (!string.IsNullOrEmpty(padContent.Shortcut)) {
diff --git a/src/Main/Base/Project/Src/Gui/App.xaml b/src/Main/Base/Project/Src/Gui/App.xaml
index 76e88653e0..3016f64868 100644
--- a/src/Main/Base/Project/Src/Gui/App.xaml
+++ b/src/Main/Base/Project/Src/Gui/App.xaml
@@ -14,6 +14,7 @@
 		<Style TargetType="{x:Type Window}" x:Key="DialogWindow">
 			<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
 			<Setter Property="ShowInTaskbar" Value="False" />
+			<Setter Property="UseLayoutRounding" Value="True" />
 		</Style>
 	</Application.Resources>
 </Application>
\ No newline at end of file
diff --git a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs
index 478a0d30bb..6bf0152111 100644
--- a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs
+++ b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonPadContent.cs
@@ -35,7 +35,7 @@ namespace ICSharpCode.SharpDevelop.Gui
 			this.SetValueToExtension(TitleProperty, new StringParseExtension(descriptor.Title));
 			placeholder = new TextBlock { Text = this.Title };
 			this.Content = placeholder;
-			this.Icon = PresentationResourceService.GetPixelSnappedImage(descriptor.Icon);
+			this.Icon = PresentationResourceService.GetImage(descriptor.Icon);
 			
 			placeholder.IsVisibleChanged += AvalonPadContent_IsVisibleChanged;
 		}
diff --git a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
index 57d44b23f4..b20c7a69ee 100644
--- a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
+++ b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
@@ -416,7 +416,7 @@ namespace ICSharpCode.SharpDevelop.Gui
 			set {
 				if (icon != value) {
 					icon = value;
-					base.Icon = new PixelSnapper(new Image { Source = value });
+					base.Icon = new Image { Source = value };
 				}
 			}
 		}
diff --git a/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.xaml b/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.xaml
index a90acb6d54..1fe311e3c8 100644
--- a/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.xaml
+++ b/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.xaml
@@ -6,6 +6,7 @@
         WindowStartupLocation = "Manual"
         Background = "{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
         AllowDrop = "True"
+        UseLayoutRounding = "True"
 >
 	<DockPanel Name="dockPanel">
 		<Menu Name="mainMenu" DockPanel.Dock="Top"/>
diff --git a/src/Main/Base/Project/Src/Util/ExtensionMethods.cs b/src/Main/Base/Project/Src/Util/ExtensionMethods.cs
index 1d1d39f7f1..d30c09d565 100644
--- a/src/Main/Base/Project/Src/Util/ExtensionMethods.cs
+++ b/src/Main/Base/Project/Src/Util/ExtensionMethods.cs
@@ -376,9 +376,10 @@ namespace ICSharpCode.SharpDevelop
 		/// <summary>
 		/// Creates a new image for the image source.
 		/// </summary>
+		[ObsoleteAttribute("Use layout rounding instead")]
 		public static UIElement CreatePixelSnappedImage(this IImage image)
 		{
-			return new PixelSnapper(CreateImage(image));
+			return CreateImage(image);
 		}
 		
 		/// <summary>
diff --git a/src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj b/src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
index 9c68e55a3a..75520b1d4e 100644
--- a/src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
+++ b/src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
@@ -1,4 +1,5 @@
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <ProjectGuid>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</ProjectGuid>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -85,7 +86,6 @@
     <Compile Include="Menu\CoreMenuItem.cs" />
     <Compile Include="NativeMethods.cs" />
     <Compile Include="OptionBinding.cs" />
-    <Compile Include="PixelSnapper.cs" />
     <Compile Include="PresentationResourceService.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="RadioButtonGroup.cs" />
diff --git a/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs b/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
index da2ebd7a12..daca662116 100644
--- a/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/Menu/CoreMenuItem.cs
@@ -36,7 +36,7 @@ namespace ICSharpCode.Core.Presentation
 				try {
 					var image = PresentationResourceService.GetImage(codon.Properties["icon"]);
 					image.Height = 16;
-					this.Icon = new PixelSnapper(image);
+					this.Icon = image;
 				} catch (ResourceNotFoundException) {}
 			}
 			UpdateText();
diff --git a/src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs b/src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs
deleted file mode 100644
index cb50b670f2..0000000000
--- a/src/Main/ICSharpCode.Core.Presentation/PixelSnapper.cs
+++ /dev/null
@@ -1,174 +0,0 @@
-// <file>
-//     <copyright see="prj:///doc/copyright.txt"/>
-//     <license see="prj:///doc/license.txt"/>
-//     <owner name="Daniel Grunwald"/>
-//     <version>$Revision$</version>
-// </file>
-using System;
-using System.Threading;
-using System.Windows;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Threading;
-
-namespace ICSharpCode.Core.Presentation
-{
-	/// <summary>
-	/// A WPF control that aligns its content on pixel boundaries.
-	/// </summary>
-	public class PixelSnapper : UIElement
-	{
-		public PixelSnapper()
-		{
-		}
-		
-		public PixelSnapper(UIElement visualChild)
-			: this()
-		{
-			this.Child = visualChild;
-		}
-		
-		UIElement _visualChild;
-		
-		/// <summary>
-		/// Gets/sets the visual child.
-		/// </summary>
-		public UIElement Child {
-			get { return _visualChild; }
-			set {
-				RemoveVisualChild(_visualChild);
-				_visualChild = value;
-				AddVisualChild(_visualChild);
-				InvalidateMeasure();
-			}
-		}
-		
-		/// <summary>
-		/// Gets the visual child.
-		/// </summary>
-		protected override Visual GetVisualChild(int index)
-		{
-			if (index == 0 && _visualChild != null)
-				return _visualChild;
-			else
-				throw new ArgumentOutOfRangeException("index");
-		}
-		
-		/// <summary>
-		/// Gets the number of visual children.
-		/// </summary>
-		protected override int VisualChildrenCount {
-			get { return _visualChild != null ? 1 : 0; }
-		}
-		
-		/// <summary>
-		/// Measure the visual child.
-		/// </summary>
-		protected override Size MeasureCore(Size availableSize)
-		{
-			if (_visualChild != null) {
-				_visualChild.Measure(availableSize);
-				return _visualChild.DesiredSize;
-			} else {
-				return base.MeasureCore(availableSize);
-			}
-		}
-		
-		protected override void ArrangeCore(Rect finalRect)
-		{
-			base.ArrangeCore(finalRect);
-			if (_visualChild != null) {
-				_pixelOffset = GetPixelOffset();
-				//LoggingService.Debug("Arrange, Pixel Offset=" + _pixelOffset);
-				_visualChild.Arrange(new Rect(new Point(_pixelOffset.X, _pixelOffset.Y), finalRect.Size));
-				
-				// check again after the whole layout pass has finished, maybe we need to move
-				Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new ThreadStart(CheckLayout));
-			}
-		}
-		
-		private void CheckLayout()
-		{
-			Point pixelOffset = GetPixelOffset();
-			if (!AreClose(pixelOffset, _pixelOffset)) {
-				InvalidateArrange();
-			}
-		}
-		
-		// Gets the matrix that will convert a point from "above" the
-		// coordinate space of a visual into the the coordinate space
-		// "below" the visual.
-		static Matrix GetVisualTransform(Visual v)
-		{
-			if (v != null) {
-				Matrix m = Matrix.Identity;
-				
-				Transform transform = VisualTreeHelper.GetTransform(v);
-				if (transform != null) {
-					m *= transform.Value;
-				}
-				
-				Vector offset = VisualTreeHelper.GetOffset(v);
-				m.Translate(offset.X, offset.Y);
-				
-				return m;
-			}
-			
-			return Matrix.Identity;
-		}
-		
-		static Point ApplyVisualTransform(Point point, Visual v, bool inverse)
-		{
-			if (v != null) {
-				Matrix visualTransform = GetVisualTransform(v);
-				if (inverse)
-					visualTransform.Invert();
-				point = visualTransform.Transform(point);
-			}
-			return point;
-		}
-		
-		private Point GetPixelOffset()
-		{
-			Point pixelOffset = new Point();
-			
-			PresentationSource ps = PresentationSource.FromVisual(this);
-			if (ps != null) {
-				Visual rootVisual = ps.RootVisual;
-				
-				// Transform (0,0) from this element up to pixels.
-				pixelOffset = this.TransformToAncestor(rootVisual).Transform(pixelOffset);
-				pixelOffset = ApplyVisualTransform(pixelOffset, rootVisual, false);
-				pixelOffset = ps.CompositionTarget.TransformToDevice.Transform(pixelOffset);
-				
-				// Round the origin to the nearest whole pixel.
-				pixelOffset.X = Math.Round(pixelOffset.X);
-				pixelOffset.Y = Math.Round(pixelOffset.Y);
-				
-				// Transform the whole-pixel back to this element.
-				pixelOffset = ps.CompositionTarget.TransformFromDevice.Transform(pixelOffset);
-				pixelOffset = ApplyVisualTransform(pixelOffset, rootVisual, true);
-				pixelOffset = rootVisual.TransformToDescendant(this).Transform(pixelOffset);
-			}
-			
-			return pixelOffset;
-		}
-		
-		static bool AreClose(Point point1, Point point2)
-		{
-			return AreClose(point1.X, point2.X) && AreClose(point1.Y, point2.Y);
-		}
-		
-		static bool AreClose(double value1, double value2)
-		{
-			if (value1 == value2)
-			{
-				return true;
-			}
-			double delta = value1 - value2;
-			return ((delta < 1.53E-06) && (delta > -1.53E-06));
-		}
-		
-		private Point _pixelOffset;
-	}
-}
diff --git a/src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs b/src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs
index 5881acb044..88fbe4594c 100644
--- a/src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/PresentationResourceService.cs
@@ -61,9 +61,13 @@ namespace ICSharpCode.Core.Presentation
 		/// <exception cref="ResourceNotFoundException">
 		/// Is thrown when the GlobalResource manager can't find a requested resource.
 		/// </exception>
-		public static PixelSnapper GetPixelSnappedImage(string name)
+		[Obsolete("Use layout rounding instead")]
+		public static System.Windows.Controls.Image GetPixelSnappedImage(string name)
 		{
-			return new PixelSnapper(GetImage(name));
+			return new System.Windows.Controls.Image {
+				Source = GetBitmapSource(name),
+				UseLayoutRounding = true
+			};
 		}
 		
 		/// <summary>
diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs
index 405a4ac65c..5e29a9ef3e 100644
--- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarButton.cs
@@ -32,7 +32,7 @@ namespace ICSharpCode.Core.Presentation
 				var image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
 				image.Height = 16;
 				image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
-				this.Content = new PixelSnapper(image);
+				this.Content = image;
 			} else {
 				this.Content = codon.Id;
 			}
diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarCheckBox.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarCheckBox.cs
index b551500e4f..beed72af33 100644
--- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarCheckBox.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarCheckBox.cs
@@ -38,7 +38,7 @@ namespace ICSharpCode.Core.Presentation
 				var image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
 				image.Height = 16;
 				image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
-				this.Content = new PixelSnapper(image);
+				this.Content = image;
 			} else {
 				this.Content = codon.Id;
 			}
diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarDropDownButton.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarDropDownButton.cs
index 8eb79ec3a0..5aa31d8390 100644
--- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarDropDownButton.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarDropDownButton.cs
@@ -31,7 +31,7 @@ namespace ICSharpCode.Core.Presentation
 				var image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
 				image.Height = 16;
 				image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
-				this.Content = new PixelSnapper(image);
+				this.Content = image;
 			} else {
 				this.Content = codon.Id;
 			}
diff --git a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarSplitButton.cs b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarSplitButton.cs
index d5bf6319fb..9360da646d 100644
--- a/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarSplitButton.cs
+++ b/src/Main/ICSharpCode.Core.Presentation/ToolBar/ToolBarSplitButton.cs
@@ -32,7 +32,7 @@ namespace ICSharpCode.Core.Presentation
 				var image = PresentationResourceService.GetImage(StringParser.Parse(codon.Properties["icon"]));
 				image.Height = 16;
 				image.SetResourceReference(StyleProperty, ToolBarService.ImageStyleKey);
-				this.Content = new PixelSnapper(image);
+				this.Content = image;
 			} else {
 				this.Content = codon.Id;
 			}