Browse Source

- implemented IBracketSearcher for C#

- added BracketHighlightRenderer (disabled by default)
- renamed ErrorDrawer to ErrorPainter

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4840 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 17 years ago
parent
commit
8570e8f7e7
  1. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  2. 342
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs
  3. 4
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  4. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
  5. 1
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  6. 67
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/BracketHighlightRenderer.cs
  7. 123
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  8. 13
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  9. 3
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  10. 55
      src/Main/Base/Project/Src/Editor/IBracketSearcher.cs
  11. 11
      src/Main/Base/Project/Src/Services/LanguageBinding/AggregatedLanguageBinding.cs
  12. 6
      src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs
  13. 7
      src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs
  14. 6
      src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -55,6 +55,7 @@ @@ -55,6 +55,7 @@
<EmbeddedResource Include="Resources\BuildOptions.xfrm" />
<EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" />
<Compile Include="Src\CSharpAdvancedHighlighter.cs" />
<Compile Include="Src\CSharpBracketSearcher.cs" />
<Compile Include="Src\CSharpLanguageBinding.cs" />
<Compile Include="Src\CSharpProjectBinding.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingStrategy.cs" />

342
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpBracketSearcher.cs

@ -0,0 +1,342 @@ @@ -0,0 +1,342 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="siegfriedpammer@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding
{
/// <summary>
/// Description of CSharpBracketSearcher.
/// </summary>
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;
}
/// <summary>
/// Gets the type of code at offset.<br/>
/// 0 = Code,<br/>
/// 1 = Comment,<br/>
/// 2 = String<br/>
/// Block comments and multiline strings are not supported.
/// </summary>
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<int> bracketStack = new Stack<int>();
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;
}
}
}

4
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

@ -25,5 +25,9 @@ namespace CSharpBinding @@ -25,5 +25,9 @@ namespace CSharpBinding
public override LanguageProperties Properties {
get { return LanguageProperties.CSharp; }
}
public override IBracketSearcher BracketSearcher {
get { return new CSharpBracketSearcher(); }
}
}
}

1
src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs

@ -541,7 +541,6 @@ namespace CSharpBinding.FormattingStrategy @@ -541,7 +541,6 @@ namespace CSharpBinding.FormattingStrategy
{
SurroundSelectionWithSingleLineComment(editor, "//");
}
/*
#region SearchBracketBackward
public override int SearchBracketBackward(IDocument document, int offset, char openBracket, char closingBracket)

1
src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj

@ -65,6 +65,7 @@ @@ -65,6 +65,7 @@
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\AvalonEditDisplayBinding.cs" />
<Compile Include="Src\AvalonEditViewContent.cs" />
<Compile Include="Src\BracketHighlightRenderer.cs" />
<Compile Include="Src\CodeEditor.cs" />
<Compile Include="Src\CodeEditorAdapter.cs" />
<Compile Include="Src\CustomCommands.cs" />

67
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/BracketHighlightRenderer.cs

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="siegfriedpammer@gmail.com"/>
// <version>$Revision$</version>
// </file>
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);
}
}
}
}

123
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -51,7 +51,10 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -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 @@ -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 @@ -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 @@ -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 @@ -203,13 +208,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
textEditor.TextArea.LeftMargins.OfType<IconBarMargin>().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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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;
}
/// <summary> Returns Popup position based on mouse position, in device independent units </summary>
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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -693,7 +710,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (secondaryTextEditorAdapter != null)
secondaryTextEditorAdapter.Language.Detach();
errorDrawer.Dispose();
errorPainter.Dispose();
this.Document = null;
}
}

13
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

@ -247,6 +247,19 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -247,6 +247,19 @@ namespace ICSharpCode.AvalonEdit.Rendering
get { return layers; }
}
/// <summary>
/// Retrieves a known layer from the Layers collection.
/// </summary>
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;
}
/// <summary>
/// Inserts a new layer at a position specified relative to an existing layer.
/// </summary>

3
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -98,6 +98,7 @@ @@ -98,6 +98,7 @@
<Compile Include="Src\Editor\Commands\GoToDefinition.cs" />
<Compile Include="Src\Editor\Commands\IndentSelection.cs" />
<Compile Include="Src\Editor\DocumentUtilitites.cs" />
<Compile Include="Src\Editor\IBracketSearcher.cs" />
<Compile Include="Src\Editor\IDocument.cs" />
<Compile Include="Src\Editor\IDocumentLine.cs" />
<Compile Include="Src\Editor\IFileDocumentProvider.cs" />
@ -259,7 +260,7 @@ @@ -259,7 +260,7 @@
<Compile Include="Src\Services\Profiler\ProfilerService.cs" />
<Compile Include="Src\Services\ProjectService\CompileModifiedProjectsOnly.cs" />
<Compile Include="Src\Services\RefactoringService\ExtractInterfaceOptions.cs" />
<Compile Include="Src\Services\Tasks\ErrorDrawer.cs" />
<Compile Include="Src\Services\Tasks\ErrorPainter.cs" />
<Compile Include="Src\Services\Tasks\Task.cs" />
<Compile Include="Src\Services\Tasks\TaskService.cs" />
<Compile Include="Src\Services\DisplayBinding\IDisplayBinding.cs" />

55
src/Main/Base/Project/Src/Editor/IBracketSearcher.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="siegfriedpammer@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.SharpDevelop.Editor
{
/// <summary>
/// Allows language specific search for matching brackets.
/// </summary>
public interface IBracketSearcher
{
/// <summary>
/// Searches for a matching bracket from the given offset to the start of the document.
/// </summary>
/// <returns>A BracketSearchResult that contains the positions and lengths of the brackets.</returns>
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;
}
}
/// <summary>
/// Describes a pair of matching brackets found by IBracketSearcher.
/// </summary>
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;
}
}
}

11
src/Main/Base/Project/Src/Services/LanguageBinding/AggregatedLanguageBinding.cs

@ -58,5 +58,16 @@ namespace ICSharpCode.SharpDevelop @@ -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;
}
}
}
}

6
src/Main/Base/Project/Src/Services/LanguageBinding/DefaultLanguageBinding.cs

@ -32,5 +32,11 @@ namespace ICSharpCode.SharpDevelop @@ -32,5 +32,11 @@ namespace ICSharpCode.SharpDevelop
public virtual void Detach()
{
}
public virtual IBracketSearcher BracketSearcher {
get {
return null;
}
}
}
}

7
src/Main/Base/Project/Src/Services/LanguageBinding/ILanguageBinding.cs

@ -30,6 +30,13 @@ namespace ICSharpCode.SharpDevelop @@ -30,6 +30,13 @@ namespace ICSharpCode.SharpDevelop
get;
}
/// <summary>
/// Provides access to the bracket search logic for this language.
/// </summary>
IBracketSearcher BracketSearcher {
get;
}
/// <summary>
/// Callback function for backend bindings to add services to ITextEditor.
/// This is called when the file name of an ITextEditor changes.

6
src/Main/Base/Project/Src/Services/Tasks/ErrorDrawer.cs → src/Main/Base/Project/Src/Services/Tasks/ErrorPainter.cs

@ -15,12 +15,12 @@ namespace ICSharpCode.SharpDevelop @@ -15,12 +15,12 @@ namespace ICSharpCode.SharpDevelop
/// <summary>
/// Synchronizes the ITextEditors with the TaskService. It adds and removes error markers.
/// </summary>
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 @@ -124,7 +124,7 @@ namespace ICSharpCode.SharpDevelop
markerColor = Colors.Blue;
break;
case TaskType.Warning:
markerColor = Colors.Yellow;
markerColor = Colors.Orange;
break;
}
Loading…
Cancel
Save