|
//-------------------------------------------------------------
// <copyright company=’Microsoft Corporation’>
// Copyright © Microsoft Corporation. All Rights Reserved.
// </copyright>
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: GridTickMarks.cs
//
// Namespace: DataVisualization.Charting
//
// Classes: TickMark, Grid
//
// Purpose: Axis tick marks and grid lines a very similar chart
// elements and most of the functionality is located
// in the Grid class. TickMark class is derived from
// the Grid class and provides tick mark specific
// functionality.
//
// Reviewed: AG - Jul 31, 2002
// AG - Microsoft 14, 2007
//
//===================================================================
#region Used namespaces
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
#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;
using System.Web.UI.DataVisualization.Charting.Utilities;
using System.Web.UI.DataVisualization.Charting.ChartTypes;
#endif
#endregion
#if Microsoft_CONTROL
namespace System.Windows.Forms.DataVisualization.Charting
#else
namespace System.Web.UI.DataVisualization.Charting
#endif
{
#region Tick marks style enumeration
/// <summary>
/// An enumeration of tick mark styles.
/// </summary>
public enum TickMarkStyle
{
/// <summary>
/// Tickmarks are disabled.
/// </summary>
None,
/// <summary>
/// Tickmarks are located outside of the chart area.
/// </summary>
OutsideArea,
/// <summary>
/// Tickmarks are located inside of the chart area.
/// </summary>
InsideArea,
/// <summary>
/// Tickmarks are set across the axis line.
/// </summary>
AcrossAxis
};
#endregion
/// <summary>
/// The TickMark class represents axis tick marks which are drawn next to
/// the axis line. TickMark shares many common properties with the Grid
/// class. This class also contains methods for tick marks drawing.
/// </summary>
[
DefaultProperty("Enabled"),
SRDescription("DescriptionAttributeTickMark_TickMark"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class TickMark : Grid
{
#region Private fields and Constructors
// Tick marks style
private TickMarkStyle _style = TickMarkStyle.OutsideArea;
// Tick marks size
private float _size = 1;
/// <summary>
/// Public default constructor
/// </summary>
public TickMark() : base(null, true)
{
}
/// <summary>
/// Public constructor
/// </summary>
/// <param name="axis">Axis which owns the grid or tick mark.</param>
/// <param name="major">Major axis element.</param>
internal TickMark(Axis axis, bool major) : base(axis, major)
{
}
#endregion
#region Tick marks painting method
/// <summary>
/// Draws and hit test for TickMarks.
/// </summary>
/// <param name="graph">Reference to the Chart Graphics object.</param>
/// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
internal void Paint( ChartGraphics graph, bool backElements )
{
PointF first = PointF.Empty; // The First point of a tick mark
PointF second = PointF.Empty; // The Second point of a tick mark
float axisPosition; // Axis position.
// Tick Marks are disabled
if( !this.enabled )
{
return;
}
// ****************************************************************
// This code creates auto interval for auto tick marks and
// gridlines. If type is not date there are always four tickmarks
// or gridlines between major gridlines and tickmarks. For date
// type interval is calculated using CalcInterval function.
// ****************************************************************
double oldInterval = this.interval;
DateTimeIntervalType oldIntervalType = this.intervalType;
double oldIntervalOffset = this.intervalOffset;
DateTimeIntervalType oldIntervalOffsetType = this.intervalOffsetType;
if( !this.majorGridTick && ( this.interval == 0 || double.IsNaN(this.interval) ) )
{
// Number type
if (this.Axis.majorGrid.GetIntervalType() == DateTimeIntervalType.Auto)
{
this.interval = this.Axis.majorGrid.GetInterval() / Grid.NumberOfIntervals;
}
// Date type
else
{
DateTimeIntervalType localIntervalType = this.Axis.majorGrid.GetIntervalType();
this.interval = Axis.CalcInterval(
this.Axis.ViewMinimum,
this.Axis.ViewMinimum + (this.Axis.ViewMaximum - this.Axis.ViewMinimum) / Grid.NumberOfDateTimeIntervals,
true,
out localIntervalType,
ChartValueType.DateTime );
this.intervalType = localIntervalType;
this.intervalOffsetType = this.Axis.majorGrid.GetIntervalOffsetType();
this.intervalOffset = this.Axis.majorGrid.GetIntervalOffset();
}
}
if( _style == TickMarkStyle.None )
{
return;
}
// Check if custom tick marks should be drawn from custom labels
if (Axis.IsCustomTickMarks())
{
PaintCustom(graph, backElements);
return;
}
// Get first series attached to this axis
Series axisSeries = null;
if (Axis.axisType == AxisName.X || Axis.axisType == AxisName.X2)
{
List<string> seriesArray = Axis.ChartArea.GetXAxesSeries((Axis.axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, Axis.SubAxisName);
if(seriesArray.Count > 0)
{
axisSeries = Axis.Common.DataManager.Series[seriesArray[0]];
if(axisSeries != null && !axisSeries.IsXValueIndexed)
{
axisSeries = null;
}
}
}
// Current position for tick mark is minimum
double current = Axis.ViewMinimum;
// Get offse type
DateTimeIntervalType offsetType = (GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? GetIntervalType() : GetIntervalOffsetType();
// ***********************************
// Check if the AJAX zooming and scrolling mode is enabled.
// ***********************************
// Adjust start position depending on the interval type
if (!Axis.ChartArea.chartAreaIsCurcular ||
Axis.axisType == AxisName.Y ||
Axis.axisType == AxisName.Y2)
{
current = ChartHelper.AlignIntervalStart(current, this.GetInterval(), this.GetIntervalType(), axisSeries, this.majorGridTick);
}
// The Current position is start position, not minimum
if (GetIntervalOffset() != 0 && !double.IsNaN(GetIntervalOffset()) && axisSeries == null)
{
current += ChartHelper.GetIntervalSize(current, GetIntervalOffset(),
offsetType, axisSeries, 0, DateTimeIntervalType.Number, true, false);
}
// Too many tick marks
if ((Axis.ViewMaximum - Axis.ViewMinimum) / ChartHelper.GetIntervalSize(current, this.GetInterval(), this.GetIntervalType(), axisSeries, 0, DateTimeIntervalType.Number, true) > ChartHelper.MaxNumOfGridlines)
{
return;
}
// If Maximum, minimum and interval don’t have
// proper value do not draw tick marks.
if (Axis.ViewMaximum <= Axis.ViewMinimum)
{
return;
}
// Axis scroll bar will increase size of the Outside and Cross style tick marks
float scrollBarSize = 0;
#if Microsoft_CONTROL
if (this.Axis.ScrollBar.IsVisible &&
this.Axis.ScrollBar.IsPositionedInside &&
(this.Axis.IsAxisOnAreaEdge || !this.Axis.IsMarksNextToAxis))
{
scrollBarSize = (float)this.Axis.ScrollBar.GetScrollBarRelativeSize();
}
#endif // Microsoft_CONTROL
// Left tickmarks
if (Axis.AxisPosition == AxisPosition.Left)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.X;
if( _style == TickMarkStyle.InsideArea )
{
first.X = axisPosition;
second.X = axisPosition + _size;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.X = axisPosition - _size - scrollBarSize;
second.X = axisPosition;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.X = axisPosition - _size/2 - scrollBarSize;
second.X = axisPosition + _size/2;
}
}
// Right tickmarks
else if (Axis.AxisPosition == AxisPosition.Right)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.Right;
if( _style == TickMarkStyle.InsideArea )
{
first.X = axisPosition - _size;
second.X = axisPosition;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.X = axisPosition;
second.X = axisPosition + _size + scrollBarSize;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.X = axisPosition - _size/2;
second.X = axisPosition + _size/2 + scrollBarSize;
}
}
// Top tickmarks
else if (Axis.AxisPosition == AxisPosition.Top)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.Y;
if( _style == TickMarkStyle.InsideArea )
{
first.Y = axisPosition;
second.Y = axisPosition + _size;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.Y = axisPosition - _size - scrollBarSize;
second.Y = axisPosition;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.Y = axisPosition - _size/2 - scrollBarSize;
second.Y = axisPosition + _size/2;
}
}
// Bottom tickmarks
else if (Axis.AxisPosition == AxisPosition.Bottom)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.Bottom;
if( _style == TickMarkStyle.InsideArea )
{
first.Y = axisPosition - _size;
second.Y = axisPosition;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.Y = axisPosition;
second.Y = axisPosition + _size + scrollBarSize;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.Y = axisPosition - _size/2;
second.Y = axisPosition + _size/2 + scrollBarSize;
}
}
// Loop for drawing grid tick marks
int counter = 0;
int logStep = 1;
double oldCurrent = current;
double interval = 0;
while (current <= Axis.ViewMaximum)
{
double logInterval = 0;
// Take an interval between gridlines. Interval
// depends on interval type.
if (this.majorGridTick || this.Axis.IsLogarithmic == false)
{
// Take an interval between tickmarks. Interval
// depends on interval type.
interval = ChartHelper.GetIntervalSize(current, this.GetInterval(), this.GetIntervalType(), axisSeries, this.GetIntervalOffset(), offsetType, true);
}
// Code for linear minor gridlines and tickmarks
// if scale is logarithmic.
else
{
// This code is used only for logarithmic scale and minor tick marks or
// gridlines which have linear minor scale in logarithmic major scale.
// This code is used to find minimum value for the interval. For example
// if logarithmic base is 2 and interval is between 4 and 8; current value
// is 5.6; this method will return linearised value for 4. This code works
// like Math.Floor for logarithmic scale.
double logMinimum = this.GetLogMinimum( current, axisSeries );
if( oldCurrent != logMinimum )
{
oldCurrent = logMinimum;
logStep = 1;
}
// Find interval for logarithmic linearised scale
logInterval = Math.Log(1 + this.interval * logStep, Axis.logarithmBase);
current = oldCurrent;
interval = logInterval;
logStep++;
// Reset current position if major interval is passed.
if( this.GetLogMinimum( current + logInterval, axisSeries ) != logMinimum )
{
current += logInterval;
continue;
}
}
// For indexed series do not draw the last tickmark
if (current == Axis.ViewMaximum && axisSeries != null)
{
current += interval;
continue;
}
// Check interval size
if( interval == 0 )
{
throw (new InvalidOperationException(SR.ExceptionTickMarksIntervalIsZero));
}
// Check if we do not exceed max number of elements
if (counter++ > ChartHelper.MaxNumOfGridlines)
{
break;
}
// Do not draw the very first tick mark for circular chart area
if (this.Axis != null && this.Axis.ChartArea != null)
{
if (this.Axis.ChartArea.chartAreaIsCurcular &&
((this.Axis.IsReversed == false && current == Axis.ViewMinimum) ||
(this.Axis.IsReversed == true && current == Axis.ViewMaximum)))
{
current += interval;
continue;
}
}
if (!this.majorGridTick && this.Axis.IsLogarithmic)
{
current += logInterval;
if (current > Axis.ViewMaximum)
{
break;
}
}
if ((decimal)current >= (decimal)Axis.ViewMinimum)
{
// Left tickmarks
if (Axis.AxisPosition == AxisPosition.Left)
{
first.Y = (float)Axis.GetLinearPosition(current);
second.Y = first.Y;
}
// Right tickmarks
else if (Axis.AxisPosition == AxisPosition.Right)
{
first.Y = (float)Axis.GetLinearPosition(current);
second.Y = first.Y;
}
// Top tickmarks
else if (Axis.AxisPosition == AxisPosition.Top)
{
first.X = (float)Axis.GetLinearPosition(current);
second.X = first.X;
}
// Bottom tickmarks
else if (Axis.AxisPosition == AxisPosition.Bottom)
{
first.X = (float)Axis.GetLinearPosition(current);
second.X = first.X;
}
if (Axis.Common.ProcessModeRegions)
{
if (this.Axis.ChartArea.chartAreaIsCurcular)
{
RectangleF rect = new RectangleF( first.X - 0.5f, first.Y - 0.5f, Math.Abs( second.X - first.X ) + 1, Math.Abs( second.Y - first.Y ) + 1 );
using (GraphicsPath path = new GraphicsPath())
{
path.AddRectangle(graph.GetAbsoluteRectangle(rect));
path.Transform(graph.Transform);
this.Axis.Common.HotRegionsList.AddHotRegion(
path,
false,
ChartElementType.TickMarks,
this);
}
}
else if (!this.Axis.ChartArea.Area3DStyle.Enable3D || this.Axis.ChartArea.chartAreaIsCurcular)
{
RectangleF rect = new RectangleF( first.X - 0.5f, first.Y - 0.5f, Math.Abs( second.X - first.X ) + 1, Math.Abs( second.Y - first.Y ) + 1 );
Axis.Common.HotRegionsList.AddHotRegion(rect, this, ChartElementType.TickMarks, true);
}
else
{
if (!Axis.Common.ProcessModePaint) //if ProcessModePaint is true it will be called later
Draw3DTickLine(graph, first, second, backElements);
}
}
if (Axis.Common.ProcessModePaint)
{
// Draw grid line
if (!this.Axis.ChartArea.Area3DStyle.Enable3D || this.Axis.ChartArea.chartAreaIsCurcular)
{
graph.DrawLineRel( borderColor, borderWidth, borderDashStyle, first, second );
}
else
{
Draw3DTickLine(graph, first, second, backElements);
}
}
}
// Move position
if (this.majorGridTick || this.Axis.IsLogarithmic == false)
{
current += interval;
}
}
// Used for auto interval for auto tick marks and
// gridlines
if( !this.majorGridTick )
{
this.interval = oldInterval;
this.intervalType = oldIntervalType;
this.intervalOffset = oldIntervalOffset;
this.intervalOffsetType = oldIntervalOffsetType;
}
}
/// <summary>
/// This method returns linearized logarithmic value
/// which is minimum for range with interval 1.
/// </summary>
/// <param name="current">Current value</param>
/// <param name="axisSeries">First series attached to axis.</param>
/// <returns>Returns Minimum for the range which contains current value</returns>
private double GetLogMinimum( double current, Series axisSeries )
{
double viewMinimum = Axis.ViewMinimum;
DateTimeIntervalType offsetType = (GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? GetIntervalType() : GetIntervalOffsetType();
if( GetIntervalOffset() != 0 && axisSeries == null)
{
viewMinimum += ChartHelper.GetIntervalSize(viewMinimum, GetIntervalOffset(),
offsetType, axisSeries, 0, DateTimeIntervalType.Number, true, false);
}
return viewMinimum + Math.Floor( ( current - viewMinimum ));
}
/// <summary>
/// Draws and hit test for custom TickMarks from the custom labels collection.
/// </summary>
/// <param name="graph">Reference to the Chart Graphics object.</param>
/// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
internal void PaintCustom( ChartGraphics graph, bool backElements )
{
PointF first = PointF.Empty; // The First point of a tick mark
PointF second = PointF.Empty; // The Second point of a tick mark
float axisPosition; // Axis position.
// Axis scroll bar will increase size of the Outside and Cross style tick marks
float scrollBarSize = 0;
#if Microsoft_CONTROL
if (this.Axis.ScrollBar.IsVisible && this.Axis.ScrollBar.IsPositionedInside && this.Axis.IsAxisOnAreaEdge)
{
scrollBarSize = (float)this.Axis.ScrollBar.GetScrollBarRelativeSize();
}
#endif // Microsoft_CONTROL
// Left tickmarks
if (Axis.AxisPosition == AxisPosition.Left)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.X;
if( _style == TickMarkStyle.InsideArea )
{
first.X = axisPosition;
second.X = axisPosition + _size;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.X = axisPosition - _size - scrollBarSize;
second.X = axisPosition;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.X = axisPosition - _size/2 - scrollBarSize;
second.X = axisPosition + _size/2;
}
}
// Right tickmarks
else if (Axis.AxisPosition == AxisPosition.Right)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.Right;
if( _style == TickMarkStyle.InsideArea )
{
first.X = axisPosition - _size;
second.X = axisPosition;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.X = axisPosition;
second.X = axisPosition + _size + scrollBarSize;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.X = axisPosition - _size/2;
second.X = axisPosition + _size/2 + scrollBarSize;
}
}
// Top tickmarks
else if (Axis.AxisPosition == AxisPosition.Top)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.Y;
if( _style == TickMarkStyle.InsideArea )
{
first.Y = axisPosition;
second.Y = axisPosition + _size;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.Y = axisPosition - _size - scrollBarSize;
second.Y = axisPosition;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.Y = axisPosition - _size/2 - scrollBarSize;
second.Y = axisPosition + _size/2;
}
}
// Bottom tickmarks
else if (Axis.AxisPosition == AxisPosition.Bottom)
{
// The tick marks will follow axis or they will
// be always on the border of the chart area.
if (Axis.GetIsMarksNextToAxis())
axisPosition = (float)Axis.GetAxisPosition();
else
axisPosition = Axis.PlotAreaPosition.Bottom;
if( _style == TickMarkStyle.InsideArea )
{
first.Y = axisPosition - _size;
second.Y = axisPosition;
}
else if( _style == TickMarkStyle.OutsideArea )
{
first.Y = axisPosition;
second.Y = axisPosition + _size + scrollBarSize;
}
else if( _style == TickMarkStyle.AcrossAxis )
{
first.Y = axisPosition - _size/2;
second.Y = axisPosition + _size/2 + scrollBarSize;
}
}
// Loop through all custom labels
foreach (CustomLabel label in Axis.CustomLabels)
{
if((label.GridTicks & GridTickTypes.TickMark) == GridTickTypes.TickMark)
{
double position = (label.ToPosition + label.FromPosition) / 2.0;
if (position >= Axis.ViewMinimum && position <= Axis.ViewMaximum)
{
// Left tickmarks
if (Axis.AxisPosition == AxisPosition.Left)
{
first.Y = (float)Axis.GetLinearPosition(position);
second.Y = first.Y;
}
// Right tickmarks
else if (Axis.AxisPosition == AxisPosition.Right)
{
first.Y = (float)Axis.GetLinearPosition(position);
second.Y = first.Y;
}
// Top tickmarks
else if (Axis.AxisPosition == AxisPosition.Top)
{
first.X = (float)Axis.GetLinearPosition(position);
second.X = first.X;
}
// Bottom tickmarks
else if (Axis.AxisPosition == AxisPosition.Bottom)
{
first.X = (float)Axis.GetLinearPosition(position);
second.X = first.X;
}
if (Axis.Common.ProcessModeRegions)
{
if (!this.Axis.ChartArea.Area3DStyle.Enable3D || this.Axis.ChartArea.chartAreaIsCurcular)
{
RectangleF rect = new RectangleF( first.X - 0.5f, first.Y - 0.5f, Math.Abs( second.X - first.X ) + 1, Math.Abs( second.Y - first.Y ) + 1 );
Axis.Common.HotRegionsList.AddHotRegion(rect, this, ChartElementType.TickMarks, true);
}
else
{
Draw3DTickLine(graph, first, second, backElements);
}
}
if (Axis.Common.ProcessModePaint)
{
// Draw grid line
if (!this.Axis.ChartArea.Area3DStyle.Enable3D || this.Axis.ChartArea.chartAreaIsCurcular)
{
graph.DrawLineRel( borderColor, borderWidth, borderDashStyle, first, second );
}
else
{
Draw3DTickLine(graph, first, second, backElements);
}
}
}
}
}
}
/// <summary>
/// Draws tick mark line in 3D space.
/// </summary>
/// <param name="graph">Reference to the Chart Graphics object.</param>
/// <param name="point1">First line point.</param>
/// <param name="point2">Second line point.</param>
/// <param name="backElements">Back elements of the axis should be drawn in 3D scene.</param>
internal void Draw3DTickLine(
ChartGraphics graph,
PointF point1,
PointF point2,
bool backElements
)
{
ChartArea area = this.Axis.ChartArea;
//*****************************************************************
//** Set the tick marks line depth
//*****************************************************************
bool axisOnEdge;
float wallZPosition = Axis.GetMarksZPosition(out axisOnEdge);
//*****************************************************************
//** Check if tick mark should be drawn as back or front element
//*****************************************************************
// Check if axis tick marks are drawn inside plotting area
bool tickMarksOnEdge = axisOnEdge;
if(tickMarksOnEdge &&
this.Axis.MajorTickMark.TickMarkStyle == TickMarkStyle.AcrossAxis ||
this.Axis.MajorTickMark.TickMarkStyle == TickMarkStyle.InsideArea ||
this.Axis.MinorTickMark.TickMarkStyle == TickMarkStyle.AcrossAxis ||
this.Axis.MinorTickMark.TickMarkStyle == TickMarkStyle.InsideArea)
{
tickMarksOnEdge = false;
}
SurfaceNames surfaceName = (wallZPosition == 0f) ? SurfaceNames.Back : SurfaceNames.Front;
if( !area.ShouldDrawOnSurface(surfaceName, backElements, tickMarksOnEdge) )
{
// Skip drawing
return;
}
//*****************************************************************
//** Add area scene wall width to the length of the tick mark
//*****************************************************************
if (Axis.AxisPosition == AxisPosition.Bottom &&
(!Axis.GetIsMarksNextToAxis() || axisOnEdge) &&
area.IsBottomSceneWallVisible())
{
point2.Y += area.areaSceneWallWidth.Height;
}
else if (Axis.AxisPosition == AxisPosition.Left &&
(!Axis.GetIsMarksNextToAxis() || axisOnEdge) &&
area.IsSideSceneWallOnLeft())
{
point1.X -= area.areaSceneWallWidth.Width;
}
else if (Axis.AxisPosition == AxisPosition.Right &&
(!Axis.GetIsMarksNextToAxis() || axisOnEdge) &&
!area.IsSideSceneWallOnLeft())
{
point2.X += area.areaSceneWallWidth.Width;
}
else if (Axis.AxisPosition == AxisPosition.Top &&
(!Axis.GetIsMarksNextToAxis() || axisOnEdge))
{
point1.Y -= area.areaSceneWallWidth.Height;
}
//*****************************************************************
//** Adjust grid line direction for the Top axis
//*****************************************************************
Point3D point3 = null, point4 = null;
if(axisOnEdge && area.areaSceneWallWidth.Width != 0f)
{
if (Axis.AxisPosition == AxisPosition.Top)
{
// Always use plot area position to draw tick mark
float axisPosition = Axis.PlotAreaPosition.Y;
if( _style == TickMarkStyle.InsideArea )
{
point1.Y = axisPosition;
point2.Y = axisPosition + _size;
point3 = new Point3D(point1.X, point1.Y, - area.areaSceneWallWidth.Width);
point4 = new Point3D(point1.X, point1.Y, 0f);
}
else if( _style == TickMarkStyle.OutsideArea )
{
point1.Y = axisPosition;
point2.Y = axisPosition;
point3 = new Point3D(point1.X, axisPosition, wallZPosition);
point4 = new Point3D(point1.X, point1.Y, - _size - area.areaSceneWallWidth.Width);
}
else if( _style == TickMarkStyle.AcrossAxis )
{
point1.Y = axisPosition;
point2.Y = axisPosition + _size/2;
point3 = new Point3D(point1.X, axisPosition, wallZPosition);
point4 = new Point3D(point1.X, point1.Y, - _size/2 - area.areaSceneWallWidth.Width);
}
// Do not show "bent" tick marks on the top surface
if(area.ShouldDrawOnSurface(SurfaceNames.Top, backElements, false))
{
point3 = null;
point4 = null;
}
}
//*****************************************************************
//** Adjust grid line direction for the Left axis
//*****************************************************************
if (Axis.AxisPosition == AxisPosition.Left && !area.IsSideSceneWallOnLeft())
{
// Always use plot area position to draw tick mark
float axisPosition = Axis.PlotAreaPosition.X;
if( _style == TickMarkStyle.InsideArea )
{
point1.X = axisPosition;
point2.X = axisPosition + _size;
point3 = new Point3D(point1.X, point1.Y, - area.areaSceneWallWidth.Width);
point4 = new Point3D(point1.X, point1.Y, 0f);
}
else if( _style == TickMarkStyle.OutsideArea )
{
point1.X = axisPosition;
point2.X = axisPosition;
point3 = new Point3D(axisPosition, point1.Y, wallZPosition);
point4 = new Point3D(axisPosition, point1.Y, - _size - area.areaSceneWallWidth.Width);
}
else if( _style == TickMarkStyle.AcrossAxis )
{
point1.X = axisPosition;
point2.X = axisPosition + _size/2;
point3 = new Point3D(axisPosition, point1.Y, wallZPosition);
point4 = new Point3D(axisPosition, point1.Y, - _size/2 - area.areaSceneWallWidth.Width);
}
// Do not show "bent" tick marks on the left surface
if(area.ShouldDrawOnSurface(SurfaceNames.Left, backElements, false))
{
point3 = null;
point4 = null;
}
}
//*****************************************************************
//** Adjust grid line direction for the Right axis
//*****************************************************************
else if (Axis.AxisPosition == AxisPosition.Right && area.IsSideSceneWallOnLeft())
{
// Always use plot area position to draw tick mark
float axisPosition = Axis.PlotAreaPosition.Right;
if( _style == TickMarkStyle.InsideArea )
{
point1.X = axisPosition - _size;
point2.X = axisPosition;
point3 = new Point3D(point2.X, point2.Y, - area.areaSceneWallWidth.Width);
point4 = new Point3D(point2.X, point2.Y, 0f);
}
else if( _style == TickMarkStyle.OutsideArea )
{
point1.X = axisPosition;
point2.X = axisPosition;
point3 = new Point3D(axisPosition, point1.Y, wallZPosition);
point4 = new Point3D(axisPosition, point1.Y, - _size - area.areaSceneWallWidth.Width);
}
else if( _style == TickMarkStyle.AcrossAxis )
{
point1.X = axisPosition - _size/2;
point2.X = axisPosition;
point3 = new Point3D(axisPosition, point1.Y, wallZPosition);
point4 = new Point3D(axisPosition, point1.Y, - _size/2 - area.areaSceneWallWidth.Width);
}
// Do not show "bent" tick marks on the right surface
if(area.ShouldDrawOnSurface(SurfaceNames.Right, backElements, false))
{
point3 = null;
point4 = null;
}
}
}
//*****************************************************************
//** Draw tick mark (first line)
//*****************************************************************
graph.Draw3DLine(
area.matrix3D,
borderColor, borderWidth, borderDashStyle,
new Point3D(point1.X, point1.Y, wallZPosition),
new Point3D(point2.X, point2.Y, wallZPosition),
Axis.Common,
this,
ChartElementType.TickMarks
);
//*****************************************************************
//** Draw tick mark (second line)
//*****************************************************************
if(point3 != null && point4 != null)
{
graph.Draw3DLine(
area.matrix3D,
borderColor, borderWidth, borderDashStyle,
point3,
point4,
Axis.Common,
this,
ChartElementType.TickMarks
);
}
}
#endregion
#region TickMark properties
/// <summary>
/// Tick mark style.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(TickMarkStyle.OutsideArea),
SRDescription("DescriptionAttributeTickMark_Style"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public TickMarkStyle TickMarkStyle
{
get
{
return _style;
}
set
{
_style = value;
this.Invalidate();
}
}
/// <summary>
/// Tick mark size.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(1.0F),
SRDescription("DescriptionAttributeTickMark_Size"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public float Size
{
get
{
return _size;
}
set
{
_size = value;
this.Invalidate();
}
}
#endregion
}
/// <summary>
/// The Grid class represents axis grid lines which are drawn in the
/// plotting area. It contains grid interval and visual appearance
/// properties. This class also contains methods for grid lines drawing.
/// </summary>
[
DefaultProperty("Enabled"),
SRDescription("DescriptionAttributeGrid_Grid"),
]
#if ASPPERM_35
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
#endif
public class Grid
{
#region Grid fields and Constructors
// Reference to the Axis object
private Axis _axis = null;
// Flags indicate that interval properties where changed
internal bool intervalOffsetChanged = false;
internal bool intervalChanged = false;
internal bool intervalTypeChanged = false;
internal bool intervalOffsetTypeChanged = false;
internal bool enabledChanged = false;
// Data members, which store properties values
internal double intervalOffset = 0;
internal double interval = 0;
internal DateTimeIntervalType intervalType = DateTimeIntervalType.Auto;
internal DateTimeIntervalType intervalOffsetType = DateTimeIntervalType.Auto;
internal Color borderColor = Color.Black;
internal int borderWidth = 1;
internal ChartDashStyle borderDashStyle = ChartDashStyle.Solid;
internal bool enabled = true;
// Indicates that object describes Major Tick Mark or Grid Line
internal bool majorGridTick = false;
// Common number of intervals on the numeric and date-time axis
internal const double NumberOfIntervals = 5.0;
internal const double NumberOfDateTimeIntervals = 4.0;
/// <summary>
/// Public default constructor.
/// </summary>
public Grid()
{
}
/// <summary>
/// Public constructor.
/// </summary>
/// <param name="axis">Axis which owns the grid.</param>
/// <param name="major">Major axis element.</param>
internal Grid(Axis axis, bool major)
{
Initialize(axis, major);
}
/// <summary>
/// Initializes the object.
/// </summary>
/// <param name="axis">Axis which owns the grid.</param>
/// <param name="major">Major axis element.</param>
internal void Initialize(Axis axis, bool major)
{
// Minor elements are disabled by default
if(!this.enabledChanged &&
this._axis == null &&
!major)
{
enabled = false;
}
// If object was first created and populated with data and then added into the axis
// we need to remember changed values.
// NOTE: Fixes issue #6237
if(this._axis == null)
{
TickMark tickMark = this as TickMark;
if(this.interval != 0)
{
if (tickMark != null)
{
if(major)
{
axis.tempMajorTickMarkInterval = this.interval;
}
else
{
axis.tempMinorTickMarkInterval = this.interval;
}
}
else
{
if(major)
{
axis.tempMajorGridInterval = this.interval;
}
else
{
axis.tempMinorGridInterval = this.interval;
}
}
}
if(this.intervalType != DateTimeIntervalType.Auto)
{
if(tickMark != null)
{
if(major)
{
axis.tempTickMarkIntervalType = this.intervalType;
}
}
else
{
if(major)
{
axis.tempGridIntervalType = this.intervalType;
}
}
}
}
// Set axis object reference
this._axis = axis;
// Set a flag if this object represent minor or major tick
this.majorGridTick = major;
// internal double interval = 0;
// internal DateTimeIntervalType intervalType = DateTimeIntervalType.Auto;
}
#endregion
#region Grid helper functions
/// <summary>
/// Gets axes to which this object attached to
/// </summary>
/// <returns>Axis object.</returns>
internal Axis GetAxis()
{
return _axis;
}
/// <summary>
/// Invalidate chart area the axis belong to.
/// </summary>
internal void Invalidate()
{
#if Microsoft_CONTROL
if(this._axis != null)
{
this._axis.Invalidate();
}
#endif
}
#endregion
#region Grid lines drawing functions
/// <summary>
/// Draws grid lines.
/// </summary>
/// <param name="graph">Reference to the Chart Graphics object.</param>
internal void Paint( ChartGraphics graph )
{
// Grids are disabled
if( !this.enabled )
{
return;
}
// Check if custom grid lines should be drawn from custom labels
if(_axis.IsCustomGridLines())
{
PaintCustom( graph );
return;
}
double gridInterval; // Grid interval
double current; // Current position
// Get first series attached to this axis
Series axisSeries = null;
if(_axis.axisType == AxisName.X || _axis.axisType == AxisName.X2)
{
List<string> seriesArray = _axis.ChartArea.GetXAxesSeries((_axis.axisType == AxisName.X) ? AxisType.Primary : AxisType.Secondary, _axis.SubAxisName);
if(seriesArray.Count > 0)
{
axisSeries = _axis.Common.DataManager.Series[seriesArray[0]];
if(axisSeries != null && !axisSeries.IsXValueIndexed)
{
axisSeries = null;
}
}
}
// ****************************************************************
// This code creates auto interval for auto tick marks and
// gridlines. If type is not date there are always four tickmarks
// or gridlines between major gridlines and tickmarks. For date
// type interval is calculated using CalcInterval function.
// ****************************************************************
double oldInterval = this.interval;
DateTimeIntervalType oldIntervalType = this.intervalType;
double oldIntervalOffset = this.intervalOffset;
DateTimeIntervalType oldIntervalOffsetType = this.intervalOffsetType;
if( !this.majorGridTick && ( this.interval == 0 || double.IsNaN(this.interval) ) )
{
// Number type
if( this._axis.majorGrid.GetIntervalType() == DateTimeIntervalType.Auto )
{
this.interval = this._axis.majorGrid.GetInterval() / Grid.NumberOfIntervals;
}
// Date type
else
{
DateTimeIntervalType localIntervalType = this._axis.majorGrid.GetIntervalType();
this.interval = _axis.CalcInterval(
this._axis.minimum,
this._axis.minimum + (this._axis.maximum - this._axis.minimum) / Grid.NumberOfDateTimeIntervals,
true,
out localIntervalType,
ChartValueType.DateTime);
this.intervalType = localIntervalType;
this.intervalOffsetType = this._axis.majorGrid.GetIntervalOffsetType();
this.intervalOffset = this._axis.majorGrid.GetIntervalOffset();
}
}
// Current position for grid lines is minimum
current = _axis.ViewMinimum;
// ***********************************
// Check if the AJAX zooming and scrolling mode is enabled.
// ***********************************
// Adjust start position depending on the interval type
if(!_axis.ChartArea.chartAreaIsCurcular ||
_axis.axisType == AxisName.Y ||
_axis.axisType == AxisName.Y2 )
{
current = ChartHelper.AlignIntervalStart(current, this.GetInterval(), this.GetIntervalType(), axisSeries, this.majorGridTick);
}
// The Current position is start position, not minimum
DateTimeIntervalType offsetType = (GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? GetIntervalType() : GetIntervalOffsetType();
if (GetIntervalOffset() != 0 && !double.IsNaN(GetIntervalOffset()) && axisSeries == null)
{
current += ChartHelper.GetIntervalSize(current, GetIntervalOffset(), offsetType, axisSeries, 0, DateTimeIntervalType.Number, true, false);
}
// Too many gridlines
if( ( _axis.ViewMaximum - _axis.ViewMinimum ) / ChartHelper.GetIntervalSize( current, this.GetInterval(), this.GetIntervalType(), axisSeries, 0, DateTimeIntervalType.Number, true ) > ChartHelper.MaxNumOfGridlines )
return;
// If Maximum, minimum and interval don’t have
// proper value do not draw grid lines.
if( _axis.ViewMaximum <= _axis.ViewMinimum )
return;
if( this.GetInterval() <= 0 )
return;
// Loop for drawing grid lines
int counter = 0;
int logStep = 1;
double oldCurrent = current;
decimal viewMaximum = (decimal)_axis.ViewMaximum;
while( (decimal)current <= viewMaximum )
{
// Take an interval between gridlines. Interval
// depends on interval type.
if( this.majorGridTick || this._axis.IsLogarithmic == false )
{
double autoInterval = this.GetInterval();
gridInterval = ChartHelper.GetIntervalSize(current, autoInterval, this.GetIntervalType(), axisSeries, this.GetIntervalOffset(), offsetType, true);
// Check interval size
if (gridInterval == 0)
{
throw (new InvalidOperationException(SR.ExceptionTickMarksIntervalIsZero));
}
// Draw between min & max values only
if((decimal)current >= (decimal)_axis.ViewMinimum)
{
DrawGrid( graph, current );
}
// Move position
current += gridInterval;
}
// Code for linear minor gridlines and tickmarks
// if scale is logarithmic.
else
{
// This code is used only for logarithmic scale and minor tick marks or
// gridlines which have linear minor scale in logarithmic major scale.
// This code is used to find minimum value for the interval. For example
// if logarithmic base is 2 and interval is between 4 and 8; current value
// is 5.6; this method will return linearised value for 4. This code works
// like Math.Floor for logarithmic scale.
double logMinimum = this.GetLogMinimum( current, axisSeries );
if( oldCurrent != logMinimum )
{
oldCurrent = logMinimum;
logStep = 1;
}
// Find interval for logarithmic linearised scale
double logInterval = Math.Log( 1 + this.interval * logStep, _axis.logarithmBase );
current = oldCurrent;
// Move position
current += logInterval;
logStep++;
// Reset current position if major interval is passed.
if( this.GetLogMinimum( current, axisSeries ) != logMinimum )
{
continue;
}
// Check interval size
if (logInterval == 0)
{
throw (new InvalidOperationException(SR.ExceptionTickMarksIntervalIsZero));
}
// Draw between min & max values only
if( (decimal)current >= (decimal)_axis.ViewMinimum && (decimal)current <= (decimal)_axis.ViewMaximum )
{
DrawGrid( graph, current );
}
}
// Check if we do not exceed max number of elements
if (counter++ > ChartHelper.MaxNumOfGridlines)
{
break;
}
}
// Used for auto interval for auto tick marks and
// gridlines
if( !this.majorGridTick )
{
this.interval = oldInterval;
this.intervalType = oldIntervalType;
this.intervalOffset = oldIntervalOffset;
this.intervalOffsetType = oldIntervalOffsetType;
}
}
/// <summary>
/// This method returns linearized logarithmic value
/// which is minimum for range with interval 1.
/// </summary>
/// <param name="current">Current value</param>
/// <param name="axisSeries">First series attached to axis.</param>
/// <returns>Returns Minimum for the range which contains current value</returns>
private double GetLogMinimum( double current, Series axisSeries )
{
double viewMinimum = _axis.ViewMinimum;
DateTimeIntervalType offsetType = (GetIntervalOffsetType() == DateTimeIntervalType.Auto) ? GetIntervalType() : GetIntervalOffsetType();
if( GetIntervalOffset() != 0 && axisSeries == null)
{
viewMinimum += ChartHelper.GetIntervalSize(viewMinimum, GetIntervalOffset(),
offsetType, axisSeries, 0, DateTimeIntervalType.Number, true, false);
}
return viewMinimum + Math.Floor( ( current - viewMinimum ));
}
/// <summary>
/// Draw the grid line
/// </summary>
/// <param name="graph">Chart Graphics object</param>
/// <param name="current">Current position of the gridline</param>
private void DrawGrid( ChartGraphics graph, double current )
{
// Common elements
CommonElements common = this._axis.Common;
PointF first = PointF.Empty; // The First point of a grid line
PointF second = PointF.Empty; // The Second point of a grid line
RectangleF plotArea; // Plot area position
plotArea = _axis.PlotAreaPosition.ToRectangleF();
// Horizontal gridlines
if( _axis.AxisPosition == AxisPosition.Left || _axis.AxisPosition == AxisPosition.Right )
{
first.X = plotArea.X;
second.X = plotArea.Right;
first.Y = (float)_axis.GetLinearPosition( current );
second.Y = first.Y;
}
// Vertical gridlines
if( _axis.AxisPosition == AxisPosition.Top || _axis.AxisPosition == AxisPosition.Bottom )
{
first.Y = plotArea.Y;
second.Y = plotArea.Bottom;
first.X = (float)_axis.GetLinearPosition( current );
second.X = first.X;
}
if( common.ProcessModeRegions )
{
if( this._axis.ChartArea.Area3DStyle.Enable3D && !this._axis.ChartArea.chartAreaIsCurcular)
{
if(!common.ProcessModePaint) //if ProcessModePaint is true it will be called later
graph.Draw3DGridLine(this._axis.ChartArea, borderColor, borderWidth, borderDashStyle, first, second, ( _axis.AxisPosition == AxisPosition.Left || _axis.AxisPosition == AxisPosition.Right ), common, this );
}
else if(!this._axis.ChartArea.chartAreaIsCurcular)
{
using (GraphicsPath path = new GraphicsPath())
{
if (Math.Abs(first.X - second.X) > Math.Abs(first.Y - second.Y))
{
path.AddLine(first.X, first.Y - 1, second.X, second.Y - 1);
path.AddLine(second.X, second.Y + 1, first.X, first.Y + 1);
path.CloseAllFigures();
}
else
{
path.AddLine(first.X - 1, first.Y, second.X - 1, second.Y);
path.AddLine(second.X + 1, second.Y, first.X + 1, first.Y);
path.CloseAllFigures();
}
common.HotRegionsList.AddHotRegion(path, true, ChartElementType.Gridlines, this);
}
}
}
if( common.ProcessModePaint )
{
// Check if grid lines should be drawn for circular chart area
if(_axis.ChartArea.chartAreaIsCurcular)
{
if(_axis.axisType == AxisName.Y)
{
_axis.DrawCircularLine( this, graph, borderColor, borderWidth, borderDashStyle, first.Y );
}
if(_axis.axisType == AxisName.X)
{
ICircularChartType chartType = this._axis.ChartArea.GetCircularChartType();
if(chartType != null && chartType.RadialGridLinesSupported())
{
_axis.DrawRadialLine( this, graph, borderColor, borderWidth, borderDashStyle, current );
}
}
}
else if(!this._axis.ChartArea.Area3DStyle.Enable3D || this._axis.ChartArea.chartAreaIsCurcular)
{
graph.DrawLineRel( borderColor, borderWidth, borderDashStyle, first, second );
}
else
{
graph.Draw3DGridLine( this._axis.ChartArea, borderColor, borderWidth, borderDashStyle, first, second, ( _axis.AxisPosition == AxisPosition.Left || _axis.AxisPosition == AxisPosition.Right ), _axis.Common, this );
}
}
}
/// <summary>
/// Draws custom grid lines from custom labels.
/// </summary>
/// <param name="graph">Reference to the Chart Graphics object.</param>
internal void PaintCustom( ChartGraphics graph )
{
// Common Elements
CommonElements common = this._axis.Common;
PointF first = PointF.Empty; // The First point of a grid line
PointF second = PointF.Empty; // The Second point of a grid line
RectangleF plotArea = _axis.PlotAreaPosition.ToRectangleF(); // Plot area position
// Loop through all custom labels
foreach(CustomLabel label in _axis.CustomLabels)
{
if((label.GridTicks & GridTickTypes.Gridline) == GridTickTypes.Gridline)
{
double position = (label.ToPosition + label.FromPosition) / 2.0;
if(position >= _axis.ViewMinimum && position <= _axis.ViewMaximum)
{
// Horizontal gridlines
if( _axis.AxisPosition == AxisPosition.Left || _axis.AxisPosition == AxisPosition.Right )
{
first.X = plotArea.X;
second.X = plotArea.Right;
first.Y = (float)_axis.GetLinearPosition( position );
second.Y = first.Y;
}
// Vertical gridlines
if( _axis.AxisPosition == AxisPosition.Top || _axis.AxisPosition == AxisPosition.Bottom )
{
first.Y = plotArea.Y;
second.Y = plotArea.Bottom;
first.X = (float)_axis.GetLinearPosition( position );
second.X = first.X;
}
if( common.ProcessModeRegions )
{
if( !this._axis.ChartArea.Area3DStyle.Enable3D || this._axis.ChartArea.chartAreaIsCurcular )
{
using (GraphicsPath path = new GraphicsPath())
{
if (Math.Abs(first.X - second.X) > Math.Abs(first.Y - second.Y))
{
path.AddLine(first.X, first.Y - 1, second.X, second.Y - 1);
path.AddLine(second.X, second.Y + 1, first.X, first.Y + 1);
path.CloseAllFigures();
}
else
{
path.AddLine(first.X - 1, first.Y, second.X - 1, second.Y);
path.AddLine(second.X + 1, second.Y, first.X + 1, first.Y);
path.CloseAllFigures();
}
common.HotRegionsList.AddHotRegion(path, true, ChartElementType.Gridlines, this);
}
}
else
{
graph.Draw3DGridLine(this._axis.ChartArea, borderColor, borderWidth, borderDashStyle, first, second, ( _axis.AxisPosition == AxisPosition.Left || _axis.AxisPosition == AxisPosition.Right ), common, this );
}
}
if( common.ProcessModePaint )
{
if(!this._axis.ChartArea.Area3DStyle.Enable3D || this._axis.ChartArea.chartAreaIsCurcular)
{
graph.DrawLineRel( borderColor, borderWidth, borderDashStyle, first, second );
}
else
{
graph.Draw3DGridLine(this._axis.ChartArea, borderColor, borderWidth, borderDashStyle, first, second, ( _axis.AxisPosition == AxisPosition.Left || _axis.AxisPosition == AxisPosition.Right ), _axis.Common, this );
}
}
}
}
}
}
#endregion
#region Grid properties
/// <summary>
/// Gets or sets grid or tick mark interval offset.
/// </summary>
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeIntervalOffset3"),
TypeConverter(typeof(AxisElementIntervalValueConverter)),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
]
public double IntervalOffset
{
get
{
return intervalOffset;
}
set
{
intervalOffset = value;
intervalOffsetChanged = true;
this.Invalidate();
}
}
/// <summary>
/// Determines if Enabled property should be serialized.
/// </summary>
/// <returns></returns>
internal bool ShouldSerializeIntervalOffset()
{
if (this.majorGridTick)
{
return !double.IsNaN(intervalOffset);
}
return intervalOffset != 0d;
}
/// <summary>
/// Gets the interval offset.
/// </summary>
/// <returns></returns>
internal double GetIntervalOffset()
{
if(this.majorGridTick && double.IsNaN(intervalOffset) && this._axis != null)
{
return this._axis.IntervalOffset;
}
return intervalOffset;
}
/// <summary>
/// Gets or sets the unit of measurement of grid or tick mark offset.
/// </summary>
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeIntervalOffsetType6"),
RefreshPropertiesAttribute(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public DateTimeIntervalType IntervalOffsetType
{
get
{
return intervalOffsetType;
}
set
{
intervalOffsetType = value;
intervalOffsetTypeChanged = true;
this.Invalidate();
}
}
/// <summary>
/// Determines if IntervalOffsetType property should be serialized.
/// </summary>
/// <returns></returns>
internal bool ShouldSerializeIntervalOffsetType()
{
if (this.majorGridTick)
{
return intervalOffsetType != DateTimeIntervalType.NotSet;
}
return intervalOffsetType != DateTimeIntervalType.Auto;
}
/// <summary>
/// Gets the type of the interval offset.
/// </summary>
/// <returns></returns>
internal DateTimeIntervalType GetIntervalOffsetType()
{
if(this.majorGridTick && intervalOffsetType == DateTimeIntervalType.NotSet && this._axis != null)
{
return this._axis.IntervalOffsetType;
}
return intervalOffsetType;
}
/// <summary>
/// Gets or sets grid or tick mark interval size.
/// </summary>
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeInterval6"),
TypeConverter(typeof(AxisElementIntervalValueConverter)),
RefreshProperties(RefreshProperties.All),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public double Interval
{
get
{
return interval;
}
set
{
// Validation
if (value < 0.0)
throw (new ArgumentException(SR.ExceptionTickMarksIntervalIsNegative, "value"));
interval = value;
intervalChanged = true;
// Enable minor elements
if (!this.majorGridTick && value != 0.0 && !Double.IsNaN(value))
{
// Prevent grids enabling during the serialization
if (this._axis != null)
{
if (this._axis.Chart != null && this._axis.Chart.serializing != false)
{
this.Enabled = true;
}
}
}
// Reset original property value fields
if (this._axis != null)
{
if (this is TickMark)
{
if (this.majorGridTick)
{
this._axis.tempMajorTickMarkInterval = interval;
}
else
{
this._axis.tempMinorTickMarkInterval = interval;
}
}
else
{
if (this.majorGridTick)
{
this._axis.tempMajorGridInterval = interval;
}
else
{
this._axis.tempMinorGridInterval = interval;
}
}
}
this.Invalidate();
}
}
/// <summary>
/// Determines if IntervalOffsetType property should be serialized.
/// </summary>
/// <returns></returns>
internal bool ShouldSerializeInterval()
{
if (this.majorGridTick)
{
return !double.IsNaN(interval);
}
return interval != 0d;
}
/// <summary>
/// Gets the interval.
/// </summary>
/// <returns></returns>
internal double GetInterval()
{
if(this.majorGridTick && double.IsNaN(interval) && this._axis != null)
{
return this._axis.Interval;
}
return interval;
}
/// <summary>
/// Gets or sets the unit of measurement of grid or tick mark interval.
/// </summary>
[
SRCategory("CategoryAttributeData"),
Bindable(true),
SRDescription("DescriptionAttributeIntervalType3"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute),
#endif
RefreshPropertiesAttribute(RefreshProperties.All)
]
public DateTimeIntervalType IntervalType
{
get
{
return intervalType;
}
set
{
intervalType = value;
intervalTypeChanged = true;
// Reset original property value fields
if (this._axis != null)
{
if (this is TickMark)
{
this._axis.tempTickMarkIntervalType = intervalType;
}
else
{
this._axis.tempGridIntervalType = intervalType;
}
}
this.Invalidate();
}
}
/// <summary>
/// Determines if IntervalOffsetType property should be serialized.
/// </summary>
/// <returns></returns>
internal bool ShouldSerializeIntervalType()
{
if (this.majorGridTick)
{
return intervalType != DateTimeIntervalType.NotSet;
}
return intervalType != DateTimeIntervalType.Auto;
}
/// <summary>
/// Gets the type of the interval.
/// </summary>
/// <returns></returns>
internal DateTimeIntervalType GetIntervalType()
{
if(this.majorGridTick && intervalType == DateTimeIntervalType.NotSet && this._axis != null)
{
// Return default value during serialization
return this._axis.IntervalType;
}
return intervalType;
}
/// <summary>
/// Gets or sets grid or tick mark line color.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(typeof(Color), "Black"),
SRDescription("DescriptionAttributeLineColor"),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public Color LineColor
{
get
{
return borderColor;
}
set
{
borderColor = value;
this.Invalidate();
}
}
/// <summary>
/// Gets or sets grid or tick mark line style.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(ChartDashStyle.Solid),
SRDescription("DescriptionAttributeLineDashStyle"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public ChartDashStyle LineDashStyle
{
get
{
return borderDashStyle;
}
set
{
borderDashStyle = value;
this.Invalidate();
}
}
/// <summary>
/// Gets or sets grid or tick mark line width.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
DefaultValue(1),
SRDescription("DescriptionAttributeLineWidth"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public int LineWidth
{
get
{
return borderWidth;
}
set
{
borderWidth = value;
this.Invalidate();
}
}
/// <summary>
/// Gets or sets a flag which indicates if the grid or tick mark is enabled.
/// </summary>
[
SRCategory("CategoryAttributeAppearance"),
Bindable(true),
SRDescription("DescriptionAttributeEnabled5"),
#if !Microsoft_CONTROL
PersistenceMode(PersistenceMode.Attribute)
#endif
]
public bool Enabled
{
get
{
//// Never serialize this property for minor elements
//// "Disabled" property should be serialized instead.
//if(this.axis != null && this.axis.IsSerializing())
//{
// if(!this.majorGridTick)
// {
// // Return default value to prevent serialization
// return true;
// }
//}
return enabled;
}
set
{
enabled = value;
enabledChanged = true;
this.Invalidate();
}
}
/// <summary>
/// Determines if Enabled property should be serialized.
/// </summary>
/// <returns></returns>
internal bool ShouldSerializeEnabled()
{
if (this.majorGridTick)
{
return !this.Enabled;
}
return this.Enabled;
}
/// <summary>
/// Gets or sets the reference to the Axis object
/// </summary>
internal Axis Axis
{
get { return _axis; }
set { _axis = value; }
}
#endregion
}
}
|