using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Drawing.Drawing2D; using System.Windows.Forms; using DevComponents.DotNetBar.Charts.Style; namespace DevComponents.DotNetBar.Charts { /// /// Represents the collection of BaseSeries. /// [Editor("DevComponents.Charts.Design.ChartSeriesCollectionEditor, DevComponents.Charts.Design, " + "Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))] public class ChartBaseSeriesCollection : CustomNamedCollection { #region GetUniqueName public string GetUniqueName() { return (GetUniqueName("Series")); } #endregion } public class BaseSeries : ChartVisualElement, ILegendItem { #region Private variables private States _States; private SeriesType _SeriesType; private int _SeriesId; private object _SeriesKey; private object _DataSource; private string _DataMember; private DataBinder _DataBinder; private string _DataPropertyNameSeries; private string _DataPropertyNameX; private CustomCollection _DataPropertyNamesY; private Color _DefaultPaletteColor = Color.Empty; private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles; private string _LegendText; private ChartLegendItem _LegendItem; private bool _SeriesRangeChanged = true; private Rectangle _RenderBounds; #endregion #region Constructors public BaseSeries() : this(null, SeriesType.Point) { } public BaseSeries(SeriesType seriesType) : this(null, seriesType) { } public BaseSeries(string name, SeriesType seriesType) { Name = name; SeriesType = seriesType; InitDefaultStates(); } #endregion #region InitDefaultStates private void InitDefaultStates() { SetState(States.ShowInLegend, true); SetState(States.ShowInParentLegend, true); SetState(States.ShowCheckBoxInLegend, true); SetState(States.ShowMarkerInLegend, true); SetState(States.CheckedInLegend, true); } #endregion #region Public properties #region ChartLegendItemVisualStyles /// /// Gets or sets the visual styles for the Legend item. /// [Category("Style")] [Description("Indicates the visual styles for the Legend item.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ChartLegendItemVisualStyles ChartLegendItemVisualStyles { get { if (_ChartLegendItemVisualStyles == null) { _ChartLegendItemVisualStyles = new ChartLegendItemVisualStyles(); StyleVisualChangeHandler(null, _ChartLegendItemVisualStyles); } return (_ChartLegendItemVisualStyles); } set { if (_ChartLegendItemVisualStyles != value) { ChartLegendItemVisualStyles oldValue = _ChartLegendItemVisualStyles; _ChartLegendItemVisualStyles = value; OnStyleChanged("ChartLegendItemVisualStyles", oldValue, value); if (oldValue != null) oldValue.Dispose(); } } } #endregion #region DataMember /// /// Gets or sets the name of the list or table /// in the data source that the Series is bound to. /// [DefaultValue(null), Category("Data")] [Description("Indicates the name of the list or table in the data source that the Series is bound to.")] public string DataMember { get { return (_DataMember); } set { if (_DataBinder != null) _DataBinder.Clear(); _DataMember = value; NeedToUpdateBindings = true; OnPropertyChangedEx("DataMember", VisualChangeType.Layout); } } #endregion #region DataPropertyNameSeries /// /// Gets or sets the name of the data field to which the Series Name is bound. /// [DefaultValue(null), Category("Data")] [Description("Indicates the name of the data field to which the Series Name is bound.")] public string DataPropertyNameSeries { get { return (_DataPropertyNameSeries); } set { if (value != _DataPropertyNameSeries) { _DataPropertyNameSeries = value; if (NeedToUpdateBindings == false) { NeedToUpdateBindings = true; InvalidateLayout(); } OnPropertyChangedEx("DataPropertyNameSeries", VisualChangeType.Layout); } } } #endregion #region DataPropertyNameX /// /// Gets or sets the name of the data field to which the X-Axis data is bound. /// [DefaultValue(null), Category("Data")] [Description("Indicates the name of the data field to which the X-Axis data is bound.")] public string DataPropertyNameX { get { return (_DataPropertyNameX); } set { if (value != _DataPropertyNameX) { _DataPropertyNameX = value; if (NeedToUpdateBindings == false) { NeedToUpdateBindings = true; InvalidateLayout(); } OnPropertyChangedEx("DataPropertyNameX", VisualChangeType.Layout); } } } #endregion #region DataPropertyNamesY /// /// Gets or sets the names of the data fields to which the Y-Axis data is bound. /// [DefaultValue(null), Category("Data")] [Description("Indicates the names of the data fields to which the Y-Axis data is bound.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public CustomCollection DataPropertyNamesY { get { if (_DataPropertyNamesY == null) { _DataPropertyNamesY = new CustomCollection(); _DataPropertyNamesY.CollectionChanged += DataPropertyNamesY_CollectionChanged; } return (_DataPropertyNamesY); } set { if (value != _DataPropertyNamesY) { if (_DataPropertyNamesY != null) { _DataPropertyNamesY.Clear(); _DataPropertyNamesY.CollectionChanged -= DataPropertyNamesY_CollectionChanged; } _DataPropertyNamesY = value; if (_DataPropertyNamesY != null) _DataPropertyNamesY.CollectionChanged += DataPropertyNamesY_CollectionChanged; OnPropertyChangedEx("DataPropertyNamesY", Style.VisualChangeType.Layout); } } } void DataPropertyNamesY_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (NeedToUpdateBindings == false) { NeedToUpdateBindings = true; InvalidateLayout(); } } #endregion #region DataSource /// /// Gets or sets the data source that the Series is bound to. /// [DefaultValue(null), AttributeProvider(typeof(IListSource)), Category("Data")] [Description("Indicates the data source that the Series is bound to.")] public object DataSource { get { return (_DataSource); } set { if (_DataBinder != null) _DataBinder.Clear(); _DataSource = value; NeedToUpdateBindings = true; OnPropertyChangedEx("DataSource", VisualChangeType.Layout); } } #endregion #region DefaultPaletteColor /// /// Gets the default palette color assigned to the series when it /// is added to the chart. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("Indicates the default palette color assigned to the series when it is added to the chart.")] public Color DefaultPaletteColor { get { return (_DefaultPaletteColor); } internal set { if (value != _DefaultPaletteColor) { _DefaultPaletteColor = value; InvalidateStyle(); } } } #endregion #region IsDisplayed /// /// Gets whether the series is displayed (based upon Visibility and Legend state). /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual bool IsDisplayed { get { BaseChart baseChart = Parent as BaseChart; ItemCheckAction ica = (baseChart != null) ? baseChart.Legend.ItemCheckAction : ItemCheckAction.ShowItem; return ((Visible == true) && (ica == ItemCheckAction.None || (ShowCheckBoxInLegend == false || CheckedInLegend == true))); } } #endregion #region SeriesRangeChanged /// /// Signals to the chart that the series data has changed. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual bool SeriesRangeChanged { get { return (_SeriesRangeChanged); } set { _SeriesRangeChanged = value; if (value == true) { BaseChart chart = Parent as BaseChart; if (chart != null) { chart.SeriesRangeChanged = true; chart.InvalidateLayout(); } } } } #endregion #region SeriesType /// /// Gets or sets the Series Type. /// [DefaultValue(SeriesType.Point), Category("Appearance")] [Description("Indicates the Series Type.")] public virtual SeriesType SeriesType { get { return (_SeriesType); } set { if (value != _SeriesType) { _SeriesType = value; BaseChart chart = Parent as BaseChart; if (chart != null) { SeriesRangeChanged = true; chart.SeriesRangeChanged = true; } OnPropertyChangedEx("SeriesType", VisualChangeType.Layout); } } } #endregion #endregion #region Internal properties #region DataBinder internal DataBinder DataBinder { get { if (_DataBinder == null) _DataBinder = new DataBinder(this); return (_DataBinder); } set { if (_DataBinder != null) _DataBinder.Clear(); _DataBinder = value; } } #endregion #region NeedToUpdateBindings internal bool NeedToUpdateBindings { get { return (TestState(States.NeedToUpdateBindings)); } set { SetState(States.NeedToUpdateBindings, value); } } #endregion #region RenderBounds internal Rectangle RenderBounds { get { return (_RenderBounds); } set { _RenderBounds = value; } } #endregion #region SeriesId internal int SeriesId { get { return (_SeriesId); } set { _SeriesId = value; } } #endregion #region SeriesKey internal object SeriesKey { get { return (_SeriesKey); } set { _SeriesKey = value; } } #endregion #endregion #region MeasureOverride protected override void MeasureOverride(ChartLayoutInfo layoutInfo) { UpdateDataBindings(); } #region UpdateDataBindings internal void UpdateDataBindings() { if (NeedToUpdateBindings == true) { BaseChart chart = Parent as BaseChart; object dataSource = DataSource ?? chart.DataSource; string dataMember = (string.IsNullOrEmpty(DataMember) == false) ? DataMember : chart.DataMember; if (dataSource != null) { ClearSeriesPoints(); DataBinder dataBinder = DataBinder; dataBinder.Clear(); dataBinder.DataConnect(dataSource, dataMember); dataBinder.LoadSeriesData(this); } NeedToUpdateBindings = false; } } #endregion #endregion #region ArrangeOverride protected override void ArrangeOverride(ChartLayoutInfo layoutInfo) { BoundsRelative = layoutInfo.LayoutBounds; } #endregion #region RenderOverride protected override void RenderOverride(ChartRenderInfo renderInfo) { throw new NotImplementedException(); } #endregion #region Render internal override void Render(ChartRenderInfo renderInfo) { if (Displayed == true) { Rectangle bounds = BoundsRelative; if (renderInfo.ClipRectangle.IntersectsWith(bounds)) RenderOverride(renderInfo); } } #endregion #region RefreshSeries /// /// Causes the series to refresh its display, as the underlying /// series data (potentially) has changed in some way. /// public void RefreshSeries() { SeriesRangeChanged = true; InvalidateLayout(); } #endregion #region AddSeriesPoint internal virtual void AddSeriesPoint(object valuex, object[] valuesY, object dataItem) { throw new NotImplementedException(); } #endregion #region ClearSeriesPoints internal virtual void ClearSeriesPoints() { throw new NotImplementedException(); } #endregion #region Style handling #region InvalidateStyle /// ///Invalidate the cached Style definitions /// public void InvalidateStyle() { ClearEffectiveStyles(); } #endregion #region ClearEffectiveStyles protected override void ClearEffectiveStyles() { if (LegendItem != null) LegendItem.EffectiveStyles.InvalidateStyles(); } #endregion #endregion #region ILegendItem #region CheckedInLegend /// /// Gets or sets whether the series is checked in the Legend. /// [DefaultValue(true), Category("Legend")] [Description("Indicates whether the series is checked in the Legend.")] public bool CheckedInLegend { get { return (TestState(States.CheckedInLegend)); } set { if (value != CheckedInLegend) { SetState(States.CheckedInLegend, value); if (LegendItem != null) LegendItem.UpdateCheckState(); OnCheckStateChanged(); } } } internal virtual void OnCheckStateChanged() { BaseChart chart = Parent as BaseChart; if (chart != null) chart.OnSeriesCheckStateChanged("CheckedInLegend"); OnPropertyChangedEx("CheckedInLegend", VisualChangeType.Render); } #endregion #region ShowCheckBoxInLegend /// /// Gets or sets whether a checkbox for the series is shown in the Legend. /// [DefaultValue(true), Category("Legend")] [Description("Indicates whether a checkbox for the series is shown in the Legend.")] public bool ShowCheckBoxInLegend { get { return (TestState(States.ShowCheckBoxInLegend)); } set { if (value != ShowCheckBoxInLegend) { SetState(States.ShowCheckBoxInLegend, value); OnPropertyChangedEx("ShowCheckBoxInLegend", VisualChangeType.Layout); } } } #endregion #region ShowInLegend /// /// Gets or sets whether the series is shown in the Legend. /// [DefaultValue(true), Category("Legend")] [Description("Indicates whether the series is shown in the Legend.")] public bool ShowInLegend { get { return (TestState(States.ShowInLegend)); } set { if (value != ShowInLegend) { SetState(States.ShowInLegend, value); OnPropertyChangedEx("ShowInLegend", VisualChangeType.Layout); } } } #endregion #region ShowInParentLegend /// /// Gets or sets whether the series is shown in parent Legend(s). /// [DefaultValue(true), Category("Legend")] [Description("Indicates whether the series is shown in parent Legend(s).")] public bool ShowInParentLegend { get { return (TestState(States.ShowInParentLegend)); } set { if (value != ShowInParentLegend) { SetState(States.ShowInParentLegend, value); OnPropertyChangedEx("ShowInParentLegend", VisualChangeType.Layout); } } } #endregion #region ShowMarkerInLegend /// /// Gets or sets whether the series Marker is shown in the Legend. /// [DefaultValue(true), Category("Legend")] [Description("Indicates whether the series Marker is shown in the Legend.")] public bool ShowMarkerInLegend { get { return (TestState(States.ShowMarkerInLegend)); } set { if (value != ShowMarkerInLegend) { SetState(States.ShowMarkerInLegend, value); OnPropertyChangedEx("ShowMarkerInLegend", VisualChangeType.Layout); } } } #endregion #region LegendItem /// /// Gets the item's parent LegendItem. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Description("Indicates the item's parent LegendItem.")] public ChartLegendItem LegendItem { get { return (_LegendItem); } internal set { _LegendItem = value; } } #endregion #region LegendText /// /// Gets or sets the text to display in the legend. /// [DefaultValue(null), Category("Legend")] [Description("Indicates the text to display in the legend.")] public string LegendText { get { return (_LegendText); } set { if (value != _LegendText) { _LegendText = value; OnPropertyChangedEx("LegendText", Style.VisualChangeType.Layout); } } } #endregion #region GetLegendItem public virtual ChartLegendItem GetLegendItem() { LegendItem = null; if (ShowInLegend == true) { ChartContainer chart = Parent as ChartContainer; if (chart != null) { LegendItem = new ChartLegendItem(); if (CheckedInLegend == true) _LegendItem.CheckState = CheckState.Checked; _LegendItem.Parent = chart.Legend; _LegendItem.Name = Name; _LegendItem.ItemText = LegendText; if (string.IsNullOrEmpty(_LegendItem.Name) == true) _LegendItem.Name = "(Series)"; _LegendItem.ChartItems.Add(this); } } return (_LegendItem); } #endregion #region GetLegendItems public List GetLegendItems() { List list = new List(); ChartLegendItem item = GetLegendItem(); if (item != null) list.Add(item); AddSubLegendItems(list); return (list); } #region AddSubLegendItems internal virtual void AddSubLegendItems(List list) { throw new NotImplementedException(); } #endregion #endregion #region GetLegendItemColor public Color GetLegendItemColor() { ChartXy chartXy = Parent as ChartXy; ChartLegendItemVisualStyle lstyle = ChartLegendItemVisualStyles[StyleType.Default]; if (lstyle.TextColor.IsEmpty == false) return (lstyle.TextColor); Color color = GetLegendItemColorEx(); if (color.IsEmpty == true) color = _DefaultPaletteColor; return (color); } #region GetLegendItemColorEx internal virtual Color GetLegendItemColorEx() { throw new NotImplementedException(); } #endregion #endregion #region RenderLegendItemMarker public void RenderLegendItemMarker(Graphics g, ChartLegendItem litem, ChartLegendItemVisualStyle style) { SmoothingMode sm = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; RenderLegendItemMarkerEx(g, litem, style); g.SmoothingMode = sm; } #region RenderLegendItemMarkerEx internal virtual void RenderLegendItemMarkerEx( Graphics g, ChartLegendItem litem, ChartLegendItemVisualStyle style) { throw new NotImplementedException(); } #endregion #region RenderDefaultMarker internal void RenderDefaultMarker(Graphics g, Rectangle bounds, ChartSeriesVisualStyle sstyle) { bounds.Width++; bounds.Height++; Background background = sstyle.MarkerVisualStyle.Background; if (background.IsEmpty == true) { g.FillRectangle(Brushes.DimGray, bounds); } else { using (Brush br = background.GetBrush(bounds)) g.FillRectangle(br, bounds); } } #endregion #endregion #endregion #region InvalidateRender public override void InvalidateRender() { BaseChart chart = Parent as BaseChart; if (chart != null) chart.InvalidateRender(); } #endregion #region Copy/CopyTo public override ChartVisualElement Copy() { BaseSeries copy = new BaseSeries(); CopyTo(copy); return (copy); } public override void CopyTo(ChartVisualElement copy) { BaseSeries c = copy as BaseSeries; if (c != null) { base.CopyTo(c); c.ChartLegendItemVisualStyles = (_ChartLegendItemVisualStyles != null) ? ChartLegendItemVisualStyles.Copy() : null; c.DataPropertyNameSeries = DataPropertyNameSeries; c.DataPropertyNameX = DataPropertyNameX; c.DataPropertyNamesY = DataPropertyNamesY; c.DataMember = DataMember; c.DataSource = DataSource; c.DefaultPaletteColor = DefaultPaletteColor; c.SeriesType = SeriesType; c.CheckedInLegend = CheckedInLegend; c.LegendText = LegendText; c.ShowCheckBoxInLegend = ShowCheckBoxInLegend; c.ShowInLegend = ShowInLegend; c.ShowInParentLegend = ShowInParentLegend; c.ShowMarkerInLegend = ShowMarkerInLegend; } } #endregion #region GetSerialData internal override SerialElementCollection GetSerialData(string serialName) { SerialElementCollection sec = new SerialElementCollection(); if (serialName != null) { if (serialName.Equals("") == true) serialName = "BaseSeries"; sec.AddStartElement(serialName); } if (_ChartLegendItemVisualStyles != null) sec.AddElement(_ChartLegendItemVisualStyles.GetSerialData("ChartLegendItemVisualStyles")); //sec.AddDataValue("DataSource", DataSource, null); sec.AddValue("DataMember", DataMember, null); sec.AddValue("DataPropertyNameSeries", DataPropertyNameSeries, null); sec.AddValue("DataPropertyNameX", DataPropertyNameX, null); if (_DataPropertyNamesY != null && _DataPropertyNamesY.Count > 0) { sec.AddStartElement("DataPropertyNamesYs count=\"" + _DataPropertyNamesY.Count + "\""); foreach (string s in _DataPropertyNamesY) sec.AddValue("DataPropertyNamesY", s); sec.AddEndElement("DataPropertyNamesYs"); } sec.AddValue("DefaultPaletteColor", DefaultPaletteColor, Color.Empty); sec.AddValue("SeriesType", SeriesType, SeriesType.Point); sec.AddValue("CheckedInLegend", CheckedInLegend, true); sec.AddValue("LegendText", LegendText, null); sec.AddValue("ShowCheckBoxInLegend", ShowCheckBoxInLegend, true); sec.AddValue("ShowInLegend", ShowInLegend, true); sec.AddValue("ShowInParentLegend", ShowInParentLegend, true); sec.AddValue("ShowMarkerInLegend", ShowMarkerInLegend, true); 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 "DataMember": DataMember = se.StringValue; break; case "DataPropertyNameSeries": DataPropertyNameSeries = se.StringValue; break; case "DataPropertyNameX": DataPropertyNameX = se.StringValue; break; case "DataPropertyNamesY": DataPropertyNamesY.Add(se.StringValue); break; case "DataSource": DataSource = se.DataValue; break; case "DefaultPaletteColor": DefaultPaletteColor = se.GetValueColor(); break; case "SeriesType": SeriesType = (SeriesType)se.GetValueEnum(typeof(SeriesType)); break; case "CheckedInLegend": CheckedInLegend = bool.Parse(se.StringValue); break; case "LegendText": LegendText = se.StringValue; break; case "ShowCheckBoxInLegend": ShowCheckBoxInLegend = bool.Parse(se.StringValue); break; case "ShowInLegend": ShowInLegend = bool.Parse(se.StringValue); break; case "ShowInParentLegend": ShowInParentLegend = bool.Parse(se.StringValue); break; case "ShowMarkerInLegend": ShowMarkerInLegend = bool.Parse(se.StringValue); break; default: base.ProcessValue(se); break; } } #endregion #region ProcessCollection internal override void ProcessCollection(SerialElement se) { SerialElementCollection sec = se.Sec; switch (se.Name) { case "ChartLegendItemVisualStyles": sec.PutSerialData(ChartLegendItemVisualStyles); break; case "DataPropertyNamesYs": if (se.ArrayCount > 0) { DataPropertyNamesY = new CustomCollection(se.ArrayCount); sec.PutSerialData(this); } break; default: base.ProcessCollection(se); break; } } #endregion #endregion #region Series States [Flags] private enum States : uint { NeedToUpdateBindings = (1U << 0), CheckedInLegend = (1U << 1), ShowInLegend = (1U << 2), ShowInParentLegend = (1U << 3), ShowCheckBoxInLegend = (1U << 4), ShowMarkerInLegend = (1U << 5), } #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 IDisposable public override void Dispose() { ChartLegendItemVisualStyles = null; base.Dispose(); } #endregion } #region enums #region SeriesType /// /// Defines available Series types /// public enum SeriesType { Bubble, HorizontalBar, VerticalBar, Line, Point, HorizontalDot, // Wilkinson dotplot VerticalDot, HorizontalHiLoBar, // Box, Candle, HiLo VerticalHiLoBar, Pie, //Polar, //Radar, //TreeMap, } #endregion #endregion }