1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Screen
10 {
11 public class ListBoxCreateParams
12 {
13 public ListBoxCreateParams() :
14 controlCreateParams(),
15 selectedItemForeColor(ConsoleColor.defaultColor),
16 selectedItemBackColor(ConsoleColor.defaultColor),
17 selectedItemFocusedForeColor(ConsoleColor.defaultColor),
18 selectedItemFocusedBackColor(ConsoleColor.defaultColor)
19 {
20 }
21 public nothrow ListBoxCreateParams& SetLocation(const Point& loc)
22 {
23 controlCreateParams.SetLocation(loc);
24 return *this;
25 }
26 public nothrow ListBoxCreateParams& SetSize(const Size& size_)
27 {
28 controlCreateParams.SetSize(size_);
29 return *this;
30 }
31 public nothrow ListBoxCreateParams& SetForeColor(ConsoleColor foreColor_)
32 {
33 controlCreateParams.SetForeColor(foreColor_);
34 return *this;
35 }
36 public nothrow ListBoxCreateParams& SetBackColor(ConsoleColor backColor_)
37 {
38 controlCreateParams.SetBackColor(backColor_);
39 return *this;
40 }
41 public nothrow ListBoxCreateParams& SetSelectedItemForeColor(ConsoleColor selectedItemForeColor_)
42 {
43 selectedItemForeColor = selectedItemForeColor_;
44 return *this;
45 }
46 public nothrow ListBoxCreateParams& SetSelectedItemBackColor(ConsoleColor selectedItemBackColor_)
47 {
48 selectedItemBackColor = selectedItemBackColor_;
49 return *this;
50 }
51 public nothrow ListBoxCreateParams& SetSelectedItemFocusedForeColor(ConsoleColor selectedItemFocusedForeColor_)
52 {
53 selectedItemFocusedForeColor = selectedItemFocusedForeColor_;
54 return *this;
55 }
56 public nothrow ListBoxCreateParams& SetSelectedItemFocusedBackColor(ConsoleColor selectedItemFocusedBackColor_)
57 {
58 selectedItemFocusedBackColor = selectedItemFocusedBackColor_;
59 return *this;
60 }
61 public ControlCreateParams controlCreateParams;
62 public ConsoleColor selectedItemForeColor;
63 public ConsoleColor selectedItemBackColor;
64 public ConsoleColor selectedItemFocusedForeColor;
65 public ConsoleColor selectedItemFocusedBackColor;
66 }
67
68 public class ListBox : Control
69 {
70 public nothrow ListBox(ListBoxCreateParams& createParams) :
71 base(createParams.controlCreateParams),
72 selectedItemForeColor(createParams.selectedItemForeColor),
73 selectedItemBackColor(createParams.selectedItemBackColor),
74 selectedItemFocusedForeColor(createParams.selectedItemFocusedForeColor),
75 selectedItemFocusedBackColor(createParams.selectedItemFocusedBackColor),
76 topIndex(0),
77 selectedIndex(0)
78 {
79 InvalidateGuard invalidateGuard(this, InvalidateKind.dontInvalidate);
80 if (ForeColor() == ConsoleColor.defaultColor)
81 {
82 SetForeColor(ConsoleColor.black);
83 }
84 if (BackColor() == ConsoleColor.defaultColor)
85 {
86 SetBackColor(ConsoleColor.cyan);
87 }
88 if (selectedItemForeColor == ConsoleColor.defaultColor)
89 {
90 selectedItemForeColor = ConsoleColor.gray;
91 }
92 if (selectedItemBackColor == ConsoleColor.defaultColor)
93 {
94 selectedItemBackColor = ConsoleColor.black;
95 }
96 if (selectedItemFocusedForeColor == ConsoleColor.defaultColor)
97 {
98 selectedItemFocusedForeColor = ConsoleColor.white;
99 }
100 if (selectedItemFocusedBackColor == ConsoleColor.defaultColor)
101 {
102 selectedItemFocusedBackColor = ConsoleColor.darkBlue;
103 }
104 SetControlCursorPos(Location());
105 }
106 public override nothrow Rect FocusRect() const
107 {
108 return LineRect(selectedIndex - topIndex);
109 }
110 public override void OnWriteScreen(WriteScreenEventArgs& args)
111 {
112 base->OnWriteScreen(args);
113 bool focused = IsFocused();
114 Rect updateRect = GetRect();
115 if (!args.GetRect().IsDefault())
116 {
117 updateRect = Rect.Intersection(updateRect, args.GetRect());
118 }
119 if (updateRect.IsEmpty()) return;
120 Clear(updateRect, ForeColor(), BackColor());
121 Point loc = Location();
122 Rect rect = GetRect();
123 int n = Min(rect.size.h, Max(cast<int>(0), cast<int>(items.Count() - topIndex)));
124 for (int i = 0; i < n; ++i;)
125 {
126 int index = topIndex + i;
127 Rect lineRect = LineRect(i);
128 if (lineRect.IntersectsWith(updateRect))
129 {
130 SetCursorPos(loc.x, loc.y + i);
131 ConsoleColor foreColor = ForeColor();
132 ConsoleColor backColor = BackColor();
133 if (index == selectedIndex)
134 {
135 if (focused)
136 {
137 foreColor = selectedItemFocusedForeColor;
138 backColor = selectedItemFocusedBackColor;
139 }
140 else
141 {
142 foreColor = selectedItemForeColor;
143 backColor = selectedItemBackColor;
144 }
145 }
146 Terminal.Out() << SetColors(foreColor, backColor) << items[index];
147 }
148 }
149 }
150 public override void OnKeyPressed(KeyEventArgs& args)
151 {
152 base->OnKeyPressed(args);
153 Size sz = GetSize();
154 if (!args.Handled())
155 {
156 int prevTopIndex = topIndex;
157 if (args.Key() == keyNewline)
158 {
159 topIndex = 0;
160 OnItemSelected();
161 args.SetHandled();
162 }
163 else
164 {
165 switch (args.Key())
166 {
167 case keyDown:
168 {
169 if (selectedIndex < items.Count() - 1)
170 {
171 Rect updateRect = LineRect(selectedIndex - topIndex);
172 ++selectedIndex;
173 if (selectedIndex >= topIndex + sz.h)
174 {
175 ++topIndex;
176 }
177 updateRect = Rect.Union(updateRect, LineRect(selectedIndex - topIndex));
178 OnSelectedIndexChanged();
179 if (topIndex == prevTopIndex)
180 {
181 Invalidate(updateRect);
182 }
183 else
184 {
185 InvalidateGuard invalidateGuard(this, InvalidateKind.forceInvalidate);
186 Invalidate();
187 }
188 args.SetHandled();
189 }
190 break;
191 }
192 case keyUp:
193 {
194 if (selectedIndex > 0)
195 {
196 Rect updateRect = LineRect(selectedIndex - topIndex);
197 --selectedIndex;
198 if (selectedIndex < topIndex)
199 {
200 --topIndex;
201 }
202 updateRect = Rect.Union(updateRect, LineRect(selectedIndex - topIndex));
203 OnSelectedIndexChanged();
204 if (topIndex == prevTopIndex)
205 {
206 Invalidate(updateRect);
207 }
208 else
209 {
210 InvalidateGuard invalidateGuard(this, InvalidateKind.forceInvalidate);
211 Invalidate();
212 }
213 args.SetHandled();
214 }
215 break;
216 }
217 case keyHome:
218 {
219 if (selectedIndex != 0)
220 {
221 Rect updateRect = LineRect(selectedIndex - topIndex);
222 selectedIndex = 0;
223 topIndex = 0;
224 updateRect = Rect.Union(updateRect, LineRect(selectedIndex - topIndex));
225 OnSelectedIndexChanged();
226 if (topIndex == prevTopIndex)
227 {
228 Invalidate(updateRect);
229 }
230 else
231 {
232 InvalidateGuard invalidateGuard(this, InvalidateKind.forceInvalidate);
233 Invalidate();
234 }
235 args.SetHandled();
236 }
237 break;
238 }
239 case keyEnd:
240 {
241 if (selectedIndex != items.Count() - 1)
242 {
243 Rect updateRect = LineRect(selectedIndex - topIndex);
244 selectedIndex = cast<int>(items.Count() - 1);
245 topIndex = cast<int>(items.Count() - sz.h);
246 if (topIndex < 0)
247 {
248 topIndex = 0;
249 }
250 updateRect = Rect.Union(updateRect, LineRect(selectedIndex - topIndex));
251 OnSelectedIndexChanged();
252 if (topIndex == prevTopIndex)
253 {
254 Invalidate(updateRect);
255 }
256 else
257 {
258 InvalidateGuard invalidateGuard(this, InvalidateKind.forceInvalidate);
259 Invalidate();
260 }
261 args.SetHandled();
262 }
263 break;
264 }
265 case keyPgDown:
266 {
267 if (selectedIndex < items.Count() - 1)
268 {
269 Rect updateRect = LineRect(selectedIndex - topIndex);
270 selectedIndex = Max(cast<int>(0), Min(cast<int>(items.Count() - 1), selectedIndex + sz.h));
271 topIndex = topIndex + sz.h;
272 if (topIndex + sz.h > items.Count())
273 {
274 topIndex = Max(cast<int>(0), cast<int>(items.Count() - sz.h));
275 }
276 updateRect = Rect.Union(updateRect, LineRect(selectedIndex - topIndex));
277 OnSelectedIndexChanged();
278 if (topIndex == prevTopIndex)
279 {
280 Invalidate(updateRect);
281 }
282 else
283 {
284 InvalidateGuard invalidateGuard(this, InvalidateKind.forceInvalidate);
285 Invalidate();
286 }
287 args.SetHandled();
288 }
289 break;
290 }
291 case keyPgUp:
292 {
293 if (selectedIndex > 0)
294 {
295 Rect updateRect = LineRect(selectedIndex - topIndex);
296 selectedIndex = Max(cast<int>(0), selectedIndex - sz.h);
297 topIndex = Max(cast<int>(0), topIndex - sz.h);
298 updateRect = Rect.Union(updateRect, LineRect(selectedIndex - topIndex));
299 OnSelectedIndexChanged();
300 if (topIndex == prevTopIndex)
301 {
302 Invalidate(updateRect);
303 }
304 else
305 {
306 InvalidateGuard invalidateGuard(this, InvalidateKind.forceInvalidate);
307 Invalidate();
308 }
309 args.SetHandled();
310 }
311 break;
312 }
313 }
314 }
315 }
316 }
317 public nothrow long ItemCount() const
318 {
319 return items.Count();
320 }
321 public void AddItem(const ustring& item)
322 {
323 items.Add(item);
324 }
325 public const ustring& GetItem(int index) const
326 {
327 return items[index];
328 }
329 public void Clear()
330 {
331 items.Clear();
332 }
333 public nothrow int SelectedIndex() const
334 {
335 return selectedIndex;
336 }
337 public nothrow void SetSelectedIndex(int selectedIndex_)
338 {
339 if (selectedIndex != selectedIndex_)
340 {
341 Size sz = GetSize();
342 selectedIndex = selectedIndex_;
343 topIndex = selectedIndex;
344 if (topIndex + sz.h > items.Count())
345 {
346 topIndex = Max(cast<int>(0), cast<int>(items.Count() - sz.h));
347 }
348 }
349 }
350 public virtual void OnSelectedIndexChanged()
351 {
352 Point loc = Location();
353 int index = selectedIndex - topIndex;
354 loc.y = loc.y + index;
355 SetControlCursorPos(loc);
356 selectedIndexChangedEvent.Fire();
357 }
358 public virtual void OnItemSelected()
359 {
360 itemSelectedEvent.Fire();
361 }
362 public nothrow Event<ChangedEventHandler>& SelectedIndexChangedEvent()
363 {
364 return selectedIndexChangedEvent;
365 }
366 public nothrow Event<SelectEventHandler>& ItemSelectedEvent()
367 {
368 return itemSelectedEvent;
369 }
370 private nothrow Rect LineRect(int i) const
371 {
372 Point loc = Location();
373 loc.y = loc.y + i;
374 Size sz = GetSize();
375 sz.h = 1;
376 return Rect(loc, sz);
377 }
378 private ConsoleColor selectedItemForeColor;
379 private ConsoleColor selectedItemBackColor;
380 private ConsoleColor selectedItemFocusedForeColor;
381 private ConsoleColor selectedItemFocusedBackColor;
382 private List<ustring> items;
383 private int topIndex;
384 private int selectedIndex;
385 private Event<ChangedEventHandler> selectedIndexChangedEvent;
386 private Event<SelectEventHandler> itemSelectedEvent;
387 }
388 }
389