diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
index 07088239aa..4bd679437f 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
@@ -55,6 +55,7 @@
+
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs
new file mode 100644
index 0000000000..2222586e03
--- /dev/null
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs
@@ -0,0 +1,342 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+
+using ICSharpCode.SharpDevelop.Editor;
+
+namespace CSharpBinding
+{
+ ///
+ /// Description of CSharpBracketSearcher.
+ ///
+ public class CSharpBracketSearcher : IBracketSearcher
+ {
+ string openingBrackets = "([{<";
+ string closingBrackets = ")]}>";
+
+ public BracketSearchResult SearchBracket(IDocument document, int offset)
+ {
+ if (offset > 0) {
+ char c = document.GetCharAt(offset - 1);
+ int index = openingBrackets.IndexOf(c);
+ int otherOffset = -1;
+ if (index > -1)
+ otherOffset = SearchBracketForward(document, offset, openingBrackets[index], closingBrackets[index]);
+ index = closingBrackets.IndexOf(c);
+ if (index > -1)
+ otherOffset = SearchBracketBackward(document, offset - 2, openingBrackets[index], closingBrackets[index]);
+
+ if (otherOffset > -1)
+ return new BracketSearchResult(Math.Min(offset - 1, otherOffset), 1, Math.Max(offset - 1, otherOffset), 1);
+ }
+
+ return null;
+ }
+
+ #region SearchBracket helper functions
+ static int ScanLineStart(IDocument document, int offset)
+ {
+ for (int i = offset - 1; i > 0; --i) {
+ if (document.GetCharAt(i) == '\n')
+ return i + 1;
+ }
+ return 0;
+ }
+
+ ///
+ /// Gets the type of code at offset.
+ /// 0 = Code,
+ /// 1 = Comment,
+ /// 2 = String
+ /// Block comments and multiline strings are not supported.
+ ///
+ static int GetStartType(IDocument document, int linestart, int offset)
+ {
+ bool inString = false;
+ bool inChar = false;
+ bool verbatim = false;
+ for(int i = linestart; i < offset; i++) {
+ switch (document.GetCharAt(i)) {
+ case '/':
+ if (!inString && !inChar && i + 1 < document.TextLength) {
+ if (document.GetCharAt(i + 1) == '/') {
+ return 1;
+ }
+ }
+ break;
+ case '"':
+ if (!inChar) {
+ if (inString && verbatim) {
+ if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') {
+ ++i; // skip escaped quote
+ inString = false; // let the string go on
+ } else {
+ verbatim = false;
+ }
+ } else if (!inString && i > 0 && document.GetCharAt(i - 1) == '@') {
+ verbatim = true;
+ }
+ inString = !inString;
+ }
+ break;
+ case '\'':
+ if (!inString) inChar = !inChar;
+ break;
+ case '\\':
+ if ((inString && !verbatim) || inChar)
+ ++i; // skip next character
+ break;
+ }
+ }
+ return (inString || inChar) ? 2 : 0;
+ }
+ #endregion
+
+ #region SearchBracketBackward
+ int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket)
+ {
+ if (offset + 1 >= document.TextLength) return -1;
+ // this method parses a c# document backwards to find the matching bracket
+
+ // first try "quick find" - find the matching bracket if there is no string/comment in the way
+ int quickResult = QuickSearchBracketBackward(document, offset, openBracket, closingBracket);
+ if (quickResult >= 0) return quickResult;
+
+ // we need to parse the line from the beginning, so get the line start position
+ int linestart = ScanLineStart(document, offset + 1);
+
+ // we need to know where offset is - in a string/comment or in normal code?
+ // ignore cases where offset is in a block comment
+ int starttype = GetStartType(document, linestart, offset + 1);
+ if (starttype != 0) {
+ return -1; // start position is in a comment/string
+ }
+
+ // I don't see any possibility to parse a C# document backwards...
+ // We have to do it forwards and push all bracket positions on a stack.
+ Stack bracketStack = new Stack();
+ bool blockComment = false;
+ bool lineComment = false;
+ bool inChar = false;
+ bool inString = false;
+ bool verbatim = false;
+
+ for(int i = 0; i <= offset; ++i) {
+ char ch = document.GetCharAt(i);
+ switch (ch) {
+ case '\r':
+ case '\n':
+ lineComment = false;
+ inChar = false;
+ if (!verbatim) inString = false;
+ break;
+ case '/':
+ if (blockComment) {
+ Debug.Assert(i > 0);
+ if (document.GetCharAt(i - 1) == '*') {
+ blockComment = false;
+ }
+ }
+ if (!inString && !inChar && i + 1 < document.TextLength) {
+ if (!blockComment && document.GetCharAt(i + 1) == '/') {
+ lineComment = true;
+ }
+ if (!lineComment && document.GetCharAt(i + 1) == '*') {
+ blockComment = true;
+ }
+ }
+ break;
+ case '"':
+ if (!(inChar || lineComment || blockComment)) {
+ if (inString && verbatim) {
+ if (i + 1 < document.TextLength && document.GetCharAt(i + 1) == '"') {
+ ++i; // skip escaped quote
+ inString = false; // let the string go
+ } else {
+ verbatim = false;
+ }
+ } else if (!inString && offset > 0 && document.GetCharAt(i - 1) == '@') {
+ verbatim = true;
+ }
+ inString = !inString;
+ }
+ break;
+ case '\'':
+ if (!(inString || lineComment || blockComment)) {
+ inChar = !inChar;
+ }
+ break;
+ case '\\':
+ if ((inString && !verbatim) || inChar)
+ ++i; // skip next character
+ break;
+ default :
+ if (ch == openBracket) {
+ if (!(inString || inChar || lineComment || blockComment)) {
+ bracketStack.Push(i);
+ }
+ } else if (ch == closingBracket) {
+ if (!(inString || inChar || lineComment || blockComment)) {
+ if (bracketStack.Count > 0)
+ bracketStack.Pop();
+ }
+ }
+ break;
+ }
+ }
+ if (bracketStack.Count > 0) return (int)bracketStack.Pop();
+ return -1;
+ }
+ #endregion
+
+ #region SearchBracketForward
+ int SearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket)
+ {
+ bool inString = false;
+ bool inChar = false;
+ bool verbatim = false;
+
+ bool lineComment = false;
+ bool blockComment = false;
+
+ if (offset < 0) return -1;
+
+ // first try "quick find" - find the matching bracket if there is no string/comment in the way
+ int quickResult = QuickSearchBracketForward(document, offset, openBracket, closingBracket);
+ if (quickResult >= 0) return quickResult;
+
+ // we need to parse the line from the beginning, so get the line start position
+ int linestart = ScanLineStart(document, offset);
+
+ // we need to know where offset is - in a string/comment or in normal code?
+ // ignore cases where offset is in a block comment
+ int starttype = GetStartType(document, linestart, offset);
+ if (starttype != 0) return -1; // start position is in a comment/string
+
+ int brackets = 1;
+
+ while (offset < document.TextLength) {
+ char ch = document.GetCharAt(offset);
+ switch (ch) {
+ case '\r':
+ case '\n':
+ lineComment = false;
+ inChar = false;
+ if (!verbatim) inString = false;
+ break;
+ case '/':
+ if (blockComment) {
+ Debug.Assert(offset > 0);
+ if (document.GetCharAt(offset - 1) == '*') {
+ blockComment = false;
+ }
+ }
+ if (!inString && !inChar && offset + 1 < document.TextLength) {
+ if (!blockComment && document.GetCharAt(offset + 1) == '/') {
+ lineComment = true;
+ }
+ if (!lineComment && document.GetCharAt(offset + 1) == '*') {
+ blockComment = true;
+ }
+ }
+ break;
+ case '"':
+ if (!(inChar || lineComment || blockComment)) {
+ if (inString && verbatim) {
+ if (offset + 1 < document.TextLength && document.GetCharAt(offset + 1) == '"') {
+ ++offset; // skip escaped quote
+ inString = false; // let the string go
+ } else {
+ verbatim = false;
+ }
+ } else if (!inString && offset > 0 && document.GetCharAt(offset - 1) == '@') {
+ verbatim = true;
+ }
+ inString = !inString;
+ }
+ break;
+ case '\'':
+ if (!(inString || lineComment || blockComment)) {
+ inChar = !inChar;
+ }
+ break;
+ case '\\':
+ if ((inString && !verbatim) || inChar)
+ ++offset; // skip next character
+ break;
+ default :
+ if (ch == openBracket) {
+ if (!(inString || inChar || lineComment || blockComment)) {
+ ++brackets;
+ }
+ } else if (ch == closingBracket) {
+ if (!(inString || inChar || lineComment || blockComment)) {
+ --brackets;
+ if (brackets == 0) {
+ return offset;
+ }
+ }
+ }
+ break;
+ }
+ ++offset;
+ }
+ return -1;
+ }
+ #endregion
+
+ int QuickSearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket)
+ {
+ int brackets = -1;
+ // first try "quick find" - find the matching bracket if there is no string/comment in the way
+ for (int i = offset; i >= 0; --i) {
+ char ch = document.GetCharAt(i);
+ if (ch == openBracket) {
+ ++brackets;
+ if (brackets == 0) return i;
+ } else if (ch == closingBracket) {
+ --brackets;
+ } else if (ch == '"') {
+ break;
+ } else if (ch == '\'') {
+ break;
+ } else if (ch == '/' && i > 0) {
+ if (document.GetCharAt(i - 1) == '/') break;
+ if (document.GetCharAt(i - 1) == '*') break;
+ }
+ }
+ return -1;
+ }
+
+ int QuickSearchBracketForward(IDocument document, int offset, char openBracket, char closingBracket)
+ {
+ int brackets = 1;
+ // try "quick find" - find the matching bracket if there is no string/comment in the way
+ for (int i = offset; i < document.TextLength; ++i) {
+ char ch = document.GetCharAt(i);
+ if (ch == openBracket) {
+ ++brackets;
+ } else if (ch == closingBracket) {
+ --brackets;
+ if (brackets == 0) return i;
+ } else if (ch == '"') {
+ break;
+ } else if (ch == '\'') {
+ break;
+ } else if (ch == '/' && i > 0) {
+ if (document.GetCharAt(i - 1) == '/') break;
+ } else if (ch == '*' && i > 0) {
+ if (document.GetCharAt(i - 1) == '/') break;
+ }
+ }
+ return -1;
+ }
+ }
+}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
index 4db22c1da6..b0c1793915 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
@@ -25,5 +25,9 @@ namespace CSharpBinding
public override LanguageProperties Properties {
get { return LanguageProperties.CSharp; }
}
+
+ public override IBracketSearcher BracketSearcher {
+ get { return new CSharpBracketSearcher(); }
+ }
}
}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
index 5be5c8e985..0c40160a8b 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
@@ -541,7 +541,6 @@ namespace CSharpBinding.FormattingStrategy
{
SurroundSelectionWithSingleLineComment(editor, "//");
}
-
/*
#region SearchBracketBackward
public override int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket)
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
index 21605eaf35..249af29c30 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
@@ -65,6 +65,7 @@
+
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/BracketHighlightRenderer.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/BracketHighlightRenderer.cs
new file mode 100644
index 0000000000..2bda1e5556
--- /dev/null
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/BracketHighlightRenderer.cs
@@ -0,0 +1,67 @@
+//
+//
+//
+//
+// $Revision$
+//
+using ICSharpCode.AvalonEdit.Document;
+using System;
+using System.Windows.Media;
+using ICSharpCode.AvalonEdit.Rendering;
+using ICSharpCode.SharpDevelop.Editor;
+
+namespace ICSharpCode.AvalonEdit.AddIn
+{
+ public class BracketHighlightRenderer : IBackgroundRenderer
+ {
+ BracketSearchResult result;
+ Pen borderPen;
+ TextView textView;
+
+ public void SetHighlight(BracketSearchResult result)
+ {
+ this.result = result;
+ var layer = textView.GetKnownLayer(Layer);
+ if (layer != null)
+ layer.InvalidateVisual();
+ }
+
+ public BracketHighlightRenderer(TextView textView)
+ {
+ if (textView == null)
+ throw new ArgumentNullException("textView");
+
+ this.borderPen = new Pen(Brushes.Blue, 1);
+ this.borderPen.Freeze();
+ this.textView = textView;
+
+ //this.textView.BackgroundRenderers.Add(this);
+ }
+
+ public KnownLayer Layer {
+ get {
+ return KnownLayer.Selection;
+ }
+ }
+
+ public void Draw(TextView textView, DrawingContext drawingContext)
+ {
+ if (this.result == null)
+ return;
+
+ BackgroundGeometryBuilder builder = new BackgroundGeometryBuilder();
+
+ builder.CornerRadius = 1;
+
+ builder.AddSegment(textView, new TextSegment() { StartOffset = result.OpeningBracketOffset, Length = result.OpeningBracketLength });
+ builder.AddSegment(textView, new TextSegment() { StartOffset = result.ClosingBracketOffset, Length = result.ClosingBracketLength });
+
+ PathGeometry geometry = builder.CreateGeometry();
+
+ if (geometry != null) {
+ geometry.Freeze();
+ drawingContext.DrawGeometry(Brushes.LightBlue, borderPen, geometry);
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
index 8cc908cb6d..22e966b95c 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
@@ -51,7 +51,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
CodeEditorAdapter secondaryTextEditorAdapter;
readonly IconBarManager iconBarManager;
readonly TextMarkerService textMarkerService;
- readonly ErrorDrawer errorDrawer;
+ readonly ErrorPainter errorPainter;
+
+ BracketHighlightRenderer primaryBracketRenderer;
+ BracketHighlightRenderer secondaryBracketRenderer;
public TextEditor PrimaryTextEditor {
get { return primaryTextEditor; }
@@ -146,7 +149,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
primaryTextEditorAdapter = (CodeEditorAdapter)primaryTextEditor.TextArea.GetService(typeof(ITextEditor));
Debug.Assert(primaryTextEditorAdapter != null);
- this.errorDrawer = new ErrorDrawer(primaryTextEditorAdapter);
+ this.errorPainter = new ErrorPainter(primaryTextEditorAdapter);
+
+ this.primaryBracketRenderer = new BracketHighlightRenderer(primaryTextEditor.TextArea.TextView);
this.Document = primaryTextEditor.Document;
primaryTextEditor.SetBinding(TextEditor.DocumentProperty, new Binding("Document") { Source = this });
@@ -169,13 +174,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
textEditor.Background = Brushes.White;
textEditor.FontFamily = new FontFamily("Consolas");
textEditor.FontSize = 13;
- textEditor.TextArea.TextEntering += TextArea_TextEntering;
- textEditor.TextArea.TextEntered += TextArea_TextEntered;
- textEditor.MouseHover += textEditor_MouseHover;
- textEditor.MouseHoverStopped += textEditor_MouseHoverStopped;
- textEditor.MouseLeave += textEditor_MouseLeave;
- textView.MouseDown += textView_MouseDown;
- textEditor.TextArea.Caret.PositionChanged += caret_PositionChanged;
+ textEditor.TextArea.TextEntering += TextAreaTextEntering;
+ textEditor.TextArea.TextEntered += TextAreaTextEntered;
+ textEditor.MouseHover += TextEditorMouseHover;
+ textEditor.MouseHoverStopped += TextEditorMouseHoverStopped;
+ textEditor.MouseLeave += TextEditorMouseLeave;
+ textView.MouseDown += TextViewMouseDown;
+ textEditor.TextArea.Caret.PositionChanged += TextAreaCaretPositionChanged;
textEditor.TextArea.DefaultInputHandler.CommandBindings.Add(
new CommandBinding(CustomCommands.CtrlSpaceCompletion, OnCodeCompletion));
@@ -191,8 +196,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
textView.Services.AddService(typeof(ISyntaxHighlighter), new AvalonEditSyntaxHighlighterAdapter(textView));
- textEditor.TextArea.TextView.MouseRightButtonDown += textEditor_TextArea_TextView_MouseRightButtonDown;
- textEditor.TextArea.TextView.ContextMenuOpening += textEditor_TextArea_TextView_ContextMenuOpening;
+ textEditor.TextArea.TextView.MouseRightButtonDown += TextViewMouseRightButtonDown;
+ textEditor.TextArea.TextView.ContextMenuOpening += TextViewContextMenuOpening;
return textEditor;
}
@@ -203,13 +208,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
textEditor.TextArea.LeftMargins.OfType().Single().TextView = null;
}
- void textEditor_TextArea_TextView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
+ void TextViewContextMenuOpening(object sender, ContextMenuEventArgs e)
{
ITextEditor adapter = GetAdapterFromSender(sender);
MenuService.CreateContextMenu(adapter, contextMenuPath).IsOpen = true;
}
- void textEditor_TextArea_TextView_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
+ void TextViewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
TextEditor textEditor = GetTextEditorFromSender(sender);
var position = textEditor.GetPositionFromPoint(e.GetPosition(textEditor));
@@ -246,6 +251,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
SetRow(secondaryTextEditor, 2);
this.Children.Add(secondaryTextEditor);
+ this.secondaryBracketRenderer = new BracketHighlightRenderer(secondaryTextEditor.TextArea.TextView);
+
secondaryTextEditorAdapter.FileNameChanged();
} else {
// remove secondary editor
@@ -254,6 +261,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
secondaryTextEditor = null;
secondaryTextEditorAdapter.Language.Detach();
secondaryTextEditorAdapter = null;
+ this.secondaryBracketRenderer = null;
this.RowDefinitions.RemoveAt(this.RowDefinitions.Count - 1);
}
}
@@ -261,7 +269,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
public event EventHandler CaretPositionChanged;
bool caretPositionWasChanged;
- void caret_PositionChanged(object sender, EventArgs e)
+ void TextAreaCaretPositionChanged(object sender, EventArgs e)
{
Debug.Assert(sender is Caret);
if (sender == this.ActiveTextEditor.TextArea.Caret) {
@@ -286,13 +294,24 @@ namespace ICSharpCode.AvalonEdit.AddIn
quickClassBrowser.SelectItemAtCaretPosition(this.ActiveTextEditorAdapter.Caret.Position);
}
var caret = this.ActiveTextEditor.TextArea.Caret;
+
+ var activeAdapter = this.ActiveTextEditorAdapter;
+
+ if (activeAdapter.Language != null) {
+ var bracketSearchResult = activeAdapter.Language.BracketSearcher.SearchBracket(activeAdapter.Document, activeAdapter.Caret.Offset);
+// if (activeAdapter == primaryTextEditorAdapter)
+// this.primaryBracketRenderer.SetHighlight(bracketSearchResult);
+// else
+// this.secondaryBracketRenderer.SetHighlight(bracketSearchResult);
+ }
+
StatusBarService.SetCaretPosition(caret.Column, caret.Line, caret.Column);
CaretPositionChanged.RaiseEvent(this, EventArgs.Empty);
}
public void JumpTo(int line, int column)
{
- tryCloseExistingPopup(true);
+ TryCloseExistingPopup(true);
// the adapter sets the caret position and takes care of scrolling
this.ActiveTextEditorAdapter.JumpTo(line, column);
@@ -302,7 +321,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
ToolTip toolTip;
Popup popup;
- void textEditor_MouseHover(object sender, MouseEventArgs e)
+ void TextEditorMouseHover(object sender, MouseEventArgs e)
{
TextEditor textEditor = (TextEditor)sender;
ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(GetAdapter(textEditor));
@@ -312,18 +331,21 @@ namespace ICSharpCode.AvalonEdit.AddIn
args.LogicalPosition = AvalonEditDocumentAdapter.ToLocation(pos.Value);
}
- var markersAtOffset = textMarkerService.GetMarkersAtOffset(args.Editor.Document.PositionToOffset(args.LogicalPosition.Line, args.LogicalPosition.Column));
-
- ITextMarker markerWithToolTip = markersAtOffset.FirstOrDefault(marker => marker.ToolTip != null);
-
- if (markerWithToolTip != null) {
- if (toolTip == null) {
- toolTip = new ToolTip();
- toolTip.Closed += toolTip_Closed;
+ if (args.InDocument) {
+ var markersAtOffset = textMarkerService.GetMarkersAtOffset(args.Editor.Document.PositionToOffset(args.LogicalPosition.Line, args.LogicalPosition.Column));
+
+ ITextMarker markerWithToolTip = markersAtOffset.FirstOrDefault(marker => marker.ToolTip != null);
+
+ if (markerWithToolTip != null) {
+ if (toolTip == null) {
+ toolTip = new ToolTip();
+ toolTip.Closed += ToolTipClosed;
+ }
+ toolTip.Content = markerWithToolTip.ToolTip;
+ toolTip.IsOpen = true;
+ e.Handled = true;
+ return;
}
- toolTip.Content = markerWithToolTip.ToolTip;
- toolTip.IsOpen = true;
- e.Handled = true;
}
ToolTipRequestService.RequestToolTip(args);
@@ -336,14 +358,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow);
}
if (popup == null) {
- popup = createPopup();
+ popup = CreatePopup();
}
- if (tryCloseExistingPopup(false)) {
+ if (TryCloseExistingPopup(false)) {
// when popup content decides to close, close the popup
contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = false; };
popup.Child = (UIElement)args.ContentToShow;
//ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged
- setPopupPosition(popup, textEditor, e);
+ SetPopupPosition(popup, textEditor, e);
popup.IsOpen = true;
}
e.Handled = true;
@@ -351,7 +373,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
else {
if (toolTip == null) {
toolTip = new ToolTip();
- toolTip.Closed += toolTip_Closed;
+ toolTip.Closed += ToolTipClosed;
}
toolTip.Content = args.ContentToShow;
toolTip.IsOpen = true;
@@ -363,11 +385,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (popup != null) {
e.Handled = true;
}
- tryCloseExistingPopup(false);
+ TryCloseExistingPopup(false);
}
}
- bool tryCloseExistingPopup(bool mouseClick)
+ bool TryCloseExistingPopup(bool mouseClick)
{
bool canClose = true;
if (popup != null) {
@@ -382,15 +404,15 @@ namespace ICSharpCode.AvalonEdit.AddIn
return canClose;
}
- void setPopupPosition(Popup popup, TextEditor textEditor, MouseEventArgs mouseArgs)
+ void SetPopupPosition(Popup popup, TextEditor textEditor, MouseEventArgs mouseArgs)
{
- var popupPosition = getPopupPosition(textEditor, mouseArgs);
+ var popupPosition = GetPopupPosition(textEditor, mouseArgs);
popup.HorizontalOffset = popupPosition.X;
popup.VerticalOffset = popupPosition.Y;
}
/// Returns Popup position based on mouse position, in device independent units
- Point getPopupPosition(TextEditor textEditor, MouseEventArgs mouseArgs)
+ Point GetPopupPosition(TextEditor textEditor, MouseEventArgs mouseArgs)
{
Point mousePos = mouseArgs.GetPosition(textEditor);
Point positionInPixels;
@@ -410,16 +432,16 @@ namespace ICSharpCode.AvalonEdit.AddIn
return positionInPixels.TransformFromDevice(textEditor);
}
- Popup createPopup()
+ Popup CreatePopup()
{
popup = new Popup();
- popup.Closed += popup_Closed;
+ popup.Closed += PopupClosed;
popup.Placement = PlacementMode.Absolute;
popup.StaysOpen = true;
return popup;
}
- void textEditor_MouseHoverStopped(object sender, MouseEventArgs e)
+ void TextEditorMouseHoverStopped(object sender, MouseEventArgs e)
{
if (toolTip != null) {
toolTip.IsOpen = false;
@@ -427,18 +449,18 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
- void textEditor_MouseLeave(object sender, MouseEventArgs e)
+ void TextEditorMouseLeave(object sender, MouseEventArgs e)
{
if (popup != null && !popup.IsMouseOver) {
// do not close popup if mouse moved from editor to popup
- tryCloseExistingPopup(false);
+ TryCloseExistingPopup(false);
}
}
- void textView_MouseDown(object sender, MouseButtonEventArgs e)
+ void TextViewMouseDown(object sender, MouseButtonEventArgs e)
{
// close existing popup immediately on text editor mouse down
- tryCloseExistingPopup(false);
+ TryCloseExistingPopup(false);
if (e.ChangedButton == MouseButton.Left && Keyboard.Modifiers == ModifierKeys.Control) {
TextEditor editor = GetTextEditorFromSender(sender);
var position = editor.GetPositionFromPoint(e.GetPosition(editor));
@@ -448,18 +470,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
}
-
- /*void textArea_GotFocus(object sender, RoutedEventArgs e)
- {
- // close popup whenever TextEditor.TextArea gets focus - eg. on debugger step (CodeEditor.JumpTo calls focus)
- }*/
- void toolTip_Closed(object sender, RoutedEventArgs e)
+ void ToolTipClosed(object sender, RoutedEventArgs e)
{
toolTip = null;
}
- void popup_Closed(object sender, EventArgs e)
+ void PopupClosed(object sender, EventArgs e)
{
popup = null;
}
@@ -475,7 +492,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
- void TextArea_TextEntering(object sender, TextCompositionEventArgs e)
+ void TextAreaTextEntering(object sender, TextCompositionEventArgs e)
{
// don't start new code completion if there is still a completion window open
if (completionWindow != null)
@@ -514,7 +531,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
- void TextArea_TextEntered(object sender, TextCompositionEventArgs e)
+ void TextAreaTextEntered(object sender, TextCompositionEventArgs e)
{
if (e.Text.Length > 0 && !e.Handled) {
ILanguageBinding languageBinding = GetAdapterFromSender(sender).Language;
@@ -693,7 +710,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (secondaryTextEditorAdapter != null)
secondaryTextEditorAdapter.Language.Detach();
- errorDrawer.Dispose();
+ errorPainter.Dispose();
this.Document = null;
}
}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
index 1de66bcd66..bd088f9c00 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
@@ -247,6 +247,19 @@ namespace ICSharpCode.AvalonEdit.Rendering
get { return layers; }
}
+ ///
+ /// Retrieves a known layer from the Layers collection.
+ ///
+ public UIElement GetKnownLayer(KnownLayer knownLayer)
+ {
+ foreach (UIElement layer in layers) {
+ LayerPosition p = LayerPosition.GetLayerPosition(layer);
+ if (p != null && p.KnownLayer == knownLayer)
+ return layer;
+ }
+ return null;
+ }
+
///
/// Inserts a new layer at a position specified relative to an existing layer.
///
diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index eac97a710a..30be583409 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -98,6 +98,7 @@
+
@@ -259,7 +260,7 @@
-
+
diff --git a/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs b/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs
new file mode 100644
index 0000000000..b0cf77d162
--- /dev/null
+++ b/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs
@@ -0,0 +1,55 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+
+namespace ICSharpCode.SharpDevelop.Editor
+{
+ ///
+ /// Allows language specific search for matching brackets.
+ ///
+ public interface IBracketSearcher
+ {
+ ///
+ /// Searches for a matching bracket from the given offset to the start of the document.
+ ///
+ /// A BracketSearchResult that contains the positions and lengths of the brackets.
+ BracketSearchResult SearchBracket(IDocument document, int offset);
+ }
+
+ public class DefaultBracketSearcher : IBracketSearcher
+ {
+ public static readonly DefaultBracketSearcher DefaultInstance = new DefaultBracketSearcher();
+
+ public BracketSearchResult SearchBracket(IDocument document, int offset)
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Describes a pair of matching brackets found by IBracketSearcher.
+ ///
+ public class BracketSearchResult
+ {
+ public int OpeningBracketOffset { get; private set; }
+
+ public int OpeningBracketLength { get; private set; }
+
+ public int ClosingBracketOffset { get; private set; }
+
+ public int ClosingBracketLength { get; private set; }
+
+ public BracketSearchResult(int openingBracketOffset, int openingBracketLength,
+ int closingBracketOffset, int closingBracketLength)
+ {
+ this.OpeningBracketOffset = openingBracketOffset;
+ this.OpeningBracketLength = openingBracketLength;
+ this.ClosingBracketOffset = closingBracketOffset;
+ this.ClosingBracketLength = closingBracketLength;
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/AggregatedLanguageBinding.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/AggregatedLanguageBinding.cs
index b0b34b531e..ed7d0d6c61 100644
--- a/src/Main/Base/Project/Src/Services/LanguageBinding/AggregatedLanguageBinding.cs
+++ b/src/Main/Base/Project/Src/Services/LanguageBinding/AggregatedLanguageBinding.cs
@@ -58,5 +58,16 @@ namespace ICSharpCode.SharpDevelop
foreach (ILanguageBinding binding in allBindings)
binding.Detach();
}
+
+ public IBracketSearcher BracketSearcher {
+ get {
+ foreach (ILanguageBinding binding in allBindings) {
+ if (binding.BracketSearcher != null)
+ return binding.BracketSearcher;
+ }
+
+ return DefaultBracketSearcher.DefaultInstance;
+ }
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs
index 24ca870a77..14a407b5a6 100644
--- a/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs
+++ b/src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs
@@ -32,5 +32,11 @@ namespace ICSharpCode.SharpDevelop
public virtual void Detach()
{
}
+
+ public virtual IBracketSearcher BracketSearcher {
+ get {
+ return null;
+ }
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs b/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs
index 8ef1bbbf19..293b9bc6fa 100644
--- a/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs
+++ b/src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs
@@ -30,6 +30,13 @@ namespace ICSharpCode.SharpDevelop
get;
}
+ ///
+ /// Provides access to the bracket search logic for this language.
+ ///
+ IBracketSearcher BracketSearcher {
+ get;
+ }
+
///
/// Callback function for backend bindings to add services to ITextEditor.
/// This is called when the file name of an ITextEditor changes.
diff --git a/src/Main/Base/Project/Src/Services/Tasks/ErrorDrawer.cs b/src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs
similarity index 96%
rename from src/Main/Base/Project/Src/Services/Tasks/ErrorDrawer.cs
rename to src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs
index c1e6a805c7..ccfdf562d9 100644
--- a/src/Main/Base/Project/Src/Services/Tasks/ErrorDrawer.cs
+++ b/src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs
@@ -15,12 +15,12 @@ namespace ICSharpCode.SharpDevelop
///
/// Synchronizes the ITextEditors with the TaskService. It adds and removes error markers.
///
- public class ErrorDrawer : IDisposable
+ public class ErrorPainter : IDisposable
{
ITextEditor textEditor;
ITextMarkerService markerService;
- public ErrorDrawer(ITextEditor textEditor)
+ public ErrorPainter(ITextEditor textEditor)
{
this.textEditor = textEditor;
this.markerService = this.textEditor.GetService(typeof(ITextMarkerService)) as ITextMarkerService;
@@ -124,7 +124,7 @@ namespace ICSharpCode.SharpDevelop
markerColor = Colors.Blue;
break;
case TaskType.Warning:
- markerColor = Colors.Yellow;
+ markerColor = Colors.Orange;
break;
}