1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Windows
10 {
11 public Color DefaultToolTipWindowColor()
12 {
13 return Color.FloralWhite();
14 }
15
16 public Color DefaultToolButtonTransparentColor()
17 {
18 return Color.DefaultBitmapTransparent();
19 }
20
21 public int DefaultToolButtonHeight()
22 {
23 return 38;
24 }
25
26 public ToolBar.Style DefaultToolBarStyle()
27 {
28 return ToolBar.Style.regular;
29 }
30
31 public Padding DefaultToolBarPadding()
32 {
33 return Padding(0, 0, 0, 0);
34 }
35
36 public Padding DefaultToolButtonPadding()
37 {
38 return Padding(0, 0, 0, 0);
39 }
40
41 public Color DefaultToolBarDarkColor()
42 {
43 return Color(100u, 100u, 100u);
44 }
45
46 public Color DefaultToolBarLightColor()
47 {
48 return Color.White();
49 }
50
51 public Color DefaultToolBarMediumLightColor()
52 {
53 return Color(227u, 227u, 227u);
54 }
55
56 public Color DefaultToolBarMediumDarkColor()
57 {
58 return Color(160u, 160u, 160u);
59 }
60
61 public Color DefaultToolBarDisabledColor()
62 {
63 return Color(204u, 204u, 207u);
64 }
65
66 public Color DefaultToolBarToolButtonSeparatorColor1()
67 {
68 return Color(204u, 206u, 219u);
69 }
70
71 public Color DefaultToolBarToolButtonSeparatorColor2()
72 {
73 return Color(245u, 245u, 245u);
74 }
75
76 public ControlCreateParams& ToolBarControlCreateParams(ControlCreateParams& controlCreateParams,
77 const Padding& padding,
78 const Padding& buttonPadding,
79 int toolButtonHeight)
80 {
81 return controlCreateParams.SetWindowClassName("System.Windows.ToolBar").SetLocation(Point(padding.left, padding.top)).
82 SetSize(Size(0, toolButtonHeight + padding.Vertical() + buttonPadding.Vertical())).SetDock(Dock.top);
83 }
84
85 public ControlCreateParams& ToolBarControlCreateParams(ControlCreateParams& controlCreateParams)
86 {
87 return ToolBarControlCreateParams(controlCreateParams, DefaultToolBarPadding(), DefaultToolButtonPadding(), DefaultToolButtonHeight());
88 }
89
90 public class ToolBarCreateParams
91 {
92 public ToolBarCreateParams(ControlCreateParams& controlCreateParams_) :
93 controlCreateParams(controlCreateParams_),
94 toolTipWindowColor(DefaultToolTipWindowColor()),
95 toolButtonTransparentColor(DefaultToolButtonTransparentColor()),
96 toolButtonHeight(DefaultToolButtonHeight()),
97 style(DefaultToolBarStyle()),
98 padding(DefaultToolBarPadding()),
99 buttonPadding(DefaultToolButtonPadding()),
100 darkColor(DefaultToolBarDarkColor()),
101 lightColor(DefaultToolBarLightColor()),
102 mediumLightColor(DefaultToolBarMediumLightColor()),
103 mediumDarkColor(DefaultToolBarMediumDarkColor()),
104 disabledColor(DefaultToolBarDisabledColor()),
105 toolButtonSeparatorColor1(DefaultToolBarToolButtonSeparatorColor1()),
106 toolButtonSeparatorColor2(DefaultToolBarToolButtonSeparatorColor2())
107 {
108 }
109 public ToolBarCreateParams& Defaults()
110 {
111 return *this;
112 }
113 public ToolBarCreateParams& SetToolTipWindowColor(const Color& toolTipWindowColor_)
114 {
115 toolTipWindowColor = toolTipWindowColor_;
116 return *this;
117 }
118 public ToolBarCreateParams& SetToolButtonTransparentColor(const Color& toolButtonTransparentColor_)
119 {
120 toolButtonTransparentColor = toolButtonTransparentColor_;
121 return *this;
122 }
123 public ToolBarCreateParams& SetToolButtonHeight(int toolButtonHeight_)
124 {
125 toolButtonHeight = toolButtonHeight_;
126 return *this;
127 }
128 public ToolBarCreateParams& SetStyle(ToolBar.Style style_)
129 {
130 style = style_;
131 return *this;
132 }
133 public ToolBarCreateParams& SetPadding(const Padding& padding_)
134 {
135 padding = padding_;
136 return *this;
137 }
138 public ToolBarCreateParams& SetButtonPadding(const Padding& buttonPadding_)
139 {
140 buttonPadding = buttonPadding_;
141 return *this;
142 }
143 public ToolBarCreateParams& SetDarkColor(const Color& darkColor_)
144 {
145 darkColor = darkColor_;
146 return *this;
147 }
148 public ToolBarCreateParams& SetLightColor(const Color& lightColor_)
149 {
150 lightColor = lightColor_;
151 return *this;
152 }
153 public ToolBarCreateParams& SetMediumLightColor(const Color& mediumLightColor_)
154 {
155 mediumLightColor = mediumLightColor_;
156 return *this;
157 }
158 public ToolBarCreateParams& SetMediumDarkColor(const Color& mediumDarkColor_)
159 {
160 mediumDarkColor = mediumDarkColor_;
161 return *this;
162 }
163 public ToolBarCreateParams& SetDisabledColor(const Color& disabledColor_)
164 {
165 disabledColor = disabledColor_;
166 return *this;
167 }
168 public ToolBarCreateParams& SetToolButtonSeparatorColor1(const Color& toolButtonSeparatorColor1_)
169 {
170 toolButtonSeparatorColor1 = toolButtonSeparatorColor1_;
171 return *this;
172 }
173 public ToolBarCreateParams& SetToolButtonSeperatorColor2(const Color& toolButtonSeparatorColor2_)
174 {
175 toolButtonSeparatorColor2 = toolButtonSeparatorColor2_;
176 return *this;
177 }
178 public ControlCreateParams& controlCreateParams;
179 public Color toolTipWindowColor;
180 public Color toolButtonTransparentColor;
181 public int toolButtonHeight;
182 public ToolBar.Style style;
183 public Padding padding;
184 public Padding buttonPadding;
185 public Color darkColor;
186 public Color lightColor;
187 public Color mediumLightColor;
188 public Color mediumDarkColor;
189 public Color disabledColor;
190 public Color toolButtonSeparatorColor1;
191 public Color toolButtonSeparatorColor2;
192 }
193
194 public class ToolBar : Control
195 {
196 private enum Flags : sbyte
197 {
198 none = 0, toolTipWindowAdded = 1 << 0, toolTipWindowVisible = 1 << 1
199 }
200 public enum Style
201 {
202 regular = 0, radioButtonGroup = 1
203 }
204 public ToolBar(const Color& backgroundColor, const Color& toolTipWindowColor, const Color& toolButtonTransparentColor_, const Point& location,
205 const Size& size, Dock dock, Anchors anchors,
206 int toolButtonHeight_, Style style_, const Padding& padding_, const Padding& buttonPadding_) :
207 base("System.Windows.ToolBar", DefaultWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
208 backgroundColor, "toolBar", location, size, dock, anchors), flags(Flags.none), toolButtonTransparentColor(toolButtonTransparentColor_),
209 toolButtonHeight(toolButtonHeight_), darkColor(Color(100u, 100u, 100u)), lightColor(Color.White()), mediumLightColor(227u, 227u, 227u),
210 mediumDarkColor(160u, 160u, 160u), disabledColor(Color(204u, 204u, 207u)),
211 toolButtonSeparatorColor1(204u, 206u, 219u), toolButtonSeparatorColor2(245u, 245u, 245u), mouseInToolButton(null), mouseDownToolButton(null),
212 pressedStateToolButton(null), style(style_), toolTipWindow(new ToolTip(toolTipWindowColor)), padding(padding_), buttonPadding(buttonPadding_),
213 toolButtons(this), centerFormat(StringAlignment.center, StringAlignment.center)
214 {
215 SetMouseHoverMs(DefaultMouseHoverMs());
216 if (toolTipWindow->Error())
217 {
218 SetErrorId(toolTipWindow->GetErrorId());
219 }
220 }
221 public ToolBar(int toolButtonHeight, const Color& toolTipWindowColor, const Color& toolButtonTransparentColor, Style style,
222 const Padding& padding, const Padding& buttonPadding) :
223 this(DefaultControlBackgroundColor(), toolTipWindowColor, toolButtonTransparentColor, Point(padding.left, padding.top),
224 Size(0, toolButtonHeight + padding.Vertical() + buttonPadding.Vertical()), Dock.top, Anchors.none, toolButtonHeight, style,
225 padding, buttonPadding)
226 {
227 }
228 public ToolBar(Style style) : this(38, Color.FloralWhite(), Color.DefaultBitmapTransparent(), style, DefaultPadding(), DefaultButtonPadding())
229 {
230 }
231 public ToolBar() : this(Style.regular)
232 {
233 }
234 public ToolBar(ToolBarCreateParams& createParams) :
235 base(createParams.controlCreateParams),
236 flags(Flags.none), toolButtonTransparentColor(createParams.toolButtonTransparentColor),
237 toolButtonHeight(createParams.toolButtonHeight),
238 darkColor(createParams.darkColor),
239 lightColor(createParams.lightColor),
240 mediumLightColor(createParams.mediumLightColor),
241 mediumDarkColor(createParams.mediumDarkColor),
242 disabledColor(createParams.disabledColor),
243 toolButtonSeparatorColor1(createParams.toolButtonSeparatorColor1),
244 toolButtonSeparatorColor2(createParams.toolButtonSeparatorColor2),
245 mouseInToolButton(null), mouseDownToolButton(null), pressedStateToolButton(null),
246 style(createParams.style), toolTipWindow(new ToolTip(createParams.toolTipWindowColor)),
247 padding(createParams.padding),
248 buttonPadding(createParams.buttonPadding),
249 toolButtons(this),
250 centerFormat(StringAlignment.center, StringAlignment.center)
251 {
252 SetMouseHoverMs(DefaultMouseHoverMs());
253 if (toolTipWindow->Error())
254 {
255 SetErrorId(toolTipWindow->GetErrorId());
256 }
257 }
258 public void SetTextToolButtonFont(const Font& textToolButtonFont_)
259 {
260 textToolButtonFont = textToolButtonFont_;
261 }
262 public inline const Font& GetTextToolButtonFont() const
263 {
264 return textToolButtonFont;
265 }
266 public inline const StringFormat& CenterFormat() const
267 {
268 return centerFormat;
269 }
270 public inline const int ToolButtonHeight() const
271 {
272 return toolButtonHeight;
273 }
274 public override Padding DefaultPadding() const
275 {
276 return Padding(0, 0, 0, 0);
277 }
278 public Padding DefaultButtonPadding()
279 {
280 return Padding(0, 0, 0, 0);
281 }
282 public const Padding& GetPadding() const
283 {
284 return padding;
285 }
286 public const Padding& GetButtonPadding()
287 {
288 return buttonPadding;
289 }
290 public void SetButtonPadding(const Padding& buttonPadding_)
291 {
292 buttonPadding = buttonPadding_;
293 }
294 public ~ToolBar()
295 {
296 if (toolTipWindow != null && ToolTipWindowAdded())
297 {
298 ResetToolTipWindowAdded();
299 Window* window = GetWindow();
300 if (window != null)
301 {
302 auto result = window->RemoveChild(toolTipWindow);
303 toolTipWindow = null;
304 }
305 }
306 }
307 public inline Style GetStyle() const
308 {
309 return style;
310 }
311 public inline const Color& DarkColor() const
312 {
313 return darkColor;
314 }
315 public void SetDarkColor(const Color& darkColor_)
316 {
317 darkColor = darkColor_;
318 }
319 public inline const Color& LightColor() const
320 {
321 return lightColor;
322 }
323 public void SetLightColor(const Color& lightColor_)
324 {
325 lightColor = lightColor_;
326 }
327 public inline const Color& MediumLightColor() const
328 {
329 return mediumLightColor;
330 }
331 public void SetMediumLightColor(const Color& mediumLightColor_)
332 {
333 mediumLightColor = mediumLightColor_;
334 }
335 public inline const Color& MediumDarkColor() const
336 {
337 return mediumDarkColor;
338 }
339 public void SetMediumDarkColor(const Color& mediumDarkColor_)
340 {
341 mediumDarkColor = mediumDarkColor_;
342 }
343 public inline const Color& DisabledColor() const
344 {
345 return disabledColor;
346 }
347 public void SetDisabledColor(const Color& disabledColor_)
348 {
349 disabledColor = disabledColor_;
350 }
351 public inline const Color& ToolButtonSeparatorColor1() const
352 {
353 return toolButtonSeparatorColor1;
354 }
355 public void SetToolButtonSeparatorColor1(const Color& toolButtonSeparatorColor1_)
356 {
357 toolButtonSeparatorColor1 = toolButtonSeparatorColor1_;
358 }
359 public inline const Color& ToolButtonSeparatorColor2() const
360 {
361 return toolButtonSeparatorColor2;
362 }
363 public void SetToolButtonSeparatorColor2(const Color& toolButtonSeparatorColor2_)
364 {
365 toolButtonSeparatorColor2 = toolButtonSeparatorColor2_;
366 }
367 [nodiscard]
368 public Result<bool> AddToolButton(ToolButtonBase* toolButton)
369 {
370 toolButton->SetToolBar(this);
371 auto result = toolButtons.AddChild(toolButton);
372 if (result.Error())
373 {
374 return Result<bool>(ErrorId(result.GetErrorId()));
375 }
376 if (toolButton is ToolButton*)
377 {
378 ToolButton* tb = cast<ToolButton*>(toolButton);
379 tb->SetTransparentColor(toolButtonTransparentColor);
380 auto result = SetToolButtonBitmaps(tb);
381 if (result.Error())
382 {
383 return Result<bool>(ErrorId(result.GetErrorId()));
384 }
385 if (style == Style.radioButtonGroup)
386 {
387 if (pressedStateToolButton == null)
388 {
389 auto result = SetPressedStateToolButton(tb);
390 if (result.Error()) return result;
391 }
392 }
393 }
394 return Result<bool>(true);
395 }
396 public ToolButton* GetToolButton(int toolButtonIndex) const
397 {
398 Component* component = toolButtons.FirstChild();
399 int index = 0;
400 while (component != null)
401 {
402 if (component is ToolButton*)
403 {
404 if (index == toolButtonIndex) return cast<ToolButton*>(component);
405 ++index;
406 }
407 component = component->NextSibling();
408 }
409 return null;
410 }
411 public inline ToolButton* PressedStateToolButton() const
412 {
413 if (style == Style.radioButtonGroup)
414 {
415 return pressedStateToolButton;
416 }
417 else
418 {
419 return null;
420 }
421 }
422 [nodiscard]
423 public Result<bool> SetPressedStateToolButton(ToolButton* newPressedStateToolButton)
424 {
425 if (style == Style.radioButtonGroup)
426 {
427 if (pressedStateToolButton != newPressedStateToolButton)
428 {
429 if (pressedStateToolButton != null)
430 {
431 auto result = pressedStateToolButton->SetState(ToolButton.State.normal);
432 if (result.Error()) return result;
433 }
434 pressedStateToolButton = newPressedStateToolButton;
435 if (pressedStateToolButton != null)
436 {
437 auto result = pressedStateToolButton->SetState(ToolButton.State.pressed);
438 if (result.Error()) return result;
439 }
440 }
441 }
442 return Result<bool>(true);
443 }
444 public void ResetPressedStateToolButton()
445 {
446 if (style == Style.radioButtonGroup)
447 {
448 pressedStateToolButton = null;
449 }
450 }
451 [nodiscard]
452 protected override Result<bool> OnPaint(PaintEventArgs& args)
453 {
454 if (!ToolTipWindowAdded())
455 {
456 SetToolTipWindowAdded();
457 Window* window = GetWindow();
458 if (window != null)
459 {
460 auto result = window->AddChild(toolTipWindow);
461 if (result.Error()) return result;
462 }
463 }
464 auto result = args.graphics.Clear(BackgroundColor());
465 if (result.Error()) return result;
466 Point origin(padding.left, padding.top);
467 Component* component = toolButtons.FirstChild();
468 while (component != null)
469 {
470 if (component is ToolButtonBase*)
471 {
472 ToolButtonBase* toolButton = cast<ToolButtonBase*>(component);
473 Size toolButtonSize = toolButton->GetSize();
474 Point toolButtonLocation = origin;
475 toolButtonLocation.Offset(buttonPadding.left, buttonPadding.top + (toolButtonHeight - toolButtonSize.h) / 2);
476 toolButton->SetLocation(toolButtonLocation);
477 result = toolButton->Draw(args.graphics, origin);
478 if (result.Error()) return result;
479 origin.x = origin.x + toolButtonSize.w + buttonPadding.Horizontal();
480 }
481 component = component->NextSibling();
482 }
483 return base->OnPaint(args);
484 }
485 [nodiscard]
486 protected override Result<bool> OnMouseEnter(EnterLeaveEventArgs& args)
487 {
488 auto result = base->OnMouseEnter(args);
489 if (result.Error()) return result;
490 mouseInToolButton = null;
491 mouseDownToolButton = null;
492 return Result<bool>(true);
493 }
494 [nodiscard]
495 protected override Result<bool> OnMouseLeave(EnterLeaveEventArgs& args)
496 {
497 auto result = base->OnMouseLeave(args);
498 if (result.Error()) return result;
499 if (mouseInToolButton != null)
500 {
501 result = mouseInToolButton->MouseLeaveInternal();
502 if (result.Error()) return result;
503 }
504 mouseInToolButton = null;
505 mouseDownToolButton = null;
506 result = HideToolTipWindow();
507 if (result.Error()) return result;
508 return Result<bool>(true);
509 }
510 [nodiscard]
511 protected override Result<bool> OnMouseMove(MouseEventArgs& args)
512 {
513 auto result = base->OnMouseMove(args);
514 if (result.Error()) return result;
515 ToolButton* toolButton = GetToolButtonAt(args.location);
516 if (toolButton != null)
517 {
518 if (mouseInToolButton != toolButton)
519 {
520 if (mouseInToolButton != null)
521 {
522 result = mouseInToolButton->MouseLeaveInternal();
523 if (result.Error()) return result;
524 mouseInToolButton = null;
525 }
526 mouseInToolButton = toolButton;
527 result = mouseInToolButton->MouseEnterInternal();
528 if (result.Error()) return result;
529 }
530 result = toolButton->MouseMoveInternal(args);
531 if (result.Error()) return result;
532 }
533 return Result<bool>(true);
534 }
535 protected override void OnMouseHover(MouseEventArgs& args)
536 {
537 base->OnMouseHover(args);
538 ToolButton* toolButton = GetToolButtonAt(args.location);
539 if (toolButton != null)
540 {
541 toolButton->MouseHoverInternal();
542 }
543 }
544 [nodiscard]
545 protected override Result<bool> OnMouseDown(MouseEventArgs& args)
546 {
547 auto result = base->OnMouseDown(args);
548 if (result.Error()) return result;
549 result = HideToolTipWindow();
550 if (result.Error()) return result;
551 if (style == Style.regular)
552 {
553 ToolButton* toolButton = GetToolButtonAt(args.location);
554 if (toolButton != null)
555 {
556 if (toolButton->GetState() == ToolButton.State.normal)
557 {
558 if (args.buttons == MouseButtons.lbutton)
559 {
560 mouseDownToolButton = toolButton;
561 }
562 result = toolButton->MouseDownInternal(args);
563 if (result.Error()) return result;
564 if (args.buttons == MouseButtons.lbutton)
565 {
566 result = toolButton->SetState(ToolButton.State.pressed);
567 if (result.Error()) return result;
568 }
569 }
570 else
571 {
572 return Result<bool>(true);
573 }
574 }
575 WinSetCapture(Handle());
576 }
577 else if (style == Style.radioButtonGroup)
578 {
579 ToolButton* toolButton = GetToolButtonAt(args.location);
580 if (toolButton != null)
581 {
582 if (args.buttons == MouseButtons.lbutton)
583 {
584 auto result = SetPressedStateToolButton(toolButton);
585 if (result.Error()) return result;
586 result = toolButton->DoClick();
587 if (result.Error()) return result;
588 }
589 }
590 }
591 return Result<bool>(true);
592 }
593 [nodiscard]
594 protected override Result<bool> OnMouseUp(MouseEventArgs& args)
595 {
596 auto result = base->OnMouseUp(args);
597 if (result.Error()) return result;
598 if (style == Style.regular)
599 {
600 ToolButton* toolButton = GetToolButtonAt(args.location);
601 if (toolButton != null)
602 {
603 if (toolButton->GetState() == ToolButton.State.pressed)
604 {
605 toolButton->MouseUpInternal(args);
606 if (args.buttons == MouseButtons.lbutton)
607 {
608 if (toolButton == mouseDownToolButton)
609 {
610 auto result = toolButton->DoClick();
611 if (result.Error()) return result;
612 }
613 }
614 }
615 }
616 if (mouseDownToolButton != null && mouseDownToolButton->GetStyle() == ToolButton.Style.automatic)
617 {
618 result = mouseDownToolButton->SetState(ToolButton.State.normal);
619 if (result.Error()) return result;
620 }
621 mouseDownToolButton = null;
622 WinReleaseCapture();
623 }
624 return Result<bool>(true);
625 }
626 internal Result<bool> ShowToolTipWindow(ToolButton* toolButton)
627 {
628 if (toolTipWindow == null || !ToolTipWindowAdded()) return Result<bool>(false);
629 if (ToolTipWindowVisible())
630 {
631 auto result = toolTipWindow->Hide();
632 if (result.Error()) return result;
633 }
634 ResetToolTipWindowVisible();
635 Point loc = toolButton->Location();
636 Size size = toolButton->GetSize();
637 auto result = toolTipWindow->SetText(toolButton->GetToolTip());
638 if (result.Error()) return result;
639 result = toolTipWindow->MeasureExtent();
640 if (result.Error()) return result;
641 Point pt(loc.x, loc.y + size.h + 8);
642 auto clientToScreenResult = ClientToScreen(pt);
643 if (clientToScreenResult.Error())
644 {
645 return Result<bool>(ErrorId(clientToScreenResult.GetErrorId()));
646 }
647 pt = clientToScreenResult.Value();
648 Window* window = GetWindow();
649 if (window != null)
650 {
651 auto screentToClientResult = window->ScreenToClient(pt);
652 if (screentToClientResult.Error())
653 {
654 return Result<bool>(ErrorId(screentToClientResult.GetErrorId()));
655 }
656 pt = screentToClientResult.Value();
657 Size sz = toolTipWindow->GetSize();
658 auto locationResult = window->Location();
659 if (locationResult.Error())
660 {
661 return Result<bool>(ErrorId(locationResult.GetErrorId()));
662 }
663 Point wloc = locationResult.Value();
664 Size wsz = window->GetSize();
665 if (pt.y + sz.h > wloc.y + wsz.h)
666 {
667 pt.y = wloc.y + wsz.h - sz.h;
668 }
669 if (pt.x + sz.w > wloc.x + wsz.w)
670 {
671 pt.x = wloc.x + wsz.w - sz.w;
672 }
673 result = toolTipWindow->SetLocation(pt);
674 if (result.Error()) return result;
675 result = toolTipWindow->BringToFront();
676 if (result.Error()) return result;
677 result = toolTipWindow->Show();
678 if (result.Error()) return result;
679 result = toolTipWindow->Invalidate();
680 if (result.Error()) return result;
681 SetToolTipWindowVisible();
682 }
683 return Result<bool>(true);
684 }
685 [nodiscard]
686 internal Result<bool> HideToolTipWindow()
687 {
688 if (toolTipWindow == null || !ToolTipWindowAdded() || !ToolTipWindowVisible()) return Result<bool>(false);
689 auto result = toolTipWindow->Hide();
690 if (result.Error()) return result;
691 ResetToolTipWindowVisible();
692 return Result<bool>(true);
693 }
694 internal SolidBrush* GetOrInsertSolidBrush(const Color& color)
695 {
696 HashMap<Color, SolidBrush*>.ConstIterator it = textBrushMap.CFind(color);
697 if (it != textBrushMap.CEnd())
698 {
699 return it->second;
700 }
701 else
702 {
703 UniquePtr<SolidBrush> brushPtr(new SolidBrush(color));
704 SolidBrush* brush = brushPtr.Get();
705 textBrushMap[color] = brushPtr.Get();
706 textBrushes.Add(Rvalue(brushPtr));
707 return brush;
708 }
709 }
710 private Result<bool> SetToolButtonBitmaps(ToolButton* toolButton)
711 {
712 Result<Pair<Bitmap*, Bitmap*>> toolBitmapPairResult = GetOrCreateBitmaps(toolButton->ToolBitmapName());
713 if (toolBitmapPairResult.Error())
714 {
715 return Result<bool>(ErrorId(toolBitmapPairResult.GetErrorId()));
716 }
717 Pair<Bitmap*, Bitmap*> toolBitmapPair = toolBitmapPairResult.Value();
718 toolButton->SetToolBitmaps(toolBitmapPair.first, toolBitmapPair.second);
719 return Result<bool>(true);
720 }
721 private Result<Pair<Bitmap*, Bitmap*>> GetOrCreateBitmaps(const string& bitmapName)
722 {
723 Pair<Bitmap*, Bitmap*> bitmapPair;
724 if (bitmapName.IsEmpty()) return bitmapPair;
725 auto it = bitmapMap.Find(bitmapName);
726 if (it != bitmapMap.End())
727 {
728 return Result<Pair<Bitmap*, Bitmap*>>(it->second);
729 }
730 auto bitmapResult = Bitmap.FromResource(bitmapName);
731 if (bitmapResult.Error())
732 {
733 return Result<Pair<Bitmap*, Bitmap*>>(ErrorId(bitmapResult.GetErrorId()));
734 }
735 UniquePtr<Bitmap> bitmapPtr(new Bitmap(Rvalue(bitmapResult.Value())));
736 Bitmap* bitmap = bitmapPtr.Get();
737 auto grayBitmapResult = bitmap->ToGrayBitmap();
738 if (grayBitmapResult.Error())
739 {
740 return Result<Pair<Bitmap*, Bitmap*>>(ErrorId(grayBitmapResult.GetErrorId()));
741 }
742 UniquePtr<Bitmap> disabledBitmapPtr(new Bitmap(Rvalue(grayBitmapResult.Value())));
743 Bitmap* disabledBitmap = disabledBitmapPtr.Get();
744 bitmapPair = MakePair(bitmap, disabledBitmap);
745 bitmapMap[bitmapName] = bitmapPair;
746 bitmaps.Add(Rvalue(bitmapPtr));
747 bitmaps.Add(Rvalue(disabledBitmapPtr));
748 return Result<Pair<Bitmap*, Bitmap*>>(bitmapPair);
749 }
750 private ToolButton* GetToolButtonAt(const Point& location) const
751 {
752 Size size = GetSize();
753 if (location.y >= 0 && location.y < size.h && location.x >= 0 && location.x < size.w)
754 {
755 Component* component = toolButtons.FirstChild();
756 while (component != null)
757 {
758 if (component is ToolButton*)
759 {
760 ToolButton* toolButton = cast<ToolButton*>(component);
761 if (location.x >= toolButton->Location().x && location.x <= toolButton->Location().x + toolButton->GetSize().w)
762 {
763 return toolButton;
764 }
765 }
766 component = component->NextSibling();
767 }
768 }
769 return null;
770 }
771 private inline bool ToolTipWindowAdded() const
772 {
773 return (flags & Flags.toolTipWindowAdded) != Flags.none;
774 }
775 private inline void SetToolTipWindowAdded()
776 {
777 flags = cast<Flags>(flags | Flags.toolTipWindowAdded);
778 }
779 private inline void ResetToolTipWindowAdded()
780 {
781 flags = cast<Flags>(flags & ~Flags.toolTipWindowAdded);
782 }
783 private inline bool ToolTipWindowVisible() const
784 {
785 return (flags & Flags.toolTipWindowVisible) != Flags.none;
786 }
787 private inline void SetToolTipWindowVisible()
788 {
789 flags = cast<Flags>(flags | Flags.toolTipWindowVisible);
790 }
791 private inline void ResetToolTipWindowVisible()
792 {
793 flags = cast<Flags>(flags & ~Flags.toolTipWindowVisible);
794 }
795 private Flags flags;
796 private ComponentContainer toolButtons;
797 private Color toolButtonTransparentColor;
798 private int toolButtonHeight;
799 private List<UniquePtr<Bitmap>> bitmaps;
800 private HashMap<string, Pair<Bitmap*, Bitmap*>> bitmapMap;
801 private Color darkColor;
802 private Color lightColor;
803 private Color mediumLightColor;
804 private Color mediumDarkColor;
805 private Color disabledColor;
806 private Color toolButtonSeparatorColor1;
807 private Color toolButtonSeparatorColor2;
808 private ToolButton* mouseInToolButton;
809 private ToolButton* mouseDownToolButton;
810 private ToolButton* pressedStateToolButton;
811 private Style style;
812 private ToolTip* toolTipWindow;
813 private Padding padding;
814 private Padding buttonPadding;
815 private Font textToolButtonFont;
816 private StringFormat centerFormat;
817 private HashMap<Color, SolidBrush*> textBrushMap;
818 private List<UniquePtr<SolidBrush>> textBrushes;
819 }
820
821 public abstract class ToolButtonBase : Component
822 {
823 public ToolButtonBase() : location(), size()
824 {
825 }
826 public virtual void SetToolBar(ToolBar* toolBar_)
827 {
828 toolBar = toolBar_;
829 }
830 public inline ToolBar* GetToolBar() const
831 {
832 return toolBar;
833 }
834 public abstract Result<bool> Draw(Graphics& graphics, const Point& origin);
835 public inline const Point& Location() const
836 {
837 return location;
838 }
839 public inline void SetLocation(const Point& location_)
840 {
841 location = location_;
842 }
843 public inline const Size& GetSize() const
844 {
845 return size;
846 }
847 public inline void SetSize(const Size& size_)
848 {
849 size = size_;
850 }
851 private ToolBar* toolBar;
852 private Point location;
853 private Size size;
854 }
855
856 public class ToolButtonSeparator : ToolButtonBase
857 {
858 public ToolButtonSeparator() : base()
859 {
860 }
861 public override void SetToolBar(ToolBar* toolBar)
862 {
863 base->SetToolBar(toolBar);
864 SetSize(Size(2, toolBar->ToolButtonHeight() - 4));
865 }
866 [nodiscard]
867 public override Result<bool> Draw(Graphics& graphics, const Point& origin)
868 {
869 ToolBar* toolBar = GetToolBar();
870 Point location = Location();
871 Size size = GetSize();
872 Point firstLineStart(origin.x, origin.y);
873 Point firstLineEnd(firstLineStart.x, firstLineStart.y + size.h);
874 Pen firstLinePen(toolBar->ToolButtonSeparatorColor1());
875 if (firstLinePen.Error())
876 {
877 return Result<bool>(ErrorId(firstLinePen.GetErrorId()));
878 }
879 auto result = graphics.DrawLine(firstLinePen, firstLineStart, firstLineEnd);
880 if (result.Error())
881 {
882 return Result<bool>(ErrorId(result.GetErrorId()));
883 }
884 Point secondLineStart(origin.x + 1, origin.y + location.y);
885 Point secondLineEnd(secondLineStart.x, secondLineStart.y + size.h);
886 Pen secondLinePen(toolBar->ToolButtonSeparatorColor2());
887 if (secondLinePen.Error())
888 {
889 return Result<bool>(ErrorId(secondLinePen.GetErrorId()));
890 }
891 result = graphics.DrawLine(secondLinePen, secondLineStart, secondLineEnd);
892 if (result.Error())
893 {
894 return Result<bool>(ErrorId(result.GetErrorId()));
895 }
896 return Result<bool>(true);
897 }
898 }
899
900 public class ClickGuard
901 {
902 public explicit ClickGuard(ToolButton* toolButton_) : toolButton(toolButton_)
903 {
904 }
905 public ~ClickGuard()
906 {
907 if (toolButton->GetStyle() == ToolButton.Style.automatic)
908 {
909 auto result = toolButton->SetState(ToolButton.State.normal);
910 }
911 }
912 private ToolButton* toolButton;
913 }
914
915 public class ToolButton : ToolButtonBase
916 {
917 public enum State : sbyte
918 {
919 normal = 0, pressed = 1, disabled = 2
920 }
921 public enum Style : sbyte
922 {
923 automatic, manual
924 }
925 public ToolButton(const string& toolBitmapName_, Style style_) :
926 base(), state(State.normal), toolBitmapName(toolBitmapName_), toolBitmap(null), transparentColor(Color.DefaultBitmapTransparent()), padding(DefaultPadding()),
927 style(style_)
928 {
929 }
930 public ToolButton(const string& toolBitmapName) : this(toolBitmapName, Style.automatic)
931 {
932 }
933 public virtual default ~ToolButton();
934 public inline Style GetStyle() const
935 {
936 return style;
937 }
938 [nodiscard]
939 public Result<bool> Enable()
940 {
941 if (state == State.disabled)
942 {
943 auto result = SetState(State.normal);
944 if (result.Error()) return result;
945 }
946 return Result<bool>(true);
947 }
948 [nodiscard]
949 public Result<bool> Disable()
950 {
951 if (state == State.normal)
952 {
953 auto result = SetState(State.disabled);
954 if (result.Error()) return result;
955 }
956 return Result<bool>(true);
957 }
958 public Padding GetPadding() const
959 {
960 return padding;
961 }
962 public void SetPadding(const Padding& padding_)
963 {
964 padding = padding_;
965 }
966 protected Padding DefaultPadding()
967 {
968 return Padding(3, 3, 3, 3);
969 }
970 public inline State GetState() const
971 {
972 return state;
973 }
974 [nodiscard]
975 public Result<bool> SetState(State state_)
976 {
977 ToolBar* toolBar = GetToolBar();
978 if (state != state_)
979 {
980 if (state_ == State.pressed)
981 {
982 if (toolBar->GetStyle() == ToolBar.Style.radioButtonGroup)
983 {
984 if (toolBar->PressedStateToolButton() != this)
985 {
986 auto result = toolBar->SetPressedStateToolButton(this);
987 if (result.Error()) return result;
988 }
989 }
990 }
991 else if (state_ == State.normal)
992 {
993 if (toolBar->GetStyle() == ToolBar.Style.radioButtonGroup)
994 {
995 if (toolBar->PressedStateToolButton() == this)
996 {
997 toolBar->ResetPressedStateToolButton();
998 }
999 }
1000 }
1001 state = state_;
1002 auto result = Invalidate();
1003 if (result.Error()) return result;
1004 }
1005 return Result<bool>(true);
1006 }
1007 [nodiscard]
1008 public Result<bool> SetToolTip(const string& toolTip_)
1009 {
1010 if (toolTip != toolTip_)
1011 {
1012 toolTip = toolTip_;
1013 auto result = Invalidate();
1014 if (result.Error()) return result;
1015 }
1016 return Result<bool>(true);
1017 }
1018 public inline const string& GetToolTip() const
1019 {
1020 return toolTip;
1021 }
1022 public void SetTransparentColor(const Color& transparentColor_)
1023 {
1024 transparentColor = transparentColor_;
1025 }
1026 [nodiscard]
1027 internal Result<bool> MouseEnterInternal()
1028 {
1029 EnterLeaveEventArgs args;
1030 auto result = OnMouseEnter(args);
1031 if (result.Error()) return result;
1032 return Result<bool>(true);
1033 }
1034 internal void MouseHoverInternal()
1035 {
1036 ToolBar* toolBar = GetToolBar();
1037 if (!toolTip.IsEmpty() && toolBar != null)
1038 {
1039 toolBar->ShowToolTipWindow(this);
1040 }
1041 }
1042 [nodiscard]
1043 protected virtual Result<bool> OnMouseEnter(EnterLeaveEventArgs& args)
1044 {
1045 mouseEnterEvent.Fire(args);
1046 if (args.errorId != 0)
1047 {
1048 return Result<bool>(ErrorId(args.errorId));
1049 }
1050 return Result<bool>(true);
1051 }
1052 public Event<MouseEnterEventHandler, EnterLeaveEventArgs>& MouseEnterEvent() const
1053 {
1054 return mouseEnterEvent;
1055 }
1056 [nodiscard]
1057 internal Result<bool> MouseLeaveInternal()
1058 {
1059 EnterLeaveEventArgs args;
1060 auto result = OnMouseLeave(args);
1061 if (result.Error()) return result;
1062 ToolBar* toolBar = GetToolBar();
1063 if (!toolTip.IsEmpty() && toolBar != null)
1064 {
1065 auto result = toolBar->HideToolTipWindow();
1066 if (result.Error()) return result;
1067 }
1068 return Result<bool>(true);
1069 }
1070 [nodiscard]
1071 protected virtual Result<bool> OnMouseLeave(EnterLeaveEventArgs& args)
1072 {
1073 mouseLeaveEvent.Fire(args);
1074 if (args.errorId != 0)
1075 {
1076 return Result<bool>(ErrorId(args.errorId));
1077 }
1078 return Result<bool>(true);
1079 }
1080 public Event<MouseLeaveEventHandler, EnterLeaveEventArgs>& MouseLeaveEvent() const
1081 {
1082 return mouseLeaveEvent;
1083 }
1084 [nodiscard]
1085 internal Result<bool> MouseMoveInternal(MouseEventArgs& args)
1086 {
1087 return OnMouseMove(args);
1088 }
1089 [nodiscard]
1090 protected virtual Result<bool> OnMouseMove(MouseEventArgs& args)
1091 {
1092 mouseMoveEvent.Fire(args);
1093 return Result<bool>(true);
1094 }
1095 public Event<MouseEventHandler, MouseEventArgs>& MouseMoveEvent() const
1096 {
1097 return mouseMoveEvent;
1098 }
1099 [nodiscard]
1100 internal Result<bool> MouseDownInternal(MouseEventArgs& args)
1101 {
1102 return OnMouseDown(args);
1103 }
1104 [nodiscard]
1105 protected virtual Result<bool> OnMouseDown(MouseEventArgs& args)
1106 {
1107 mouseDownEvent.Fire(args);
1108 return Result<bool>(true);
1109 }
1110 public Event<MouseEventHandler, MouseEventArgs>& MouseDownEvent() const
1111 {
1112 return mouseDownEvent;
1113 }
1114 internal void MouseUpInternal(MouseEventArgs& args)
1115 {
1116 OnMouseUp(args);
1117 }
1118 protected virtual void OnMouseUp(MouseEventArgs& args)
1119 {
1120 mouseUpEvent.Fire(args);
1121 }
1122 public Event<MouseEventHandler, MouseEventArgs>& MouseUpEvent() const
1123 {
1124 return mouseUpEvent;
1125 }
1126 [nodiscard]
1127 internal Result<bool> DoClick()
1128 {
1129 ClickEventArgs args;
1130 auto result = OnClick(args);
1131 if (result.Error()) return result;
1132 if (args.errorId != 0)
1133 {
1134 return Result<bool>(ErrorId(args.errorId));
1135 }
1136 return Result<bool>(true);
1137 }
1138 [nodiscard]
1139 protected virtual Result<bool> OnClick(ClickEventArgs& args)
1140 {
1141 ClickGuard guard(this);
1142 clickEvent.Fire(args);
1143 return Result<bool>(true);
1144 }
1145 public Event<ClickEventHandler, ClickEventArgs>& ClickEvent() const
1146 {
1147 return clickEvent;
1148 }
1149 [nodiscard]
1150 public override Result<bool> Draw(Graphics& graphics, const Point& location)
1151 {
1152 switch (state)
1153 {
1154 case State.normal:
1155 case State.disabled:
1156 {
1157 return DrawNormalOrDisabled(graphics, location);
1158 }
1159 case State.pressed:
1160 {
1161 return DrawPressed(graphics, location);
1162 }
1163 }
1164 return Result<bool>(true);
1165 }
1166 private Result<bool> DrawNormalOrDisabled(Graphics& graphics, const Point& location)
1167 {
1168 ToolBar* toolBar = GetToolBar();
1169 Pen darkPen(toolBar->DarkColor(), 1.000000f);
1170 if (darkPen.Error())
1171 {
1172 return Result<bool>(ErrorId(darkPen.GetErrorId()));
1173 }
1174 Size size = GetSize();
1175 Rect rect(location, size);
1176 rect.size.w = rect.size.w - 1;
1177 rect.size.h = rect.size.h - 1;
1178 auto result = graphics.DrawRectangle(darkPen, rect);
1179 if (result.Error())
1180 {
1181 return Result<bool>(ErrorId(result.GetErrorId()));
1182 }
1183 Point startRightInnerDarkLoc = location;
1184 startRightInnerDarkLoc.x = startRightInnerDarkLoc.x + size.w - 2;
1185 Point endRightInnerDarkLoc = location;
1186 endRightInnerDarkLoc.x = endRightInnerDarkLoc.x + size.w - 2;
1187 endRightInnerDarkLoc.y = endRightInnerDarkLoc.y + size.h - 1;
1188 result = graphics.DrawLine(darkPen, startRightInnerDarkLoc, endRightInnerDarkLoc);
1189 if (result.Error())
1190 {
1191 return Result<bool>(ErrorId(result.GetErrorId()));
1192 }
1193 Point startBottomInnerDarkLoc = location;
1194 startBottomInnerDarkLoc.x = startBottomInnerDarkLoc.x + 1;
1195 startBottomInnerDarkLoc.y = startBottomInnerDarkLoc.y + size.h - 2;
1196 Point endBottomInnerDarkLoc = location;
1197 endBottomInnerDarkLoc.x = endBottomInnerDarkLoc.x + size.w - 2;
1198 endBottomInnerDarkLoc.y = endBottomInnerDarkLoc.y + size.h - 2;
1199 result = graphics.DrawLine(darkPen, startBottomInnerDarkLoc, endBottomInnerDarkLoc);
1200 if (result.Error())
1201 {
1202 return Result<bool>(ErrorId(result.GetErrorId()));
1203 }
1204 Pen lightPen(toolBar->LightColor(), 1.000000f);
1205 Point startTopOuterLightLoc = location;
1206 startTopOuterLightLoc.x = startTopOuterLightLoc.x + 1;
1207 startTopOuterLightLoc.y = startTopOuterLightLoc.y + 1;
1208 Point endTopOuterLightLoc = location;
1209 endTopOuterLightLoc.x = endTopOuterLightLoc.x + size.w - 3;
1210 endTopOuterLightLoc.y = endTopOuterLightLoc.y + 1;
1211 result = graphics.DrawLine(lightPen, startTopOuterLightLoc, endTopOuterLightLoc);
1212 if (result.Error())
1213 {
1214 return Result<bool>(ErrorId(result.GetErrorId()));
1215 }
1216 Point startLeftOuterLightLoc = location;
1217 startLeftOuterLightLoc.x = startLeftOuterLightLoc.x + 1;
1218 startLeftOuterLightLoc.y = startLeftOuterLightLoc.y + 1;
1219 Point endLeftOuterLightLoc = location;
1220 endLeftOuterLightLoc.x = endLeftOuterLightLoc.x + 1;
1221 endLeftOuterLightLoc.y = endLeftOuterLightLoc.y + size.h - 3;
1222 result = graphics.DrawLine(lightPen, startLeftOuterLightLoc, endLeftOuterLightLoc);
1223 if (result.Error())
1224 {
1225 return Result<bool>(ErrorId(result.GetErrorId()));
1226 }
1227 Pen mediumLightPen(toolBar->MediumLightColor(), 1.000000f);
1228 if (mediumLightPen.Error())
1229 {
1230 return Result<bool>(ErrorId(mediumLightPen.GetErrorId()));
1231 }
1232 Point startTopInnerLightLoc = location;
1233 startTopInnerLightLoc.x = startTopInnerLightLoc.x + 2;
1234 startTopInnerLightLoc.y = startTopInnerLightLoc.y + 2;
1235 Point endTopInnerLightLoc = location;
1236 endTopInnerLightLoc.x = endTopInnerLightLoc.x + size.w - 4;
1237 endTopInnerLightLoc.y = endTopInnerLightLoc.y + 2;
1238 result = graphics.DrawLine(mediumLightPen, startTopInnerLightLoc, endTopInnerLightLoc);
1239 if (result.Error())
1240 {
1241 return Result<bool>(ErrorId(result.GetErrorId()));
1242 }
1243 Point startLeftInnerLightLoc = location;
1244 startLeftInnerLightLoc.x = startLeftInnerLightLoc.x + 2;
1245 startLeftInnerLightLoc.y = startLeftInnerLightLoc.y + 2;
1246 Point endLeftInnerLightLoc = location;
1247 endLeftInnerLightLoc.x = endLeftInnerLightLoc.x + 2;
1248 endLeftInnerLightLoc.y = endLeftInnerLightLoc.y + size.h - 4;
1249 result = graphics.DrawLine(mediumLightPen, startLeftInnerLightLoc, endLeftInnerLightLoc);
1250 if (result.Error())
1251 {
1252 return Result<bool>(ErrorId(result.GetErrorId()));
1253 }
1254 Pen mediumDarkPen(toolBar->MediumDarkColor(), 1.000000f);
1255 Point startRightInnerMediumDarkLoc = location;
1256 startRightInnerMediumDarkLoc.x = startRightInnerMediumDarkLoc.x + size.w - 3;
1257 startRightInnerMediumDarkLoc.y = startRightInnerMediumDarkLoc.y + 2;
1258 Point endRightInnerMediumDarkLoc = location;
1259 endRightInnerMediumDarkLoc.x = endRightInnerMediumDarkLoc.x + size.w - 3;
1260 endRightInnerMediumDarkLoc.y = endRightInnerMediumDarkLoc.y + size.h - 3;
1261 result = graphics.DrawLine(mediumDarkPen, startRightInnerMediumDarkLoc, endRightInnerMediumDarkLoc);
1262 if (result.Error())
1263 {
1264 return Result<bool>(ErrorId(result.GetErrorId()));
1265 }
1266 Point startBottomInnerMediumDarkLoc = location;
1267 startBottomInnerMediumDarkLoc.x = startBottomInnerMediumDarkLoc.x + 2;
1268 startBottomInnerMediumDarkLoc.y = startBottomInnerMediumDarkLoc.y + size.h - 3;
1269 Point endBottomInnerMediumDarkLoc = location;
1270 endBottomInnerMediumDarkLoc.x = endBottomInnerMediumDarkLoc.x + size.w - 3;
1271 endBottomInnerMediumDarkLoc.y = endBottomInnerMediumDarkLoc.y + size.h - 3;
1272 result = graphics.DrawLine(mediumDarkPen, startBottomInnerMediumDarkLoc, endBottomInnerMediumDarkLoc);
1273 if (result.Error())
1274 {
1275 return Result<bool>(ErrorId(result.GetErrorId()));
1276 }
1277 return DrawContent(graphics, location);
1278 }
1279 private Result<bool> DrawPressed(Graphics& graphics, const Point& location)
1280 {
1281 ToolBar* toolBar = GetToolBar();
1282 Pen darkPen(toolBar->DarkColor(), 1.000000f);
1283 if (darkPen.Error())
1284 {
1285 return Result<bool>(ErrorId(darkPen.GetErrorId()));
1286 }
1287 Size size = GetSize();
1288 Rect rect(location, size);
1289 rect.size.w = rect.size.w - 1;
1290 rect.size.h = rect.size.h - 1;
1291 auto result = graphics.DrawRectangle(darkPen, rect);
1292 if (result.Error())
1293 {
1294 return Result<bool>(ErrorId(result.GetErrorId()));
1295 }
1296
1297 Point startTopInnerDarkLoc = location;
1298 startTopInnerDarkLoc.x = startTopInnerDarkLoc.x + 1;
1299 startTopInnerDarkLoc.y = startTopInnerDarkLoc.y + 1;
1300 Point endTopInnerDarkLoc = location;
1301 endTopInnerDarkLoc.x = endTopInnerDarkLoc.x + size.w - 2;
1302 endTopInnerDarkLoc.y = endTopInnerDarkLoc.y + 1;
1303 result = graphics.DrawLine(darkPen, startTopInnerDarkLoc, endTopInnerDarkLoc);
1304 if (result.Error())
1305 {
1306 return Result<bool>(ErrorId(result.GetErrorId()));
1307 }
1308
1309 Point startLeftInnerDarkLoc = location;
1310 startLeftInnerDarkLoc.x = startLeftInnerDarkLoc.x + 1;
1311 startLeftInnerDarkLoc.y = startLeftInnerDarkLoc.y + 2;
1312 Point endLeftInnerDarkLoc = location;
1313 endLeftInnerDarkLoc.x = endLeftInnerDarkLoc.x + 1;
1314 endLeftInnerDarkLoc.y = endLeftInnerDarkLoc.y + size.h - 2;
1315 result = graphics.DrawLine(darkPen, startLeftInnerDarkLoc, endLeftInnerDarkLoc);
1316 if (result.Error())
1317 {
1318 return Result<bool>(ErrorId(result.GetErrorId()));
1319 }
1320
1321 Pen mediumDarkPen(toolBar->MediumDarkColor(), 1.000000f);
1322 Point startTopInnerMediumDarkLoc = location;
1323 startTopInnerMediumDarkLoc.x = startTopInnerMediumDarkLoc.x + 2;
1324 startTopInnerMediumDarkLoc.y = startTopInnerMediumDarkLoc.y + 2;
1325 Point endTopInnerMediumDarkLoc = location;
1326 endTopInnerMediumDarkLoc.x = endTopInnerMediumDarkLoc.x + size.w - 2;
1327 endTopInnerMediumDarkLoc.y = endTopInnerMediumDarkLoc.y + 2;
1328 result = graphics.DrawLine(mediumDarkPen, startTopInnerMediumDarkLoc, endTopInnerMediumDarkLoc);
1329 if (result.Error())
1330 {
1331 return Result<bool>(ErrorId(result.GetErrorId()));
1332 }
1333
1334 Point startLeftInnerMediumDarkLoc = location;
1335 startLeftInnerMediumDarkLoc.x = startLeftInnerMediumDarkLoc.x + 2;
1336 startLeftInnerMediumDarkLoc.y = startLeftInnerMediumDarkLoc.y + 2;
1337 Point endLeftInnerMediumDarkLoc = location;
1338 endLeftInnerMediumDarkLoc.x = endLeftInnerMediumDarkLoc.x + 2;
1339 endLeftInnerMediumDarkLoc.y = endLeftInnerMediumDarkLoc.y + size.h - 2;
1340 result = graphics.DrawLine(mediumDarkPen, startLeftInnerMediumDarkLoc, endLeftInnerMediumDarkLoc);
1341 if (result.Error())
1342 {
1343 return Result<bool>(ErrorId(result.GetErrorId()));
1344 }
1345
1346 return DrawContent(graphics, Point(location.x + 1, location.y + 1));
1347 }
1348 protected virtual Result<bool> DrawContent(Graphics& graphics, const Point& location)
1349 {
1350 return DrawToolBitmap(graphics, location);
1351 }
1352 private Result<bool> DrawToolBitmap(Graphics& graphics, const Point& location)
1353 {
1354 if (toolBitmap == null) return Result<bool>(false);
1355 Point bitmapLocation(location);
1356 bitmapLocation.x = bitmapLocation.x + padding.left;
1357 bitmapLocation.y = bitmapLocation.y + padding.top;
1358 Rect r(bitmapLocation, toolBitmapSize);
1359 ImageAttributes attributes;
1360 if (attributes.Error())
1361 {
1362 return Result<bool>(ErrorId(attributes.GetErrorId()));
1363 }
1364 auto result = attributes.SetColorKey(transparentColor, transparentColor, ColorAdjustType.default_);
1365 if (result.Error())
1366 {
1367 return Result<bool>(ErrorId(result.GetErrorId()));
1368 }
1369 if (state == State.normal || state == State.pressed)
1370 {
1371 result = graphics.DrawImage(*toolBitmap, r, 0, 0, toolBitmapSize.w, toolBitmapSize.h, Unit.pixel, attributes);
1372 if (result.Error())
1373 {
1374 return Result<bool>(ErrorId(result.GetErrorId()));
1375 }
1376 }
1377 else if (state == State.disabled)
1378 {
1379 result = graphics.DrawImage(*disabledToolBitmap, r, 0, 0, toolBitmapSize.w, toolBitmapSize.h, Unit.pixel, attributes);
1380 if (result.Error())
1381 {
1382 return Result<bool>(ErrorId(result.GetErrorId()));
1383 }
1384 }
1385 return Result<bool>(true);
1386 }
1387 public inline const string& ToolBitmapName() const
1388 {
1389 return toolBitmapName;
1390 }
1391 internal void SetToolBitmaps(Bitmap* toolBitmap_, Bitmap* disabledToolBitmap_)
1392 {
1393 toolBitmap = toolBitmap_;
1394 disabledToolBitmap = disabledToolBitmap_;
1395 if (toolBitmap != null && disabledToolBitmap != null)
1396 {
1397 toolBitmapSize = Size(cast<int>(toolBitmap->GetWidth()), cast<int>(toolBitmap->GetHeight()));
1398 SetSize(Size(padding.Horizontal() + toolBitmapSize.w, padding.Vertical() + toolBitmapSize.h));
1399 }
1400 }
1401 [nodiscard]
1402 private Result<bool> Invalidate()
1403 {
1404 ToolBar* toolBar = GetToolBar();
1405 if (toolBar != null)
1406 {
1407 auto result = toolBar->Invalidate();
1408 if (result.Error()) return result;
1409 }
1410 return Result<bool>(true);
1411 }
1412 private State state;
1413 private Style style;
1414 private string toolBitmapName;
1415 private Bitmap* toolBitmap;
1416 private Bitmap* disabledToolBitmap;
1417 private Color transparentColor;
1418 private Size toolBitmapSize;
1419 private string toolTip;
1420 private Padding padding;
1421 private Event<MouseEnterEventHandler, EnterLeaveEventArgs> mouseEnterEvent;
1422 private Event<MouseLeaveEventHandler, EnterLeaveEventArgs> mouseLeaveEvent;
1423 private Event<MouseEventHandler, MouseEventArgs> mouseMoveEvent;
1424 private Event<MouseEventHandler, MouseEventArgs> mouseDownEvent;
1425 private Event<MouseEventHandler, MouseEventArgs> mouseUpEvent;
1426 private Event<ClickEventHandler, ClickEventArgs> clickEvent;
1427 }
1428
1429 public class TextToolButton : ToolButton
1430 {
1431 public TextToolButton(const string& text_, const Size& size, const Color& textColor_, ToolButton.Style style) :
1432 base("", style), text(text_), textColor(textColor_)
1433 {
1434 SetSize(size);
1435 }
1436 public TextToolButton(const string& text) : this(text, Size(12, 12), Color.Black(), ToolButton.Style.automatic)
1437 {
1438 }
1439 protected override void SetToolBar(ToolBar* toolBar)
1440 {
1441 base->SetToolBar(toolBar);
1442 Padding padding = GetPadding();
1443 Size size = GetSize();
1444 SetSize(Size(padding.Horizontal() + size.w, padding.Vertical() + size.h));
1445 normalBrush = toolBar->GetOrInsertSolidBrush(textColor);
1446 disabledBrush = toolBar->GetOrInsertSolidBrush(textColor.ToGray());
1447 }
1448 protected override Result<bool> DrawContent(Graphics& graphics, const Point& location)
1449 {
1450 return DrawText(graphics, location);
1451 }
1452 private Result<bool> DrawText(Graphics& graphics, const Point& location)
1453 {
1454 TextRenderingHint prevRenderingHint = graphics.GetTextRenderingHint();
1455 auto result = graphics.SetTextRenderingHint(TextRenderingHint.clearTypeGridFit);
1456 if (result.Error())
1457 {
1458 return Result<bool>(ErrorId(result.GetErrorId()));
1459 }
1460 ToolBar* toolBar = GetToolBar();
1461 Brush* brush = normalBrush;
1462 if (GetState() == State.disabled)
1463 {
1464 brush = disabledBrush;
1465 }
1466 Size size = GetSize();
1467 RectF r(PointF(location.x, location.y), SizeF(size.w, size.h));
1468 result = graphics.DrawString(text, toolBar->GetTextToolButtonFont(), r, toolBar->CenterFormat(), *brush);
1469 if (result.Error())
1470 {
1471 return Result<bool>(ErrorId(result.GetErrorId()));
1472 }
1473 result = graphics.SetTextRenderingHint(prevRenderingHint);
1474 if (result.Error())
1475 {
1476 return Result<bool>(ErrorId(result.GetErrorId()));
1477 }
1478 return Result<bool>(true);
1479 }
1480 private string text;
1481 private Color textColor;
1482 private SolidBrush* normalBrush;
1483 private SolidBrush* disabledBrush;
1484 }