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.
263 lines
8.5 KiB
263 lines
8.5 KiB
// <file> |
|
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> |
|
// <license see="prj:///doc/license.txt">GNU General Public License</license> |
|
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> |
|
// <version>$Revision$</version> |
|
// </file> |
|
|
|
using System; |
|
using System.Drawing; |
|
using System.Windows.Forms; |
|
using System.Reflection; |
|
using System.Collections; |
|
using System.Diagnostics; |
|
|
|
using ICSharpCode.TextEditor; |
|
|
|
namespace ICSharpCode.TextEditor.Gui.CompletionWindow |
|
{ |
|
public class CodeCompletionWindow : AbstractCompletionWindow |
|
{ |
|
static ICompletionData[] completionData; |
|
CodeCompletionListView codeCompletionListView; |
|
VScrollBar vScrollBar = new VScrollBar(); |
|
|
|
int startOffset; |
|
int endOffset; |
|
DeclarationViewWindow declarationViewWindow = null; |
|
Rectangle workingScreen; |
|
|
|
public static CodeCompletionWindow ShowCompletionWindow(Form parent, TextEditorControl control, string fileName, ICompletionDataProvider completionDataProvider, char firstChar) |
|
{ |
|
completionData = completionDataProvider.GenerateCompletionData(fileName, control.ActiveTextAreaControl.TextArea, firstChar); |
|
if (completionData == null || completionData.Length == 0) { |
|
return null; |
|
} |
|
CodeCompletionWindow codeCompletionWindow = new CodeCompletionWindow(completionDataProvider, parent, control, fileName); |
|
codeCompletionWindow.ShowCompletionWindow(); |
|
return codeCompletionWindow; |
|
} |
|
|
|
CodeCompletionWindow(ICompletionDataProvider completionDataProvider, Form parentForm, TextEditorControl control, string fileName) : base(parentForm, control, fileName) |
|
{ |
|
workingScreen = Screen.GetWorkingArea(Location); |
|
startOffset = control.ActiveTextAreaControl.Caret.Offset + 1; |
|
endOffset = startOffset; |
|
if (completionDataProvider.PreSelection != null) { |
|
startOffset -= completionDataProvider.PreSelection.Length + 1; |
|
endOffset--; |
|
} |
|
|
|
codeCompletionListView = new CodeCompletionListView(completionData); |
|
codeCompletionListView.ImageList = completionDataProvider.ImageList; |
|
codeCompletionListView.Dock = DockStyle.Fill; |
|
codeCompletionListView.SelectedItemChanged += new EventHandler(CodeCompletionListViewSelectedItemChanged); |
|
codeCompletionListView.DoubleClick += new EventHandler(CodeCompletionListViewDoubleClick); |
|
codeCompletionListView.Click += new EventHandler(CodeCompletionListViewClick); |
|
Controls.Add(codeCompletionListView); |
|
|
|
if (completionData.Length > 10) { |
|
vScrollBar.Dock = DockStyle.Right; |
|
vScrollBar.Minimum = 0; |
|
vScrollBar.Maximum = completionData.Length - 8; |
|
vScrollBar.SmallChange = 1; |
|
vScrollBar.LargeChange = 3; |
|
codeCompletionListView.FirstItemChanged += new EventHandler(CodeCompletionListViewFirstItemChanged); |
|
Controls.Add(vScrollBar); |
|
} |
|
|
|
this.drawingSize = new Size(codeCompletionListView.ItemHeight * 10, codeCompletionListView.ItemHeight * Math.Min(10, completionData.Length)); |
|
SetLocation(); |
|
|
|
if (declarationViewWindow == null) { |
|
declarationViewWindow = new DeclarationViewWindow(parentForm); |
|
} |
|
SetDeclarationViewLocation(); |
|
declarationViewWindow.ShowDeclarationViewWindow(); |
|
control.Focus(); |
|
CodeCompletionListViewSelectedItemChanged(this, EventArgs.Empty); |
|
|
|
if (completionDataProvider.DefaultIndex >= 0) { |
|
codeCompletionListView.SelectIndex(completionDataProvider.DefaultIndex); |
|
} |
|
|
|
if (completionDataProvider.PreSelection != null) { |
|
CaretOffsetChanged(this, EventArgs.Empty); |
|
} |
|
|
|
|
|
|
|
vScrollBar.Scroll += new ScrollEventHandler(DoScroll); |
|
} |
|
|
|
void CodeCompletionListViewFirstItemChanged(object sender, EventArgs e) |
|
{ |
|
vScrollBar.Value = Math.Min(vScrollBar.Maximum, codeCompletionListView.FirstItem); |
|
} |
|
|
|
void SetDeclarationViewLocation() |
|
{ |
|
// This method uses the side with more free space |
|
int leftSpace = Bounds.Left - workingScreen.Left; |
|
int rightSpace = workingScreen.Right - Bounds.Right; |
|
Point pos; |
|
// The declaration view window has better line break when used on |
|
// the right side, so prefer the right side to the left. |
|
if (rightSpace * 2 > leftSpace) |
|
pos = new Point(Bounds.Right, Bounds.Top); |
|
else |
|
pos = new Point(Bounds.Left - declarationViewWindow.Width, Bounds.Top); |
|
if (declarationViewWindow.Location != pos) { |
|
declarationViewWindow.Location = pos; |
|
} |
|
} |
|
|
|
protected override void SetLocation() |
|
{ |
|
base.SetLocation(); |
|
if (declarationViewWindow != null) { |
|
SetDeclarationViewLocation(); |
|
} |
|
} |
|
|
|
public void HandleMouseWheel(MouseEventArgs e) |
|
{ |
|
int MAX_DELTA = 120; // basically it's constant now, but could be changed later by MS |
|
int multiplier = Math.Abs(e.Delta) / MAX_DELTA; |
|
|
|
int newValue; |
|
if (System.Windows.Forms.SystemInformation.MouseWheelScrollLines > 0) { |
|
newValue = this.vScrollBar.Value - (control.TextEditorProperties.MouseWheelScrollDown ? 1 : -1) * Math.Sign(e.Delta) * System.Windows.Forms.SystemInformation.MouseWheelScrollLines * vScrollBar.SmallChange * multiplier; |
|
} else { |
|
newValue = this.vScrollBar.Value - (control.TextEditorProperties.MouseWheelScrollDown ? 1 : -1) * Math.Sign(e.Delta) * vScrollBar.LargeChange; |
|
} |
|
vScrollBar.Value = Math.Max(vScrollBar.Minimum, Math.Min(vScrollBar.Maximum, newValue)); |
|
DoScroll(this, null); |
|
} |
|
|
|
|
|
void CodeCompletionListViewSelectedItemChanged(object sender, EventArgs e) |
|
{ |
|
ICompletionData data = codeCompletionListView.SelectedCompletionData; |
|
if (data != null && data.Description != null && data.Description.Length > 0) { |
|
declarationViewWindow.Description = data.Description; |
|
SetDeclarationViewLocation(); |
|
} else { |
|
declarationViewWindow.Description = null; |
|
} |
|
} |
|
|
|
public override bool ProcessKeyEvent(char ch) |
|
{ |
|
if (!Char.IsLetterOrDigit(ch) && ch != '_') { |
|
return InsertSelectedItem(ch); |
|
} |
|
++endOffset; |
|
return base.ProcessKeyEvent(ch); |
|
} |
|
|
|
protected override void CaretOffsetChanged(object sender, EventArgs e) |
|
{ |
|
int offset = control.ActiveTextAreaControl.Caret.Offset; |
|
if (offset < startOffset || offset > endOffset) { |
|
Close(); |
|
} else { |
|
codeCompletionListView.SelectItemWithStart(control.Document.GetText(startOffset, offset - startOffset)); |
|
} |
|
} |
|
|
|
protected void DoScroll(object sender, ScrollEventArgs sea) |
|
{ |
|
codeCompletionListView.FirstItem = vScrollBar.Value; |
|
codeCompletionListView.Refresh(); |
|
control.ActiveTextAreaControl.TextArea.Focus(); |
|
} |
|
|
|
protected override bool ProcessTextAreaKey(Keys keyData) |
|
{ |
|
if (!Visible) { |
|
return false; |
|
} |
|
|
|
switch (keyData) { |
|
case Keys.Back: |
|
--endOffset; |
|
if (endOffset < startOffset) { |
|
Close(); |
|
} |
|
return false; |
|
case Keys.Delete: |
|
if (control.ActiveTextAreaControl.Caret.Offset <= endOffset) { |
|
--endOffset; |
|
} |
|
if (endOffset < startOffset) { |
|
Close(); |
|
} |
|
return false; |
|
case Keys.Home: |
|
codeCompletionListView.SelectIndex(0); |
|
return true; |
|
case Keys.End: |
|
codeCompletionListView.SelectIndex(completionData.Length-1); |
|
return true; |
|
case Keys.PageDown: |
|
codeCompletionListView.PageDown(); |
|
return true; |
|
case Keys.PageUp: |
|
codeCompletionListView.PageUp(); |
|
return true; |
|
case Keys.Down: |
|
case Keys.Right: |
|
codeCompletionListView.SelectNextItem(); |
|
return true; |
|
case Keys.Up: |
|
case Keys.Left: |
|
codeCompletionListView.SelectPrevItem(); |
|
return true; |
|
case Keys.Tab: |
|
case Keys.Return: |
|
InsertSelectedItem('\0'); |
|
return true; |
|
} |
|
return base.ProcessTextAreaKey(keyData); |
|
} |
|
|
|
void CodeCompletionListViewDoubleClick(object sender, EventArgs e) |
|
{ |
|
InsertSelectedItem('\0'); |
|
} |
|
|
|
void CodeCompletionListViewClick(object sender, EventArgs e) |
|
{ |
|
control.ActiveTextAreaControl.TextArea.Focus(); |
|
} |
|
|
|
protected override void OnClosed(EventArgs e) |
|
{ |
|
base.OnClosed(e); |
|
Dispose(); |
|
codeCompletionListView.Dispose(); |
|
codeCompletionListView = null; |
|
declarationViewWindow.Dispose(); |
|
declarationViewWindow = null; |
|
} |
|
|
|
bool InsertSelectedItem(char ch) |
|
{ |
|
ICompletionData data = codeCompletionListView.SelectedCompletionData; |
|
bool result = false; |
|
if (data != null) { |
|
control.BeginUpdate(); |
|
|
|
if (endOffset - startOffset > 0) { |
|
control.Document.Remove(startOffset, endOffset - startOffset); |
|
control.ActiveTextAreaControl.Caret.Position = control.Document.OffsetToPosition(startOffset); |
|
} |
|
result = data.InsertAction(control.ActiveTextAreaControl.TextArea, ch); |
|
control.EndUpdate(); |
|
} |
|
Close(); |
|
return result; |
|
} |
|
} |
|
}
|
|
|