/// <summary>
        /// Scrolls the line into viewable area.
        /// </summary>
        /// <param name="lineIndex">Index of the line.</param>
        /// <param name="lineSize">Size of the line.</param>
        public override void ScrollInView(int lineIndex, double lineSize)
        {
            VisibleLinesCollection lines = GetVisibleLines();
            VisibleLineInfo        line  = lines.GetVisibleLineAtLineIndex(lineIndex);
            double delta = 0;

            if (line != null)
            {
                if (!line.IsClipped || line.IsFooter || line.IsHeader)
                {
                    return;
                }

                if (line.IsClippedOrigin && !line.IsClippedCorner)
                {
                    delta = -(lineSize - line.ClippedSize);
                }
                else if (!line.IsClippedOrigin && line.IsClippedCorner)
                {
                    //Following code prevent the horizontal auto scrolling when column size is bigger than viewPort size.
                    if (line.ClippedOrigin < line.ClippedSize)
                    {
                        delta = 0;
                    }
                    else
                    {
                        delta = lineSize - line.ClippedSize;
                    }
                }
                else
                {
                    delta = lineSize - line.ClippedSize;
                }
            }
            else
            {
                double d = Distances.GetCumulatedDistanceAt(lineIndex);

                if (d > ScrollBar.Value)
                {
                    d = d + lineSize - ScrollBar.LargeChange;
                }

                delta = d - ScrollBar.Value;
            }

            if (delta != 0)
            {
                ScrollBar.Value += delta;
            }
        }
        /// <summary>
        /// Scrolls the line into viewable area.
        /// </summary>
        /// <param name="lineIndex">Index of the line.</param>
        /// <param name="lineSize"></param>
        public override void ScrollInView(int lineIndex, double lineSize)
        {
            VisibleLinesCollection lines = GetVisibleLines();
            VisibleLineInfo        line  = lines.GetVisibleLineAtLineIndex(lineIndex);
            double delta = 0;

            if (line != null)
            {
                if (!line.IsClipped || line.IsFooter || line.IsHeader)
                {
                    return;
                }

                if (line.IsClippedOrigin && !line.IsClippedCorner)
                {
                    delta = -1;
                }

                else if (!line.IsClippedOrigin && line.IsClippedCorner)
                {
                    double y                  = line.Size - line.ClippedSize;
                    int    scrollIndex        = this.ScrollLineIndex;
                    double visibleScrollIndex = ScrollBar.Value;
                    while (y > 0 && visibleScrollIndex < ScrollBar.Maximum)
                    {
                        delta++;
                        visibleScrollIndex++;
                        y -= GetLineSize(ScrollBarValueToLineIndex(visibleScrollIndex));
                    }
                }
            }
            else
            {
                double visibleScrollIndex = LineIndexToScrollBarValue(lineIndex);

                if (visibleScrollIndex > ScrollBar.Value)
                {
                    int scrollIndexLinex = this.IntPreviousPageLineIndex(ScrollPageSize - GetLineSize(lineIndex), lineIndex);
                    visibleScrollIndex = LineIndexToScrollBarValue(scrollIndexLinex);
                }
                delta = visibleScrollIndex - ScrollBar.Value;
            }

            if (delta != 0)
            {
                ScrollBar.Value += delta;
            }

            base.ScrollInView(lineIndex, lineSize);
        }
        /// <summary>
        /// Gets the cumulated corner taking scroll position into account. The
        /// returned value is between ScrollBar.Minimum and ScrollBar.Maximum.
        /// </summary>
        /// <param name="line">The line.</param>
        /// <returns></returns>
        private double GetCumulatedCorner(VisibleLineInfo line)
        {
            VisibleLinesCollection lines = GetVisibleLines();

            if (line.IsHeader)
            {
                return(line.Corner);
            }
            else if (line.IsFooter)
            {
                return(ScrollBar.Maximum - lines[lines.firstFooterVisibleIndex].Origin + line.Corner);
            }

            return(line.Corner - ScrollBar.Minimum + ScrollBar.Value);
        }
        /// <summary>
        /// Returns the first and last point for the given lines in a region.
        /// </summary>
        /// <param name="region">The region.</param>
        /// <param name="first">The index of the first line.</param>
        /// <param name="last">The index of the last line.</param>
        /// <param name="allowEstimatesForOutOfViewLines">if set to <c>true</c> allow estimates for out of view lines.</param>
        /// <returns></returns>
        public override DoubleSpan RangeToPoints(ScrollAxisRegion region, int first, int last, bool allowEstimatesForOutOfViewLines)
        {
            VisibleLinesCollection lines = GetVisibleLines();

            // If line is visible use already calculated values,
            // otherwise get value from Distances
            VisibleLineInfo line1 = lines.GetVisibleLineAtLineIndex(first);
            VisibleLineInfo line2 = lines.GetVisibleLineAtLineIndex(last);

            double p1, p2;

            p1 = line1 == null?Distances.GetCumulatedDistanceAt(first) : GetCumulatedOrigin(line1);

            p2 = line2 == null?Distances.GetCumulatedDistanceAt(last + 1) : GetCumulatedCorner(line2);

            return(RangeToPointsHelper(region, p1, p2));
        }
        private DoubleSpan RangeToPointsHelper(ScrollAxisRegion region, double p1, double p2)
        {
            VisibleLinesCollection lines = GetVisibleLines();

            switch (region)
            {
            case ScrollAxisRegion.Header:
                if (HeaderLineCount > 0)
                {
                    return(new DoubleSpan(p1, p2));
                }
                else
                {
                    return(DoubleSpan.Empty);
                }

            case ScrollAxisRegion.Footer:
                if (IsFooterVisible)
                {
                    VisibleLineInfo l  = lines[lines.FirstFooterVisibleIndex];
                    double          p3 = Distances.TotalDistance - this.FooterExtent;
                    p1 += l.Origin - p3;
                    p2 += l.Origin - p3;
                    return(new DoubleSpan(p1, p2));
                }
                else
                {
                    return(DoubleSpan.Empty);
                }

            case ScrollAxisRegion.Body:
                p1 += HeaderExtent - ScrollBar.Value;
                p2 += HeaderExtent - ScrollBar.Value;
                return(new DoubleSpan(p1, p2));
            }

            return(DoubleSpan.Empty);
        }
        /// <summary>
        /// Returns the first and last point for the given lines in a region.
        /// </summary>
        /// <param name="region">The region.</param>
        /// <param name="first">The index of the first line.</param>
        /// <param name="last">The index of the last line.</param>
        /// <param name="allowEstimatesForOutOfViewLines">if set to <c>true</c> allow estimates for out of view lines.</param>
        /// <returns></returns>
        public override DoubleSpan RangeToPoints(ScrollAxisRegion region, int first, int last, bool allowEstimatesForOutOfViewLines)
        {
            VisibleLinesCollection visibleLines = this.GetVisibleLines();
            bool            firstVisible, lastVisible;
            VisibleLineInfo firstLine, lastLine;

            GetLinesAndVisibility(first, last, true, out firstVisible, out lastVisible, out firstLine, out lastLine);

            if (firstLine == null || lastLine == null)
            {
                return(DoubleSpan.Empty);
            }

            if (allowEstimatesForOutOfViewLines)
            {
                switch (region)
                {
                case ScrollAxisRegion.Header:
                    if (!firstLine.IsHeader)
                    {
                        return(DoubleSpan.Empty);
                    }
                    break;

                case ScrollAxisRegion.Footer:
                    if (!lastLine.IsFooter)
                    {
                        return(DoubleSpan.Empty);
                    }
                    break;

                case ScrollAxisRegion.Body:
                    if (firstLine.IsFooter || lastLine.IsHeader)
                    {
                        return(DoubleSpan.Empty);
                    }
                    break;
                } // switch

                return(new DoubleSpan(firstLine.Origin, lastLine.Corner));
            }
            else
            {
                switch (region)
                {
                case ScrollAxisRegion.Header:
                {
                    if (!firstLine.IsHeader)
                    {
                        return(DoubleSpan.Empty);
                    }

                    if (!lastVisible || !lastLine.IsHeader)
                    {
                        double corner = firstLine.Corner;
                        for (int n = firstLine.LineIndex + 1; n <= last; n++)
                        {
                            corner += GetLineSize(n);
                        }

                        return(new DoubleSpan(firstLine.Origin, corner));
                    }

                    return(new DoubleSpan(firstLine.Origin, lastLine.Corner));
                }

                case ScrollAxisRegion.Footer:
                {
                    if (!lastLine.IsFooter)
                    {
                        return(DoubleSpan.Empty);
                    }

                    if (!firstVisible || !firstLine.IsFooter)
                    {
                        double origin = lastLine.Origin;
                        for (int n = lastLine.LineIndex - 1; n >= first; n--)
                        {
                            origin -= GetLineSize(n);
                        }

                        return(new DoubleSpan(origin, lastLine.Corner));
                    }

                    return(new DoubleSpan(firstLine.Origin, lastLine.Corner));
                }

                case ScrollAxisRegion.Body:
                {
                    if (firstLine.IsFooter || lastLine.IsHeader)
                    {
                        return(DoubleSpan.Empty);
                    }

                    double origin = firstLine.Origin;
                    if (!firstVisible || firstLine.Region != ScrollAxisRegion.Body)
                    {
                        origin = HeaderExtent;
                        for (int n = ScrollLineIndex - 1; n >= first; n--)
                        {
                            origin -= GetLineSize(n);
                        }
                    }

                    double corner = lastLine.Corner;
                    if (!lastVisible || lastLine.Region != ScrollAxisRegion.Body)
                    {
                        corner = LastBodyVisibleLine.Corner;
                        for (int n = LastBodyVisibleLine.LineIndex + 1; n <= last; n++)
                        {
                            corner += GetLineSize(n);
                        }
                    }

                    return(new DoubleSpan(origin, corner));
                }
                } // switch

                return(new DoubleSpan(firstLine.Origin, lastLine.Corner));
            }
        }