|
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: Title.cs
//
// Namespace: DataVisualization.Charting
//
// Classes: TitleCollection, Title, Docking
//
// Purpose: Titles can be added to the chart by simply including
// those titles into the Titles collection, which is
// found in the root Chart object. The Title object
// incorporates several properties that can be used to
// position, dock, and control the appearance of any
// Title. Title positioning can be explicitly set, or
// you can specify that your title be docked. The
// charting control gives you full control over all of
// the appearance properties of your Titles, so you have
// the ability to set specific properties for such things
// as fonts, or colors, and even text effects.
//
// NOTE: In early versions of the Chart control only 1 title was
// exposed through the Title, TitleFont and TitleFontColor properties
// in the root chart object. Due to the customer requests, support for
// unlimited number of titles was added through the TitleCollection
// exposed as a Titles property of the root chart object. Old
// properties were deprecated and marked as non-browsable.
//
// Reviewed: AG - Microsoft 13, 2007
//
//===================================================================
#region Used namespaces
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
#if Microsoft_CONTROL
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms.DataVisualization.Charting.Data;
using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
using System.Windows.Forms.DataVisualization.Charting.Utilities;
using System.Windows.Forms.DataVisualization.Charting.Borders3D;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
using System.Windows.Forms.Design;
#else
using System.Web;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.DataVisualization.Charting.Data;
using System.Web.UI.DataVisualization.Charting.Utilities;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
#region Title enumerations
/// <summary>
/// An enumeration of chart element docking styles.
/// </summary>
public enum Docking
{
/// <summary>
/// Docked to the top.
/// </summary>
Top,
/// <summary>
/// Docked to the right.
/// </summary>
Right,
/// <summary>
/// Docked to the bottom.
/// </summary>
Bottom,
/// <summary>
/// Docked to the left.
/// </summary>
Left,
};
/// <summary>
/// Text drawing styles.
/// </summary>
public enum TextStyle
{
/// <summary>
/// Default text drawing style.
/// </summary>
Default,
/// <summary>
/// Shadow text.
/// </summary>
Shadow,
/// <summary>
/// Emboss text.
/// </summary>
Emboss,
/// <summary>
/// Embed text.
/// </summary>
Embed,
/// <summary>
/// Frame text.
/// </summary>
Frame
}
/// <summary>
/// An enumeration of chart text orientation.
/// </summary>
public enum TextOrientation
{
/// <summary>
/// Orientation is automatically determined based on the type of the
/// chart element it is used in.
/// </summary>
Auto,
/// <summary>
/// Horizontal text.
/// </summary>
Horizontal,
/// <summary>
/// Text rotated 90 degrees and oriented from top to bottom.
/// </summary>
Rotated90,
/// <summary>
/// Text rotated 270 degrees and oriented from bottom to top.
/// </summary>
Rotated270,
/// <summary>
/// Text characters are not rotated and position one below the other.
/// </summary>
Stacked
}
#endregion
/// <summary>
/// The Title class provides properties which define content, visual
/// appearance and position of the single chart title. It also
/// contains methods responsible for calculating title position,
/// drawing and hit testing.
/// </summary>
[
SRDescription("DescriptionAttributeTitle5"),
]
#if Microsoft_CONTROL
public class Title : ChartNamedElement, IDisposable
#else
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class Title : ChartNamedElement, IDisposable, IChartMapArea
#endif
{
#region Fields
// Spacing between title text and the border in pixels
internal int titleBorderSpacing = 4;
//***********************************************************
//** Private data members, which store properties values
//***********************************************************
// Title text
private string _text = String.Empty;
// Title drawing style
private TextStyle _style = TextStyle.Default;
// Title position
private ElementPosition _position = null;
// Background properties
private bool _visible = true;
private Color _backColor = Color.Empty;
private ChartHatchStyle _backHatchStyle = ChartHatchStyle.None;
private string _backImage = "";
private ChartImageWrapMode _backImageWrapMode = ChartImageWrapMode.Tile;
private Color _backImageTransparentColor = Color.Empty;
private ChartImageAlignmentStyle _backImageAlignment = ChartImageAlignmentStyle.TopLeft;
private GradientStyle _backGradientStyle = GradientStyle.None;
private Color _backSecondaryColor = Color.Empty;
private int _shadowOffset = 0;
private Color _shadowColor = Color.FromArgb(128, 0, 0, 0);
// Border properties
private Color _borderColor = Color.Empty;
private int _borderWidth = 1;
private ChartDashStyle _borderDashStyle = ChartDashStyle.Solid;
// Font properties
private FontCache _fontCache = new FontCache();
private Font _font;
private Color _foreColor = Color.Black;
// Docking and Alignment properties
private ContentAlignment _alignment = ContentAlignment.MiddleCenter;
private Docking _docking = Docking.Top;
private string _dockedToChartArea = Constants.NotSetValue;
private bool _isDockedInsideChartArea = true;
private int _dockingOffset = 0;
// Interactive properties
private string _toolTip = String.Empty;
#if !Microsoft_CONTROL
private string _url = String.Empty;
private string _mapAreaAttributes = String.Empty;
private string _postbackValue = String.Empty;
#endif
// Default text orientation
private TextOrientation _textOrientation = TextOrientation.Auto;
#endregion
#region Constructors and Initialization
/// <summary>
/// Title constructor.
/// </summary>
public Title()
{
Initialize(string.Empty, Docking.Top, null, Color.Black);
}
/// <summary>
/// Public constructor.
/// </summary>
/// <param name="text">Title text.</param>
public Title(string text)
{
Initialize(text, Docking.Top, null, Color.Black);
}
/// <summary>
/// Title constructor.
/// </summary>
/// <param name="text">Title text.</param>
/// <param name="docking">Title docking.</param>
public Title(string text, Docking docking)
{
Initialize(text, docking, null, Color.Black);
}
/// <summary>
/// Title constructor.
/// </summary>
/// <param name="text">Title text.</param>
/// <param name="docking">Title docking.</param>
/// <param name="font">Title font.</param>
/// <param name="color">Title color.</param>
public Title(string text, Docking docking, Font font, Color color)
{
Initialize(text, docking, font, color);
}
/// <summary>
/// Initialize title object.
/// </summary>
/// <param name="text">Title text.</param>
/// <param name="docking">Title docking.</param>
/// <param name="font">Title font.</param>
/// <param name="color">Title color.</param>
private void Initialize(string text, Docking docking, Font font, Color color)
{
// Initialize fields
this._position = new ElementPosition(this);
this._font = _fontCache.DefaultFont;
this._text = text;
this._docking = docking;
this._foreColor = color;
if(font != null)
{
this._font = font;
}
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the unique name of a ChartArea object.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
Bindable(true),
SRDescription("DescriptionAttributeTitle_Name"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public override string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
/// <summary>
/// Gets or sets the text orientation.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(TextOrientation.Auto),
SRDescription("DescriptionAttribute_TextOrientation"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public TextOrientation TextOrientation
{
get
{
return this._textOrientation;
}
set
{
this._textOrientation = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets a flag that specifies whether the title is visible.
/// </summary>
/// <value>
/// <b>True</b> if the title is visible; <b>false</b> otherwise.
/// </value>
[
SRCategory("CategoryAttributeAppearance"),
DefaultValue(true),
SRDescription("DescriptionAttributeTitle_Visible"),
ParenthesizePropertyNameAttribute(true),
]
virtual public bool Visible
{
get
{
return _visible;
}
set
{
_visible = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the chart area name which the title is docked to inside or outside.
/// </summary>
[
SRCategory("CategoryAttributeDocking"),
Bindable(true),
DefaultValue(Constants.NotSetValue),
SRDescription("DescriptionAttributeTitle_DockToChartArea"),
TypeConverter(typeof(LegendAreaNameConverter)),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
]
public string DockedToChartArea
{
get
{
return _dockedToChartArea;
}
set
{
if(value != _dockedToChartArea)
{
if(value.Length == 0)
{
_dockedToChartArea = Constants.NotSetValue;
}
else
{
if (Chart != null && Chart.ChartAreas != null)
{
Chart.ChartAreas.VerifyNameReference(value);
}
_dockedToChartArea = value;
}
this.Invalidate(false);
}
}
}
/// <summary>
/// Gets or sets a property which indicates whether the title is docked inside chart area.
/// DockedToChartArea property must be set first.
/// </summary>
[
SRCategory("CategoryAttributeDocking"),
Bindable(true),
DefaultValue(true),
SRDescription("DescriptionAttributeTitle_DockInsideChartArea"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
]
public bool IsDockedInsideChartArea
{
get
{
return _isDockedInsideChartArea;
}
set
{
if(value != _isDockedInsideChartArea)
{
_isDockedInsideChartArea = value;
this.Invalidate(false);
}
}
}
/// <summary>
/// Gets or sets the positive or negative offset of the docked title position.
/// </summary>
[
SRCategory("CategoryAttributeDocking"),
Bindable(true),
DefaultValue(0),
SRDescription("DescriptionAttributeTitle_DockOffset"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
]
public int DockingOffset
{
get
{
return _dockingOffset;
}
set
{
if(value != _dockingOffset)
{
if (value < -100 || value > 100)
{
throw (new ArgumentOutOfRangeException("value", SR.ExceptionValueMustBeInRange("DockingOffset", (-100).ToString(CultureInfo.CurrentCulture), (100).ToString(CultureInfo.CurrentCulture))));
}
_dockingOffset = value;
this.Invalidate(false);
}
}
}
/// <summary>
/// Gets or sets the position of the title.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
SRDescription("DescriptionAttributeTitle_Position"),
#if Microsoft_CONTROL
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
#else
PersistenceMode(PersistenceMode.InnerProperty),
#endif
NotifyParentPropertyAttribute(true),
TypeConverter(typeof(ElementPositionConverter)),
SerializationVisibilityAttribute(SerializationVisibility.Element)
]
public ElementPosition Position
{
get
{
// Serialize only position values if Auto set to false
if (Chart != null && Chart.serializationStatus == SerializationStatus.Saving)
{
if(_position.Auto)
{
return new ElementPosition();
}
else
{
ElementPosition newPosition = new ElementPosition();
#if Microsoft_CONTROL
newPosition.Auto = false;
#else
newPosition.Auto = true;
#endif
newPosition.SetPositionNoAuto(_position.X, _position.Y, _position.Width, _position.Height);
return newPosition;
}
}
return _position;
}
set
{
_position = value;
_position.Parent = this;
this.Invalidate(false);
}
}
/// <summary>
/// Determoines if this position should be serialized.
/// </summary>
/// <returns></returns>
internal bool ShouldSerializePosition()
{
return !this.Position.Auto;
}
/// <summary>
/// Gets or sets the text of the title.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(""),
SRDescription("DescriptionAttributeTitle_Text"),
NotifyParentPropertyAttribute(true),
ParenthesizePropertyNameAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public string Text
{
get
{
return _text;
}
set
{
_text = (value == null) ? string.Empty : value;
this.Invalidate(false);
}
}
/// <summary>
/// Title drawing style.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(TextStyle.Default),
SRDescription("DescriptionAttributeTextStyle"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public TextStyle TextStyle
{
get
{
return _style;
}
set
{
_style = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the background color of the title.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeBackColor"),
NotifyParentPropertyAttribute(true),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color BackColor
{
get
{
return _backColor;
}
set
{
_backColor = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the border color of the title.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeBorderColor"),
NotifyParentPropertyAttribute(true),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color BorderColor
{
get
{
return _borderColor;
}
set
{
_borderColor = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the border style of the title.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartDashStyle.Solid),
SRDescription("DescriptionAttributeBorderDashStyle"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public ChartDashStyle BorderDashStyle
{
get
{
return _borderDashStyle;
}
set
{
_borderDashStyle = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the border width of the title.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(1),
SRDescription("DescriptionAttributeBorderWidth"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public int BorderWidth
{
get
{
return _borderWidth;
}
set
{
if(value < 0)
{
throw (new ArgumentOutOfRangeException("value", SR.ExceptionTitleBorderWidthIsNegative));
}
_borderWidth = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the background image.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(""),
SRDescription("DescriptionAttributeBackImage"),
Editor(Editors.ImageValueEditor.Editor, Editors.ImageValueEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
NotifyParentPropertyAttribute(true),
]
public string BackImage
{
get
{
return _backImage;
}
set
{
_backImage = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the background image drawing mode.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartImageWrapMode.Tile),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeImageWrapMode"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public ChartImageWrapMode BackImageWrapMode
{
get
{
return _backImageWrapMode;
}
set
{
_backImageWrapMode = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets a color which will be replaced with a transparent color while drawing the background image.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), ""),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeImageTransparentColor"),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color BackImageTransparentColor
{
get
{
return _backImageTransparentColor;
}
set
{
_backImageTransparentColor = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the background image alignment used by unscale drawing mode.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartImageAlignmentStyle.TopLeft),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeBackImageAlign"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public ChartImageAlignmentStyle BackImageAlignment
{
get
{
return _backImageAlignment;
}
set
{
_backImageAlignment = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the background gradient style.
/// <seealso cref="BackSecondaryColor"/>
/// <seealso cref="BackColor"/>
/// <seealso cref="BackHatchStyle"/>
/// </summary>
/// <value>
/// A <see cref="GradientStyle"/> value used for the background.
/// </value>
/// <remarks>
/// Two colors are used to draw the gradient, <see cref="BackColor"/> and <see cref="BackSecondaryColor"/>.
/// </remarks>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(GradientStyle.None),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeBackGradientStyle"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
Editor(Editors.GradientEditor.Editor, Editors.GradientEditor.Base)
]
public GradientStyle BackGradientStyle
{
get
{
return _backGradientStyle;
}
set
{
_backGradientStyle = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the secondary background color.
/// <seealso cref="BackColor"/>
/// <seealso cref="BackHatchStyle"/>
/// <seealso cref="BackGradientStyle"/>
/// </summary>
/// <value>
/// A <see cref="Color"/> value used for the secondary color of a background with
/// hatching or gradient fill.
/// </value>
/// <remarks>
/// This color is used with <see cref="BackColor"/> when <see cref="BackHatchStyle"/> or
/// <see cref="BackGradientStyle"/> are used.
/// </remarks>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), ""),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeBackSecondaryColor"),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color BackSecondaryColor
{
get
{
return _backSecondaryColor;
}
set
{
_backSecondaryColor = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the background hatch style.
/// <seealso cref="BackSecondaryColor"/>
/// <seealso cref="BackColor"/>
/// <seealso cref="BackGradientStyle"/>
/// </summary>
/// <value>
/// A <see cref="ChartHatchStyle"/> value used for the background.
/// </value>
/// <remarks>
/// Two colors are used to draw the hatching, <see cref="BackColor"/> and <see cref="BackSecondaryColor"/>.
/// </remarks>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartHatchStyle.None),
NotifyParentPropertyAttribute(true),
SRDescription("DescriptionAttributeBackHatchStyle"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
Editor(Editors.HatchStyleEditor.Editor, Editors.HatchStyleEditor.Base)
]
public ChartHatchStyle BackHatchStyle
{
get
{
return _backHatchStyle;
}
set
{
_backHatchStyle = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets the title font.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Font), "Microsoft Sans Serif, 8pt"),
SRDescription("DescriptionAttributeTitle_Font"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Font Font
{
get
{
return _font;
}
set
{
_font = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the title fore color.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), "Black"),
SRDescription("DescriptionAttributeTitle_Color"),
NotifyParentPropertyAttribute(true),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color ForeColor
{
get
{
return _foreColor;
}
set
{
_foreColor = value;
this.Invalidate(true);
}
}
/// <summary>
/// Gets or sets title alignment.
/// </summary>
[
SRCategory("CategoryAttributeDocking"),
Bindable(true),
DefaultValue(ContentAlignment.MiddleCenter),
SRDescription("DescriptionAttributeTitle_Alignment"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public ContentAlignment Alignment
{
get
{
return _alignment;
}
set
{
_alignment = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the title docking style.
/// </summary>
[
SRCategory("CategoryAttributeDocking"),
Bindable(true),
DefaultValue(Docking.Top),
SRDescription("DescriptionAttributeTitle_Docking"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Docking Docking
{
get
{
return _docking;
}
set
{
_docking = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the title shadow offset.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(0),
SRDescription("DescriptionAttributeShadowOffset"),
NotifyParentPropertyAttribute(true),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public int ShadowOffset
{
get
{
return _shadowOffset;
}
set
{
_shadowOffset = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the title shadow color.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), "128, 0, 0, 0"),
SRDescription("DescriptionAttributeShadowColor"),
NotifyParentPropertyAttribute(true),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color ShadowColor
{
get
{
return _shadowColor;
}
set
{
_shadowColor = value;
this.Invalidate(false);
}
}
/// <summary>
/// Gets or sets the tooltip.
/// </summary>
[
#if !Microsoft_CONTROL
SRCategory("CategoryAttributeMapArea"),
#else
SRCategory("CategoryAttributeToolTip"),
#endif
Bindable(true),
SRDescription("DescriptionAttributeToolTip"),
DefaultValue(""),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public string ToolTip
{
set
{
_toolTip = value;
}
get
{
return _toolTip;
}
}
#if !Microsoft_CONTROL
/// <summary>
/// Gets or sets the URL target of the title.
/// </summary>
[
SRCategory("CategoryAttributeMapArea"),
Bindable(true),
SRDescription("DescriptionAttributeUrl"),
DefaultValue(""),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
Editor(Editors.UrlValueEditor.Editor, Editors.UrlValueEditor.Base)
#endif
]
public string Url
{
set
{
_url = value;
}
get
{
return _url;
}
}
/// <summary>
/// Gets or sets the other attributes of the title map area.
/// </summary>
[
SRCategory("CategoryAttributeMapArea"),
Bindable(true),
SRDescription("DescriptionAttributeMapAreaAttributes"),
DefaultValue(""),
PersistenceMode(PersistenceMode.Attribute)
]
public string MapAreaAttributes
{
set
{
_mapAreaAttributes = value;
}
get
{
return _mapAreaAttributes;
}
}
/// <summary>
/// Gets or sets the postback value which can be processed on a click event.
/// </summary>
/// <value>The value which is passed to a click event as an argument.</value>
[DefaultValue("")]
[SRCategory(SR.Keys.CategoryAttributeMapArea)]
[SRDescription(SR.Keys.DescriptionAttributePostBackValue)]
public string PostBackValue
{
get
{
return this._postbackValue;
}
set
{
this._postbackValue = value;
}
}
#endif
/// <summary>
/// True if title background or border is visible
/// </summary>
internal bool BackGroundIsVisible
{
get
{
if(!this.BackColor.IsEmpty ||
this.BackImage.Length > 0 ||
(!this.BorderColor.IsEmpty && this.BorderDashStyle != ChartDashStyle.NotSet) )
{
return true;
}
return false;
}
}
#endregion
#region Helper Methods
/// <summary>
/// Checks if chart title is drawn vertically.
/// Note: From the drawing perspective stacked text orientation is not vertical.
/// </summary>
/// <returns>True if text is vertical.</returns>
private bool IsTextVertical
{
get
{
TextOrientation currentTextOrientation = this.GetTextOrientation();
return currentTextOrientation == TextOrientation.Rotated90 || currentTextOrientation == TextOrientation.Rotated270;
}
}
/// <summary>
/// Returns title text orientation. If set to Auto automatically determines the
/// orientation based on title docking.
/// </summary>
/// <returns>Current text orientation.</returns>
private TextOrientation GetTextOrientation()
{
if (this.TextOrientation == TextOrientation.Auto)
{
// When chart title is docked to the left or right we automatically
// set vertical text with different rotation angles.
if (this.Position.Auto)
{
if (this.Docking == Docking.Left)
{
return TextOrientation.Rotated270;
}
else if (this.Docking == Docking.Right)
{
return TextOrientation.Rotated90;
}
}
return TextOrientation.Horizontal;
}
return this.TextOrientation;
}
/// <summary>
/// Helper method that checks if title is visible.
/// </summary>
/// <returns>True if title is visible.</returns>
internal bool IsVisible()
{
if(this.Visible)
{
// Check if title is docked to the chart area
if(this.DockedToChartArea.Length > 0 &&
this.Chart != null)
{
if(this.Chart.ChartAreas.IndexOf(this.DockedToChartArea) >= 0)
{
// Do not show title when it is docked to invisible chart area
ChartArea area = this.Chart.ChartAreas[this.DockedToChartArea];
if(!area.Visible)
{
return false;
}
}
}
return true;
}
return false;
}
/// <summary>
/// Invalidate chart title when one of the properties is changed.
/// </summary>
/// <param name="invalidateTitleOnly">Indicates that only title area should be invalidated.</param>
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "This parameter is used when compiling for the Microsoft version of Chart")]
internal void Invalidate(bool invalidateTitleOnly)
{
#if Microsoft_CONTROL
if(Chart != null)
{
// Set dirty flag
Chart.dirtyFlag = true;
// Invalidate chart
if(invalidateTitleOnly)
{
// Calculate the position of the title
Rectangle invalRect = Chart.ClientRectangle;
if(this.Position.Width != 0 && this.Position.Height != 0 )
{
// Convert relative coordinates to absolute coordinates
invalRect.X = (int)(this.Position.X * (Common.ChartPicture.Width - 1) / 100F);
invalRect.Y = (int)(this.Position.Y * (Common.ChartPicture.Height - 1) / 100F);
invalRect.Width = (int)(this.Position.Width * (Common.ChartPicture.Width - 1) / 100F);
invalRect.Height = (int)(this.Position.Height * (Common.ChartPicture.Height - 1) / 100F);
// Inflate rectangle size using border size and shadow size
invalRect.Inflate(this.BorderWidth + this.ShadowOffset + 1, this.BorderWidth + this.ShadowOffset + 1);
}
// Invalidate title rectangle only
Chart.Invalidate(invalRect);
}
else
{
Invalidate();
}
}
#endif // #if Microsoft_CONTROL
}
#endregion
#region Painting and Selection Methods
/// <summary>
/// Paints title using chart graphics object.
/// </summary>
/// <param name="chartGraph">The graph provides drawing object to the display device. A Graphics object is associated with a specific device context.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
internal void Paint(ChartGraphics chartGraph )
{
// check if title is visible
if(!this.IsVisible())
{
return;
}
// Title text
string titleText = this.Text;
//***************************************************************
//** Calculate title relative position
//***************************************************************
RectangleF titlePosition = this.Position.ToRectangleF();
// Auto set the title position if width or height is not set for custom position
if(!this.Position.Auto && Common != null && Common.ChartPicture != null)
{
if(titlePosition.Width == 0 || titlePosition.Height == 0)
{
// Calculate text layout area
SizeF layoutArea = new SizeF(
(titlePosition.Width == 0) ? Common.ChartPicture.Width : titlePosition.Width,
(titlePosition.Height == 0) ? Common.ChartPicture.Height : titlePosition.Height);
if (this.IsTextVertical)
{
float tempValue = layoutArea.Width;
layoutArea.Width = layoutArea.Height;
layoutArea.Height = tempValue;
}
// Measure text size
layoutArea = chartGraph.GetAbsoluteSize(layoutArea);
SizeF titleSize = chartGraph.MeasureString(
"W" + titleText.Replace("\\n", "\n"),
this.Font,
layoutArea,
StringFormat.GenericDefault,
this.GetTextOrientation());
// Increase text size by 4 pixels
if(this.BackGroundIsVisible)
{
titleSize.Width += titleBorderSpacing;
titleSize.Height += titleBorderSpacing;
}
// Switch width and height for vertical text
if (this.IsTextVertical)
{
float tempValue = titleSize.Width;
titleSize.Width = titleSize.Height;
titleSize.Height = tempValue;
}
// Convert text size to relative coordinates
titleSize = chartGraph.GetRelativeSize(titleSize);
// Update custom position
if(titlePosition.Width == 0)
{
titlePosition.Width = titleSize.Width;
if(this.Alignment == ContentAlignment.BottomRight ||
this.Alignment == ContentAlignment.MiddleRight ||
this.Alignment == ContentAlignment.TopRight)
{
titlePosition.X = titlePosition.X - titlePosition.Width;
}
else if(this.Alignment == ContentAlignment.BottomCenter ||
this.Alignment == ContentAlignment.MiddleCenter ||
this.Alignment == ContentAlignment.TopCenter)
{
titlePosition.X = titlePosition.X - titlePosition.Width/2f;
}
}
if(titlePosition.Height == 0)
{
titlePosition.Height = titleSize.Height;
if(this.Alignment == ContentAlignment.BottomRight ||
this.Alignment == ContentAlignment.BottomCenter ||
this.Alignment == ContentAlignment.BottomLeft)
{
titlePosition.Y = titlePosition.Y - titlePosition.Height;
}
else if(this.Alignment == ContentAlignment.MiddleCenter ||
this.Alignment == ContentAlignment.MiddleLeft ||
this.Alignment == ContentAlignment.MiddleRight)
{
titlePosition.Y = titlePosition.Y - titlePosition.Height/2f;
}
}
}
}
//***************************************************************
//** Convert title position to absolute coordinates
//***************************************************************
RectangleF absPosition = new RectangleF(titlePosition.Location, titlePosition.Size);
absPosition = chartGraph.GetAbsoluteRectangle(absPosition);
//***************************************************************
//** Draw title background, border and shadow
//***************************************************************
if(this.BackGroundIsVisible && Common.ProcessModePaint )
{
chartGraph.FillRectangleRel( titlePosition,
BackColor,
BackHatchStyle,
BackImage,
BackImageWrapMode,
BackImageTransparentColor,
BackImageAlignment,
BackGradientStyle,
BackSecondaryColor,
BorderColor,
BorderWidth,
BorderDashStyle,
ShadowColor,
ShadowOffset,
PenAlignment.Inset);
}
else
{
// Adjust text position to be only around the text itself
SizeF titleArea = chartGraph.GetAbsoluteSize(titlePosition.Size);
SizeF titleSize = chartGraph.MeasureString(
"W" + titleText.Replace("\\n", "\n"),
this.Font,
titleArea,
StringFormat.GenericDefault,
this.GetTextOrientation());
// Convert text size to relative coordinates
titleSize = chartGraph.GetRelativeSize(titleSize);
// Adjust position depending on alignment
RectangleF exactTitleRect = new RectangleF(
titlePosition.X,
titlePosition.Y,
titleSize.Width,
titleSize.Height);
if(this.Alignment == ContentAlignment.BottomCenter ||
this.Alignment == ContentAlignment.BottomLeft ||
this.Alignment == ContentAlignment.BottomRight )
{
exactTitleRect.Y = titlePosition.Bottom - exactTitleRect.Height;
}
else if(this.Alignment == ContentAlignment.MiddleCenter ||
this.Alignment == ContentAlignment.MiddleLeft ||
this.Alignment == ContentAlignment.MiddleRight )
{
exactTitleRect.Y = titlePosition.Y +
titlePosition.Height / 2f -
exactTitleRect.Height / 2f;
}
if(this.Alignment == ContentAlignment.BottomRight ||
this.Alignment == ContentAlignment.MiddleRight ||
this.Alignment == ContentAlignment.TopRight )
{
exactTitleRect.X = titlePosition.Right - exactTitleRect.Width;
}
else if(this.Alignment == ContentAlignment.BottomCenter ||
this.Alignment == ContentAlignment.MiddleCenter ||
this.Alignment == ContentAlignment.TopCenter )
{
exactTitleRect.X = titlePosition.X +
titlePosition.Width / 2f -
exactTitleRect.Width / 2f;
}
// NOTE: This approach for text selection can not be used with
// Flash animations because of the bug in Flash viewer. When the
// button shape is placed in the last frame the Alpha value of the
// color is ignored.
// NOTE: Feature tested again with Flash Player 7 and it seems to be
// working fine. Code below is commented to enable selection in flash
// through transparent rectangle.
// Fixes issue #4172.
bool drawRect = true;
// Draw transparent rectangle in the text position
if(drawRect)
{
chartGraph.FillRectangleRel(
exactTitleRect,
Color.FromArgb(0, Color.White),
ChartHatchStyle.None,
String.Empty,
ChartImageWrapMode.Tile,
BackImageTransparentColor,
BackImageAlignment,
GradientStyle.None,
BackSecondaryColor,
Color.Transparent,
0,
BorderDashStyle,
Color.Transparent,
0,
PenAlignment.Inset);
}
// End Selection mode
chartGraph.EndHotRegion( );
}
if( Common.ProcessModePaint)
Common.Chart.CallOnPrePaint(new ChartPaintEventArgs(this, chartGraph, Common, Position));
//***************************************************************
//** Add spacing between text and border
//***************************************************************
if(this.BackGroundIsVisible)
{
absPosition.Width -= this.titleBorderSpacing;
absPosition.Height -= this.titleBorderSpacing;
absPosition.X += this.titleBorderSpacing / 2f;
absPosition.Y += this.titleBorderSpacing / 2f;
}
//***************************************************************
//** Create string format
//***************************************************************
using (StringFormat format = new StringFormat())
{
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
if (this.Alignment == ContentAlignment.BottomCenter ||
this.Alignment == ContentAlignment.BottomLeft ||
this.Alignment == ContentAlignment.BottomRight)
{
format.LineAlignment = StringAlignment.Far;
}
else if (this.Alignment == ContentAlignment.TopCenter ||
this.Alignment == ContentAlignment.TopLeft ||
this.Alignment == ContentAlignment.TopRight)
{
format.LineAlignment = StringAlignment.Near;
}
if (this.Alignment == ContentAlignment.BottomLeft ||
this.Alignment == ContentAlignment.MiddleLeft ||
this.Alignment == ContentAlignment.TopLeft)
{
format.Alignment = StringAlignment.Near;
}
else if (this.Alignment == ContentAlignment.BottomRight ||
this.Alignment == ContentAlignment.MiddleRight ||
this.Alignment == ContentAlignment.TopRight)
{
format.Alignment = StringAlignment.Far;
}
//***************************************************************
//** Draw text shadow for the default style when background is not drawn anf ShadowOffset is not null
//***************************************************************
Color textShadowColor = ChartGraphics.GetGradientColor(this.ForeColor, Color.Black, 0.8);
int textShadowOffset = 1;
TextStyle textStyle = this.TextStyle;
if ((textStyle == TextStyle.Default || textStyle == TextStyle.Shadow) &&
!this.BackGroundIsVisible &&
ShadowOffset != 0)
{
// Draw shadowed text
textStyle = TextStyle.Shadow;
textShadowColor = ShadowColor;
textShadowOffset = ShadowOffset;
}
if (textStyle == TextStyle.Shadow)
{
textShadowColor = (textShadowColor.A != 255) ? textShadowColor : Color.FromArgb(textShadowColor.A / 2, textShadowColor);
}
//***************************************************************
//** Replace new line characters
//***************************************************************
titleText = titleText.Replace("\\n", "\n");
//***************************************************************
//** Define text angle depending on the docking
//***************************************************************
Matrix oldTransform = null;
if (this.IsTextVertical)
{
if (this.GetTextOrientation() == TextOrientation.Rotated270)
{
// IMPORTANT !
// Right to Left flag has to be used because of bug with .net with multi line vertical text. As soon as .net bug is fixed this flag HAS TO be removed. Bug number 1870.
format.FormatFlags |= StringFormatFlags.DirectionVertical | StringFormatFlags.DirectionRightToLeft;
// Save old graphics transformation
oldTransform = chartGraph.Transform.Clone();
// Rotate tile 180 degrees at center
PointF center = PointF.Empty;
center.X = absPosition.X + absPosition.Width / 2F;
center.Y = absPosition.Y + absPosition.Height / 2F;
// Create and set new transformation matrix
Matrix newMatrix = chartGraph.Transform.Clone();
newMatrix.RotateAt(180, center);
chartGraph.Transform = newMatrix;
}
else if (this.GetTextOrientation() == TextOrientation.Rotated90)
{
// IMPORTANT !
// Right to Left flag has to be used because of bug with .net with multi line vertical text. As soon as .net bug is fixed this flag HAS TO be removed. Bug number 1870.
format.FormatFlags |= StringFormatFlags.DirectionVertical | StringFormatFlags.DirectionRightToLeft;
}
}
try
{
chartGraph.IsTextClipped = !Position.Auto;
Title.DrawStringWithStyle(chartGraph, titleText, textStyle, this.Font, absPosition, this.ForeColor, textShadowColor, textShadowOffset, format, this.GetTextOrientation());
}
finally
{
chartGraph.IsTextClipped = false;
}
// Call Paint event
if (Common.ProcessModePaint)
Common.Chart.CallOnPostPaint(new ChartPaintEventArgs(this, chartGraph, Common, Position));
//***************************************************************
//** Restore old transformation
//***************************************************************
if(oldTransform != null)
{
chartGraph.Transform = oldTransform;
}
if( Common.ProcessModeRegions )
{
#if !Microsoft_CONTROL
Common.HotRegionsList.AddHotRegion( titlePosition, this.ToolTip, this.Url, this.MapAreaAttributes, this.PostBackValue, this, ChartElementType.Title, string.Empty );
#else
Common.HotRegionsList.AddHotRegion( titlePosition, this.ToolTip, null, null, null, this, ChartElementType.Title, null );
#endif // !Microsoft_CONTROL
}
}
}
/// <summary>
/// Draws the string with style.
/// </summary>
/// <param name="chartGraph">The chart graph.</param>
/// <param name="titleText">The title text.</param>
/// <param name="textStyle">The text style.</param>
/// <param name="font">The font.</param>
/// <param name="absPosition">The abs position.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="shadowColor">Color of the shadow.</param>
/// <param name="shadowOffset">The shadow offset.</param>
/// <param name="format">The format.</param>
/// <param name="orientation">The orientation.</param>
internal static void DrawStringWithStyle(
ChartGraphics chartGraph,
string titleText,
TextStyle textStyle,
Font font,
RectangleF absPosition,
Color foreColor,
Color shadowColor,
int shadowOffset,
StringFormat format,
TextOrientation orientation
)
{
//***************************************************************
//** Draw title text
//***************************************************************
if (titleText.Length > 0)
{
if (textStyle == TextStyle.Default)
{
using (SolidBrush brush = new SolidBrush(foreColor))
{
chartGraph.DrawString(titleText, font, brush, absPosition, format, orientation);
}
}
else if (textStyle == TextStyle.Frame)
{
using (GraphicsPath graphicsPath = new GraphicsPath())
{
graphicsPath.AddString(
titleText,
font.FontFamily,
(int)font.Style,
font.Size * 1.3f,
absPosition,
format);
graphicsPath.CloseAllFigures();
using (Pen pen = new Pen(foreColor, 1))
{
chartGraph.DrawPath(pen, graphicsPath);
}
}
}
else if (textStyle == TextStyle.Embed)
{
// Draw shadow
RectangleF shadowPosition = new RectangleF(absPosition.Location, absPosition.Size);
shadowPosition.X -= 1;
shadowPosition.Y -= 1;
using (SolidBrush brush = new SolidBrush(shadowColor))
{
chartGraph.DrawString(titleText, font, brush, shadowPosition, format, orientation);
}
// Draw highlighting
shadowPosition.X += 2;
shadowPosition.Y += 2;
Color texthighlightColor = ChartGraphics.GetGradientColor(Color.White, foreColor, 0.3);
using (SolidBrush brush = new SolidBrush(texthighlightColor))
{
chartGraph.DrawString(titleText, font, brush, shadowPosition, format, orientation);
}
using (SolidBrush brush = new SolidBrush(foreColor))
{
// Draw text
chartGraph.DrawString(titleText, font, brush, absPosition, format, orientation);
}
}
else if (textStyle == TextStyle.Emboss)
{
// Draw shadow
RectangleF shadowPosition = new RectangleF(absPosition.Location, absPosition.Size);
shadowPosition.X += 1;
shadowPosition.Y += 1;
using (SolidBrush brush = new SolidBrush(shadowColor))
{
chartGraph.DrawString(titleText, font, brush, shadowPosition, format, orientation);
}
// Draw highlighting
shadowPosition.X -= 2;
shadowPosition.Y -= 2;
Color texthighlightColor = ChartGraphics.GetGradientColor(Color.White, foreColor, 0.3);
using (SolidBrush brush = new SolidBrush(texthighlightColor))
{
chartGraph.DrawString(titleText, font, brush, shadowPosition, format, orientation);
}
// Draw text
using (SolidBrush brush = new SolidBrush(foreColor))
{
chartGraph.DrawString(titleText, font, brush, absPosition, format, orientation);
}
}
else if (textStyle == TextStyle.Shadow)
{
// Draw shadow
RectangleF shadowPosition = new RectangleF(absPosition.Location, absPosition.Size);
shadowPosition.X += shadowOffset;
shadowPosition.Y += shadowOffset;
using (SolidBrush brush = new SolidBrush(shadowColor))
{
chartGraph.DrawString(titleText, font, brush, shadowPosition, format, orientation);
}
// Draw text
using (SolidBrush brush = new SolidBrush(foreColor))
{
chartGraph.DrawString(titleText, font, brush, absPosition, format, orientation);
}
}
}
}
#endregion
#region Position Calculation Methods
/// <summary>
/// Recalculates title position.
/// </summary>
/// <param name="chartGraph">Chart graphics used.</param>
/// <param name="chartAreasRectangle">Area where the title should be docked.</param>
/// <param name="frameTitlePosition">Position of the title in the frame.</param>
/// <param name="elementSpacing">Spacing size in percentage of the area.</param>
internal void CalcTitlePosition(
ChartGraphics chartGraph,
ref RectangleF chartAreasRectangle,
ref RectangleF frameTitlePosition,
float elementSpacing)
{
// Special case for the first title docked to the top when the title frame is used
if(!frameTitlePosition.IsEmpty &&
this.Position.Auto &&
this.Docking == Docking.Top &&
this.DockedToChartArea == Constants.NotSetValue)
{
this.Position.SetPositionNoAuto(
frameTitlePosition.X + elementSpacing,
frameTitlePosition.Y,
frameTitlePosition.Width - 2f * elementSpacing,
frameTitlePosition.Height);
frameTitlePosition = RectangleF.Empty;
return;
}
// Get title size
RectangleF titlePosition = new RectangleF();
SizeF layoutArea = new SizeF(chartAreasRectangle.Width, chartAreasRectangle.Height);
// Switch width and height for vertical text
if (this.IsTextVertical)
{
float tempValue = layoutArea.Width;
layoutArea.Width = layoutArea.Height;
layoutArea.Height = tempValue;
}
// Meausure text size
layoutArea.Width -= 2f * elementSpacing;
layoutArea.Height -= 2f * elementSpacing;
layoutArea = chartGraph.GetAbsoluteSize(layoutArea);
SizeF titleSize = chartGraph.MeasureString(
"W" + this.Text.Replace("\\n", "\n"),
this.Font,
layoutArea,
StringFormat.GenericDefault,
this.GetTextOrientation());
// Increase text size by 4 pixels
if(this.BackGroundIsVisible)
{
titleSize.Width += titleBorderSpacing;
titleSize.Height += titleBorderSpacing;
}
// Switch width and height for vertical text
if (this.IsTextVertical)
{
float tempValue = titleSize.Width;
titleSize.Width = titleSize.Height;
titleSize.Height = tempValue;
}
// Convert text size to relative coordinates
titleSize = chartGraph.GetRelativeSize(titleSize);
titlePosition.Height = titleSize.Height;
titlePosition.Width = titleSize.Width;
if(float.IsNaN(titleSize.Height) || float.IsNaN(titleSize.Width))
{
return;
}
// Calculate title position
if(this.Docking == Docking.Top)
{
titlePosition.Y = chartAreasRectangle.Y + elementSpacing;
titlePosition.X = chartAreasRectangle.X + elementSpacing;
titlePosition.Width = chartAreasRectangle.Right - titlePosition.X - elementSpacing;
if(titlePosition.Width < 0)
{
titlePosition.Width = 0;
}
// Adjust position of the chart area(s)
chartAreasRectangle.Height -= titlePosition.Height + elementSpacing;
chartAreasRectangle.Y = titlePosition.Bottom;
}
else if(this.Docking == Docking.Bottom)
{
titlePosition.Y = chartAreasRectangle.Bottom - titleSize.Height - elementSpacing;
titlePosition.X = chartAreasRectangle.X + elementSpacing;
titlePosition.Width = chartAreasRectangle.Right - titlePosition.X - elementSpacing;
if(titlePosition.Width < 0)
{
titlePosition.Width = 0;
}
// Adjust position of the chart area(s)
chartAreasRectangle.Height -= titlePosition.Height + elementSpacing;
}
if(this.Docking == Docking.Left)
{
titlePosition.X = chartAreasRectangle.X + elementSpacing;
titlePosition.Y = chartAreasRectangle.Y + elementSpacing;
titlePosition.Height = chartAreasRectangle.Bottom - titlePosition.Y - elementSpacing;
if(titlePosition.Height < 0)
{
titlePosition.Height = 0;
}
// Adjust position of the chart area(s)
chartAreasRectangle.Width -= titlePosition.Width + elementSpacing;
chartAreasRectangle.X = titlePosition.Right;
}
if(this.Docking == Docking.Right)
{
titlePosition.X = chartAreasRectangle.Right - titleSize.Width - elementSpacing;
titlePosition.Y = chartAreasRectangle.Y + elementSpacing;
titlePosition.Height = chartAreasRectangle.Bottom - titlePosition.Y - elementSpacing;
if(titlePosition.Height < 0)
{
titlePosition.Height = 0;
}
// Adjust position of the chart area(s)
chartAreasRectangle.Width -= titlePosition.Width + elementSpacing;
}
// Offset calculated docking position
if(this.DockingOffset != 0)
{
if(this.Docking == Docking.Top || this.Docking == Docking.Bottom)
{
titlePosition.Y += this.DockingOffset;
}
else
{
titlePosition.X += this.DockingOffset;
}
}
this.Position.SetPositionNoAuto(titlePosition.X, titlePosition.Y, titlePosition.Width, titlePosition.Height);
}
#endregion
#region IDisposable Members
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_fontCache != null)
{
_fontCache.Dispose();
_fontCache = null;
}
if (_position != null)
{
_position.Dispose();
_position = null;
}
}
}
#endregion
}
/// <summary>
/// The TitleCollection class is a strongly typed collection of Title classes.
/// Indexer of this collection can take the title index (integer) or unique
/// title name (string) as a parameter.
/// </summary>
[
SRDescription("DescriptionAttributeTitles"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class TitleCollection : ChartNamedElementCollection<Title>
{
#region Constructors
/// <summary>
/// TitleCollection constructor.
/// </summary>
/// <param name="parent">Parent chart element.</param>
internal TitleCollection(IChartElement parent)
: base(parent)
{
}
#endregion
#region Methods
/// <summary>
/// Creates a new Title with the specified name and adds it to the collection.
/// </summary>
/// <param name="name">The new chart area name.</param>
/// <returns>New title</returns>
public Title Add(string name)
{
Title title = new Title(name);
this.Add(title);
return title;
}
/// <summary>
/// Recalculates title position in the collection for titles docked outside of chart area.
/// </summary>
/// <param name="chartPicture">Chart picture object.</param>
/// <param name="chartGraph">Chart graphics used.</param>
/// <param name="area">Area the title is docked to.</param>
/// <param name="chartAreasRectangle">Area where the title should be positioned.</param>
/// <param name="elementSpacing">Spacing size in percentage of the area.</param>
internal static void CalcOutsideTitlePosition(
ChartPicture chartPicture,
ChartGraphics chartGraph,
ChartArea area,
ref RectangleF chartAreasRectangle,
float elementSpacing)
{
if(chartPicture != null)
{
// Get elemets spacing
float areaSpacing = Math.Min((chartAreasRectangle.Height/100F) * elementSpacing, (chartAreasRectangle.Width/100F) * elementSpacing);
// Loop through all titles
foreach(Title title in chartPicture.Titles)
{
// Check if title visible
if(!title.IsVisible())
{
continue;
}
// Check if all chart area names are valid
if (title.DockedToChartArea != Constants.NotSetValue && chartPicture.ChartAreas.IndexOf(title.DockedToChartArea)<0)
{
throw (new ArgumentException(SR.ExceptionChartTitleDockedChartAreaIsMissing((string)title.DockedToChartArea)));
}
// Process only titles docked to specified area
if(title.IsDockedInsideChartArea == false &&
title.DockedToChartArea == area.Name &&
title.Position.Auto)
{
// Calculate title position
RectangleF frameRect = RectangleF.Empty;
RectangleF prevChartAreasRectangle = chartAreasRectangle;
title.CalcTitlePosition(chartGraph,
ref chartAreasRectangle,
ref frameRect,
areaSpacing);
// Adjust title position
RectangleF titlePosition = title.Position.ToRectangleF();
if(title.Docking == Docking.Top)
{
titlePosition.Y -= areaSpacing;
if(!area.Position.Auto)
{
titlePosition.Y -= titlePosition.Height;
prevChartAreasRectangle.Y -= titlePosition.Height + areaSpacing;
prevChartAreasRectangle.Height += titlePosition.Height + areaSpacing;
}
}
else if(title.Docking == Docking.Bottom)
{
titlePosition.Y += areaSpacing;
if(!area.Position.Auto)
{
titlePosition.Y = prevChartAreasRectangle.Bottom + areaSpacing;
prevChartAreasRectangle.Height += titlePosition.Height +areaSpacing;
}
}
if(title.Docking == Docking.Left)
{
titlePosition.X -= areaSpacing;
if(!area.Position.Auto)
{
titlePosition.X -= titlePosition.Width;
prevChartAreasRectangle.X -= titlePosition.Width + areaSpacing;
prevChartAreasRectangle.Width += titlePosition.Width + areaSpacing;
}
}
if(title.Docking == Docking.Right)
{
titlePosition.X += areaSpacing;
if(!area.Position.Auto)
{
titlePosition.X = prevChartAreasRectangle.Right + areaSpacing;
prevChartAreasRectangle.Width += titlePosition.Width + areaSpacing;
}
}
// Set title position without changing the 'Auto' flag
title.Position.SetPositionNoAuto(titlePosition.X, titlePosition.Y, titlePosition.Width, titlePosition.Height);
// If custom position is used in the chart area reset the curent adjusted position
if (!area.Position.Auto)
{
chartAreasRectangle = prevChartAreasRectangle;
}
}
}
}
}
/// <summary>
/// Recalculates all titles position inside chart area in the collection.
/// </summary>
/// <param name="chartPicture">Chart picture object.</param>
/// <param name="chartGraph">Chart graphics used.</param>
/// <param name="elementSpacing">Spacing size in percentage of the area.</param>
internal static void CalcInsideTitlePosition(
ChartPicture chartPicture,
ChartGraphics chartGraph,
float elementSpacing)
{
if(chartPicture != null)
{
// Check if all chart area names are valid
foreach(Title title in chartPicture.Titles)
{
// Check if title visible
if(!title.IsVisible())
{
continue;
}
if (title.DockedToChartArea != Constants.NotSetValue)
{
try
{
ChartArea area = chartPicture.ChartAreas[title.DockedToChartArea];
}
catch
{
throw(new ArgumentException( SR.ExceptionChartTitleDockedChartAreaIsMissing( (string)title.DockedToChartArea ) ) );
}
}
}
// Loop through all chart areas
foreach(ChartArea area in chartPicture.ChartAreas)
{
// Check if chart area is visible
if(area.Visible)
{
// Get area position
RectangleF titlePlottingRectangle = area.PlotAreaPosition.ToRectangleF();
// Get elemets spacing
float areaSpacing = Math.Min((titlePlottingRectangle.Height/100F) * elementSpacing, (titlePlottingRectangle.Width/100F) * elementSpacing);
// Loop through all titles
foreach(Title title in chartPicture.Titles)
{
if(title.IsDockedInsideChartArea == true &&
title.DockedToChartArea == area.Name &&
title.Position.Auto)
{
// Calculate title position
RectangleF frameRect = RectangleF.Empty;
title.CalcTitlePosition(chartGraph,
ref titlePlottingRectangle,
ref frameRect,
areaSpacing);
}
}
}
}
}
}
#endregion
#region Event handlers
internal void ChartAreaNameReferenceChanged(object sender, NameReferenceChangedEventArgs e)
{
//If all the chart areas are removed and then the first one is added we don't want to dock the titles
if (e.OldElement == null)
return;
foreach (Title title in this)
if (title.DockedToChartArea == e.OldName)
title.DockedToChartArea = e.NewName;
}
#endregion
}
}
|