// 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); } } }