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

            }
        }
        /// <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 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 );
            }
        }