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