#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

214 lines
6.7 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.CodeCompletion;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.Core;
using ICSharpCode.Editor;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
namespace ICSharpCode.AvalonEdit.AddIn
{
/// <summary>
/// The code completion window.
/// </summary>
public partial class SharpDevelopCompletionWindow : CompletionWindow, ICompletionListWindow
{
public ICompletionItem SelectedItem {
get {
return ((CodeCompletionDataAdapter)this.CompletionList.SelectedItem).Item;
}
set {
var itemAdapters = this.CompletionList.CompletionData.Cast<CodeCompletionDataAdapter>();
this.CompletionList.SelectedItem = itemAdapters.FirstOrDefault(a => a.Item == value);
}
}
double ICompletionWindow.Width {
get { return this.Width; }
set {
// Disable virtualization if we use automatic width - this prevents the window from resizing
// when the user scrolls.
VirtualizingStackPanel.SetIsVirtualizing(this.CompletionList.ListBox, !double.IsNaN(value));
this.Width = value;
if (double.IsNaN(value)) {
// enable size-to-width:
if (this.SizeToContent == SizeToContent.Manual)
this.SizeToContent = SizeToContent.Width;
else if (this.SizeToContent == SizeToContent.Height)
this.SizeToContent = SizeToContent.WidthAndHeight;
} else {
// disable size-to-width:
if (this.SizeToContent == SizeToContent.Width)
this.SizeToContent = SizeToContent.Manual;
else if (this.SizeToContent == SizeToContent.WidthAndHeight)
this.SizeToContent = SizeToContent.Height;
}
}
}
readonly ICompletionItemList itemList;
public ICompletionItemList ItemList {
get { return itemList; }
}
public ITextEditor Editor { get; private set; }
public SharpDevelopCompletionWindow(ITextEditor editor, TextArea textArea, ICompletionItemList itemList) : base(textArea)
{
if (editor == null)
throw new ArgumentNullException("editor");
if (itemList == null)
throw new ArgumentNullException("itemList");
if (!itemList.ContainsAllAvailableItems) {
// If more items are available (Ctrl+Space wasn't pressed), show this hint
this.EmptyText = StringParser.Parse("${res:ICSharpCode.AvalonEdit.AddIn.SharpDevelopCompletionWindow.EmptyText}");
}
InitializeComponent();
this.Editor = editor;
this.itemList = itemList;
ICompletionItem suggestedItem = itemList.SuggestedItem;
foreach (ICompletionItem item in itemList.Items) {
ICompletionData adapter = new CodeCompletionDataAdapter(this, item);
this.CompletionList.CompletionData.Add(adapter);
if (item == suggestedItem)
this.CompletionList.SelectedItem = adapter;
}
this.StartOffset -= itemList.PreselectionLength;
}
public static readonly DependencyProperty EmptyTextProperty =
DependencyProperty.Register("EmptyText", typeof(string), typeof(SharpDevelopCompletionWindow),
new FrameworkPropertyMetadata());
/// <summary>
/// The text thats is displayed when the <see cref="ItemList" /> is empty.
/// </summary>
public string EmptyText {
get { return (string)GetValue(EmptyTextProperty); }
set { SetValue(EmptyTextProperty, value); }
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
if (itemList.PreselectionLength > 0 && itemList.SuggestedItem == null) {
string preselection = this.TextArea.Document.GetText(this.StartOffset, this.EndOffset - this.StartOffset);
this.CompletionList.SelectItem(preselection);
}
}
protected override void OnTextInput(TextCompositionEventArgs e)
{
base.OnTextInput(e);
if (!e.Handled) {
foreach (char c in e.Text) {
switch (itemList.ProcessInput(c)) {
case CompletionItemListKeyResult.BeforeStartKey:
this.ExpectInsertionBeforeStart = true;
break;
case CompletionItemListKeyResult.NormalKey:
break;
case CompletionItemListKeyResult.InsertionKey:
this.CompletionList.RequestInsertion(e);
return;
}
}
}
}
}
/// <summary>
/// Completion item that supports complex content and description.
/// </summary>
public interface IFancyCompletionItem : ICompletionItem
{
object Content { get; }
new object Description { get; }
}
sealed class CodeCompletionDataAdapter : ICompletionData, INotifyPropertyChanged
{
readonly SharpDevelopCompletionWindow window;
readonly ICompletionItem item;
readonly IFancyCompletionItem fancyCompletionItem;
public CodeCompletionDataAdapter(SharpDevelopCompletionWindow window, ICompletionItem item)
{
if (window == null)
throw new ArgumentNullException("window");
if (item == null)
throw new ArgumentNullException("item");
this.window = window;
this.item = item;
this.fancyCompletionItem = item as IFancyCompletionItem;
}
public ICompletionItem Item {
get { return item; }
}
public string Text {
get { return item.Text; }
}
public object Content {
get {
return (fancyCompletionItem != null) ? fancyCompletionItem.Content : item.Text;
}
}
public object Description {
get {
return (fancyCompletionItem != null) ? fancyCompletionItem.Description : item.Description;
}
}
public ImageSource Image {
get {
IImage image = item.Image;
return image != null ? image.ImageSource : null;
}
}
public double Priority {
get { return item.Priority; }
}
public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs)
{
CompletionContext context = new CompletionContext {
Editor = window.Editor,
StartOffset = window.StartOffset,
EndOffset = window.EndOffset
};
TextCompositionEventArgs txea = insertionRequestEventArgs as TextCompositionEventArgs;
KeyEventArgs kea = insertionRequestEventArgs as KeyEventArgs;
if (txea != null && txea.Text.Length > 0)
context.CompletionChar = txea.Text[0];
else if (kea != null && kea.Key == Key.Tab)
context.CompletionChar = '\t';
window.ItemList.Complete(context, item);
if (context.CompletionCharHandled && txea != null)
txea.Handled = true;
}
// This is required to work around http://support.microsoft.com/kb/938416/en-us
event System.ComponentModel.PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged {
add { }
remove { }
}
}
}