Beispiel #1
0
        /// <summary>
        /// Appends the <paramref name="text"/> to the <see cref="TextBox"/> at the end.
        /// </summary>
        /// <param name="text">The text to append.</param>
        public void Append(StyledText text)
        {
            if (text.Text.Length == 0)
            {
                return;
            }

            if (!IsMultiLine)
            {
                _lines.LastLine.Append(text.ToSingleline());
            }
            else
            {
                var textLines = StyledText.ToMultiline(text);
                _lines.LastLine.Append(textLines[0]);

                for (var i = 1; i < textLines.Count; i++)
                {
                    var newLine = new TextBoxLine(_lines);
                    _lines.Insert(_lines.Count, newLine);
                    newLine.Append(textLines[i]);
                }

                TruncateIfNeeded();
            }

            _numCharsToDraw.Invalidate();

            _hasTextChanged = true;
        }
Beispiel #2
0
        /// <summary>
        /// A callback for the <see cref="TextBoxLine"/> to notify this <see cref="TextBoxLines"/> that the line
        /// was increased in length.
        /// </summary>
        /// <param name="line">The <see cref="TextBoxLine"/> that had text added to it.</param>
        internal void NotifyTextAdded(TextBoxLine line)
        {
            if (_font == null)
            {
                return;
            }

            var width = line.GetWidth(_font);

            if (width <= _maxLineLength)
            {
                return;
            }

            var newLines = StyledText.ToMultiline(line.GetLineTexts, false, _font, _maxLineLength);

            if (newLines.Count <= 1)
            {
                return;
            }

            // Avoid infinite recursion by not updating if the text didn't change
            var first = newLines[0];

            if (first.Sum(x => x.Text.Length) == line.LineText.Length &&
                StyledText.ToString(first).Equals(line.LineText, StringComparison.Ordinal))
            {
                return;
            }

            line.Clear();
            line.Append(newLines[0]);

            var lineIndex = _lines.IndexOf(line);

            if (lineIndex != _lines.Count - 1 && _lines[lineIndex + 1].WasAutoBroken)
            {
                // We're not at the last line AND the next line was auto-split, so keep inserting at the
                // start of the next line in reverse
                for (var i = newLines.Count - 1; i > 0; i--)
                {
                    foreach (var j in newLines[i].Reverse <StyledText>())
                    {
                        _lines[lineIndex + 1].Insert(j, 0);
                    }
                }
            }
            else
            {
                // We're at the last line or the next line was not an auto-split line
                for (var i = 1; i < newLines.Count; i++)
                {
                    var newLine = new TextBoxLine(this, true);
                    newLine.Append(newLines[i]);
                    _lines.Insert(lineIndex + i, newLine);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Appends another <see cref="TextBoxLine"/> to this <see cref="TextBoxLine"/>.
        /// </summary>
        /// <param name="textBoxLine">The other <see cref="TextBoxLine"/> to append to this.</param>
        public void Append(TextBoxLine textBoxLine)
        {
            for (var i = 0; i < textBoxLine._texts.Count; i++)
            {
                InternalAppend(textBoxLine._texts[i]);
            }

            if (TextBoxLines != null)
            {
                TextBoxLines.NotifyTextAdded(this);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Splits the text in this <see cref="TextBoxLine"/> at the given character index in the line.
        /// </summary>
        /// <param name="lineCharacterIndex">The index of the character to split the line at. This character
        /// at this index will be the first character on the new line.</param>
        /// <param name="currentLine">A <see cref="TextBoxLine"/> representing the remainder of the current
        /// line (the one the split initially was made on).</param>
        /// <param name="nextLine">A <see cref="TextBoxLine"/> representing the additional line created
        /// from the split.</param>
        public void SplitAt(int lineCharacterIndex, out TextBoxLine currentLine, out TextBoxLine nextLine)
        {
            if (lineCharacterIndex == 0)
            {
                // Split at the start of the line
                // First line is empty, second line is the full line
                currentLine = new TextBoxLine(TextBoxLines);
                nextLine    = this;
                return;
            }
            else if (lineCharacterIndex == LineText.Length)
            {
                // Split at the end of the line
                // First line is the full line, second line is empty
                currentLine = this;
                nextLine    = new TextBoxLine(TextBoxLines);
                return;
            }
            else
            {
                // Split up somewhere in the middle

                // Find the StyledText for the character
                StyledText text;
                int        textIndex;
                int        listIndex;
                FindLineCharacter(lineCharacterIndex, out text, out textIndex, out listIndex);

                // Split the StyledText
                StyledText left;
                StyledText right;
                text.SplitAt(textIndex, out left, out right);

                // The first line will be all the StyledTexts before the one split, plus the left side of the split
                // The second line will be the right side of the split, plus all the StyledTexts after the one split
                currentLine = new TextBoxLine(TextBoxLines);
                for (var i = 0; i < listIndex; i++)
                {
                    currentLine.Append(_texts[i]);
                }
                currentLine.Append(left);

                nextLine = new TextBoxLine(TextBoxLines);
                nextLine.Append(right);
                for (var i = listIndex + 1; i < _texts.Count; i++)
                {
                    nextLine.Append(_texts[i]);
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Rebuilds all of the lines and re-applies wrapping.
        /// </summary>
        void RebuildLines()
        {
            var contents = GetText();

            Clear();

            for (var i = 0; i < contents.Count; i++)
            {
                TextBoxLine newLine;
                if (i < _lines.Count)
                {
                    newLine = _lines[i];
                }
                else
                {
                    newLine = new TextBoxLine(this);
                    Append(newLine);
                }

                newLine.Append(contents[i]);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Rebuilds all of the lines and re-applies wrapping.
        /// </summary>
        void RebuildLines()
        {
            var contents = GetText();

            Clear();

            for (var i = 0; i < contents.Count; i++)
            {
                TextBoxLine newLine;
                if (i < _lines.Count)
                    newLine = _lines[i];
                else
                {
                    newLine = new TextBoxLine(this);
                    Append(newLine);
                }

                newLine.Append(contents[i]);
            }
        }
Beispiel #7
0
        /// <summary>
        /// A callback for the <see cref="TextBoxLine"/> to notify this <see cref="TextBoxLines"/> that the line
        /// was increased in length.
        /// </summary>
        /// <param name="line">The <see cref="TextBoxLine"/> that had text added to it.</param>
        internal void NotifyTextAdded(TextBoxLine line)
        {
            if (_font == null)
                return;

            var width = line.GetWidth(_font);
            if (width <= _maxLineLength)
                return;

            var newLines = StyledText.ToMultiline(line.GetLineTexts, false, _font, _maxLineLength);
            if (newLines.Count <= 1)
                return;

            // Avoid infinite recursion by not updating if the text didn't change
            var first = newLines[0];
            if (first.Sum(x => x.Text.Length) == line.LineText.Length &&
                StyledText.ToString(first).Equals(line.LineText, StringComparison.Ordinal))
                return;

            line.Clear();
            line.Append(newLines[0]);

            var lineIndex = _lines.IndexOf(line);

            if (lineIndex != _lines.Count - 1 && _lines[lineIndex + 1].WasAutoBroken)
            {
                // We're not at the last line AND the next line was auto-split, so keep inserting at the
                // start of the next line in reverse
                for (var i = newLines.Count - 1; i > 0; i--)
                {
                    foreach (var j in newLines[i].Reverse<StyledText>())
                    {
                        _lines[lineIndex + 1].Insert(j, 0);
                    }
                }
            }
            else
            {
                // We're at the last line or the next line was not an auto-split line
                for (var i = 1; i < newLines.Count; i++)
                {
                    var newLine = new TextBoxLine(this, true);
                    newLine.Append(newLines[i]);
                    _lines.Insert(lineIndex + i, newLine);
                }
            }
        }
Beispiel #8
0
 /// <summary>
 /// Inserts a line of text.
 /// </summary>
 /// <param name="lineIndex">The index at which to insert the line.</param>
 /// <param name="line">The <see cref="TextBoxLine"/> describing the line to insert.</param>
 public void Insert(int lineIndex, TextBoxLine line)
 {
     line.TextBoxLines = this;
     _lines.Insert(lineIndex, line);
 }
Beispiel #9
0
 /// <summary>
 /// Inserts a line of text after the line the cursor is currently on.
 /// </summary>
 /// <param name="line">The <see cref="TextBoxLine"/> describing the line to insert.</param>
 public void Insert(TextBoxLine line)
 {
     Insert(CurrentLineIndex + 1, line);
 }
Beispiel #10
0
 /// <summary>
 /// Appends a new line to this <see cref="TextBoxLines"/>.
 /// </summary>
 /// <param name="line">The <see cref="TextBoxLine"/> describing the line to append.</param>
 public void Append(TextBoxLine line)
 {
     line.TextBoxLines = this;
     _lines.Add(line);
 }
Beispiel #11
0
 /// <summary>
 /// Inserts a line of text.
 /// </summary>
 /// <param name="lineIndex">The index at which to insert the line.</param>
 /// <param name="line">The <see cref="TextBoxLine"/> describing the line to insert.</param>
 public void Insert(int lineIndex, TextBoxLine line)
 {
     line.TextBoxLines = this;
     _lines.Insert(lineIndex, line);
 }
Beispiel #12
0
 /// <summary>
 /// Inserts a line of text after the line the cursor is currently on.
 /// </summary>
 /// <param name="line">The <see cref="TextBoxLine"/> describing the line to insert.</param>
 public void Insert(TextBoxLine line)
 {
     Insert(CurrentLineIndex + 1, line);
 }
Beispiel #13
0
 /// <summary>
 /// Appends a new line to this <see cref="TextBoxLines"/>.
 /// </summary>
 /// <param name="line">The <see cref="TextBoxLine"/> describing the line to append.</param>
 public void Append(TextBoxLine line)
 {
     line.TextBoxLines = this;
     _lines.Add(line);
 }
Beispiel #14
0
        /// <summary>
        /// Appends the <paramref name="text"/> to the <see cref="TextBox"/> at the end.
        /// </summary>
        /// <param name="text">The text to append.</param>
        public void Append(StyledText text)
        {
            if (text.Text.Length == 0)
                return;

            if (!IsMultiLine)
                _lines.LastLine.Append(text.ToSingleline());
            else
            {
                var textLines = StyledText.ToMultiline(text);
                _lines.LastLine.Append(textLines[0]);

                for (var i = 1; i < textLines.Count; i++)
                {
                    var newLine = new TextBoxLine(_lines);
                    _lines.Insert(_lines.Count, newLine);
                    newLine.Append(textLines[i]);
                }

                TruncateIfNeeded();
            }

            _numCharsToDraw.Invalidate();

            _hasTextChanged = true;
        }
Beispiel #15
0
        /// <summary>
        /// Appends another <see cref="TextBoxLine"/> to this <see cref="TextBoxLine"/>.
        /// </summary>
        /// <param name="textBoxLine">The other <see cref="TextBoxLine"/> to append to this.</param>
        public void Append(TextBoxLine textBoxLine)
        {
            for (var i = 0; i < textBoxLine._texts.Count; i++)
            {
                InternalAppend(textBoxLine._texts[i]);
            }

            if (TextBoxLines != null)
                TextBoxLines.NotifyTextAdded(this);
        }
Beispiel #16
0
        /// <summary>
        /// Splits the text in this <see cref="TextBoxLine"/> at the given character index in the line.
        /// </summary>
        /// <param name="lineCharacterIndex">The index of the character to split the line at. This character
        /// at this index will be the first character on the new line.</param>
        /// <param name="currentLine">A <see cref="TextBoxLine"/> representing the remainder of the current
        /// line (the one the split initially was made on).</param>
        /// <param name="nextLine">A <see cref="TextBoxLine"/> representing the additional line created
        /// from the split.</param>
        public void SplitAt(int lineCharacterIndex, out TextBoxLine currentLine, out TextBoxLine nextLine)
        {
            if (lineCharacterIndex == 0)
            {
                // Split at the start of the line
                // First line is empty, second line is the full line
                currentLine = new TextBoxLine(TextBoxLines);
                nextLine = this;
                return;
            }
            else if (lineCharacterIndex == LineText.Length)
            {
                // Split at the end of the line
                // First line is the full line, second line is empty
                currentLine = this;
                nextLine = new TextBoxLine(TextBoxLines);
                return;
            }
            else
            {
                // Split up somewhere in the middle

                // Find the StyledText for the character
                StyledText text;
                int textIndex;
                int listIndex;
                FindLineCharacter(lineCharacterIndex, out text, out textIndex, out listIndex);

                // Split the StyledText
                StyledText left;
                StyledText right;
                text.SplitAt(textIndex, out left, out right);

                // The first line will be all the StyledTexts before the one split, plus the left side of the split
                // The second line will be the right side of the split, plus all the StyledTexts after the one split
                currentLine = new TextBoxLine(TextBoxLines);
                for (var i = 0; i < listIndex; i++)
                {
                    currentLine.Append(_texts[i]);
                }
                currentLine.Append(left);

                nextLine = new TextBoxLine(TextBoxLines);
                nextLine.Append(right);
                for (var i = listIndex + 1; i < _texts.Count; i++)
                {
                    nextLine.Append(_texts[i]);
                }
            }
        }