1
2
3
4
5
6 using System;
7
8 namespace System.Screen
9 {
10 public enum InvalidateKind
11 {
12 dontInvalidate = 0, invalidateIfNotDefault = 1, forceInvalidate = 2
13 }
14
15 public class InvalidateGuard
16 {
17 public nothrow InvalidateGuard(Control* control_, InvalidateKind invalidateKind_) : control(control_), invalidateKind(invalidateKind_)
18 {
19 control->BeginInvalidate();
20 }
21 public ~InvalidateGuard()
22 {
23 control->EndInvalidate(invalidateKind);
24 }
25 private Control* control;
26 private InvalidateKind invalidateKind;
27 }
28
29 public class ControlCreateParams
30 {
31 public nothrow ControlCreateParams() : location(Point.Default()), size(Size.Default()), foreColor(ConsoleColor.defaultColor), backColor(ConsoleColor.defaultColor)
32 {
33 }
34 public nothrow ControlCreateParams& Defaults()
35 {
36 return *this;
37 }
38 public nothrow ControlCreateParams& SetLocation(const Point& location_)
39 {
40 location = location_;
41 return *this;
42 }
43 public nothrow ControlCreateParams& SetSize(const Size& size_)
44 {
45 size = size_;
46 return *this;
47 }
48 public nothrow ControlCreateParams& SetForeColor(ConsoleColor foreColor_)
49 {
50 foreColor = foreColor_;
51 return *this;
52 }
53 public nothrow ControlCreateParams& SetBackColor(ConsoleColor backColor_)
54 {
55 backColor = backColor_;
56 return *this;
57 }
58 public Point location;
59 public Size size;
60 public ConsoleColor foreColor;
61 public ConsoleColor backColor;
62 }
63
64 public enum ControlFlags
65 {
66 none = 0, disabled = 1 << 0
67 }
68
69 public class Control : Component
70 {
71 public nothrow Control(ControlCreateParams& createParams) :
72 flags(ControlFlags.none),
73 handle(-1),
74 location(createParams.location),
75 size(createParams.size),
76 foreColor(createParams.foreColor),
77 backColor(createParams.backColor),
78 invalidateCount(0)
79 {
80 Application.Instance().GetWindowManager().AddWindow(this);
81 }
82 public ~Control()
83 {
84 if (IsFocused())
85 {
86 Application.Instance().SetFocusedControl(null);
87 }
88 Application.Instance().GetWindowManager().RemoveWindow(this);
89 }
90 public nothrow int Handle() const
91 {
92 return handle;
93 }
94 public nothrow void SetHandle(int handle_)
95 {
96 handle = handle_;
97 }
98 public nothrow void SetDisabled()
99 {
100 if (!IsDisabled())
101 {
102 flags = cast<ControlFlags>(flags | ControlFlags.disabled);
103 OnEnabledChanged();
104 Invalidate(GetRect());
105 }
106 }
107 public nothrow void SetEnabled()
108 {
109 if (IsDisabled())
110 {
111 flags = cast<ControlFlags>(flags & ~ControlFlags.disabled);
112 OnEnabledChanged();
113 Invalidate(GetRect());
114 }
115 }
116 public nothrow bool IsDisabled() const
117 {
118 return (flags & ControlFlags.disabled) != ControlFlags.none;
119 }
120 public nothrow bool IsEnabled() const
121 {
122 return (flags & ControlFlags.disabled) == ControlFlags.none;
123 }
124 public nothrow const Point& Location() const
125 {
126 return location;
127 }
128 public nothrow void SetLocation(const Point& location_)
129 {
130 if (location != location_)
131 {
132 location = location_;
133 OnLocationChanged();
134 Invalidate();
135 }
136 }
137 public nothrow const Size& GetSize() const
138 {
139 return size;
140 }
141 public nothrow void SetSize(const Size& size_)
142 {
143 if (size != size_)
144 {
145 size = size_;
146 OnSizeChanged();
147 Invalidate();
148 }
149 }
150 public nothrow Rect GetRect() const
151 {
152 return Rect(location, size);
153 }
154 public nothrow Window* GetWindow() const
155 {
156 Container* container = GetContainer();
157 if (container != null)
158 {
159 Component* parent = container->Parent();
160 if (parent != null)
161 {
162 if (parent is Window*)
163 {
164 return cast<Window*>(parent);
165 }
166 else if (parent is Control*)
167 {
168 return cast<Control*>(parent)->GetWindow();
169 }
170 }
171 }
172 return null;
173 }
174 public nothrow Control* ParentControl() const
175 {
176 Container* container = GetContainer();
177 if (container != null)
178 {
179 Component* parent = container->Parent();
180 if (parent != null)
181 {
182 if (parent is Control*)
183 {
184 return cast<Control*>(parent);
185 }
186 }
187 }
188 return null;
189 }
190 public nothrow Control* NextControl() const
191 {
192 Component* nextSibling = NextSibling();
193 while (nextSibling != null)
194 {
195 if (nextSibling is Control*)
196 {
197 return cast<Control*>(nextSibling);
198 }
199 nextSibling = nextSibling->NextSibling();
200 }
201 return null;
202 }
203 public nothrow Control* PrevControl() const
204 {
205 Component* prevSibling = PrevSibling();
206 while (prevSibling != null)
207 {
208 if (prevSibling is Control*)
209 {
210 return cast<Control*>(prevSibling);
211 }
212 prevSibling = prevSibling->PrevSibling();
213 }
214 return null;
215 }
216 public nothrow Control* NextFocusableControl() const
217 {
218 Control* nextControl = NextControl();
219 while (nextControl != null)
220 {
221 if (nextControl->CanFocus())
222 {
223 return nextControl;
224 }
225 nextControl = nextControl->NextControl();
226 }
227 return null;
228 }
229 public nothrow Control* PrevFocusableControl() const
230 {
231 Control* prevControl = PrevControl();
232 while (prevControl != null)
233 {
234 if (prevControl->CanFocus())
235 {
236 return prevControl;
237 }
238 prevControl = prevControl->PrevControl();
239 }
240 return null;
241 }
242 public nothrow ConsoleColor ForeColor() const
243 {
244 return foreColor;
245 }
246 public nothrow void SetForeColor(ConsoleColor foreColor_)
247 {
248 if (foreColor != foreColor_)
249 {
250 foreColor = foreColor_;
251 OnForeColorChanged();
252 Invalidate();
253 }
254 }
255 public nothrow ConsoleColor BackColor() const
256 {
257 return backColor;
258 }
259 public nothrow void SetBackColor(ConsoleColor backColor_)
260 {
261 if (backColor != backColor_)
262 {
263 backColor = backColor_;
264 OnBackColorChanged();
265 Invalidate();
266 }
267 }
268 public nothrow void Timer(const Duration& duration, int timerId)
269 {
270 Application.Instance().Timer(duration, this, timerId);
271 }
272 public nothrow void BeginInvalidate()
273 {
274 Control* parentControl = ParentControl();
275 if (parentControl != null && parentControl->InvalidateCount() > 0)
276 {
277 return;
278 }
279 if (invalidateCount == 0)
280 {
281 updateRect = Rect();
282 }
283 ++invalidateCount;
284 }
285 public nothrow void EndInvalidate(InvalidateKind invalidateKind)
286 {
287 Control* parentControl = ParentControl();
288 if (parentControl != null && parentControl->InvalidateCount() > 0)
289 {
290 return;
291 }
292 --invalidateCount;
293 if (invalidateCount == 0 && invalidateKind != InvalidateKind.dontInvalidate)
294 {
295 if (!updateRect.IsEmpty())
296 {
297 WriteScreenMessage message(updateRect, invalidateKind);
298 message.SetTargetWindowHandle(handle);
299 Application.Instance().PostMessage(message);
300 }
301 }
302 }
303 public nothrow int InvalidateCount() const
304 {
305 return invalidateCount;
306 }
307 public void Invalidate()
308 {
309 Invalidate(Rect.Default());
310 }
311 public void Invalidate(const Rect& rect)
312 {
313 InvalidateGuard guard(this, InvalidateKind.invalidateIfNotDefault);
314 if (updateRect.IsEmpty())
315 {
316 updateRect = rect;
317 }
318 else if (rect.IsDefault())
319 {
320 updateRect = Rect.Default();
321 }
322 else
323 {
324 updateRect = Rect.Union(updateRect, rect);
325 }
326 }
327 public nothrow void SetControlCursorPos(const Point& controlCursorPos_)
328 {
329 controlCursorPos = controlCursorPos_;
330 }
331 public nothrow const Point& ControlCursorPos() const
332 {
333 return controlCursorPos;
334 }
335 public virtual nothrow bool CanFocus() const
336 {
337 return IsEnabled();
338 }
339 public nothrow bool IsFocused() const
340 {
341 return Application.Instance().FocusedControl() == this;
342 }
343 public virtual nothrow Rect FocusRect() const
344 {
345 return GetRect();
346 }
347 public virtual void SetFocus()
348 {
349 Control* prevFocusedControl = Application.Instance().FocusedControl();
350 if (prevFocusedControl != this)
351 {
352 if (prevFocusedControl != null)
353 {
354 prevFocusedControl->OnLostFocus();
355 }
356 Application.Instance().SetFocusedControl(this);
357 OnGotFocus();
358 if (prevFocusedControl != null)
359 {
360 prevFocusedControl->Invalidate(prevFocusedControl->FocusRect());
361 }
362 Invalidate(FocusRect());
363 }
364 }
365 public virtual bool HandleMessage(Message* message)
366 {
367 return message->Dispatch(this);
368 }
369 public virtual bool HandleKeyPressed(KeyPressedMessage* message)
370 {
371 KeyEventArgs args(message->Key());
372 MenuBar* menuBar = Application.Instance().GetMenuBar();
373 if (menuBar != null)
374 {
375 menuBar->OnKeyPressed(args);
376 if (menuBar->IsOpen())
377 {
378 return true;
379 }
380 }
381 if (args.Handled())
382 {
383 return true;
384 }
385 Control* focusedControl = Application.Instance().FocusedControl();
386 if (focusedControl != null)
387 {
388 focusedControl->OnKeyPressed(args);
389 if (args.Handled())
390 {
391 return true;
392 }
393 }
394 OnKeyPressed(args);
395 return args.Handled();
396 }
397 public virtual bool HandleWriteScreen(WriteScreenMessage* message)
398 {
399 WriteScreenEventArgs args(message->GetRect());
400 OnWriteScreen(args);
401 return true;
402 }
403 public virtual bool HandleTimerMessage(TimerMessage* message)
404 {
405 TimerEventArgs args(message->TimerId());
406 OnTimer(args);
407 return true;
408 }
409 public virtual void OnLocationChanged()
410 {
411 locationChangedEvent.Fire();
412 }
413 public virtual void OnSizeChanged()
414 {
415 sizeChangedEvent.Fire();
416 }
417 public virtual void OnForeColorChanged()
418 {
419 foreColorChangedEvent.Fire();
420 }
421 public virtual void OnBackColorChanged()
422 {
423 backColorChangedEvent.Fire();
424 }
425 public virtual void OnEnabledChanged()
426 {
427 enabledChangedEvent.Fire();
428 }
429 public virtual void OnGotFocus()
430 {
431 gotFocusEvent.Fire();
432 }
433 public virtual void OnLostFocus()
434 {
435 lostFocusEvent.Fire();
436 }
437 public virtual void OnWriteScreen(WriteScreenEventArgs& args)
438 {
439 writeScreenEvent.Fire(args);
440 }
441 public virtual void OnKeyPressed(KeyEventArgs& args)
442 {
443 keyPressedEvent.Fire(args);
444 }
445 public virtual void OnTimer(TimerEventArgs& args)
446 {
447 timerEvent.Fire(args);
448 }
449 public nothrow Event<ChangedEventHandler>& LocationChangedEvent()
450 {
451 return locationChangedEvent;
452 }
453 public nothrow Event<ChangedEventHandler>& SizeChangedEvent()
454 {
455 return sizeChangedEvent;
456 }
457 public nothrow Event<ChangedEventHandler>& ForeColorChangedEvent()
458 {
459 return foreColorChangedEvent;
460 }
461 public nothrow Event<ChangedEventHandler>& BackColorChangedEvent()
462 {
463 return backColorChangedEvent;
464 }
465 public nothrow Event<ChangedEventHandler>& EnabledChangedEvent()
466 {
467 return enabledChangedEvent;
468 }
469 public nothrow Event<FocusEventHandler>& GotFocusEvent()
470 {
471 return gotFocusEvent;
472 }
473 public nothrow Event<FocusEventHandler>& LostFocusEvent()
474 {
475 return lostFocusEvent;
476 }
477 public nothrow Event<WriteScreenEventHandler, WriteScreenEventArgs>& WriteScreenEvent()
478 {
479 return writeScreenEvent;
480 }
481 public nothrow Event<KeyEventHandler, KeyEventArgs>& KeyPressedEvent()
482 {
483 return keyPressedEvent;
484 }
485 public nothrow Event<TimerEventHandler, TimerEventArgs> TimerEvent()
486 {
487 return timerEvent;
488 }
489 private ControlFlags flags;
490 private int handle;
491 private Point location;
492 private Size size;
493 private ConsoleColor foreColor;
494 private ConsoleColor backColor;
495 private Event<ChangedEventHandler> locationChangedEvent;
496 private Event<ChangedEventHandler> sizeChangedEvent;
497 private Event<ChangedEventHandler> foreColorChangedEvent;
498 private Event<ChangedEventHandler> backColorChangedEvent;
499 private Event<ChangedEventHandler> enabledChangedEvent;
500 private Event<FocusEventHandler> gotFocusEvent;
501 private Event<FocusEventHandler> lostFocusEvent;
502 private Event<WriteScreenEventHandler, WriteScreenEventArgs> writeScreenEvent;
503 private Event<KeyEventHandler, KeyEventArgs> keyPressedEvent;
504 private Event<TimerEventHandler, TimerEventArgs> timerEvent;
505 private int invalidateCount;
506 private Rect updateRect;
507 private Point controlCursorPos;
508 }
509 }