Xamarin Public Jenkins (auto-signing) 536cd135cc Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
2017-08-21 15:34:15 +00:00

2047 lines
64 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//-------------------------------------------------------------
// <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 dont 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 dont 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
}
}