|
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: ElementPosition.cs
//
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
//
// Classes: ElementPosition
//
// Purpose: Class is used to store relative position of the chart
// elements like Legend, Title and others. It uses
// relative coordinate system where top left corner is
// 0,0 and bottom right is 100,100.
//
// If Auto property is set to true, all position properties
// (X,Y,Width and Height) are ignored and they automatically
// calculated during chart rendering.
//
// Note that setting any of the position properties will
// automatically set Auto property to false.
//
// Reviewed: AG - August 7, 2002
// AG - Microsoft 5, 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;
#else
using System.Web;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.DataVisualization.Charting.Data;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
/// <summary>
/// ElementPosition is the base class for many chart visual
/// elements like Legend, Title and ChartArea. It provides
/// the position of the chart element in relative coordinates,
/// from (0,0) to (100,100).
/// </summary>
[
SRDescription("DescriptionAttributeElementPosition_ElementPosition"),
DefaultProperty("Data"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class ElementPosition : ChartElement
{
#region Fields
// Private data members, which store properties values
private float _x = 0;
private float _y = 0;
private float _width = 0;
private float _height = 0;
internal bool _auto = true;
// Indicates the auto position of all areas must be reset
internal bool resetAreaAutoPosition = false;
#endregion
#region Constructors
/// <summary>
/// ElementPosition default constructor
/// </summary>
public ElementPosition()
{
}
/// <summary>
/// ElementPosition default constructor
/// </summary>
internal ElementPosition(IChartElement parent)
: base(parent)
{
}
/// <summary>
/// ElementPosition constructor.
/// </summary>
/// <param name="x">X position.</param>
/// <param name="y">Y position.</param>
/// <param name="width">Width.</param>
/// <param name="height">Height.</param>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public ElementPosition(float x, float y, float width, float height)
{
this._auto = false;
this._x = x;
this._y = y;
this._width = width;
this._height = height;
}
#endregion
#region Methods
/// <summary>
/// Asks the user at design-time if he wants to change the Auto position
/// of all areas at the same time.
/// </summary>
/// <param name="autoValue">Value to be set for the Auto property.</param>
private void ResetAllAreasAutoPosition(bool autoValue)
{
if(resetAreaAutoPosition)
{
// Proceed only if at design time
if(Chart != null && Chart.IsDesignMode() && !Chart.serializing && Chart.Site != null)
{
// Check if there is more than one area and Auto position set to the same value
if(Chart.ChartAreas.Count > 1)
{
bool firstAutoValue = Chart.ChartAreas[0].Position.Auto;
bool sameAutoValue = true;
foreach(ChartArea area in Chart.ChartAreas)
{
if(area.Position.Auto != firstAutoValue)
{
sameAutoValue = false;
break;
}
}
// Proceed only all Auto values are the same
if(sameAutoValue)
{
string message = SR.MessageChangingChartAreaPositionProperty;
if (autoValue)
{
message += SR.MessageChangingChartAreaPositionConfirmAutomatic;
}
else
{
message += SR.MessageChangingChartAreaPositionConfirmCustom;
}
IDesignerMessageBoxDialog confirm = Chart.Site.GetService(typeof(IDesignerMessageBoxDialog)) as IDesignerMessageBoxDialog;
if (confirm != null && confirm.ShowQuestion(message))
{
foreach (ChartArea area in Chart.ChartAreas)
{
if (autoValue)
{
this.SetPositionNoAuto(0f, 0f, 0f, 0f);
}
area.Position._auto = autoValue;
}
}
}
}
}
}
}
/// <summary>
/// Convert element position into RectangleF
/// </summary>
/// <returns>RectangleF structure.</returns>
public RectangleF ToRectangleF()
{
return new RectangleF(_x, _y, _width, _height);
}
/// <summary>
/// Initializes ElementPosition from RectangleF
/// </summary>
/// <param name="rect">RectangleF structure.</param>
public void FromRectangleF(RectangleF rect)
{
if (rect == null)
throw new ArgumentNullException("rect");
this._x = rect.X;
this._y = rect.Y;
this._width = rect.Width;
this._height = rect.Height;
this._auto = false;
}
/// <summary>
/// Gets the size of the ElementPosition object.
/// </summary>
/// <returns>The size of the ElementPosition object.</returns>
[Browsable(false)]
[Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
public SizeF Size
{
get { return new SizeF(this._width, this._height); }
}
/// <summary>
/// Gets the bottom position in relative coordinates.
/// </summary>
/// <returns>Bottom position.</returns>
[Browsable(false)]
[Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
public float Bottom
{
get { return this._y + this._height; }
}
/// <summary>
/// Gets the right position in relative coordinates.
/// </summary>
/// <returns>Right position.</returns>
[Browsable(false)]
[Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
public float Right
{
get{ return this._x + this._width; }
}
/// <summary>
/// Determines whether the specified Object is equal to the current Object.
/// </summary>
/// <param name="obj">The Object to compare with the current Object.</param>
/// <returns>true if the specified Object is equal to the current Object; otherwise, false.</returns>
internal override bool EqualsInternal(object obj)
{
ElementPosition pos = obj as ElementPosition;
if(pos != null)
{
if(this._auto == true && this._auto == pos._auto)
{
return true;
}
else if(this._x == pos._x && this._y == pos._y &&
this._width == pos._width && this._height == pos._height)
{
return true;
}
}
return false;
}
/// <summary>
/// Returns a string that represents the element position data.
/// </summary>
/// <returns>Element position data as a string.</returns>
internal override string ToStringInternal()
{
string posString = Constants.AutoValue;
if(!this._auto)
{
posString =
this._x.ToString(System.Globalization.CultureInfo.CurrentCulture)+", "+
this._y.ToString(System.Globalization.CultureInfo.CurrentCulture)+", "+
this._width.ToString(System.Globalization.CultureInfo.CurrentCulture)+", "+
this._height.ToString(System.Globalization.CultureInfo.CurrentCulture);
}
return posString;
}
/// <summary>
/// Set the element position without modifying the "Auto" property
/// </summary>
/// <param name="x">X position.</param>
/// <param name="y">Y position.</param>
/// <param name="width">Width.</param>
/// <param name="height">Height.</param>
internal void SetPositionNoAuto(float x, float y, float width, float height)
{
bool oldValue = this._auto;
this._x = x;
this._y = y;
this._width = width;
this._height = height;
this._auto = oldValue;
}
#endregion
#region Element Position properties
/// <summary>
/// X position of element.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
Bindable(true),
DefaultValue(0.0F),
SRDescription("DescriptionAttributeElementPosition_X"),
NotifyParentPropertyAttribute(true),
RefreshPropertiesAttribute(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "X")]
public float X
{
get
{
return _x;
}
set
{
if(value < 0.0 || value > 100.0)
{
throw(new ArgumentOutOfRangeException("value", SR.ExceptionElementPositionArgumentOutOfRange));
}
_x = value;
Auto = false;
// Adjust width
if( (_x + Width) > 100)
{
Width = 100 - _x;
}
this.Invalidate();
}
}
/// <summary>
/// Y position of element.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
Bindable(true),
DefaultValue(0.0F),
SRDescription("DescriptionAttributeElementPosition_Y"),
NotifyParentPropertyAttribute(true),
RefreshPropertiesAttribute(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Y")]
public float Y
{
get
{
return _y;
}
set
{
if(value < 0.0 || value > 100.0)
{
throw(new ArgumentOutOfRangeException("value", SR.ExceptionElementPositionArgumentOutOfRange));
}
_y = value;
Auto = false;
// Adjust heigth
if( (_y + Height) > 100)
{
Height = 100 - _y;
}
this.Invalidate();
}
}
/// <summary>
/// Width of element.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
Bindable(true),
DefaultValue(0.0F),
SRDescription("DescriptionAttributeElementPosition_Width"),
NotifyParentPropertyAttribute(true),
RefreshPropertiesAttribute(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public float Width
{
get
{
return _width;
}
set
{
if(value < 0.0 || value > 100.0)
{
throw(new ArgumentOutOfRangeException("value", SR.ExceptionElementPositionArgumentOutOfRange));
}
_width = value;
Auto = false;
// Adjust x
if( (_x + Width) > 100)
{
_x = 100 - Width;
}
this.Invalidate();
}
}
/// <summary>
/// Height of element.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
Bindable(true),
DefaultValue(0.0F),
SRDescription("DescriptionAttributeElementPosition_Height"),
NotifyParentPropertyAttribute(true),
RefreshPropertiesAttribute(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public float Height
{
get
{
return _height;
}
set
{
if(value < 0.0 || value > 100.0)
{
throw(new ArgumentOutOfRangeException("value", SR.ExceptionElementPositionArgumentOutOfRange));
}
_height = value;
Auto = false;
// Adjust y
if( (_y + Height) > 100)
{
_y = 100 - Height;
}
this.Invalidate();
}
}
/// <summary>
/// Gets or sets a flag which indicates whether positioning is on.
/// </summary>
[
SRCategory("CategoryAttributeMisc"),
Bindable(true),
DefaultValue(true),
SRDescription("DescriptionAttributeElementPosition_Auto"),
NotifyParentPropertyAttribute(true),
RefreshPropertiesAttribute(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public bool Auto
{
get
{
return _auto;
}
set
{
if(value != _auto)
{
ResetAllAreasAutoPosition(value);
if(value)
{
this._x = 0;
this._y = 0;
this._width = 0;
this._height = 0;
}
_auto = value;
this.Invalidate();
}
}
}
#endregion
}
/// <summary>
/// Used for invoking windows forms MesageBox dialog.
/// </summary>
internal interface IDesignerMessageBoxDialog
{
/// <summary>
/// Shows Yes/No MessageBox.
/// </summary>
/// <param name="message">The message.</param>
/// <returns>
/// true if user confirms with Yes
/// </returns>
bool ShowQuestion(string message);
}
}
|