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