1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Windows
10 {
11 public class delegate void TreeViewNodeMouseClickEventHandler(TreeViewNodeMouseClickEventArgs& args);
12 public class delegate void TreeViewNodeEventHandler(TreeViewNodeEventArgs& args);
13
14 public nothrow string DefaultTreeViewNormalNodeFontFamilyName()
15 {
16 return "Segoe UI";
17 }
18
19 public nothrow float DefaultTreeViewNormalNodeFontSize()
20 {
21 return 9.0f;
22 }
23
24 public nothrow FontStyle DefaultTreeViewNormalNodeFontStyle()
25 {
26 return FontStyle.regular;
27 }
28
29 public nothrow string DefaultTreeViewActiveNodeFontFamilyName()
30 {
31 return "Segoe UI";
32 }
33
34 public nothrow float DefaultTreeViewActiveNodeFontSize()
35 {
36 return 9.0f;
37 }
38
39 public nothrow FontStyle DefaultTreeViewActiveNodeFontStyle()
40 {
41 return FontStyle.bold;
42 }
43
44 public nothrow Color DefaultTreeViewBackgroundColor()
45 {
46 return Color.White();
47 }
48
49 public nothrow Color DefaultTreeViewStateIndicatorColor()
50 {
51 return Color.Red();
52 }
53
54 public nothrow Color DefaultTreeViewNodeSelectedColor()
55 {
56 return Color(201u, 222u, 245u);
57 }
58
59 public nothrow float DefaultTreeViewStateIndicatorPercentage()
60 {
61 return 50.0f;
62 }
63
64 public nothrow float DefaultTreeViewNodeIndentPercent()
65 {
66 return 200.0f;
67 }
68
69 public nothrow float DefaultTreeViewNodeTextIndentPercent()
70 {
71 return 100.0f;
72 }
73
74 public nothrow Padding DefaultTreeViewNodeImagePadding()
75 {
76 return Padding(0, 0, 0, 0);
77 }
78
79 public nothrow ControlCreateParams& TreeViewControlCreateParams(ControlCreateParams& controlCreateParams)
80 {
81 return controlCreateParams.SetWindowClassName("System.Windows.TreeView").SetWindowClassStyle(DoubleClickWindowClassStyle()).
82 SetWindowClassBackgroundColor(SystemColor.COLOR_WINDOW).SetBackgroundColor(DefaultTreeViewBackgroundColor());
83 }
84
85 public class TreeViewCreateParams
86 {
87 public nothrow TreeViewCreateParams(ControlCreateParams& controlCreateParams_) :
88 controlCreateParams(controlCreateParams_),
89 normalNodeFontFamilyName(DefaultTreeViewNormalNodeFontFamilyName()),
90 normalNodeFontSize(DefaultTreeViewNormalNodeFontSize()),
91 normalNodeFontStyle(DefaultTreeViewNormalNodeFontStyle()),
92 activeNodeFontFamilyName(DefaultTreeViewActiveNodeFontFamilyName()),
93 activeNodeFontSize(DefaultTreeViewActiveNodeFontSize()),
94 activeNodeFontStyle(DefaultTreeViewActiveNodeFontStyle()),
95 stateIndicatorColor(DefaultTreeViewStateIndicatorColor()),
96 nodeSelectedColor(DefaultTreeViewNodeSelectedColor()),
97 stateIndicatorPercentage(DefaultTreeViewStateIndicatorPercentage()),
98 nodeIndentPercent(DefaultTreeViewNodeIndentPercent()),
99 nodeTextIndentPercent(DefaultTreeViewNodeTextIndentPercent()),
100 nodeImagePadding(DefaultTreeViewNodeImagePadding())
101 {
102 }
103 public nothrow TreeViewCreateParams& Defaults()
104 {
105 return *this;
106 }
107 public nothrow TreeViewCreateParams& SetNormalNodeFontFamilyName(const string& normalNodeFontFamilyName_)
108 {
109 normalNodeFontFamilyName = normalNodeFontFamilyName_;
110 return *this;
111 }
112 public nothrow TreeViewCreateParams& SetNormalNodeFontSize(float normalNodeFontSize_)
113 {
114 normalNodeFontSize = normalNodeFontSize_;
115 return *this;
116 }
117 public nothrow TreeViewCreateParams& SetNormalNodeFontStyle(FontStyle normalNodeFontStyle_)
118 {
119 normalNodeFontStyle = normalNodeFontStyle_;
120 return *this;
121 }
122 public nothrow TreeViewCreateParams& SetActiveNodeFontFamilyName(const string& activeNodeFontFamilyName_)
123 {
124 activeNodeFontFamilyName = activeNodeFontFamilyName_;
125 return *this;
126 }
127 public nothrow TreeViewCreateParams& SetActiveNodeFontSize(float activeNodeFontSize_)
128 {
129 activeNodeFontSize = activeNodeFontSize_;
130 return *this;
131 }
132 public nothrow TreeViewCreateParams& SetActiveNodeFontStyle(FontStyle activeNodeFontStyle_)
133 {
134 activeNodeFontStyle = activeNodeFontStyle_;
135 return *this;
136 }
137 public nothrow TreeViewCreateParams& SetStateIndicatorColor(const Color& stateIndicatorColor_)
138 {
139 stateIndicatorColor = stateIndicatorColor_;
140 return *this;
141 }
142 public nothrow TreeViewCreateParams& SetNodeSelectedColor(const Color& nodeSelectedColor_)
143 {
144 nodeSelectedColor = nodeSelectedColor_;
145 return *this;
146 }
147 public nothrow TreeViewCreateParams& SetTextColor(const Color& textColor_)
148 {
149 textColor = textColor_;
150 return *this;
151 }
152 public nothrow TreeViewCreateParams& SetStateIndicatorPercentage(float stateIndicatorPercentage_)
153 {
154 stateIndicatorPercentage = stateIndicatorPercentage_;
155 return *this;
156 }
157 public nothrow TreeViewCreateParams& SetNodeIndentPercent(float nodeIndentPercent_)
158 {
159 nodeIndentPercent = nodeIndentPercent_;
160 return *this;
161 }
162 public nothrow TreeViewCreateParams& SetNodeTextIndentPercent(float nodeTextIndentPercent_)
163 {
164 nodeTextIndentPercent = nodeTextIndentPercent_;
165 return *this;
166 }
167 public nothrow TreeViewCreateParams& SetNodeImagePadding(const Padding& nodeImagePadding_)
168 {
169 nodeImagePadding = nodeImagePadding_;
170 return *this;
171 }
172 public ControlCreateParams& controlCreateParams;
173 public string normalNodeFontFamilyName;
174 public float normalNodeFontSize;
175 public FontStyle normalNodeFontStyle;
176 public string activeNodeFontFamilyName;
177 public float activeNodeFontSize;
178 public FontStyle activeNodeFontStyle;
179 public Color stateIndicatorColor;
180 public Color nodeSelectedColor;
181 public Color textColor;
182 public float stateIndicatorPercentage;
183 public float nodeIndentPercent;
184 public float nodeTextIndentPercent;
185 public Padding nodeImagePadding;
186 }
187
188 public class TreeView : Control
189 {
190 private enum Flags : sbyte
191 {
192 none = 0, changed = 1 << 0, treeViewNodeChanged = 1 << 1, treeViewNodeStateChanged = 1 << 2, toolTipWindowAdded = 1 << 3
193 }
194 public TreeView(const Font& normalNodeFont_, const Font& activeNodeFont_,
195 const Color& backgroundColor, const Color& stateIndicatorColor_, const Color& nodeSelectedColor_, const Color& textColor_,
196 const Point& location, const Size& size, Dock dock, Anchors anchors) :
197 base("System.Windows.TreeView", DoubleClickWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
198 backgroundColor, "treeView",
199 location, size, dock, anchors), flags(Flags.none), root(), normalNodeFont(normalNodeFont_), activeNodeFont(activeNodeFont_),
200 textHeight(0), stateIndicatorPercentage(50.0f),
201 stateIndicatorColor(stateIndicatorColor_), nodeSelectedColor(nodeSelectedColor_), nodeSelectedBrush(nodeSelectedColor),
202 textColor(textColor_), textBrush(textColor),
203 nodeIndentPercent(DefaultTreeViewNodeIndentPercent()),
204 nodeTextIndentPercent(DefaultTreeViewNodeTextIndentPercent()),
205 format(StringAlignment.near, StringAlignment.near), bitmapIndex(-1), animationMs(5), selectedNode(null), trackedNode(null),
206 toolTipWindow(new ToolTip())
207 {
208 SetChanged();
209 SetMouseHoverMs(DefaultMouseHoverMs());
210 }
211 public TreeView(const Point& location, const Size& size, Dock dock, Anchors anchors) :
212 this(Font(FontFamily("Segoe UI"), 9.0f), Font(FontFamily("Segoe UI"), 9.0f, FontStyle.bold, Unit.point),
213 Color.White(), Color.Red(), Color(201u, 222u, 245u), Color.Black(), location, size, dock, anchors)
214 {
215 }
216 public TreeView(TreeViewCreateParams& createParams) :
217 base(createParams.controlCreateParams),
218 flags(Flags.none), root(),
219 normalNodeFont(
220 Font(FontFamily(createParams.normalNodeFontFamilyName),
221 createParams.normalNodeFontSize,
222 createParams.normalNodeFontStyle,
223 Unit.point)),
224 activeNodeFont(
225 Font(FontFamily(createParams.activeNodeFontFamilyName),
226 createParams.activeNodeFontSize,
227 createParams.activeNodeFontStyle,
228 Unit.point)),
229 textHeight(0), stateIndicatorPercentage(createParams.stateIndicatorPercentage),
230 stateIndicatorColor(createParams.stateIndicatorColor),
231 nodeSelectedColor(createParams.nodeSelectedColor), nodeSelectedBrush(nodeSelectedColor),
232 textColor(createParams.textColor), textBrush(textColor),
233 nodeIndentPercent(createParams.nodeIndentPercent),
234 nodeTextIndentPercent(createParams.nodeTextIndentPercent),
235 nodeImagePadding(createParams.nodeImagePadding),
236 format(StringAlignment.near, StringAlignment.near), bitmapIndex(-1), animationMs(5),
237 selectedNode(null), trackedNode(null), toolTipWindow(new ToolTip())
238 {
239 SetChanged();
240 SetMouseHoverMs(DefaultMouseHoverMs());
241 }
242 public ~TreeView()
243 {
244 if (toolTipWindow != null && ToolTipWindowAdded())
245 {
246 ResetToolTipWindowAdded();
247 Window* window = GetWindow();
248 if (window != null)
249 {
250 window->RemoveChild(toolTipWindow);
251 toolTipWindow = null;
252 }
253 }
254 }
255 public override void PrintWindowTree(int level)
256 {
257 LogView* log = Application.GetLogView();
258 if (log != null)
259 {
260 log->WriteLine(string(' ', level) + "TreeView." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point(), GetSize()).ToString() + "]");
261 }
262 }
263 public void EnsureNodeVisible(TreeViewNode* node)
264 {
265 Size size = GetSize();
266 Point contentLocation = ContentLocation();
267 Point nodeLocation = node->Location();
268 if (nodeLocation.y >= contentLocation.y && nodeLocation.y < contentLocation.y + size.h)
269 {
270 return;
271 }
272 if (nodeLocation.y > contentLocation.y)
273 {
274 int y = nodeLocation.y - Max(cast<int>(0), cast<int>(size.h - 2 * textHeight));
275 Point newOrigin(0, y);
276 SetContentLocation(newOrigin);
277 Invalidate();
278 }
279 else
280 {
281 int y = nodeLocation.y;
282 Point newOrigin(0, y);
283 SetContentLocation(newOrigin);
284 Invalidate();
285 }
286 }
287 public nothrow bool NodeVisible(TreeViewNode* node) const
288 {
289 Size size = GetSize();
290 Point contentLocation = ContentLocation();
291 Point nodeLocation = node->Location();
292 if (nodeLocation.y >= contentLocation.y && nodeLocation.y < contentLocation.y + size.h)
293 {
294 return true;
295 }
296 else
297 {
298 return false;
299 }
300 }
301 public List<TreeViewNode*> GetVisibleNodes(int level) const
302 {
303 List<TreeViewNode*> visibleNodes;
304 root->GetVisibleNodes(visibleNodes, this, level);
305 return visibleNodes;
306 }
307 public List<TreeViewNode*> GetVisibleNodes() const
308 {
309 return GetVisibleNodes(-1);
310 }
311 protected override void OnPaint(PaintEventArgs& args)
312 {
313 try
314 {
315 if (Debug.Paint())
316 {
317 Rect r(Point(), GetSize());
318 LogView* log = Application.GetLogView();
319 if (log != null)
320 {
321 log->WriteLine("TreeView.OnPaint: " + r.ToString());
322 }
323 }
324 if (!ToolTipWindowAdded())
325 {
326 SetToolTipWindowAdded();
327 Window* window = GetWindow();
328 if (window != null)
329 {
330 window->AddChild(toolTipWindow);
331 }
332 }
333 if (Changed())
334 {
335 ResetChanged();
336 Measure(args.graphics);
337 MakeStateIndicatorBitmaps(args.graphics);
338 SetTreeViewNodeChanged();
339 SetTreeViewNodeStateChanged();
340 }
341 if (TreeViewNodeChanged())
342 {
343 ResetTreeViewNodeChanged();
344 if (!root.IsNull())
345 {
346 root->MeasureSize(args.graphics, this);
347 }
348 }
349 if (TreeViewNodeStateChanged())
350 {
351 ResetTreeViewNodeStateChanged();
352 if (!root.IsNull())
353 {
354 Rect r(Point(), GetSize());
355 r.size.w = r.size.w - 1;
356 r.size.h = r.size.h - 1;
357 int idx = 0;
358 Rect rect;
359 root->Measure(args.graphics, r.location, this, 0, idx, rect);
360 SetContentSize(rect.size);
361 }
362 }
363 args.graphics.Clear(BackgroundColor());
364 if (bitmapIndex != -1)
365 {
366 Point location;
367 PointF loc(location.x, location.y);
368 args.graphics.DrawImage(stateIndicatorBitmaps[bitmapIndex], loc);
369 }
370 else
371 {
372 if (!root.IsNull())
373 {
374 root->Draw(args.graphics, this);
375 }
376 base->OnPaint(args);
377 }
378 }
379 catch (const Exception& ex)
380 {
381 MessageBox.Show(ex.Message());
382 }
383 }
384 public inline nothrow TreeViewNode* Root() const
385 {
386 return root.Get();
387 }
388 public nothrow TreeViewNode* ReleaseRoot()
389 {
390 return root.Release();
391 }
392 public nothrow void ResetRoot(TreeViewNode* root_)
393 {
394 root.Reset(root_);
395 }
396 public nothrow void SetRoot(TreeViewNode* root_)
397 {
398 if (!root.IsNull())
399 {
400 root->SetTreeView(null);
401 }
402 root.Reset(root_);
403 SetContentLocation(Point(0, 0));
404 if (!root.IsNull())
405 {
406 root->SetTreeView(this);
407 SetTreeViewNodeChanged();
408 SetTreeViewNodeStateChanged();
409 SetContentChanged();
410 }
411 SetChanged();
412 Invalidate();
413 }
414 public inline nothrow const Font& GetNormalNodeFont() const
415 {
416 return normalNodeFont;
417 }
418 public inline nothrow const Font& GetActiveNodeFont() const
419 {
420 return activeNodeFont;
421 }
422 public nothrow void SetNormalNodeFont(const Font& normalNodeFont_)
423 {
424 normalNodeFont = normalNodeFont_;
425 SetChanged();
426 }
427 public nothrow void SetActiveNodeFont(const Font& activeNodeFont_)
428 {
429 activeNodeFont = activeNodeFont_;
430 SetChanged();
431 }
432 public inline nothrow const SolidBrush& TextBrush() const
433 {
434 return textBrush;
435 }
436 public inline nothrow const SolidBrush& NodeSelectedBrush() const
437 {
438 return nodeSelectedBrush;
439 }
440 public inline nothrow float TextHeight() const
441 {
442 return textHeight;
443 }
444 public inline nothrow float StateIndicatorPercentage() const
445 {
446 return stateIndicatorPercentage;
447 }
448 public inline nothrow void SetStateIndicatorPercentage(float stateIndicatorPercentage_)
449 {
450 stateIndicatorPercentage = stateIndicatorPercentage_;
451 SetChanged();
452 }
453 public inline nothrow float StateIndicatorHeight() const
454 {
455 return stateIndicatorHeight;
456 }
457 public inline nothrow const Color& StateIndicatorColor() const
458 {
459 return stateIndicatorColor;
460 }
461 public void SetStateIndicatorColor(const Color& stateIndicatorColor_)
462 {
463 stateIndicatorColor = stateIndicatorColor_;
464 SetChanged();
465 }
466 public inline nothrow const Color& NodeSelectedColor() const
467 {
468 return nodeSelectedColor;
469 }
470 public nothrow void SetNodeSelectedColor(const Color& nodeSelectedColor_)
471 {
472 if (nodeSelectedColor != nodeSelectedColor_)
473 {
474 nodeSelectedColor = nodeSelectedColor_;
475 nodeSelectedBrush = SolidBrush(nodeSelectedColor);
476 }
477 }
478 public inline nothrow const Color& TextColor() const
479 {
480 return textColor;
481 }
482 public void SetTextColor(const Color& textColor_)
483 {
484 if (textColor != textColor_)
485 {
486 textColor = textColor_;
487 textBrush = SolidBrush(textColor);
488 SetChanged();
489 }
490 }
491 public inline nothrow float NodeIndentPercent() const
492 {
493 return nodeIndentPercent;
494 }
495 public inline nothrow float NodeTextIndentPercent() const
496 {
497 return nodeTextIndentPercent;
498 }
499 public inline nothrow int AnimationMs() const
500 {
501 return animationMs;
502 }
503 public nothrow void SetAnimationMs(int animationMs_)
504 {
505 animationMs = animationMs_;
506 }
507 public void ShowToolTipWindow(const string& toolTipText, TreeViewNode* node)
508 {
509 toolTipWindow->Hide();
510 Point loc = node->Location();
511 Size size = node->GetSize();
512 Point pt(loc.x, loc.y + size.h + 4);
513 if (!node->Children().IsEmpty())
514 {
515 pt.x = pt.x + cast<int>(textHeight + 2.0f);
516 }
517 TranslateContentLocation(pt);
518 pt = ClientToScreen(pt);
519 toolTipWindow->SetText(toolTipText);
520 toolTipWindow->MeasureExtent();
521 Window* window = GetWindow();
522 if (window != null)
523 {
524 pt = window->ScreenToClient(pt);
525 Size sz = toolTipWindow->GetSize();
526 Point wloc = window->Location();
527 Size wsz = window->GetSize();
528 if (pt.y + sz.h > wloc.y + wsz.h)
529 {
530 pt.y = wloc.y + wsz.h - sz.h;
531 }
532 if (pt.x + sz.w > wloc.x + wsz.w)
533 {
534 pt.x = wloc.x + wsz.w - sz.w;
535 }
536 toolTipWindow->SetLocation(pt);
537 toolTipWindow->BringToFront();
538 toolTipWindow->Show();
539 toolTipWindow->Invalidate();
540 toolTipWindow->Update();
541 }
542 }
543 public void HideToolTipWindow()
544 {
545 toolTipWindow->Hide();
546 }
547 public nothrow Event<TreeViewNodeMouseClickEventHandler, TreeViewNodeMouseClickEventArgs>& NodeClickEvent()
548 {
549 return nodeClickEvent;
550 }
551 public nothrow Event<TreeViewNodeMouseClickEventHandler, TreeViewNodeMouseClickEventArgs>& NodeDoubleClickEvent()
552 {
553 return nodeDoubleClickEvent;
554 }
555 public nothrow Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs>& NodeEnterEvent()
556 {
557 return nodeEnterEvent;
558 }
559 public nothrow Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs>& NodeLeaveEvent()
560 {
561 return nodeLeaveEvent;
562 }
563 public nothrow Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs>& NodeSelectedEvent()
564 {
565 return nodeSelectedEvent;
566 }
567 public nothrow Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs>& NodeExpandedEvent()
568 {
569 return nodeExpandedEvent;
570 }
571 public nothrow Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs>& NodeCollapsedEvent()
572 {
573 return nodeCollapsedEvent;
574 }
575 public nothrow Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs>& NodeHoveredEvent()
576 {
577 return nodeHoveredEvent;
578 }
579 protected override void OnMouseDown(MouseEventArgs& args)
580 {
581 base->OnMouseDown(args);
582 if (!root.IsNull())
583 {
584 bool handled = false;
585 root->DispatchMouseDown(args, handled);
586 if (TreeViewNodeStateChanged())
587 {
588 DeselectNode();
589 Invalidate();
590 }
591 }
592 }
593 protected override void OnMouseUp(MouseEventArgs& args)
594 {
595 base->OnMouseUp(args);
596 if (!root.IsNull())
597 {
598 bool handled = false;
599 root->DispatchMouseUp(args, handled);
600 }
601 }
602 protected override void OnMouseDoubleClick(MouseEventArgs& args)
603 {
604 base->OnMouseDoubleClick(args);
605 if (!root.IsNull())
606 {
607 bool handled = false;
608 root->DispatchMouseDoubleClick(args, handled);
609 if (TreeViewNodeStateChanged())
610 {
611 DeselectNode();
612 Invalidate();
613 }
614 }
615 }
616 protected override void OnMouseEnter()
617 {
618 base->OnMouseEnter();
619 trackedNode = null;
620 }
621 protected override void OnMouseMove(MouseEventArgs& args)
622 {
623 base->OnMouseMove(args);
624 if (!root.IsNull())
625 {
626 bool handled = false;
627 root->DispatchMouseMove(args, handled);
628 if (!handled)
629 {
630 if (trackedNode != null)
631 {
632 if (trackedNode->MouseEntered())
633 {
634 trackedNode->ResetMouseEntered();
635 trackedNode->MouseLeaveInternal();
636 }
637 trackedNode = null;
638 }
639 }
640 }
641 }
642 protected override void OnMouseLeave()
643 {
644 base->OnMouseLeave();
645 if (trackedNode != null)
646 {
647 if (trackedNode->MouseEntered())
648 {
649 trackedNode->ResetMouseEntered();
650 trackedNode->MouseLeaveInternal();
651 }
652 trackedNode = null;
653 }
654 }
655 protected override void OnMouseHover(MouseEventArgs& args)
656 {
657 base->OnMouseHover(args);
658 if (!root.IsNull())
659 {
660 bool handled = false;
661 root->DispatchMouseHover(args, handled);
662 }
663 }
664 internal inline nothrow bool Changed() const
665 {
666 return (flags & Flags.changed) != Flags.none;
667 }
668 public inline nothrow void SetChanged()
669 {
670 flags = cast<Flags>(flags | Flags.changed);
671 }
672 private inline nothrow void ResetChanged()
673 {
674 flags = cast<Flags>(flags & ~Flags.changed);
675 }
676 internal inline nothrow bool TreeViewNodeChanged() const
677 {
678 return (flags & Flags.treeViewNodeChanged) != Flags.none;
679 }
680 internal inline nothrow void SetTreeViewNodeChanged()
681 {
682 flags = cast<Flags>(flags | Flags.treeViewNodeChanged);
683 }
684 private inline nothrow void ResetTreeViewNodeChanged()
685 {
686 flags = cast<Flags>(flags & ~Flags.treeViewNodeChanged);
687 }
688 internal inline nothrow bool TreeViewNodeStateChanged() const
689 {
690 return (flags & Flags.treeViewNodeStateChanged) != Flags.none;
691 }
692 private inline nothrow void ResetTreeViewNodeStateChanged()
693 {
694 flags = cast<Flags>(flags & ~Flags.treeViewNodeStateChanged);
695 }
696 internal inline nothrow void SetTreeViewNodeStateChanged()
697 {
698 flags = cast<Flags>(flags | Flags.treeViewNodeStateChanged);
699 }
700 private inline nothrow bool ToolTipWindowAdded() const
701 {
702 return (flags & Flags.toolTipWindowAdded) != Flags.none;
703 }
704 private inline nothrow void SetToolTipWindowAdded()
705 {
706 flags = cast<Flags>(flags | Flags.toolTipWindowAdded);
707 }
708 private inline nothrow void ResetToolTipWindowAdded()
709 {
710 flags = cast<Flags>(flags & ~Flags.toolTipWindowAdded);
711 }
712 private void Measure(Graphics& graphics)
713 {
714 string s = "RootNode";
715 RectF normalTextRect = graphics.MeasureStringChecked(s, normalNodeFont, PointF(0, 0), format);
716 textHeight = normalTextRect.size.h;
717 RectF activeTextRect = graphics.MeasureStringChecked(s, activeNodeFont, PointF(0, 0), format);
718 textHeight = Max(textHeight, activeTextRect.size.h);
719 stateIndicatorHeight = stateIndicatorPercentage * textHeight / 100.0f;
720 SetScrollUnits(cast<int>(textHeight + 0.5), cast<int>(textHeight + 0.5));
721 }
722 private void MakeStateIndicatorBitmaps(Graphics& graphics)
723 {
724 SolidBrush stateIndicatorBrush(stateIndicatorColor);
725 stateIndicatorBitmaps.Clear();
726 PointF center(textHeight / 2, textHeight / 2);
727 float w = cast<float>((Sqrt(3.0) / 2) * stateIndicatorHeight);
728 PointF pt1(center.x - w / 2, center.y - stateIndicatorHeight / 2);
729 PointF pt2(center.x - w / 2, center.y + stateIndicatorHeight / 2);
730 PointF pt3(center.x + w / 2, center.y);
731 for (int i = 9; i >= 0; --i;)
732 {
733 float angle = i * 10.0f;
734 List<PointF> triangle;
735 triangle.Add(pt1);
736 triangle.Add(pt2);
737 triangle.Add(pt3);
738 Bitmap bm(cast<int>(textHeight), cast<int>(textHeight), graphics);
739 Graphics bmGraphics = Graphics.FromImage(bm);
740 bmGraphics.Clear(BackgroundColor());
741 if (i > 0)
742 {
743 Matrix id;
744 Matrix rm = RotateAt(id, angle, center);
745 rm.TransformPointsChecked(triangle);
746 }
747 List<Point> indicatorTriangle;
748 for (const PointF& pt : triangle)
749 {
750 indicatorTriangle.Add(Point(cast<int>(pt.x), cast<int>(pt.y)));
751 }
752 bmGraphics.SetSmoothingModeChecked(SmoothingMode.highQuality);
753 bmGraphics.FillPolygonChecked(stateIndicatorBrush, 3, indicatorTriangle.Begin().Ptr());
754 stateIndicatorBitmaps.Add(Rvalue(bm));
755 }
756 }
757 internal void DoAnimation(TreeViewNode.State targetState, const Rect& stateRect)
758 {
759 if (targetState == TreeViewNode.State.expanded)
760 {
761 for (long i = stateIndicatorBitmaps.Count() - 1; i >= 0; --i;)
762 {
763 UpdateGuard guard(this, i);
764 Invalidate(stateRect.ToWinRect());
765 Update();
766 Sleep(Duration.FromMilliseconds(animationMs));
767 }
768 }
769 else if (targetState == TreeViewNode.State.collapsed)
770 {
771 for (long i = 0; i < stateIndicatorBitmaps.Count(); ++i;)
772 {
773 UpdateGuard guard(this, i);
774 Invalidate(stateRect.ToWinRect());
775 Update();
776 Sleep(Duration.FromMilliseconds(animationMs));
777 }
778 }
779 }
780 private class UpdateGuard
781 {
782 public nothrow UpdateGuard(TreeView* view_, long bitmapIndex) : view(view_)
783 {
784 view->SetBitmapIndex(bitmapIndex);
785 }
786 public ~UpdateGuard()
787 {
788 view->ResetBitmapIndex();
789 }
790 private TreeView* view;
791 }
792 private nothrow void SetBitmapIndex(long bitmapIndex_)
793 {
794 bitmapIndex = bitmapIndex_;
795 }
796 private nothrow void ResetBitmapIndex()
797 {
798 bitmapIndex = -1;
799 }
800 public const Bitmap& NodeExpandedBitmap() const
801 {
802 if (stateIndicatorBitmaps.IsEmpty())
803 {
804 throw Exception("no state indicator bitmaps");
805 }
806 return stateIndicatorBitmaps.Front();
807 }
808 public const Bitmap& NodeCollapsedBitmap() const
809 {
810 if (stateIndicatorBitmaps.IsEmpty())
811 {
812 throw Exception("no state indicator bitmaps");
813 }
814 return stateIndicatorBitmaps.Back();
815 }
816 public inline nothrow const StringFormat& Format() const
817 {
818 return format;
819 }
820 internal nothrow void SetSelectedNode(TreeViewNode* node)
821 {
822 if (selectedNode != node)
823 {
824 if (selectedNode != null)
825 {
826 selectedNode->ResetSelected();
827 }
828 selectedNode = node;
829 SetTreeViewNodeStateChanged();
830 }
831 }
832 public nothrow TreeViewNode* SelectedNode() const
833 {
834 return selectedNode;
835 }
836 public void DeselectNode()
837 {
838 if (selectedNode != null)
839 {
840 TreeViewNode* selectedNodeParent = selectedNode->Parent();
841 while (selectedNodeParent != null)
842 {
843 if (selectedNodeParent->GetState() == TreeViewNode.State.collapsed)
844 {
845 SetSelectedNode(null);
846 break;
847 }
848 selectedNodeParent = selectedNodeParent->Parent();
849 }
850 }
851 }
852 internal inline nothrow TreeViewNode* TrackedNode() const
853 {
854 return trackedNode;
855 }
856 internal nothrow void SetTrackedNode(TreeViewNode* trackedNode_)
857 {
858 trackedNode = trackedNode_;
859 }
860 public inline nothrow const Padding& NodeImagePadding() const
861 {
862 return nodeImagePadding;
863 }
864 protected virtual void OnNodeClick(TreeViewNodeMouseClickEventArgs& args)
865 {
866 nodeClickEvent.Fire(args);
867 }
868 internal void NodeClick(const Point& location, MouseButtons buttons, TreeViewNode* node)
869 {
870 TreeViewNodeMouseClickEventArgs args(location, buttons, 1, node);
871 OnNodeClick(args);
872 }
873 protected virtual void OnNodeDoubleClick(TreeViewNodeMouseClickEventArgs& args)
874 {
875 nodeDoubleClickEvent.Fire(args);
876 }
877 internal void NodeDoubleClick(const Point& location, MouseButtons buttons, TreeViewNode* node)
878 {
879 TreeViewNodeMouseClickEventArgs args(location, buttons, 2, node);
880 OnNodeDoubleClick(args);
881 }
882 protected virtual void OnNodeEnter(TreeViewNodeEventArgs& args)
883 {
884 nodeEnterEvent.Fire(args);
885 }
886 internal void NodeEnter(TreeViewNode* node)
887 {
888 TreeViewNodeEventArgs args(node);
889 OnNodeEnter(args);
890 }
891 protected virtual void OnNodeLeave(TreeViewNodeEventArgs& args)
892 {
893 nodeLeaveEvent.Fire(args);
894 }
895 internal void NodeLeave(TreeViewNode* node)
896 {
897 TreeViewNodeEventArgs args(node);
898 OnNodeLeave(args);
899 }
900 protected virtual void OnNodeSelected(TreeViewNodeEventArgs& args)
901 {
902 nodeSelectedEvent.Fire(args);
903 }
904 internal void NodeSelected(TreeViewNode* node)
905 {
906 TreeViewNodeEventArgs args(node);
907 OnNodeSelected(args);
908 }
909 protected virtual void OnNodeExpanded(TreeViewNodeEventArgs& args)
910 {
911 nodeExpandedEvent.Fire(args);
912 }
913 internal void NodeExpanded(TreeViewNode* node)
914 {
915 TreeViewNodeEventArgs args(node);
916 OnNodeExpanded(args);
917 }
918 protected virtual void OnNodeCollapsed(TreeViewNodeEventArgs& args)
919 {
920 nodeCollapsedEvent.Fire(args);
921 }
922 protected virtual void OnNodeHovered(TreeViewNodeEventArgs& args)
923 {
924 nodeHoveredEvent.Fire(args);
925 }
926 internal void NodeCollapsed(TreeViewNode* node)
927 {
928 TreeViewNodeEventArgs args(node);
929 OnNodeCollapsed(args);
930 }
931 internal void NodeHovered(TreeViewNode* node)
932 {
933 TreeViewNodeEventArgs args(node);
934 OnNodeHovered(args);
935 }
936 public inline nothrow ImageList* GetImageList() const
937 {
938 return imageList;
939 }
940 public nothrow void SetImageList(ImageList* imageList_)
941 {
942 imageList = imageList_;
943 }
944 private Flags flags;
945 private UniquePtr<TreeViewNode> root;
946 private Font normalNodeFont;
947 private Font activeNodeFont;
948 private float textHeight;
949 private float stateIndicatorPercentage;
950 private float stateIndicatorHeight;
951 private Color stateIndicatorColor;
952 private Color nodeSelectedColor;
953 private Color textColor;
954 private float nodeIndentPercent;
955 private float nodeTextIndentPercent;
956 private Padding nodeImagePadding;
957 private SolidBrush nodeSelectedBrush;
958 private SolidBrush textBrush;
959 private List<Bitmap> stateIndicatorBitmaps;
960 private StringFormat format;
961 private long bitmapIndex;
962 private int animationMs;
963 private TreeViewNode* selectedNode;
964 private TreeViewNode* trackedNode;
965 private ToolTip* toolTipWindow;
966 private ImageList* imageList;
967 private Event<TreeViewNodeMouseClickEventHandler, TreeViewNodeMouseClickEventArgs> nodeClickEvent;
968 private Event<TreeViewNodeMouseClickEventHandler, TreeViewNodeMouseClickEventArgs> nodeDoubleClickEvent;
969 private Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs> nodeEnterEvent;
970 private Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs> nodeLeaveEvent;
971 private Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs> nodeSelectedEvent;
972 private Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs> nodeExpandedEvent;
973 private Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs> nodeCollapsedEvent;
974 private Event<TreeViewNodeEventHandler, TreeViewNodeEventArgs> nodeHoveredEvent;
975 }
976
977 public class TreeViewNode : Component
978 {
979 public enum State : sbyte
980 {
981 collapsed = 0, expanded = 1
982 }
983 private enum Flags : sbyte
984 {
985 none = 0, mouseEntered = 1 << 0, selected = 1 << 1, active = 1 << 2
986 }
987 public explicit nothrow TreeViewNode(const string& text_) :
988 treeView(null), text(text_), children(this), state(State.collapsed), flags(Flags.none), index(-1), imageIndex(-1), expandedImageIndex(-1)
989 {
990 }
991 public nothrow void SetTreeView(TreeView* treeView_)
992 {
993 treeView = treeView_;
994 }
995 public nothrow TreeViewNode* Parent() const
996 {
997 Container* container = GetContainer();
998 if (container != null)
999 {
1000 Component* parent = container->Parent();
1001 if (parent != null)
1002 {
1003 if (parent is TreeViewNode*)
1004 {
1005 return cast<TreeViewNode*>(parent);
1006 }
1007 }
1008 }
1009 return null;
1010 }
1011 public nothrow TreeView* GetTreeView() const
1012 {
1013 if (treeView != null)
1014 {
1015 return treeView;
1016 }
1017 TreeViewNode* parent = Parent();
1018 if (parent != null)
1019 {
1020 return parent->GetTreeView();
1021 }
1022 return null;
1023 }
1024 public void AddChild(TreeViewNode* child)
1025 {
1026 children.AddChild(child);
1027 TreeView* view = GetTreeView();
1028 if (view != null)
1029 {
1030 view->SetTreeViewNodeChanged();
1031 }
1032 }
1033 public UniquePtr<TreeViewNode> RemoveChild(TreeViewNode* child)
1034 {
1035 UniquePtr<Component> removed = children.RemoveChild(child);
1036 TreeView* view = GetTreeView();
1037 if (view != null)
1038 {
1039 view->SetTreeViewNodeChanged();
1040 }
1041 return UniquePtr<TreeViewNode>(cast<TreeViewNode*>(removed.Release()));
1042 }
1043 public void RemoveChildren()
1044 {
1045 Component* component = children.FirstChild();
1046 while (component != null)
1047 {
1048 Component* next = component->NextSibling();
1049 UniquePtr<Component> removed = children.RemoveChild(component);
1050 component = next;
1051 }
1052 }
1053 public nothrow int Level() const
1054 {
1055 TreeViewNode* parent = Parent();
1056 if (parent != null)
1057 {
1058 return parent->Level() + 1;
1059 }
1060 return 0;
1061 }
1062 public nothrow const Point& Location() const
1063 {
1064 return location;
1065 }
1066 public nothrow const Size& GetSize() const
1067 {
1068 return size;
1069 }
1070 public nothrow void MeasureSize(Graphics& graphics, TreeView* treeView)
1071 {
1072 RectF textRect = graphics.MeasureStringChecked(text, treeView->GetNormalNodeFont(), PointF(0, 0), treeView->Format());
1073 SizeF imageSize(0, 0);
1074 if (imageIndex != -1)
1075 {
1076 Padding padding = treeView->NodeImagePadding();
1077 ImageList* imageList = treeView->GetImageList();
1078 if (imageList != null)
1079 {
1080 Bitmap* bitmap = imageList->GetImage(imageIndex);
1081 imageSize.w = bitmap->GetWidth() + padding.Horizontal();
1082 imageSize.h = bitmap->GetHeight() + padding.Vertical();
1083 }
1084 }
1085 size = Size(cast<int>(treeView->TextHeight() + textRect.size.w + imageSize.w), cast<int>(Max(textRect.size.h, imageSize.h)));
1086 Component* child = children.FirstChild();
1087 while (child != null)
1088 {
1089 if (child is TreeViewNode*)
1090 {
1091 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1092 childNode->MeasureSize(graphics, treeView);
1093 }
1094 child = child->NextSibling();
1095 }
1096 }
1097 internal nothrow void Measure(Graphics& graphics, const Point& loc, TreeView* treeView, int level, int& idx, Rect& parentRect)
1098 {
1099
1100 float imageHeight = 0;
1101 if (imageIndex != -1)
1102 {
1103 Padding padding = treeView->NodeImagePadding();
1104 ImageList* imageList = treeView->GetImageList();
1105 if (imageList != null)
1106 {
1107 Bitmap* image = imageList->GetImage(imageIndex);
1108 imageHeight = image->GetHeight() + padding.Vertical();
1109 }
1110 }
1111 location = Point(cast<int>(loc.x + level * treeView->NodeIndentPercent() * treeView->TextHeight() / 100.0f),
1112 cast<int>(loc.y + idx * Max(treeView->TextHeight(), imageHeight)));
1113 Rect rect(location, size);
1114 childRect = rect;
1115 parentRect = Rect.Union(parentRect, childRect);
1116 if (state == State.expanded)
1117 {
1118 Component* child = children.FirstChild();
1119 while (child != null)
1120 {
1121 if (child is TreeViewNode*)
1122 {
1123 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1124 ++idx;
1125 childNode->Measure(graphics, loc, treeView, level + 1, idx, childRect);
1126 parentRect = Rect.Union(parentRect, childRect);
1127 }
1128 child = child->NextSibling();
1129 }
1130 }
1131 }
1132 internal void DispatchMouseDown(MouseEventArgs& args, bool& handled)
1133 {
1134 Rect r(location, size);
1135 if (r.Contains(args.location))
1136 {
1137 OnMouseDown(args);
1138 handled = true;
1139 }
1140 else
1141 {
1142 if (childRect.Contains(args.location))
1143 {
1144 Component* child = children.FirstChild();
1145 while (child != null)
1146 {
1147 if (child is TreeViewNode*)
1148 {
1149 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1150 childNode->DispatchMouseDown(args, handled);
1151 if (handled)
1152 {
1153 return;
1154 }
1155 }
1156 child = child->NextSibling();
1157 }
1158 }
1159 }
1160 }
1161 internal void DispatchMouseUp(MouseEventArgs& args, bool& handled)
1162 {
1163 Rect r(location, size);
1164 if (r.Contains(args.location))
1165 {
1166 OnMouseUp(args);
1167 handled = true;
1168 }
1169 else
1170 {
1171 if (childRect.Contains(args.location))
1172 {
1173 Component* child = children.FirstChild();
1174 while (child != null)
1175 {
1176 if (child is TreeViewNode*)
1177 {
1178 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1179 childNode->DispatchMouseUp(args, handled);
1180 if (handled)
1181 {
1182 return;
1183 }
1184 }
1185 child = child->NextSibling();
1186 }
1187 }
1188 }
1189 }
1190 internal void DispatchMouseDoubleClick(MouseEventArgs& args, bool& handled)
1191 {
1192 Rect r(location, size);
1193 if (r.Contains(args.location))
1194 {
1195 OnMouseDoubleClick(args);
1196 handled = true;
1197 }
1198 else
1199 {
1200 if (childRect.Contains(args.location))
1201 {
1202 Component* child = children.FirstChild();
1203 while (child != null)
1204 {
1205 if (child is TreeViewNode*)
1206 {
1207 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1208 childNode->DispatchMouseDoubleClick(args, handled);
1209 if (handled)
1210 {
1211 return;
1212 }
1213 }
1214 child = child->NextSibling();
1215 }
1216 }
1217 }
1218 }
1219 internal void DispatchMouseMove(MouseEventArgs& args, bool& handled)
1220 {
1221 Rect r(location, size);
1222 if (r.Contains(args.location))
1223 {
1224 handled = true;
1225 TreeView* view = GetTreeView();
1226 if (view != null)
1227 {
1228 TreeViewNode* prevNode = view->TrackedNode();
1229 if (prevNode != null && prevNode != this)
1230 {
1231 if (prevNode->MouseEntered())
1232 {
1233 prevNode->ResetMouseEntered();
1234 prevNode->OnMouseLeave();
1235 }
1236 }
1237 view->SetTrackedNode(this);
1238 if (!MouseEntered())
1239 {
1240 SetMouseEntered();
1241 OnMouseEnter();
1242 }
1243 }
1244 }
1245 else
1246 {
1247 if (childRect.Contains(args.location))
1248 {
1249 Component* child = children.FirstChild();
1250 while (child != null)
1251 {
1252 if (child is TreeViewNode*)
1253 {
1254 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1255 childNode->DispatchMouseMove(args, handled);
1256 if (handled)
1257 {
1258 return;
1259 }
1260 }
1261 child = child->NextSibling();
1262 }
1263 }
1264 }
1265 }
1266 internal void MouseLeaveInternal()
1267 {
1268 OnMouseLeave();
1269 }
1270 internal void DispatchMouseHover(MouseEventArgs& args, bool& handled)
1271 {
1272 Rect r(location, size);
1273 if (r.Contains(args.location))
1274 {
1275 handled = true;
1276 OnMouseHover();
1277 }
1278 else
1279 {
1280 if (childRect.Contains(args.location))
1281 {
1282 Component* child = children.FirstChild();
1283 while (child != null)
1284 {
1285 if (child is TreeViewNode*)
1286 {
1287 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1288 childNode->DispatchMouseHover(args, handled);
1289 if (handled)
1290 {
1291 return;
1292 }
1293 }
1294 child = child->NextSibling();
1295 }
1296 }
1297 }
1298 }
1299 private void OnMouseDown(MouseEventArgs& args)
1300 {
1301 if (args.buttons == MouseButtons.lbutton)
1302 {
1303 TreeView* view = GetTreeView();
1304 if (view != null)
1305 {
1306 if (children.IsEmpty())
1307 {
1308 Select();
1309 }
1310 else
1311 {
1312 int stateSquareSideLength = cast<int>(view->TextHeight());
1313 Rect stateRect(location, Size(stateSquareSideLength, stateSquareSideLength));
1314 if (stateRect.Contains(args.location))
1315 {
1316 Toggle();
1317 }
1318 else
1319 {
1320 Select();
1321 }
1322 }
1323 }
1324 }
1325 else if (args.buttons == MouseButtons.rbutton)
1326 {
1327 Select();
1328 }
1329 }
1330 private void OnMouseUp(MouseEventArgs& args)
1331 {
1332 if (args.buttons == MouseButtons.lbutton)
1333 {
1334 if (Selected())
1335 {
1336 TreeView* view = GetTreeView();
1337 if (view != null)
1338 {
1339 view->NodeClick(args.location, args.buttons, this);
1340 }
1341 }
1342 }
1343 else if (args.buttons == MouseButtons.rbutton)
1344 {
1345 if (Selected())
1346 {
1347 TreeView* view = GetTreeView();
1348 if (view != null)
1349 {
1350 view->NodeClick(args.location, args.buttons, this);
1351 }
1352 }
1353 }
1354 }
1355 private void OnMouseDoubleClick(MouseEventArgs& args)
1356 {
1357 TreeView* view = GetTreeView();
1358 if (view != null)
1359 {
1360 view->NodeDoubleClick(args.location, args.buttons, this);
1361 }
1362 }
1363 private void OnMouseEnter()
1364 {
1365 TreeView* view = GetTreeView();
1366 if (view != null)
1367 {
1368 view->NodeEnter(this);
1369 }
1370 }
1371 private void OnMouseLeave()
1372 {
1373 TreeView* view = GetTreeView();
1374 if (view != null)
1375 {
1376 view->NodeLeave(this);
1377 }
1378 }
1379 private void OnMouseHover()
1380 {
1381 TreeView* view = GetTreeView();
1382 if (view != null)
1383 {
1384 view->NodeHovered(this);
1385 }
1386 }
1387 public void Toggle()
1388 {
1389 switch (state)
1390 {
1391 case State.expanded: Collapse(); break;
1392 case State.collapsed: Expand(); break;
1393 }
1394 }
1395 public void Select()
1396 {
1397 if (!Selected())
1398 {
1399 SetSelected();
1400 TreeView* view = GetTreeView();
1401 if (view != null)
1402 {
1403 view->SetSelectedNode(this);
1404 view->NodeSelected(this);
1405 }
1406 }
1407 }
1408 public void Deselect()
1409 {
1410 if (Selected())
1411 {
1412 ResetSelected();
1413 TreeView* view = GetTreeView();
1414 if (view != null)
1415 {
1416 view->SetSelectedNode(null);
1417 }
1418 }
1419 }
1420 public void Expand()
1421 {
1422 if (children.IsEmpty()) return;
1423 DoAnimation();
1424 Expand(false);
1425 TreeView* view = GetTreeView();
1426 if (view != null)
1427 {
1428 view->NodeExpanded(this);
1429 }
1430 }
1431 public void ExpandAll()
1432 {
1433 if (children.IsEmpty()) return;
1434 DoAnimation();
1435 Expand(true);
1436 TreeView* view = GetTreeView();
1437 if (view != null)
1438 {
1439 view->NodeExpanded(this);
1440 }
1441 }
1442 public void Expand(bool all)
1443 {
1444 if (children.IsEmpty()) return;
1445 SetState(State.expanded);
1446 if (all)
1447 {
1448 Component* child = children.FirstChild();
1449 while (child != null)
1450 {
1451 if (child is TreeViewNode*)
1452 {
1453 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1454 childNode->Expand(all);
1455 }
1456 child = child->NextSibling();
1457 }
1458 }
1459 }
1460 public void Collapse()
1461 {
1462 if (children.IsEmpty()) return;
1463 DoAnimation();
1464 Collapse(false);
1465 TreeView* view = GetTreeView();
1466 if (view != null)
1467 {
1468 view->NodeCollapsed(this);
1469 }
1470 }
1471 public void CollapseAll()
1472 {
1473 if (children.IsEmpty()) return;
1474 DoAnimation();
1475 Collapse(true);
1476 TreeView* view = GetTreeView();
1477 if (view != null)
1478 {
1479 view->NodeCollapsed(this);
1480 }
1481 }
1482 public void Collapse(bool all)
1483 {
1484 if (children.IsEmpty()) return;
1485 SetState(State.collapsed);
1486 if (all)
1487 {
1488 Component* child = children.FirstChild();
1489 while (child != null)
1490 {
1491 if (child is TreeViewNode*)
1492 {
1493 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1494 childNode->Collapse(all);
1495 }
1496 child = child->NextSibling();
1497 }
1498 }
1499 }
1500 private void DoAnimation()
1501 {
1502 TreeView* view = GetTreeView();
1503 if (view != null)
1504 {
1505 int stateSquareSideLength = cast<int>(view->TextHeight());
1506 Rect stateRect(location, Size(stateSquareSideLength, stateSquareSideLength));
1507 view->DoAnimation(cast<State>(1 - state), stateRect);
1508 }
1509 }
1510 public inline nothrow const string& Text() const
1511 {
1512 return text;
1513 }
1514 public nothrow void SetText(const string& text_)
1515 {
1516 text = text_;
1517 TreeView* view = GetTreeView();
1518 if (view != null)
1519 {
1520 view->SetTreeViewNodeChanged();
1521 }
1522 }
1523 public inline nothrow Container& Children() const
1524 {
1525 return children;
1526 }
1527 public inline nothrow State GetState() const
1528 {
1529 return state;
1530 }
1531 public nothrow void SetState(State state_)
1532 {
1533 if (state != state_)
1534 {
1535 state = state_;
1536 TreeView* view = GetTreeView();
1537 if (view != null)
1538 {
1539 view->SetTreeViewNodeStateChanged();
1540 if (state == State.collapsed)
1541 {
1542 view->SetContentLocation(Point(0, 0));
1543 }
1544 }
1545 }
1546 }
1547 public inline nothrow void* Data() const
1548 {
1549 return data;
1550 }
1551 public inline nothrow void SetData(void* data_)
1552 {
1553 data = data_;
1554 }
1555 public void EnsureVisible()
1556 {
1557 TreeView* treeView = GetTreeView();
1558 if (treeView != null)
1559 {
1560 treeView->EnsureNodeVisible(this);
1561 }
1562 }
1563 public void GetVisibleNodes(List<TreeViewNode*>& visibleNodes, TreeView* treeView, int selectLevel)
1564 {
1565 if (selectLevel == -1 || Level() == selectLevel)
1566 {
1567 if (treeView->NodeVisible(this))
1568 {
1569 visibleNodes.Add(this);
1570 }
1571 }
1572 if (state == State.expanded)
1573 {
1574 Component* child = children.FirstChild();
1575 while (child != null)
1576 {
1577 if (child is TreeViewNode*)
1578 {
1579 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1580 childNode->GetVisibleNodes(visibleNodes, treeView, selectLevel);
1581 }
1582 child = child->NextSibling();
1583 }
1584 }
1585 }
1586 public void Draw(Graphics& graphics, TreeView* treeView)
1587 {
1588 bool isVisible = treeView->NodeVisible(this);
1589 Point loc = location;
1590 if (!children.IsEmpty())
1591 {
1592 if (isVisible)
1593 {
1594 switch (state)
1595 {
1596 case State.expanded:
1597 {
1598 graphics.DrawImageChecked(treeView->NodeExpandedBitmap(), PointF(loc.x, loc.y));
1599 break;
1600 }
1601 case State.collapsed:
1602 {
1603 graphics.DrawImageChecked(treeView->NodeCollapsedBitmap(), PointF(loc.x, loc.y));
1604 break;
1605 }
1606 }
1607 }
1608 loc.x = cast<int>(loc.x + treeView->NodeTextIndentPercent() * treeView->TextHeight() / 100.0f);
1609 }
1610 if (isVisible)
1611 {
1612 if (imageIndex != -1)
1613 {
1614 DrawImage(treeView, graphics, loc);
1615 }
1616 }
1617 if (isVisible)
1618 {
1619 if (Selected())
1620 {
1621 Rect rect(loc, size);
1622 graphics.FillRectangleChecked(treeView->NodeSelectedBrush(), rect);
1623 }
1624 if (Active())
1625 {
1626 graphics.DrawStringChecked(text, treeView->GetActiveNodeFont(), PointF(loc.x, loc.y), treeView->TextBrush());
1627 }
1628 else
1629 {
1630 graphics.DrawStringChecked(text, treeView->GetNormalNodeFont(), PointF(loc.x, loc.y), treeView->TextBrush());
1631 }
1632 }
1633 if (state == State.expanded)
1634 {
1635 Component* child = children.FirstChild();
1636 while (child != null)
1637 {
1638 if (child is TreeViewNode*)
1639 {
1640 TreeViewNode* childNode = cast<TreeViewNode*>(child);
1641 childNode->Draw(graphics, treeView);
1642 }
1643 child = child->NextSibling();
1644 }
1645 }
1646 }
1647 internal inline nothrow bool MouseEntered() const
1648 {
1649 return (flags & Flags.mouseEntered) != Flags.none;
1650 }
1651 internal inline nothrow void SetMouseEntered()
1652 {
1653 flags = cast<Flags>(flags | Flags.mouseEntered);
1654 }
1655 internal inline nothrow void ResetMouseEntered()
1656 {
1657 flags = cast<Flags>(flags & ~Flags.mouseEntered);
1658 }
1659 public inline nothrow bool Selected() const
1660 {
1661 return (flags & Flags.selected) != Flags.none;
1662 }
1663 private inline nothrow void SetSelected()
1664 {
1665 flags = cast<Flags>(flags | Flags.selected);
1666 }
1667 internal inline nothrow void ResetSelected()
1668 {
1669 flags = cast<Flags>(flags & ~Flags.selected);
1670 }
1671 public inline nothrow bool Active() const
1672 {
1673 return (flags & Flags.active) != Flags.none;
1674 }
1675 public nothrow void SetActive(bool active)
1676 {
1677 if (Active() != active)
1678 {
1679 if (active)
1680 {
1681 flags = cast<Flags>(flags | Flags.active);
1682 }
1683 else
1684 {
1685 flags = cast<Flags>(flags & ~Flags.active);
1686 }
1687 TreeView* view = GetTreeView();
1688 if (view != null)
1689 {
1690 view->SetTreeViewNodeStateChanged();
1691 }
1692 }
1693 }
1694 public inline nothrow int Index() const
1695 {
1696 return index;
1697 }
1698 public nothrow void SetIndex(int index_)
1699 {
1700 index = index_;
1701 }
1702 public inline nothrow int ImageIndex() const
1703 {
1704 return imageIndex;
1705 }
1706 public nothrow void SetImageIndex(int imageIndex_)
1707 {
1708 if (imageIndex != imageIndex_)
1709 {
1710 imageIndex = imageIndex_;
1711 TreeView* view = GetTreeView();
1712 if (view != null)
1713 {
1714 view->SetTreeViewNodeStateChanged();
1715 view->SetChanged();
1716 view->Invalidate();
1717 }
1718 }
1719 }
1720 public nothrow void SetExpandedImageIndex(int expandedImageIndex_)
1721 {
1722 if (expandedImageIndex != expandedImageIndex_)
1723 {
1724 expandedImageIndex = expandedImageIndex_;
1725 TreeView* view = GetTreeView();
1726 if (view != null)
1727 {
1728 view->SetTreeViewNodeStateChanged();
1729 view->SetChanged();
1730 view->Invalidate();
1731 }
1732 }
1733 }
1734 public nothrow void DrawImage(TreeView* view, Graphics& graphics, Point& loc)
1735 {
1736 ImageList* imageList = view->GetImageList();
1737 if (imageList != null)
1738 {
1739 int imgIndex = imageIndex;
1740 if (state == State.expanded)
1741 {
1742 if (expandedImageIndex != -1)
1743 {
1744 imgIndex = expandedImageIndex;
1745 }
1746 }
1747 Bitmap* image = imageList->GetImage(imgIndex);
1748 if (image != null)
1749 {
1750 int imageWidth = cast<int>(image->GetWidth());
1751 int imageHeight = cast<int>(image->GetHeight());
1752 Padding padding = view->NodeImagePadding();
1753 Rect r(loc, Size(imageWidth + padding.Horizontal(), imageHeight + padding.Vertical()));
1754 ImageAttributes attributes;
1755 Color transparentColor = System.Windows.Color.DefaultBitmapTransparent();
1756 attributes.SetColorKeyChecked(transparentColor, transparentColor, ColorAdjustType.default_);
1757 graphics.DrawImageChecked(*image, r, 0, 0, imageWidth + padding.Horizontal(), imageHeight + padding.Vertical(), Unit.pixel, attributes);
1758 loc.x = loc.x + imageWidth + padding.Horizontal();
1759 }
1760 }
1761 }
1762 private TreeView* treeView;
1763 private string text;
1764 private Container children;
1765 private State state;
1766 private Flags flags;
1767 private void* data;
1768 private Point location;
1769 private Size size;
1770 private Rect childRect;
1771 private int index;
1772 private int imageIndex;
1773 private int expandedImageIndex;
1774 }
1775 }