//-------------------------------------------------------------
//
// Copyright © Microsoft Corporation. All Rights Reserved.
//
//-------------------------------------------------------------
// @owner=alexgor, deliant
//=================================================================
// File: AxisScrollBar.cs
//
// Namespace: System.Web.UI.WebControls[Windows.Forms].Charting
//
// Classes: AxisScrollBar, ScrollBarEventArgs
//
// Purpose: AxisScrollBar class represent axis scroolbar. There
// is a big difference how this UI functionality
// implemented for Windows Forms and ASP.NET. For
// Windows Forms a custom drawn scrollbar control is
// drawn in the chart which reacts to the mouse input and
// changes current axis data scaleView.
//
// ASP.NET version uses client-side scripting and partial
// loading of data segment by segment. Due to the fact
// that scrollbar operates on the client side not all
// functionality of WindowsForms scrollbar is supported.
//
// Reviewed: AG - March 16, 2007
//
//===================================================================
#if WINFORMS_CONTROL
#region Used namespaces
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Windows.Forms.DataVisualization.Charting.Data;
using System.Windows.Forms.DataVisualization.Charting.ChartTypes;
using System.Windows.Forms.DataVisualization.Charting.Utilities;
using System.Windows.Forms.DataVisualization.Charting.Borders3D;
using System.Diagnostics.CodeAnalysis;
#endregion
namespace System.Windows.Forms.DataVisualization.Charting
{
#region Scroll bar enumerations
///
/// An enumeration of scrollbar button types.
///
public enum ScrollBarButtonType
{
///
/// Thumb tracker button.
///
ThumbTracker,
///
/// Scroll by substracting small distance.
///
SmallDecrement,
///
/// Scroll by adding small distance.
///
SmallIncrement,
///
/// Scroll by substracting large distance.
///
LargeDecrement,
///
/// Scroll by adding large distance.
///
LargeIncrement,
///
/// Zoom reset button.
///
ZoomReset
}
///
/// An enumeration of scrollbar button style flags.
///
[Flags]
public enum ScrollBarButtonStyles
{
///
/// No buttons are shown.
///
None = 0,
///
/// Small increment or decrement buttons are shown.
///
SmallScroll = 1,
///
/// Reset zoom buttons are shown.
///
ResetZoom = 2,
///
/// All buttons are shown.
///
All = SmallScroll | ResetZoom
}
#endregion
///
/// AxisScrollBar class represents the axis scrollbar. It is exposed as the
/// ScrollBar property of the Axis class. It contains scrollbar appearance
/// properties and drawing methods.
///
public class AxisScrollBar : IDisposable
{
#region Scroll bar fields
// Reference to the axis data scaleView class
internal Axis axis = null;
// Indicates that scollbra will be drawn
private bool _enabled = true;
// Axis data scaleView scroll bar style
private ScrollBarButtonStyles _scrollBarButtonStyle = ScrollBarButtonStyles.All;
// Axis data scaleView scroll bar size
private double _scrollBarSize = 14.0;
// Index of the pressed butoon in the scroll bar
private int _pressedButtonType = int.MaxValue;
// Axis data scaleView scroll bar buttons color
private Color _buttonColor = Color.Empty;
// Axis data scaleView scroll bar back color
private Color _backColor = Color.Empty;
// Axis data scaleView scroll bar lines color
private Color _lineColor = Color.Empty;
// Current scroll bar drawing colors
private Color _buttonCurrentColor = Color.Empty;
private Color _backCurrentColor = Color.Empty;
private Color _lineCurrentColor = Color.Empty;
// Last mouse click mouse and scaleView position
private PointF _lastClickMousePosition = PointF.Empty;
private double _lastClickViewPosition = double.NaN;
// Timer used to scroll the data while selecting
private System.Windows.Forms.Timer _scrollTimer = new System.Windows.Forms.Timer();
// Scroll size and direction when AutoScroll is set
private MouseEventArgs _mouseArguments = null;
// Position of the scrollbar (true - edge of PlotArea, false - edge of chart area)
private bool _isPositionedInside = true;
#endregion
#region Scroll bar constructors and initialization
///
/// AxisScrollBar constructor.
///
public AxisScrollBar()
{
}
///
/// Axis scroll bar constructor.
///
/// Reference to the axis class.
internal AxisScrollBar(Axis axis)
{
// Save reference to the axis data scaleView
this.axis = axis;
}
///
/// Initialize axis scroll bar class.
///
internal void Initialize()
{
}
#endregion
#region Scroll bar properties
///
/// Gets or sets a flag which indicates whether scroll bar is positioned inside or outside of chart area.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
DefaultValue(true),
SRDescription("DescriptionAttributeAxisScrollBar_PositionInside")
]
public bool IsPositionedInside
{
get
{
return _isPositionedInside;
}
set
{
if(_isPositionedInside != value)
{
_isPositionedInside = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
///
/// Gets or sets a flag which indicates whether the scroll bar is enabled.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
DefaultValue(true),
SRDescription("DescriptionAttributeAxisScrollBar_Enabled")
]
public bool Enabled
{
get
{
return _enabled;
}
set
{
if(_enabled != value)
{
_enabled = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
///
/// Gets the ChartArea that contains this scrollbar.
///
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
]
public ChartArea ChartArea
{
get
{
return this.axis.ChartArea;
}
}
///
/// Gets the Axis that contains this scrollbar.
///
[
Browsable(false),
Bindable(false),
DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden),
SerializationVisibilityAttribute(SerializationVisibility.Hidden)
]
public Axis Axis
{
get
{
return this.axis;
}
}
///
/// Gets or sets the style of the scrollbar button.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
#if WEB_OLAP
DefaultValue(ScrollBarButtonStyle.SmallScroll),
#else
DefaultValue(ScrollBarButtonStyles.All),
#endif
SRDescription("DescriptionAttributeAxisScrollBar_Buttons"),
Editor(Editors.FlagsEnumUITypeEditor.Editor, Editors.FlagsEnumUITypeEditor.Base)
]
public ScrollBarButtonStyles ButtonStyle
{
get
{
return _scrollBarButtonStyle;
}
set
{
if(_scrollBarButtonStyle != value)
{
_scrollBarButtonStyle = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
///
/// Gets or sets the size of the scrollbar.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
DefaultValue(14.0),
SRDescription("DescriptionAttributeAxisScrollBar_Size"),
]
public double Size
{
get
{
return _scrollBarSize;
}
set
{
if(_scrollBarSize != value)
{
// Check values range
if(value < 5.0 || value > 20.0)
{
throw (new ArgumentOutOfRangeException("value", SR.ExceptionScrollBarSizeInvalid));
}
_scrollBarSize = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
///
/// Gets or sets the button color of the scrollbar.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeAxisScrollBar_ButtonColor"),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
]
public Color ButtonColor
{
get
{
return _buttonColor;
}
set
{
if(_buttonColor != value)
{
_buttonColor = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
///
/// Gets or sets the line color of the scrollbar.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeLineColor"),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
]
public Color LineColor
{
get
{
return _lineColor;
}
set
{
if(_lineColor != value)
{
_lineColor = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
///
/// Gets or sets the background color of the scrollbar.
///
[
SRCategory("CategoryAttributeAxisView"),
Bindable(true),
DefaultValue(typeof(Color), ""),
SRDescription("DescriptionAttributeBackColor"),
TypeConverter(typeof(ColorConverter)),
Editor(Editors.ChartColorEditor.Editor, Editors.ChartColorEditor.Base)
]
public Color BackColor
{
get
{
return _backColor;
}
set
{
if(_backColor != value)
{
_backColor = value;
if(axis != null)
{
axis.ChartArea.Invalidate();
}
}
}
}
#endregion
#region Scroll bar public methods
///
/// This method returns true if the scrollbar is visible.
///
[Browsable(false)]
[Utilities.SerializationVisibility(Utilities.SerializationVisibility.Hidden)]
public bool IsVisible
{
get
{
// Check scroll bar enabled flag
if (!this.Enabled)
{
return false;
}
// Do not show scroll bars while printing
if (this.axis == null ||
this.axis.ChartArea == null ||
this.axis.ChartArea.Common == null ||
this.axis.ChartArea.Common.ChartPicture == null ||
this.axis.ChartArea.Common.ChartPicture.isPrinting)
{
return false;
}
#if SUBAXES
// Scrollbar is not supported on the sub axis
if(this.axis.IsSubAxis)
{
return false;
}
#endif // SUBAXES
// Check if data scaleView size in percentage is less than 100%
return (GetDataViewPercentage() < 100.0) ? true : false;
}
}
#endregion
#region Scroll bar painting methods
///
/// Draws axis scroll bar.
///
/// Reference to the Chart Graphics object.
internal void Paint( ChartGraphics graph )
{
// Scroll bar border width
int borderWidth = 1;
// Scroll bar should not be visible
if(!this.IsVisible)
{
return;
}
#if SUBAXES
// Scrollbar not supported on sub axis
if( this.axis != null && this.axis.IsSubAxis)
{
return;
}
#endif //SUBAXES
// Set current scroll bar colors
_buttonCurrentColor = this._buttonColor;
_backCurrentColor = this._backColor;
_lineCurrentColor = this._lineColor;
// Make sure the current colors are not empty
if(_buttonCurrentColor == Color.Empty)
{
_buttonCurrentColor = this.axis.ChartArea.BackColor;
if(_buttonCurrentColor == Color.Empty)
{
_buttonCurrentColor = Color.DarkGray;
}
}
if(_backCurrentColor == Color.Empty)
{
_backCurrentColor = this.axis.ChartArea.BackColor;
if(_backCurrentColor == Color.Empty)
{
_backCurrentColor = Color.LightGray;
}
}
if(_lineCurrentColor == Color.Empty)
{
_lineCurrentColor = this.axis.LineColor;
if(_lineCurrentColor == Color.Empty)
{
_lineCurrentColor = Color.Black;
}
}
// Get scroll bar rectangle
RectangleF scrollBarRect = this.GetScrollBarRect();
// Fill scroll bar background
graph.FillRectangleRel(
scrollBarRect,
_backCurrentColor,
ChartHatchStyle.None,
"",
ChartImageWrapMode.Tile,
Color.Empty,
ChartImageAlignmentStyle.Center,
GradientStyle.None,
Color.Empty,
_lineCurrentColor,
borderWidth,
ChartDashStyle.Solid,
Color.Empty,
0,
PenAlignment.Outset );
// Fill rectangle between to neighbour scroll bars
PaintScrollBarConnectionRect(graph, scrollBarRect, borderWidth);
// Get scroll bar client rectangle
SizeF borderRelativeSize = new SizeF(borderWidth, borderWidth);
borderRelativeSize = graph.GetRelativeSize(borderRelativeSize);
RectangleF scrollBarClientRect = new RectangleF(scrollBarRect.Location, scrollBarRect.Size);
scrollBarClientRect.Inflate(-borderRelativeSize.Width, -borderRelativeSize.Height);
// Draw all button types
foreach (ScrollBarButtonType buttonType in Enum.GetValues(typeof(ScrollBarButtonType)))
{
// Get button rectangle
RectangleF buttonRect = this.GetScrollBarButtonRect(scrollBarClientRect, (ScrollBarButtonType)buttonType);
// Paint button
if(!buttonRect.IsEmpty)
{
PaintScrollBar3DButton(
graph,
buttonRect,
((ScrollBarButtonType)this._pressedButtonType) == (ScrollBarButtonType)buttonType,
(ScrollBarButtonType)buttonType);
}
}
if( this.ChartArea.Common.ProcessModeRegions )
{
SetHotRegionElement( this.ChartArea.Common );
}
}
///
/// Fills a connection rectangle between two scoll bars.
///
/// Chart graphics.
/// Scroll bar position.
/// Border width.
private void PaintScrollBarConnectionRect(
ChartGraphics graph,
RectangleF scrollBarRect,
int borderWidth)
{
// Do not draw anything if scroll bar is vertical
if(this.axis.AxisPosition == AxisPosition.Left ||
this.axis.AxisPosition == AxisPosition.Right)
{
return;
}
// Check if scoll bar is shown on the left/right sides of
// the plotting area and get their sizes in relative coordinates
float leftSize = 0f;
float rightSize = 0f;
foreach(Axis a in this.axis.ChartArea.Axes)
{
if(a.AxisPosition == AxisPosition.Left && a.ScrollBar.IsVisible && a.ScrollBar.IsPositionedInside == this.axis.ScrollBar.IsPositionedInside)
{
leftSize = (float)a.ScrollBar.GetScrollBarRelativeSize();
}
if(a.AxisPosition == AxisPosition.Right && a.ScrollBar.IsVisible && a.ScrollBar.IsPositionedInside == this.axis.ScrollBar.IsPositionedInside)
{
rightSize = (float)a.ScrollBar.GetScrollBarRelativeSize();
}
}
// Prepare generic rectangle coordinates
RectangleF connectorRect = new RectangleF(scrollBarRect.Location, scrollBarRect.Size);
// Prepare coordinates and fill area to the left
if(leftSize > 0f)
{
connectorRect.X = scrollBarRect.X - leftSize;
connectorRect.Width = leftSize;
// Fill background
graph.FillRectangleRel(
connectorRect,
_backCurrentColor,
ChartHatchStyle.None,
"",
ChartImageWrapMode.Tile,
Color.Empty,
ChartImageAlignmentStyle.Center,
GradientStyle.None,
Color.Empty,
_lineCurrentColor,
borderWidth,
ChartDashStyle.Solid,
Color.Empty,
0,
PenAlignment.Outset );
}
// Prepare coordinates and fill area to the right
if(rightSize > 0f)
{
connectorRect.X = scrollBarRect.Right;
connectorRect.Width = rightSize;
// Fill background
graph.FillRectangleRel(
connectorRect,
_backCurrentColor,
ChartHatchStyle.None,
"",
ChartImageWrapMode.Tile,
Color.Empty,
ChartImageAlignmentStyle.Center,
GradientStyle.None,
Color.Empty,
_lineCurrentColor,
borderWidth,
ChartDashStyle.Solid,
Color.Empty,
0,
PenAlignment.Outset );
}
}
///
/// Draws 3D button in the scroll bar
///
/// Chart graphics.
/// Button position.
/// Indicates that button is pressed.
/// Button type to draw.
internal void PaintScrollBar3DButton(
ChartGraphics graph,
RectangleF buttonRect,
bool pressedState,
ScrollBarButtonType buttonType)
{
// Page Up/Down buttons do not require drawing
if(buttonType == ScrollBarButtonType.LargeIncrement || buttonType == ScrollBarButtonType.LargeDecrement)
{
return;
}
// Get 3 levels of colors for button drawing
Color darkerColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, Color.Black, 0.5);
Color darkestColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, Color.Black, 0.8);
Color lighterColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, Color.White, 0.5);
// Fill button rectangle background
graph.FillRectangleRel(
buttonRect,
_buttonCurrentColor,
ChartHatchStyle.None,
"",
ChartImageWrapMode.Tile,
Color.Empty,
ChartImageAlignmentStyle.Center,
GradientStyle.None,
Color.Empty,
darkerColor,
(pressedState) ? 1 : 0,
ChartDashStyle.Solid,
Color.Empty,
0,
PenAlignment.Outset );
// Check if 2 or 1 pixel border will be drawn (if size too small)
bool singlePixelBorder = this.Size <= 12;
// Draw 3D effect around the button when not pressed
if(!pressedState)
{
// Get relative size of 1 pixel
SizeF pixelRelativeSize = new SizeF(1, 1);
pixelRelativeSize = graph.GetRelativeSize(pixelRelativeSize);
// Draw top/left border with button color
graph.DrawLineRel(
(singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.X, buttonRect.Bottom),
new PointF(buttonRect.X, buttonRect.Top));
graph.DrawLineRel(
(singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.Left, buttonRect.Y),
new PointF(buttonRect.Right, buttonRect.Y));
// Draw right/bottom border with the darkest color
graph.DrawLineRel(
(singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.Right, buttonRect.Bottom),
new PointF(buttonRect.Right, buttonRect.Top));
graph.DrawLineRel(
(singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.Left, buttonRect.Bottom),
new PointF(buttonRect.Right, buttonRect.Bottom));
if(!singlePixelBorder)
{
// Draw right/bottom border (offset 1) with the dark color
graph.DrawLineRel(
darkerColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.Right-pixelRelativeSize.Width, buttonRect.Bottom-pixelRelativeSize.Height),
new PointF(buttonRect.Right-pixelRelativeSize.Width, buttonRect.Top+pixelRelativeSize.Height));
graph.DrawLineRel(
darkerColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.Left+pixelRelativeSize.Width, buttonRect.Bottom-pixelRelativeSize.Height),
new PointF(buttonRect.Right-pixelRelativeSize.Width, buttonRect.Bottom-pixelRelativeSize.Height));
// Draw top/left border (offset 1) with lighter color
graph.DrawLineRel(
lighterColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.X+pixelRelativeSize.Width, buttonRect.Bottom-pixelRelativeSize.Height),
new PointF(buttonRect.X+pixelRelativeSize.Width, buttonRect.Top+pixelRelativeSize.Height));
graph.DrawLineRel(
lighterColor, 1, ChartDashStyle.Solid,
new PointF(buttonRect.Left+pixelRelativeSize.Width, buttonRect.Y+pixelRelativeSize.Height),
new PointF(buttonRect.Right-pixelRelativeSize.Width, buttonRect.Y+pixelRelativeSize.Height));
}
}
// Check axis orientation
bool verticalAxis = (this.axis.AxisPosition == AxisPosition.Left ||
this.axis.AxisPosition == AxisPosition.Right) ? true : false;
// Set graphics transformation for button pressed mode
float pressedShifting = (singlePixelBorder) ? 0.5f : 1f;
if(pressedState)
{
graph.TranslateTransform(pressedShifting, pressedShifting);
}
// Draw button image
RectangleF buttonAbsRect = graph.GetAbsoluteRectangle(buttonRect);
float imageOffset = (singlePixelBorder) ? 2 : 3;
switch(buttonType)
{
case(ScrollBarButtonType.SmallDecrement):
{
// Calculate triangal points position
PointF[] points = new PointF[3];
if(verticalAxis)
{
points[0].X = buttonAbsRect.X + imageOffset;
points[0].Y = buttonAbsRect.Y + (imageOffset + 1f);
points[1].X = buttonAbsRect.X + buttonAbsRect.Width/2f;
points[1].Y = buttonAbsRect.Bottom - imageOffset;
points[2].X = buttonAbsRect.Right - imageOffset;
points[2].Y = buttonAbsRect.Y + (imageOffset + 1f);
}
else
{
points[0].X = buttonAbsRect.X + imageOffset;
points[0].Y = buttonAbsRect.Y + buttonAbsRect.Height/2f;
points[1].X = buttonAbsRect.Right - (imageOffset + 1f);
points[1].Y = buttonAbsRect.Y + imageOffset;
points[2].X = buttonAbsRect.Right - (imageOffset + 1f);
points[2].Y = buttonAbsRect.Bottom - imageOffset;
}
using (Brush brush = new SolidBrush(this._lineCurrentColor))
{
graph.FillPolygon(brush, points);
}
break;
}
case(ScrollBarButtonType.SmallIncrement):
{
// Calculate triangal points position
PointF[] points = new PointF[3];
if(verticalAxis)
{
points[0].X = buttonAbsRect.X + imageOffset;
points[0].Y = buttonAbsRect.Bottom - (imageOffset + 1f);
points[1].X = buttonAbsRect.X + buttonAbsRect.Width/2f;
points[1].Y = buttonAbsRect.Y + imageOffset;
points[2].X = buttonAbsRect.Right - imageOffset;
points[2].Y = buttonAbsRect.Bottom - (imageOffset + 1f);
}
else
{
points[0].X = buttonAbsRect.Right - imageOffset;
points[0].Y = buttonAbsRect.Y + buttonAbsRect.Height/2f;
points[1].X = buttonAbsRect.X + (imageOffset + 1f);
points[1].Y = buttonAbsRect.Y + imageOffset;
points[2].X = buttonAbsRect.X + (imageOffset + 1f);
points[2].Y = buttonAbsRect.Bottom - imageOffset;
}
using (Brush brush = new SolidBrush(this._lineCurrentColor))
{
graph.FillPolygon(brush, points);
}
break;
}
case(ScrollBarButtonType.ZoomReset):
{
// Draw circule with a minus sign
using (Pen pen = new Pen(this._lineCurrentColor, 1))
{
graph.DrawEllipse(pen, buttonAbsRect.X + imageOffset - 0.5f, buttonAbsRect.Y + imageOffset - 0.5f, buttonAbsRect.Width - 2f * imageOffset, buttonAbsRect.Height - 2f * imageOffset);
graph.DrawLine(pen, buttonAbsRect.X + imageOffset + 1.5f, buttonAbsRect.Y + buttonAbsRect.Height / 2f - 0.5f, buttonAbsRect.Right - imageOffset - 2.5f, buttonAbsRect.Y + buttonAbsRect.Height / 2f - 0.5f);
}
break;
}
}
// Reset graphics transformation for button pressed mode
if(pressedState)
{
graph.TranslateTransform(-pressedShifting, -pressedShifting);
}
}
#endregion
#region Mouse events handling for the Scroll Bar
///
/// Mouse down event handler.
///
internal void ScrollBar_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
// Process left mouse button
if(e.Button == MouseButtons.Left && this.IsVisible)
{
// Remember position where mouse was clicked
_lastClickMousePosition = new PointF(e.X, e.Y);
_lastClickViewPosition = this.axis.ScaleView.Position;
// Check if button was pressed inside the scroll bar
ScrollBarButtonType buttonType;
if(GetElementByPixelPosition(e.X, e.Y, out buttonType))
{
this.ButtonClicked(buttonType, e.X, e.Y);
}
}
}
///
/// Mouse up event handler.
///
internal void ScrollBar_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
// If scroll bar button was pressed
if(this._pressedButtonType != int.MaxValue)
{
// Check if button was unpressed inside the reset zoom button
ScrollBarButtonType buttonType;
if(GetElementByPixelPosition(e.X, e.Y, out buttonType))
{
if(buttonType == ScrollBarButtonType.ZoomReset)
{
this.ButtonClicked(buttonType, e.X, e.Y);
}
}
// Stop scrolling timer
_scrollTimer.Stop();
_mouseArguments = null;
// Clear pressed button state
this._pressedButtonType = int.MaxValue;
// Invalidate chart
this.axis.Invalidate();
}
}
///
/// Mouse move event handler.
///
internal void ScrollBar_MouseMove(System.Windows.Forms.MouseEventArgs e, ref bool handled)
{
// If scroll bar button was pressed
if(this._pressedButtonType != int.MaxValue)
{
// Mouse move event should not be handled by any other chart elements
handled = true;
// Check if tracking buton was pressed
if((ScrollBarButtonType)this._pressedButtonType == ScrollBarButtonType.ThumbTracker)
{
// Proceed if last clicked position is known
if(!_lastClickMousePosition.IsEmpty)
{
this.ButtonClicked(ScrollBarButtonType.ThumbTracker, e.X, e.Y);
}
}
// Non tracking scroll bar button
else
{
// Check if mouse cursor is still in the pressed button's rectangle
bool inPressedButton = false;
ScrollBarButtonType buttonType;
if(GetElementByPixelPosition(e.X, e.Y, out buttonType))
{
if(buttonType == (ScrollBarButtonType)this._pressedButtonType)
{
inPressedButton = true;
}
}
// Clear pressed button state
if(!inPressedButton)
{
// Stop scrolling timer
_scrollTimer.Stop();
_mouseArguments = null;
// Clear pressed button state
this._pressedButtonType = int.MaxValue;
// Invalidate chart
this.axis.Invalidate();
}
}
}
}
///
/// Scroll bar button was clicked by the user.
///
/// Button type.
/// X click position in pixels.
/// Y click position in pixels.
[SuppressMessage("Microsoft.Mobility", "CA1601:DoNotUseTimersThatPreventPowerStateChanges", Justification = "The timer is used for simulating scrolling behavior")]
private void ButtonClicked(ScrollBarButtonType buttonType, int x, int y)
{
// Call zoom reset on the second pass when button is released
if(buttonType != ScrollBarButtonType.ZoomReset ||
(ScrollBarButtonType)this._pressedButtonType == buttonType)
{
//**************************************************
//** Fire scroll bar button clicked event
//**************************************************
ScrollBarEventArgs eventArg = new ScrollBarEventArgs(this.axis, x, y, buttonType);
this.axis.ScaleView.GetChartObject().OnAxisScrollBarClicked(eventArg);
// Check if event was handled by user
if(eventArg.IsHandled)
{
// Save type of the button pressed
this._pressedButtonType = (int)buttonType;
return;
}
//**************************************************
//** Scroll data scaleView
//**************************************************
switch(buttonType)
{
case(ScrollBarButtonType.SmallIncrement):
this.axis.ScaleView.Scroll(ScrollType.SmallIncrement, true);
break;
case(ScrollBarButtonType.SmallDecrement):
this.axis.ScaleView.Scroll(ScrollType.SmallDecrement, true);
break;
case(ScrollBarButtonType.LargeIncrement):
this.axis.ScaleView.Scroll(ScrollType.LargeIncrement, true);
break;
case(ScrollBarButtonType.LargeDecrement):
this.axis.ScaleView.Scroll(ScrollType.LargeDecrement, true);
break;
case(ScrollBarButtonType.ZoomReset):
this.axis.ScaleView.ZoomReset(1, true);
break;
case(ScrollBarButtonType.ThumbTracker):
{
if(!_lastClickMousePosition.IsEmpty &&
!double.IsNaN(this._lastClickViewPosition) &&
(_lastClickMousePosition.X != x || _lastClickMousePosition.Y != y))
{
// Get scroll bar client rectangle
RectangleF scrollBarRect = this.GetScrollBarRect();
SizeF borderRelativeSize = new SizeF(1, 1);
borderRelativeSize = this.GetRelativeSize(borderRelativeSize);
RectangleF scrollBarClientRect = new RectangleF(scrollBarRect.Location, scrollBarRect.Size);
scrollBarClientRect.Inflate(-borderRelativeSize.Width, -borderRelativeSize.Height);
// Check axis orientation
bool verticalAxis = (this.axis.AxisPosition == AxisPosition.Left ||
this.axis.AxisPosition == AxisPosition.Right) ? true : false;
// Get button relative size
SizeF buttonSize = new SizeF(scrollBarClientRect.Width, scrollBarClientRect.Height);
buttonSize = this.GetAbsoluteSize(buttonSize);
if(verticalAxis)
{
buttonSize.Height = buttonSize.Width;
}
else
{
buttonSize.Width = buttonSize.Height;
}
buttonSize = this.GetRelativeSize(buttonSize);
// Calculate the distance in percentages the mouse was moved
// from it's original (clicked) position.
float distance = 0f;
double trackingAreaSize = 0f;
if(verticalAxis)
{
// Calculate max tracking size
trackingAreaSize = scrollBarClientRect.Height - this.GetButtonsNumberAll() * buttonSize.Height;
distance = _lastClickMousePosition.Y - y;
// Convert to relative coordinates
distance = distance * 100F / ((float)(this.axis.Common.Height - 1));
}
else
{
trackingAreaSize = scrollBarClientRect.Width - this.GetButtonsNumberAll() * buttonSize.Width;
distance = x - _lastClickMousePosition.X;
// Convert to relative coordinates
distance = distance * 100F / ((float)(this.axis.Common.Width - 1));
}
// Convert to percentages from total tracking area
distance = (float)(distance / (trackingAreaSize / 100f));
// Get axis scale size without margins
double axisScaleSize = Math.Abs(
(this.axis.maximum - this.axis.marginView) -
(this.axis.minimum + this.axis.marginView));
// Calculate the same percentage using axis scale
distance = (float)(distance * (axisScaleSize/100f));
// Round the distance to the minimum scroll line size
if(!double.IsNaN(axis.ScaleView.SmallScrollMinSize) && axis.ScaleView.SmallScrollMinSize != 0.0)
{
double minSize = ChartHelper.GetIntervalSize(0, axis.ScaleView.SmallScrollMinSize, axis.ScaleView.SmallScrollMinSizeType);
double rounder = (Math.Round(distance / minSize));
distance = (float)(rounder * minSize);
}
// Scroll scaleView into the new position
this.axis.ScaleView.Scroll(this._lastClickViewPosition + ((this.axis.IsReversed) ? -1 : 1) * distance, true);
}
break;
}
}
//************************************************************
//** Initialize timer for repeating scroll (if mouse is hold)
//************************************************************
// Reset mouse arguments
_mouseArguments = null;
if(buttonType != ScrollBarButtonType.ThumbTracker && buttonType != ScrollBarButtonType.ZoomReset)
{
// Remember last mouse position
_mouseArguments = new MouseEventArgs(MouseButtons.Left, 1, x, y, 0);
// Enable timer
if(!_scrollTimer.Enabled)
{
_scrollTimer.Tick += new EventHandler(ScrollingTimerEventProcessor);
_scrollTimer.Interval = 400;
_scrollTimer.Start();
}
}
}
//************************************************************
//** Invalidate chart
//************************************************************
// Save type of the button pressed
this._pressedButtonType = (int)buttonType;
// Invalidate
this.axis.Invalidate();
}
///
/// This is the method to run when the timer is raised.
/// Used to repetedly scroll data scaleView while mouse button is pressed.
///
/// Object.
/// Event arguments.
[SuppressMessage("Microsoft.Mobility", "CA1601:DoNotUseTimersThatPreventPowerStateChanges", Justification = "The timer is used for simulating scrolling behavior")]
private void ScrollingTimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
// Simulate mouse move events
if(_mouseArguments != null)
{
_scrollTimer.Interval = 200;
this.ScrollBar_MouseDown(null, _mouseArguments);
}
}
///
/// This method fills hot region collection with scroll bar elements.
/// Possible elements are all scroll bar buttons and scroll bar background
/// which performs PgUp/PgDn action.
///
/// Common Elements
private void SetHotRegionElement( CommonElements common )
{
// Check if mouse button was clicked in the scroll bar
RectangleF scrollBarRect = this.GetScrollBarRect();
// Get scroll bar client rectangle
SizeF borderRelativeSize = new SizeF(1, 1);
borderRelativeSize = this.GetRelativeSize(borderRelativeSize);
RectangleF scrollBarClientRect = new RectangleF(scrollBarRect.Location, scrollBarRect.Size);
scrollBarClientRect.Inflate(-borderRelativeSize.Width, -borderRelativeSize.Height);
ChartElementType buttonType = ChartElementType.Nothing;
// Fill collection with scroll buttons rectangles.
foreach(object type in Enum.GetValues(typeof(ScrollBarButtonType)))
{
// Convert Scroll Bar Button type enum to Chart Element AxisName enum.
switch( (ScrollBarButtonType)type )
{
case ScrollBarButtonType.SmallIncrement:
buttonType = ChartElementType.ScrollBarSmallIncrement;
break;
case ScrollBarButtonType.LargeIncrement:
buttonType = ChartElementType.ScrollBarLargeIncrement;
break;
case ScrollBarButtonType.LargeDecrement:
buttonType = ChartElementType.ScrollBarLargeDecrement;
break;
case ScrollBarButtonType.ThumbTracker:
buttonType = ChartElementType.ScrollBarThumbTracker;
break;
case ScrollBarButtonType.SmallDecrement:
buttonType = ChartElementType.ScrollBarSmallDecrement;
break;
case ScrollBarButtonType.ZoomReset:
buttonType = ChartElementType.ScrollBarZoomReset;
break;
}
// Get button rectangle
RectangleF buttonRect = this.GetScrollBarButtonRect(scrollBarClientRect, (ScrollBarButtonType)type);
common.HotRegionsList.AddHotRegion( buttonRect, this, buttonType, true );
}
}
///
/// Detects the scroll bar elements by pixel position.
/// Possible elements are all scroll bar buttons and scroll bar background
/// which performs PgUp/PgDn action.
///
/// X coordinate in pixels.
/// Y coordinate in pixels.
/// Return button type.
/// True if position is in the scroll bar.
private bool GetElementByPixelPosition(float x, float y, out ScrollBarButtonType buttonType)
{
// Set initial values
buttonType = ScrollBarButtonType.ThumbTracker;
// Convert mouse click coordinates to relative
PointF position = new PointF(x, y);
position.X = x * 100F / ((float)(this.axis.Common.Width - 1));
position.Y = y * 100F / ((float)(this.axis.Common.Height - 1));
// Check if mouse button was clicked in the scroll bar
RectangleF scrollBarRect = this.GetScrollBarRect();
if(scrollBarRect.Contains(position))
{
// Get scroll bar client rectangle
SizeF borderRelativeSize = new SizeF(1, 1);
borderRelativeSize = this.GetRelativeSize(borderRelativeSize);
RectangleF scrollBarClientRect = new RectangleF(scrollBarRect.Location, scrollBarRect.Size);
scrollBarClientRect.Inflate(-borderRelativeSize.Width, -borderRelativeSize.Height);
//******************************************************************
//** Check if scroll bar button was clicked
//******************************************************************
foreach(object type in Enum.GetValues(typeof(ScrollBarButtonType)))
{
// Get button rectangle
RectangleF buttonRect = this.GetScrollBarButtonRect(scrollBarClientRect, (ScrollBarButtonType)type);
// Check if position is inside the button
if(buttonRect.Contains(position))
{
buttonType = (ScrollBarButtonType)type;
return true;
}
}
}
// Pixel position is outside scroll bar area
return false;
}
#endregion
#region Scroll bar helper methods
///
/// Returns scroll bar button rectangle position in relative coordinates.
///
/// Scroll bar client rectangle.
/// Scroll bar button type.
/// Scroll bar position.
internal RectangleF GetScrollBarButtonRect(RectangleF scrollBarClientRect, ScrollBarButtonType buttonType)
{
// Initialize button rectangle
RectangleF buttonRect = new RectangleF(scrollBarClientRect.Location, scrollBarClientRect.Size);
// Check axis orientation
bool verticalAxis = (this.axis.AxisPosition == AxisPosition.Left ||
this.axis.AxisPosition == AxisPosition.Right) ? true : false;
// Get relative size of 1 pixel
SizeF pixelRelativeSize = new SizeF(1, 1);
pixelRelativeSize = this.GetRelativeSize(pixelRelativeSize);
// Get button relative size
SizeF buttonSize = new SizeF(scrollBarClientRect.Width, scrollBarClientRect.Height);
buttonSize = this.GetAbsoluteSize(buttonSize);
if(verticalAxis)
{
buttonSize.Height = buttonSize.Width;
}
else
{
buttonSize.Width = buttonSize.Height;
}
buttonSize = this.GetRelativeSize(buttonSize);
// Set common position sizes
buttonRect.Width = buttonSize.Width;
buttonRect.Height = buttonSize.Height;
if(verticalAxis)
{
buttonRect.X = scrollBarClientRect.X;
}
else
{
buttonRect.Y = scrollBarClientRect.Y;
}
// Calculate scroll bar buttons position
switch(buttonType)
{
case(ScrollBarButtonType.LargeDecrement):
case(ScrollBarButtonType.LargeIncrement):
case(ScrollBarButtonType.ThumbTracker):
{
// Get tracker button position and size first
if(verticalAxis)
{
// Calculate tracker size
double trackingAreaSize = scrollBarClientRect.Height - this.GetButtonsNumberAll() * buttonSize.Height;
buttonRect.Height = (float)(this.GetDataViewPercentage() * (trackingAreaSize / 100f));
// Check if tracker size is too small
if(buttonRect.Height < pixelRelativeSize.Height * 6f)
{
buttonRect.Height = pixelRelativeSize.Height * 6f;
}
// Calculate tracker position
if(!this.axis.IsReversed)
{
buttonRect.Y = scrollBarClientRect.Bottom - this.GetButtonsNumberBottom()*buttonSize.Height - buttonRect.Height;
buttonRect.Y -= (float)(this.GetDataViewPositionPercentage() * (trackingAreaSize / 100f));
if(buttonRect.Y < scrollBarClientRect.Y + this.GetButtonsNumberTop()*buttonSize.Height + ((this.GetButtonsNumberTop() == 0) ? 0 : pixelRelativeSize.Height))
{
buttonRect.Y = scrollBarClientRect.Y + this.GetButtonsNumberTop()*buttonSize.Height + ((this.GetButtonsNumberTop() == 0) ? 0 : pixelRelativeSize.Height);
}
}
else
{
buttonRect.Y = scrollBarClientRect.Top + this.GetButtonsNumberTop()*buttonSize.Height;
buttonRect.Y += (float)(this.GetDataViewPositionPercentage() * (trackingAreaSize / 100f));
if((buttonRect.Y + buttonRect.Height) > scrollBarClientRect.Bottom - this.GetButtonsNumberBottom()*buttonSize.Height - ((this.GetButtonsNumberBottom() == 0) ? 0 : pixelRelativeSize.Height))
{
buttonRect.Y = (scrollBarClientRect.Bottom - this.GetButtonsNumberBottom()*buttonSize.Height) - buttonRect.Height - ((this.GetButtonsNumberBottom() == 0) ? 0 : pixelRelativeSize.Height);
}
}
}
else
{
// Calculate tracker size
double trackingAreaSize = scrollBarClientRect.Width - this.GetButtonsNumberAll() * buttonSize.Width;
buttonRect.Width = (float)(this.GetDataViewPercentage() * (trackingAreaSize / 100f));
// Check if tracker size is too small
if(buttonRect.Width < pixelRelativeSize.Width * 6f)
{
buttonRect.Width = pixelRelativeSize.Width * 6f;
}
// Calculate tracker position
if(!this.axis.IsReversed)
{
buttonRect.X = scrollBarClientRect.X + this.GetButtonsNumberTop() * buttonSize.Width;
buttonRect.X += (float)(this.GetDataViewPositionPercentage() * (trackingAreaSize / 100f));
if((buttonRect.X + buttonRect.Width) > scrollBarClientRect.Right - this.GetButtonsNumberBottom()*buttonSize.Width - ((this.GetButtonsNumberBottom() == 0) ? 0 : pixelRelativeSize.Width))
{
buttonRect.X = (scrollBarClientRect.Right - buttonRect.Width) - this.GetButtonsNumberBottom()*buttonSize.Width - ((this.GetButtonsNumberBottom() == 0) ? 0 : pixelRelativeSize.Width);
}
}
else
{
buttonRect.X = scrollBarClientRect.Right - this.GetButtonsNumberBottom()*buttonSize.Width - ((this.GetButtonsNumberBottom() == 0) ? 0 : pixelRelativeSize.Width) - buttonRect.Width;
buttonRect.X -= (float)(this.GetDataViewPositionPercentage() * (trackingAreaSize / 100f));
if(buttonRect.X < scrollBarClientRect.X + this.GetButtonsNumberTop()*buttonSize.Width)
{
buttonRect.X = scrollBarClientRect.X + this.GetButtonsNumberTop()*buttonSize.Width;
}
}
}
// Get page up region rectangle depending on the tracker position
if(buttonType == ScrollBarButtonType.LargeDecrement)
{
if(verticalAxis)
{
buttonRect.Y = buttonRect.Bottom + pixelRelativeSize.Height;
buttonRect.Height = (scrollBarClientRect.Bottom - this.GetButtonsNumberBottom()*buttonSize.Height - pixelRelativeSize.Height) - buttonRect.Y;
}
else
{
float x = scrollBarClientRect.X +
this.GetButtonsNumberTop() * buttonSize.Width +
pixelRelativeSize.Width;
buttonRect.Width = buttonRect.X - x;
buttonRect.X = x;
}
}
// Get page down region rectangle depending on the tracker position
else if(buttonType == ScrollBarButtonType.LargeIncrement)
{
if(verticalAxis)
{
float y = scrollBarClientRect.Y +
this.GetButtonsNumberTop() * buttonSize.Height +
pixelRelativeSize.Height;
buttonRect.Height = buttonRect.Y - y;
buttonRect.Y = y;
}
else
{
buttonRect.X = buttonRect.Right + pixelRelativeSize.Width;
buttonRect.Width = (scrollBarClientRect.Right - this.GetButtonsNumberBottom()*buttonSize.Width - pixelRelativeSize.Height) - buttonRect.X;
}
}
break;
}
case(ScrollBarButtonType.SmallDecrement):
if(this._scrollBarButtonStyle == ScrollBarButtonStyles.All ||
this._scrollBarButtonStyle == ScrollBarButtonStyles.SmallScroll)
{
if(verticalAxis)
{
buttonRect.Y = scrollBarClientRect.Bottom - buttonRect.Height;
}
else
{
buttonRect.X = scrollBarClientRect.X + (this.GetButtonsNumberTop()-1f)*buttonSize.Width;
buttonRect.X += (this.GetButtonsNumberTop() == 1) ? 0 : pixelRelativeSize.Width;
}
}
else
{
buttonRect = RectangleF.Empty;
}
break;
case(ScrollBarButtonType.SmallIncrement):
if(this._scrollBarButtonStyle == ScrollBarButtonStyles.All ||
this._scrollBarButtonStyle == ScrollBarButtonStyles.SmallScroll)
{
if(verticalAxis)
{
buttonRect.Y = scrollBarClientRect.Y + (this.GetButtonsNumberTop()-1f) * buttonSize.Height;
buttonRect.Y += (this.GetButtonsNumberTop() == 1) ? 0 : pixelRelativeSize.Height;
}
else
{
buttonRect.X = scrollBarClientRect.Right - buttonRect.Width;
}
}
else
{
buttonRect = RectangleF.Empty;
}
break;
case(ScrollBarButtonType.ZoomReset):
if(this._scrollBarButtonStyle == ScrollBarButtonStyles.All ||
this._scrollBarButtonStyle == ScrollBarButtonStyles.ResetZoom)
{
if(verticalAxis)
{
buttonRect.Y = scrollBarClientRect.Y;
}
else
{
buttonRect.X = scrollBarClientRect.X;
}
}
else
{
buttonRect = RectangleF.Empty;
}
break;
}
return buttonRect;
}
///
/// Returns scroll bar rectangle position in relative coordinates.
///
/// Scroll bar position.
internal RectangleF GetScrollBarRect()
{
// Get scroll bar relative size
float scrollBarSize = (float)this.GetScrollBarRelativeSize();
// Get relative size of the axis line (Note: Code removed for now. -- AG)
//SizeF axisLineSize = new SizeF(axis.LineWidth, axis.LineWidth);
//axisLineSize.Width = axisLineSize.Width * 100F / ((float)(this.axis.Common.Width - 1));
//axisLineSize.Height = axisLineSize.Height * 100F / ((float)(this.axis.Common.Height - 1));
// Check if scroll bar is positioned next to PlotArea or ChartArea
RectangleF areaPosition = axis.PlotAreaPosition.ToRectangleF();
if(!this.IsPositionedInside)
{
areaPosition = axis.ChartArea.Position.ToRectangleF();
// Reduce rectangle size by scroll bar size
foreach(Axis a in this.ChartArea.Axes)
{
if(a.ScrollBar.IsVisible && !a.ScrollBar.IsPositionedInside)
{
float size = (float)a.ScrollBar.GetScrollBarRelativeSize();
switch( a.AxisPosition )
{
case AxisPosition.Left:
areaPosition.X += size;
areaPosition.Width -= size;
break;
case AxisPosition.Right:
areaPosition.Width -= size;
break;
case AxisPosition.Bottom:
areaPosition.Height -= size;
break;
case AxisPosition.Top:
areaPosition.Y += size;
areaPosition.Height -= size;
break;
}
}
}
}
// Get bar position depending on the axis type
RectangleF barPosition = RectangleF.Empty;
if(this.axis.PlotAreaPosition != null)
{
switch( axis.AxisPosition )
{
case AxisPosition.Left:
barPosition.Y = areaPosition.Y;
barPosition.Height = areaPosition.Height;
barPosition.X =
( (this.IsPositionedInside) ? (float)(axis.GetAxisPosition(true)) : areaPosition.X) - scrollBarSize;// - axisLineSize.Width / 2f;
barPosition.Width = scrollBarSize;
break;
case AxisPosition.Right:
barPosition.Y = areaPosition.Y;
barPosition.Height = areaPosition.Height;
barPosition.X =
(this.IsPositionedInside) ? (float)axis.GetAxisPosition(true) : areaPosition.Right;// + axisLineSize.Width / 2f;
barPosition.Width = scrollBarSize;
break;
case AxisPosition.Bottom:
barPosition.X = areaPosition.X;
barPosition.Width = areaPosition.Width;
barPosition.Y =
(this.IsPositionedInside) ? (float)axis.GetAxisPosition(true) : areaPosition.Bottom;// + axisLineSize.Height / 2f;
barPosition.Height = scrollBarSize;
break;
case AxisPosition.Top:
barPosition.X = areaPosition.X;
barPosition.Width = areaPosition.Width;
barPosition.Y =
( (this.IsPositionedInside) ? (float)axis.GetAxisPosition(true) : areaPosition.Y) - scrollBarSize;// - axisLineSize.Height / 2f;
barPosition.Height = scrollBarSize;
break;
}
}
return barPosition;
}
///
/// Internal helper method which returns the relative scroll bar size.
///
/// Relative scroll bar size.
internal double GetScrollBarRelativeSize()
{
// Scroll bar is not shown in 3D
if(this.axis.ChartArea.Area3DStyle.Enable3D || this.axis.ChartArea.chartAreaIsCurcular)
{
return 0.0;
}
#if SUBAXES
// Scrollbar not supported on sub axis
if( this.axis != null && this.axis.IsSubAxis)
{
return 0.0;
}
#endif //SUBAXES
// Get scroll bar relative size depending on the axis location
if(this.axis.AxisPosition == AxisPosition.Left || this.axis.AxisPosition == AxisPosition.Right)
{
return this._scrollBarSize * 100F / ((float)(this.axis.Common.Width - 1));
}
else
{
return this._scrollBarSize * 100F / ((float)(this.axis.Common.Height - 1));
}
}
///
/// Returns the percentage size (0-100%) of the data scaleView comparing to
/// the axis scale minimum and maximum values.
///
/// Size of the data scaleView in percentage.
private double GetDataViewPercentage()
{
double viewPercentage = 100.0;
// Check if axis data scaleView properties are set
if(this.axis != null &&
!double.IsNaN(this.axis.ScaleView.Position) &&
!double.IsNaN(this.axis.ScaleView.Size))
{
// Get data scaleView size
double dataViewSize = ChartHelper.GetIntervalSize(
this.axis.ScaleView.Position,
this.axis.ScaleView.Size,
this.axis.ScaleView.SizeType);
// Get axis scale size without margins
double minimum = this.axis.minimum + this.axis.marginView;
double maximum = this.axis.maximum - this.axis.marginView;
if(this.axis.ScaleView.Position < minimum)
{
minimum = this.axis.ScaleView.Position;
}
if((this.axis.ScaleView.Position + dataViewSize) > maximum)
{
maximum = this.axis.ScaleView.Position + dataViewSize;
}
double axisScaleSize = Math.Abs(minimum - maximum);
// Check if data scaleView is smaller than axis scale and if it is find the pecentage
if(dataViewSize < axisScaleSize)
{
viewPercentage = dataViewSize / (axisScaleSize / 100.0);
}
}
return viewPercentage;
}
///
/// Returns the the data scaleView position in percentage (0-100%) using
/// the axis scale minimum and maximum values.
///
/// Data scaleView position in percentage.
private double GetDataViewPositionPercentage()
{
double viewPosition = 0.0;
// Check if axis data scaleView properties are set
if(this.axis != null &&
!double.IsNaN(this.axis.ScaleView.Position) &&
!double.IsNaN(this.axis.ScaleView.Size))
{
// Get data scaleView size
double dataViewSize = ChartHelper.GetIntervalSize(
this.axis.ScaleView.Position,
this.axis.ScaleView.Size,
this.axis.ScaleView.SizeType);
// Get axis scale size without margins
double minimum = this.axis.minimum + this.axis.marginView;
double maximum = this.axis.maximum - this.axis.marginView;
if(this.axis.ScaleView.Position < minimum)
{
minimum = this.axis.ScaleView.Position;
}
if((this.axis.ScaleView.Position + dataViewSize) > maximum)
{
maximum = this.axis.ScaleView.Position + dataViewSize;
}
double axisScaleSize = Math.Abs(minimum - maximum);
// Calculate data scaleView position in percentage
viewPosition = (this.axis.ScaleView.Position - (minimum)) / (axisScaleSize / 100.0);
}
return viewPosition;
}
///
/// Get total number of buttons in the scroll bar (except tracker).
///
/// Number of buttons.
private int GetButtonsNumberAll()
{
int buttonNumber = 0;
if((this._scrollBarButtonStyle & ScrollBarButtonStyles.ResetZoom) == ScrollBarButtonStyles.ResetZoom)
{
buttonNumber += 1;
}
if((this._scrollBarButtonStyle & ScrollBarButtonStyles.SmallScroll) == ScrollBarButtonStyles.SmallScroll)
{
buttonNumber += 2;
}
return buttonNumber;
}
///
/// Get number of buttons in the top (left) part of the scroll bar.
///
/// Number of buttons.
private int GetButtonsNumberTop()
{
int buttonNumber = 0;
if((this._scrollBarButtonStyle & ScrollBarButtonStyles.ResetZoom) == ScrollBarButtonStyles.ResetZoom)
{
buttonNumber += 1;
}
if((this._scrollBarButtonStyle & ScrollBarButtonStyles.SmallScroll) == ScrollBarButtonStyles.SmallScroll)
{
buttonNumber += 1;
}
return buttonNumber;
}
///
/// Get number of buttons in the bottom (right) part of the scroll bar.
///
/// Number of buttons.
private int GetButtonsNumberBottom()
{
int buttonNumber = 0;
if((this._scrollBarButtonStyle & ScrollBarButtonStyles.SmallScroll) == ScrollBarButtonStyles.SmallScroll)
{
buttonNumber += 1;
}
return buttonNumber;
}
#endregion
#region Coordinate convertion methods
///
/// Converts Relative size to Absolute size
///
/// Relative size in %
/// Absolute size
internal SizeF GetAbsoluteSize( SizeF relative )
{
SizeF absolute = SizeF.Empty;
// Convert relative coordinates to absolute coordinates
absolute.Width = relative.Width * (this.axis.Common.Width - 1) / 100F;
absolute.Height = relative.Height * (this.axis.Common.Height - 1) / 100F;
// Return Absolute coordinates
return absolute;
}
///
/// Converts Absolute size to Relative size
///
/// Absolute size
/// Relative size
internal SizeF GetRelativeSize( SizeF size )
{
SizeF relative = SizeF.Empty;
// Convert absolute coordinates to relative coordinates
relative.Width = size.Width * 100F / ((float)(this.axis.Common.Width - 1));
relative.Height = size.Height * 100F / ((float)(this.axis.Common.Height - 1));
// Return relative coordinates
return relative;
}
#endregion
#region IDisposable Members
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Dispose managed resources
if (this._scrollTimer != null)
{
this._scrollTimer.Dispose();
this._scrollTimer = null;
}
}
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
///
/// The arguments for a scrollbar event.
///
public class ScrollBarEventArgs : EventArgs
{
#region Private fields
// Private fields for properties values storage
private Axis _axis = null;
private bool _isHandled = false;
private int _mousePositionX = 0;
private int _mousePositionY = 0;
private ScrollBarButtonType _buttonType = ScrollBarButtonType.ThumbTracker;
#endregion
#region Constructors
///
/// ScrollBarEventArgs constructor.
///
/// Axis containing the scrollbar.
/// X position of mouse cursor.
/// Y position of mouse cursor.
/// Button type of the button clicked.
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly",
Justification = "X and Y are cartesian coordinates and well understood")]
public ScrollBarEventArgs(Axis axis, int x, int y, ScrollBarButtonType buttonType)
{
this._axis = axis;
this._mousePositionX = x;
this._mousePositionY = y;
this._buttonType = buttonType;
}
#endregion
#region Properties
///
/// Axis containing the scrollbar of the event.
///
[
SRDescription("DescriptionAttributeAxis"),
]
public Axis Axis
{
get
{
return _axis;
}
}
///
/// ChartArea containing the scrollbar of the event.
///
[
SRDescription("DescriptionAttributeChartArea"),
]
public ChartArea ChartArea
{
get
{
return _axis.ChartArea;
}
}
///
/// Button type of the scrollbar button clicked.
///
[
SRDescription("DescriptionAttributeScrollBarEventArgs_ButtonType"),
]
public ScrollBarButtonType ButtonType
{
get
{
return _buttonType;
}
}
///
/// Indicates if the event is handled by the user and no further processing is required.
///
[
SRDescription("DescriptionAttributeScrollBarEventArgs_Handled"),
]
public bool IsHandled
{
get
{
return _isHandled;
}
set
{
_isHandled = value;
}
}
///
/// X position of mouse cursor.
///
[
SRDescription("DescriptionAttributeScrollBarEventArgs_MousePositionX"),
]
public int MousePositionX
{
get
{
return _mousePositionX;
}
}
///
/// Y position of mouse cursor.
///
[
SRDescription("DescriptionAttributeScrollBarEventArgs_MousePositionY"),
]
public int MousePositionY
{
get
{
return _mousePositionY;
}
}
#endregion
}
}
#endif // #if WINFORMS_CONTROL