mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-03-03 00:00:57 +08:00
385 lines
12 KiB
C#
385 lines
12 KiB
C#
using System;
|
|
using System.Windows;
|
|
|
|
namespace AIStudio.Wpf.DiagramDesigner.Geometrys
|
|
{
|
|
[Serializable]
|
|
public struct SizeBase : IFormattable
|
|
{
|
|
public static SizeBase Zero { get; } = new SizeBase(0, 0);
|
|
|
|
public SizeBase(double width, double height)
|
|
{
|
|
if (width < 0 || height < 0)
|
|
{
|
|
throw new System.ArgumentException("Size_WidthAndHeightCannotBeNegative");
|
|
}
|
|
|
|
_width = width;
|
|
_height = height;
|
|
}
|
|
|
|
public bool IsEmpty
|
|
{
|
|
get
|
|
{
|
|
return _width < 0;
|
|
}
|
|
}
|
|
|
|
internal double _width;
|
|
|
|
public double Width
|
|
{
|
|
get
|
|
{
|
|
return _width;
|
|
}
|
|
set
|
|
{
|
|
if (IsEmpty)
|
|
{
|
|
throw new System.InvalidOperationException("Size_CannotModifyEmptySize");
|
|
}
|
|
|
|
if (value < 0)
|
|
{
|
|
throw new System.ArgumentException("Size_WidthCannotBeNegative");
|
|
}
|
|
|
|
_width = value;
|
|
}
|
|
}
|
|
|
|
internal double _height;
|
|
public double Height
|
|
{
|
|
get
|
|
{
|
|
return _height;
|
|
}
|
|
set
|
|
{
|
|
if (IsEmpty)
|
|
{
|
|
throw new System.InvalidOperationException("Size_CannotModifyEmptySize");
|
|
}
|
|
|
|
if (value < 0)
|
|
{
|
|
throw new System.ArgumentException("Size_HeightCannotBeNegative");
|
|
}
|
|
|
|
_height = value;
|
|
}
|
|
}
|
|
|
|
public SizeBase Add(double value) => new SizeBase(Width + value, Height + value);
|
|
|
|
//public bool Equals(Size size) => size != null && Width == size.Width && Height == size.Height;
|
|
|
|
//public override string ToString() => $"Size(width={Width}, height={Height})";
|
|
|
|
public static implicit operator SizeBase(Size size)
|
|
{
|
|
return new SizeBase(size.Width, size.Height);
|
|
}
|
|
|
|
public static implicit operator Size(SizeBase sizebase)
|
|
{
|
|
return new Size(sizebase.Width, sizebase.Height);
|
|
}
|
|
|
|
#region Statics
|
|
|
|
/// <summary>
|
|
/// Empty - a static property which provides an Empty size. Width and Height are
|
|
/// negative-infinity. This is the only situation
|
|
/// where size can be negative.
|
|
/// </summary>
|
|
public static SizeBase Empty
|
|
{
|
|
get
|
|
{
|
|
return s_empty;
|
|
}
|
|
}
|
|
|
|
#endregion Statics
|
|
|
|
#region Public Methods
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Compares two Size instances for exact equality.
|
|
/// Note that double values can acquire error when operated upon, such that
|
|
/// an exact comparison between two values which are logically equal may fail.
|
|
/// Furthermore, using this equality operator, Double.NaN is not equal to itself.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the two Size instances are exactly equal, false otherwise
|
|
/// </returns>
|
|
/// <param name='size1'>The first Size to compare</param>
|
|
/// <param name='size2'>The second Size to compare</param>
|
|
public static bool operator ==(SizeBase size1, SizeBase size2)
|
|
{
|
|
return size1.Width == size2.Width &&
|
|
size1.Height == size2.Height;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compares two Size instances for exact inequality.
|
|
/// Note that double values can acquire error when operated upon, such that
|
|
/// an exact comparison between two values which are logically equal may fail.
|
|
/// Furthermore, using this equality operator, Double.NaN is not equal to itself.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the two Size instances are exactly unequal, false otherwise
|
|
/// </returns>
|
|
/// <param name='size1'>The first Size to compare</param>
|
|
/// <param name='size2'>The second Size to compare</param>
|
|
public static bool operator !=(SizeBase size1, SizeBase size2)
|
|
{
|
|
return !(size1 == size2);
|
|
}
|
|
/// <summary>
|
|
/// Compares two Size instances for object equality. In this equality
|
|
/// Double.NaN is equal to itself, unlike in numeric equality.
|
|
/// Note that double values can acquire error when operated upon, such that
|
|
/// an exact comparison between two values which
|
|
/// are logically equal may fail.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the two Size instances are exactly equal, false otherwise
|
|
/// </returns>
|
|
/// <param name='size1'>The first Size to compare</param>
|
|
/// <param name='size2'>The second Size to compare</param>
|
|
public static bool Equals(SizeBase size1, SizeBase size2)
|
|
{
|
|
if (size1.IsEmpty)
|
|
{
|
|
return size2.IsEmpty;
|
|
}
|
|
else
|
|
{
|
|
return size1.Width.Equals(size2.Width) &&
|
|
size1.Height.Equals(size2.Height);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Equals - compares this Size with the passed in object. In this equality
|
|
/// Double.NaN is equal to itself, unlike in numeric equality.
|
|
/// Note that double values can acquire error when operated upon, such that
|
|
/// an exact comparison between two values which
|
|
/// are logically equal may fail.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if the object is an instance of Size and if it's equal to "this".
|
|
/// </returns>
|
|
/// <param name='o'>The object to compare to "this"</param>
|
|
public override bool Equals(object o)
|
|
{
|
|
if ((null == o) || !(o is SizeBase))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SizeBase value = (SizeBase)o;
|
|
return SizeBase.Equals(this, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Equals - compares this Size with the passed in object. In this equality
|
|
/// Double.NaN is equal to itself, unlike in numeric equality.
|
|
/// Note that double values can acquire error when operated upon, such that
|
|
/// an exact comparison between two values which
|
|
/// are logically equal may fail.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// bool - true if "value" is equal to "this".
|
|
/// </returns>
|
|
/// <param name='value'>The Size to compare to "this"</param>
|
|
public bool Equals(SizeBase value)
|
|
{
|
|
return SizeBase.Equals(this, value);
|
|
}
|
|
/// <summary>
|
|
/// Returns the HashCode for this Size
|
|
/// </summary>
|
|
/// <returns>
|
|
/// int - the HashCode for this Size
|
|
/// </returns>
|
|
public override int GetHashCode()
|
|
{
|
|
if (IsEmpty)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
// Perform field-by-field XOR of HashCodes
|
|
return Width.GetHashCode() ^
|
|
Height.GetHashCode();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse - returns an instance converted from the provided string using
|
|
/// the culture "en-US"
|
|
/// <param name="source"> string with Size data </param>
|
|
/// </summary>
|
|
//public static Size Parse(string source)
|
|
//{
|
|
// IFormatProvider formatProvider = System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS;
|
|
|
|
// TokenizerHelper th = new TokenizerHelper(source, formatProvider);
|
|
|
|
// Size value;
|
|
|
|
// String firstToken = th.NextTokenRequired();
|
|
|
|
// // The token will already have had whitespace trimmed so we can do a
|
|
// // simple string compare.
|
|
// if (firstToken == "Empty")
|
|
// {
|
|
// value = Empty;
|
|
// }
|
|
// else
|
|
// {
|
|
// value = new Size(
|
|
// Convert.ToDouble(firstToken, formatProvider),
|
|
// Convert.ToDouble(th.NextTokenRequired(), formatProvider));
|
|
// }
|
|
|
|
// // There should be no more tokens in this string.
|
|
// th.LastTokenRequired();
|
|
|
|
// return value;
|
|
//}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Public Operators
|
|
|
|
/// <summary>
|
|
/// Explicit conversion to Vector.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Vector - A Vector equal to this Size
|
|
/// </returns>
|
|
/// <param name="size"> Size - the Size to convert to a Vector </param>
|
|
public static explicit operator VectorBase(SizeBase size)
|
|
{
|
|
return new VectorBase(size._width, size._height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Explicit conversion to PointBase
|
|
/// </summary>
|
|
/// <returns>
|
|
/// PointBase - A PointBase equal to this Size
|
|
/// </returns>
|
|
/// <param name="size"> Size - the Size to convert to a PointBase </param>
|
|
public static explicit operator PointBase(SizeBase size)
|
|
{
|
|
return new PointBase(size._width, size._height);
|
|
}
|
|
|
|
#endregion Public Operators
|
|
|
|
#region Private Methods
|
|
|
|
static private SizeBase CreateEmptySize()
|
|
{
|
|
SizeBase size = new SizeBase();
|
|
// We can't set these via the property setters because negatives widths
|
|
// are rejected in those APIs.
|
|
size._width = Double.NegativeInfinity;
|
|
size._height = Double.NegativeInfinity;
|
|
return size;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
|
|
#region Private Fields
|
|
|
|
private readonly static SizeBase s_empty = CreateEmptySize();
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Internal Properties
|
|
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of this object based on the current culture.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
public override string ToString()
|
|
{
|
|
// Delegate to the internal method which implements all ToString calls.
|
|
return ConvertToString(null /* format string */, null /* format provider */);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of this object based on the IFormatProvider
|
|
/// passed in. If the provider is null, the CurrentCulture is used.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
public string ToString(IFormatProvider provider)
|
|
{
|
|
// Delegate to the internal method which implements all ToString calls.
|
|
return ConvertToString(null /* format string */, provider);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of this object based on the format string
|
|
/// and IFormatProvider passed in.
|
|
/// If the provider is null, the CurrentCulture is used.
|
|
/// See the documentation for IFormattable for more information.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
string IFormattable.ToString(string format, IFormatProvider provider)
|
|
{
|
|
// Delegate to the internal method which implements all ToString calls.
|
|
return ConvertToString(format, provider);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a string representation of this object based on the format string
|
|
/// and IFormatProvider passed in.
|
|
/// If the provider is null, the CurrentCulture is used.
|
|
/// See the documentation for IFormattable for more information.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A string representation of this object.
|
|
/// </returns>
|
|
internal string ConvertToString(string format, IFormatProvider provider)
|
|
{
|
|
if (IsEmpty)
|
|
{
|
|
return "Empty";
|
|
}
|
|
|
|
// Helper to get the numeric list separator for a given culture.
|
|
char separator = ',';
|
|
return String.Format(provider,
|
|
"{1:" + format + "}{0}{2:" + format + "}",
|
|
separator,
|
|
_width,
|
|
_height);
|
|
}
|
|
|
|
|
|
|
|
#endregion Internal Properties
|
|
}
|
|
} |