File: Common\Converters\DataManagerConverters.cs
Project: ndp\fx\src\DataVisualization\System.Windows.Forms.DataVisualization.csproj (System.Windows.Forms.DataVisualization)
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
//   Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
//  File:		DataManagerConverters.cs
//
//  Namespace:	DataVisualization.Charting.Design
//
//	Classes:	SeriesAreaNameConverter, 
//				ChartTypeConverter, SeriesNameConverter, 
//				NoNameExpandableObjectConverter, DoubleArrayConverter,
//				DataPointValueConverter, SeriesYValueTypeConverter
//
//  Purpose:	Converter classes for the Series and DataPoint properties.
//
//	Reviewed:	AG - August 7, 2002
//
//===================================================================
 
 
 
using System.ComponentModel.Design.Serialization;
#region Used Namespaces
 
using System;
using System.Resources;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Design;
using System.Drawing.Text;
using System.IO;
using System.Globalization;
using System.Data;
using System.Reflection;
#if Microsoft_CONTROL
	using System.Windows.Forms.DataVisualization.Charting;
	using System.Windows.Forms.DataVisualization.Charting.Data;
	using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
	using System.Windows.Forms.DataVisualization.Charting.Utilities;
	using System.Windows.Forms.DataVisualization.Charting.Borders3D;
    using System.Collections.Generic;
 
#else
	using System.Web;
	using System.Web.UI;
	using System.Web.UI.WebControls;
    using System.Web.UI.DataVisualization.Charting;
	using System.Web.UI.DataVisualization.Charting.Data;
	using System.Web.UI.DataVisualization.Charting.ChartTypes;
#endif
 
#endregion
 
#if Microsoft_CONTROL
    namespace System.Windows.Forms.DataVisualization.Charting
#else
	namespace System.Web.UI.DataVisualization.Charting
#endif
{
	/// <summary>
	/// Chart area name converter. Displays list of available areas names
	/// </summary>
    internal class SeriesAreaNameConverter : StringConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Standart values supported - return true
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values supported.</returns>
		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
		{
			return true;
		}
 
		/// <summary>
		/// Standart values are not exclusive - return false
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Non exclusive standard values.</returns>
		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
		{
			return false;
		}
 
		/// <summary>
		/// Fill in the list of the chart areas for the series.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standart values collection.</returns>
		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
		{
			ArrayList values = new ArrayList();
 
            Chart chart = ConverterHelper.GetChartFromContext(context);
 
            if (chart != null)
            {
                foreach (ChartArea area in chart.ChartAreas)
                {
                    values.Add(area.Name);
                }
            }
			return new StandardValuesCollection(values);
		}
	
		#endregion
	}
 
	/// <summary>
	/// Chart data source design-time converter. Displays list of available data sources.
	/// </summary>
    internal class ChartDataSourceConverter : StringConverter
	{
		#region Converter methods
 
			/// <summary>
			/// Standart values supported - return true
			/// </summary>
			/// <param name="context">Descriptor context.</param>
			/// <returns>Standard values supported.</returns>
			public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
			{
				return true;
			}
 
			/// <summary>
			/// Standart values are not exclusive - return false
			/// </summary>
			/// <param name="context">Descriptor context.</param>
			/// <returns>Non exclusive standard values.</returns>
			public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
			{
				return true;
			}
 
			/// <summary>
			/// Fill in the list of chart type names.
			/// </summary>
			/// <param name="context">Descriptor context.</param>
			/// <returns>Standard values collection.</returns>
			public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
			{
				ArrayList values = new ArrayList();
 
				if (context != null && context.Container != null)
				{
					// Loop through all components in the container
					foreach(IComponent comonent in context.Container.Components)
					{
						// Check if component can be a data source
						if(ChartImage.IsValidDataSource(comonent))
						{
							// Add component name
							values.Add(comonent.Site.Name);
						}
					}
				}
 
				// Add "None" data source
				values.Add("(none)");
 
				return new StandardValuesCollection(values);
			}
 
		#endregion
	}
 
	/// <summary>
	/// Series data source members converter.
	/// </summary>
    internal class SeriesDataSourceMemberConverter : StringConverter
	{
		#region Converter methods
 
			/// <summary>
			/// Standart values supported - return true
			/// </summary>
			/// <param name="context">Descriptor context.</param>
			/// <returns>Standard values supported.</returns>
			public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
			{
				return true;
			}
 
			/// <summary>
			/// Standart values are not exclusive - return false
			/// </summary>
			/// <param name="context">Descriptor context.</param>
			/// <returns>Non exclusive standard values.</returns>
			public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
			{
				return false;
			}
 
			/// <summary>
			/// Fill in the list of the data source members.
			/// </summary>
			/// <param name="context">Descriptor context.</param>
			/// <returns>Standart values collection.</returns>
			public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
			{
				ArrayList values = new ArrayList();
 
                Chart chart = ConverterHelper.GetChartFromContext(context);
                object dataSource = null;
 
				if(chart != null)
				{
                    if (chart != null && ChartImage.IsValidDataSource(chart.DataSource))
                    {
                        dataSource = chart.DataSource;
                    }
 
                    // Check if it's Y values member
					bool usedForYValues = false;
                    if (context.PropertyDescriptor != null && context.PropertyDescriptor.Name == "YValueMembers")
					{
						usedForYValues = true;
					}
 
					// Populate list with all members names
					ArrayList	memberNames = ChartImage.GetDataSourceMemberNames(dataSource, usedForYValues);
					foreach(string name in memberNames)
					{
						values.Add(name);
					}
 
					values.Add("(none)");
				}
 
				return new StandardValuesCollection(values);
			}
 
	#endregion
	}
 
	/// <summary>
	/// Chart legend name converter. Displays list of available legend names
	/// </summary>
    internal class SeriesLegendNameConverter : StringConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Standart values supported - return true
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values supported.</returns>
		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
		{
			return true;
		}
 
		/// <summary>
		/// Standart values are not exclusive - return false
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Non exclusive standard values.</returns>
		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
		{
			return false;
		}
 
		/// <summary>
		/// Fill in the list of the chart legend for the series.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standart values collection.</returns>
		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
		{
			ArrayList values = new ArrayList();
 
            Chart chart = ConverterHelper.GetChartFromContext(context);
 
            if (chart != null)
            {
                foreach (Legend legend in chart.Legends)
                {
                    values.Add(legend.Name);
                }
            }
 
			return new StandardValuesCollection(values);
		}
 
	#endregion
	}
 
	/// <summary>
	/// Chart type converter. Displays list of available chart type names
	/// </summary>
    internal class ChartTypeConverter : StringConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Standart values supported - return true
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values supported.</returns>
		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
		{
			return true;
		}
 
		/// <summary>
		/// Standart values are not exclusive - return false
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Non exclusive standard values.</returns>
		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
		{
			return true;
		}
 
		/// <summary>
		/// Fill in the list of chart type names.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values collection.</returns>
		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
		{
			ChartTypeRegistry	registry = null;
			ArrayList values = new ArrayList();
 
            Chart chart = ConverterHelper.GetChartFromContext(context);
            if (chart!=null)
			{
				// Get chart type registry service
				registry = (ChartTypeRegistry)chart.GetService(typeof(ChartTypeRegistry));
				if(registry != null)
				{
					// Enumerate all chart types names
					foreach(Object obj in registry.registeredChartTypes.Keys)
					{
						if(obj is string)
						{
							values.Add(obj);
						}
					}
				}
				else
				{
                    throw (new InvalidOperationException(SR.ExceptionEditorChartTypeRegistryServiceInaccessible));
				}
			}
 
			// Sort all values
			values.Sort();
 
			return new StandardValuesCollection(values);
		}
	
		#endregion
	}
 
 
	/// <summary>
	/// Data series name converter. Displays list of available series names
	/// </summary>
    internal class SeriesNameConverter : StringConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Standart values supported - return true
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values supported.</returns>
		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
		{
			return true;
		}
 
		/// <summary>
		/// Standart values are not exclusive - return false
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Non exclusive standard values.</returns>
		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
		{
			return false;
		}
 
		/// <summary>
		/// Fill in the list of data series names.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values collection.</returns>
		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
		{
			DataManager	dataManager = null;
			ArrayList values = new ArrayList();
 
			if (context != null && context.Instance != null)
			{
				// Call GetService method using reflection
				MethodInfo	methodInfo = context.Instance.GetType().GetMethod("GetService");
				if(methodInfo != null)
				{
					object[] parameters = new object[1];
					parameters[0] = typeof(DataManager);
					dataManager = (DataManager)methodInfo.Invoke(context.Instance, parameters);
				}
 
				// If data manager service was seccesfully retrived
				if(dataManager != null)
				{
					foreach(Series series in dataManager.Series)
					{
						values.Add(series.Name);
					}
				}
				else
				{
                    throw (new InvalidOperationException(SR.ExceptionEditorChartTypeRegistryServiceInObjectInaccessible(context.Instance.GetType().ToString())));
				}
			}
 
			return new StandardValuesCollection(values);
		}
	
		#endregion
	}
 
	/// <summary>
	/// Data point properties converter
	/// </summary>
    internal class NoNameExpandableObjectConverter : ExpandableObjectConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Overrides the ConvertTo method of TypeConverter.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert.</param>
		/// <param name="destinationType">Convertion destination type.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
		{  
			if (context != null && context.Instance != null)
			{
				if (destinationType == typeof(string)) 
				{
					return "";
				}
			}
 
			return base.ConvertTo(context, culture, value, destinationType);
		}
 
		#endregion
	}
 
	/// <summary>
	/// Converter for the array of doubles
	/// </summary>
    internal class DoubleArrayConverter : ArrayConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Overrides the CanConvertFrom method of TypeConverter.
		/// The ITypeDescriptorContext interface provides the context for the
		/// conversion. Typically this interface is used at design time to 
		/// provide information about the design-time container.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="sourceType">Convertion source type.</param>
		/// <returns>Indicates if convertion is possible.</returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
		{
      		if (sourceType == typeof(string)) 
			{
				return true;
			}
			return base.CanConvertFrom(context, sourceType);
		}
		
		/// <summary>
		/// Overrides the ConvertFrom method of TypeConverter.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert from.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
		{
			object	result = null;
			bool	convertFromDate = false;
 
			// Try to check if value type is date
			if (context != null && context.Instance != null)
			{
				DataPoint dataPoint = (DataPoint)context.Instance;
				if(dataPoint.series != null && dataPoint.series.IsYValueDateTime())
				{
					convertFromDate = true;
				}
			}
 
			// Can convert from string where each array element is separated by comma
            string stringValue = value as string;
			if (stringValue != null) 
			{
				string[] values = stringValue.Split(new char[] {','});
				double[] array = new double[values.Length];
				for(int index = 0; index < values.Length; index ++)
				{
					// Try to convert from date-time string format
                    if (convertFromDate)
                    {
                        DateTime valueAsDate;
                        if (DateTime.TryParse(values[index], CultureInfo.InvariantCulture, DateTimeStyles.None, out valueAsDate))
                        {
                            result = valueAsDate;
                        }
                        else if (DateTime.TryParse(values[index], CultureInfo.CurrentCulture, DateTimeStyles.None, out valueAsDate))
                        {
                            result = valueAsDate;
                        }
                        else
                        {
                            result = null;
                        }
                    }
 
					// Save converted value in the array
					if(result != null)
					{
						array[index] = (double)result;
					}
					else
					{
						array[index] = CommonElements.ParseDouble(values[index]);
					}
				}
										
				return array;
			}
 
			// Call base class
			return base.ConvertFrom(context, culture, value);
		}
		
		/// <summary>
		/// Overrides the ConvertTo method of TypeConverter.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert.</param>
		/// <param name="destinationType">Convertion destination type.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
		{  
			bool	convertToDate = false;
 
			// Check if we should convert to date string format
			if (context != null && context.Instance != null)
			{
				DataPoint dataPoint = (DataPoint)context.Instance;
				if(dataPoint.series != null && dataPoint.series.IsYValueDateTime())
				{
					convertToDate = true;
				}
			}
 
 
			if (destinationType == typeof(string)) 
			{
				double[] array = (double[]) value;
				string result = "";
					
				foreach(double d in array)
				{
					if(convertToDate)
					{
						result += DateTime.FromOADate(d).ToString("g", System.Globalization.CultureInfo.InvariantCulture) + ",";
					}
					else
					{
						result += d.ToString(System.Globalization.CultureInfo.InvariantCulture) + ",";
					}
				}
 
				return result.TrimEnd(',');
			}
 
 
			return base.ConvertTo(context, culture, value, destinationType);
		}
	
		#endregion
	}
 
	/// <summary>
	/// Converts data point values to and from date string format
	/// </summary>
    internal class DataPointValueConverter : DoubleConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Convert values to date string
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert.</param>
		/// <param name="destinationType">Convertion destination type.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
		{  
			if (context != null && context.Instance != null)
			{
				DataPoint	dataPoint = (DataPoint)context.Instance;
 
				if (destinationType == typeof(string) && dataPoint.series.IsXValueDateTime()) 
				{
					DateTime valueAsSate = DateTime.FromOADate((double)value);
					return valueAsSate.ToString("g", System.Globalization.CultureInfo.CurrentCulture);
				}
			}
			return base.ConvertTo(context, culture, value, destinationType);
		}
 
		/// <summary>
		/// Convert values from date string.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert from.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
		{
			if (context != null && context.Instance != null)
			{
                string stringValue = value as string;
 
                if (stringValue != null)
                {
                    DataPoint dataPoint = (DataPoint)context.Instance;
 
                    if (dataPoint.series.IsXValueDateTime())
                    {
                        DateTime valueAsSate = DateTime.Parse(stringValue, System.Globalization.CultureInfo.CurrentCulture);
                        return valueAsSate.ToOADate();
                    }
                }
			}
 
			return base.ConvertFrom(context, culture, value);
		}
 
		#endregion
	}
 
	/// <summary>
	/// Removes the String type for Y axes
	/// </summary>
    internal class SeriesYValueTypeConverter : EnumConverter
	{
		#region Converter methods
 
		/// <summary>
		/// Public constructor
		/// </summary>
		/// <param name="type">Enumeration type.</param>
		public SeriesYValueTypeConverter(Type type) : base(type)
		{
		}
 
		/// <summary>
		/// Fill in the list of data series names.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <returns>Standard values collection.</returns>
		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
		{
			ArrayList values = new ArrayList();
 
			// Call base class
			StandardValuesCollection	val = base.GetStandardValues(context);
 
			// Remove string type
			foreach(object o in val)
			{
				if(o.ToString() != "String")
				{
					
					values.Add(o);
				}
			}
 
			return new StandardValuesCollection(values);
		}
	
		#endregion
	}
 
	/// <summary>
	/// Data point properties converter
	/// </summary>
    internal class ColorArrayConverter : TypeConverter
	{
		#region Converter methods
 
		/// <summary>
		/// This method overrides CanConvertTo from TypeConverter. This is called when someone
		/// wants to convert an instance of object to another type.  Here,
		/// only conversion to an InstanceDescriptor is supported.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="destinationType">Destination type.</param>
		/// <returns>True if object can be converted.</returns>
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			if (destinationType == typeof(string))
			{
				return true;
			}
 
			// Always call the base to see if it can perform the conversion.
			return base.CanConvertTo(context, destinationType);
		}
 
		/// <summary>
		/// Overrides the CanConvertFrom method of TypeConverter.
		/// The ITypeDescriptorContext interface provides the context for the
		/// conversion. Typically this interface is used at design time to 
		/// provide information about the design-time container.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="sourceType">Convertion source type.</param>
		/// <returns>Indicates if convertion is possible.</returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
		{
			if (sourceType == typeof(string)) 
			{
				return true;
			}
			return base.CanConvertFrom(context, sourceType);
		}
 
		/// <summary>
		/// Overrides the ConvertTo method of TypeConverter.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert.</param>
		/// <param name="destinationType">Convertion destination type.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
		{  
			if (destinationType == typeof(string)) 
			{
				return ColorArrayToString(value as Color[]);
			}
 
			return base.ConvertTo(context, culture, value, destinationType);
		}
 
		/// <summary>
		/// Overrides the ConvertFrom method of TypeConverter.
		/// </summary>
		/// <param name="context">Descriptor context.</param>
		/// <param name="culture">Culture information.</param>
		/// <param name="value">Value to convert from.</param>
		/// <returns>Converted object.</returns>
		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
		{
			// Can convert from string where each array element is separated by comma
            string stringValue = value as string;
			if (stringValue != null) 
			{
                return StringToColorArray(stringValue);
			}
 
			// Call base class
			return base.ConvertFrom(context, culture, value);
		}
 
		/// <summary>
		/// Converts array of colors into string.
		/// </summary>
		/// <param name="colors">Colors array.</param>
		/// <returns>Result string.</returns>
		public static string ColorArrayToString(Color[] colors)
		{
			if(colors != null && colors.GetLength(0) > 0)
			{
				ColorConverter colorConverter = new ColorConverter();
				string result = string.Empty;
				foreach(Color color in colors)
				{
					if(result.Length > 0)
					{
						result += "; ";
					}
					result += colorConverter.ConvertToInvariantString(color);
				}
				return result;
			}
			return string.Empty;
		}
 
		/// <summary>
		/// Converts string into array of colors.
		/// </summary>
		/// <param name="colorNames">String data.</param>
		/// <returns>Array of colors.</returns>
		public static Color[] StringToColorArray(String colorNames)
		{
			ColorConverter colorConverter = new ColorConverter();
			Color[] array = new Color[0];
			if(colorNames.Length > 0)
			{
				string[] colorValues = colorNames.Split(';');
				array = new Color[colorValues.Length];
				int index = 0;
				foreach(string str in colorValues)
				{
					array[index++] = (Color)colorConverter.ConvertFromInvariantString(str);
				}
			}
			return array;
		}
 
		#endregion
	}
 
    /// <summary>
    /// Provides a set of helper methods used by converters
    /// </summary>
    internal static class ConverterHelper 
    {
 
        #region Static
        /// <summary>
        /// Gets the chart from context.
        /// </summary>
        /// <param name="context">The context.</param>
        public static Chart GetChartFromContext(ITypeDescriptorContext context)
        {
            if (context == null || context.Instance == null)
            {
                return null;
            }
 
            IChartElement element = context.Instance as IChartElement;
            if (element != null && element.Common != null)
            {
                return element.Common.Chart;
            }
 
            IList list = context.Instance as IList;
            if (list != null && list.Count > 0)
            {
                element = list[0] as IChartElement;
                if (element.Common != null)
                {
                    return element.Common.Chart;
                }
 
            }
 
            Chart chart = context.Instance as Chart;
            if (chart != null)
            {
                return chart;
            }
 
            IServiceProvider provider = context.Instance as IServiceProvider;
            if (provider != null)
            {
                chart = provider.GetService(typeof(Chart)) as Chart;
                if (chart != null)
                {
                    return chart;
                }
            }
 
            return null;
        }
        #endregion
    }
}