1
2
3
4
5
6 using System;
7
8 namespace System.Windows
9 {
10 public enum BorderStyle : sbyte
11 {
12 single, style3D
13 }
14
15 public inline int DefaultSingleBorderWidth()
16 {
17 return 1;
18 }
19
20 public inline int Default3DBorderWidth()
21 {
22 return 2;
23 }
24
25 public int GetBorderWidth(BorderStyle borderStyle)
26 {
27 switch (borderStyle)
28 {
29 case BorderStyle.single: return DefaultSingleBorderWidth();
30 case BorderStyle.style3D: return Default3DBorderWidth();
31 }
32 return 0;
33 }
34
35 public Color DefaultBorderedControlNormalBorderdColor()
36 {
37 return Color.Black();
38 }
39
40 public Color DefaultBorderedControlFocusedBorderColor()
41 {
42 return Color.Blue();
43 }
44
45 public ControlCreateParams& BorderedControlControlCreateParams(ControlCreateParams& controlCreateParams, Control* child)
46 {
47 return controlCreateParams.SetWindowClassName("System.Windows.BorderedControl").SetBackgroundColor(child->BackgroundColor());
48 }
49
50 public class BorderedControlCreateParams
51 {
52 public BorderedControlCreateParams(ControlCreateParams& controlCreateParams_, Control* child_) :
53 controlCreateParams(controlCreateParams_),
54 child(child_),
55 borderStyle(BorderStyle.single),
56 borderWidth(GetBorderWidth(borderStyle)),
57 normalBorderColor(DefaultBorderedControlNormalBorderdColor()),
58 focusedBorderColor(DefaultBorderedControlFocusedBorderColor())
59 {
60 }
61 public BorderedControlCreateParams& Defaults()
62 {
63 return *this;
64 }
65 public BorderedControlCreateParams& SetBorderStyle(BorderStyle borderStyle_)
66 {
67 borderStyle = borderStyle_;
68 return *this;
69 }
70 public BorderedControlCreateParams& SetBorderWidth(int borderWidth_)
71 {
72 borderWidth = borderWidth_;
73 return *this;
74 }
75 public BorderedControlCreateParams& SetNormalBorderColor(const Color& normalBorderColor_)
76 {
77 normalBorderColor = normalBorderColor_;
78 return *this;
79 }
80 public BorderedControlCreateParams& SetFocusedBorderColor(const Color& focusedBorderColor_)
81 {
82 focusedBorderColor = focusedBorderColor_;
83 return *this;
84 }
85 public ControlCreateParams& controlCreateParams;
86 public Control* child;
87 public BorderStyle borderStyle;
88 public int borderWidth;
89 public Color normalBorderColor;
90 public Color focusedBorderColor;
91 }
92
93 public class BorderedControl : Control
94 {
95 private enum Flags : sbyte
96 {
97 none = 0, childFocused = 1 << 0
98 }
99 public BorderedControl(Control* child_, BorderStyle borderStyle_, const Color& normalBorderColor_, const Color& focusedBorderColor_,
100 const Point& location, const Size& size, Dock dock, Anchors anchors) :
101 base("System.Windows.BorderedControl", DefaultWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
102 child_->BackgroundColor(), "borderedControl", location, size, dock, anchors),
103 container(this), borderStyle(borderStyle_), normalBorderColor(normalBorderColor_), focusedBorderColor(focusedBorderColor_),
104 borderWidth(GetBorderWidth(borderStyle)), child(child_)
105 {
106 auto result = container.AddChild(child);
107 if (result.Error())
108 {
109 SetErrorId(result.GetErrorId());
110 return;
111 }
112 result = SetChildPos();
113 if (result.Error())
114 {
115 SetErrorId(result.GetErrorId());
116 return;
117 }
118 }
119 public BorderedControl(Control* child, BorderStyle borderStyle, const Point& location, const Size& size, Dock dock, Anchors anchors) :
120 this(child, borderStyle, Color.Black(), Color.Blue(), location, size, dock, anchors)
121 {
122 }
123 public BorderedControl(Control* child, const Point& location, const Size& size, Dock dock, Anchors anchors) :
124 this(child, BorderStyle.single, location, size, dock, anchors)
125 {
126 }
127 public explicit BorderedControl(Control* child) : this(child, Point(), Size(), Dock.none, Anchors.none)
128 {
129 }
130 public BorderedControl(BorderedControlCreateParams& createParams) :
131 base(createParams.controlCreateParams),
132 container(this),
133 borderStyle(createParams.borderStyle),
134 borderWidth(createParams.borderWidth),
135 normalBorderColor(createParams.normalBorderColor),
136 focusedBorderColor(createParams.focusedBorderColor),
137 child(createParams.child),
138 flags(Flags.none)
139 {
140 auto result = container.AddChild(child);
141 if (result.Error())
142 {
143 SetErrorId(result.GetErrorId());
144 return;
145 }
146 result = SetChildPos();
147 if (result.Error())
148 {
149 SetErrorId(result.GetErrorId());
150 return;
151 }
152 }
153 [nodiscard]
154 public Result<bool> SetNormalBorderColor(const Color& normalBorderColor_)
155 {
156 if (normalBorderColor != normalBorderColor_)
157 {
158 normalBorderColor = normalBorderColor_;
159 auto result = Invalidate();
160 if (result.Error()) return result;
161 }
162 return Result<bool>(true);
163 }
164 [nodiscard]
165 public Result<bool> SetFocusedBorderColor(const Color& focusedBorderColor_)
166 {
167 if (focusedBorderColor != focusedBorderColor_)
168 {
169 focusedBorderColor = focusedBorderColor_;
170 auto result = Invalidate();
171 if (result.Error()) return result;
172 }
173 return Result<bool>(true);
174 }
175 [nodiscard]
176 public Result<bool> SetBorderWidth(int borderWidth_)
177 {
178 borderWidth = borderWidth_;
179 auto result = Invalidate();
180 if (result.Error()) return result;
181 return Result<bool>(true);
182 }
183 protected override bool IsDecoratorControl() const
184 {
185 return true;
186 }
187 public override ContainerControl* GetContainerControl() const
188 {
189 if (child is ContainerControl*)
190 {
191 return cast<ContainerControl*>(child);
192 }
193 return base->GetContainerControl();
194 }
195 internal override Control* GetFirstEnabledTabStopControl() const
196 {
197 return child->GetFirstEnabledTabStopControl();
198 }
199 internal override Control* GetLastEnabledTabStopControl() const
200 {
201 return child->GetLastEnabledTabStopControl();
202 }
203 protected override void OnChildContentLocationChanged(ControlEventArgs& args)
204 {
205 base->OnChildContentLocationChanged(args);
206 Control* parentControl = ParentControl();
207 if (parentControl != null)
208 {
209 parentControl->OnChildContentLocationChanged(args);
210 }
211 }
212 protected override void OnChildContentChanged(ControlEventArgs& args)
213 {
214 base->OnChildContentChanged(args);
215 Control* parentControl = ParentControl();
216 if (parentControl != null)
217 {
218 parentControl->OnChildContentChanged(args);
219 }
220 }
221 [nodiscard]
222 protected override Result<bool> OnChildContentSizeChanged(ControlEventArgs& args)
223 {
224 auto result = base->OnChildContentSizeChanged(args);
225 if (result.Error()) return result;
226 Control* parentControl = ParentControl();
227 if (parentControl != null)
228 {
229 result = parentControl->OnChildContentSizeChanged(args);
230 if (result.Error()) return result;
231 }
232 return Result<bool>(true);
233 }
234 [nodiscard]
235 protected override Result<bool> OnChildGotFocus(ControlEventArgs& args)
236 {
237 auto result = base->OnChildGotFocus(args);
238 if (result.Error()) return result;
239 SetChildFocused();
240 Control* parentControl = ParentControl();
241 if (parentControl != null)
242 {
243 result = parentControl->OnChildGotFocus(args);
244 if (result.Error()) return result;
245 }
246 result = Invalidate();
247 if (result.Error()) return result;
248 return Result<bool>(true);
249 }
250 [nodiscard]
251 protected override Result<bool> OnChildLostFocus(ControlEventArgs& args)
252 {
253 auto result = base->OnChildLostFocus(args);
254 if (result.Error()) return result;
255 ResetChildFocused();
256 Control* parentControl = ParentControl();
257 if (parentControl != null)
258 {
259 result = parentControl->OnChildLostFocus(args);
260 if (result.Error()) return result;
261 }
262 result = Invalidate();
263 if (result.Error()) return result;
264 return Result<bool>(true);
265 }
266 [nodiscard]
267 public override Result<bool> PrintWindowTree(int level)
268 {
269 LogView* log = Application.GetLogView();
270 if (log != null)
271 {
272 auto handleResult = ToHexString(cast<ulong>(Handle()));
273 if (handleResult.Error())
274 {
275 return Result<bool>(ErrorId(handleResult.GetErrorId()));
276 }
277 auto parentTextResult = ParentText();
278 if (parentTextResult.Error())
279 {
280 return Result<bool>(ErrorId(parentTextResult.GetErrorId()));
281 }
282 auto locationResult = Location();
283 if (locationResult.Error())
284 {
285 return Result<bool>(ErrorId(locationResult.GetErrorId()));
286 }
287 auto result = log->WriteLine(string(' ', level) + "BorderedControl." + Text() + ".handle=" + handleResult.Value() + " " +
288 parentTextResult.Value() + "[" + Rect(locationResult.Value(), GetSize()).ToString() + "]");
289 if (result.Error()) return result;
290 }
291 Component* child = container.FirstChild();
292 while (child != null)
293 {
294 if (child is Control*)
295 {
296 Control* childControl = cast<Control*>(child);
297 auto result = childControl->PrintWindowTree(level + 1);
298 if (result.Error())
299 {
300 return Result<bool>(ErrorId(result.GetErrorId()));
301 }
302 }
303 child = child->NextSibling();
304 }
305 return Result<bool>(true);
306 }
307 [nodiscard]
308 protected override Result<bool> OnLocationChanged()
309 {
310 auto result = base->OnLocationChanged();
311 if (result.Error()) return result;
312 result = SetChildPos();
313 if (result.Error()) return result;
314 return Result<bool>(true);
315 }
316 [nodiscard]
317 protected override Result<bool> OnSizeChanged(SizeChangedEventArgs& args)
318 {
319 auto result = base->OnSizeChanged(args);
320 if (result.Error()) return result;
321 result = SetChildPos();
322 if (result.Error()) return result;
323 return Result<bool>(true);
324 }
325 [nodiscard]
326 protected override Result<bool> OnChildSizeChanged(ControlEventArgs& args)
327 {
328 auto result = base->OnChildSizeChanged(args);
329 if (result.Error()) return result;
330 Control* parentControl = ParentControl();
331 if (parentControl != null)
332 {
333 result = parentControl->FireChildSizeChanged(args);
334 if (result.Error()) return result;
335 }
336 return Result<bool>(true);
337 }
338 [nodiscard]
339 protected override Result<bool> OnPaint(PaintEventArgs& args)
340 {
341 if (Debug.Paint())
342 {
343 Rect r(Point(), GetSize());
344 LogView* log = Application.GetLogView();
345 if (log != null)
346 {
347 auto result = log->WriteLine("BorderedControl.OnPaint: " + r.ToString());
348 if (result.Error()) return result;
349 }
350 }
351 auto result = DrawBorder(args.graphics);
352 if (result.Error())
353 {
354 return Result<bool>(ErrorId(result.GetErrorId()));
355 }
356 return base->OnPaint(args);
357 }
358 [nodiscard]
359 private Result<bool> SetChildPos()
360 {
361 Point loc;
362 Size size = GetSize();
363 Rect childRect(loc, size);
364 childRect.Inflate(-borderWidth, -borderWidth);
365 auto result = child->SetLocation(childRect.location);
366 if (result.Error()) return result;
367 result = child->SetSize(childRect.size);
368 if (result.Error()) return result;
369 return Result<bool>(true);
370 }
371 private Result<bool> DrawBorder(Graphics& graphics)
372 {
373 switch (borderStyle)
374 {
375 case BorderStyle.single:
376 {
377 auto result = DrawSingleBorder(graphics);
378 if (result.Error())
379 {
380 return Result<bool>(ErrorId(result.GetErrorId()));
381 }
382 break;
383 }
384 case BorderStyle.style3D:
385 {
386 auto result = Draw3DBorder(graphics);
387 if (result.Error())
388 {
389 return Result<bool>(ErrorId(result.GetErrorId()));
390 }
391 break;
392 }
393 }
394 return Result<bool>(true);
395 }
396 private Result<bool> DrawSingleBorder(Graphics& graphics)
397 {
398 Rect r(Point(), GetSize());
399 r.size.w = r.size.w - 1;
400 r.size.h = r.size.h - 1;
401 if (ChildFocused())
402 {
403 Pen pen(focusedBorderColor, 1);
404 if (pen.Error())
405 {
406 return Result<bool>(ErrorId(pen.GetErrorId()));
407 }
408 auto drawResult = graphics.DrawRectangle(pen, r);
409 if (drawResult.Error())
410 {
411 return Result<bool>(ErrorId(drawResult.GetErrorId()));
412 }
413 }
414 else
415 {
416 Pen pen(normalBorderColor, 1);
417 if (pen.Error())
418 {
419 return Result<bool>(ErrorId(pen.GetErrorId()));
420 }
421 auto drawResult = graphics.DrawRectangle(pen, r);
422 if (drawResult.Error())
423 {
424 return Result<bool>(ErrorId(drawResult.GetErrorId()));
425 }
426 }
427 return Result<bool>(true);
428 }
429 private Result<bool> Draw3DBorder(Graphics& graphics)
430 {
431 Rect r(Point(), GetSize());
432 r.size.w = r.size.w - 1;
433 r.size.h = r.size.h - 1;
434 Pen outerLeftTopEdgePen(Color(160u, 160u, 160u), 1);
435 if (outerLeftTopEdgePen.Error())
436 {
437 return Result<bool>(ErrorId(outerLeftTopEdgePen.GetErrorId()));
438 }
439 auto drawResult = graphics.DrawLine(outerLeftTopEdgePen, r.location, Point(r.location.x + r.size.w - 1, r.location.y));
440 if (drawResult.Error())
441 {
442 return Result<bool>(ErrorId(drawResult.GetErrorId()));
443 }
444 drawResult = graphics.DrawLine(outerLeftTopEdgePen, r.location, Point(r.location.x, r.location.y + r.size.h - 1));
445 if (drawResult.Error())
446 {
447 return Result<bool>(ErrorId(drawResult.GetErrorId()));
448 }
449 Pen outerRightBottomEdgePen(Color.White(), 1);
450 if (outerRightBottomEdgePen.Error())
451 {
452 return Result<bool>(ErrorId(outerRightBottomEdgePen.GetErrorId()));
453 }
454 drawResult = graphics.DrawLine(outerRightBottomEdgePen, Point(r.location.x + r.size.w, r.location.y), Point(r.location.x + r.size.w, r.location.y + r.size.h));
455 if (drawResult.Error())
456 {
457 return Result<bool>(ErrorId(drawResult.GetErrorId()));
458 }
459 drawResult = graphics.DrawLine(outerRightBottomEdgePen, Point(r.location.x, r.location.y + r.size.h), Point(r.location.x + r.size.w, r.location.y + r.size.h));
460 if (drawResult.Error())
461 {
462 return Result<bool>(ErrorId(drawResult.GetErrorId()));
463 }
464 r.Inflate(-1, -1);
465 Pen innerLeftTopEdgePen(Color(105u, 105u, 105u), 1);
466 if (innerLeftTopEdgePen.Error())
467 {
468 return Result<bool>(ErrorId(innerLeftTopEdgePen.GetErrorId()));
469 }
470 drawResult = graphics.DrawLine(innerLeftTopEdgePen, r.location, Point(r.location.x + r.size.w - 1, r.location.y));
471 if (drawResult.Error())
472 {
473 return Result<bool>(ErrorId(drawResult.GetErrorId()));
474 }
475 drawResult = graphics.DrawLine(innerLeftTopEdgePen, r.location, Point(r.location.x, r.location.y + r.size.h - 1));
476 if (drawResult.Error())
477 {
478 return Result<bool>(ErrorId(drawResult.GetErrorId()));
479 }
480 Pen innerRightBottomEdgePen(Color(227u, 227u, 227u), 1);
481 if (innerRightBottomEdgePen.Error())
482 {
483 return Result<bool>(ErrorId(innerRightBottomEdgePen.GetErrorId()));
484 }
485 drawResult = graphics.DrawLine(innerRightBottomEdgePen, Point(r.location.x + r.size.w, r.location.y), Point(r.location.x + r.size.w, r.location.y + r.size.h));
486 if (drawResult.Error())
487 {
488 return Result<bool>(ErrorId(drawResult.GetErrorId()));
489 }
490 drawResult = graphics.DrawLine(innerRightBottomEdgePen, Point(r.location.x, r.location.y + r.size.h), Point(r.location.x + r.size.w, r.location.y + r.size.h));
491 if (drawResult.Error())
492 {
493 return Result<bool>(ErrorId(drawResult.GetErrorId()));
494 }
495 return Result<bool>(true);
496 }
497 private inline bool ChildFocused() const
498 {
499 return (flags & Flags.childFocused) != Flags.none;
500 }
501 private inline void SetChildFocused()
502 {
503 flags = cast<Flags>(flags | Flags.childFocused);
504 }
505 private inline void ResetChildFocused()
506 {
507 flags = cast<Flags>(flags & ~Flags.childFocused);
508 }
509 private ComponentContainer container;
510 private BorderStyle borderStyle;
511 private int borderWidth;
512 private Color normalBorderColor;
513 private Color focusedBorderColor;
514 private Control* child;
515 private Flags flags;
516 }