Browse Source

Rewritten TextView.PaintLinePart. Text markers now can start or end inside TextWords; the highlight marker now can be placed inside a TextWord.

Fixes SD2-667: Text marker colour bleeds into tabs following text

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1436 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
e56e0f6f8a
  1. 4
      src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs
  2. 2
      src/AddIns/Misc/HighlightingEditor/Project/Src/EditorHighlightColor.cs
  3. 16
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs
  4. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs
  5. 22
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs
  6. 24
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs
  7. 20
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs
  8. 2
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs
  9. 303
      src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs
  10. 16
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/ErrorDrawer.cs

4
src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageHighlighter.cs

@ -40,14 +40,14 @@ namespace ICSharpCode.CodeCoverage @@ -40,14 +40,14 @@ namespace ICSharpCode.CodeCoverage
if (sequencePoint.EndLine == sequencePoint.Line) {
LineSegment lineSegment = markerStrategy.Document.GetLineSegment(sequencePoint.Line - 1);
markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column, sequencePoint));
markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column - 1, sequencePoint));
} else {
// Sequence point spread across lines.
for (int line = sequencePoint.Line; line <= sequencePoint.EndLine; ++line) {
LineSegment lineSegment = markerStrategy.Document.GetLineSegment(line - 1);
if (line == sequencePoint.Line) {
// First line.
markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column, lineSegment.Length - (lineSegment.DelimiterLength - 1) - sequencePoint.Column, sequencePoint));
markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset + sequencePoint.Column - 1, lineSegment.Length - (lineSegment.DelimiterLength - 1) - sequencePoint.Column, sequencePoint));
} else if (line == sequencePoint.EndLine) {
// Last line.
markerStrategy.AddMarker(new CodeCoverageTextMarker(lineSegment.Offset, sequencePoint.EndColumn - 1, sequencePoint));

2
src/AddIns/Misc/HighlightingEditor/Project/Src/EditorHighlightColor.cs

@ -148,7 +148,7 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes @@ -148,7 +148,7 @@ namespace ICSharpCode.SharpDevelop.AddIns.HighlightingEditor.Nodes
public static EditorHighlightColor FromTextEditor(ICSharpCode.TextEditor.Document.HighlightColor color)
{
return new EditorHighlightColor(color.HasForgeground, color.Color, color.HasBackground, color.BackgroundColor, color.Bold, color.Italic);
return new EditorHighlightColor(color.HasForeground, color.Color, color.HasBackground, color.BackgroundColor, color.Bold, color.Italic);
}
public EditorHighlightColor(bool hascolor, Color Color, bool hasbackcolor, Color BackColor, bool bold, bool italic)

16
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/HighlightColor.cs

@ -33,12 +33,12 @@ namespace ICSharpCode.TextEditor.Document @@ -33,12 +33,12 @@ namespace ICSharpCode.TextEditor.Document
bool bold = false;
bool italic = false;
bool hasForgeground = false;
bool hasForeground = false;
bool hasBackground = false;
public bool HasForgeground {
public bool HasForeground {
get {
return hasForgeground;
return hasForeground;
}
}
@ -144,7 +144,7 @@ namespace ICSharpCode.TextEditor.Document @@ -144,7 +144,7 @@ namespace ICSharpCode.TextEditor.Document
} else {
color = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]);
}
hasForgeground = true;
hasForeground = true;
} else {
color = Color.Transparent; // to set it to the default value.
}
@ -191,7 +191,7 @@ namespace ICSharpCode.TextEditor.Document @@ -191,7 +191,7 @@ namespace ICSharpCode.TextEditor.Document
} else {
color = (Color)(Color.GetType()).InvokeMember(c, BindingFlags.GetProperty, null, Color, new object[0]);
}
hasForgeground = true;
hasForeground = true;
} else {
color = defaultColor.color;
}
@ -217,7 +217,7 @@ namespace ICSharpCode.TextEditor.Document @@ -217,7 +217,7 @@ namespace ICSharpCode.TextEditor.Document
/// </summary>
public HighlightColor(Color color, bool bold, bool italic)
{
hasForgeground = true;
hasForeground = true;
this.color = color;
this.bold = bold;
this.italic = italic;
@ -228,7 +228,7 @@ namespace ICSharpCode.TextEditor.Document @@ -228,7 +228,7 @@ namespace ICSharpCode.TextEditor.Document
/// </summary>
public HighlightColor(Color color, Color backgroundcolor, bool bold, bool italic)
{
hasForgeground = true;
hasForeground = true;
hasBackground = true;
this.color = color;
this.backgroundcolor = backgroundcolor;
@ -242,7 +242,7 @@ namespace ICSharpCode.TextEditor.Document @@ -242,7 +242,7 @@ namespace ICSharpCode.TextEditor.Document
/// </summary>
public HighlightColor(string systemColor, string systemBackgroundColor, bool bold, bool italic)
{
hasForgeground = true;
hasForeground = true;
hasBackground = true;
this.systemColor = true;

2
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/SpanStack.cs

@ -77,7 +77,7 @@ namespace ICSharpCode.TextEditor.Document @@ -77,7 +77,7 @@ namespace ICSharpCode.TextEditor.Document
return this.GetEnumerator();
}
public sealed class Enumerator : IEnumerator<Span>
public struct Enumerator : IEnumerator<Span>
{
StackNode c;

22
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/HighlightingStrategy/TextWord.cs

@ -120,6 +120,25 @@ namespace ICSharpCode.TextEditor.Document @@ -120,6 +120,25 @@ namespace ICSharpCode.TextEditor.Document
}
}
/// <summary>
/// Splits the <paramref name="word"/> into two parts: the part before <paramref name="pos"/> is assigned to
/// the reference parameter <paramref name="word"/>, the part after <paramref name="pos"/> is returned.
/// </summary>
public static TextWord Split(ref TextWord word, int pos)
{
#if DEBUG
if (word.Type != TextWordType.Word)
throw new ArgumentException("word.Type must be Word");
if (pos <= 0)
throw new ArgumentOutOfRangeException("pos", pos, "pos must be > 0");
if (pos >= word.Length)
throw new ArgumentOutOfRangeException("pos", pos, "pos must be < word.Length");
#endif
TextWord after = new TextWord(word.document, word.line, word.offset + pos, word.length - pos, word.color, word.hasDefaultColor);
word = new TextWord(word.document, word.line, word.offset, pos, word.color, word.hasDefaultColor);
return after;
}
public bool HasDefaultColor {
get {
return hasDefaultColor;
@ -149,6 +168,9 @@ namespace ICSharpCode.TextEditor.Document @@ -149,6 +168,9 @@ namespace ICSharpCode.TextEditor.Document
public Color Color {
get {
if (color == null)
return Color.Black;
else
return color.Color;
}
}

24
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/MarkerStrategy.cs

@ -14,9 +14,9 @@ using System.Collections.Generic; @@ -14,9 +14,9 @@ using System.Collections.Generic;
namespace ICSharpCode.TextEditor.Document
{
/// <summary>
/// Description of MarkerStrategy.
/// Manages the list of markers and provides ways to retrieve markers for specific positions.
/// </summary>
public class MarkerStrategy
public sealed class MarkerStrategy
{
List<TextMarker> textMarker = new List<TextMarker>();
IDocument document;
@ -29,7 +29,7 @@ namespace ICSharpCode.TextEditor.Document @@ -29,7 +29,7 @@ namespace ICSharpCode.TextEditor.Document
public IEnumerable<TextMarker> TextMarker {
get {
return textMarker;
return textMarker.AsReadOnly();
}
}
@ -71,7 +71,7 @@ namespace ICSharpCode.TextEditor.Document @@ -71,7 +71,7 @@ namespace ICSharpCode.TextEditor.Document
List<TextMarker> markers = new List<TextMarker>();
for (int i = 0; i < textMarker.Count; ++i) {
TextMarker marker = (TextMarker)textMarker[i];
if (marker.Offset <= offset && offset <= marker.Offset + marker.Length) {
if (marker.Offset <= offset && offset <= marker.EndOffset) {
markers.Add(marker);
}
}
@ -82,14 +82,20 @@ namespace ICSharpCode.TextEditor.Document @@ -82,14 +82,20 @@ namespace ICSharpCode.TextEditor.Document
public List<TextMarker> GetMarkers(int offset, int length)
{
int endOffset = offset + length - 1;
List<TextMarker> markers = new List<TextMarker>();
for (int i = 0; i < textMarker.Count; ++i) {
TextMarker marker = (TextMarker)textMarker[i];
if (marker.Offset <= offset && offset <= marker.Offset + marker.Length ||
marker.Offset <= offset + length && offset + length <= marker.Offset + marker.Length ||
offset <= marker.Offset && marker.Offset <= offset + length ||
offset <= marker.Offset + marker.Length && marker.Offset + marker.Length <= offset + length
) {
if (// start in marker region
marker.Offset <= offset && offset <= marker.EndOffset ||
// end in marker region
marker.Offset <= endOffset && endOffset <= marker.EndOffset ||
// marker start in region
offset <= marker.Offset && marker.Offset <= endOffset ||
// marker end in region
offset <= marker.EndOffset && marker.EndOffset <= endOffset
)
{
markers.Add(marker);
}
}

20
src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/MarkerStrategy/TextMarker.cs

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
@ -12,14 +12,15 @@ using System.Collections; @@ -12,14 +12,15 @@ using System.Collections;
namespace ICSharpCode.TextEditor.Document
{
public enum TextMarkerType {
public enum TextMarkerType
{
SolidBlock,
Underlined,
WaveLine
}
/// <summary>
/// Description of TextMarker.
/// Marks a part of a document.
/// </summary>
public class TextMarker : AbstractSegment
{
@ -62,12 +63,23 @@ namespace ICSharpCode.TextEditor.Document @@ -62,12 +63,23 @@ namespace ICSharpCode.TextEditor.Document
}
}
/// <summary>
/// Gets the last offset that is inside the marker region.
/// </summary>
public int EndOffset {
get {
return Offset + Length - 1;
}
}
public TextMarker(int offset, int length, TextMarkerType textMarkerType) : this(offset, length, textMarkerType, Color.Red)
{
}
public TextMarker(int offset, int length, TextMarkerType textMarkerType, Color color)
{
if (length < 1)
throw new ArgumentOutOfRangeException("length", length, "length must be >= 1");
this.offset = offset;
this.length = length;
this.textMarkerType = textMarkerType;
@ -76,6 +88,8 @@ namespace ICSharpCode.TextEditor.Document @@ -76,6 +88,8 @@ namespace ICSharpCode.TextEditor.Document
public TextMarker(int offset, int length, TextMarkerType textMarkerType, Color color, Color foreColor)
{
if (length < 1)
throw new ArgumentOutOfRangeException("length", length, "length must be >= 1");
this.offset = offset;
this.length = length;
this.textMarkerType = textMarkerType;

2
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs

@ -59,6 +59,8 @@ namespace ICSharpCode.TextEditor @@ -59,6 +59,8 @@ namespace ICSharpCode.TextEditor
/// <value>
/// Current file's character encoding
/// </value>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Encoding Encoding {
get {
if (encoding == null)

303
src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextView.cs

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
@ -190,6 +190,8 @@ namespace ICSharpCode.TextEditor @@ -190,6 +190,8 @@ namespace ICSharpCode.TextEditor
}
}
DrawMarkerDraw(g);
if (horizontalDelta > 0) {
g.ResetClip();
}
@ -325,8 +327,30 @@ namespace ICSharpCode.TextEditor @@ -325,8 +327,30 @@ namespace ICSharpCode.TextEditor
return ceiling;
}
struct MarkerToDraw {
internal TextMarker marker;
internal RectangleF drawingRect;
public MarkerToDraw(TextMarker marker, RectangleF drawingRect)
{
this.marker = marker;
this.drawingRect = drawingRect;
}
}
List<MarkerToDraw> markersToDraw = new List<MarkerToDraw>();
void DrawMarker(Graphics g, TextMarker marker, RectangleF drawingRect)
{
// draw markers later so they can overdraw the following text
markersToDraw.Add(new MarkerToDraw(marker, drawingRect));
}
void DrawMarkerDraw(Graphics g)
{
foreach (MarkerToDraw m in markersToDraw) {
TextMarker marker = m.marker;
RectangleF drawingRect = m.drawingRect;
float drawYPos = drawingRect.Bottom - 1;
switch (marker.TextMarkerType) {
case TextMarkerType.Underlined:
@ -334,16 +358,20 @@ namespace ICSharpCode.TextEditor @@ -334,16 +358,20 @@ namespace ICSharpCode.TextEditor
break;
case TextMarkerType.WaveLine:
int reminder = ((int)drawingRect.X) % 6;
for (float i = drawingRect.X - reminder; i < drawingRect.Right + reminder; i+= 6) {
for (float i = (int)drawingRect.X - reminder; i < drawingRect.Right; i += 6) {
g.DrawLine(BrushRegistry.GetPen(marker.Color), i, drawYPos + 3 - 4, i + 3, drawYPos + 1 - 4);
if (i + 3 < drawingRect.Right) {
g.DrawLine(BrushRegistry.GetPen(marker.Color), i + 3, drawYPos + 1 - 4, i + 6, drawYPos + 3 - 4);
}
}
break;
case TextMarkerType.SolidBlock:
g.FillRectangle(BrushRegistry.GetBrush(marker.Color), drawingRect);
break;
}
}
markersToDraw.Clear();
}
/// <summary>
/// Get the marker brush (for solid block markers) at a given position.
@ -352,7 +380,7 @@ namespace ICSharpCode.TextEditor @@ -352,7 +380,7 @@ namespace ICSharpCode.TextEditor
/// <param name="length">The length.</param>
/// <param name="markers">All markers that have been found.</param>
/// <returns>The Brush or null when no marker was found.</returns>
Brush GetMarkerBrushAt(int offset, int length, ref Color foreColor, out List<TextMarker> markers)
Brush GetMarkerBrushAt(int offset, int length, ref Color foreColor, out IList<TextMarker> markers)
{
markers = Document.MarkerStrategy.GetMarkers(offset, length);
foreach (TextMarker marker in markers) {
@ -369,8 +397,7 @@ namespace ICSharpCode.TextEditor @@ -369,8 +397,7 @@ namespace ICSharpCode.TextEditor
float PaintLinePart(Graphics g, int lineNumber, int startColumn, int endColumn, Rectangle lineRectangle, float physicalXPos)
{
bool drawLineMarker = DrawLineMarkerAtLine(lineNumber);
Brush bgColorBrush = GetBgColorBrush(lineNumber);
Brush backgroundBrush = textArea.Enabled ? bgColorBrush : SystemBrushes.InactiveBorder;
Brush backgroundBrush = textArea.Enabled ? GetBgColorBrush(lineNumber) : SystemBrushes.InactiveBorder;
HighlightColor selectionColor = textArea.Document.HighlightingStrategy.GetColorFor("Selection");
ColumnRange selectionRange = textArea.SelectionManager.GetSelectionAtLine(lineNumber);
@ -379,85 +406,119 @@ namespace ICSharpCode.TextEditor @@ -379,85 +406,119 @@ namespace ICSharpCode.TextEditor
LineSegment currentLine = textArea.Document.GetLineSegment(lineNumber);
int logicalColumn = startColumn;
Brush selectionBackgroundBrush = BrushRegistry.GetBrush(selectionColor.BackgroundColor);
Brush unselectedBackgroundBrush = backgroundBrush;
if (currentLine.Words != null) {
int startword = 0;
// search the first word after startColumn and update physicalColumn if a word is Tab
int wordOffset = 0;
for (; startword < currentLine.Words.Count; ++startword) {
if (wordOffset >= startColumn) {
break;
}
TextWord currentWord = ((TextWord)currentLine.Words[startword]);
if (currentWord.Type == TextWordType.Tab) {
++wordOffset;
} else if (currentWord.Type == TextWordType.Space) {
++wordOffset;
} else {
wordOffset += currentWord.Length;
}
if (currentLine.Words == null) {
return physicalXPos;
}
int currentWordOffset = 0; // we cannot use currentWord.Offset because it is not set on space words
for (int i = startword; i < currentLine.Words.Count && physicalXPos < lineRectangle.Right; ++i) {
// if already all words before endColumn are drawen: break
if (logicalColumn >= endColumn) {
TextWord currentWord;
TextWord nextCurrentWord = null;
for (int wordIdx = 0; wordIdx < currentLine.Words.Count; wordIdx++) {
currentWord = currentLine.Words[wordIdx];
if (currentWordOffset < startColumn) {
// TODO: maybe we need to split at startColumn when we support fold markers
// inside words
currentWordOffset += currentWord.Length;
continue;
}
repeatDrawCurrentWord:
//physicalXPos += 10; // leave room between drawn words - useful for debugging the drawing code
if (currentWordOffset >= endColumn || physicalXPos >= lineRectangle.Right) {
break;
}
int currentWordEndOffset = currentWordOffset + currentWord.Length - 1;
TextWordType currentWordType = currentWord.Type;
IList<TextMarker> markers;
Color wordForeColor;
if (currentWordType == TextWordType.Space)
wordForeColor = spaceMarkerColor.Color;
else if (currentWordType == TextWordType.Tab)
wordForeColor = tabMarkerColor.Color;
else
wordForeColor = currentWord.Color;
Brush wordBackBrush = GetMarkerBrushAt(currentLine.Offset + currentWordOffset, currentWord.Length, ref wordForeColor, out markers);
List<TextMarker> markers = Document.MarkerStrategy.GetMarkers(currentLine.Offset + wordOffset);
// It is possible that we have to split the current word because a marker/the selection begins/ends inside it
if (currentWord.Length > 1) {
int splitPos = int.MaxValue;
if (highlight != null) {
// split both before and after highlight
if (highlight.OpenBrace.Y == lineNumber) {
if (highlight.OpenBrace.X >= currentWordOffset && highlight.OpenBrace.X <= currentWordEndOffset) {
splitPos = Math.Min(splitPos, highlight.OpenBrace.X - currentWordOffset);
}
}
if (highlight.CloseBrace.Y == lineNumber) {
if (highlight.CloseBrace.X >= currentWordOffset && highlight.CloseBrace.X <= currentWordEndOffset) {
splitPos = Math.Min(splitPos, highlight.CloseBrace.X - currentWordOffset);
}
}
if (splitPos == 0) {
splitPos = 1; // split after highlight
}
}
if (endColumn < currentWordEndOffset) { // split when endColumn is reached
splitPos = Math.Min(splitPos, endColumn - currentWordOffset);
}
if (selectionRange.StartColumn > currentWordOffset && selectionRange.StartColumn <= currentWordEndOffset) {
splitPos = Math.Min(splitPos, selectionRange.StartColumn - currentWordOffset);
} else if (selectionRange.EndColumn > currentWordOffset && selectionRange.EndColumn <= currentWordEndOffset) {
splitPos = Math.Min(splitPos, selectionRange.EndColumn - currentWordOffset);
}
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType == TextMarkerType.SolidBlock) {
unselectedBackgroundBrush = BrushRegistry.GetBrush(marker.Color);
break;
int markerColumn = marker.Offset - currentLine.Offset;
int markerEndColumn = marker.EndOffset - currentLine.Offset + 1; // make end offset exclusive
if (markerColumn > currentWordOffset && markerColumn <= currentWordEndOffset) {
splitPos = Math.Min(splitPos, markerColumn - currentWordOffset);
} else if (markerEndColumn > currentWordOffset && markerEndColumn <= currentWordEndOffset) {
splitPos = Math.Min(splitPos, markerEndColumn - currentWordOffset);
}
}
// TODO: cut the word if startColumn or endColimn is in the word;
// needed for foldings wich can start or end in the middle of a word
TextWord currentWord = ((TextWord)currentLine.Words[i]);
switch (currentWord.Type) {
case TextWordType.Space:
RectangleF spaceRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(SpaceWidth), lineRectangle.Height);
Brush spaceBackgroundBrush;
Color spaceMarkerForeColor = spaceMarkerColor.Color;
if (ColumnRange.WholeColumn.Equals(selectionRange) || logicalColumn >= selectionRange.StartColumn && logicalColumn < selectionRange.EndColumn) {
spaceBackgroundBrush = selectionBackgroundBrush;
} else {
Brush markerBrush = GetMarkerBrushAt(currentLine.Offset + logicalColumn, 1, ref spaceMarkerForeColor, out markers);
if (!drawLineMarker && markerBrush != null) {
spaceBackgroundBrush = markerBrush;
} else if (!drawLineMarker && currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground) {
spaceBackgroundBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor);
} else {
spaceBackgroundBrush = unselectedBackgroundBrush;
if (splitPos != int.MaxValue) {
if (nextCurrentWord != null)
throw new ApplicationException("split part invalid: first part cannot be splitted further");
nextCurrentWord = TextWord.Split(ref currentWord, splitPos);
goto repeatDrawCurrentWord; // get markers for first word part
}
}
g.FillRectangle(spaceBackgroundBrush, spaceRectangle);
if (TextEditorProperties.ShowSpaces) {
DrawSpaceMarker(g, spaceMarkerForeColor, physicalXPos, lineRectangle.Y);
// get colors from selection status:
if (ColumnRange.WholeColumn.Equals(selectionRange) || (selectionRange.StartColumn <= currentWordOffset
&& selectionRange.EndColumn > currentWordEndOffset))
{
// word is completely selected
wordBackBrush = selectionBackgroundBrush;
if (selectionColor.HasForeground) {
wordForeColor = selectionColor.Color;
}
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType != TextMarkerType.SolidBlock) {
DrawMarker(g, marker, spaceRectangle);
} else if (drawLineMarker) {
wordBackBrush = backgroundBrush;
}
if (wordBackBrush == null) { // use default background if no other background is set
if (currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground)
wordBackBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor);
else
wordBackBrush = backgroundBrush;
}
physicalXPos += SpaceWidth;
RectangleF wordRectangle;
++logicalColumn;
if (currentWord.Type == TextWordType.Space) {
++physicalColumn;
break;
case TextWordType.Tab:
wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(SpaceWidth), lineRectangle.Height);
g.FillRectangle(wordBackBrush, wordRectangle);
if (TextEditorProperties.ShowSpaces) {
DrawSpaceMarker(g, wordForeColor, physicalXPos, lineRectangle.Y);
}
physicalXPos += SpaceWidth;
} else if (currentWord.Type == TextWordType.Tab) {
physicalColumn += TextEditorProperties.TabIndent;
physicalColumn = (physicalColumn / TextEditorProperties.TabIndent) * TextEditorProperties.TabIndent;
@ -466,121 +527,57 @@ namespace ICSharpCode.TextEditor @@ -466,121 +527,57 @@ namespace ICSharpCode.TextEditor
/ WideSpaceWidth / TextEditorProperties.TabIndent)
* WideSpaceWidth * TextEditorProperties.TabIndent + lineRectangle.X;
physicalTabEnd += WideSpaceWidth * TextEditorProperties.TabIndent;
RectangleF tabRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(physicalTabEnd - physicalXPos), lineRectangle.Height);
Color tabMarkerForeColor = tabMarkerColor.Color;
if (ColumnRange.WholeColumn.Equals(selectionRange) || logicalColumn >= selectionRange.StartColumn && logicalColumn <= selectionRange.EndColumn - 1) {
spaceBackgroundBrush = selectionBackgroundBrush;
} else {
Brush markerBrush = GetMarkerBrushAt(currentLine.Offset + logicalColumn, 1, ref tabMarkerForeColor, out markers);
if (!drawLineMarker && markerBrush != null) {
spaceBackgroundBrush = markerBrush;
} else if (!drawLineMarker && currentWord.SyntaxColor != null && currentWord.SyntaxColor.HasBackground) {
spaceBackgroundBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor);
} else {
spaceBackgroundBrush = unselectedBackgroundBrush;
}
}
g.FillRectangle(spaceBackgroundBrush, tabRectangle);
wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, (float)Math.Ceiling(physicalTabEnd - physicalXPos), lineRectangle.Height);
g.FillRectangle(wordBackBrush, wordRectangle);
if (TextEditorProperties.ShowTabs) {
DrawTabMarker(g, tabMarkerForeColor, physicalXPos, lineRectangle.Y);
DrawTabMarker(g, wordForeColor, physicalXPos, lineRectangle.Y);
}
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType != TextMarkerType.SolidBlock) {
DrawMarker(g, marker, tabRectangle);
}
}
physicalXPos = physicalTabEnd;
++logicalColumn;
break;
case TextWordType.Word:
string word = currentWord.Word;
float lastPos = physicalXPos;
Color wordForeColor = currentWord.Color;
Brush bgMarkerBrush = GetMarkerBrushAt(currentLine.Offset + logicalColumn, word.Length, ref wordForeColor, out markers);
Brush wordBackgroundBrush;
if (!drawLineMarker && bgMarkerBrush != null) {
wordBackgroundBrush = bgMarkerBrush;
} else if (!drawLineMarker && currentWord.SyntaxColor.HasBackground) {
wordBackgroundBrush = BrushRegistry.GetBrush(currentWord.SyntaxColor.BackgroundColor);
} else {
wordBackgroundBrush = unselectedBackgroundBrush;
}
if (ColumnRange.WholeColumn.Equals(selectionRange) || selectionRange.EndColumn - 1 >= word.Length + logicalColumn &&
selectionRange.StartColumn <= logicalColumn) {
physicalXPos += DrawDocumentWord(g,
word,
new Point((int)physicalXPos, lineRectangle.Y),
currentWord.Font,
selectionColor.HasForgeground ? selectionColor.Color : wordForeColor,
selectionBackgroundBrush);
} else {
if (ColumnRange.NoColumn.Equals(selectionRange) /* || selectionRange.StartColumn > logicalColumn + word.Length || selectionRange.EndColumn - 1 <= logicalColumn */) {
physicalXPos += DrawDocumentWord(g,
word,
new Point((int)physicalXPos, lineRectangle.Y),
currentWord.Font,
wordForeColor,
wordBackgroundBrush);
} else {
int offset1 = Math.Min(word.Length, Math.Max(0, selectionRange.StartColumn - logicalColumn ));
int offset2 = Math.Max(offset1, Math.Min(word.Length, selectionRange.EndColumn - logicalColumn));
physicalXPos += DrawDocumentWord(g,
word.Substring(0, offset1),
new Point((int)physicalXPos, lineRectangle.Y),
currentWord.Font,
wordForeColor,
wordBackgroundBrush);
physicalXPos += DrawDocumentWord(g,
word.Substring(offset1, offset2 - offset1),
new Point((int)physicalXPos, lineRectangle.Y),
currentWord.Font,
selectionColor.HasForgeground ? selectionColor.Color : wordForeColor,
selectionBackgroundBrush);
physicalXPos += DrawDocumentWord(g,
word.Substring(offset2),
float wordWidth = DrawDocumentWord(g,
currentWord.Word,
new Point((int)physicalXPos, lineRectangle.Y),
currentWord.Font,
wordForeColor,
wordBackgroundBrush);
}
wordBackBrush);
wordRectangle = new RectangleF(physicalXPos, lineRectangle.Y, wordWidth, lineRectangle.Height);
physicalXPos += wordWidth;
}
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType != TextMarkerType.SolidBlock) {
DrawMarker(g, marker, new RectangleF(lastPos, lineRectangle.Y, (physicalXPos - lastPos), lineRectangle.Height));
DrawMarker(g, marker, wordRectangle);
}
}
// draw bracket highlight
if (highlight != null) {
if (highlight.OpenBrace.Y == lineNumber && highlight.OpenBrace.X == logicalColumn ||
highlight.CloseBrace.Y == lineNumber && highlight.CloseBrace.X == logicalColumn) {
DrawBracketHighlight(g, new Rectangle((int)lastPos, lineRectangle.Y, (int)(physicalXPos - lastPos) - 1, lineRectangle.Height - 1));
if (highlight.OpenBrace.Y == lineNumber && highlight.OpenBrace.X == currentWordOffset ||
highlight.CloseBrace.Y == lineNumber && highlight.CloseBrace.X == currentWordOffset) {
DrawBracketHighlight(g, new Rectangle((int)wordRectangle.X, lineRectangle.Y, (int)wordRectangle.Width - 1, lineRectangle.Height - 1));
}
}
physicalColumn += word.Length;
logicalColumn += word.Length;
break;
currentWordOffset += currentWord.Length;
if (nextCurrentWord != null) {
currentWord = nextCurrentWord;
nextCurrentWord = null;
goto repeatDrawCurrentWord;
}
}
if (physicalXPos < lineRectangle.Right && endColumn >= currentLine.Length) {
// draw markers at line end
IList<TextMarker> markers = Document.MarkerStrategy.GetMarkers(currentLine.Offset + currentLine.Length);
foreach (TextMarker marker in markers) {
if (marker.TextMarkerType != TextMarkerType.SolidBlock) {
DrawMarker(g, marker, new RectangleF(physicalXPos, lineRectangle.Y, WideSpaceWidth, lineRectangle.Height));
}
}
}
return physicalXPos;
}
//int num;
float DrawDocumentWord(Graphics g, string word, Point position, Font font, Color foreColor, Brush backBrush)
{
if (word == null || word.Length == 0) {

16
src/Main/Base/Project/Src/TextEditor/Gui/Editor/ErrorDrawer.cs

@ -149,21 +149,19 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor @@ -149,21 +149,19 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
if (task.Line >= 0 && task.Line < textEditor.Document.TotalNumberOfLines) {
LineSegment line = textEditor.Document.GetLineSegment(task.Line);
int offset = line.Offset + task.Column;
int length = 1;
if (line.Words != null) {
foreach (TextWord tw in line.Words) {
if (task.Column >= tw.Offset && task.Column < (tw.Offset + tw.Length)) {
textEditor.Document.MarkerStrategy.AddMarker(new VisualError(offset, tw.Length, task));
if (refresh) {
textEditor.Refresh();
if (task.Column == tw.Offset) {
length = tw.Length;
break;
}
return;
}
}
if (length == 1 && task.Column < line.Length) {
length = 2; // use minimum length
}
offset = Math.Min(offset, textEditor.Document.TextLength);
int startOffset = offset;
int endOffset = Math.Max(1, TextUtilities.FindWordEnd(textEditor.Document, offset));
textEditor.Document.MarkerStrategy.AddMarker(new VisualError(startOffset, endOffset - startOffset + 1, task));
textEditor.Document.MarkerStrategy.AddMarker(new VisualError(offset, length, task));
if (refresh) {
textEditor.Refresh();
}

Loading…
Cancel
Save