/contrib/ICSharpCode.TextEditor/Project/Src/Gui/CompletionWindow/CodeCompletionListView.cs
https://github.com/Ziaw/npad · C# · 293 lines · 242 code · 30 blank · 21 comment · 67 complexity · d7f8ca48fabda0c64f42057a48662068 MD5 · raw file
- // <file>
- // <copyright see="prj:///doc/copyright.txt"/>
- // <license see="prj:///doc/license.txt"/>
- // <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
- // <version>$Revision$</version>
- // </file>
- using System;
- using System.Drawing;
- using System.Windows.Forms;
- namespace ICSharpCode.TextEditor.Gui.CompletionWindow
- {
- /// <summary>
- /// Description of CodeCompletionListView.
- /// </summary>
- public class CodeCompletionListView : System.Windows.Forms.UserControl
- {
- ICompletionData[] completionData;
- int firstItem = 0;
- int selectedItem = -1;
- ImageList imageList;
-
- public ImageList ImageList {
- get {
- return imageList;
- }
- set {
- imageList = value;
- }
- }
-
- public int FirstItem {
- get {
- return firstItem;
- }
- set {
- if (firstItem != value) {
- firstItem = value;
- OnFirstItemChanged(EventArgs.Empty);
- }
- }
- }
-
- public ICompletionData SelectedCompletionData {
- get {
- if (selectedItem < 0) {
- return null;
- }
- return completionData[selectedItem];
- }
- }
-
- public int ItemHeight {
- get {
- return Math.Max(imageList.ImageSize.Height, (int)(Font.Height * 1.25));
- }
- }
-
- public int MaxVisibleItem {
- get {
- return Height / ItemHeight;
- }
- }
-
- public CodeCompletionListView(ICompletionData[] completionData)
- {
- Array.Sort(completionData, DefaultCompletionData.Compare);
- this.completionData = completionData;
-
- // this.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKey);
- // SetStyle(ControlStyles.Selectable, false);
- // SetStyle(ControlStyles.UserPaint, true);
- // SetStyle(ControlStyles.DoubleBuffer, false);
- }
-
- public void Close()
- {
- if (completionData != null) {
- Array.Clear(completionData, 0, completionData.Length);
- }
- base.Dispose();
- }
-
- public void SelectIndex(int index)
- {
- int oldSelectedItem = selectedItem;
- int oldFirstItem = firstItem;
-
- index = Math.Max(0, index);
- selectedItem = Math.Max(0, Math.Min(completionData.Length - 1, index));
- if (selectedItem < firstItem) {
- FirstItem = selectedItem;
- }
- if (firstItem + MaxVisibleItem <= selectedItem) {
- FirstItem = selectedItem - MaxVisibleItem + 1;
- }
- if (oldSelectedItem != selectedItem) {
- if (firstItem != oldFirstItem) {
- Invalidate();
- } else {
- int min = Math.Min(selectedItem, oldSelectedItem) - firstItem;
- int max = Math.Max(selectedItem, oldSelectedItem) - firstItem;
- Invalidate(new Rectangle(0, 1 + min * ItemHeight, Width, (max - min + 1) * ItemHeight));
- }
- OnSelectedItemChanged(EventArgs.Empty);
- }
- }
-
- public void CenterViewOn(int index)
- {
- int oldFirstItem = this.FirstItem;
- int firstItem = index - MaxVisibleItem / 2;
- if (firstItem < 0)
- this.FirstItem = 0;
- else if (firstItem >= completionData.Length - MaxVisibleItem)
- this.FirstItem = completionData.Length - MaxVisibleItem;
- else
- this.FirstItem = firstItem;
- if (this.FirstItem != oldFirstItem) {
- Invalidate();
- }
- }
-
- public void ClearSelection()
- {
- if (selectedItem < 0)
- return;
- int itemNum = selectedItem - firstItem;
- selectedItem = -1;
- Invalidate(new Rectangle(0, itemNum * ItemHeight, Width, (itemNum + 1) * ItemHeight + 1));
- Update();
- OnSelectedItemChanged(EventArgs.Empty);
- }
-
- public void PageDown()
- {
- SelectIndex(selectedItem + MaxVisibleItem);
- }
-
- public void PageUp()
- {
- SelectIndex(selectedItem - MaxVisibleItem);
- }
-
- public void SelectNextItem()
- {
- SelectIndex(selectedItem + 1);
- }
-
- public void SelectPrevItem()
- {
- SelectIndex(selectedItem - 1);
- }
-
- public void SelectItemWithStart(string startText)
- {
- if (startText == null || startText.Length == 0) return;
- string originalStartText = startText;
- startText = startText.ToLower();
- int bestIndex = -1;
- int bestQuality = -1;
- // Qualities: 0 = match start
- // 1 = match start case sensitive
- // 2 = full match
- // 3 = full match case sensitive
- double bestPriority = 0;
- for (int i = 0; i < completionData.Length; ++i) {
- string itemText = completionData[i].Text;
- string lowerText = itemText.ToLower();
- if (lowerText.StartsWith(startText)) {
- double priority = completionData[i].Priority;
- int quality;
- if (lowerText == startText) {
- if (itemText == originalStartText)
- quality = 3;
- else
- quality = 2;
- } else if (itemText.StartsWith(originalStartText)) {
- quality = 1;
- } else {
- quality = 0;
- }
- bool useThisItem;
- if (bestQuality < quality) {
- useThisItem = true;
- } else {
- if (bestIndex == selectedItem) {
- useThisItem = false;
- } else if (i == selectedItem) {
- useThisItem = bestQuality == quality;
- } else {
- useThisItem = bestQuality == quality && bestPriority < priority;
- }
- }
- if (useThisItem) {
- bestIndex = i;
- bestPriority = priority;
- bestQuality = quality;
- }
- }
- }
- if (bestIndex < 0) {
- ClearSelection();
- } else {
- if (bestIndex < firstItem || firstItem + MaxVisibleItem <= bestIndex) {
- SelectIndex(bestIndex);
- CenterViewOn(bestIndex);
- } else {
- SelectIndex(bestIndex);
- }
- }
- }
-
- protected override void OnPaint(PaintEventArgs pe)
- {
- float yPos = 1;
- float itemHeight = ItemHeight;
- // Maintain aspect ratio
- int imageWidth = (int)(itemHeight * imageList.ImageSize.Width / imageList.ImageSize.Height);
-
- int curItem = firstItem;
- Graphics g = pe.Graphics;
- while (curItem < completionData.Length && yPos < Height) {
- RectangleF drawingBackground = new RectangleF(1, yPos, Width - 2, itemHeight);
- if (drawingBackground.IntersectsWith(pe.ClipRectangle)) {
- // draw Background
- if (curItem == selectedItem) {
- g.FillRectangle(SystemBrushes.Highlight, drawingBackground);
- } else {
- g.FillRectangle(SystemBrushes.Window, drawingBackground);
- }
-
- // draw Icon
- int xPos = 0;
- if (imageList != null && completionData[curItem].ImageIndex < imageList.Images.Count) {
- g.DrawImage(imageList.Images[completionData[curItem].ImageIndex], new RectangleF(1, yPos, imageWidth, itemHeight));
- xPos = imageWidth;
- }
-
- // draw text
- if (curItem == selectedItem) {
- g.DrawString(completionData[curItem].Text, Font, SystemBrushes.HighlightText, xPos, yPos);
- } else {
- g.DrawString(completionData[curItem].Text, Font, SystemBrushes.WindowText, xPos, yPos);
- }
- }
-
- yPos += itemHeight;
- ++curItem;
- }
- g.DrawRectangle(SystemPens.Control, new Rectangle(0, 0, Width - 1, Height - 1));
- }
-
- protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
- {
- float yPos = 1;
- int curItem = firstItem;
- float itemHeight = ItemHeight;
-
- while (curItem < completionData.Length && yPos < Height) {
- RectangleF drawingBackground = new RectangleF(1, yPos, Width - 2, itemHeight);
- if (drawingBackground.Contains(e.X, e.Y)) {
- SelectIndex(curItem);
- break;
- }
- yPos += itemHeight;
- ++curItem;
- }
- }
-
- protected override void OnPaintBackground(PaintEventArgs pe)
- {
- }
-
- protected virtual void OnSelectedItemChanged(EventArgs e)
- {
- if (SelectedItemChanged != null) {
- SelectedItemChanged(this, e);
- }
- }
-
- protected virtual void OnFirstItemChanged(EventArgs e)
- {
- if (FirstItemChanged != null) {
- FirstItemChanged(this, e);
- }
- }
-
- public event EventHandler SelectedItemChanged;
- public event EventHandler FirstItemChanged;
- }
- }