1506 lines
39 KiB
C#
1506 lines
39 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Windows.Forms;
|
|
using DevComponents.DotNetBar.Charts.Style;
|
|
|
|
namespace DevComponents.DotNetBar.Charts
|
|
{
|
|
/// <summary>
|
|
/// Represents an item in the chart Legend.
|
|
/// </summary>
|
|
public class ChartLegendItem : ChartVisualElement
|
|
{
|
|
#region Private variables
|
|
|
|
private States _States;
|
|
|
|
private List<ILegendItem> _ChartItems;
|
|
private ChartLegendItem _LikeItem;
|
|
|
|
private Tbool _ShowCheckBox = Tbool.NotSet;
|
|
private Tbool _ShowItemText = Tbool.NotSet;
|
|
private Tbool _ShowMarker = Tbool.NotSet;
|
|
private Tbool _ShowInParentLegend = Tbool.NotSet;
|
|
|
|
private ChartLegendItemVisualStyles _ChartLegendItemVisualStyles;
|
|
private EffectiveStyles<ChartLegendItemVisualStyle> _EffectiveStyles;
|
|
|
|
private Size _MarkerSize;
|
|
private Size _TextSize;
|
|
|
|
private Rectangle _MarkerBounds;
|
|
|
|
private string _ItemText;
|
|
private string _FormattedText;
|
|
|
|
private LegendItemArea _HitArea;
|
|
private LegendItemArea _MouseDownHitArea;
|
|
|
|
private CheckState _CheckState = CheckState.Unchecked;
|
|
private bool _InCheckStateUpdate;
|
|
|
|
#endregion
|
|
|
|
public ChartLegendItem()
|
|
{
|
|
InitDefaultStates();
|
|
|
|
_EffectiveStyles = new EffectiveStyles<ChartLegendItemVisualStyle>(this);
|
|
}
|
|
|
|
#region InitDefaultStates
|
|
|
|
private void InitDefaultStates()
|
|
{
|
|
SetState(States.IsEnabled, true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public properties
|
|
|
|
#region ChartItems
|
|
|
|
/// <summary>
|
|
/// Gets or sets the referenced Chart items.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public List<ILegendItem> ChartItems
|
|
{
|
|
get
|
|
{
|
|
if (_ChartItems == null)
|
|
_ChartItems = new List<ILegendItem>();
|
|
|
|
return (_ChartItems);
|
|
}
|
|
|
|
set
|
|
{
|
|
if (value != ChartItems)
|
|
{
|
|
_ChartItems = value;
|
|
|
|
OnPropertyChangedEx("ChartItems", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ChartLegendItemVisualStyles
|
|
|
|
/// <summary>
|
|
/// Gets or sets the visual styles for the Legend item.
|
|
/// </summary>
|
|
[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 CheckState
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the item's checkbox is checked.
|
|
/// </summary>
|
|
[DefaultValue(CheckState.Unchecked), Category("Appearance")]
|
|
[Description("Indicates whether the item's checkbox is checked.")]
|
|
public CheckState CheckState
|
|
{
|
|
get { return (_CheckState); }
|
|
|
|
set
|
|
{
|
|
if (value != _CheckState)
|
|
{
|
|
_CheckState = value;
|
|
|
|
UpdateChartItemsCheckState();
|
|
|
|
OnPropertyChangedEx("CheckState", VisualChangeType.Render);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region EffectiveStyles
|
|
|
|
/// <summary>
|
|
/// Gets a reference to the item's Effective (cached, composite) styles.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public EffectiveStyles<ChartLegendItemVisualStyle> EffectiveStyles
|
|
{
|
|
get { return (_EffectiveStyles); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ItemText
|
|
|
|
/// <summary>
|
|
/// Gets or sets the item Text.
|
|
/// </summary>
|
|
[DefaultValue(null), Category("Appearance")]
|
|
[Description("Indicates the item Text.")]
|
|
public string ItemText
|
|
{
|
|
get { return (_ItemText); }
|
|
|
|
set
|
|
{
|
|
if (value != _ItemText)
|
|
{
|
|
_ItemText = value;
|
|
|
|
OnPropertyChangedEx("ItemText", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ItemTextBounds
|
|
|
|
/// <summary>
|
|
/// Gets the Item's Text bounds
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public Rectangle ItemTextBounds
|
|
{
|
|
get
|
|
{
|
|
Rectangle bounds = Bounds;
|
|
|
|
int n = _MarkerSize.Width + Dpi.Width(Legend.ItemTextOffset);
|
|
|
|
bounds.X += n;
|
|
bounds.Width -= n;
|
|
|
|
return (bounds);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Legend
|
|
|
|
/// <summary>
|
|
/// Gets the associated ChartLegend
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public ChartLegend Legend
|
|
{
|
|
get { return (Parent as ChartLegend); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MarkerBounds
|
|
|
|
/// <summary>
|
|
/// Gets the Marker bounds
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public Rectangle MarkerBounds
|
|
{
|
|
get { return (_MarkerBounds); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ShowCheckBox
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the item CheckBox is shown in the Legend.
|
|
/// </summary>
|
|
[DefaultValue(Tbool.NotSet), Category("Appearance")]
|
|
[Description("Indicates whether the item CheckBox is shown in the Legend.")]
|
|
public Tbool ShowCheckBox
|
|
{
|
|
get { return (_ShowCheckBox); }
|
|
|
|
set
|
|
{
|
|
if (value != _ShowCheckBox)
|
|
{
|
|
_ShowCheckBox = value;
|
|
|
|
OnPropertyChangedEx("ShowCheckBox", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ShowInParentLegend
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the item is shown in parent Legend(s).
|
|
/// </summary>
|
|
[DefaultValue(Tbool.NotSet), Category("Layout")]
|
|
[Description("Indicates whether the item is shown in parent Legend(s).")]
|
|
public Tbool ShowInParentLegend
|
|
{
|
|
get { return (_ShowInParentLegend); }
|
|
|
|
set
|
|
{
|
|
if (value != _ShowInParentLegend)
|
|
{
|
|
_ShowInParentLegend = value;
|
|
|
|
OnPropertyChangedEx("ShowInParentLegend", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ShowItemText
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the item text is shown in the Legend.
|
|
/// </summary>
|
|
[DefaultValue(Tbool.NotSet), Category("Appearance")]
|
|
[Description("Indicates whether the item text is shown in the Legend.")]
|
|
public Tbool ShowItemText
|
|
{
|
|
get { return (_ShowItemText); }
|
|
|
|
set
|
|
{
|
|
if (value != _ShowItemText)
|
|
{
|
|
_ShowItemText = value;
|
|
|
|
OnPropertyChangedEx("ShowItemText", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ShowMarker
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether the item Marker is shown in the Legend.
|
|
/// </summary>
|
|
[DefaultValue(Tbool.NotSet), Category("Appearance")]
|
|
[Description("Indicates whether the item Marker is shown in the Legend.")]
|
|
public Tbool ShowMarker
|
|
{
|
|
get { return (_ShowMarker); }
|
|
|
|
set
|
|
{
|
|
if (value != _ShowMarker)
|
|
{
|
|
_ShowMarker = value;
|
|
|
|
OnPropertyChangedEx("ShowMarker", VisualChangeType.Layout);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Internal properties
|
|
|
|
#region FormattedText
|
|
|
|
internal string FormattedText
|
|
{
|
|
get { return (_FormattedText); }
|
|
set { _FormattedText = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IsEnabled
|
|
|
|
internal bool IsEnabled
|
|
{
|
|
get { return (TestState(States.IsEnabled)); }
|
|
set { SetState(States.IsEnabled, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IsHitItem
|
|
|
|
internal bool IsHitItem
|
|
{
|
|
get { return (TestState(States.IsHitItem)); }
|
|
set { SetState(States.IsHitItem, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IsLegendHitItem
|
|
|
|
internal bool IsLegendHitItem
|
|
{
|
|
get { return (TestState(States.IsLegendHitItem)); }
|
|
set { SetState(States.IsLegendHitItem, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region LikeItem
|
|
|
|
internal ChartLegendItem LikeItem
|
|
{
|
|
get { return (_LikeItem ?? this); }
|
|
set { _LikeItem = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region TextWrapped
|
|
|
|
internal bool TextWrapped
|
|
{
|
|
get { return (TestState(States.TextWrapped)); }
|
|
set { SetState(States.TextWrapped, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region MeasureOverride
|
|
|
|
protected override void MeasureOverride(ChartLayoutInfo layoutInfo)
|
|
{
|
|
BoundsRelative = layoutInfo.LayoutBounds;
|
|
|
|
ChartLegend cl = Parent as ChartLegend;
|
|
|
|
if (cl != null)
|
|
{
|
|
Size sizeNeeded = Size.Empty;
|
|
Rectangle layoutBounds = layoutInfo.LayoutBounds;
|
|
|
|
ChartLegendItemVisualStyle style = EffectiveStyles[StyleType.Default];
|
|
|
|
if (cl.ShowMarkers == true || cl.ShowCheckBoxes == true)
|
|
{
|
|
Size size = MeasureMarker(layoutInfo, cl);
|
|
|
|
sizeNeeded.Width += (size.Width + Dpi.Width2);
|
|
|
|
if (cl.ShowItemText == true)
|
|
sizeNeeded.Width += Dpi.Width(cl.ItemTextOffset);
|
|
|
|
sizeNeeded.Height = size.Height;
|
|
|
|
layoutInfo.LayoutBounds.Width -= sizeNeeded.Width;
|
|
}
|
|
|
|
_TextSize = Size.Empty;
|
|
|
|
if (cl.ShowItemText == true)
|
|
{
|
|
Size size = MeasureItemText(layoutInfo, cl, style);
|
|
|
|
sizeNeeded.Width += size.Width;
|
|
|
|
if (size.Height > sizeNeeded.Height)
|
|
sizeNeeded.Height = size.Height;
|
|
}
|
|
|
|
layoutInfo.LayoutBounds = layoutBounds;
|
|
|
|
Size = sizeNeeded;
|
|
}
|
|
}
|
|
|
|
#region MeasureMarker
|
|
|
|
private Size MeasureMarker(ChartLayoutInfo layoutInfo, ChartLegend legend)
|
|
{
|
|
_MarkerSize = Size.Empty;
|
|
|
|
if (legend.ShowCheckBoxes == true)
|
|
_MarkerSize = Dpi.Size(legend.CheckBoxSize);
|
|
|
|
if (legend.ShowMarkers == true)
|
|
{
|
|
Size msize = Dpi.Size(legend.MarkerSize);
|
|
|
|
_MarkerSize.Width = Math.Max(_MarkerSize.Width, msize.Width);
|
|
_MarkerSize.Height = Math.Max(_MarkerSize.Height, msize.Height);
|
|
}
|
|
|
|
return (_MarkerSize);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MeasureItemText
|
|
|
|
private Size MeasureItemText(
|
|
ChartLayoutInfo layoutInfo, ChartLegend legend, ChartLegendItemVisualStyle style)
|
|
{
|
|
if (legend.ShowItemText == true && (ShowItemText != Tbool.False))
|
|
{
|
|
Graphics g = layoutInfo.Graphics;
|
|
|
|
string text = GetItemText();
|
|
|
|
if (string.IsNullOrEmpty(text) == false)
|
|
{
|
|
using (StringFormat sf = new StringFormat())
|
|
{
|
|
style.GetStringFormatFlags(sf);
|
|
|
|
Size size = layoutInfo.LayoutBounds.Size;
|
|
|
|
_TextSize = g.MeasureString(text, style.Font, size, sf).ToSize();
|
|
}
|
|
}
|
|
|
|
_TextSize.Width++;
|
|
_TextSize.Height++;
|
|
|
|
TextWrapped = false;
|
|
|
|
if (style.MaxLineCount > 1)
|
|
{
|
|
if (_TextSize.Height > style.Font.Height + 2)
|
|
{
|
|
if (text.Contains("\n") == false)
|
|
TextWrapped = true;
|
|
}
|
|
|
|
int lineHeight = style.Font.Height * style.MaxLineCount;
|
|
|
|
if (_TextSize.Height > lineHeight)
|
|
_TextSize.Height = lineHeight;
|
|
}
|
|
}
|
|
|
|
return (_TextSize);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ArrangeOverride
|
|
|
|
protected override void ArrangeOverride(ChartLayoutInfo layoutInfo)
|
|
{
|
|
BoundsRelative = layoutInfo.LayoutBounds;
|
|
|
|
Rectangle bounds = Bounds;
|
|
_MarkerBounds = bounds;
|
|
|
|
_MarkerBounds.X += Dpi.Width2;
|
|
|
|
if (_MarkerSize.IsEmpty == false)
|
|
{
|
|
_MarkerBounds.Size = _MarkerSize;
|
|
|
|
ChartLegend legend = Legend;
|
|
|
|
if (legend != null)
|
|
{
|
|
if (bounds.Height > _MarkerBounds.Height)
|
|
_MarkerBounds.Y += (bounds.Height - _MarkerBounds.Height) / 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_MarkerBounds.Size = Size.Empty;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RenderOverride
|
|
|
|
protected override void RenderOverride(ChartRenderInfo renderInfo)
|
|
{
|
|
ChartLegend legend = Parent as ChartLegend;
|
|
|
|
if (legend != null)
|
|
{
|
|
Graphics g = renderInfo.Graphics;
|
|
Rectangle bounds = Bounds;
|
|
|
|
bool showCheckBoxes = (CanShowCheckBox(legend) == true);
|
|
|
|
StyleState state = (IsMouseOver == true || IsHitItem == true)
|
|
? StyleState.MouseOver : StyleState.Default;
|
|
|
|
if (showCheckBoxes == true)
|
|
{
|
|
if (CheckState != CheckState.Unchecked)
|
|
state |= StyleState.Selected;
|
|
}
|
|
|
|
ChartLegendItemVisualStyle istyle = EffectiveStyles[state];
|
|
Color dcolor = GetLegendItemColor(legend, istyle);
|
|
|
|
if (istyle.Background.IsEmpty == false)
|
|
{
|
|
using (Brush br = istyle.Background.GetBrush(bounds))
|
|
g.FillRectangle(br, bounds);
|
|
}
|
|
|
|
if (_MarkerSize.IsEmpty == false)
|
|
{
|
|
if (CanShowCheckBox(legend) == true)
|
|
RenderCheckBox(g, istyle, dcolor);
|
|
|
|
else if (CanShowMarker(legend) == true)
|
|
RenderMarker(g, istyle);
|
|
|
|
int n = _MarkerSize.Width;
|
|
|
|
if (_TextSize.IsEmpty == false)
|
|
n += Dpi.Width(legend.ItemTextOffset);
|
|
|
|
bounds.X += n;
|
|
bounds.Width -= n;
|
|
}
|
|
|
|
if (_TextSize.IsEmpty == false)
|
|
RenderItemText(g, bounds, istyle, dcolor);
|
|
}
|
|
}
|
|
|
|
#region RenderCheckBox
|
|
|
|
private void RenderCheckBox(Graphics g,
|
|
ChartLegendItemVisualStyle istyle, Color dcolor)
|
|
{
|
|
if (_HitArea != LegendItemArea.CheckBox)
|
|
istyle = EffectiveStyles[StyleState.Default];
|
|
|
|
Rectangle r = _MarkerBounds;
|
|
r.Inflate(-1, -1);
|
|
|
|
Background background = istyle.CheckBoxBackground;
|
|
|
|
if (background.IsEmpty == false)
|
|
{
|
|
using (Brush br = background.GetBrush(r))
|
|
g.FillRectangle(br, r);
|
|
}
|
|
|
|
Color color = GetCheckBoxBorderColor(istyle, dcolor);
|
|
|
|
using (Pen pen = new Pen(color, Dpi.Width1))
|
|
g.DrawRectangle(pen, r);
|
|
|
|
color = GetCheckBoxCheckColor(istyle, dcolor);
|
|
|
|
Rectangle t = r;
|
|
t.Inflate(-Dpi.Width2, -Dpi.Width2);
|
|
|
|
float fx = (float)t.Width / Dpi.Width9;
|
|
float fy = (float)t.Height / Dpi.Width9;
|
|
|
|
switch (_CheckState)
|
|
{
|
|
case CheckState.Checked:
|
|
SmoothingMode sm = g.SmoothingMode;
|
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|
|
|
Point pt1 = new Point(t.X + (int)(fx), t.Y + (int)(fy * Dpi.Width4));
|
|
Point pt2 = new Point(t.X + (int)(fx * Dpi.Width3), t.Bottom - Dpi.Width2);
|
|
Point pt3 = new Point(t.Right - Dpi.Width1, t.Y + (int)fy);
|
|
|
|
using (Pen pen = new Pen(color, Dpi.Width2))
|
|
g.DrawLines(pen, new Point[] { pt1, pt2, pt3 });
|
|
|
|
g.SmoothingMode = sm;
|
|
break;
|
|
|
|
case CheckState.Indeterminate:
|
|
Rectangle z = t;
|
|
z.Inflate(-(int)fx, -(int)fy);
|
|
z.Width += Dpi.Width1;
|
|
z.Height += Dpi.Width1;
|
|
|
|
using (Brush br = new SolidBrush(color))
|
|
g.FillRectangle(br, z);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#region GetCheckBoxCheckColor
|
|
|
|
private Color GetCheckBoxCheckColor(
|
|
ChartLegendItemVisualStyle istyle, Color dcolor)
|
|
{
|
|
Color color = istyle.CheckBoxCheckColor;
|
|
|
|
if (color.IsEmpty == true)
|
|
color = dcolor;
|
|
|
|
return (color);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetCheckBoxBorderColor
|
|
|
|
private Color GetCheckBoxBorderColor(
|
|
ChartLegendItemVisualStyle istyle, Color dcolor)
|
|
{
|
|
Color color = istyle.CheckBoxBorderColor;
|
|
|
|
if (color.IsEmpty == true)
|
|
color = dcolor;
|
|
|
|
return (color);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region RenderMarker
|
|
|
|
private void RenderMarker(Graphics g, ChartLegendItemVisualStyle istyle)
|
|
{
|
|
if (istyle.MarkerVisualStyle.IsEmpty == false)
|
|
{
|
|
Color color = GetLegendItemColor(Legend, istyle);
|
|
|
|
istyle.MarkerVisualStyle.RenderMarker(g, Legend.PointMarker, MarkerBounds, color);
|
|
}
|
|
else
|
|
{
|
|
if (ChartItems.Count > 0)
|
|
{
|
|
ILegendItem item = ChartItems[0];
|
|
|
|
item.RenderLegendItemMarker(g, this, istyle);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RenderItemText
|
|
|
|
private void RenderItemText(Graphics g,
|
|
Rectangle bounds, ChartLegendItemVisualStyle istyle, Color dcolor)
|
|
{
|
|
bounds.Y++;
|
|
|
|
string text = GetItemText();
|
|
|
|
using (StringFormat sf = new StringFormat())
|
|
{
|
|
istyle.GetStringFormatFlags(sf);
|
|
|
|
Color color = istyle.TextColor;
|
|
|
|
if (color.IsEmpty == true)
|
|
color = dcolor;
|
|
|
|
using (Brush br = new SolidBrush(color))
|
|
g.DrawString(text, istyle.Font, br, bounds, sf);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetLegendItemColor
|
|
|
|
private Color GetLegendItemColor(ChartLegend legend, ChartLegendItemVisualStyle istyle)
|
|
{
|
|
if (IsEnabled == true)
|
|
{
|
|
Color color = istyle.TextColor;
|
|
|
|
if (color.IsEmpty == false)
|
|
return (color);
|
|
|
|
if (ChartItems.Count > 0)
|
|
{
|
|
color = ChartItems[0].LegendItem.EffectiveStyles[StyleType.Default].TextColor;
|
|
|
|
if (color.IsEmpty == true)
|
|
color = ChartItems[0].GetLegendItemColor();
|
|
}
|
|
|
|
if (color.IsEmpty == true)
|
|
color = Color.DimGray;
|
|
else
|
|
color = Color.FromArgb(255, color);
|
|
|
|
return (color);
|
|
}
|
|
else
|
|
{
|
|
Color color = istyle.DisabledTextColor;
|
|
|
|
if (color.IsEmpty == true)
|
|
color = Color.Silver;
|
|
|
|
return (color);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Mouse handling
|
|
|
|
#region OnMouseEnter
|
|
|
|
protected override bool OnMouseEnter(EventArgs e)
|
|
{
|
|
base.OnMouseEnter(e);
|
|
|
|
InvalidateRender();
|
|
InvalidateChartItems(true);
|
|
|
|
return (true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnMouseLeave
|
|
|
|
protected override bool OnMouseLeave(EventArgs e)
|
|
{
|
|
base.OnMouseLeave(e);
|
|
|
|
InvalidateRender();
|
|
InvalidateChartItems(false);
|
|
|
|
return (true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region InvalidateChartItems
|
|
|
|
private void InvalidateChartItems(bool isHitItem)
|
|
{
|
|
IsLegendHitItem = isHitItem;
|
|
|
|
foreach (ILegendItem item in ChartItems)
|
|
{
|
|
ILegendItemEx itemEx = item as ILegendItemEx;
|
|
|
|
if (itemEx != null)
|
|
{
|
|
if (itemEx.TrackLegendItem == true)
|
|
{
|
|
if (item is PieRing)
|
|
{
|
|
PieRing pieRing = (PieRing)item;
|
|
|
|
foreach (PieSeriesPoint psp in pieRing.Psps)
|
|
{
|
|
psp.LegendItem.IsLegendHitItem = isHitItem;
|
|
psp.InvalidateRender();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item.LegendItem.IsLegendHitItem = isHitItem;
|
|
itemEx.InvalidateRender();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnMouseMove
|
|
|
|
protected override bool OnMouseMove(MouseEventArgs e)
|
|
{
|
|
LegendItemArea area = GetItemAreaAt(e.Location);
|
|
|
|
if (_HitArea != area)
|
|
InvalidateRender();
|
|
|
|
_HitArea = area;
|
|
|
|
if (_HitArea == LegendItemArea.CheckBox)
|
|
{
|
|
ChartCursor = Cursors.Hand;
|
|
|
|
return (true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnMouseDown
|
|
|
|
protected override bool OnMouseDown(MouseEventArgs e)
|
|
{
|
|
base.OnMouseDown(e);
|
|
|
|
_MouseDownHitArea = _HitArea;
|
|
|
|
if (_HitArea == LegendItemArea.CheckBox)
|
|
{
|
|
ChartControl.CapturedItem = this;
|
|
|
|
return (true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region OnMouseUp
|
|
|
|
protected override bool OnMouseUp(MouseEventArgs e)
|
|
{
|
|
base.OnMouseUp(e);
|
|
|
|
if (_HitArea == LegendItemArea.CheckBox &&
|
|
_MouseDownHitArea == LegendItemArea.CheckBox)
|
|
{
|
|
switch (CheckState)
|
|
{
|
|
case CheckState.Checked:
|
|
CheckState = CheckState.Unchecked;
|
|
break;
|
|
|
|
default:
|
|
CheckState = CheckState.Checked;
|
|
break;
|
|
}
|
|
|
|
ChartControl.CapturedItem = null;
|
|
|
|
InvalidateDisplay();
|
|
}
|
|
|
|
return (true);
|
|
}
|
|
|
|
#region UpdateChartItemsCheckState
|
|
|
|
private void UpdateChartItemsCheckState()
|
|
{
|
|
if (_InCheckStateUpdate == false)
|
|
{
|
|
_InCheckStateUpdate = true;
|
|
|
|
if (CheckState != CheckState.Indeterminate)
|
|
{
|
|
foreach (ILegendItem item in ChartItems)
|
|
item.CheckedInLegend = (CheckState == CheckState.Checked);
|
|
}
|
|
|
|
if (ChartControl != null)
|
|
ChartControl.DoLegendItemCheckedChangedEvent(Legend, this);
|
|
|
|
_InCheckStateUpdate = false;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetItemText
|
|
|
|
private string GetItemText()
|
|
{
|
|
string text = GetItemTextEx();
|
|
|
|
if (string.IsNullOrEmpty(text) == false)
|
|
{
|
|
if (ChartItems.Count > 0)
|
|
{
|
|
if (ChartItems[0] is ILegendItemEx)
|
|
{
|
|
ILegendItemEx itemEx = (ILegendItemEx)ChartItems[0];
|
|
|
|
text = itemEx.FormatItemText(text);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (text);
|
|
}
|
|
|
|
#region GetItemTextEx
|
|
|
|
private string GetItemTextEx()
|
|
{
|
|
if (String.IsNullOrEmpty(_ItemText) == false)
|
|
return (_ItemText);
|
|
|
|
foreach (ILegendItem item in _ChartItems)
|
|
{
|
|
if (String.IsNullOrEmpty(item.LegendText) == false)
|
|
return (item.LegendText);
|
|
}
|
|
|
|
if (_ChartItems.Count > 0)
|
|
{
|
|
if (String.IsNullOrEmpty(_ChartItems[0].Name) == false)
|
|
return (_ChartItems[0].Name);
|
|
}
|
|
|
|
if (String.IsNullOrEmpty(Name) == false)
|
|
return (Name);
|
|
|
|
return ("");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region GetItemAreaAt
|
|
|
|
private LegendItemArea GetItemAreaAt(Point pt)
|
|
{
|
|
if (Bounds.Contains(pt) == true)
|
|
{
|
|
if (_MarkerBounds.Contains(pt))
|
|
{
|
|
ChartLegend legend = Parent as ChartLegend;
|
|
|
|
if (CanShowCheckBox(legend) == true)
|
|
return (LegendItemArea.CheckBox);
|
|
|
|
return (LegendItemArea.Marker);
|
|
}
|
|
|
|
if (pt.X > _MarkerBounds.Right)
|
|
return (LegendItemArea.ItemText);
|
|
}
|
|
|
|
return (LegendItemArea.None);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Style Support
|
|
|
|
#region ApplyStyles
|
|
|
|
public override void ApplyStyles(BaseVisualStyle style, StyleType cs)
|
|
{
|
|
ChartLegendItemVisualStyle lstyle = style as ChartLegendItemVisualStyle;
|
|
|
|
if (lstyle != null)
|
|
{
|
|
ApplyParentStyles(lstyle, cs, Parent as ChartVisualElement);
|
|
|
|
lstyle.ApplyStyle(ChartLegendItemVisualStyles[cs]);
|
|
|
|
if (ChartItems.Count > 0 && ChartItems[0] != null)
|
|
lstyle.ApplyStyle(ChartItems[0].ChartLegendItemVisualStyles[cs]);
|
|
}
|
|
}
|
|
|
|
#region ApplyParentStyles
|
|
|
|
private void ApplyParentStyles(
|
|
ChartLegendItemVisualStyle lstyle, StyleType cs, ChartVisualElement item)
|
|
{
|
|
if (item != null)
|
|
{
|
|
ApplyParentStyles(lstyle, cs, item.Parent as ChartVisualElement);
|
|
|
|
if (item is ChartLegend)
|
|
lstyle.ApplyStyle(((ChartLegend)item).ChartLegendItemVisualStyles[cs]);
|
|
|
|
else if (item is ChartPanel)
|
|
lstyle.ApplyStyle(((ChartPanel)item).DefaultVisualStyles.ChartLegendItemVisualStyles[cs]);
|
|
}
|
|
else
|
|
{
|
|
lstyle.ApplyStyle(ChartControl.BaseVisualStyles.ChartLegendItemVisualStyles[cs]);
|
|
lstyle.ApplyStyle(ChartControl.DefaultVisualStyles.ChartLegendItemVisualStyles[cs]);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region ApplyDefaults
|
|
|
|
public override void ApplyDefaults(BaseVisualStyle style, StyleType cs)
|
|
{
|
|
ChartLegendItemVisualStyle lstyle = style as ChartLegendItemVisualStyle;
|
|
|
|
if (lstyle != null)
|
|
{
|
|
if (lstyle.MaxLineCount <= 0)
|
|
lstyle.MaxLineCount = 2;
|
|
|
|
if (lstyle.Font == null)
|
|
lstyle.Font = SystemFonts.DefaultFont;
|
|
}
|
|
|
|
base.ApplyDefaults(style, cs);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region InvalidateStyle
|
|
|
|
///<summary>
|
|
///Invalidate the cached Styles
|
|
///</summary>
|
|
public void InvalidateStyle()
|
|
{
|
|
ClearEffectiveStyles();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ClearEffectiveStyles
|
|
|
|
protected override void ClearEffectiveStyles()
|
|
{
|
|
base.ClearEffectiveStyles();
|
|
|
|
EffectiveStyles.InvalidateStyles();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region InvalidateDisplay
|
|
|
|
private void InvalidateDisplay()
|
|
{
|
|
ChartContainer cc = ParentChartContainer;
|
|
|
|
if (cc != null)
|
|
{
|
|
cc.InvalidateRender(GetScrollBounds(cc.ContentBounds));
|
|
cc.InvalidateLayoutBounds(null);
|
|
}
|
|
|
|
while (cc != null)
|
|
{
|
|
ILegendData ld = cc as ILegendData;
|
|
|
|
if (ld != null)
|
|
{
|
|
ChartLegend legend = ld.Legend;
|
|
|
|
if (legend != null)
|
|
{
|
|
if (CanShowInParentLegend(legend) == true)
|
|
legend.InvalidateItem(this);
|
|
}
|
|
}
|
|
|
|
cc = cc.ParentChartContainer;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region UpdateCheckState
|
|
|
|
internal void UpdateCheckState()
|
|
{
|
|
if (_InCheckStateUpdate == false)
|
|
{
|
|
_InCheckStateUpdate = true;
|
|
|
|
if (ChartItems.Count > 0)
|
|
{
|
|
CheckState checkState = CheckState.Unchecked;
|
|
|
|
for (int i = 0; i < ChartItems.Count; i++)
|
|
{
|
|
ILegendItem chartItem = ChartItems[i];
|
|
|
|
CheckState ics = chartItem.CheckedInLegend ? CheckState.Checked : CheckState.Unchecked;
|
|
|
|
if (i == 0)
|
|
{
|
|
checkState = ics;
|
|
}
|
|
else
|
|
{
|
|
if (checkState != ics)
|
|
{
|
|
checkState = CheckState.Indeterminate;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (CheckState != checkState)
|
|
{
|
|
CheckState = checkState;
|
|
|
|
InvalidateDisplay();
|
|
}
|
|
}
|
|
|
|
_InCheckStateUpdate = false;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CanShowCheckBox
|
|
|
|
private bool CanShowCheckBox(ChartLegend legend)
|
|
{
|
|
if (legend.ShowCheckBoxes == true)
|
|
{
|
|
if (ShowCheckBox != Tbool.NotSet)
|
|
{
|
|
bool show = (ShowCheckBox == Tbool.False ? false : true);
|
|
|
|
if (ChartItems.Count > 0)
|
|
ChartItems[0].ShowCheckBoxInLegend = show;
|
|
|
|
return (show);
|
|
}
|
|
|
|
if (ChartItems.Count > 0)
|
|
return (ChartItems[0].ShowCheckBoxInLegend);
|
|
|
|
return (true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CanShowMarker
|
|
|
|
private bool CanShowMarker(ChartLegend legend)
|
|
{
|
|
if (legend.ShowMarkers == true)
|
|
{
|
|
if (ShowMarker == Tbool.NotSet)
|
|
{
|
|
if (ChartItems.Count > 0)
|
|
return (ChartItems[0].ShowMarkerInLegend);
|
|
}
|
|
|
|
return (ShowMarker == Tbool.False ? false : true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CanShowInParentLegend
|
|
|
|
private bool CanShowInParentLegend(ChartLegend legend)
|
|
{
|
|
if (ChartItems.Count > 0)
|
|
{
|
|
if (ShowInParentLegend == Tbool.NotSet)
|
|
return (ChartItems[0].ShowInParentLegend);
|
|
|
|
return (ShowInParentLegend == Tbool.False ? false : true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Copy/CopyTo
|
|
|
|
public override ChartVisualElement Copy()
|
|
{
|
|
ChartLegendItem copy = new ChartLegendItem();
|
|
|
|
CopyTo(copy);
|
|
|
|
return (copy);
|
|
}
|
|
|
|
public override void CopyTo(ChartVisualElement copy)
|
|
{
|
|
ChartLegendItem c = copy as ChartLegendItem;
|
|
|
|
if (c != null)
|
|
{
|
|
base.CopyTo(c);
|
|
|
|
c.ChartLegendItemVisualStyles =
|
|
(_ChartLegendItemVisualStyles != null) ? ChartLegendItemVisualStyles.Copy() : null;
|
|
|
|
c.CheckState = CheckState;
|
|
c.ItemText = ItemText;
|
|
c.ShowCheckBox = ShowCheckBox;
|
|
c.ShowInParentLegend = ShowInParentLegend;
|
|
c.ShowItemText = ShowItemText;
|
|
c.ShowMarker = ShowMarker;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetSerialData
|
|
|
|
internal override SerialElementCollection GetSerialData(string serialName)
|
|
{
|
|
SerialElementCollection sec = new SerialElementCollection();
|
|
|
|
if (serialName != null)
|
|
{
|
|
if (serialName.Equals("") == true)
|
|
serialName = "BaseChart";
|
|
|
|
sec.AddStartElement(serialName);
|
|
}
|
|
|
|
if (_ChartLegendItemVisualStyles != null)
|
|
sec.AddElement(_ChartLegendItemVisualStyles.GetSerialData("ChartLegendItemVisualStyles"));
|
|
|
|
sec.AddValue("CheckState", CheckState, CheckState.Unchecked);
|
|
sec.AddValue("ItemText", ItemText, null);
|
|
sec.AddValue("ShowCheckBox", ShowCheckBox, Tbool.NotSet);
|
|
sec.AddValue("ShowInParentLegend", ShowInParentLegend, Tbool.NotSet);
|
|
sec.AddValue("ShowItemText", ShowItemText, Tbool.NotSet);
|
|
sec.AddValue("ShowMarker", ShowMarker, Tbool.NotSet);
|
|
|
|
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 "CheckState":
|
|
CheckState = (CheckState)se.GetValueEnum(typeof(CheckState));
|
|
break;
|
|
|
|
case "ItemText":
|
|
ItemText = se.StringValue;
|
|
break;
|
|
|
|
case "ShowCheckBox":
|
|
ShowCheckBox = (Tbool)se.GetValueEnum(typeof(Tbool));
|
|
break;
|
|
|
|
case "ShowInParentLegend":
|
|
ShowInParentLegend = (Tbool)se.GetValueEnum(typeof(Tbool));
|
|
break;
|
|
|
|
case "ShowItemText":
|
|
ShowItemText = (Tbool)se.GetValueEnum(typeof(Tbool));
|
|
break;
|
|
|
|
case "ShowMarker":
|
|
ShowMarker = (Tbool)se.GetValueEnum(typeof(Tbool));
|
|
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;
|
|
|
|
default:
|
|
base.ProcessCollection(se);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region States
|
|
|
|
[Flags]
|
|
private enum States : uint
|
|
{
|
|
IsEnabled = (1U << 0),
|
|
|
|
IsHitItem = (1 << 1),
|
|
IsLegendHitItem = (1 << 2),
|
|
|
|
TextWrapped = (1U << 3),
|
|
}
|
|
|
|
#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 LegendItemArea
|
|
|
|
public enum LegendItemArea
|
|
{
|
|
None = 0,
|
|
|
|
CheckBox,
|
|
ItemText,
|
|
Marker,
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Interfaces
|
|
|
|
#region ILegendItem
|
|
|
|
public interface ILegendItem
|
|
{
|
|
string Name { get; set; }
|
|
string LegendText { get; set; }
|
|
|
|
ChartLegendItem LegendItem { get; }
|
|
ChartLegendItem GetLegendItem();
|
|
List<ChartLegendItem> GetLegendItems();
|
|
|
|
Color GetLegendItemColor();
|
|
|
|
bool ShowInLegend { get; set; }
|
|
bool ShowInParentLegend { get; set; }
|
|
bool ShowCheckBoxInLegend { get; set; }
|
|
bool ShowMarkerInLegend { get; set; }
|
|
bool CheckedInLegend { get; set; }
|
|
|
|
void RenderLegendItemMarker(Graphics g, ChartLegendItem item, ChartLegendItemVisualStyle style);
|
|
|
|
ChartLegendItemVisualStyles ChartLegendItemVisualStyles { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ILegendItem
|
|
|
|
internal interface ILegendItemEx
|
|
{
|
|
bool TrackLegendItem { get; }
|
|
|
|
void InvalidateRender();
|
|
string FormatItemText(string text);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
}
|