From 080f1697e97e13461ec6df4d31c8924d01257a1b Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 9 Apr 2019 01:47:48 +0300 Subject: MERGE --- .../Utils/ExtensionMethods.cs | 214 +++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Utils/ExtensionMethods.cs (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Utils/ExtensionMethods.cs') diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Utils/ExtensionMethods.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Utils/ExtensionMethods.cs new file mode 100644 index 000000000..d9b00ed33 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Utils/ExtensionMethods.cs @@ -0,0 +1,214 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Xml; + +namespace Tango.Scripting.Editors.Utils +{ + static class ExtensionMethods + { + #region Epsilon / IsClose / CoerceValue + /// + /// Epsilon used for IsClose() implementations. + /// We can use up quite a few digits in front of the decimal point (due to visual positions being relative to document origin), + /// and there's no need to be too accurate (we're dealing with pixels here), + /// so we will use the value 0.01. + /// Previosly we used 1e-8 but that was causing issues: + /// http://community.sharpdevelop.net/forums/t/16048.aspx + /// + public const double Epsilon = 0.01; + + /// + /// Returns true if the doubles are close (difference smaller than 0.01). + /// + public static bool IsClose(this double d1, double d2) + { + if (d1 == d2) // required for infinities + return true; + return Math.Abs(d1 - d2) < Epsilon; + } + + /// + /// Returns true if the doubles are close (difference smaller than 0.01). + /// + public static bool IsClose(this Size d1, Size d2) + { + return IsClose(d1.Width, d2.Width) && IsClose(d1.Height, d2.Height); + } + + /// + /// Returns true if the doubles are close (difference smaller than 0.01). + /// + public static bool IsClose(this Vector d1, Vector d2) + { + return IsClose(d1.X, d2.X) && IsClose(d1.Y, d2.Y); + } + + /// + /// Forces the value to stay between mininum and maximum. + /// + /// minimum, if value is less than minimum. + /// Maximum, if value is greater than maximum. + /// Otherwise, value. + public static double CoerceValue(this double value, double minimum, double maximum) + { + return Math.Max(Math.Min(value, maximum), minimum); + } + + /// + /// Forces the value to stay between mininum and maximum. + /// + /// minimum, if value is less than minimum. + /// Maximum, if value is greater than maximum. + /// Otherwise, value. + public static int CoerceValue(this int value, int minimum, int maximum) + { + return Math.Max(Math.Min(value, maximum), minimum); + } + #endregion + + #region CreateTypeface + /// + /// Creates typeface from the framework element. + /// + public static Typeface CreateTypeface(this FrameworkElement fe) + { + return new Typeface((FontFamily)fe.GetValue(TextBlock.FontFamilyProperty), + (FontStyle)fe.GetValue(TextBlock.FontStyleProperty), + (FontWeight)fe.GetValue(TextBlock.FontWeightProperty), + (FontStretch)fe.GetValue(TextBlock.FontStretchProperty)); + } + #endregion + + #region AddRange / Sequence + public static void AddRange(this ICollection collection, IEnumerable elements) + { + foreach (T e in elements) + collection.Add(e); + } + + /// + /// Creates an IEnumerable with a single value. + /// + public static IEnumerable Sequence(T value) + { + yield return value; + } + #endregion + + #region XML reading + /// + /// Gets the value of the attribute, or null if the attribute does not exist. + /// + public static string GetAttributeOrNull(this XmlElement element, string attributeName) + { + XmlAttribute attr = element.GetAttributeNode(attributeName); + return attr != null ? attr.Value : null; + } + + /// + /// Gets the value of the attribute as boolean, or null if the attribute does not exist. + /// + public static bool? GetBoolAttribute(this XmlElement element, string attributeName) + { + XmlAttribute attr = element.GetAttributeNode(attributeName); + return attr != null ? (bool?)XmlConvert.ToBoolean(attr.Value) : null; + } + + /// + /// Gets the value of the attribute as boolean, or null if the attribute does not exist. + /// + public static bool? GetBoolAttribute(this XmlReader reader, string attributeName) + { + string attributeValue = reader.GetAttribute(attributeName); + if (attributeValue == null) + return null; + else + return XmlConvert.ToBoolean(attributeValue); + } + #endregion + + #region DPI independence + public static Rect TransformToDevice(this Rect rect, Visual visual) + { + Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; + return Rect.Transform(rect, matrix); + } + + public static Rect TransformFromDevice(this Rect rect, Visual visual) + { + Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice; + return Rect.Transform(rect, matrix); + } + + public static Size TransformToDevice(this Size size, Visual visual) + { + Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; + return new Size(size.Width * matrix.M11, size.Height * matrix.M22); + } + + public static Size TransformFromDevice(this Size size, Visual visual) + { + Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice; + return new Size(size.Width * matrix.M11, size.Height * matrix.M22); + } + + public static Point TransformToDevice(this Point point, Visual visual) + { + Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; + return new Point(point.X * matrix.M11, point.Y * matrix.M22); + } + + public static Point TransformFromDevice(this Point point, Visual visual) + { + Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice; + return new Point(point.X * matrix.M11, point.Y * matrix.M22); + } + #endregion + + #region System.Drawing <-> WPF conversions + public static System.Drawing.Point ToSystemDrawing(this Point p) + { + return new System.Drawing.Point((int)p.X, (int)p.Y); + } + + public static Point ToWpf(this System.Drawing.Point p) + { + return new Point(p.X, p.Y); + } + + public static Size ToWpf(this System.Drawing.Size s) + { + return new Size(s.Width, s.Height); + } + + public static Rect ToWpf(this System.Drawing.Rectangle rect) + { + return new Rect(rect.Location.ToWpf(), rect.Size.ToWpf()); + } + #endregion + + [Conditional("DEBUG")] + public static void CheckIsFrozen(Freezable f) + { + if (f != null && !f.IsFrozen) + Debug.WriteLine("Performance warning: Not frozen: " + f.ToString()); + } + + [Conditional("DEBUG")] + public static void Log(bool condition, string format, params object[] args) + { + if (condition) { + string output = DateTime.Now.ToString("hh:MM:ss") + ": " + string.Format(format, args) + Environment.NewLine + Environment.StackTrace; + Console.WriteLine(output); + Debug.WriteLine(output); + } + } + } +} -- cgit v1.3.1