2321 lines
68 KiB
C#
2321 lines
68 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Design;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Globalization;
|
|
using System.Windows.Forms;
|
|
using DevComponents.DotNetBar.Charts.Style;
|
|
|
|
namespace DevComponents.DotNetBar.Charts
|
|
{
|
|
/// <summary>
|
|
/// ChartPanel is a container object which holds
|
|
/// and defines ChartGraphs, which can be single or multiple.
|
|
/// </summary>
|
|
[TypeConverter(typeof(BlankExpandableObjectConverter))]
|
|
public class ChartPanel : ChartContainer, IEffectiveStyle
|
|
{
|
|
#region Private variables
|
|
|
|
private States _States;
|
|
|
|
private ChartContainerCollection _ChartContainers;
|
|
private ContainerLayout _ContainerLayout = ContainerLayout.Auto;
|
|
|
|
private ChartMatrix _ChartMatrix;
|
|
private List<ChartContainer> _MatrixList;
|
|
|
|
private DefaultVisualStyles _DefaultVisualStyles;
|
|
|
|
private ChartPanelVisualStyle _ChartPanelVisualStyle;
|
|
private EffectiveStyle<ChartPanelVisualStyle> _EffectivePanelStyle;
|
|
|
|
private List<ChartLegendItem> _LegendData;
|
|
private LegendSource _LegendSource = (LegendSource.NestedCharts | LegendSource.NestedPanels);
|
|
|
|
#endregion
|
|
|
|
public ChartPanel(string name)
|
|
: this()
|
|
{
|
|
Name = name;
|
|
}
|
|
|
|
public ChartPanel()
|
|
{
|
|
InitDefaultStates();
|
|
|
|
_EffectivePanelStyle = new EffectiveStyle<ChartPanelVisualStyle>(this);
|
|
|
|
Legend.Visible = false;
|
|
}
|
|
|
|
#region InitDefaultStates
|
|
|
|
private void InitDefaultStates()
|
|
{
|
|
SetState(States.AutoFillChartMatrix, true);
|
|
SetState(States.AutoSizeChartMatrix, true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public properties
|
|
|
|
#region AutoFillChartMatrix
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the ChartMatrix is auto filled
|
|
/// from the ChartContainer collection.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Layout")]
|
|
[Description("Indicates whether the ChartMatrix is auto filled from the ChartContainer collection.")]
|
|
public bool AutoFillChartMatrix
|
|
{
|
|
get { return (TestState(States.AutoFillChartMatrix)); }
|
|
|
|
set
|
|
{
|
|
if (value != AutoFillChartMatrix)
|
|
{
|
|
SetState(States.AutoFillChartMatrix, value);
|
|
|
|
OnPropertyChangedEx("AutoFillChartMatrix", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AutoGenSeriesCollection
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether series definitions are auto generated from the set DataSource.
|
|
/// </summary>
|
|
[DefaultValue(false), Category("Data")]
|
|
[Description("Indicates whether series definitions are auto generated from the set DataSource.")]
|
|
public bool AutoGenSeriesCollection
|
|
{
|
|
get { return (TestState(States.AutoGenSeriesCollection)); }
|
|
|
|
set
|
|
{
|
|
if (value != AutoGenSeriesCollection)
|
|
{
|
|
SetState(States.AutoGenSeriesCollection, value);
|
|
|
|
OnPropertyChangedEx("AutoGenSeriesCollection", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AutoSizeChartMatrix
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the ChartMatrix is auto sized
|
|
/// from the ChartContainer collection.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Layout")]
|
|
[Description("Indicates whether the ChartMatrix is auto sized from the ChartContainer collection.")]
|
|
public bool AutoSizeChartMatrix
|
|
{
|
|
get { return (TestState(States.AutoSizeChartMatrix)); }
|
|
|
|
set
|
|
{
|
|
if (value != AutoSizeChartMatrix)
|
|
{
|
|
SetState(States.AutoSizeChartMatrix, value);
|
|
|
|
OnPropertyChangedEx("AutoSizeChartMatrix", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ChartContainers
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the collection of Chart Containers (ChartPanels and Chart graphs).
|
|
/// </summary>
|
|
[Category("Layout")]
|
|
[Description("Indicates the reference to the collection of Chart Containers (ChartPanels and Chart graphs).")]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public ChartContainerCollection ChartContainers
|
|
{
|
|
get
|
|
{
|
|
if (_ChartContainers == null)
|
|
{
|
|
_ChartContainers = new ChartContainerCollection();
|
|
|
|
_ChartContainers.CollectionChanged += ChartContainersCollectionChanged;
|
|
}
|
|
|
|
return (_ChartContainers);
|
|
}
|
|
|
|
internal set
|
|
{
|
|
if (_ChartContainers != null)
|
|
_ChartContainers.CollectionChanged -= ChartContainersCollectionChanged;
|
|
|
|
_ChartContainers = value;
|
|
|
|
if (_ChartContainers != null)
|
|
_ChartContainers.CollectionChanged += ChartContainersCollectionChanged;
|
|
}
|
|
}
|
|
|
|
#region ChartContainersCollectionChanged
|
|
|
|
void ChartContainersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
ChartControl chartControl = ChartControl;
|
|
|
|
switch (e.Action)
|
|
{
|
|
case NotifyCollectionChangedAction.Add:
|
|
foreach (ChartContainer item in e.NewItems)
|
|
{
|
|
item.Parent = this;
|
|
|
|
if (chartControl != null)
|
|
AddSelectedItems(chartControl, item);
|
|
}
|
|
break;
|
|
|
|
case NotifyCollectionChangedAction.Replace:
|
|
foreach (ChartContainer item in e.OldItems)
|
|
{
|
|
if (chartControl != null)
|
|
RemoveSelectedItems(chartControl, item);
|
|
|
|
item.Parent = null;
|
|
}
|
|
|
|
foreach (ChartContainer item in e.NewItems)
|
|
{
|
|
item.Parent = this;
|
|
|
|
if (chartControl != null)
|
|
AddSelectedItems(chartControl, item);
|
|
}
|
|
break;
|
|
|
|
case NotifyCollectionChangedAction.Remove:
|
|
foreach (ChartContainer item in e.OldItems)
|
|
{
|
|
item.Parent = null;
|
|
|
|
if (chartControl != null)
|
|
RemoveSelectedItems(chartControl, item);
|
|
}
|
|
break;
|
|
}
|
|
|
|
InvalidateLayout();
|
|
}
|
|
|
|
#region AddSelectedItems
|
|
|
|
private void AddSelectedItems(ChartControl chartControl, ChartContainer item)
|
|
{
|
|
BaseChart chart = item as BaseChart;
|
|
|
|
if (chart != null)
|
|
{
|
|
if (chart.IsSelected == true)
|
|
chartControl.SetSelected(item, true);
|
|
}
|
|
else if (item is ChartPanel)
|
|
{
|
|
foreach (ChartContainer citem in ((ChartPanel)item).ChartContainers)
|
|
AddSelectedItems(chartControl, citem);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RemoveSelectedItems
|
|
|
|
private void RemoveSelectedItems(ChartControl chartControl, ChartContainer item)
|
|
{
|
|
BaseChart chart = item as BaseChart;
|
|
|
|
if (chart != null)
|
|
{
|
|
if (chart.IsSelected == true)
|
|
chartControl.SetSelected(item, false);
|
|
}
|
|
else if (item is ChartPanel)
|
|
{
|
|
foreach (ChartContainer citem in ((ChartPanel)item).ChartContainers)
|
|
RemoveSelectedItems(chartControl, citem);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ChartMatrix
|
|
|
|
/// <summary>
|
|
/// Gets the Matrix used to display the defined Panels and Charts in a Matrix format.
|
|
/// </summary>
|
|
[Category("Layout")]
|
|
[Description("Indicates the Matrix used to display the defined Panels and Charts in a Matrix format.")]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public ChartMatrix ChartMatrix
|
|
{
|
|
get
|
|
{
|
|
if (_ChartMatrix == null)
|
|
{
|
|
_ChartMatrix = new ChartMatrix();
|
|
_ChartMatrix.Parent = this;
|
|
|
|
_ChartMatrix.PropertyChanged += ChartMatrix_PropertyChanged;
|
|
}
|
|
|
|
return (_ChartMatrix);
|
|
}
|
|
|
|
internal set
|
|
{
|
|
if (_ChartMatrix != value)
|
|
{
|
|
if (_ChartMatrix != null)
|
|
{
|
|
_ChartMatrix.PropertyChanged -= ChartMatrix_PropertyChanged;
|
|
_ChartMatrix.Parent = null;
|
|
}
|
|
|
|
_ChartMatrix = value;
|
|
|
|
if (_ChartMatrix != null)
|
|
{
|
|
_ChartMatrix.Parent = this;
|
|
_ChartMatrix.PropertyChanged += ChartMatrix_PropertyChanged;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#region ChartMatrix_PropertyChanged
|
|
|
|
void ChartMatrix_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (ChartControl != null)
|
|
{
|
|
if (e.PropertyName.Equals("Size") || e.PropertyName.Equals("Height") || e.PropertyName.Equals("Width"))
|
|
ChartControl.DoChartMatrixResizedEvent(this);
|
|
|
|
if (ChartControl.InUpdateLayout == false)
|
|
InvalidateLayout();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ChartPanelVisualStyle
|
|
|
|
/// <summary>
|
|
/// Gets or sets the visual style for the Chart Panel.
|
|
/// </summary>
|
|
[Category("Style")]
|
|
[Description("Indicates the visual style for the Chart Panel.")]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public ChartPanelVisualStyle ChartPanelVisualStyle
|
|
{
|
|
get
|
|
{
|
|
if (_ChartPanelVisualStyle == null)
|
|
{
|
|
_ChartPanelVisualStyle = new ChartPanelVisualStyle();
|
|
|
|
StyleVisualChangeHandler(null, _ChartPanelVisualStyle);
|
|
}
|
|
|
|
return (_ChartPanelVisualStyle);
|
|
}
|
|
|
|
set
|
|
{
|
|
if (_ChartPanelVisualStyle != value)
|
|
{
|
|
ChartPanelVisualStyle oldValue = _ChartPanelVisualStyle;
|
|
|
|
_ChartPanelVisualStyle = value;
|
|
|
|
OnStyleChanged("ChartPanelVisualStyle", oldValue, value);
|
|
|
|
if (oldValue != null)
|
|
oldValue.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ContainerLayout
|
|
|
|
/// <summary>
|
|
/// Gets or sets the layout (horizontal, vertical, matrix) for the defined Chart Containers.
|
|
/// </summary>
|
|
[DefaultValue(ContainerLayout.Auto), Category("Layout")]
|
|
[Description("Indicates the layout (horizontal, vertical, matrix) for the defined Chart Containers.")]
|
|
public ContainerLayout ContainerLayout
|
|
{
|
|
get { return (_ContainerLayout); }
|
|
|
|
set
|
|
{
|
|
if (_ContainerLayout != value)
|
|
{
|
|
_ContainerLayout = value;
|
|
|
|
OnPropertyChangedEx("ContainerLayout", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DefaultVisualStyles
|
|
|
|
///<summary>
|
|
/// Gets or sets the Default Visual Styles for each Chart element.
|
|
///</summary>
|
|
[Browsable(true), Category("Style"), DefaultValue(null)]
|
|
[Description("Indicates the Default Visual Styles for each Chart element.")]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public DefaultVisualStyles DefaultVisualStyles
|
|
{
|
|
get
|
|
{
|
|
if (_DefaultVisualStyles == null)
|
|
{
|
|
_DefaultVisualStyles = new DefaultVisualStyles();
|
|
|
|
_DefaultVisualStyles.PropertyChanged += DefaultVisualStylesPropertyChanged;
|
|
}
|
|
|
|
return (_DefaultVisualStyles);
|
|
}
|
|
|
|
set
|
|
{
|
|
if (_DefaultVisualStyles != value)
|
|
{
|
|
if (_DefaultVisualStyles != null)
|
|
_DefaultVisualStyles.PropertyChanged -= DefaultVisualStylesPropertyChanged;
|
|
|
|
_DefaultVisualStyles = value;
|
|
|
|
if (_DefaultVisualStyles != null)
|
|
_DefaultVisualStyles.PropertyChanged += DefaultVisualStylesPropertyChanged;
|
|
}
|
|
}
|
|
}
|
|
|
|
#region DefaultVisualStylesPropertyChanged
|
|
|
|
private void DefaultVisualStylesPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
VisualChangeType changeType = ((VisualPropertyChangedEventArgs)e).ChangeType;
|
|
|
|
switch (changeType)
|
|
{
|
|
case VisualChangeType.Layout:
|
|
InvalidateRender();
|
|
break;
|
|
|
|
case VisualChangeType.Render:
|
|
InvalidateRender();
|
|
break;
|
|
}
|
|
|
|
//ChartControl cc = ChartControl;
|
|
|
|
//if (cc != null)
|
|
// cc.UpdateStyleCount();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region EffectivePanelStyle
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the panel's effective (cached, composite) style.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public ChartPanelVisualStyle EffectivePanelStyle
|
|
{
|
|
get { return (_EffectivePanelStyle.Style); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region LegendSource
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source for the items in the panel legend.
|
|
/// </summary>
|
|
[Category("Layout")]
|
|
[Description("Indicates the source for the items in the panel legend.")]
|
|
[Editor("DevComponents.Charts.Design.FlagsEnumUIEditor, DevComponents.Charts.Design, " +
|
|
"Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))]
|
|
public LegendSource LegendSource
|
|
{
|
|
get { return (_LegendSource); }
|
|
|
|
set
|
|
{
|
|
if (value != _LegendSource)
|
|
{
|
|
_LegendSource = value;
|
|
|
|
OnPropertyChangedEx("LegendSource", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
|
|
internal virtual bool ShouldSerializeLegendSource()
|
|
{
|
|
return (_LegendSource != (LegendSource.NestedCharts | LegendSource.NestedPanels));
|
|
}
|
|
|
|
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
|
|
internal virtual void ResetLegendSource()
|
|
{
|
|
LegendSource = (LegendSource.NestedCharts | LegendSource.NestedPanels);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Internal properties
|
|
|
|
#region LegendData
|
|
|
|
internal List<ChartLegendItem> LegendData
|
|
{
|
|
get { return (_LegendData); }
|
|
|
|
set
|
|
{
|
|
if (_LegendData != null)
|
|
{
|
|
foreach (ChartLegendItem item in _LegendData)
|
|
item.Dispose();
|
|
}
|
|
|
|
_LegendData = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region MeasureOverride
|
|
|
|
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
|
|
{
|
|
ChartPanelVisualStyle pstyle = EffectivePanelStyle;
|
|
ContainerVisualStyle cstyle = GetEffectiveContainerStyle();
|
|
|
|
if (cstyle.DropShadow.Enabled == Tbool.True)
|
|
{
|
|
layoutInfo.LayoutBounds.Height -= 3;
|
|
layoutInfo.LayoutBounds.Width -= 3;
|
|
}
|
|
|
|
BoundsRelative = layoutInfo.LayoutBounds;
|
|
|
|
FrameBounds = GetAdjustedBounds(BoundsRelative, cstyle.Margin);
|
|
ContentBounds = GetAdjustedBounds(FrameBounds, cstyle.BorderThickness);
|
|
ContentBounds = GetAdjustedBounds(ContentBounds, cstyle.Padding);
|
|
|
|
layoutInfo.LayoutBounds = ContentBounds;
|
|
|
|
base.MeasureOverride(layoutInfo);
|
|
|
|
ContentBounds = layoutInfo.LayoutBounds;
|
|
ContentBoundsEx = ContentBounds;
|
|
|
|
if (AutoFillChartMatrix == true)
|
|
AutoFillMatrix(layoutInfo);
|
|
else
|
|
FillMatrix();
|
|
|
|
Size size = MeasureMatrix(layoutInfo, pstyle);
|
|
|
|
Size minContentSize = Dpi.Size(MinContentSize);
|
|
|
|
if (size.Width < minContentSize.Width)
|
|
size.Width = minContentSize.Width;
|
|
|
|
if (size.Height < minContentSize.Height)
|
|
size.Height = minContentSize.Height;
|
|
|
|
Rectangle r = ContentBoundsEx;
|
|
|
|
if (size.Width > r.Width)
|
|
r.Width = size.Width;
|
|
|
|
if (size.Height > r.Height)
|
|
r.Height = size.Height;
|
|
|
|
ContentBoundsEx = r;
|
|
|
|
if ((ContentBoundsEx.Width > ContentBounds.Width && ContentBoundsEx.Height == ContentBounds.Height) ||
|
|
(ContentBoundsEx.Height > ContentBounds.Height && ContentBoundsEx.Width == ContentBounds.Width))
|
|
{
|
|
layoutInfo.LayoutBounds = ContentBounds;
|
|
|
|
if (ContentBoundsEx.Width > ContentBounds.Width)
|
|
layoutInfo.LayoutBounds.Height -= (HScrollBar.Height + 1);
|
|
|
|
if (ContentBoundsEx.Height > ContentBounds.Height)
|
|
layoutInfo.LayoutBounds.Width -= (VScrollBar.Width + 1);
|
|
|
|
size = MeasureMatrix(layoutInfo, pstyle);
|
|
|
|
if (size.IsEmpty == false)
|
|
{
|
|
if (size.Width < minContentSize.Width)
|
|
size.Width = minContentSize.Width;
|
|
|
|
if (size.Height < minContentSize.Height)
|
|
size.Height = minContentSize.Height;
|
|
|
|
r = ContentBoundsEx;
|
|
r.Size = size;
|
|
ContentBoundsEx = r;
|
|
}
|
|
}
|
|
else if (ContentBoundsEx.Width > ContentBounds.Width &&
|
|
ContentBoundsEx.Height > ContentBounds.Height)
|
|
{
|
|
r.Width += (VScrollBar.Width + 1);
|
|
r.Height += (HScrollBar.Height + 1);
|
|
|
|
ContentBoundsEx = r;
|
|
}
|
|
}
|
|
|
|
#region FillMatrix
|
|
|
|
private void FillMatrix()
|
|
{
|
|
Size size = Size.Empty;
|
|
|
|
_MatrixList = new List<ChartContainer>();
|
|
|
|
foreach (ChartContainer cc in ChartContainers)
|
|
{
|
|
if (cc.Visible == true)
|
|
{
|
|
if (cc.MatrixDisplayBounds.Right > 0 && cc.MatrixDisplayBounds.Bottom > 0)
|
|
{
|
|
_MatrixList.Add(cc);
|
|
|
|
if (cc.MatrixDisplayBounds.Right > size.Width)
|
|
size.Width = cc.MatrixDisplayBounds.Right;
|
|
|
|
if (cc.MatrixDisplayBounds.Bottom > size.Height)
|
|
size.Height = cc.MatrixDisplayBounds.Bottom;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (AutoSizeChartMatrix == true)
|
|
{
|
|
ChartMatrix.Size = size;
|
|
}
|
|
else
|
|
{
|
|
if (size.Width > ChartMatrix.Size.Width || size.Height > ChartMatrix.Size.Height)
|
|
throw new Exception("ChartMatrix not large enough for assigned containers.");
|
|
}
|
|
|
|
ChartMatrix.Clear();
|
|
|
|
_MatrixList.Sort(new MatrixComparer());
|
|
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
Rectangle r = cc.MatrixDisplayBounds;
|
|
|
|
for (int i = r.X; i < r.Right; i++)
|
|
{
|
|
for (int j = r.Y; j < r.Bottom; j++)
|
|
ChartMatrix[i, j] = cc;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AutoFillMatrix
|
|
|
|
private void AutoFillMatrix(ChartLayoutInfo layoutInfo)
|
|
{
|
|
_MatrixList = new List<ChartContainer>();
|
|
|
|
int count = VisibleContainerCount();
|
|
|
|
if (count > 0)
|
|
{
|
|
Size size = ChartMatrix.Size;
|
|
|
|
ContainerLayout clayout = ContainerLayout;
|
|
|
|
if (AutoSizeChartMatrix == true)
|
|
size = GetAutoMatrixSize(layoutInfo, count, ref clayout);
|
|
|
|
ChartMatrix.Size = size;
|
|
|
|
int n = -1;
|
|
|
|
if (clayout == ContainerLayout.Horizontal)
|
|
{
|
|
for (int i = 0; i < size.Height; i++)
|
|
{
|
|
for (int j = 0; j < size.Width; j++)
|
|
{
|
|
ChartContainer container = GetNextVisibleContainer(ref n);
|
|
|
|
if (container == null)
|
|
{
|
|
i = size.Height;
|
|
break;
|
|
}
|
|
|
|
ChartMatrix[j, i] = container;
|
|
container.MatrixDisplayBounds = new Rectangle(j, i, 1, 1);
|
|
|
|
_MatrixList.Add(container);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < size.Width; i++)
|
|
{
|
|
for (int j = 0; j < size.Height; j++)
|
|
{
|
|
ChartContainer container = GetNextVisibleContainer(ref n);
|
|
|
|
if (container == null)
|
|
{
|
|
i = size.Width;
|
|
break;
|
|
}
|
|
|
|
ChartMatrix[i, j] = container;
|
|
container.MatrixDisplayBounds = new Rectangle(i, j, 1, 1);
|
|
|
|
_MatrixList.Add(container);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#region VisibleContainerCount
|
|
|
|
private int VisibleContainerCount()
|
|
{
|
|
int count = 0;
|
|
|
|
foreach (ChartContainer cc in ChartContainers)
|
|
{
|
|
if (cc.Visible == true)
|
|
count++;
|
|
}
|
|
|
|
return (count);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetAutoMatrixSize
|
|
|
|
private Size GetAutoMatrixSize(
|
|
ChartLayoutInfo layoutInfo, int count, ref ContainerLayout clayout)
|
|
{
|
|
if (count > 0)
|
|
{
|
|
if (ContainerLayout == ContainerLayout.Horizontal)
|
|
return (new Size(count, 1));
|
|
|
|
if (ContainerLayout == ContainerLayout.Vertical)
|
|
return (new Size(1, count));
|
|
|
|
double w = Math.Ceiling(Math.Sqrt((double)count));
|
|
double h = (w * w == count) ? w : Math.Ceiling(count / w);
|
|
|
|
if (w != h)
|
|
{
|
|
if ((layoutInfo.LayoutBounds.Width > layoutInfo.LayoutBounds.Height && w < h) ||
|
|
(layoutInfo.LayoutBounds.Width < layoutInfo.LayoutBounds.Height && w > h))
|
|
{
|
|
clayout = ContainerLayout.Vertical;
|
|
|
|
return (new Size((int)h, (int)w));
|
|
}
|
|
}
|
|
|
|
clayout = ContainerLayout.Horizontal;
|
|
|
|
return (new Size((int)w, (int)h));
|
|
}
|
|
|
|
return (Size.Empty);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetNextVisibleContainer
|
|
|
|
private ChartContainer GetNextVisibleContainer(ref int n)
|
|
{
|
|
n++;
|
|
|
|
while (n < ChartContainers.Count)
|
|
{
|
|
if (ChartContainers[n].Visible == true)
|
|
return (ChartContainers[n]);
|
|
|
|
n++;
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region MeasureMatrix
|
|
|
|
private Size MeasureMatrix(ChartLayoutInfo layoutInfo, ChartPanelVisualStyle style)
|
|
{
|
|
int hLen = GetMatrixLayout(layoutInfo, ContainerLayout.Horizontal);
|
|
int vLen = GetMatrixLayout(layoutInfo, ContainerLayout.Vertical);
|
|
|
|
Rectangle layoutBounds = layoutInfo.LayoutBounds;
|
|
Point ptLayout = layoutBounds.Location;
|
|
|
|
for (int i = 0; i < ChartMatrix.Width; i++)
|
|
{
|
|
int width = ChartMatrix.ColumnProperties[i].Length;
|
|
|
|
Point ptBounds = ptLayout;
|
|
|
|
for (int j = 0; j < ChartMatrix.Height; j++)
|
|
{
|
|
int height = ChartMatrix.RowProperties[j].Length;
|
|
|
|
ChartMatrix.BoundsArray[i, j] = new Rectangle(ptBounds, new Size(width, height));
|
|
|
|
ptBounds.Y += height;
|
|
}
|
|
|
|
ptLayout.X += width;
|
|
}
|
|
|
|
int dx = style.DividerLineX.LineWidth / 2;
|
|
int dy = style.DividerLineY.LineWidth / 2;
|
|
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
Rectangle r = GetMatrixBounds(cc, dx, dy);
|
|
|
|
cc.BoundsRelative = r;
|
|
|
|
layoutInfo.LayoutBounds = cc.BoundsRelative;
|
|
|
|
cc.Measure(layoutInfo);
|
|
}
|
|
|
|
AlignMatrix(layoutInfo);
|
|
|
|
return (new Size(hLen, vLen));
|
|
}
|
|
|
|
#region GetMatrixBounds
|
|
|
|
private Rectangle GetMatrixBounds(ChartContainer cc, int dx, int dy)
|
|
{
|
|
Rectangle r = Rectangle.Empty;
|
|
|
|
Rectangle ccb = cc.MatrixDisplayBounds;
|
|
|
|
for (int i = ccb.X; i < ccb.Right; i++)
|
|
{
|
|
for (int j = ccb.Y; j < ccb.Bottom; j++)
|
|
{
|
|
if (r.IsEmpty == true)
|
|
r = ChartMatrix.BoundsArray[i, j];
|
|
else
|
|
r = Rectangle.Union(r, ChartMatrix.BoundsArray[i, j]);
|
|
}
|
|
}
|
|
|
|
if (ccb.X != 0)
|
|
{
|
|
r.X += dy;
|
|
r.Width -= dy;
|
|
}
|
|
|
|
if (ccb.Right != ChartMatrix.Width)
|
|
r.Width -= dy;
|
|
|
|
if (ccb.Y != 0)
|
|
{
|
|
r.Y += dx;
|
|
r.Height -= dx;
|
|
}
|
|
|
|
if (ccb.Bottom != ChartMatrix.Height)
|
|
r.Height -= dx;
|
|
|
|
return (r);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AlignMatrix
|
|
|
|
private void AlignMatrix(ChartLayoutInfo layoutInfo)
|
|
{
|
|
for (int i = 0; i < ChartMatrix.Width; i++)
|
|
{
|
|
Vector v = GetMatrixColumnVector(i);
|
|
|
|
UpdateMatrixColumnBounds(v, i);
|
|
}
|
|
|
|
for (int i = 0; i < ChartMatrix.Height; i++)
|
|
{
|
|
Vector v = GetMatrixRowVector(i);
|
|
|
|
UpdateMatrixRowBounds(v, i);
|
|
}
|
|
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
if (cc.MatrixColumnAligned == true || cc.MatrixRowAligned == true)
|
|
{
|
|
cc.MatrixColumnAligned = false;
|
|
cc.MatrixRowAligned = false;
|
|
|
|
layoutInfo.LayoutBounds = cc.BoundsRelative;
|
|
|
|
cc.Measure(layoutInfo);
|
|
}
|
|
}
|
|
}
|
|
|
|
#region GetMatrixColumnVector
|
|
|
|
private Vector GetMatrixColumnVector(int index)
|
|
{
|
|
Vector v = new Vector();
|
|
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
Rectangle cb = cc.ContentBounds;
|
|
|
|
if (cc.MatrixDisplayBounds.X == index)
|
|
{
|
|
if (cc.MatrixAlignStartColumn == true)
|
|
{
|
|
if (v.IsEmpty == true)
|
|
{
|
|
v.Start = cb.X;
|
|
v.End = cb.Right;
|
|
}
|
|
else
|
|
{
|
|
if (cb.X > v.Start)
|
|
{
|
|
int n = cb.X - v.Start;
|
|
v.Start += n;
|
|
v.End -= n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cc.MatrixDisplayBounds.Right - 1 == index)
|
|
{
|
|
if (cc.MatrixAlignEndColumn == true)
|
|
{
|
|
if (v.IsEmpty == true)
|
|
{
|
|
v.End = cb.Right;
|
|
}
|
|
else
|
|
{
|
|
if (cb.Right < v.End)
|
|
{
|
|
int n = v.End - cb.Right;
|
|
v.End -= n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (v);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region UpdateMatrixColumnBounds
|
|
|
|
private void UpdateMatrixColumnBounds(Vector v, int index)
|
|
{
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
Rectangle cb = cc.ContentBounds;
|
|
Rectangle t = cc.BoundsRelative;
|
|
|
|
if (cc.MatrixDisplayBounds.X == index)
|
|
{
|
|
if (cc.MatrixAlignStartColumn == true)
|
|
{
|
|
if (cb.X != v.Start)
|
|
{
|
|
t.X += (v.Start - cb.X);
|
|
t.Width -= (v.Start - cb.X);
|
|
|
|
cc.MatrixColumnAligned = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cc.MatrixDisplayBounds.Right - 1 == index)
|
|
{
|
|
if (cc.MatrixAlignEndColumn == true)
|
|
{
|
|
if (cb.Right != v.End)
|
|
{
|
|
t.Width -= (cb.Right - v.End);
|
|
|
|
cc.MatrixColumnAligned = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
cc.BoundsRelative = t;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMatrixRowVector
|
|
|
|
private Vector GetMatrixRowVector(int index)
|
|
{
|
|
Vector v = new Vector();
|
|
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
Rectangle cb = cc.ContentBounds;
|
|
|
|
if (cc.MatrixDisplayBounds.Y == index)
|
|
{
|
|
if (cc.MatrixAlignStartRow == true)
|
|
{
|
|
if (v.IsEmpty == true)
|
|
{
|
|
v.Start = cb.Y;
|
|
v.End = cb.Bottom;
|
|
}
|
|
else
|
|
{
|
|
if (cb.Y > v.Start)
|
|
{
|
|
int n = (cb.Y - v.Start);
|
|
|
|
v.Start += n;
|
|
v.End -= n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cc.MatrixDisplayBounds.Bottom - 1 == index)
|
|
{
|
|
if (cc.MatrixAlignEndRow == true)
|
|
{
|
|
if (v.IsEmpty == true)
|
|
{
|
|
v.Start = cb.Y;
|
|
v.End = cb.Bottom;
|
|
}
|
|
else
|
|
{
|
|
if (cb.Bottom < v.End)
|
|
v.End = cb.Bottom;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (v);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region UpdateMatrixRowBounds
|
|
|
|
private void UpdateMatrixRowBounds(Vector v, int index)
|
|
{
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
if (cc.MatrixDisplayBounds.Y == index)
|
|
{
|
|
Rectangle cb = cc.ContentBounds;
|
|
Rectangle t = cc.BoundsRelative;
|
|
|
|
if (cc.MatrixAlignStartRow == true)
|
|
{
|
|
if (cb.Y != v.Start)
|
|
{
|
|
t.Y += (v.Start - cb.Y);
|
|
t.Height -= (v.Start - cb.Y);
|
|
|
|
cc.MatrixRowAligned = true;
|
|
}
|
|
}
|
|
|
|
if (cc.MatrixAlignEndRow == true)
|
|
{
|
|
if (cb.Bottom != v.End)
|
|
{
|
|
t.Height -= (cb.Bottom - v.End);
|
|
|
|
cc.MatrixRowAligned = true;
|
|
}
|
|
}
|
|
|
|
cc.BoundsRelative = t;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region RowComparer
|
|
|
|
private class MatrixComparer : IComparer<ChartContainer>
|
|
{
|
|
public int Compare(ChartContainer x, ChartContainer y)
|
|
{
|
|
return (x.MatrixDisplayOrder - y.MatrixDisplayOrder);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMatrixLayout
|
|
|
|
private int GetMatrixLayout(
|
|
ChartLayoutInfo layoutInfo, ContainerLayout containerLayout)
|
|
{
|
|
int fillBase;
|
|
int noFillBase;
|
|
|
|
CalculateMatrixFillData(layoutInfo, containerLayout, out fillBase, out noFillBase);
|
|
|
|
int length = CalcMatrixContentSize(layoutInfo, containerLayout, fillBase, noFillBase);
|
|
|
|
return (length);
|
|
}
|
|
|
|
#region CalculateMatrixFillData
|
|
|
|
private void CalculateMatrixFillData(ChartLayoutInfo layoutInfo,
|
|
ContainerLayout containerLayout, out int fillBase, out int noFillBase)
|
|
{
|
|
fillBase = 0;
|
|
noFillBase = 0;
|
|
|
|
if (containerLayout == ContainerLayout.Horizontal)
|
|
{
|
|
for (int i = 0; i < ChartMatrix.Width; i++)
|
|
{
|
|
MatrixRowColProperties props = ChartMatrix.ColumnProperties[i];
|
|
|
|
if (props.AutoSizeMode == AutoSizeMode.NotSet)
|
|
{
|
|
if (ChartMatrix[i] != null && AutoSizeMode != AutoSizeMode.None)
|
|
fillBase += ChartMatrix[i].FillWeight;
|
|
else
|
|
noFillBase += props.Length;
|
|
}
|
|
else
|
|
{
|
|
if (props.AutoSizeMode != AutoSizeMode.None)
|
|
fillBase += props.FillWeight;
|
|
else
|
|
noFillBase += props.Length;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < ChartMatrix.Height; i++)
|
|
{
|
|
MatrixRowColProperties props = ChartMatrix.RowProperties[i];
|
|
|
|
if (props.AutoSizeMode == AutoSizeMode.NotSet)
|
|
{
|
|
if (ChartMatrix[i] != null && AutoSizeMode != AutoSizeMode.None)
|
|
fillBase += ChartMatrix[i].FillWeight;
|
|
else
|
|
noFillBase += props.Length;
|
|
}
|
|
else
|
|
{
|
|
if (props.AutoSizeMode != AutoSizeMode.None)
|
|
fillBase += props.FillWeight;
|
|
else
|
|
noFillBase += props.Length;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CalcMatrixContentSize
|
|
|
|
private int CalcMatrixContentSize(ChartLayoutInfo layoutInfo,
|
|
ContainerLayout containerLayout, int fillBase, int noFillBase)
|
|
{
|
|
int length;
|
|
|
|
if (containerLayout == ContainerLayout.Horizontal)
|
|
length = CalcHorizontalMatrixContentSize(layoutInfo, fillBase, noFillBase);
|
|
else
|
|
length = CalctVerticalMatrixContentSize(layoutInfo, fillBase, noFillBase);
|
|
|
|
return (length);
|
|
}
|
|
|
|
#region CalcHorizontalMatrixContentSize
|
|
|
|
private int CalcHorizontalMatrixContentSize(
|
|
ChartLayoutInfo layoutInfo, int fillBase, int noFillBase)
|
|
{
|
|
int lenNeeded = 0;
|
|
int n = layoutInfo.LayoutBounds.Width - noFillBase;
|
|
|
|
for (int i = 0; i < ChartMatrix.Width; i++)
|
|
{
|
|
MatrixRowColProperties props = ChartMatrix.ColumnProperties[i];
|
|
|
|
int length = 0;
|
|
AutoSizeMode autoSizeMode = props.AutoSizeMode;
|
|
|
|
if (autoSizeMode == AutoSizeMode.NotSet)
|
|
autoSizeMode = AutoSizeMode;
|
|
|
|
if (fillBase > 0)
|
|
{
|
|
int fillWeight = (ChartMatrix[i] != null && props.AutoSizeMode == AutoSizeMode.NotSet)
|
|
? ChartMatrix[i].FillWeight : props.FillWeight;
|
|
|
|
if (fillWeight != 0)
|
|
{
|
|
if (i == ChartMatrix.Width - 1)
|
|
length = layoutInfo.LayoutBounds.Width - lenNeeded;
|
|
else
|
|
length = (int)(n * (float)fillWeight / fillBase);
|
|
}
|
|
}
|
|
|
|
int minLength = (props.MinimumLength > 0)
|
|
? props.MinimumLength : ChartMatrix.DefaultCellSize.Width;
|
|
|
|
length = Math.Max(length, minLength);
|
|
|
|
props.Length = length;
|
|
|
|
lenNeeded += length;
|
|
}
|
|
|
|
return (lenNeeded);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CalctVerticalMatrixContentSize
|
|
|
|
private int CalctVerticalMatrixContentSize(
|
|
ChartLayoutInfo layoutInfo, int fillBase, int noFillBase)
|
|
{
|
|
int lengthNeeded = 0;
|
|
int n = layoutInfo.LayoutBounds.Height - noFillBase;
|
|
|
|
for (int i = 0; i < ChartMatrix.Height; i++)
|
|
{
|
|
MatrixRowColProperties props = ChartMatrix.RowProperties[i];
|
|
|
|
int length = 0;
|
|
AutoSizeMode autoSizeMode = props.AutoSizeMode;
|
|
|
|
if (autoSizeMode == AutoSizeMode.NotSet)
|
|
autoSizeMode = AutoSizeMode;
|
|
|
|
if (fillBase > 0 && autoSizeMode != AutoSizeMode.None)
|
|
{
|
|
if (props.FillWeight != 0)
|
|
{
|
|
if (i == ChartMatrix.Height - 1)
|
|
length = layoutInfo.LayoutBounds.Height - lengthNeeded;
|
|
else
|
|
length = (int)(n * (float)props.FillWeight / fillBase);
|
|
}
|
|
}
|
|
|
|
int minLength = (props.MinimumLength > 0)
|
|
? props.MinimumLength : ChartMatrix.DefaultCellSize.Height;
|
|
|
|
length = Math.Max(length, minLength);
|
|
|
|
props.Length = length;
|
|
|
|
lengthNeeded += length;
|
|
}
|
|
|
|
return (lengthNeeded);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ArrangeOverride
|
|
|
|
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
|
|
{
|
|
base.ArrangeOverride(layoutInfo);
|
|
|
|
layoutInfo.ScrollOffset.X += HScrollOffset;
|
|
layoutInfo.ScrollOffset.Y += VScrollOffset;
|
|
|
|
Rectangle scContentBounds = GetScrollBounds(ContentBounds);
|
|
|
|
_ChartMatrix.ScrollOffset = layoutInfo.ScrollOffset;
|
|
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
{
|
|
if (cc.Visible == true)
|
|
{
|
|
cc.Arrange(layoutInfo);
|
|
|
|
cc.Displayed = cc.Bounds.IntersectsWith(scContentBounds);
|
|
}
|
|
}
|
|
|
|
layoutInfo.ScrollOffset.X -= HScrollOffset;
|
|
layoutInfo.ScrollOffset.Y -= VScrollOffset;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RenderOverride
|
|
|
|
protected override void RenderOverride(ChartRenderInfo renderInfo)
|
|
{
|
|
Graphics g = renderInfo.Graphics;
|
|
|
|
ChartPanelVisualStyle pstyle = EffectivePanelStyle;
|
|
ContainerVisualStyle cstyle = GetEffectiveContainerStyle();
|
|
|
|
Rectangle scFrameBounds = GetScrollBounds(FrameBounds);
|
|
Rectangle scContentBounds = GetScrollBounds(ContentBounds);
|
|
Rectangle scDisplayBounds = GetDisplayBounds(scContentBounds);
|
|
|
|
RenderPanelBackground(g, scFrameBounds, cstyle);
|
|
|
|
cstyle.RenderBorder(g, scFrameBounds);
|
|
|
|
Rectangle imageBounds = GetImageBounds(FrameBounds, cstyle);
|
|
|
|
if (cstyle.ImageOverlay != ImageOverlay.Top)
|
|
cstyle.RenderBackgroundFigure(g, imageBounds);
|
|
|
|
Region clip = g.Clip;
|
|
g.SetClip(scContentBounds, CombineMode.Intersect);
|
|
|
|
if (ChartMatrix.Size.Width > 0 && ChartMatrix.Size.Height > 0)
|
|
RenderMatrix(renderInfo, pstyle);
|
|
|
|
if (_MatrixList == null || _MatrixList.Count <= 0)
|
|
RenderEmptyText(g, cstyle, scDisplayBounds);
|
|
|
|
if (cstyle.ImageOverlay == ImageOverlay.Top)
|
|
cstyle.RenderBackgroundFigure(g, imageBounds);
|
|
|
|
RenderScrollbars(renderInfo);
|
|
|
|
g.Clip = clip;
|
|
|
|
if (cstyle.DropShadow.Enabled == Tbool.True)
|
|
cstyle.DropShadow.RenderDropShadow(g, scFrameBounds, true, true);
|
|
|
|
base.RenderOverride(renderInfo);
|
|
}
|
|
|
|
#region RenderPanelBackground
|
|
|
|
private void RenderPanelBackground(
|
|
Graphics g, Rectangle bounds, ContainerVisualStyle cstyle)
|
|
{
|
|
ChartControl chartControl = ChartControl;
|
|
|
|
if (chartControl.DoPreRenderPanelBackgroundEvent(g, this, bounds) == false)
|
|
{
|
|
cstyle.RenderBackground(g, bounds);
|
|
|
|
chartControl.DoPostRenderPanelBackgroundEvent(g, this, bounds);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetImageBounds
|
|
|
|
private Rectangle GetImageBounds(Rectangle bounds, ContainerVisualStyle style)
|
|
{
|
|
bounds = GetAdjustedBounds(bounds, style.BorderThickness);
|
|
|
|
Rectangle scBounds = GetScrollBounds(bounds);
|
|
|
|
if (HScrollBar.Visible == true)
|
|
scBounds.Height -= HScrollBar.Height;
|
|
|
|
if (VScrollBar.Visible == true)
|
|
scBounds.Width -= VScrollBar.Width;
|
|
|
|
return (scBounds);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RenderMatrix
|
|
|
|
private void RenderMatrix(ChartRenderInfo renderInfo, ChartPanelVisualStyle style)
|
|
{
|
|
Graphics g = renderInfo.Graphics;
|
|
|
|
// Render divider lines
|
|
|
|
switch (ChartMatrix.DividerLines)
|
|
{
|
|
case DividerLines.Horizontal:
|
|
RenderDividerLinesX(g, style.DividerLineX);
|
|
break;
|
|
|
|
case DividerLines.Vertical:
|
|
RenderDividerLinesY(g, style.DividerLineY);
|
|
break;
|
|
|
|
case DividerLines.BothXy:
|
|
RenderDividerLinesX(g, style.DividerLineX);
|
|
RenderDividerLinesY(g, style.DividerLineY);
|
|
break;
|
|
|
|
case DividerLines.BothYx:
|
|
RenderDividerLinesY(g, style.DividerLineY);
|
|
RenderDividerLinesX(g, style.DividerLineX);
|
|
break;
|
|
}
|
|
|
|
// Render each matrix item
|
|
|
|
if (_MatrixList != null && _MatrixList.Count > 0)
|
|
{
|
|
foreach (ChartContainer cc in _MatrixList)
|
|
cc.Render(renderInfo);
|
|
}
|
|
}
|
|
|
|
#region RenderDividerLinesX
|
|
|
|
private void RenderDividerLinesX(Graphics g, DividerLineVisualStyle style)
|
|
{
|
|
if (style.LinePattern != LinePattern.None && style.LineWidth != 0)
|
|
{
|
|
LinePattern pattern = (style.LinePattern == LinePattern.NotSet) ? LinePattern.Solid : style.LinePattern;
|
|
int thickness = (style.LineWidth > 0) ? style.LineWidth : 1;
|
|
|
|
int n = ChartMatrix.Width - 1;
|
|
int xoffset = _ChartMatrix.ScrollOffset.X;
|
|
int yoffset = _ChartMatrix.ScrollOffset.Y;
|
|
|
|
for (int i = 1; i < ChartMatrix.Height; i++)
|
|
{
|
|
Point pt1 = ChartMatrix.BoundsArray[0, i].Location;
|
|
Point pt2 = ChartMatrix.BoundsArray[n, i].Location;
|
|
|
|
pt1.X -= xoffset;
|
|
pt1.Y -= yoffset;
|
|
|
|
pt2.X -= xoffset;
|
|
pt2.Y -= yoffset;
|
|
|
|
pt2.X += ChartMatrix.BoundsArray[n, i].Width;
|
|
|
|
using (Pen pen = new Pen(style.LineColor, Dpi.Width(style.LineWidth)))
|
|
{
|
|
pen.DashStyle = (DashStyle)pattern;
|
|
|
|
g.DrawLine(pen, pt1, pt2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RenderDividerLinesY
|
|
|
|
private void RenderDividerLinesY(Graphics g, DividerLineVisualStyle style)
|
|
{
|
|
if (style.LinePattern != LinePattern.None && style.LineWidth != 0)
|
|
{
|
|
LinePattern pattern = (style.LinePattern == LinePattern.NotSet) ? LinePattern.Solid : style.LinePattern;
|
|
int thickness = (style.LineWidth > 0) ? style.LineWidth : 1;
|
|
|
|
int n = ChartMatrix.Height - 1;
|
|
int xoffset = _ChartMatrix.ScrollOffset.X;
|
|
int yoffset = _ChartMatrix.ScrollOffset.Y;
|
|
|
|
for (int i = 1; i < ChartMatrix.Width; i++)
|
|
{
|
|
Point pt1 = ChartMatrix.BoundsArray[i, 0].Location;
|
|
Point pt2 = ChartMatrix.BoundsArray[i, n].Location;
|
|
|
|
pt1.X -= xoffset;
|
|
pt1.Y -= yoffset;
|
|
|
|
pt2.X -= xoffset;
|
|
pt2.Y -= yoffset;
|
|
|
|
pt2.Y += ChartMatrix.BoundsArray[i, n].Height;
|
|
|
|
using (Pen pen = new Pen(style.LineColor, Dpi.Height(thickness)))
|
|
{
|
|
pen.DashStyle = (DashStyle)pattern;
|
|
|
|
g.DrawLine(pen, pt1, pt2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Mouse handling
|
|
|
|
#region OnMouseMove
|
|
|
|
protected override bool OnMouseMove(MouseEventArgs e)
|
|
{
|
|
if (base.OnMouseMove(e) == true)
|
|
return (true);
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region OnResize
|
|
|
|
protected override bool OnResize(EventArgs e)
|
|
{
|
|
InvalidateLayout();
|
|
|
|
foreach (ChartContainer cc in ChartContainers)
|
|
cc.InternalOnResize(e);
|
|
|
|
return (base.OnResize(e));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetElementAt
|
|
|
|
/// <summary>
|
|
/// Gets the visua element at the given Point.
|
|
/// </summary>
|
|
/// <param name="pt"></param>
|
|
/// <returns></returns>
|
|
public override ChartVisualElement GetElementAt(Point pt)
|
|
{
|
|
ChartVisualElement item = base.GetElementAt(pt);
|
|
|
|
if (item == null)
|
|
{
|
|
if (ContentBounds.Contains(pt))
|
|
{
|
|
if (ChartMatrix.IsEmpty == false)
|
|
{
|
|
item = ChartMatrix.GetElementAt(pt);
|
|
|
|
if (item != null && item.Visible == true)
|
|
{
|
|
if (item.Bounds.Contains(pt))
|
|
{
|
|
ChartVisualElement subItem = item.GetElementAt(pt);
|
|
|
|
if (subItem != null)
|
|
return (subItem);
|
|
|
|
return (item);
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (item);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMatrixCoordAt
|
|
|
|
/// <summary>
|
|
/// Gets the matric coordinate (row/column) at the given Point.
|
|
/// </summary>
|
|
/// <param name="pt"></param>
|
|
/// <param name="column"></param>
|
|
/// <param name="row"></param>
|
|
/// <returns>true if valid coordinate is returned</returns>
|
|
public bool GetMatrixCoordAt(Point pt, ref int column, ref int row)
|
|
{
|
|
if (ContentBounds.Contains(pt))
|
|
return (ChartMatrix.GetMatrixCoordAt(pt, ref column, ref row));
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMatrixCoordOf
|
|
|
|
/// <summary>
|
|
/// Gets the matric coordinate (row/column) of the given container.
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
/// <param name="row"></param>
|
|
/// <param name="column"></param>
|
|
/// <returns>true if valid coordinate returned.</returns>
|
|
public bool GetMatrixCoordOf(ChartContainer item, ref int row, ref int column)
|
|
{
|
|
return (ChartMatrix.GetMatrixCoordOf(item, ref row, ref column));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Style handling
|
|
|
|
#region ApplyStyles
|
|
|
|
public override void ApplyStyles(BaseVisualStyle style)
|
|
{
|
|
ChartPanelVisualStyle pstyle = style as ChartPanelVisualStyle;
|
|
|
|
if (pstyle != null)
|
|
{
|
|
ApplyParentStyles(pstyle, Parent as ChartContainer);
|
|
|
|
pstyle.DividerLineX.ApplyStyle(DefaultVisualStyles.DividerLineVisualStyle);
|
|
pstyle.DividerLineY.ApplyStyle(DefaultVisualStyles.DividerLineVisualStyle);
|
|
|
|
pstyle.ApplyStyle(DefaultVisualStyles.ChartPanelVisualStyle);
|
|
pstyle.ApplyStyle(ChartPanelVisualStyle);
|
|
}
|
|
}
|
|
|
|
#region ApplyParentStyles
|
|
|
|
private void ApplyParentStyles(ChartPanelVisualStyle pstyle, ChartContainer item)
|
|
{
|
|
if (item != null)
|
|
{
|
|
ApplyParentStyles(pstyle, item.Parent as ChartContainer);
|
|
|
|
ChartPanel panel = item as ChartPanel;
|
|
|
|
if (panel != null)
|
|
{
|
|
pstyle.DividerLineX.ApplyStyle(panel.DefaultVisualStyles.DividerLineVisualStyle);
|
|
pstyle.DividerLineY.ApplyStyle(panel.DefaultVisualStyles.DividerLineVisualStyle);
|
|
|
|
pstyle.ApplyStyle(panel.DefaultVisualStyles.ChartPanelVisualStyle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pstyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartPanelVisualStyle);
|
|
|
|
pstyle.DividerLineX.ApplyStyle(ChartControl.DefaultVisualStyles.DividerLineVisualStyle);
|
|
pstyle.DividerLineY.ApplyStyle(ChartControl.DefaultVisualStyles.DividerLineVisualStyle);
|
|
|
|
pstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartPanelVisualStyle);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ClearEffectiveStyles
|
|
|
|
protected override void ClearEffectiveStyles()
|
|
{
|
|
base.ClearEffectiveStyles();
|
|
|
|
_EffectivePanelStyle.InvalidateStyle();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ILegendData
|
|
|
|
#region GetLegendData
|
|
|
|
public override List<ChartLegendItem> GetLegendData()
|
|
{
|
|
LegendData = new List<ChartLegendItem>();
|
|
|
|
if (LegendSource != LegendSource.None)
|
|
{
|
|
ChartContainerCollection containers = ChartContainers;
|
|
|
|
foreach (ChartContainer cc in containers)
|
|
{
|
|
if ((cc is ChartPanel) && ((LegendSource & LegendSource.NestedPanels) != 0) ||
|
|
(cc is BaseChart) && ((LegendSource & LegendSource.NestedCharts) != 0))
|
|
{
|
|
List<ChartLegendItem> data = cc.GetLegendData();
|
|
|
|
if (data != null && data.Count > 0)
|
|
AddLegendItems(data);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (_LegendData);
|
|
}
|
|
|
|
#region AddLegendItems
|
|
|
|
private void AddLegendItems(List<ChartLegendItem> items)
|
|
{
|
|
foreach (ChartLegendItem item in items)
|
|
{
|
|
ChartLegendItem likeItem = null;
|
|
|
|
if (Legend.CombineLikeItems == true)
|
|
likeItem = FindLikeItems(item);
|
|
|
|
if (likeItem == null)
|
|
{
|
|
likeItem = new ChartLegendItem();
|
|
|
|
likeItem.Parent = Legend;
|
|
|
|
likeItem.Name = item.Name;
|
|
likeItem.ItemText = item.ItemText;
|
|
|
|
_LegendData.Add(likeItem);
|
|
}
|
|
|
|
likeItem.ChartItems.AddRange(item.ChartItems);
|
|
}
|
|
}
|
|
|
|
#region FindLikeItems
|
|
|
|
private ChartLegendItem FindLikeItems(ChartLegendItem item)
|
|
{
|
|
string itemName = item.Name ?? item.ItemText;
|
|
|
|
if (String.IsNullOrEmpty(itemName) == false)
|
|
{
|
|
foreach (ChartLegendItem likeItem in _LegendData)
|
|
{
|
|
string likeName = likeItem.Name ?? likeItem.ItemText;
|
|
|
|
if (String.IsNullOrEmpty(likeName) == false)
|
|
{
|
|
if (likeName.Equals(itemName) == true)
|
|
return (likeItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetContainerByName
|
|
|
|
/// <summary>
|
|
/// Gets the ChartContainer object from the given name.
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <returns></returns>
|
|
public ChartContainer GetContainerByName(string name)
|
|
{
|
|
return (GetContainerByName(name, false));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the ChartContainer object from the given name, with
|
|
/// optional searching of nested panels/charts.
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <param name="searchNested"></param>
|
|
/// <returns></returns>
|
|
public ChartContainer GetContainerByName(string name, bool searchNested)
|
|
{
|
|
if (String.IsNullOrEmpty(name) == true)
|
|
return (null);
|
|
|
|
if (_ChartContainers != null)
|
|
{
|
|
foreach (ChartContainer container in _ChartContainers)
|
|
{
|
|
if (name.Equals(container.Name) == true)
|
|
return (container);
|
|
|
|
else if (searchNested == true)
|
|
{
|
|
ChartPanel panel = container as ChartPanel;
|
|
|
|
if (panel != null)
|
|
{
|
|
ChartContainer item = panel.GetContainerByName(name, true);
|
|
|
|
if (item != null)
|
|
return (item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetChartByName
|
|
|
|
/// <summary>
|
|
/// Gets the BaseChart from the given name.
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <returns></returns>
|
|
public BaseChart GetChartByName(string name)
|
|
{
|
|
return (GetChartByName(name, false));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the BaseChart from the given name, optionally searching
|
|
/// nested panels and charts.
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <param name="searchNested"></param>
|
|
/// <returns></returns>
|
|
public BaseChart GetChartByName(string name, bool searchNested)
|
|
{
|
|
if (String.IsNullOrEmpty(name) == true)
|
|
return (null);
|
|
|
|
if (_ChartContainers != null)
|
|
{
|
|
foreach (ChartContainer container in _ChartContainers)
|
|
{
|
|
if (container is BaseChart)
|
|
{
|
|
if (name.Equals(container.Name) == true)
|
|
return ((BaseChart)container);
|
|
}
|
|
else if (searchNested == true)
|
|
{
|
|
ChartPanel panel = container as ChartPanel;
|
|
|
|
if (panel != null)
|
|
{
|
|
BaseChart item = panel.GetChartByName(name, true);
|
|
|
|
if (item != null)
|
|
return (item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetPanelByName
|
|
|
|
/// <summary>
|
|
/// Gets the ChartPanel from the given name.
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <returns></returns>
|
|
public ChartPanel GetPanelByName(string name)
|
|
{
|
|
return (GetPanelByName(name, false));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the ChartPanel from the given name, optionally
|
|
/// searching through nested panels.
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <param name="searchNested"></param>
|
|
/// <returns></returns>
|
|
public ChartPanel GetPanelByName(string name, bool searchNested)
|
|
{
|
|
if (String.IsNullOrEmpty(name) == true)
|
|
return (null);
|
|
|
|
if (_ChartContainers != null)
|
|
{
|
|
foreach (ChartContainer container in _ChartContainers)
|
|
{
|
|
ChartPanel panel = container as ChartPanel;
|
|
|
|
if (panel != null)
|
|
{
|
|
if (name.Equals(panel.Name) == true)
|
|
return (panel);
|
|
|
|
if (searchNested == true)
|
|
{
|
|
ChartPanel item = panel.GetPanelByName(name, true);
|
|
|
|
if (item != null)
|
|
return (item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (null);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Copy/CopyTo
|
|
|
|
public override ChartVisualElement Copy()
|
|
{
|
|
ChartPanel copy = new ChartPanel();
|
|
|
|
CopyTo(copy);
|
|
|
|
return (copy);
|
|
}
|
|
|
|
public override void CopyTo(ChartVisualElement copy)
|
|
{
|
|
ChartPanel c = copy as ChartPanel;
|
|
|
|
if (c != null)
|
|
{
|
|
base.CopyTo(c);
|
|
|
|
c.AutoFillChartMatrix = AutoFillChartMatrix;
|
|
c.AutoGenSeriesCollection = AutoGenSeriesCollection;
|
|
c.AutoSizeChartMatrix = AutoSizeChartMatrix;
|
|
|
|
foreach (ChartContainer cc in ChartContainers)
|
|
c.ChartContainers.Add((ChartContainer)cc.Copy());
|
|
|
|
c.ChartMatrix = ChartMatrix.Copy();
|
|
|
|
c.ChartPanelVisualStyle =
|
|
(_ChartPanelVisualStyle != null) ? ChartPanelVisualStyle.Copy() : null;
|
|
|
|
c.ContainerLayout = ContainerLayout;
|
|
|
|
c.DefaultVisualStyles =
|
|
(_DefaultVisualStyles != null) ? DefaultVisualStyles.Copy() : null;
|
|
|
|
c.LegendSource = LegendSource;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetSerialData
|
|
|
|
internal override SerialElementCollection GetSerialData(string serialName)
|
|
{
|
|
SerialElementCollection sec = new SerialElementCollection();
|
|
|
|
if (serialName != null)
|
|
{
|
|
if (serialName.Equals("") == true)
|
|
serialName = "ChartPanel";
|
|
|
|
sec.AddStartElement(serialName);
|
|
}
|
|
|
|
sec.AddValue("AutoFillChartMatrix", AutoFillChartMatrix, true);
|
|
sec.AddValue("AutoGenSeriesCollection", AutoGenSeriesCollection, false);
|
|
sec.AddValue("AutoSizeChartMatrix", AutoSizeChartMatrix, true);
|
|
|
|
if (ChartContainers.Count > 0)
|
|
{
|
|
sec.AddStartElement("ChartContainers count=\"" + ChartContainers.Count + "\"");
|
|
|
|
foreach (ChartContainer cc in ChartContainers)
|
|
sec.AddElement(cc.GetSerialData(""));
|
|
|
|
sec.AddEndElement("ChartContainers");
|
|
}
|
|
|
|
if (_ChartMatrix != null && _ChartMatrix.IsEmpty == false)
|
|
{
|
|
if (AutoFillChartMatrix == false)
|
|
sec.AddElement(_ChartMatrix.GetSerialData());
|
|
}
|
|
|
|
if (_ChartPanelVisualStyle != null && _ChartPanelVisualStyle.IsEmpty == false)
|
|
sec.AddElement(_ChartPanelVisualStyle.GetSerialData("ChartPanelVisualStyle"));
|
|
|
|
sec.AddValue("ContainerLayout", ContainerLayout, ContainerLayout.Auto);
|
|
|
|
if (_DefaultVisualStyles != null && _DefaultVisualStyles.IsEmpty == false)
|
|
sec.AddElement(_DefaultVisualStyles.GetSerialData());
|
|
|
|
sec.AddValue("LegendSource",
|
|
LegendSource, (LegendSource.NestedCharts | LegendSource.NestedPanels));
|
|
|
|
sec.AddElement(base.GetSerialData(null));
|
|
|
|
if (serialName != null)
|
|
sec.AddEndElement(serialName);
|
|
|
|
return (sec);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region PutSerialData
|
|
|
|
#region ProcessValue
|
|
|
|
internal override void ProcessValue(SerialElement se)
|
|
{
|
|
switch (se.Name)
|
|
{
|
|
case "AutoFillChartMatrix":
|
|
AutoFillChartMatrix = bool.Parse(se.StringValue);
|
|
break;
|
|
|
|
case "AutoGenSeriesCollection":
|
|
AutoGenSeriesCollection = bool.Parse(se.StringValue);
|
|
break;
|
|
|
|
case "AutoSizeChartMatrix":
|
|
AutoSizeChartMatrix = bool.Parse(se.StringValue);
|
|
break;
|
|
|
|
case "ContainerLayout":
|
|
ContainerLayout = (ContainerLayout)se.GetValueEnum(typeof(ContainerLayout));
|
|
break;
|
|
|
|
case "LegendSource":
|
|
LegendSource = (LegendSource)se.GetValueEnum(typeof(LegendSource));
|
|
break;
|
|
|
|
default:
|
|
base.ProcessValue(se);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ProcessCollection
|
|
|
|
internal override void ProcessCollection(SerialElement se)
|
|
{
|
|
SerialElementCollection sec = se.Sec;
|
|
|
|
switch (se.Name)
|
|
{
|
|
case "ChartPanel":
|
|
case "ChartContainers":
|
|
sec.PutSerialData(this);
|
|
break;
|
|
|
|
case "ChartXy":
|
|
string name = sec.GetItemValue("Name");
|
|
|
|
ChartXy chartXy = new ChartXy(name);
|
|
|
|
sec.PutSerialData(chartXy);
|
|
|
|
ChartContainers.Add(chartXy);
|
|
break;
|
|
|
|
case "ChartMatrix":
|
|
sec.PutSerialData(ChartMatrix);
|
|
break;
|
|
|
|
case "ChartPanelVisualStyle":
|
|
sec.PutSerialData(ChartPanelVisualStyle);
|
|
break;
|
|
|
|
case "DefaultVisualStyles":
|
|
sec.PutSerialData(DefaultVisualStyles);
|
|
break;
|
|
|
|
case "PieChart":
|
|
string pname = sec.GetItemValue("Name");
|
|
|
|
PieChart pieChart = new PieChart(pname);
|
|
|
|
sec.PutSerialData(pieChart);
|
|
|
|
ChartContainers.Add(pieChart);
|
|
break;
|
|
|
|
default:
|
|
base.ProcessCollection(se);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region States
|
|
|
|
[Flags]
|
|
private enum States : uint
|
|
{
|
|
AutoFillChartMatrix = (1U << 0),
|
|
AutoGenSeriesCollection = (1U << 1),
|
|
AutoSizeChartMatrix = (1U << 2),
|
|
}
|
|
|
|
#region TestState
|
|
|
|
private bool TestState(States state)
|
|
{
|
|
return ((_States & state) == state);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SetState
|
|
|
|
private void SetState(States state, bool value)
|
|
{
|
|
if (value == true)
|
|
_States |= state;
|
|
else
|
|
_States &= ~state;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Structs
|
|
|
|
private struct Vector
|
|
{
|
|
public int Start;
|
|
public int End;
|
|
|
|
public bool IsEmpty
|
|
{
|
|
get { return (Start == End); }
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDisposable
|
|
|
|
public override void Dispose()
|
|
{
|
|
ChartContainers = null;
|
|
ChartMatrix = null;
|
|
ChartPanelVisualStyle = null;
|
|
DefaultVisualStyles = null;
|
|
|
|
base.Dispose();
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#region enums
|
|
|
|
#region ContainerLayout
|
|
|
|
public enum ContainerLayout
|
|
{
|
|
Auto,
|
|
Horizontal,
|
|
Vertical,
|
|
HorizontalThenVertical,
|
|
VerticalThenHorizontal,
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DividerLines
|
|
|
|
///<summary>
|
|
/// Specifies which divider lines are displayed
|
|
///</summary>
|
|
public enum DividerLines
|
|
{
|
|
///<summary>
|
|
/// Not set
|
|
///</summary>
|
|
NotSet,
|
|
|
|
///<summary>
|
|
/// No lines are displayed
|
|
///</summary>
|
|
None,
|
|
|
|
///<summary>
|
|
/// Only horizontal divider lines are displayed
|
|
///</summary>
|
|
Horizontal,
|
|
|
|
///<summary>
|
|
/// Only vertical divider lines are displayed
|
|
///</summary>
|
|
Vertical,
|
|
|
|
///<summary>
|
|
/// Both horizontal and vertical divider lines are displayed,
|
|
/// horizontal first, then vertical.
|
|
///</summary>
|
|
BothXy,
|
|
|
|
///<summary>
|
|
/// Both horizontal and vertical divider lines are displayed
|
|
/// vertical first, then horizontal.
|
|
///</summary>
|
|
BothYx,
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region LegendSource
|
|
|
|
[Flags]
|
|
public enum LegendSource
|
|
{
|
|
None = 0,
|
|
|
|
NestedCharts = (1 << 0),
|
|
NestedPanels = (1 << 1),
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region BlankExpandableObjectConverter
|
|
|
|
///<summary>
|
|
/// BlankExpandableObjectConverter
|
|
///</summary>
|
|
public class BlankExpandableObjectConverter : ExpandableObjectConverter
|
|
{
|
|
///<summary>
|
|
/// ConvertTo
|
|
///</summary>
|
|
///<param name="context"></param>
|
|
///<param name="culture"></param>
|
|
///<param name="value"></param>
|
|
///<param name="destinationType"></param>
|
|
///<returns></returns>
|
|
public override object ConvertTo(
|
|
ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
|
{
|
|
if (destinationType == typeof(string))
|
|
return (" ");
|
|
|
|
return (base.ConvertTo(context, culture, value, destinationType));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|