/// <summary>
        /// Sets the nested lines.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="nestedLines">The nested lines. If parameter is null the line will be converted to a normal (not nested) line with default line size.</param>
        public void SetNestedLines(int index, IEditableLineSizeHost nestedLines)
        {
            if (nestedLines != null)
            {
                lineSizes[index]  = -2; // -1 indicates default value, -2 indicates nested.
                lineNested[index] = (LineSizeCollection)nestedLines;
            }
            else
            {
                lineSizes[index] = -1; // -1 indicates default value, -2 indicates nested.
                lineNested.Remove(index);
            }

            if (IsSuspendUpdates)
            {
                return;
            }

            if (distances != null)
            {
                DistancesUtil.DistancesLineSizeChanged(distances, this, index, index);
            }

            if (LineSizeChanged != null)
            {
                LineSizeChanged(this, new RangeChangedEventArgs(index, index));
            }
        }
        public static void SetRange(IEditableLineSizeHost lines, int from, int to, double[] values)
        {
            int index = from;
            int n     = 0;

            while (index <= to)
            {
                lines.SetRange(index, index, values[n++]);
                index++;
            }
        }
        /// <summary>
        /// Gets the size.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <param name="repeatValueCount">The number of subsequent values with same size.</param>
        /// <returns></returns>
        public virtual double GetSize(int index, out int repeatValueCount)
        {
            repeatValueCount = 1;
            IEditableLineSizeHost nested = GetNestedLines(index);

            if (nested != null)
            {
                return(nested.TotalExtent);
            }

            return(GetRange(index, out repeatValueCount));
        }
        /// <summary>
        /// Inserts lines in the collection and raises the <see cref="LinesInserted"/> event.
        /// </summary>
        /// <param name="insertAtLine">The index of the first line to insert.</param>
        /// <param name="count">The count.</param>
        /// <param name="movelines">A container with saved state from a preceeding <see cref="RemoveLines"/> call when lines should be moved. When it is null empty lines with default size are inserted.</param>
        public void InsertLines(int insertAtLine, int count, IEditableLineSizeHost movelines)
        {
            var moveLines = (LineSizeCollection)movelines;

            lineSizes.Insert(insertAtLine, count, moveLines == null ? null : moveLines.lineSizes);
            lineHidden.Insert(insertAtLine, count, moveLines == null ? null : moveLines.lineHidden);

            Dictionary <int, LineSizeCollection> _lineNested = lineNested;

            lineNested = new Dictionary <int, LineSizeCollection>();

            foreach (KeyValuePair <int, LineSizeCollection> entry in _lineNested)
            {
                if (entry.Key >= insertAtLine)
                {
                    lineNested.Add(entry.Key + count, entry.Value);
                }
                else
                {
                    lineNested.Add(entry.Key, entry.Value);
                }
            }

            if (moveLines != null)
            {
                foreach (KeyValuePair <int, LineSizeCollection> entry in moveLines.lineNested)
                {
                    lineNested.Add(entry.Key + insertAtLine, entry.Value);
                }
            }

            lineCount += count;

            if (IsSuspendUpdates)
            {
                return;
            }

            if (distances != null)
            {
                DistancesUtil.OnInserted(distances, this, insertAtLine, count);
            }

            if (LinesInserted != null)
            {
                LinesInserted(this, new LinesInsertedEventArgs(insertAtLine, count));
            }
        }
        /// <summary>
        /// Removes lines from the collection and raises the <see cref="LinesRemoved"/> event.
        /// </summary>
        /// <param name="removeAtLine">The index of the first line to be removed.</param>
        /// <param name="count">The count.</param>
        /// <param name="movelines">A container to save state for a subsequent <see cref="InsertLines"/> call when lines should be moved.</param>
        public void RemoveLines(int removeAtLine, int count, IEditableLineSizeHost movelines)
        {
            var moveLines = (LineSizeCollection)movelines;

            lineSizes.Remove(removeAtLine, count, moveLines == null ? null : moveLines.lineSizes);
            lineHidden.Remove(removeAtLine, count, moveLines == null ? null : moveLines.lineHidden);

            Dictionary <int, LineSizeCollection> _lineNested = lineNested;

            lineNested = new Dictionary <int, LineSizeCollection>();

            foreach (KeyValuePair <int, LineSizeCollection> entry in _lineNested)
            {
                if (entry.Key >= removeAtLine)
                {
                    if (entry.Key >= removeAtLine + count)
                    {
                        lineNested.Add(entry.Key - count, entry.Value);
                    }
                    else if (moveLines != null)
                    {
                        moveLines.lineNested.Add(entry.Key - removeAtLine, entry.Value);
                    }
                }
                else
                {
                    lineNested.Add(entry.Key, entry.Value);
                }
            }

            lineCount -= count;

            if (IsSuspendUpdates)
            {
                return;
            }

            if (distances != null)
            {
                distances.Remove(removeAtLine, count);
            }

            if (LinesRemoved != null)
            {
                LinesRemoved(this, new LinesRemovedEventArgs(removeAtLine, count));
            }
        }