|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
//
//
// Description: Grid length converter implementation
//
// See spec at http://avalon/layout/Specs/Star%20LengthUnit.mht
//
//
using MS.Internal;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
using System.Windows.Markup;
namespace System.Windows
{
/// <summary>
/// GridLengthConverter - Converter class for converting
/// instances of other types to and from GridLength instances.
/// </summary>
public class GridLengthConverter: TypeConverter
{
//-------------------------------------------------------------------
//
// Public Methods
//
//-------------------------------------------------------------------
#region Public Methods
/// <summary>
/// Checks whether or not this class can convert from a given type.
/// </summary>
/// <param name="typeDescriptorContext">The ITypeDescriptorContext
/// for this call.</param>
/// <param name="sourceType">The Type being queried for support.</param>
/// <returns>
/// <c>true</c> if thie converter can convert from the provided type,
/// <c>false</c> otherwise.
/// </returns>
public override bool CanConvertFrom(
ITypeDescriptorContext typeDescriptorContext,
Type sourceType)
{
// We can only handle strings, integral and floating types
TypeCode tc = Type.GetTypeCode(sourceType);
switch (tc)
{
case TypeCode.String:
case TypeCode.Decimal:
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return true;
default:
return false;
}
}
/// <summary>
/// Checks whether or not this class can convert to a given type.
/// </summary>
/// <param name="typeDescriptorContext">The ITypeDescriptorContext
/// for this call.</param>
/// <param name="destinationType">The Type being queried for support.</param>
/// <returns>
/// <c>true</c> if this converter can convert to the provided type,
/// <c>false</c> otherwise.
/// </returns>
public override bool CanConvertTo(
ITypeDescriptorContext typeDescriptorContext,
Type destinationType)
{
return ( destinationType == typeof(InstanceDescriptor)
|| destinationType == typeof(string) );
}
/// <summary>
/// Attempts to convert to a GridLength from the given object.
/// </summary>
/// <param name="typeDescriptorContext">The ITypeDescriptorContext for this call.</param>
/// <param name="cultureInfo">The CultureInfo which is respected when converting.</param>
/// <param name="source">The object to convert to a GridLength.</param>
/// <returns>
/// The GridLength instance which was constructed.
/// </returns>
/// <exception cref="ArgumentNullException">
/// An ArgumentNullException is thrown if the example object is null.
/// </exception>
/// <exception cref="ArgumentException">
/// An ArgumentException is thrown if the example object is not null
/// and is not a valid type which can be converted to a GridLength.
/// </exception>
public override object ConvertFrom(
ITypeDescriptorContext typeDescriptorContext,
CultureInfo cultureInfo,
object source)
{
if (source != null)
{
if (source is string)
{
return (FromString((string)source, cultureInfo));
}
else
{
// conversion from numeric type
double value;
GridUnitType type;
value = Convert.ToDouble(source, cultureInfo);
if (double.IsNaN(value))
{
// this allows for conversion from Width / Height = "Auto"
value = 1.0;
type = GridUnitType.Auto;
}
else
{
type = GridUnitType.Pixel;
}
return new GridLength(value, type);
}
}
throw GetConvertFromException(source);
}
/// <summary>
/// Attempts to convert a GridLength instance to the given type.
/// </summary>
/// <param name="typeDescriptorContext">The ITypeDescriptorContext for this call.</param>
/// <param name="cultureInfo">The CultureInfo which is respected when converting.</param>
/// <param name="value">The GridLength to convert.</param>
/// <param name="destinationType">The type to which to convert the GridLength instance.</param>
/// <returns>
/// The object which was constructed.
/// </returns>
/// <exception cref="ArgumentNullException">
/// An ArgumentNullException is thrown if the example object is null.
/// </exception>
/// <exception cref="ArgumentException">
/// An ArgumentException is thrown if the object is not null and is not a GridLength,
/// or if the destinationType isn't one of the valid destination types.
/// </exception>
public override object ConvertTo(
ITypeDescriptorContext typeDescriptorContext,
CultureInfo cultureInfo,
object value,
Type destinationType)
{
ArgumentNullException.ThrowIfNull(destinationType);
if ( value != null
&& value is GridLength )
{
GridLength gl = (GridLength)value;
if (destinationType == typeof(string))
{
return (ToString(gl, cultureInfo));
}
if (destinationType == typeof(InstanceDescriptor))
{
ConstructorInfo ci = typeof(GridLength).GetConstructor(new Type[] { typeof(double), typeof(GridUnitType) });
return (new InstanceDescriptor(ci, new object[] { gl.Value, gl.GridUnitType }));
}
}
throw GetConvertToException(value, destinationType);
}
#endregion Public Methods
//-------------------------------------------------------------------
//
// Internal Methods
//
//-------------------------------------------------------------------
#region Internal Methods
/// <summary>
/// Converts a GridLength instance to a String given the CultureInfo.
/// </summary>
/// <param name="gl">GridLength instance to convert.</param>
/// <param name="cultureInfo">Culture Info.</param>
/// <returns>String representation of the object.</returns>
static internal string ToString(GridLength gl, CultureInfo cultureInfo)
{
switch (gl.GridUnitType)
{
// for Auto print out "Auto". value is always "1.0"
case (GridUnitType.Auto):
return ("Auto");
// Star has one special case when value is "1.0".
// in this case drop value part and print only "Star"
case (GridUnitType.Star):
return (
DoubleUtil.IsOne(gl.Value)
? "*"
: $"{Convert.ToString(gl.Value, cultureInfo)}*");
// for Pixel print out the numeric value. "px" can be omitted.
default:
return (Convert.ToString(gl.Value, cultureInfo));
}
}
/// <summary>
/// Parses a GridLength from a string given the CultureInfo.
/// </summary>
/// <param name="s">String to parse from.</param>
/// <param name="cultureInfo">Culture Info.</param>
/// <returns>Newly created GridLength instance.</returns>
/// <remarks>
/// Formats:
/// "[value][unit]"
/// [value] is a double
/// [unit] is a string in GridLength._unitTypes connected to a GridUnitType
/// "[value]"
/// As above, but the GridUnitType is assumed to be GridUnitType.Pixel
/// "[unit]"
/// As above, but the value is assumed to be 1.0
/// This is only acceptable for a subset of GridUnitType: Auto
/// </remarks>
static internal GridLength FromString(string s, CultureInfo cultureInfo)
{
double value;
GridUnitType unit;
XamlGridLengthSerializer.FromString(s, cultureInfo,
out value, out unit);
return (new GridLength(value, unit));
}
#endregion Internal Methods
}
}
|