Browse Source

Change TextChangeEventArgs.InsertedText and RemovedText from string to ITextSource.

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
2e63fcd5bf
  1. 20
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeEventArgs.cs
  2. 9
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/LineManager.cs
  3. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/RopeTextSource.cs
  4. 136
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  5. 32
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/IDocument.cs
  6. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs
  7. 26
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/StringBuilderDocument.cs
  8. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/StringTextSource.cs
  9. 30
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs

20
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeEventArgs.cs

@ -71,14 +71,24 @@ namespace ICSharpCode.AvalonEdit.Document
public DocumentChangeEventArgs(int offset, string removedText, string insertedText, OffsetChangeMap offsetChangeMap) public DocumentChangeEventArgs(int offset, string removedText, string insertedText, OffsetChangeMap offsetChangeMap)
: base(offset, removedText, insertedText) : base(offset, removedText, insertedText)
{ {
ThrowUtil.CheckNotNegative(offset, "offset"); SetOffsetChangeMap(offsetChangeMap);
ThrowUtil.CheckNotNull(removedText, "removedText"); }
ThrowUtil.CheckNotNull(insertedText, "insertedText");
/// <summary>
/// Creates a new DocumentChangeEventArgs object.
/// </summary>
public DocumentChangeEventArgs(int offset, ITextSource removedText, ITextSource insertedText, OffsetChangeMap offsetChangeMap)
: base(offset, removedText, insertedText)
{
SetOffsetChangeMap(offsetChangeMap);
}
void SetOffsetChangeMap(OffsetChangeMap offsetChangeMap)
{
if (offsetChangeMap != null) { if (offsetChangeMap != null) {
if (!offsetChangeMap.IsFrozen) if (!offsetChangeMap.IsFrozen)
throw new ArgumentException("The OffsetChangeMap must be frozen before it can be used in DocumentChangeEventArgs"); throw new ArgumentException("The OffsetChangeMap must be frozen before it can be used in DocumentChangeEventArgs");
if (!offsetChangeMap.IsValidForDocumentChange(offset, removedText.Length, insertedText.Length)) if (!offsetChangeMap.IsValidForDocumentChange(this.Offset, this.RemovalLength, this.InsertionLength))
throw new ArgumentException("OffsetChangeMap is not valid for this document change", "offsetChangeMap"); throw new ArgumentException("OffsetChangeMap is not valid for this document change", "offsetChangeMap");
this.offsetChangeMap = offsetChangeMap; this.offsetChangeMap = offsetChangeMap;
} }

9
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/LineManager.cs

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.AvalonEdit.Document namespace ICSharpCode.AvalonEdit.Document
{ {
@ -181,7 +182,7 @@ namespace ICSharpCode.AvalonEdit.Document
#endregion #endregion
#region Insert #region Insert
public void Insert(int offset, string text) public void Insert(int offset, ITextSource text)
{ {
DocumentLine line = documentLineTree.GetByOffset(offset); DocumentLine line = documentLineTree.GetByOffset(offset);
int lineOffset = line.Offset; int lineOffset = line.Offset;
@ -202,7 +203,7 @@ namespace ICSharpCode.AvalonEdit.Document
if (ds == SimpleSegment.Invalid) { if (ds == SimpleSegment.Invalid) {
// no newline is being inserted, all text is inserted in a single line // no newline is being inserted, all text is inserted in a single line
//line.InsertedLinePart(offset - line.Offset, text.Length); //line.InsertedLinePart(offset - line.Offset, text.Length);
SetLineLength(line, line.TotalLength + text.Length); SetLineLength(line, line.TotalLength + text.TextLength);
return; return;
} }
//DocumentLine firstLine = line; //DocumentLine firstLine = line;
@ -224,9 +225,9 @@ namespace ICSharpCode.AvalonEdit.Document
} }
//firstLine.SplitTo(line); //firstLine.SplitTo(line);
// insert rest after last delimiter // insert rest after last delimiter
if (lastDelimiterEnd != text.Length) { if (lastDelimiterEnd != text.TextLength) {
//line.InsertedLinePart(0, text.Length - lastDelimiterEnd); //line.InsertedLinePart(0, text.Length - lastDelimiterEnd);
SetLineLength(line, line.TotalLength + text.Length - lastDelimiterEnd); SetLineLength(line, line.TotalLength + text.TextLength - lastDelimiterEnd);
} }
} }

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/RopeTextSource.cs

@ -11,6 +11,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <summary> /// <summary>
/// Implements the ITextSource interface using a rope. /// Implements the ITextSource interface using a rope.
/// </summary> /// </summary>
[Serializable]
public sealed class RopeTextSource : ITextSource public sealed class RopeTextSource : ITextSource
{ {
readonly Rope<char> rope; readonly Rope<char> rope;

136
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -524,6 +524,21 @@ namespace ICSharpCode.AvalonEdit.Document
/// The caret will also move behind the inserted text. /// The caret will also move behind the inserted text.
/// </remarks> /// </remarks>
public void Insert(int offset, string text) public void Insert(int offset, string text)
{
Replace(offset, 0, new StringTextSource(text), null);
}
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <remarks>
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
/// For AnchorMovementType.Default, they will move behind the inserted text.
/// The caret will also move behind the inserted text.
/// </remarks>
public void Insert(int offset, ITextSource text)
{ {
Replace(offset, 0, text, null); Replace(offset, 0, text, null);
} }
@ -539,6 +554,25 @@ namespace ICSharpCode.AvalonEdit.Document
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter. /// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param> /// </param>
public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType) public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{
if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion) {
Replace(offset, 0, new StringTextSource(text), OffsetChangeMappingType.KeepAnchorBeforeInsertion);
} else {
Replace(offset, 0, new StringTextSource(text), null);
}
}
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <param name="defaultAnchorMovementType">
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param>
public void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{ {
if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion) { if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion) {
Replace(offset, 0, text, OffsetChangeMappingType.KeepAnchorBeforeInsertion); Replace(offset, 0, text, OffsetChangeMappingType.KeepAnchorBeforeInsertion);
@ -562,7 +596,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <param name="length">Length of the text to be removed.</param> /// <param name="length">Length of the text to be removed.</param>
public void Remove(int offset, int length) public void Remove(int offset, int length)
{ {
Replace(offset, length, string.Empty); Replace(offset, length, StringTextSource.Empty);
} }
internal bool inDocumentChanging; internal bool inDocumentChanging;
@ -571,6 +605,16 @@ namespace ICSharpCode.AvalonEdit.Document
/// Replaces text. /// Replaces text.
/// </summary> /// </summary>
public void Replace(ISegment segment, string text) public void Replace(ISegment segment, string text)
{
if (segment == null)
throw new ArgumentNullException("segment");
Replace(segment.Offset, segment.Length, new StringTextSource(text), null);
}
/// <summary>
/// Replaces text.
/// </summary>
public void Replace(ISegment segment, ITextSource text)
{ {
if (segment == null) if (segment == null)
throw new ArgumentNullException("segment"); throw new ArgumentNullException("segment");
@ -584,6 +628,17 @@ namespace ICSharpCode.AvalonEdit.Document
/// <param name="length">The length of the text to be replaced.</param> /// <param name="length">The length of the text to be replaced.</param>
/// <param name="text">The new text.</param> /// <param name="text">The new text.</param>
public void Replace(int offset, int length, string text) public void Replace(int offset, int length, string text)
{
Replace(offset, length, new StringTextSource(text), null);
}
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="text">The new text.</param>
public void Replace(int offset, int length, ITextSource text)
{ {
Replace(offset, length, text, null); Replace(offset, length, text, null);
} }
@ -597,6 +652,19 @@ namespace ICSharpCode.AvalonEdit.Document
/// <param name="offsetChangeMappingType">The offsetChangeMappingType determines how offsets inside the old text are mapped to the new text. /// <param name="offsetChangeMappingType">The offsetChangeMappingType determines how offsets inside the old text are mapped to the new text.
/// This affects how the anchors and segments inside the replaced region behave.</param> /// This affects how the anchors and segments inside the replaced region behave.</param>
public void Replace(int offset, int length, string text, OffsetChangeMappingType offsetChangeMappingType) public void Replace(int offset, int length, string text, OffsetChangeMappingType offsetChangeMappingType)
{
Replace(offset, length, new StringTextSource(text), offsetChangeMappingType);
}
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="text">The new text.</param>
/// <param name="offsetChangeMappingType">The offsetChangeMappingType determines how offsets inside the old text are mapped to the new text.
/// This affects how the anchors and segments inside the replaced region behave.</param>
public void Replace(int offset, int length, ITextSource text, OffsetChangeMappingType offsetChangeMappingType)
{ {
if (text == null) if (text == null)
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
@ -607,33 +675,33 @@ namespace ICSharpCode.AvalonEdit.Document
break; break;
case OffsetChangeMappingType.KeepAnchorBeforeInsertion: case OffsetChangeMappingType.KeepAnchorBeforeInsertion:
Replace(offset, length, text, OffsetChangeMap.FromSingleElement( Replace(offset, length, text, OffsetChangeMap.FromSingleElement(
new OffsetChangeMapEntry(offset, length, text.Length, false, true))); new OffsetChangeMapEntry(offset, length, text.TextLength, false, true)));
break; break;
case OffsetChangeMappingType.RemoveAndInsert: case OffsetChangeMappingType.RemoveAndInsert:
if (length == 0 || text.Length == 0) { if (length == 0 || text.TextLength == 0) {
// only insertion or only removal? // only insertion or only removal?
// OffsetChangeMappingType doesn't matter, just use Normal. // OffsetChangeMappingType doesn't matter, just use Normal.
Replace(offset, length, text, null); Replace(offset, length, text, null);
} else { } else {
OffsetChangeMap map = new OffsetChangeMap(2); OffsetChangeMap map = new OffsetChangeMap(2);
map.Add(new OffsetChangeMapEntry(offset, length, 0)); map.Add(new OffsetChangeMapEntry(offset, length, 0));
map.Add(new OffsetChangeMapEntry(offset, 0, text.Length)); map.Add(new OffsetChangeMapEntry(offset, 0, text.TextLength));
map.Freeze(); map.Freeze();
Replace(offset, length, text, map); Replace(offset, length, text, map);
} }
break; break;
case OffsetChangeMappingType.CharacterReplace: case OffsetChangeMappingType.CharacterReplace:
if (length == 0 || text.Length == 0) { if (length == 0 || text.TextLength == 0) {
// only insertion or only removal? // only insertion or only removal?
// OffsetChangeMappingType doesn't matter, just use Normal. // OffsetChangeMappingType doesn't matter, just use Normal.
Replace(offset, length, text, null); Replace(offset, length, text, null);
} else if (text.Length > length) { } else if (text.TextLength > length) {
// look at OffsetChangeMappingType.CharacterReplace XML comments on why we need to replace // look at OffsetChangeMappingType.CharacterReplace XML comments on why we need to replace
// the last character // the last character
OffsetChangeMapEntry entry = new OffsetChangeMapEntry(offset + length - 1, 1, 1 + text.Length - length); OffsetChangeMapEntry entry = new OffsetChangeMapEntry(offset + length - 1, 1, 1 + text.TextLength - length);
Replace(offset, length, text, OffsetChangeMap.FromSingleElement(entry)); Replace(offset, length, text, OffsetChangeMap.FromSingleElement(entry));
} else if (text.Length < length) { } else if (text.TextLength < length) {
OffsetChangeMapEntry entry = new OffsetChangeMapEntry(offset + text.Length, length - text.Length, 0, true, false); OffsetChangeMapEntry entry = new OffsetChangeMapEntry(offset + text.TextLength, length - text.TextLength, 0, true, false);
Replace(offset, length, text, OffsetChangeMap.FromSingleElement(entry)); Replace(offset, length, text, OffsetChangeMap.FromSingleElement(entry));
} else { } else {
Replace(offset, length, text, OffsetChangeMap.Empty); Replace(offset, length, text, OffsetChangeMap.Empty);
@ -660,10 +728,30 @@ namespace ICSharpCode.AvalonEdit.Document
/// DocumentChangeEventArgs instance. /// DocumentChangeEventArgs instance.
/// </param> /// </param>
public void Replace(int offset, int length, string text, OffsetChangeMap offsetChangeMap) public void Replace(int offset, int length, string text, OffsetChangeMap offsetChangeMap)
{
Replace(offset, length, new StringTextSource(text), offsetChangeMap);
}
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="text">The new text.</param>
/// <param name="offsetChangeMap">The offsetChangeMap determines how offsets inside the old text are mapped to the new text.
/// This affects how the anchors and segments inside the replaced region behave.
/// If you pass null (the default when using one of the other overloads), the offsets are changed as
/// in OffsetChangeMappingType.Normal mode.
/// If you pass OffsetChangeMap.Empty, then everything will stay in its old place (OffsetChangeMappingType.CharacterReplace mode).
/// The offsetChangeMap must be a valid 'explanation' for the document change. See <see cref="OffsetChangeMap.IsValidForDocumentChange"/>.
/// Passing an OffsetChangeMap to the Replace method will automatically freeze it to ensure the thread safety of the resulting
/// DocumentChangeEventArgs instance.
/// </param>
public void Replace(int offset, int length, ITextSource text, OffsetChangeMap offsetChangeMap)
{ {
if (text == null) if (text == null)
throw new ArgumentNullException("text"); throw new ArgumentNullException("text");
text = text.CreateSnapshot();
if (offsetChangeMap != null) if (offsetChangeMap != null)
offsetChangeMap.Freeze(); offsetChangeMap.Freeze();
@ -687,18 +775,26 @@ namespace ICSharpCode.AvalonEdit.Document
} }
} }
void DoReplace(int offset, int length, string newText, OffsetChangeMap offsetChangeMap) void DoReplace(int offset, int length, ITextSource newText, OffsetChangeMap offsetChangeMap)
{ {
if (length == 0 && newText.Length == 0) if (length == 0 && newText.TextLength == 0)
return; return;
// trying to replace a single character in 'Normal' mode? // trying to replace a single character in 'Normal' mode?
// for single characters, 'CharacterReplace' mode is equivalent, but more performant // for single characters, 'CharacterReplace' mode is equivalent, but more performant
// (we don't have to touch the anchorTree at all in 'CharacterReplace' mode) // (we don't have to touch the anchorTree at all in 'CharacterReplace' mode)
if (length == 1 && newText.Length == 1 && offsetChangeMap == null) if (length == 1 && newText.TextLength == 1 && offsetChangeMap == null)
offsetChangeMap = OffsetChangeMap.Empty; offsetChangeMap = OffsetChangeMap.Empty;
string removedText = rope.ToString(offset, length); ITextSource removedText;
if (length == 0) {
removedText = StringTextSource.Empty;
} else if (length < 100) {
removedText = new StringTextSource(rope.ToString(offset, length));
} else {
// use a rope if the removed string is long
removedText = new RopeTextSource(rope.GetRange(offset, length));
}
DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, removedText, newText, offsetChangeMap); DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, removedText, newText, offsetChangeMap);
// fire DocumentChanging event // fire DocumentChanging event
@ -721,7 +817,11 @@ namespace ICSharpCode.AvalonEdit.Document
if (offset == 0 && length == rope.Length) { if (offset == 0 && length == rope.Length) {
// optimize replacing the whole document // optimize replacing the whole document
rope.Clear(); rope.Clear();
rope.InsertText(0, newText); var newRopeTextSource = newText as RopeTextSource;
if (newRopeTextSource != null)
rope.InsertRange(0, newRopeTextSource.GetRope());
else
rope.InsertText(0, newText.Text);
lineManager.Rebuild(); lineManager.Rebuild();
} else { } else {
rope.RemoveRange(offset, length); rope.RemoveRange(offset, length);
@ -729,7 +829,11 @@ namespace ICSharpCode.AvalonEdit.Document
#if DEBUG #if DEBUG
lineTree.CheckProperties(); lineTree.CheckProperties();
#endif #endif
rope.InsertText(offset, newText); var newRopeTextSource = newText as RopeTextSource;
if (newRopeTextSource != null)
rope.InsertRange(offset, newRopeTextSource.GetRope());
else
rope.InsertText(offset, newText.Text);
lineManager.Insert(offset, newText); lineManager.Insert(offset, newText);
#if DEBUG #if DEBUG
lineTree.CheckProperties(); lineTree.CheckProperties();

32
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/IDocument.cs

@ -109,6 +109,18 @@ namespace ICSharpCode.NRefactory.Editor
/// </remarks> /// </remarks>
void Insert(int offset, string text); void Insert(int offset, string text);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <remarks>
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
/// For AnchorMovementType.Default, they will move behind the inserted text.
/// The caret will also move behind the inserted text.
/// </remarks>
void Insert(int offset, ITextSource text);
/// <summary> /// <summary>
/// Inserts text. /// Inserts text.
/// </summary> /// </summary>
@ -121,6 +133,18 @@ namespace ICSharpCode.NRefactory.Editor
/// </param> /// </param>
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType); void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <param name="defaultAnchorMovementType">
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param>
void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType);
/// <summary> /// <summary>
/// Removes text. /// Removes text.
/// </summary> /// </summary>
@ -136,6 +160,14 @@ namespace ICSharpCode.NRefactory.Editor
/// <param name="newText">The new text.</param> /// <param name="newText">The new text.</param>
void Replace(int offset, int length, string newText); void Replace(int offset, int length, string newText);
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="newText">The new text.</param>
void Replace(int offset, int length, ITextSource newText);
/// <summary> /// <summary>
/// Make the document combine the following actions into a single /// Make the document combine the following actions into a single
/// action for undo purposes. /// action for undo purposes.

15
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs

@ -257,6 +257,21 @@ namespace ICSharpCode.NRefactory.Editor
throw new NotSupportedException(); throw new NotSupportedException();
} }
void IDocument.Insert(int offset, ITextSource text)
{
throw new NotImplementedException();
}
void IDocument.Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{
throw new NotImplementedException();
}
void IDocument.Replace(int offset, int length, ITextSource newText)
{
throw new NotImplementedException();
}
void IDocument.StartUndoableAction() void IDocument.StartUndoableAction()
{ {
} }

26
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/StringBuilderDocument.cs

@ -104,17 +104,35 @@ namespace ICSharpCode.NRefactory.Editor
Replace(offset, 0, text); Replace(offset, 0, text);
} }
/// <inheritdoc/>
public void Insert(int offset, ITextSource text)
{
if (text == null)
throw new ArgumentNullException("text");
Replace(offset, 0, text.Text);
}
/// <inheritdoc/> /// <inheritdoc/>
public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType) public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{ {
if (offset < 0 || offset > this.TextLength) if (offset < 0 || offset > this.TextLength)
throw new ArgumentOutOfRangeException("offset"); throw new ArgumentOutOfRangeException("offset");
if (text == null)
throw new ArgumentNullException("text");
if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion) if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion)
PerformChange(new InsertionWithMovementBefore(offset, text)); PerformChange(new InsertionWithMovementBefore(offset, text));
else else
Replace(offset, 0, text); Replace(offset, 0, text);
} }
/// <inheritdoc/>
public void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{
if (text == null)
throw new ArgumentNullException("text");
Insert(offset, text.Text, defaultAnchorMovementType);
}
[Serializable] [Serializable]
sealed class InsertionWithMovementBefore : TextChangeEventArgs sealed class InsertionWithMovementBefore : TextChangeEventArgs
{ {
@ -149,6 +167,14 @@ namespace ICSharpCode.NRefactory.Editor
PerformChange(new TextChangeEventArgs(offset, b.ToString(offset, length), newText)); PerformChange(new TextChangeEventArgs(offset, b.ToString(offset, length), newText));
} }
/// <inheritdoc/>
public void Replace(int offset, int length, ITextSource newText)
{
if (newText == null)
throw new ArgumentNullException("newText");
Replace(offset, length, newText.Text);
}
bool isInChange; bool isInChange;
void PerformChange(TextChangeEventArgs change) void PerformChange(TextChangeEventArgs change)

7
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/StringTextSource.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.Editor
[Serializable] [Serializable]
public class StringTextSource : ITextSource public class StringTextSource : ITextSource
{ {
/// <summary>
/// Gets a text source containing the empty string.
/// </summary>
public static readonly StringTextSource Empty = new StringTextSource(string.Empty);
readonly string text; readonly string text;
readonly ITextSourceVersion version; readonly ITextSourceVersion version;
@ -69,7 +74,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <inheritdoc/> /// <inheritdoc/>
public ITextSource CreateSnapshot() public ITextSource CreateSnapshot()
{ {
return this; // StringTextBuffer is immutable return this; // StringTextSource is immutable
} }
/// <inheritdoc/> /// <inheritdoc/>

30
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs

@ -28,8 +28,8 @@ namespace ICSharpCode.NRefactory.Editor
public class TextChangeEventArgs : EventArgs public class TextChangeEventArgs : EventArgs
{ {
readonly int offset; readonly int offset;
readonly string removedText; readonly ITextSource removedText;
readonly string insertedText; readonly ITextSource insertedText;
/// <summary> /// <summary>
/// The offset at which the change occurs. /// The offset at which the change occurs.
@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <summary> /// <summary>
/// The text that was removed. /// The text that was removed.
/// </summary> /// </summary>
public string RemovedText { public ITextSource RemovedText {
get { return removedText; } get { return removedText; }
} }
@ -49,13 +49,13 @@ namespace ICSharpCode.NRefactory.Editor
/// The number of characters removed. /// The number of characters removed.
/// </summary> /// </summary>
public int RemovalLength { public int RemovalLength {
get { return removedText.Length; } get { return removedText.TextLength; }
} }
/// <summary> /// <summary>
/// The text that was inserted. /// The text that was inserted.
/// </summary> /// </summary>
public string InsertedText { public ITextSource InsertedText {
get { return insertedText; } get { return insertedText; }
} }
@ -63,7 +63,7 @@ namespace ICSharpCode.NRefactory.Editor
/// The number of characters inserted. /// The number of characters inserted.
/// </summary> /// </summary>
public int InsertionLength { public int InsertionLength {
get { return insertedText.Length; } get { return insertedText.TextLength; }
} }
/// <summary> /// <summary>
@ -71,9 +71,23 @@ namespace ICSharpCode.NRefactory.Editor
/// </summary> /// </summary>
public TextChangeEventArgs(int offset, string removedText, string insertedText) public TextChangeEventArgs(int offset, string removedText, string insertedText)
{ {
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "offset must not be negative");
this.offset = offset; this.offset = offset;
this.removedText = removedText ?? string.Empty; this.removedText = removedText != null ? new StringTextSource(removedText) : StringTextSource.Empty;
this.insertedText = insertedText ?? string.Empty; this.insertedText = insertedText != null ? new StringTextSource(insertedText) : StringTextSource.Empty;
}
/// <summary>
/// Creates a new TextChangeEventArgs object.
/// </summary>
public TextChangeEventArgs(int offset, ITextSource removedText, ITextSource insertedText)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "offset must not be negative");
this.offset = offset;
this.removedText = removedText ?? StringTextSource.Empty;
this.insertedText = insertedText ?? StringTextSource.Empty;
} }
/// <summary> /// <summary>

Loading…
Cancel
Save