Browse Source

Reimplemented method insight for AvalonEdit.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4035 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 16 years ago
parent
commit
b58af24885
  1. 12
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs
  2. 6
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  3. 43
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  4. 24
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs
  5. 114
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopInsightWindow.cs
  6. 55
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs
  7. 84
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindowBase.cs
  8. 46
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/IOverloadProvider.cs
  9. 52
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.cs
  10. 112
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.xaml
  11. 56
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadInsightWindow.cs
  12. 105
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadViewer.cs
  13. 16
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/Caret.cs
  14. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/CaretNavigationCommandHandler.cs
  15. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/EditingCommandHandler.cs
  16. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/SelectionLayer.cs
  17. 26
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs
  18. 8
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs
  19. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
  20. 8
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs
  21. 1
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/themes/generic.xaml
  22. 4
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  23. 38
      src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditInsightWindow.cs
  24. 18
      src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditTextEditorAdapter.cs
  25. 2
      src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs
  26. 7
      src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionItemProvider.cs
  27. 15
      src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindow.cs
  28. 55
      src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightItem.cs
  29. 141
      src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightProvider.cs
  30. 7
      src/Main/Base/Project/Src/Editor/ITextEditor.cs
  31. 9
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
  32. 4
      src/Main/Base/Project/Src/TextEditor/Gui/TextEditorAdapter.cs
  33. 11
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultCompilationUnit.cs
  34. 7
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ICompilationUnit.cs
  35. 1
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

12
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs

@ -36,17 +36,7 @@ namespace CSharpBinding @@ -36,17 +36,7 @@ namespace CSharpBinding
CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName);
int cursor = editor.Caret.Offset;
ExpressionContext context = null;
if (ch == '(') {
if (context != null) {
if (IsInComment(editor)) return CodeCompletionKeyPressResult.None;
new CtrlSpaceCompletionItemProvider(context).ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
} else if (EnableMethodInsight && CodeCompletionOptions.InsightEnabled) {
editor.ShowInsightWindow(new MethodInsightDataProvider());
return CodeCompletionKeyPressResult.Completed;
}
return CodeCompletionKeyPressResult.None;
} else if (ch == '[') {
if (ch == '[') {
var line = editor.Document.GetLineForOffset(cursor);
/* TODO: AVALONEDIT Reimplement this
if (TextUtilities.FindPrevWordStart(editor.ActiveTextAreaControl.Document, cursor) <= line.Offset) {

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

@ -70,6 +70,7 @@ @@ -70,6 +70,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Src\SharpDevelopCompletionWindow.cs" />
<Compile Include="Src\SharpDevelopInsightWindow.cs" />
<Compile Include="Src\TextMarkerService.cs" />
</ItemGroup>
<ItemGroup>
@ -79,11 +80,6 @@ @@ -79,11 +80,6 @@
<Name>ICSharpCode.AvalonEdit</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj">
<Project>{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}</Project>
<Name>ICSharpCode.TextEditor</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\NRefactory\Project\NRefactory.csproj">
<Project>{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}</Project>
<Name>NRefactory</Name>

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

@ -301,6 +301,9 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -301,6 +301,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
// tell it to expect the text insertion
completionWindow.ExpectInsertionBeforeStart = true;
}
if (insightWindow != null) {
insightWindow.ExpectInsertionBeforeStart = true;
}
return;
} else if (result == CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion) {
if (completionWindow != null) {
@ -317,11 +320,18 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -317,11 +320,18 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
}
TextEditor GetTextEditorFromRoutedCommand(object sender)
{
TextArea textArea = (TextArea)sender;
TextEditor textEditor = (TextEditor)textArea.GetService(typeof(TextEditor));
Debug.Assert(textEditor != null);
return textEditor;
}
void OnCodeCompletion(object sender, ExecutedRoutedEventArgs e)
{
TextEditor textEditor = (TextEditor)sender;
if (completionWindow != null)
completionWindow.Close();
CloseExistingCompletionWindows();
TextEditor textEditor = GetTextEditorFromRoutedCommand(sender);
foreach (ICodeCompletionBinding cc in CodeCompletionBindings) {
if (cc.CtrlSpace(GetAdapter(textEditor))) {
e.Handled = true;
@ -332,7 +342,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -332,7 +342,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
void OnDeleteLine(object sender, ExecutedRoutedEventArgs e)
{
TextEditor textEditor = (TextEditor)sender;
TextEditor textEditor = GetTextEditorFromRoutedCommand(sender);
e.Handled = true;
using (textEditor.Document.RunUpdate()) {
DocumentLine currentLine = textEditor.Document.GetLineByNumber(textEditor.TextArea.Caret.Line);
@ -342,19 +352,40 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -342,19 +352,40 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
CompletionWindow completionWindow;
SharpDevelopInsightWindow insightWindow;
internal void NotifyCompletionWindowOpened(CompletionWindow window)
void CloseExistingCompletionWindows()
{
if (completionWindow != null) {
// if there already is a completion window open, close it
completionWindow.Close();
}
if (insightWindow != null) {
insightWindow.Close();
}
}
public SharpDevelopInsightWindow ActiveInsightWindow {
get { return insightWindow; }
}
internal void NotifyCompletionWindowOpened(CompletionWindow window)
{
CloseExistingCompletionWindows();
completionWindow = window;
window.Closed += delegate {
completionWindow = null;
};
}
internal void NotifyInsightWindowOpened(SharpDevelopInsightWindow window)
{
CloseExistingCompletionWindows();
insightWindow = window;
window.Closed += delegate {
insightWindow = null;
};
}
IFormattingStrategy formattingStrategy;
public IFormattingStrategy FormattingStrategy {

24
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs

@ -6,7 +6,9 @@ @@ -6,7 +6,9 @@
// </file>
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.AvalonEdit.CodeCompletion;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
@ -39,5 +41,27 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -39,5 +41,27 @@ namespace ICSharpCode.AvalonEdit.AddIn
codeEditor.NotifyCompletionWindowOpened(window);
window.Show();
}
public override IInsightWindow ShowInsightWindow(IEnumerable<IInsightItem> items)
{
if (items == null)
return null;
var insightWindow = new SharpDevelopInsightWindow(this.TextEditor.TextArea);
insightWindow.Items.AddRange(items);
if (insightWindow.Items.Count > 0) {
insightWindow.SelectedItem = insightWindow.Items[0];
} else {
// don't open insight window when there are no items
return null;
}
codeEditor.NotifyInsightWindowOpened(insightWindow);
insightWindow.Show();
return insightWindow;
}
public override IInsightWindow ActiveInsightWindow {
get { return codeEditor.ActiveInsightWindow; }
}
}
}

114
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopInsightWindow.cs

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using ICSharpCode.AvalonEdit.CodeCompletion;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.AvalonEdit.AddIn
{
/// <summary>
/// Adapter between AvalonEdit InsightWindow and SharpDevelop IInsightWindow interface.
/// </summary>
public class SharpDevelopInsightWindow : OverloadInsightWindow, IInsightWindow
{
sealed class SDItemProvider : IOverloadProvider
{
readonly SharpDevelopInsightWindow insightWindow;
int selectedIndex;
public SDItemProvider(SharpDevelopInsightWindow insightWindow)
{
this.insightWindow = insightWindow;
insightWindow.items.CollectionChanged += insightWindow_items_CollectionChanged;
}
void insightWindow_items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("Count");
OnPropertyChanged("CurrentHeader");
OnPropertyChanged("CurrentContent");
OnPropertyChanged("CurrentIndexText");
}
public event PropertyChangedEventHandler PropertyChanged;
public int SelectedIndex {
get {
return selectedIndex;
}
set {
if (selectedIndex != value) {
selectedIndex = value;
OnPropertyChanged("SelectedIndex");
OnPropertyChanged("CurrentHeader");
OnPropertyChanged("CurrentContent");
OnPropertyChanged("CurrentIndexText");
}
}
}
public int Count {
get { return insightWindow.Items.Count; }
}
public string CurrentIndexText {
get { return (selectedIndex + 1).ToString() + " of " + this.Count.ToString(); }
}
public object CurrentHeader {
get {
IInsightItem item = insightWindow.SelectedItem;
return item != null ? item.Header : null;
}
}
public object CurrentContent {
get {
IInsightItem item = insightWindow.SelectedItem;
return item != null ? item.Content : null;
}
}
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
readonly ObservableCollection<IInsightItem> items = new ObservableCollection<IInsightItem>();
public SharpDevelopInsightWindow(TextArea textArea) : base(textArea)
{
this.Provider = new SDItemProvider(this);
}
public IList<IInsightItem> Items {
get { return items; }
}
public IInsightItem SelectedItem {
get {
int index = this.Provider.SelectedIndex;
if (index < 0 || index >= items.Count)
return null;
else
return items[index];
}
set {
this.Provider.SelectedIndex = items.IndexOf(value);
}
}
}
}

55
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs

@ -25,9 +25,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -25,9 +25,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
/// </summary>
public class CompletionWindow : CompletionWindowBase
{
TextDocument document;
int startOffset;
int endOffset;
readonly CompletionList completionList = new CompletionList();
ToolTip toolTip = new ToolTip();
@ -48,8 +45,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -48,8 +45,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
toolTip.Placement = PlacementMode.Right;
toolTip.Closed += toolTip_Closed;
startOffset = endOffset = this.TextArea.Caret.Offset;
document = textArea.TextView.Document;
completionList.InsertionRequested += completionList_InsertionRequested;
completionList.SelectionChanged += completionList_SelectionChanged;
}
@ -83,28 +78,10 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -83,28 +78,10 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
{
var item = completionList.SelectedItem;
if (item != null)
item.Complete(this.TextArea, new AnchorSegment(this.TextArea.Document, startOffset, endOffset - startOffset), e);
item.Complete(this.TextArea, new AnchorSegment(this.TextArea.Document, this.StartOffset, this.EndOffset - this.StartOffset), e);
Close();
}
/// <summary>
/// Gets/Sets the start offset of the edited text portion.
/// This text portion is used to determine the text used to select an entry in the completion list by typing.
/// </summary>
public int StartOffset {
get { return startOffset; }
set { startOffset = value; }
}
/// <summary>
/// Gets/Sets the end offset of the edited text portion.
/// This text portion is used to determine the text used to select an entry in the completion list by typing.
/// </summary>
public int EndOffset {
get { return endOffset; }
set { endOffset = value; }
}
/// <inheritdoc/>
protected override void OnSourceInitialized(EventArgs e)
{
@ -121,7 +98,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -121,7 +98,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
protected override void AttachEvents()
{
base.AttachEvents();
document.Changing += textArea_Document_Changing;
this.TextArea.Caret.PositionChanged += CaretPositionChanged;
this.TextArea.MouseWheel += textArea_MouseWheel;
this.TextArea.PreviewTextInput += textArea_PreviewTextInput;
@ -131,7 +107,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -131,7 +107,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
/// <inheritdoc/>
protected override void DetachEvents()
{
document.Changing -= textArea_Document_Changing;
this.TextArea.Caret.PositionChanged -= CaretPositionChanged;
this.TextArea.MouseWheel -= textArea_MouseWheel;
this.TextArea.PreviewTextInput -= textArea_PreviewTextInput;
@ -212,25 +187,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -212,25 +187,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
return completionList.ScrollViewer ?? completionList.ListBox ?? (UIElement)completionList;
}
/// <summary>
/// Gets/sets whether the completion window should expect text insertion at the start offset,
/// which not go into the completion region, but before it.
/// </summary>
/// <remarks>This property allows only a single insertion, it is reset to false
/// when that insertion has occurred.</remarks>
public bool ExpectInsertionBeforeStart { get; set; }
void textArea_Document_Changing(object sender, DocumentChangeEventArgs e)
{
if (e.Offset == startOffset && e.RemovalLength == 0 && ExpectInsertionBeforeStart) {
startOffset = e.GetNewOffset(startOffset, AnchorMovementType.AfterInsertion);
this.ExpectInsertionBeforeStart = false;
} else {
startOffset = e.GetNewOffset(startOffset, AnchorMovementType.BeforeInsertion);
}
endOffset = e.GetNewOffset(endOffset, AnchorMovementType.AfterInsertion);
}
/// <summary>
/// When this flag is set, code completion closes if the caret moves to the
/// beginning of the allowed range. This is useful in Ctrl+Space and "complete when typing",
@ -241,15 +197,18 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -241,15 +197,18 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
void CaretPositionChanged(object sender, EventArgs e)
{
int offset = this.TextArea.Caret.Offset;
if (offset == startOffset) {
if (offset == this.StartOffset) {
if (CloseWhenCaretAtBeginning)
Close();
return;
}
if (offset < startOffset || offset > endOffset) {
if (offset < this.StartOffset || offset > this.EndOffset) {
Close();
} else {
completionList.SelectItemWithStart(document.GetText(startOffset, offset - startOffset));
TextDocument document = this.TextArea.Document;
if (document != null) {
completionList.SelectItemWithStart(document.GetText(this.StartOffset, offset - this.StartOffset));
}
}
}

84
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindowBase.cs

@ -5,12 +5,12 @@ @@ -5,12 +5,12 @@
// <version>$Revision$</version>
// </file>
using ICSharpCode.AvalonEdit.Document;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Gui;
using ICSharpCode.AvalonEdit.Utils;
@ -34,6 +34,9 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -34,6 +34,9 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
public TextArea TextArea { get; private set; }
Window parentWindow;
TextDocument document;
int startOffset;
int endOffset;
/// <summary>
/// Creates a new CompletionWindowBase.
@ -46,6 +49,8 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -46,6 +49,8 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
parentWindow = Window.GetWindow(textArea);
this.Owner = parentWindow;
this.AddHandler(MouseUpEvent, new MouseButtonEventHandler(OnMouseUp), true);
startOffset = endOffset = this.TextArea.Caret.Offset;
}
#region Event Handlers
@ -54,11 +59,15 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -54,11 +59,15 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
/// </summary>
protected virtual void AttachEvents()
{
document = this.TextArea.Document;
if (document != null) {
document.Changing += textArea_Document_Changing;
}
this.TextArea.PreviewLostKeyboardFocus += TextAreaLostFocus;
this.TextArea.TextView.ScrollOffsetChanged += TextViewScrollOffsetChanged;
this.TextArea.TextView.DocumentChanged += TextViewDocumentChanged;
this.TextArea.PreviewKeyDown += textArea_PreviewKeyDown;
this.TextArea.PreviewKeyUp += textArea_PreviewKeyUp;
this.TextArea.DocumentChanged += TextAreaDocumentChanged;
this.TextArea.PreviewKeyDown += TextAreaPreviewKeyDown;
this.TextArea.PreviewKeyUp += TextAreaPreviewKeyUp;
if (parentWindow != null) {
parentWindow.LocationChanged += parentWindow_LocationChanged;
}
@ -69,23 +78,26 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -69,23 +78,26 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
/// </summary>
protected virtual void DetachEvents()
{
if (document != null) {
document.Changing -= textArea_Document_Changing;
}
this.TextArea.PreviewLostKeyboardFocus -= TextAreaLostFocus;
this.TextArea.TextView.ScrollOffsetChanged -= TextViewScrollOffsetChanged;
this.TextArea.TextView.DocumentChanged -= TextViewDocumentChanged;
this.TextArea.PreviewKeyDown -= textArea_PreviewKeyDown;
this.TextArea.PreviewKeyUp -= textArea_PreviewKeyUp;
this.TextArea.DocumentChanged -= TextAreaDocumentChanged;
this.TextArea.PreviewKeyDown -= TextAreaPreviewKeyDown;
this.TextArea.PreviewKeyUp -= TextAreaPreviewKeyUp;
if (parentWindow != null) {
parentWindow.LocationChanged -= parentWindow_LocationChanged;
}
}
void textArea_PreviewKeyDown(object sender, KeyEventArgs e)
void TextAreaPreviewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = RaiseEventPair(this, PreviewKeyDownEvent, KeyDownEvent,
new KeyEventArgs(e.KeyboardDevice, e.InputSource, e.Timestamp, e.Key));
}
void textArea_PreviewKeyUp(object sender, KeyEventArgs e)
void TextAreaPreviewKeyUp(object sender, KeyEventArgs e)
{
e.Handled = RaiseEventPair(this, PreviewKeyUpEvent, KeyUpEvent,
new KeyEventArgs(e.KeyboardDevice, e.InputSource, e.Timestamp, e.Key));
@ -96,7 +108,7 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -96,7 +108,7 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
UpdatePosition();
}
void TextViewDocumentChanged(object sender, EventArgs e)
void TextAreaDocumentChanged(object sender, EventArgs e)
{
Close();
}
@ -189,8 +201,13 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -189,8 +201,13 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
SetPosition();
AttachEvents();
if (document != null && this.StartOffset != this.TextArea.Caret.Offset) {
SetPosition(new TextViewPosition(document.GetLocation(this.StartOffset)));
} else {
SetPosition(this.TextArea.Caret.Position);
}
}
/// <inheritdoc/>
@ -213,14 +230,14 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -213,14 +230,14 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
Point visualLocation, visualLocationTop;
/// <summary>
/// Positions the completion window at the caret position.
/// Positions the completion window at the specified position.
/// </summary>
void SetPosition()
protected void SetPosition(TextViewPosition position)
{
TextView textView = this.TextArea.TextView;
visualLocation = textView.GetVisualPosition(this.TextArea.Caret.Position, VisualYPosition.LineBottom);
visualLocationTop = textView.GetVisualPosition(this.TextArea.Caret.Position, VisualYPosition.LineTop);
visualLocation = textView.GetVisualPosition(position, VisualYPosition.LineBottom);
visualLocationTop = textView.GetVisualPosition(position, VisualYPosition.LineTop);
UpdatePosition();
}
@ -249,5 +266,42 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -249,5 +266,42 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
this.Left = bounds.X;
this.Top = bounds.Y;
}
/// <summary>
/// Gets/Sets the start of the text range in which the completion window stays open.
/// This text portion is used to determine the text used to select an entry in the completion list by typing.
/// </summary>
public int StartOffset {
get { return startOffset; }
set { startOffset = value; }
}
/// <summary>
/// Gets/Sets the end of the text range in which the completion window stays open.
/// This text portion is used to determine the text used to select an entry in the completion list by typing.
/// </summary>
public int EndOffset {
get { return endOffset; }
set { endOffset = value; }
}
/// <summary>
/// Gets/sets whether the completion window should expect text insertion at the start offset,
/// which not go into the completion region, but before it.
/// </summary>
/// <remarks>This property allows only a single insertion, it is reset to false
/// when that insertion has occurred.</remarks>
public bool ExpectInsertionBeforeStart { get; set; }
void textArea_Document_Changing(object sender, DocumentChangeEventArgs e)
{
if (e.Offset == startOffset && e.RemovalLength == 0 && ExpectInsertionBeforeStart) {
startOffset = e.GetNewOffset(startOffset, AnchorMovementType.AfterInsertion);
this.ExpectInsertionBeforeStart = false;
} else {
startOffset = e.GetNewOffset(startOffset, AnchorMovementType.BeforeInsertion);
}
endOffset = e.GetNewOffset(endOffset, AnchorMovementType.AfterInsertion);
}
}
}

46
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/IOverloadProvider.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace ICSharpCode.AvalonEdit.CodeCompletion
{
/// <summary>
/// Provides the items for the OverloadViewer.
/// </summary>
public interface IOverloadProvider : INotifyPropertyChanged
{
/// <summary>
/// Gets/Sets the selected index.
/// </summary>
int SelectedIndex { get; set; }
/// <summary>
/// Gets the number of overloads.
/// </summary>
int Count { get; }
/// <summary>
/// Gets the text 'SelectedIndex of Count'.
/// </summary>
string CurrentIndexText { get; }
/// <summary>
/// Gets the current header.
/// </summary>
object CurrentHeader { get; }
/// <summary>
/// Gets the current content.
/// </summary>
object CurrentContent { get; }
}
}

52
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.cs

@ -5,33 +5,34 @@ @@ -5,33 +5,34 @@
// <version>$Revision$</version>
// </file>
using ICSharpCode.AvalonEdit.Gui;
using System;
using System.Windows;
using ICSharpCode.AvalonEdit.Document;
using System.Windows.Controls;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.CodeCompletion
{
/// <summary>
/// A popup-like window.
/// A popup-like window that is attached to a text segment.
/// </summary>
public class InsightWindow : CompletionWindowBase
{
TextDocument document;
int startOffset;
int endOffset;
static InsightWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(InsightWindow),
new FrameworkPropertyMetadata(typeof(InsightWindow)));
AllowsTransparencyProperty.OverrideMetadata(typeof(InsightWindow),
new FrameworkPropertyMetadata(Boxes.True));
}
/// <summary>
/// Creates a new InsightWindow.
/// </summary>
public InsightWindow(TextArea textArea) : base(textArea)
{
this.SizeToContent = SizeToContent.WidthAndHeight;
// prevent user from resizing window to 0x0
this.MinHeight = 15;
this.MinWidth = 30;
startOffset = endOffset = this.TextArea.Caret.Offset;
this.CloseAutomatically = true;
}
/// <summary>
@ -45,51 +46,28 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion @@ -45,51 +46,28 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion
get { return this.CloseAutomatically; }
}
/// <summary>
/// Gets/Sets the start of the text range in which the insight window stays open.
/// Has no effect if CloseAutomatically is false.
/// </summary>
public int StartOffset { get; set; }
/// <summary>
/// Gets/Sets the end of the text range in which the insight window stays open.
/// Has no effect if CloseAutomatically is false.
/// </summary>
public int EndOffset { get; set; }
/// <inheritdoc/>
protected override void AttachEvents()
{
base.AttachEvents();
document = this.TextArea.Document;
if (document != null) {
document.Changing += textArea_Document_Changing;
}
this.TextArea.Caret.PositionChanged += CaretPositionChanged;
}
/// <inheritdoc/>
protected override void DetachEvents()
{
if (document != null) {
document.Changing -= textArea_Document_Changing;
}
this.TextArea.Caret.PositionChanged -= CaretPositionChanged;
base.DetachEvents();
}
void textArea_Document_Changing(object sender, DocumentChangeEventArgs e)
{
startOffset = e.GetNewOffset(startOffset, AnchorMovementType.BeforeInsertion);
endOffset = e.GetNewOffset(endOffset, AnchorMovementType.AfterInsertion);
}
void CaretPositionChanged(object sender, EventArgs e)
{
if (this.CloseAutomatically) {
int offset = this.TextArea.Caret.Offset;
if (offset < startOffset || offset > endOffset) {
if (offset < this.StartOffset || offset > this.EndOffset) {
Close();
}
}
}
}
}

112
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.xaml

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:ICSharpCode.AvalonEdit.CodeCompletion"
>
<!-- Template for InsightWindow. Based on the template for ToolTip. -->
<Style TargetType="{x:Type cc:InsightWindow}">
<Setter Property="SizeToContent" Value="WidthAndHeight" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.InfoBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InfoTextBrushKey}}" />
<Setter Property="FontFamily" Value="{DynamicResource {x:Static SystemFonts.StatusFontFamilyKey}}" />
<Setter Property="FontSize" Value="{DynamicResource {x:Static SystemFonts.StatusFontSizeKey}}" />
<Setter Property="FontStyle" Value="{DynamicResource {x:Static SystemFonts.StatusFontStyleKey}}" />
<Setter Property="FontWeight" Value="{DynamicResource {x:Static SystemFonts.StatusFontWeightKey}}" />
<Setter Property="Padding" Value="1,1,3,1" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:InsightWindow}">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
CornerRadius="2,2,2,2"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}">
<AdornerDecorator>
<ContentPresenter
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</AdornerDecorator>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Template for OverloadViewer. -->
<Style TargetType="{x:Type cc:OverloadViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:OverloadViewer}">
<Grid>
<Grid.Resources>
<cc:CollapseIfSingleOverloadConverter x:Key="collapseIfSingleOverloadConverter"/>
<!-- Style of the UpDownButton -->
<Style TargetType="{x:Type Button}" x:Key="upDownButtonStyle">
<Style.Setters>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Padding" Value="2,2,2,2"/>
<Setter Property="Width" Value="9"/>
<Setter Property="Height" Value="9"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="bd"
Background="{TemplateBinding Background}" CornerRadius="2">
<ContentControl Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Content}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="bd" Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0"
Margin="0,0,4,0"
Orientation="Horizontal"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Provider.Count, Converter={StaticResource collapseIfSingleOverloadConverter}}">
<Button Name="PART_UP" Style="{StaticResource upDownButtonStyle}">
<Path Stroke="Black" Fill="Black" Data="M 0,0.866 L 1,0.866 L 0.5,0 Z" Stretch="UniformToFill" />
</Button>
<TextBlock Margin="2,0,2,0"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Provider.CurrentIndexText}"/>
<Button Name="PART_DOWN" Style="{StaticResource upDownButtonStyle}">
<Path Stroke="Black" Fill="Black" Data="M 0,0 L 1,0 L 0.5,0.866 Z" Stretch="UniformToFill" />
</Button>
</StackPanel>
<ContentControl Grid.Row="0" Grid.Column="1"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Provider.CurrentHeader}"/>
<ContentControl Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Provider.CurrentContent}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

56
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadInsightWindow.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.AvalonEdit.CodeCompletion
{
/// <summary>
/// Insight window that shows an OverloadViewer.
/// </summary>
public class OverloadInsightWindow : InsightWindow
{
OverloadViewer overloadViewer = new OverloadViewer();
/// <summary>
/// Creates a new OverloadInsightWindow.
/// </summary>
public OverloadInsightWindow(TextArea textArea) : base(textArea)
{
overloadViewer.Margin = new Thickness(2,0,0,0);
this.Content = overloadViewer;
}
/// <summary>
/// Gets/Sets the item provider.
/// </summary>
public IOverloadProvider Provider {
get { return overloadViewer.Provider; }
set { overloadViewer.Provider = value; }
}
/// <inheritdoc/>
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (!e.Handled && this.Provider.Count > 1) {
switch (e.Key) {
case Key.Up:
e.Handled = true;
overloadViewer.ChangeIndex(-1);
break;
case Key.Down:
e.Handled = true;
overloadViewer.ChangeIndex(+1);
break;
}
}
}
}
}

105
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadViewer.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace ICSharpCode.AvalonEdit.CodeCompletion
{
/// <summary>
/// Represents a text between "Up" and "Down" buttons.
/// </summary>
public class OverloadViewer : Control
{
static OverloadViewer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(OverloadViewer),
new FrameworkPropertyMetadata(typeof(OverloadViewer)));
}
/// <summary>
/// The text property.
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(OverloadViewer));
/// <summary>
/// Gets/Sets the text between the Up and Down buttons.
/// </summary>
public string Text {
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <inheritdoc/>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Button upButton = (Button)this.Template.FindName("PART_UP", this);
upButton.Click += (sender, e) => {
e.Handled = true;
ChangeIndex(-1);
};
Button downButton = (Button)this.Template.FindName("PART_DOWN", this);
downButton.Click += (sender, e) => {
e.Handled = true;
ChangeIndex(+1);
};
}
/// <summary>
/// The ItemProvider property.
/// </summary>
public static readonly DependencyProperty ProviderProperty =
DependencyProperty.Register("Provider", typeof(IOverloadProvider), typeof(OverloadViewer));
/// <summary>
/// Gets/Sets the item provider.
/// </summary>
public IOverloadProvider Provider {
get { return (IOverloadProvider)GetValue(ProviderProperty); }
set { SetValue(ProviderProperty, value); }
}
/// <summary>
/// Changes the selected index.
/// </summary>
/// <param name="relativeIndexChange">The relative index change - usual values are +1 or -1.</param>
public void ChangeIndex(int relativeIndexChange)
{
IOverloadProvider p = this.Provider;
if (p != null) {
int newIndex = p.SelectedIndex + relativeIndexChange;
if (newIndex < 0)
newIndex = p.Count - 1;
if (newIndex >= p.Count)
newIndex = 0;
p.SelectedIndex = newIndex;
}
}
}
sealed class CollapseIfSingleOverloadConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((int)value < 2) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

16
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/Caret.cs

@ -57,6 +57,8 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -57,6 +57,8 @@ namespace ICSharpCode.AvalonEdit.Gui
/// <summary>
/// Gets/Sets the position of the caret.
/// Retrieving this property will validate the visual column.
/// Use the <see cref="Location"/> property instead if you don't need the visual column.
/// </summary>
public TextViewPosition Position {
get {
@ -83,6 +85,20 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -83,6 +85,20 @@ namespace ICSharpCode.AvalonEdit.Gui
}
}
/// <summary>
/// Gets/Sets the location of the caret.
/// The getter of this property is faster than <see cref="Position"/> because it doesn't have
/// to validate the visual column.
/// </summary>
public TextLocation Location {
get {
return position;
}
set {
this.Position = new TextViewPosition(value);
}
}
/// <summary>
/// Gets/Sets the caret line.
/// </summary>

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/CaretNavigationCommandHandler.cs

@ -166,7 +166,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -166,7 +166,7 @@ namespace ICSharpCode.AvalonEdit.Gui
#region Caret movement
static void MoveCaret(TextArea textArea, CaretMovementType direction)
{
DocumentLine caretLine = textArea.Document.GetLineByNumber(textArea.Caret.Position.Line);
DocumentLine caretLine = textArea.Document.GetLineByNumber(textArea.Caret.Line);
VisualLine visualLine = textArea.TextView.GetOrConstructVisualLine(caretLine);
TextViewPosition caretPosition = textArea.Caret.Position;
TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn);
@ -215,7 +215,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -215,7 +215,7 @@ namespace ICSharpCode.AvalonEdit.Gui
if (newVC < 0)
newVC = visualLine.VisualLength;
// when the caret is already at the start of the text, jump to start before whitespace
if (newVC == textArea.Caret.Position.VisualColumn)
if (newVC == textArea.Caret.VisualColumn)
newVC = 0;
int offset = visualLine.FirstDocumentLine.Offset + visualLine.GetRelativeOffset(newVC);
SetCaretPosition(textArea, newVC, offset);

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/EditingCommandHandler.cs

@ -106,7 +106,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -106,7 +106,7 @@ namespace ICSharpCode.AvalonEdit.Gui
start = start.NextLine;
}
} else {
string indentationString = textArea.Options.GetIndentationString(textArea.Caret.Position.VisualColumn);
string indentationString = textArea.Options.GetIndentationString(textArea.Caret.Column);
textArea.ReplaceSelectionWithText(indentationString);
}
}

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/SelectionLayer.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.AvalonEdit.Gui @@ -24,7 +24,7 @@ namespace ICSharpCode.AvalonEdit.Gui
TextViewWeakEventManager.ScrollOffsetChanged.AddListener(textView, this);
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(TextViewWeakEventManager.VisualLinesChanged)
|| managerType == typeof(TextViewWeakEventManager.ScrollOffsetChanged))

26
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Gui/TextEditor.cs

@ -47,17 +47,6 @@ namespace ICSharpCode.AvalonEdit @@ -47,17 +47,6 @@ namespace ICSharpCode.AvalonEdit
{
}
// Forward focus to TextArea.
/// <inheritdoc/>
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
if (!this.TextArea.IsKeyboardFocusWithin) {
Keyboard.Focus(this.TextArea);
e.Handled = true;
}
}
/// <summary>
/// Creates a new TextEditor instance.
/// </summary>
@ -66,12 +55,26 @@ namespace ICSharpCode.AvalonEdit @@ -66,12 +55,26 @@ namespace ICSharpCode.AvalonEdit
if (textArea == null)
throw new ArgumentNullException("textArea");
this.textArea = textArea;
textArea.TextView.Services.AddService(typeof(TextEditor), this);
this.Options = textArea.Options;
this.Document = new TextDocument();
textArea.SetBinding(TextArea.DocumentProperty, new Binding(DocumentProperty.Name) { Source = this });
textArea.SetBinding(TextArea.OptionsProperty, new Binding(OptionsProperty.Name) { Source = this });
}
// Forward focus to TextArea.
/// <inheritdoc/>
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
if (!this.TextArea.IsKeyboardFocusWithin) {
Keyboard.Focus(this.TextArea);
e.Handled = true;
}
}
#region Document property
/// <summary>
/// Document property.
@ -169,7 +172,6 @@ namespace ICSharpCode.AvalonEdit @@ -169,7 +172,6 @@ namespace ICSharpCode.AvalonEdit
}
/// <inheritdoc/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(PropertyChangedWeakEventManager)) {

8
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingColorizer.cs

@ -43,7 +43,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -43,7 +43,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting
OnDocumentChanged();
}
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
/// <inheritdoc/>
protected virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(TextViewWeakEventManager.DocumentChanged)) {
OnDocumentChanged();
@ -52,6 +53,11 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -52,6 +53,11 @@ namespace ICSharpCode.AvalonEdit.Highlighting
return false;
}
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
return ReceiveWeakEvent(managerType, sender, e);
}
void OnDocumentChanged()
{
if (highlighter != null && isInTextView) {

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj

@ -81,6 +81,9 @@ @@ -81,6 +81,9 @@
</Compile>
<Compile Include="CodeCompletion\ICompletionData.cs" />
<Compile Include="CodeCompletion\InsightWindow.cs" />
<Compile Include="CodeCompletion\IOverloadProvider.cs" />
<Compile Include="CodeCompletion\OverloadInsightWindow.cs" />
<Compile Include="CodeCompletion\OverloadViewer.cs" />
<Compile Include="Document\DocumentChangeOperation.cs">
<DependentUpon>UndoStack.cs</DependentUpon>
</Compile>
@ -335,6 +338,7 @@ @@ -335,6 +338,7 @@
<Folder Include="Utils" />
<Folder Include="themes" />
<Page Include="CodeCompletion\CompletionList.xaml" />
<Page Include="CodeCompletion\InsightWindow.xaml" />
<Page Include="Gui\TextEditor.xaml" />
<Page Include="themes\generic.xaml" />
</ItemGroup>

8
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditorOptions.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.AvalonEdit @@ -141,7 +141,7 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
public string IndentationString {
get { return GetIndentationString(0); }
get { return GetIndentationString(1); }
}
/// <summary>
@ -149,11 +149,11 @@ namespace ICSharpCode.AvalonEdit @@ -149,11 +149,11 @@ namespace ICSharpCode.AvalonEdit
/// </summary>
public virtual string GetIndentationString(int column)
{
if (column < 0)
throw new ArgumentOutOfRangeException("column", column, "Value must be non-negative.");
if (column < 1)
throw new ArgumentOutOfRangeException("column", column, "Value must be at least 1.");
int indentationSize = this.IndentationSize;
if (ConvertTabsToSpaces) {
return new string(' ', indentationSize - (column % indentationSize));
return new string(' ', indentationSize - ((column - 1) % indentationSize));
} else {
return "\t";
}

1
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/themes/generic.xaml

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/Gui/TextEditor.xaml" />
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/CodeCompletion/CompletionList.xaml" />
<ResourceDictionary Source="/ICSharpCode.AvalonEdit;component/CodeCompletion/InsightWindow.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type gui:LineNumberMargin}">

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

@ -69,8 +69,6 @@ @@ -69,8 +69,6 @@
<ItemGroup>
<Compile Include="Src\Commands\SharpDevelopRoutedCommands.cs" />
<Compile Include="Src\Editor\AvalonEdit\AvalonEditDocumentAdapter.cs" />
<Compile Include="Src\Editor\AvalonEdit\AvalonEditInsightWindow.cs">
</Compile>
<Compile Include="Src\Editor\AvalonEdit\AvalonEditTextEditorAdapter.cs" />
<Compile Include="Src\Editor\AvalonEdit\IndentationStrategyAdapter.cs" />
<Compile Include="Src\Editor\CodeCompletion\AttributesItemProvider.cs" />
@ -85,6 +83,8 @@ @@ -85,6 +83,8 @@
<Compile Include="Src\Editor\CodeCompletion\ICompletionItemList.cs" />
<Compile Include="Src\Editor\CodeCompletion\IInsightItem.cs" />
<Compile Include="Src\Editor\CodeCompletion\IInsightWindow.cs" />
<Compile Include="Src\Editor\CodeCompletion\MethodInsightItem.cs" />
<Compile Include="Src\Editor\CodeCompletion\MethodInsightProvider.cs" />
<Compile Include="Src\Editor\CodeCompletion\NRefactoryCodeCompletionBinding.cs" />
<Compile Include="Src\Editor\CodeCompletion\TemplateCompletionItemProvider.cs" />
<Compile Include="Src\Editor\CodeCompletion\TextCompletionItemProvider.cs" />

38
src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditInsightWindow.cs

@ -1,38 +0,0 @@ @@ -1,38 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.AvalonEdit;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ICSharpCode.AvalonEdit.CodeCompletion;
namespace ICSharpCode.SharpDevelop.Editor
{
public class AvalonEditInsightWindow : InsightWindow, IInsightWindow
{
public AvalonEditInsightWindow(TextArea textArea) : base(textArea)
{
}
ObservableCollection<IInsightItem> items = new ObservableCollection<IInsightItem>();
public IList<IInsightItem> Items {
get { return items; }
}
public IInsightItem SelectedItem {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
}

18
src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditTextEditorAdapter.cs

@ -94,8 +94,8 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -94,8 +94,8 @@ namespace ICSharpCode.SharpDevelop.Editor
}
public ICSharpCode.NRefactory.Location Position {
get { return AvalonEditDocumentAdapter.ToLocation(caret.Position); }
set { caret.Position = new TextViewPosition(AvalonEditDocumentAdapter.ToPosition(value)); }
get { return AvalonEditDocumentAdapter.ToLocation(caret.Location); }
set { caret.Location = AvalonEditDocumentAdapter.ToPosition(value); }
}
}
@ -170,25 +170,19 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -170,25 +170,19 @@ namespace ICSharpCode.SharpDevelop.Editor
public void JumpTo(int line, int column)
{
textEditor.TextArea.Selection = Selection.Empty;
textEditor.TextArea.Caret.Position = new TextViewPosition(line, column, -1);
textEditor.TextArea.Caret.Position = new TextViewPosition(line, column);
textEditor.TextArea.Caret.BringCaretToView();
}
AvalonEditInsightWindow activeInsightWindow;
public virtual IInsightWindow ActiveInsightWindow {
get {
return activeInsightWindow;
return null;
}
}
public virtual IInsightWindow OpenInsightWindow(IEnumerable<IInsightItem> items)
public virtual IInsightWindow ShowInsightWindow(IEnumerable<IInsightItem> items)
{
activeInsightWindow = new AvalonEditInsightWindow(textEditor.TextArea);
activeInsightWindow.Items.AddRange(items);
activeInsightWindow.SelectedItem = activeInsightWindow.Items[0];
return activeInsightWindow;
return null;
}
}
}

2
src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs

@ -174,7 +174,7 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -174,7 +174,7 @@ namespace ICSharpCode.SharpDevelop.Editor
switch (ch) {
case '(':
if (enableMethodInsight && CodeCompletionOptions.InsightEnabled) {
editor.ShowInsightWindow(new MethodInsightDataProvider());
editor.ShowInsightWindow(new MethodInsightProvider().ProvideInsight(editor));
return CodeCompletionKeyPressResult.Completed;
}
break;

7
src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionItemProvider.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -67,7 +67,7 @@ namespace ICSharpCode.SharpDevelop.Editor
if (expressionFinder == null) {
return ExpressionResult.Empty;
} else {
return expressionFinder.FindExpression(document.GetText(0, offset), offset);
return expressionFinder.FindExpression(document.Text, offset);
}
}
@ -224,8 +224,9 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -224,8 +224,9 @@ namespace ICSharpCode.SharpDevelop.Editor
description += Environment.NewLine +
StringParser.Parse("${res:ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.CodeCompletionData.OverloadsCounter}", new string[,] {{"NumOverloads", this.Overloads.ToString()}});
}
if (!string.IsNullOrEmpty(entity.Documentation)) {
string documentation = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.CodeCompletionData.ConvertDocumentation(entity.Documentation);
string entityDoc = entity.Documentation;
if (!string.IsNullOrEmpty(entityDoc)) {
string documentation = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.CodeCompletionData.ConvertDocumentation(entityDoc);
if (!string.IsNullOrEmpty(documentation)) {
description += Environment.NewLine + documentation;
}

15
src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindow.cs

@ -31,6 +31,16 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -31,6 +31,16 @@ namespace ICSharpCode.SharpDevelop.Editor
/// </summary>
bool CloseAutomatically { get; set; }
/// <summary>
/// Closes the insight window.
/// </summary>
void Close();
/// <summary>
/// Occurs after the insight window was closed.
/// </summary>
event EventHandler Closed;
/// <summary>
/// Gets/Sets the start of the text range in which the insight window stays open.
/// Has no effect if CloseAutomatically is false.
@ -42,10 +52,5 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -42,10 +52,5 @@ namespace ICSharpCode.SharpDevelop.Editor
/// Has no effect if CloseAutomatically is false.
/// </summary>
int EndOffset { get; set; }
/// <summary>
/// Closes the insight window.
/// </summary>
void Close();
}
}

55
src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightItem.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop.Dom;
using System;
namespace ICSharpCode.SharpDevelop.Editor
{
/// <summary>
/// An insight item that represents an entity.
/// </summary>
public class MethodInsightItem : IInsightItem
{
IEntity entity;
public MethodInsightItem(IEntity entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
this.entity = entity;
}
string headerText;
bool descriptionCreated;
string description;
public object Header {
get {
if (headerText == null) {
IAmbience ambience = AmbienceService.GetCurrentAmbience();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
headerText = ambience.Convert(entity);
}
return headerText;
}
}
public object Content {
get {
if (!descriptionCreated) {
string entityDoc = entity.Documentation;
if (!string.IsNullOrEmpty(entityDoc)) {
description = ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.CodeCompletionData.ConvertDocumentation(entityDoc);
}
descriptionCreated = true;
}
return description;
}
}
}
}

141
src/Main/Base/Project/Src/Editor/CodeCompletion/MethodInsightProvider.cs

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.SharpDevelop.Editor
{
/// <summary>
/// Description of MethodInsightProvider.
/// </summary>
public class MethodInsightProvider
{
public int LookupOffset { get; set; }
public MethodInsightProvider()
{
this.LookupOffset = -1;
}
public IInsightItem[] ProvideInsight(ITextEditor editor)
{
if (editor == null)
throw new ArgumentNullException("editor");
IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(editor.FileName);
if (expressionFinder == null) {
return null;
}
IDocument document = editor.Document;
int useOffset = (this.LookupOffset < 0) ? editor.Caret.Offset : this.LookupOffset;
ExpressionResult expressionResult = expressionFinder.FindExpression(document.Text, useOffset);
if (expressionResult.Expression == null) // expression is null when cursor is in string/comment
return null;
if (LoggingService.IsDebugEnabled) {
if (expressionResult.Context == ExpressionContext.Default)
LoggingService.DebugFormatted("ShowInsight for >>{0}<<", expressionResult.Expression);
else
LoggingService.DebugFormatted("ShowInsight for >>{0}<<, context={1}", expressionResult.Expression, expressionResult.Context);
}
var position = document.OffsetToPosition(useOffset);
ResolveResult rr = ParserService.Resolve(expressionResult, position.Line, position.Column, editor.FileName, document.Text);
return ProvideInsight(expressionResult, rr);
}
public virtual IInsightItem[] ProvideInsight(ExpressionResult expressionResult, ResolveResult result)
{
if (result == null)
return null;
bool constructorInsight = false;
if (expressionResult.Context == ExpressionContext.Attribute) {
constructorInsight = true;
} else if (expressionResult.Context.IsObjectCreation) {
constructorInsight = true;
expressionResult.Context = ExpressionContext.Type;
} else if (expressionResult.Context == ExpressionContext.BaseConstructorCall) {
constructorInsight = true;
}
LanguageProperties language;
if (result.CallingClass != null)
language = result.CallingClass.CompilationUnit.Language;
else
language = ParserService.CurrentProjectContent.Language;
TypeResolveResult trr = result as TypeResolveResult;
if (trr == null && language.AllowObjectConstructionOutsideContext) {
if (result is MixedResolveResult)
trr = (result as MixedResolveResult).TypeResult;
}
if (trr != null && !constructorInsight) {
if (language.AllowObjectConstructionOutsideContext)
constructorInsight = true;
}
List<IMethod> methods = new List<IMethod>();
if (constructorInsight) {
if (trr != null || expressionResult.Context == ExpressionContext.BaseConstructorCall) {
if (result.ResolvedType != null) {
methods.AddRange(GetConstructors(result.ResolvedType));
}
}
} else {
MethodGroupResolveResult mgrr = result as MethodGroupResolveResult;
if (mgrr == null)
return null;
bool classIsInInheritanceTree = false;
if (result.CallingClass != null)
classIsInInheritanceTree = result.CallingClass.IsTypeInInheritanceTree(mgrr.ContainingType.GetUnderlyingClass());
foreach (IMethod method in mgrr.ContainingType.GetMethods()) {
if (language.NameComparer.Equals(method.Name, mgrr.Name)) {
if (method.IsAccessible(result.CallingClass, classIsInInheritanceTree)) {
methods.Add(method);
}
}
}
if (methods.Count == 0 && result.CallingClass != null && language.SupportsExtensionMethods) {
ArrayList list = new ArrayList();
ResolveResult.AddExtensions(language, list, result.CallingClass, mgrr.ContainingType);
foreach (IMethodOrProperty mp in list) {
if (language.NameComparer.Equals(mp.Name, mgrr.Name) && mp is IMethod) {
DefaultMethod m = (DefaultMethod)mp.CreateSpecializedMember();
// for the insight window, remove first parameter and mark the
// method as normal - this is required to show the list of
// parameters the method expects.
m.IsExtensionMethod = false;
m.Parameters.RemoveAt(0);
methods.Add(m);
}
}
}
}
return methods.Select(m => new MethodInsightItem(m)).ToArray();
}
IEnumerable<IMethod> GetConstructors(IReturnType rt)
{
// no need to add default constructor here:
// default constructors should already be present in rt.GetMethods()
if (rt == null)
return Enumerable.Empty<IMethod>();
else
return rt.GetMethods().Where(m => m.IsConstructor && !m.IsStatic);
}
}
}

7
src/Main/Base/Project/Src/Editor/ITextEditor.cs

@ -71,9 +71,10 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -71,9 +71,10 @@ namespace ICSharpCode.SharpDevelop.Editor
/// <summary>
/// Open a new insight window showing the specific insight items.
/// </summary>
/// <param name="items">The insight items to show in the window.</param>
/// <returns>The insight window.</returns>
IInsightWindow OpenInsightWindow(IEnumerable<IInsightItem> items);
/// <param name="items">The insight items to show in the window.
/// If this property is null or an empty list, the insight window will not be shown.</param>
/// <returns>The insight window; or null if no insight window was opened.</returns>
IInsightWindow ShowInsightWindow(IEnumerable<IInsightItem> items);
/// <summary>
/// Gets the insight window that is currently open.

9
src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs

@ -346,17 +346,12 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -346,17 +346,12 @@ namespace ICSharpCode.SharpDevelop.Gui
switch (dr) {
case MessageBoxResult.Yes:
foreach (IViewContent vc in this.ViewContents) {
if (!vc.IsDirty) continue;
if (vc.PrimaryFile != null) {
while (true) {
vc.Files.ForEach(ICSharpCode.SharpDevelop.Commands.SaveFile.Save);
while (vc.IsDirty) {
ICSharpCode.SharpDevelop.Commands.SaveFile.Save(vc);
if (vc.IsDirty) {
if (MessageService.AskQuestion("${res:MainWindow.DiscardChangesMessage}")) {
break;
}
} else {
break;
}
}
}
}

4
src/Main/Base/Project/Src/TextEditor/Gui/TextEditorAdapter.cs

@ -205,9 +205,9 @@ namespace ICSharpCode.SharpDevelop @@ -205,9 +205,9 @@ namespace ICSharpCode.SharpDevelop
}
}
public IInsightWindow OpenInsightWindow(IEnumerable<IInsightItem> items)
public IInsightWindow ShowInsightWindow(IEnumerable<IInsightItem> items)
{
throw new NotImplementedException();
return null;
}
}

11
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultCompilationUnit.cs

@ -133,7 +133,8 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -133,7 +133,8 @@ namespace ICSharpCode.SharpDevelop.Dom
public DefaultCompilationUnit(IProjectContent projectContent)
{
Debug.Assert(projectContent != null);
if (projectContent == null)
throw new ArgumentNullException("projectContent");
this.projectContent = projectContent;
}
@ -147,11 +148,17 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -147,11 +148,17 @@ namespace ICSharpCode.SharpDevelop.Dom
return null;
}
public override string ToString() {
public override string ToString()
{
return String.Format("[CompilationUnit: classes = {0}, fileName = {1}]",
classes.Count,
fileName);
}
public LanguageProperties Language {
get {
return projectContent.Language;
}
}
}
}

7
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ICompilationUnit.cs

@ -30,6 +30,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -30,6 +30,13 @@ namespace ICSharpCode.SharpDevelop.Dom
get;
}
/// <summary>
/// Gets the language this compilation unit was written in.
/// </summary>
LanguageProperties Language {
get;
}
/// <summary>
/// Gets the main using scope of the compilation unit.
/// That scope usually represents the root namespace.

1
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

@ -740,6 +740,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -740,6 +740,7 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary>
/// Gets the class that contains the method.
/// This property cannot be null.
/// </summary>
public IReturnType ContainingType {
get { return containingType; }

Loading…
Cancel
Save