1 // =================================
   2 // Copyright (c) 2024 Seppo Laakko
   3 // Distributed under the MIT license
   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(0000);
  34     }
  35 
  36     public Padding DefaultToolButtonPadding()
  37     {
  38         return Padding(0000);
  39     }
  40 
  41     public Color DefaultToolBarDarkColor()
  42     {
  43         return Color(100u100u100u);
  44     }
  45 
  46     public Color DefaultToolBarLightColor()
  47     {
  48         return Color.White();
  49     }
  50 
  51     public Color DefaultToolBarMediumLightColor()
  52     {
  53         return Color(227u227u227u);
  54     }
  55 
  56     public Color DefaultToolBarMediumDarkColor()
  57     {
  58         return Color(160u160u160u);
  59     }
  60 
  61     public Color DefaultToolBarDisabledColor()
  62     {
  63         return Color(204u204u207u);
  64     }
  65 
  66     public Color DefaultToolBarToolButtonSeparatorColor1()
  67     {
  68         return Color(204u206u219u);
  69     }
  70 
  71     public Color DefaultToolBarToolButtonSeparatorColor2()
  72     {
  73         return Color(245u245u245u);
  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.leftpadding.top)).
  82             SetSize(Size(0toolButtonHeight + padding.Vertical() + buttonPadding.Vertical())).SetDock(Dock.top);
  83     }
  84 
  85     public ControlCreateParams& ToolBarControlCreateParams(ControlCreateParams& controlCreateParams)
  86     {
  87         return ToolBarControlCreateParams(controlCreateParamsDefaultToolBarPadding()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 = 0toolTipWindowAdded = 1 << 0toolTipWindowVisible = 1 << 1
 199         }
 200         public enum Style
 201         {
 202             regular = 0radioButtonGroup = 1
 203         }
 204         public ToolBar(const Color& backgroundColorconst Color& toolTipWindowColorconst Color& toolButtonTransparentColor_const Point& location
 205             const Size& sizeDock dockAnchors anchors
 206             int toolButtonHeight_Style style_const Padding& padding_const Padding& buttonPadding_) : 
 207             base("System.Windows.ToolBar"DefaultWindowClassStyle()DefaultChildWindowStyle()DefaultExtendedWindowStyle()
 208             backgroundColor"toolBar"locationsizedockanchors)flags(Flags.none)toolButtonTransparentColor(toolButtonTransparentColor_)
 209             toolButtonHeight(toolButtonHeight_)darkColor(Color(100u100u100u))lightColor(Color.White())mediumLightColor(227u227u227u)
 210             mediumDarkColor(160u160u160u)disabledColor(Color(204u204u207u))
 211             toolButtonSeparatorColor1(204u206u219u)toolButtonSeparatorColor2(245u245u245u)mouseInToolButton(null)mouseDownToolButton(null)
 212             pressedStateToolButton(null)style(style_)toolTipWindow(new ToolTip(toolTipWindowColor))padding(padding_)buttonPadding(buttonPadding_)
 213             toolButtons(this)centerFormat(StringAlignment.centerStringAlignment.center)
 214         {
 215             SetMouseHoverMs(DefaultMouseHoverMs());
 216             if (toolTipWindow->Error())
 217             {
 218                 SetErrorId(toolTipWindow->GetErrorId());
 219             }
 220         }
 221         public ToolBar(int toolButtonHeightconst Color& toolTipWindowColorconst Color& toolButtonTransparentColorStyle style
 222             const Padding& paddingconst Padding& buttonPadding) : 
 223             this(DefaultControlBackgroundColor()toolTipWindowColortoolButtonTransparentColorPoint(padding.leftpadding.top)
 224                 Size(0toolButtonHeight + padding.Vertical() + buttonPadding.Vertical())Dock.topAnchors.nonetoolButtonHeightstyle
 225                 paddingbuttonPadding)
 226         {
 227         }
 228         public ToolBar(Style style) : this(38Color.FloralWhite()Color.DefaultBitmapTransparent()styleDefaultPadding()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.centerStringAlignment.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(0000);
 277         }
 278         public Padding DefaultButtonPadding()
 279         {
 280             return Padding(0000);
 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.leftpadding.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.leftbuttonPadding.top + (toolButtonHeight - toolButtonSize.h) / 2);
 476                     toolButton->SetLocation(toolButtonLocation);
 477                     result = toolButton->Draw(args.graphicsorigin);
 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.xloc.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<ColorSolidBrush*>.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.firsttoolBitmapPair.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(bitmapdisabledBitmap);
 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<stringPair<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<ColorSolidBrush*> 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& graphicsconst 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(2toolBar->ToolButtonHeight() - 4));
 865         }
 866         [nodiscard]
 867         public override Result<bool> Draw(Graphics& graphicsconst Point& origin)
 868         {
 869             ToolBar* toolBar = GetToolBar();
 870             Point location = Location();
 871             Size size = GetSize();
 872             Point firstLineStart(origin.xorigin.y);
 873             Point firstLineEnd(firstLineStart.xfirstLineStart.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(firstLinePenfirstLineStartfirstLineEnd);
 880             if (result.Error())
 881             {
 882                 return Result<bool>(ErrorId(result.GetErrorId()));
 883             }
 884             Point secondLineStart(origin.x + 1origin.y + location.y);
 885             Point secondLineEnd(secondLineStart.xsecondLineStart.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(secondLinePensecondLineStartsecondLineEnd);
 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 = 0pressed = 1disabled = 2
 920         }
 921         public enum Style : sbyte
 922         {
 923             automaticmanual
 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(toolBitmapNameStyle.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(3333);
 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<MouseEnterEventHandlerEnterLeaveEventArgs>& 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<MouseLeaveEventHandlerEnterLeaveEventArgs>& 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<MouseEventHandlerMouseEventArgs>& 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<MouseEventHandlerMouseEventArgs>& 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<MouseEventHandlerMouseEventArgs>& 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<ClickEventHandlerClickEventArgs>& ClickEvent() const
1146         {
1147             return clickEvent;
1148         }
1149         [nodiscard]
1150         public override Result<bool> Draw(Graphics& graphicsconst Point& location)
1151         {
1152             switch (state)
1153             {
1154                 case State.normal:
1155                 case State.disabled:
1156                 {
1157                     return DrawNormalOrDisabled(graphicslocation);
1158                 }
1159                 case State.pressed:
1160                 {
1161                     return DrawPressed(graphicslocation);
1162                 }
1163             }
1164             return Result<bool>(true);
1165         }
1166         private Result<bool> DrawNormalOrDisabled(Graphics& graphicsconst 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(locationsize);
1176             rect.size.w = rect.size.w - 1;
1177             rect.size.h = rect.size.h - 1;
1178             auto result = graphics.DrawRectangle(darkPenrect);
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(darkPenstartRightInnerDarkLocendRightInnerDarkLoc);
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(darkPenstartBottomInnerDarkLocendBottomInnerDarkLoc);
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(lightPenstartTopOuterLightLocendTopOuterLightLoc);
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(lightPenstartLeftOuterLightLocendLeftOuterLightLoc);
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(mediumLightPenstartTopInnerLightLocendTopInnerLightLoc);
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(mediumLightPenstartLeftInnerLightLocendLeftInnerLightLoc);
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(mediumDarkPenstartRightInnerMediumDarkLocendRightInnerMediumDarkLoc);
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(mediumDarkPenstartBottomInnerMediumDarkLocendBottomInnerMediumDarkLoc);
1273             if (result.Error())
1274             {
1275                 return Result<bool>(ErrorId(result.GetErrorId()));
1276             }
1277             return DrawContent(graphicslocation);
1278         }
1279         private Result<bool> DrawPressed(Graphics& graphicsconst 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(locationsize);
1289             rect.size.w = rect.size.w - 1;
1290             rect.size.h = rect.size.h - 1;
1291             auto result = graphics.DrawRectangle(darkPenrect);
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(darkPenstartTopInnerDarkLocendTopInnerDarkLoc);
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(darkPenstartLeftInnerDarkLocendLeftInnerDarkLoc);
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(mediumDarkPenstartTopInnerMediumDarkLocendTopInnerMediumDarkLoc);
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(mediumDarkPenstartLeftInnerMediumDarkLocendLeftInnerMediumDarkLoc);
1341             if (result.Error())
1342             {
1343                 return Result<bool>(ErrorId(result.GetErrorId()));
1344             }
1345 
1346             return DrawContent(graphicsPoint(location.x + 1location.y + 1));
1347         }
1348         protected virtual Result<bool> DrawContent(Graphics& graphicsconst Point& location)
1349         {
1350             return DrawToolBitmap(graphicslocation);
1351         }
1352         private Result<bool> DrawToolBitmap(Graphics& graphicsconst 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(bitmapLocationtoolBitmapSize);
1359             ImageAttributes attributes;
1360             if (attributes.Error())
1361             {
1362                 return Result<bool>(ErrorId(attributes.GetErrorId()));
1363             }
1364             auto result = attributes.SetColorKey(transparentColortransparentColorColorAdjustType.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(*toolBitmapr00toolBitmapSize.wtoolBitmapSize.hUnit.pixelattributes);
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(*disabledToolBitmapr00toolBitmapSize.wtoolBitmapSize.hUnit.pixelattributes);
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.wpadding.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<MouseEnterEventHandlerEnterLeaveEventArgs> mouseEnterEvent;
1422         private Event<MouseLeaveEventHandlerEnterLeaveEventArgs> mouseLeaveEvent;
1423         private Event<MouseEventHandlerMouseEventArgs> mouseMoveEvent;
1424         private Event<MouseEventHandlerMouseEventArgs> mouseDownEvent;
1425         private Event<MouseEventHandlerMouseEventArgs> mouseUpEvent;
1426         private Event<ClickEventHandlerClickEventArgs> clickEvent;
1427     }
1428 
1429     public class TextToolButton : ToolButton
1430     {
1431         public TextToolButton(const string& text_const Size& sizeconst Color& textColor_ToolButton.Style style) : 
1432             base(""style)text(text_)textColor(textColor_)
1433         {
1434             SetSize(size);
1435         }
1436         public TextToolButton(const string& text) : this(textSize(1212)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.wpadding.Vertical() + size.h));
1445             normalBrush = toolBar->GetOrInsertSolidBrush(textColor);
1446             disabledBrush = toolBar->GetOrInsertSolidBrush(textColor.ToGray());
1447         }
1448         protected override Result<bool> DrawContent(Graphics& graphicsconst Point& location)
1449         {
1450             return DrawText(graphicslocation);
1451         }
1452         private Result<bool> DrawText(Graphics& graphicsconst 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.xlocation.y)SizeF(size.wsize.h));
1468             result = graphics.DrawString(texttoolBar->GetTextToolButtonFont()rtoolBar->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     }