/// <summary>
        /// Renders a graph using this renderer
        /// </summary>
        public void Render( IGraphCanvas graphics, GraphTransform transform, IGraph2dSource data, PointF cursorDataPt, bool enabled )
        {
            Graph2dSourceUniformValue uniformData = ( Graph2dSourceUniformValue )data;

            if ( uniformData.FixedAxis == Graph2dSourceUniformValue.Axis.X )
            {
                float dataX = transform.DataToScreen( new PointF( uniformData.Value, 0 ) ).X;

                //	TODO: Need to
                if ( Math.Abs( cursorDataPt.X - uniformData.Value ) < transform.ScreenToDataXScale * Graph2dUniformValueController.ScreenSelectionTolerance )
                {
                    graphics.DrawLine( s_HighlightPen, dataX, transform.DrawBounds.Top, dataX, transform.DrawBounds.Bottom );
                }
                graphics.DrawLine( m_Pen, dataX, transform.DrawBounds.Top, dataX, transform.DrawBounds.Bottom );

            }
            else
            {
                float dataY = transform.DataToScreen( new PointF( 0, uniformData.Value ) ).Y;
                if ( Math.Abs( cursorDataPt.Y - uniformData.Value ) < transform.ScreenToDataYScale * Graph2dUniformValueController.ScreenSelectionTolerance )
                {
                    graphics.DrawLine( s_HighlightPen, transform.DrawBounds.Left, dataY, transform.DrawBounds.Right, dataY );
                }
                graphics.DrawLine( m_Pen, transform.DrawBounds.Left, dataY, transform.DrawBounds.Right, dataY );

            }
        }
 public void Render( IGraphCanvas graphics, GraphTransform transform, IGraph2dSource data, PointF cursorDataPt, bool enabled )
 {
     foreach ( IGraph2dRenderer renderer in m_Renderers )
     {
         renderer.Render( graphics, transform, data, cursorDataPt, enabled );
     }
 }
        /// <summary>
        /// Renders graph data
        /// </summary>
        /// <param name="graphics">Graphics object to render into</param>
        /// <param name="transform">Graph transform</param>
        /// <param name="data">Data to render</param>
        /// <param name="cursorDataPt">Position of the mouse cursor in data space</param>
        /// <param name="enabled">The enabled state of the graph control</param>
        public void Render( IGraphCanvas graphics, GraphTransform transform, IGraph2dSource data, PointF cursorDataPt, bool enabled )
        {
            IGraphX2dSampleSource sampleSource = ( IGraphX2dSampleSource )data;

            int sample = ( int )( transform.DataBounds.Left / sampleSource.XStepPerSample );
            Color darkColour = GraphUtils.ScaleColour( m_Colour, 0.2f );
            float hStep = sampleSource.XStepPerSample / 2;
            float dataX = ( sample * sampleSource.XStepPerSample ) + hStep;
            while ( dataX < transform.DataBounds.Right )
            {
                float value = sampleSource.Evaluate( dataX );
                dataX += sampleSource.XStepPerSample;

                Point tl = transform.DataToScreen( new PointF( dataX - hStep, value ) );
                Point br = transform.DataToScreen( new PointF( dataX + hStep, 0 ) );
                if ( ( br.Y - tl.Y ) == 0 )
                {
                    continue;
                }

                Rectangle barArea = new Rectangle( tl.X - 1, tl.Y, ( br.X - tl.X ) + 1, br.Y - tl.Y );
                using ( LinearGradientBrush brush = new LinearGradientBrush( barArea, m_Colour, darkColour, 90.0f ) )
                {
                    brush.InterpolationColors = m_Blends;
                    graphics.FillRectangle( brush, barArea );
                }
            }
        }
        /// <summary>
        /// Draws a grid
        /// </summary>
        public static void DrawGrid( IGraphCanvas graphics, Pen pen, Pen zeroPen, Rectangle drawBounds, RectangleF dataBounds, float cellDataWidth, float cellDataHeight )
        {
            float dataX = ( int )( dataBounds.Left / cellDataWidth ) * cellDataWidth;
            float dataY = ( int )( dataBounds.Top / cellDataHeight ) * cellDataHeight;
            int widthInCells = ( int )( dataBounds.Width / cellDataWidth ) + 1;
            int heightInCells = ( int )( dataBounds.Height / cellDataHeight ) + 1;
            for ( int cellX = 0; cellX < widthInCells; ++cellX )
            {
                Pen drawPen = ( Math.Abs( dataX ) < 0.001f ) ? zeroPen : pen;
                float drawX = ( ( ( dataX - dataBounds.Left ) / dataBounds.Width ) * drawBounds.Width ) + drawBounds.Left;
                graphics.DrawLine( drawPen, drawX, drawBounds.Bottom, drawX, drawBounds.Top );

                dataX += cellDataWidth;
            }
            for ( int cellY = 0; cellY < heightInCells; ++cellY )
            {
                Pen drawPen = ( Math.Abs( dataY ) < 0.001f ) ? zeroPen : pen;
                float drawY = InvY( ( ( ( dataY - dataBounds.Top ) / dataBounds.Height ) * drawBounds.Height ) + drawBounds.Top, drawBounds );
                graphics.DrawLine( drawPen, drawBounds.Left, drawY, drawBounds.Right, drawY );

                dataY += cellDataHeight;
            }
        }
        /// <summary>
        /// Renders the graph
        /// </summary>
        public void Render( IGraphCanvas graphics, GraphTransform transform, IGraph2dSource data, PointF cursorDataPt, bool enabled )
        {
            Pen pen = ( enabled && !data.Disabled ) ? m_Pen : s_DisabledPen;
            Pen shadowPen = GetShadowPen( data );

            GraphX2dSourceFunction1dAdapter cpData = ( GraphX2dSourceFunction1dAdapter )data;
            PiecewiseLinearFunction1d pwl = ( PiecewiseLinearFunction1d )cpData.Function;

            float tolerance = transform.ScreenToDataYScale * GraphX2dControlPointController.ScreenSelectionTolerance;
            int highlightCpIndex = IndexOfControlPointNearPoint( pwl.ControlPoints, new Point2( cursorDataPt.X, cursorDataPt.Y ), tolerance );

            Point2 cp = pwl[ 0 ];
            Point lastPt = transform.DataToScreen( new PointF( cp.X, cp.Y ) );
            if ( NoEndPoints )
            {
                Point edgePt = transform.DataToScreen( new PointF( transform.DataBounds.Left, cp.Y ) );
                DrawGraphLine( graphics, pen, shadowPen, enabled, lastPt, edgePt );
            }

            for ( int cpIndex = 1; cpIndex < pwl.NumControlPoints; ++cpIndex )
            {
                cp = pwl[ cpIndex ];
                Point pt = transform.DataToScreen( new PointF( cp.X, cp.Y ) );

                DrawGraphLine( graphics, pen, shadowPen, enabled, lastPt, pt );
                DrawControlPoint( graphics, lastPt, enabled ? m_Brush : s_DisabledBrush, highlightCpIndex == ( cpIndex - 1 ) );

                lastPt = pt;
            }

            if ( NoEndPoints )
            {
                Point edgePt = transform.DataToScreen( new PointF( transform.DataBounds.Right, cp.Y ) );
                DrawGraphLine( graphics, pen, shadowPen, enabled, lastPt, edgePt );
            }
            DrawControlPoint( graphics, lastPt, Brushes.Blue, highlightCpIndex == ( pwl.NumControlPoints - 1 ) );
        }
        /// <summary>
        /// Renders control points in a graph that derives from Graph2dPiecewiseLinear
        /// </summary>
        public void Render( IGraphCanvas graphics, GraphTransform transform, IGraph2dSource data, PointF cursorDataPt, bool enabled )
        {
            if ( data.Disabled )
            {
                return;
            }
            GraphX2dSourceFunction1dAdapter pwlGraph = ( GraphX2dSourceFunction1dAdapter )data;
            PiecewiseLinearFunction1d pwlFunc = ( PiecewiseLinearFunction1d )pwlGraph.Function;

            float tolerance = transform.ScreenToDataYScale * GraphX2dControlPointController.ScreenSelectionTolerance;
            int highlightCpIndex = pwlFunc.FindControlPoint( new Point2( cursorDataPt.X, cursorDataPt.Y ), tolerance );

            for ( int cpIndex = 0; cpIndex < pwlFunc.NumControlPoints; ++cpIndex )
            {
                Point2 cp = pwlFunc[ cpIndex ];
                PointF screenPt = transform.DataToScreen( new PointF( cp.X, cp.Y ) );
                graphics.FillCircle( m_CpBrush, screenPt.X, screenPt.Y, 2 );

                if ( cpIndex == highlightCpIndex )
                {
                    graphics.DrawCircle( s_HighlightPen, screenPt.X, screenPt.Y, 4 );
                }
            }
        }
        /// <summary>
        /// Draws the axis vertically
        /// </summary>
        public void DrawVertical( IGraphCanvas canvas, Rectangle drawBounds, RectangleF dataBounds )
        {
            if ( m_TickFont == null )
            {
                return;
            }
            float cellSize = m_LineStep;
            float dataY = ( int )( dataBounds.Top / cellSize ) * cellSize;
            int heightInCells = ( int )( dataBounds.Height / cellSize ) + 1;

            float drawX = ( ( -dataBounds.Left / dataBounds.Width ) * drawBounds.Width ) + drawBounds.Left;
            if ( drawX < 2 )
            {
                drawX = 2;
            }
            for ( int cellY = 0; cellY < heightInCells; ++cellY )
            {
                float drawY = ( ( ( dataY - dataBounds.Top ) / dataBounds.Height ) * drawBounds.Height ) + drawBounds.Top;
                canvas.DrawText( m_TickFont, m_TickFontBrush, drawX, GraphUtils.InvY( drawY, drawBounds ), AxisValueToString( dataY ) );

                dataY += cellSize;
            }
        }
        /// <summary>
        /// Draws the axis horizontally
        /// </summary>
        public void DrawHorizontal( IGraphCanvas canvas, Rectangle drawBounds, RectangleF dataBounds )
        {
            if ( m_TickFont == null )
            {
                return;
            }
            float cellSize = m_LineStep;
            float dataX = ( int )( dataBounds.Left / cellSize ) * cellSize;
            float drawY = ( ( ( -dataBounds.Top / dataBounds.Height ) * drawBounds.Height ) + drawBounds.Top );
            if ( drawY < m_TickFont.Height )
            {
                drawY = m_TickFont.Height;
            }
            int widthInCells = ( int )( dataBounds.Width / cellSize ) + 1;
            for ( int cellX = 0; cellX < widthInCells; ++cellX )
            {
                float drawX = ( ( ( dataX - dataBounds.Left ) / dataBounds.Width ) * drawBounds.Width ) + drawBounds.Left;
                canvas.DrawText( m_TickFont, m_TickFontBrush, drawX, GraphUtils.InvY( drawY, drawBounds ), AxisValueToString( dataX ) );

                dataX += cellSize;
            }
        }
        /// <summary>
        /// Renders graph data
        /// </summary>
        /// <param name="graphics">Graphics object to render into</param>
        /// <param name="transform">Graph view transform</param>
        /// <param name="data">Data to render</param>
        /// <param name="cursorDataPt">Position of the mouse cursor in data space</param>
        /// <param name="enabled">The enabled state of the graph control</param>
        public virtual void Render( IGraphCanvas graphics, GraphTransform transform, IGraph2dSource data, PointF cursorDataPt, bool enabled )
        {
            IGraphX2dSource eval = ( IGraphX2dSource )data;
            Pen pen = ( enabled && !data.Disabled ) ? m_Pen : s_DisabledPen;

            Pen shadowPen = null;
            if ( !data.Disabled )
            {
                if ( data.Selected )
                {
                    shadowPen = s_SelectedPen;
                }
                else if ( data.Highlighted )
                {
                    shadowPen = s_HighlightedPen;
                }
            }

            float dataX = transform.DataBounds.Left;
            float dataXInc = transform.DataBounds.Width / transform.DrawBounds.Width;

            Point lastPt = transform.DataToScreen( new PointF( dataX, eval.Evaluate( dataX ) ) ) ;
            dataX += dataXInc;

            for ( int drawX = 1; drawX < transform.DrawBounds.Width; ++drawX, dataX += dataXInc )
            {
                Point pt = transform.DataToScreen( new PointF( dataX, eval.Evaluate( dataX ) ) );
                graphics.DrawLine( pen, lastPt.X, lastPt.Y, pt.X, pt.Y );
                if ( enabled && shadowPen != null )
                {
                    graphics.DrawLine( shadowPen, lastPt.X, lastPt.Y + 1, pt.X, pt.Y + 1 );
                    graphics.DrawLine( shadowPen, lastPt.X, lastPt.Y - 1, pt.X, pt.Y - 1 );
                }
                lastPt = pt;
            }
        }
        /// <summary>
        /// Draws a graph line
        /// </summary>
        private static void DrawGraphLine( IGraphCanvas graphics, Pen pen, Pen shadowPen, bool enabled, Point lastPt, Point pt )
        {
            graphics.DrawLine( pen, pt.X, pt.Y, lastPt.X, lastPt.Y );

            if ( enabled && shadowPen != null )
            {
                graphics.DrawLine( shadowPen, lastPt.X, lastPt.Y + 1, pt.X, pt.Y + 1 );
                graphics.DrawLine( shadowPen, lastPt.X, lastPt.Y - 1, pt.X, pt.Y - 1 );
            }
        }
 /// <summary>
 /// Draws a control point
 /// </summary>
 private static void DrawControlPoint( IGraphCanvas graphics, Point screenPt, Brush brush, bool highlight )
 {
     graphics.FillCircle( brush, screenPt.X, screenPt.Y, 2 );
     if ( highlight )
     {
         graphics.DrawCircle( s_HighlightedPen, screenPt.X, screenPt.Y, 4 );
     }
 }
        /// <summary>
        /// Draws legends for all the graphs
        /// </summary>
        public static void DrawLegends( IGraphCanvas graphics, Font font, IEnumerable< GraphComponent > graphComponents )
        {
            int x = 0;
            int y = 0;
            using ( SolidBrush fontBrush = new SolidBrush( Color.Black ) )
            {
                using ( Pen pen = new Pen( Color.Black ) )
                {
                    foreach ( GraphComponent graphComponent in graphComponents )
                    {
                        fontBrush.Color = ( graphComponent.Renderer != null ) ? graphComponent.Renderer.Colour : Color.Black;
                        pen.Color = fontBrush.Color;

                        graphics.DrawText( font, fontBrush, x, y, graphComponent.Name );
                        y += font.Height + 2;

                        //graphics.DrawLine( pen, x, y, x + 30, y );
                    }
                }
            }
        }