// 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.
//
// Purpose: Design-time editors and converters for the Axes array.
//
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using System.Reflection;
using FastReport.DataVisualization.Charting;
namespace FastReport.Design.DataVisualization.Charting
{
#if DESIGNER
///
/// Designer editor for the chart areas collection.
///
internal class AxesArrayEditor : ArrayEditor
{
#region Fields and Constructor
// Collection form
CollectionForm _form = null;
// Help topic string
private string _helpTopic = "";
///
/// Object constructor.
///
public AxesArrayEditor() : base(typeof(Axis[]))
{
}
#endregion
#region Methods
///
/// Items can not be removed.
///
/// Value.
/// False if can't remove.
protected override bool CanRemoveInstance(object value)
{
return false;
}
///
/// Ovveride the HelpTopic property to provide different topics,
/// depending on selected property.
///
protected override string HelpTopic
{
get
{
return (_helpTopic.Length == 0) ? base.HelpTopic : _helpTopic;
}
}
///
/// Returns the collection form property grid. Added for VS2005 compatibility.
///
///
///
private PropertyGrid GetPropertyGrid(System.Windows.Forms.Control.ControlCollection controls)
{
foreach (System.Windows.Forms.Control control in controls)
{
PropertyGrid grid = control as PropertyGrid;
if (grid != null)
{
return grid;
}
if (control.Controls.Count > 0)
{
grid = GetPropertyGrid(control.Controls);
if (grid != null)
{
return grid;
}
}
}
return null;
}
///
/// Collect the collection editor form buttons into array. Added for VS2005 compatibility.
///
///
///
private void CollectButtons(ArrayList buttons, System.Windows.Forms.Control.ControlCollection controls)
{
foreach (System.Windows.Forms.Control control in controls)
{
if (control is System.Windows.Forms.Button)
{
buttons.Add(control);
}
if (control.Controls.Count > 0)
{
CollectButtons(buttons, control.Controls);
}
}
}
///
/// Displaying help for the curently selected item in the property grid
///
protected override void ShowHelp()
{
// Init topic name
_helpTopic = "";
PropertyGrid grid = this.GetPropertyGrid(_form.Controls);;
// Check currently selected grid item
if(grid != null)
{
GridItem item = grid.SelectedGridItem;
if(item != null && (item.GridItemType == GridItemType.Property || item.GridItemType == GridItemType.ArrayValue))
{
_helpTopic = item.PropertyDescriptor.ComponentType.ToString() + "." + item.PropertyDescriptor.Name;
}
}
// Call base class
base.ShowHelp();
// Re-Init topic name
_helpTopic = "";
}
///
/// Creates editor's form.
///
/// Collection form.
protected override CollectionForm CreateCollectionForm()
{
// Create collection form using the base class
_form = base.CreateCollectionForm();
// Changed Apr 29, DT, for VS2005 compatibility
PropertyGrid grid = GetPropertyGrid(_form.Controls);
if (grid != null)
{
// Show properties help
grid.HelpVisible = true;
grid.CommandsVisibleIfAvailable = true;
}
// Changed Apr 29, DT, for VS2005 compatibility
ArrayList buttons = new ArrayList();
this.CollectButtons(buttons, _form.Controls);
foreach (System.Windows.Forms.Button button in buttons)
{
if (button.Name.StartsWith("add", StringComparison.OrdinalIgnoreCase) ||
button.Name.StartsWith("remove", StringComparison.OrdinalIgnoreCase) ||
button.Text.Length == 0)
{
button.Enabled = false;
button.EnabledChanged += new EventHandler(Button_EnabledChanged);
}
}
return _form;
}
///
/// Flag to prevent stack overflow.
///
private bool _button_EnabledChanging = false;
///
/// Handles the EnabledChanged event of the Button control.
///
/// The source of the event.
/// The instance containing the event data.
private void Button_EnabledChanged(object sender, EventArgs e)
{
if ( _button_EnabledChanging ) return;
_button_EnabledChanging = true;
try
{
((System.Windows.Forms.Button)sender).Enabled = false;
}
finally
{
_button_EnabledChanging = false;
}
}
#endregion
}
#endif
internal class DataPointCustomPropertiesConverter : TypeConverter
{
///
/// Returns whether this object supports properties, using the specified context.
///
/// An that provides a format context.
///
/// true if should be called to find the properties of this object; otherwise, false.
///
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
///
/// Returns a collection of properties for the type of array specified by the value parameter, using the specified context and attributes.
///
/// An that provides a format context.
/// An that specifies the type of array for which to get properties.
/// An array of type that is used as a filter.
///
/// A with the properties that are exposed for this data type, or null if there are no properties.
///
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
// Fill collection with properties descriptors
PropertyDescriptorCollection propDescriptors = TypeDescriptor.GetProperties(value, attributes, false);
// Return original collection if not in design mode
if (context != null && context.Instance is ChartElement &&
(context.Instance as ChartElement).Chart != null &&
(context.Instance as ChartElement).Chart.IsDesignMode())
{
// Create new descriptors collection
PropertyDescriptorCollection newPropDescriptors = new PropertyDescriptorCollection(null);
// Loop through all original property descriptors
foreach (PropertyDescriptor propertyDescriptor in propDescriptors)
{
// Change name of "CustomAttributesEx" property to "CustomProperties"
if (propertyDescriptor.Name == "CustomAttributesEx")
{
DynamicPropertyDescriptor dynPropDesc = new DynamicPropertyDescriptor(
propertyDescriptor,
"CustomProperties");
newPropDescriptors.Add(dynPropDesc);
}
else
{
newPropDescriptors.Add(propertyDescriptor);
}
}
return newPropDescriptors;
}
// Return original collection if not in design mode
return propDescriptors;
}
///
/// Converts the given value object to the specified type, using the specified context and culture information.
///
/// An that provides a format context.
/// A . If null is passed, the current culture is assumed.
/// The to convert.
/// The to convert the parameter to.
///
/// An that represents the converted value.
///
/// The parameter is null.
/// The conversion cannot be performed.
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (context != null)
{
if (destinationType == typeof(string))
{
return "";
}
} // Always call base, even if you can't convert.
return base.ConvertTo(context, culture, value, destinationType);
}
}
///
/// DataPoint Converter - helps windows form serializer to create inline datapoints.
///
internal class DataPointConverter : DataPointCustomPropertiesConverter
{
///
/// 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.
///
/// Descriptor context.
/// Destination type.
/// True if object can be converted.
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(InstanceDescriptor))
{
return true;
}
// Always call the base to see if it can perform the conversion.
return base.CanConvertTo(context, destinationType);
}
///
/// This methods performs the actual conversion from an object to an InstanceDescriptor.
///
/// Descriptor context.
/// Culture information.
/// Object value.
/// Destination type.
/// Converted object.
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
DataPoint dataPoint = value as DataPoint;
if (destinationType == typeof(InstanceDescriptor) && dataPoint != null)
{
if (dataPoint.YValues.Length > 1)
{
ConstructorInfo ci = typeof(DataPoint).GetConstructor(new Type[] { typeof(double), typeof(string) });
string yValues = "";
foreach (double y in dataPoint.YValues)
{
yValues += y.ToString(System.Globalization.CultureInfo.InvariantCulture) + ",";
}
return new InstanceDescriptor(ci, new object[] { dataPoint.XValue, yValues.TrimEnd(',') }, false);
}
else
{
ConstructorInfo ci = typeof(DataPoint).GetConstructor(new Type[] { typeof(double), typeof(double) });
return new InstanceDescriptor(ci, new object[] { dataPoint.XValue, dataPoint.YValues[0] }, false);
}
}
// Always call base, even if you can't convert.
return base.ConvertTo(context, culture, value, destinationType);
}
}
}