Code Coverage Statistics for Source File
c:\Tools\SD3\src\Libraries\ICSharpCode.TextEditor\Project\Src\Gui\CompletionWindow\CodeCompletionListView.cs
|
Sequence Point Coverage
N/A
0 of 0
|
Branch Coverage
N/A
0 of 0
|
Lines
293
|
Highlight:
Uncovered Code
Covered Code
| L | V | Source |
|---|---|---|
1 |
// <file> |
|
2 |
// <copyright see="prj:///doc/copyright.txt"/> |
|
3 |
// <license see="prj:///doc/license.txt"/> |
|
4 |
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/> |
|
5 |
// <version>$Revision: 2533 $</version> |
|
6 |
// </file> |
|
7 |
||
8 |
using System; |
|
9 |
using System.Drawing; |
|
10 |
using System.Windows.Forms; |
|
11 |
||
12 |
namespace ICSharpCode.TextEditor.Gui.CompletionWindow |
|
13 |
{ |
|
14 |
/// <summary> |
|
15 |
/// Description of CodeCompletionListView. |
|
16 |
/// </summary> |
|
17 |
public class CodeCompletionListView : System.Windows.Forms.UserControl |
|
18 |
{ |
|
19 |
ICompletionData[] completionData; |
|
20 |
int firstItem = 0; |
|
21 |
int selectedItem = -1; |
|
22 |
ImageList imageList; |
|
23 |
||
24 |
public ImageList ImageList { |
|
25 |
get { |
|
26 |
return imageList; |
|
27 |
} |
|
28 |
set { |
|
29 |
imageList = value; |
|
30 |
} |
|
31 |
} |
|
32 |
||
33 |
public int FirstItem { |
|
34 |
get { |
|
35 |
return firstItem; |
|
36 |
} |
|
37 |
set { |
|
38 |
if (firstItem != value) { |
|
39 |
firstItem = value; |
|
40 |
OnFirstItemChanged(EventArgs.Empty); |
|
41 |
} |
|
42 |
} |
|
43 |
} |
|
44 |
||
45 |
public ICompletionData SelectedCompletionData { |
|
46 |
get { |
|
47 |
if (selectedItem < 0) { |
|
48 |
return null; |
|
49 |
} |
|
50 |
return completionData[selectedItem]; |
|
51 |
} |
|
52 |
} |
|
53 |
||
54 |
public int ItemHeight { |
|
55 |
get { |
|
56 |
return Math.Max(imageList.ImageSize.Height, (int)(Font.Height * 1.25)); |
|
57 |
} |
|
58 |
} |
|
59 |
||
60 |
public int MaxVisibleItem { |
|
61 |
get { |
|
62 |
return Height / ItemHeight; |
|
63 |
} |
|
64 |
} |
|
65 |
||
66 |
public CodeCompletionListView(ICompletionData[] completionData) |
|
67 |
{ |
|
68 |
Array.Sort(completionData); |
|
69 |
this.completionData = completionData; |
|
70 |
||
71 |
// this.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKey); |
|
72 |
// SetStyle(ControlStyles.Selectable, false); |
|
73 |
// SetStyle(ControlStyles.UserPaint, true); |
|
74 |
// SetStyle(ControlStyles.DoubleBuffer, false); |
|
75 |
} |
|
76 |
||
77 |
public void Close() |
|
78 |
{ |
|
79 |
if (completionData != null) { |
|
80 |
Array.Clear(completionData, 0, completionData.Length); |
|
81 |
} |
|
82 |
base.Dispose(); |
|
83 |
} |
|
84 |
||
85 |
public void SelectIndex(int index) |
|
86 |
{ |
|
87 |
int oldSelectedItem = selectedItem; |
|
88 |
int oldFirstItem = firstItem; |
|
89 |
||
90 |
index = Math.Max(0, index); |
|
91 |
selectedItem = Math.Max(0, Math.Min(completionData.Length - 1, index)); |
|
92 |
if (selectedItem < firstItem) { |
|
93 |
FirstItem = selectedItem; |
|
94 |
} |
|
95 |
if (firstItem + MaxVisibleItem <= selectedItem) { |
|
96 |
FirstItem = selectedItem - MaxVisibleItem + 1; |
|
97 |
} |
|
98 |
if (oldSelectedItem != selectedItem) { |
|
99 |
if (firstItem != oldFirstItem) { |
|
100 |
Invalidate(); |
|
101 |
} else { |
|
102 |
int min = Math.Min(selectedItem, oldSelectedItem) - firstItem; |
|
103 |
int max = Math.Max(selectedItem, oldSelectedItem) - firstItem; |
|
104 |
Invalidate(new Rectangle(0, 1 + min * ItemHeight, Width, (max - min + 1) * ItemHeight)); |
|
105 |
} |
|
106 |
OnSelectedItemChanged(EventArgs.Empty); |
|
107 |
} |
|
108 |
} |
|
109 |
||
110 |
public void CenterViewOn(int index) |
|
111 |
{ |
|
112 |
int oldFirstItem = this.FirstItem; |
|
113 |
int firstItem = index - MaxVisibleItem / 2; |
|
114 |
if (firstItem < 0) |
|
115 |
this.FirstItem = 0; |
|
116 |
else if (firstItem >= completionData.Length - MaxVisibleItem) |
|
117 |
this.FirstItem = completionData.Length - MaxVisibleItem; |
|
118 |
else |
|
119 |
this.FirstItem = firstItem; |
|
120 |
if (this.FirstItem != oldFirstItem) { |
|
121 |
Invalidate(); |
|
122 |
} |
|
123 |
} |
|
124 |
||
125 |
public void ClearSelection() |
|
126 |
{ |
|
127 |
if (selectedItem < 0) |
|
128 |
return; |
|
129 |
int itemNum = selectedItem - firstItem; |
|
130 |
selectedItem = -1; |
|
131 |
Invalidate(new Rectangle(0, itemNum * ItemHeight, Width, (itemNum + 1) * ItemHeight + 1)); |
|
132 |
Update(); |
|
133 |
OnSelectedItemChanged(EventArgs.Empty); |
|
134 |
} |
|
135 |
||
136 |
public void PageDown() |
|
137 |
{ |
|
138 |
SelectIndex(selectedItem + MaxVisibleItem); |
|
139 |
} |
|
140 |
||
141 |
public void PageUp() |
|
142 |
{ |
|
143 |
SelectIndex(selectedItem - MaxVisibleItem); |
|
144 |
} |
|
145 |
||
146 |
public void SelectNextItem() |
|
147 |
{ |
|
148 |
SelectIndex(selectedItem + 1); |
|
149 |
} |
|
150 |
||
151 |
public void SelectPrevItem() |
|
152 |
{ |
|
153 |
SelectIndex(selectedItem - 1); |
|
154 |
} |
|
155 |
||
156 |
public void SelectItemWithStart(string startText) |
|
157 |
{ |
|
158 |
if (startText == null || startText.Length == 0) return; |
|
159 |
string originalStartText = startText; |
|
160 |
startText = startText.ToLower(); |
|
161 |
int bestIndex = -1; |
|
162 |
int bestQuality = -1; |
|
163 |
// Qualities: 0 = match start |
|
164 |
// 1 = match start case sensitive |
|
165 |
// 2 = full match |
|
166 |
// 3 = full match case sensitive |
|
167 |
double bestPriority = 0; |
|
168 |
for (int i = 0; i < completionData.Length; ++i) { |
|
169 |
string itemText = completionData[i].Text; |
|
170 |
string lowerText = itemText.ToLower(); |
|
171 |
if (lowerText.StartsWith(startText)) { |
|
172 |
double priority = completionData[i].Priority; |
|
173 |
int quality; |
|
174 |
if (lowerText == startText) { |
|
175 |
if (itemText == originalStartText) |
|
176 |
quality = 3; |
|
177 |
else |
|
178 |
quality = 2; |
|
179 |
} else if (itemText.StartsWith(originalStartText)) { |
|
180 |
quality = 1; |
|
181 |
} else { |
|
182 |
quality = 0; |
|
183 |
} |
|
184 |
bool useThisItem; |
|
185 |
if (bestQuality < quality) { |
|
186 |
useThisItem = true; |
|
187 |
} else { |
|
188 |
if (bestIndex == selectedItem) { |
|
189 |
useThisItem = false; |
|
190 |
} else if (i == selectedItem) { |
|
191 |
useThisItem = bestQuality == quality; |
|
192 |
} else { |
|
193 |
useThisItem = bestQuality == quality && bestPriority < priority; |
|
194 |
} |
|
195 |
} |
|
196 |
if (useThisItem) { |
|
197 |
bestIndex = i; |
|
198 |
bestPriority = priority; |
|
199 |
bestQuality = quality; |
|
200 |
} |
|
201 |
} |
|
202 |
} |
|
203 |
if (bestIndex < 0) { |
|
204 |
ClearSelection(); |
|
205 |
} else { |
|
206 |
if (bestIndex < firstItem || firstItem + MaxVisibleItem <= bestIndex) { |
|
207 |
SelectIndex(bestIndex); |
|
208 |
CenterViewOn(bestIndex); |
|
209 |
} else { |
|
210 |
SelectIndex(bestIndex); |
|
211 |
} |
|
212 |
} |
|
213 |
} |
|
214 |
||
215 |
protected override void OnPaint(PaintEventArgs pe) |
|
216 |
{ |
|
217 |
float yPos = 1; |
|
218 |
float itemHeight = ItemHeight; |
|
219 |
// Maintain aspect ratio |
|
220 |
int imageWidth = (int)(itemHeight * imageList.ImageSize.Width / imageList.ImageSize.Height); |
|
221 |
||
222 |
int curItem = firstItem; |
|
223 |
Graphics g = pe.Graphics; |
|
224 |
while (curItem < completionData.Length && yPos < Height) { |
|
225 |
RectangleF drawingBackground = new RectangleF(1, yPos, Width - 2, itemHeight); |
|
226 |
if (drawingBackground.IntersectsWith(pe.ClipRectangle)) { |
|
227 |
// draw Background |
|
228 |
if (curItem == selectedItem) { |
|
229 |
g.FillRectangle(SystemBrushes.Highlight, drawingBackground); |
|
230 |
} else { |
|
231 |
g.FillRectangle(SystemBrushes.Window, drawingBackground); |
|
232 |
} |
|
233 |
||
234 |
// draw Icon |
|
235 |
int xPos = 0; |
|
236 |
if (imageList != null && completionData[curItem].ImageIndex < imageList.Images.Count) { |
|
237 |
g.DrawImage(imageList.Images[completionData[curItem].ImageIndex], new RectangleF(1, yPos, imageWidth, itemHeight)); |
|
238 |
xPos = imageWidth; |
|
239 |
} |
|
240 |
||
241 |
// draw text |
|
242 |
if (curItem == selectedItem) { |
|
243 |
g.DrawString(completionData[curItem].Text, Font, SystemBrushes.HighlightText, xPos, yPos); |
|
244 |
} else { |
|
245 |
g.DrawString(completionData[curItem].Text, Font, SystemBrushes.WindowText, xPos, yPos); |
|
246 |
} |
|
247 |
} |
|
248 |
||
249 |
yPos += itemHeight; |
|
250 |
++curItem; |
|
251 |
} |
|
252 |
g.DrawRectangle(SystemPens.Control, new Rectangle(0, 0, Width - 1, Height - 1)); |
|
253 |
} |
|
254 |
||
255 |
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e) |
|
256 |
{ |
|
257 |
float yPos = 1; |
|
258 |
int curItem = firstItem; |
|
259 |
float itemHeight = ItemHeight; |
|
260 |
||
261 |
while (curItem < completionData.Length && yPos < Height) { |
|
262 |
RectangleF drawingBackground = new RectangleF(1, yPos, Width - 2, itemHeight); |
|
263 |
if (drawingBackground.Contains(e.X, e.Y)) { |
|
264 |
SelectIndex(curItem); |
|
265 |
break; |
|
266 |
} |
|
267 |
yPos += itemHeight; |
|
268 |
++curItem; |
|
269 |
} |
|
270 |
} |
|
271 |
||
272 |
protected override void OnPaintBackground(PaintEventArgs pe) |
|
273 |
{ |
|
274 |
} |
|
275 |
||
276 |
protected virtual void OnSelectedItemChanged(EventArgs e) |
|
277 |
{ |
|
278 |
if (SelectedItemChanged != null) { |
|
279 |
SelectedItemChanged(this, e); |
|
280 |
} |
|
281 |
} |
|
282 |
||
283 |
protected virtual void OnFirstItemChanged(EventArgs e) |
|
284 |
{ |
|
285 |
if (FirstItemChanged != null) { |
|
286 |
FirstItemChanged(this, e); |
|
287 |
} |
|
288 |
} |
|
289 |
||
290 |
public event EventHandler SelectedItemChanged; |
|
291 |
public event EventHandler FirstItemChanged; |
|
292 |
} |
|
293 |
} |