diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextAnchorTree.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextAnchorTree.cs
index f45d50ba50..e2b6f5f430 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextAnchorTree.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextAnchorTree.cs
@@ -37,7 +37,7 @@ namespace ICSharpCode.AvalonEdit.Document
#region Insert Text
public void InsertText(int offset, int length)
{
- Log("InsertText(" + offset + ", " + length + ")");
+ //Log("InsertText(" + offset + ", " + length + ")");
if (length == 0 || root == null || offset > root.totalLength)
return;
@@ -139,7 +139,7 @@ namespace ICSharpCode.AvalonEdit.Document
#region Remove Text
public void RemoveText(int offset, int length, DelayedEvents delayedEvents)
{
- Log("RemoveText(" + offset + ", " + length + ")");
+ //Log("RemoveText(" + offset + ", " + length + ")");
if (length == 0 || root == null || offset >= root.totalLength)
return;
TextAnchorNode node = FindNode(ref offset);
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/FoldingMargin.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/FoldingMargin.cs
index fa5db5d058..98832cbcde 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/FoldingMargin.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/FoldingMargin.cs
@@ -75,7 +75,7 @@ namespace ICSharpCode.AvalonEdit.Gui
}
markers.Clear();
InvalidateVisual();
- if (TextView != null && FoldingManager != null) {
+ if (TextView != null && FoldingManager != null && TextView.VisualLinesValid) {
foreach (VisualLine line in TextView.VisualLines) {
FoldingSection fs = FoldingManager.GetNextFolding(line.FirstDocumentLine.Offset);
if (fs == null)
@@ -113,6 +113,8 @@ namespace ICSharpCode.AvalonEdit.Gui
///
protected override void OnRender(DrawingContext drawingContext)
{
+ if (!TextView.VisualLinesValid)
+ return;
if (TextView.VisualLines.Count == 0 || FoldingManager == null)
return;
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/LineNumberMargin.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/LineNumberMargin.cs
index 54d3dfc28c..b6c49ee39d 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/LineNumberMargin.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/LineNumberMargin.cs
@@ -69,7 +69,7 @@ namespace ICSharpCode.AvalonEdit.Gui
{
TextView textView = this.TextView;
Size renderSize = this.RenderSize;
- if (textView != null) {
+ if (textView != null && textView.VisualLinesValid) {
var foreground = (Brush)GetValue(Control.ForegroundProperty);
foreach (VisualLine line in textView.VisualLines) {
int lineNumber = line.FirstDocumentLine.LineNumber;
@@ -170,7 +170,6 @@ namespace ICSharpCode.AvalonEdit.Gui
SimpleSegment GetTextLineSegment(MouseEventArgs e)
{
- TextView.EnsureVisualLines();
Point pos = e.GetPosition(TextView);
pos.X = 0;
pos.Y += TextView.VerticalOffset;
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/SelectionMouseHandler.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/SelectionMouseHandler.cs
index 92ace40aa1..567d398f21 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/SelectionMouseHandler.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/SelectionMouseHandler.cs
@@ -154,7 +154,10 @@ namespace ICSharpCode.AvalonEdit.Gui
if (mode != SelectionMode.None || !AllowTextDragDrop) {
e.Cursor = Cursors.IBeam;
e.Handled = true;
- } else {
+ } else if (textArea.TextView.VisualLinesValid) {
+ // Only query the cursor if the visual lines are valid.
+ // If they are invalid, the cursor will get re-queried when the visual lines
+ // get refreshed.
Point p = e.GetPosition(textArea.TextView);
if (p.X >= 0 && p.Y >= 0 && p.X <= textArea.TextView.ActualWidth && p.Y <= textArea.TextView.ActualHeight) {
int visualColumn;
@@ -281,7 +284,6 @@ namespace ICSharpCode.AvalonEdit.Gui
{
TextView textView = textArea.TextView;
if (textView == null) return SimpleSegment.Invalid;
- textView.EnsureVisualLines();
Point pos = e.GetPosition(textView);
if (pos.Y < 0)
pos.Y = 0;
@@ -325,7 +327,6 @@ namespace ICSharpCode.AvalonEdit.Gui
{
visualColumn = 0;
TextView textView = textArea.TextView;
- textView.EnsureVisualLines();
Point pos = positionRelativeToTextView;
if (pos.Y < 0)
pos.Y = 0;
@@ -348,17 +349,11 @@ namespace ICSharpCode.AvalonEdit.Gui
return;
if (mode == SelectionMode.Normal || mode == SelectionMode.WholeWord) {
e.Handled = true;
- int oldOffset = textArea.Caret.Offset;
- SetCaretOffsetToMousePosition(e);
- if (mode == SelectionMode.Normal) {
- textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldOffset, textArea.Caret.Offset);
- } else if (mode == SelectionMode.WholeWord) {
- var newWord = GetWordAtMousePosition(e);
- if (newWord != SimpleSegment.Invalid) {
- textArea.Selection = new SimpleSelection(
- Math.Min(newWord.Offset, startWord.Offset),
- Math.Max(newWord.GetEndOffset(), startWord.GetEndOffset()));
- }
+ if (textArea.TextView.VisualLinesValid) {
+ // If the visual lines are not valid, don't extend the selection.
+ // Extending the selection forces a VisualLine refresh, and it is sufficient
+ // to do that on MouseUp, we don't have to do it every MouseMove.
+ ExtendSelectionToMouse(e);
}
} else if (mode == SelectionMode.PossibleDragStart) {
e.Handled = true;
@@ -371,6 +366,20 @@ namespace ICSharpCode.AvalonEdit.Gui
}
}
+ void ExtendSelectionToMouse(MouseEventArgs e)
+ {
+ int oldOffset = textArea.Caret.Offset;
+ SetCaretOffsetToMousePosition(e);
+ if (mode == SelectionMode.Normal) {
+ textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldOffset, textArea.Caret.Offset);
+ } else if (mode == SelectionMode.WholeWord) {
+ var newWord = GetWordAtMousePosition(e);
+ if (newWord != SimpleSegment.Invalid) {
+ textArea.Selection = new SimpleSelection(Math.Min(newWord.Offset, startWord.Offset), Math.Max(newWord.GetEndOffset(), startWord.GetEndOffset()));
+ }
+ }
+ }
+
void textArea_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (mode == SelectionMode.None || e.Handled)
@@ -380,6 +389,8 @@ namespace ICSharpCode.AvalonEdit.Gui
// -> this was not a drag start (mouse didn't move after mousedown)
SetCaretOffsetToMousePosition(e);
textArea.Selection = Selection.Empty;
+ } else if (mode == SelectionMode.Normal || mode == SelectionMode.WholeWord) {
+ ExtendSelectionToMouse(e);
}
mode = SelectionMode.None;
textArea.ReleaseMouseCapture();
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs
index 7400e4fb67..54ca9e2b30 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs
@@ -99,6 +99,9 @@ namespace ICSharpCode.AvalonEdit
value = string.Empty;
TextDocument document = GetOrCreateDocument();
document.Text = value;
+ // after replacing the full text, the caret is positioned at the end of the document
+ // - reset it to the beginning.
+ this.CaretOffset = 0;
document.UndoStack.ClearAll();
}
}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextView.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextView.cs
index 4af9fe4666..898c57ac7b 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextView.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextView.cs
@@ -242,17 +242,15 @@ namespace ICSharpCode.AvalonEdit.Gui
///
/// Waits for the visual lines to be built.
- /// Warning: this methods runs all operations with priority >= Render
///
- public void EnsureVisualLines()
+ private void EnsureVisualLines()
{
Dispatcher.VerifyAccess();
if (visibleVisualLines == null) {
- if (invalidateMeasureOperation != null) {
- // increase priority
- InvalidateMeasure(DispatcherPriority.Normal);
- }
- Dispatcher.DoEvents(DispatcherPriority.Render);
+ // increase priority for real Redraw
+ InvalidateMeasure(DispatcherPriority.Normal);
+ // force immediate re-measure
+ UpdateLayout();
}
}
@@ -285,7 +283,7 @@ namespace ICSharpCode.AvalonEdit.Gui
///
public VisualLine GetVisualLine(int documentLineNumber)
{
- VerifyAccess();
+ // TODO: EnsureVisualLines() ?
foreach (VisualLine visualLine in allVisualLines) {
Debug.Assert(visualLine.IsDisposed == false);
int start = visualLine.FirstDocumentLine.LineNumber;
@@ -355,15 +353,23 @@ namespace ICSharpCode.AvalonEdit.Gui
///
/// Gets the currently visible visual lines.
- /// Is empty when the visual lines are not available
- /// (when one or more of the visual lines need to be regenerated).
///
public ReadOnlyCollection VisualLines {
get {
- return visibleVisualLines ?? Empty.ReadOnlyCollection;
+ EnsureVisualLines();
+ return visibleVisualLines;
}
}
+ ///
+ /// Gets whether the visual lines are valid.
+ /// Will return false after a call to Redraw(). Accessing the visual lines property
+ /// will force immediate regeneration of valid lines.
+ ///
+ public bool VisualLinesValid {
+ get { return visibleVisualLines != null; }
+ }
+
///
/// Occurs when the TextView was measured and changed its visual lines.
///
@@ -398,10 +404,21 @@ namespace ICSharpCode.AvalonEdit.Gui
{
if (!canHorizontallyScroll && !availableSize.Width.IsClose(lastAvailableSize.Width))
ClearVisualLines();
-
- RemoveInlineObjectsNow();
-
lastAvailableSize = availableSize;
+ return DoMeasure(availableSize);
+ }
+
+ ///
+ /// Immediately performs the text creation.
+ ///
+ /// The size of the text view.
+ ///
+ Size DoMeasure(Size availableSize)
+ {
+ bool isRealMeasure = true;
+ if (isRealMeasure)
+ RemoveInlineObjectsNow();
+
if (document == null)
return Size.Empty;
@@ -455,7 +472,8 @@ namespace ICSharpCode.AvalonEdit.Gui
if (!newVisualLines.Contains(line))
DisposeVisualLine(line);
}
- RemoveInlineObjectsNow();
+ if (isRealMeasure)
+ RemoveInlineObjectsNow();
allVisualLines = newVisualLines;
// visibleVisualLines = readonly copy of visual lines
@@ -1032,7 +1050,6 @@ namespace ICSharpCode.AvalonEdit.Gui
///
public VisualLine GetVisualLineFromVisualTop(double visualTop)
{
- VerifyAccess();
foreach (VisualLine vl in this.VisualLines) {
if (visualTop < vl.VisualTop)
continue;
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColor.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColor.cs
index b94adfec1f..26caf1ec1e 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColor.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColor.cs
@@ -34,6 +34,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
///
/// Gets CSS code for the color.
///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "CSS usually uses lowercase, and all possible values are English-only")]
public virtual string ToCss()
{
StringBuilder b = new StringBuilder();
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/SaveXshdVisitor.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/SaveXshdVisitor.cs
index 326899097b..ee3ff97214 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/SaveXshdVisitor.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/Xshd/SaveXshdVisitor.cs
@@ -94,6 +94,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting.Xshd
}
}
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "The file format requires lowercase, and all possible values are English-only")]
void WriteColorAttributes(XshdColor color)
{
if (color.Foreground != null)
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
index ed5d8d5318..283e1c5137 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
@@ -18,7 +18,7 @@
False
File
False
- -Microsoft.Design#CA1020;-Microsoft.Design#CA1033;-Microsoft.Globalization#CA1308
+ -Microsoft.Design#CA1020;-Microsoft.Design#CA1033
..\..\..\..\bin\
..\..\..\..\bin\ICSharpCode.AvalonEdit.xml
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/ExtensionMethods.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/ExtensionMethods.cs
index bb1d97deea..ae63748225 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/ExtensionMethods.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/ExtensionMethods.cs
@@ -58,22 +58,6 @@ namespace ICSharpCode.AvalonEdit.Utils
(FontStretch)fe.GetValue(TextBlock.FontStretchProperty));
}
- ///
- /// Runs all outstanding dispatcher tasks with a priority higher or equal to .
- ///
- public static void DoEvents(this Dispatcher dispatcher, DispatcherPriority priority)
- {
- dispatcher.VerifyAccess();
- DispatcherFrame frame = new DispatcherFrame();
- dispatcher.BeginInvoke(
- priority, new DispatcherOperationCallback(
- delegate {
- frame.Continue = false;
- return null;
- }), null);
- Dispatcher.PushFrame(frame);
- }
-
public static void AddRange(this ICollection collection, IEnumerable elements)
{
foreach (T e in elements)