1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Windows
10 {
11 public abstract class ContainerControl : Control
12 {
13 public ContainerControl(const string& windowClassName, WindowClassStyle windowClassStyle, WindowStyle style, ExtendedWindowStyle exStyle,
14 const Color& backgroundColor, const string& text, const Point& location, const Size& size, Dock dock, Anchors anchors) :
15 base(windowClassName, windowClassStyle, style, exStyle, backgroundColor, text, location, size, dock, anchors), children(this)
16 {
17 }
18 public ContainerControl(ControlCreateParams& createParams) : base(createParams), children(this)
19 {
20 }
21 [nodiscard]
22 public Result<bool> AddChild(Control* child)
23 {
24 auto result = children.AddChild(child);
25 if (result.Error()) return result;
26 ControlEventArgs args(child);
27 result = OnControlAdded(args);
28 if (result.Error()) return result;
29 if (args.errorId != 0)
30 {
31 return Result<bool>(ErrorId(args.errorId));
32 }
33 return Result<bool>(true);
34 }
35 [nodiscard]
36 public Result<UniquePtr<Control>> RemoveChild(Control* child)
37 {
38 UniquePtr<Component> childComponent = children.RemoveChild(child);
39 ControlEventArgs args(child);
40 auto result = OnControlRemoved(args);
41 if (result.Error())
42 {
43 return Result<UniquePtr<Control>>(ErrorId(result.GetErrorId()));
44 }
45 return UniquePtr<Control>(childComponent.Release() as Control*);
46 }
47 [nodiscard]
48 public Result<bool> InsertChildBefore(Control* child, Control* before)
49 {
50 auto result = children.InsertBefore(child, before);
51 if (result.Error()) return result;
52 ControlEventArgs args(child);
53 result = OnControlAdded(args);
54 if (result.Error()) return result;
55 if (args.errorId != 0)
56 {
57 return Result<bool>(ErrorId(args.errorId));
58 }
59 return Result<bool>(true);
60 }
61 [nodiscard]
62 public Result<bool> InsertChildAfter(Control* child, Control* after)
63 {
64 auto result = children.InsertAfter(child, after);
65 if (result.Error()) return result;
66 ControlEventArgs args(child);
67 result = OnControlAdded(args);
68 if (result.Error()) return result;
69 if (args.errorId != 0)
70 {
71 return Result<bool>(ErrorId(args.errorId));
72 }
73 return Result<bool>(true);
74 }
75 public const ComponentContainer& Children() const
76 {
77 return children;
78 }
79 public override ContainerControl* GetContainerControl() const
80 {
81 return this;
82 }
83 internal override Control* GetFirstEnabledTabStopControl() const
84 {
85 Component* child = children.FirstChild();
86 while (child != null)
87 {
88 if (child is Control*)
89 {
90 Control* control = cast<Control*>(child);
91 Control* tabStopChild = control->GetFirstEnabledTabStopControl();
92 if (tabStopChild != null)
93 {
94 return tabStopChild;
95 }
96 }
97 child = child->NextSibling();
98 }
99 return null;
100 }
101 internal override Control* GetLastEnabledTabStopControl() const
102 {
103 Component* child = children.LastChild();
104 while (child != null)
105 {
106 if (child is Control*)
107 {
108 Control* control = cast<Control*>(child);
109 Control* tabStopChild = control->GetLastEnabledTabStopControl();
110 if (tabStopChild != null)
111 {
112 return tabStopChild;
113 }
114 }
115 child = child->PrevSibling();
116 }
117 return null;
118 }
119 [nodiscard]
120 protected override Result<bool> OnSizeChanging(SizeChangingEventArgs& args)
121 {
122 auto result = base->OnSizeChanging(args);
123 if (result.Error()) return result;
124 int dx = args.newSize.w - args.oldSize.w;
125 int dy = args.newSize.h - args.oldSize.h;
126 result = MoveChildren(dx, dy);
127 if (result.Error()) return result;
128 return Result<bool>(true);
129 }
130 [nodiscard]
131 protected override Result<bool> OnChildSizeChanged(ControlEventArgs& args)
132 {
133 auto result = base->OnChildSizeChanged(args);
134 if (result.Error()) return result;
135 Control* parentControl = ParentControl();
136 if (parentControl != null)
137 {
138 result = parentControl->FireChildSizeChanged(args);
139 if (result.Error()) return result;
140 }
141 return Result<bool>(true);
142 }
143 protected override void OnChildContentLocationChanged(ControlEventArgs& args)
144 {
145 base->OnChildContentLocationChanged(args);
146 Control* parentControl = ParentControl();
147 if (parentControl != null)
148 {
149 parentControl->OnChildContentLocationChanged(args);
150 }
151 }
152 protected override void OnChildContentChanged(ControlEventArgs& args)
153 {
154 base->OnChildContentChanged(args);
155 Control* parentControl = ParentControl();
156 if (parentControl != null)
157 {
158 parentControl->OnChildContentChanged(args);
159 }
160 }
161 [nodiscard]
162 protected override Result<bool> OnChildContentSizeChanged(ControlEventArgs& args)
163 {
164 auto result = base->OnChildContentSizeChanged(args);
165 if (result.Error()) return result;
166 Control* parentControl = ParentControl();
167 if (parentControl != null)
168 {
169 result = parentControl->OnChildContentSizeChanged(args);
170 if (result.Error()) return result;
171 }
172 return Result<bool>(true);
173 }
174 [nodiscard]
175 protected override Result<bool> OnChildGotFocus(ControlEventArgs& args)
176 {
177 auto result = base->OnChildGotFocus(args);
178 if (result.Error()) return result;
179 Control* parentControl = ParentControl();
180 if (parentControl != null)
181 {
182 result = parentControl->OnChildGotFocus(args);
183 if (result.Error()) return result;
184 }
185 return Result<bool>(true);
186 }
187 [nodiscard]
188 protected override Result<bool> OnChildLostFocus(ControlEventArgs& args)
189 {
190 auto result = base->OnChildLostFocus(args);
191 if (result.Error()) return result;
192 Control* parentControl = ParentControl();
193 if (parentControl != null)
194 {
195 result = parentControl->OnChildLostFocus(args);
196 if (result.Error()) return result;
197 }
198 return Result<bool>(true);
199 }
200 [nodiscard]
201 public override Result<bool> PrintWindowTree(int level)
202 {
203 LogView* log = Application.GetLogView();
204 if (log != null)
205 {
206 auto handleResult = ToHexString(cast<ulong>(Handle()));
207 if (handleResult.Error())
208 {
209 return Result<bool>(ErrorId(handleResult.GetErrorId()));
210 }
211 else
212 {
213 const string& handleStr = handleResult.Value();
214 auto parentTextResult = ParentText();
215 if (parentTextResult.Error())
216 {
217 return Result<bool>(ErrorId(parentTextResult.GetErrorId()));
218 }
219 else
220 {
221 const string& parentText = parentTextResult.Value();
222 auto result = log->WriteLine(string(' ', level) + "ContainerControl." + Text() + ".handle=" + handleStr + " " +
223 parentText + "[" + Rect(Point(), GetSize()).ToString() + "]");
224 if (result.Error()) return result;
225 }
226 }
227 }
228 Component* child = children.FirstChild();
229 while (child != null)
230 {
231 if (child is Control*)
232 {
233 Control* childControl = cast<Control*>(child);
234 auto result = childControl->PrintWindowTree(level + 1);
235 if (result.Error())
236 {
237 return Result<bool>(ErrorId(result.GetErrorId()));
238 }
239 }
240 child = child->NextSibling();
241 }
242 return Result<bool>(true);
243 }
244 [nodiscard]
245 protected override Result<bool> ProcessMessage(Message& message)
246 {
247 switch (message.msg)
248 {
249 case WM_SIZE:
250 {
251 Size newSize = message.LParamSize();
252 Size oldSize = GetSize();
253 if (newSize != oldSize)
254 {
255 Rect parentRect(Point(), newSize);
256 int dx = newSize.w - oldSize.w;
257 int dy = newSize.h - oldSize.h;
258 auto result = MoveChildren(dx, dy);
259 if (result.Error()) return result;
260 uint windowState = cast<uint>(message.wparam);
261 result = SetSizeInternal(newSize, windowState);
262 if (result.Error()) return result;
263 result = DockChildren();
264 if (result.Error()) return result;
265 SizeChangedEventArgs args(windowState);
266 result = OnSizeChanged(args);
267 if (result.Error()) return result;
268 }
269 message.result = 0;
270 return Result<bool>(true);
271 }
272 case WM_PAINT: case WM_MOVE: case WM_MOUSEMOVE: case WM_MOUSELEAVE: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP:
273 case WM_CHAR: case WM_KEYDOWN: case WM_KEYUP: case WM_SYSCOMMAND: case WM_HSCROLL: case WM_VSCROLL: case WM_MOUSEWHEEL:
274 case WM_SETFOCUS: case WM_KILLFOCUS: case WM_TIMER: case WM_COMMAND: case WM_SHOWWINDOW: case WM_CLIPBOARDUPDATE:
275 {
276 return base->ProcessMessage(message);
277 }
278 }
279 return Result<bool>(false);
280 }
281 [nodiscard]
282 public Result<bool> MoveChildren(int dx, int dy)
283 {
284 Component* child = children.FirstChild();
285 while (child != null)
286 {
287 if (child is Control*)
288 {
289 Control* childControl = cast<Control*>(child);
290 if (childControl->GetDock() == Dock.none)
291 {
292 auto result = childControl->MoveWindow(dx, dy);
293 if (result.Error()) return result;
294 }
295 }
296 child = child->NextSibling();
297 }
298 return Result<bool>(true);
299 }
300 [nodiscard]
301 public Result<bool> DockChildren()
302 {
303 Rect parentRect(Point(), GetSize());
304 return DockChildren(parentRect);
305 }
306 [nodiscard]
307 public Result<bool> DockChildren(Rect& parentRect)
308 {
309 List<Control*> filledControls;
310 List<ContainerControl*> containers;
311 Component* child = children.FirstChild();
312 while (child != null)
313 {
314 if (child is Control*)
315 {
316 Control* childControl = cast<Control*>(child);
317 switch (childControl->GetDock())
318 {
319 case Dock.none: break;
320 case Dock.fill: filledControls.Add(childControl); break;
321 default:
322 {
323 auto result = childControl->DockWindow(parentRect);
324 if (result.Error()) return result;
325 break;
326 }
327 }
328 if (childControl is ContainerControl*)
329 {
330 ContainerControl* containerChild = cast<ContainerControl*>(childControl);
331 containers.Add(containerChild);
332 }
333 }
334 child = child->NextSibling();
335 }
336 for (Control* filledControl : filledControls)
337 {
338 auto result = filledControl->DockWindow(parentRect);
339 if (result.Error()) return result;
340 }
341 for (ContainerControl* container : containers)
342 {
343 auto result = container->DockChildren();
344 if (result.Error()) return result;
345 }
346 return Result<bool>(true);
347 }
348 [nodiscard]
349 internal override Result<bool> PaintAll(PaintEventArgs& args, bool skipMenuBar)
350 {
351 auto baseResult = base->PaintAll(args, skipMenuBar);
352 if (baseResult.Error())
353 {
354 return Result<bool>(ErrorId(baseResult.GetErrorId()));
355 }
356 Control* topControl = TopControl();
357 Component* child = children.FirstChild();
358 while (child != null)
359 {
360 if (child is Control*)
361 {
362 Control* childControl = cast<Control*>(child);
363 if (childControl != topControl)
364 {
365 bool skip = false;
366 if (skipMenuBar)
367 {
368 if (childControl is MenuBar*)
369 {
370 skip = true;
371 }
372 else if (childControl is MenuBox*)
373 {
374 MenuBox* menuBox = cast<MenuBox*>(childControl);
375 if (!menuBox->PaintThisMenuBox())
376 {
377 skip = true;
378 }
379 }
380 }
381 if (!skip)
382 {
383 auto saveResult = args.graphics.Save();
384 if (saveResult.Error())
385 {
386 return Result<bool>(ErrorId(saveResult.GetErrorId()));
387 }
388 GraphicsState state = saveResult.Value();
389 Result<Point> locResult = childControl->Location();
390 if (locResult.Error())
391 {
392 return Result<bool>(ErrorId(locResult.GetErrorId()));
393 }
394 Point loc = locResult.Value();
395 auto childLocResult = childControl->Location();
396 if (childLocResult.Error())
397 {
398 return Result<bool>(ErrorId(childLocResult.GetErrorId()));
399 }
400 Point childLoc = childLocResult.Value();
401 auto setClipResult = args.graphics.SetClip(Rect(childLoc, childControl->GetSize()));
402 if (setClipResult.Error())
403 {
404 return Result<bool>(ErrorId(setClipResult.GetErrorId()));
405 }
406 auto translateResult = args.graphics.TranslateTransform(loc.x, loc.y);
407 if (translateResult.Error())
408 {
409 return Result<bool>(ErrorId(translateResult.GetErrorId()));
410 }
411 auto childResult = childControl->PaintAll(args, skipMenuBar);
412 if (childResult.Error())
413 {
414 return Result<bool>(ErrorId(childResult.GetErrorId()));
415 }
416 auto restoreResult = args.graphics.Restore(state);
417 if (restoreResult.Error())
418 {
419 return Result<bool>(ErrorId(restoreResult.GetErrorId()));
420 }
421 }
422 }
423 }
424 child = child->NextSibling();
425 }
426 if (topControl != null)
427 {
428 auto saveResult = args.graphics.Save();
429 if (saveResult.Error())
430 {
431 return Result<bool>(ErrorId(saveResult.GetErrorId()));
432 }
433 GraphicsState state = saveResult.Value();
434 auto locResult = topControl->Location();
435 if (locResult.Error())
436 {
437 return Result<bool>(ErrorId(locResult.GetErrorId()));
438 }
439 Point loc = locResult.Value();
440 auto setClipResult = args.graphics.SetClip(Rect(loc, topControl->GetSize()));
441 if (setClipResult.Error())
442 {
443 return Result<bool>(ErrorId(setClipResult.GetErrorId()));
444 }
445 auto translateResult = args.graphics.TranslateTransform(loc.x, loc.y);
446 if (translateResult.Error())
447 {
448 return Result<bool>(ErrorId(translateResult.GetErrorId()));
449 }
450 auto topResult = topControl->PaintAll(args, skipMenuBar);
451 if (topResult.Error())
452 {
453 return Result<bool>(ErrorId(topResult.GetErrorId()));
454 }
455 auto restoreResult = args.graphics.Restore(state);
456 if (restoreResult.Error())
457 {
458 return Result<bool>(ErrorId(restoreResult.GetErrorId()));
459 }
460 }
461 return Result<bool>(true);
462 }
463 private ComponentContainer children;
464 }