1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Windows
  9 {
 10     public ControlCreateParams& GroupBoxControlCreateParams(ControlCreateParams& controlCreateParamsButtonStyle buttonStyle)
 11     {
 12         controlCreateParams.SetWindowClassName("BUTTON");
 13         controlCreateParams.SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | buttonStyle));
 14         controlCreateParams.SetBackgroundColor(DefaultControlBackgroundColor());
 15         return controlCreateParams;
 16     }
 17 
 18     public ControlCreateParams& GroupBoxControlCreateParams(ControlCreateParams& controlCreateParams)
 19     {
 20         return GroupBoxControlCreateParams(controlCreateParamsButtonStyle.BS_GROUPBOX);
 21     }
 22 
 23     public class GroupBoxCreateParams
 24     {
 25         public GroupBoxCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_)
 26         {
 27         }
 28         public GroupBoxCreateParams& Defaults()
 29         {
 30             return *this;
 31         }
 32         public ControlCreateParams& controlCreateParams;
 33     }
 34 
 35     public class GroupBox : ButtonBase
 36     {
 37         public GroupBox(const Color& backgroundColorconst string& textconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
 38             base("BUTTON"DefaultWindowClassStyle()cast<WindowStyle>(DefaultChildWindowStyle() | ButtonStyle.BS_GROUPBOX)DefaultExtendedWindowStyle()
 39             backgroundColortextlocationsizedockanchors)children(this)checkedRadioButton(null)
 40         {
 41         }
 42         public GroupBox(const string& textconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
 43             this(DefaultControlBackgroundColor()textlocationsizedockanchors)
 44         {
 45         }
 46         public GroupBox(GroupBoxCreateParams& createParams) : base(createParams.controlCreateParams)children(this)checkedRadioButton(null)
 47         {
 48         }
 49         [nodiscard]
 50         public Result<bool> AddChild(Control* child)
 51         {
 52             auto result = children.AddChild(child);
 53             if (result.Error()) return result;
 54             ControlEventArgs args(child);
 55             result = OnControlAdded(args);
 56             if (result.Error()) return result;
 57             if (args.errorId != 0)
 58             {
 59                 return Result<bool>(ErrorId(args.errorId));
 60             }
 61             return Result<bool>(true);
 62         }
 63         [nodiscard]
 64         public Result<UniquePtr<Control>> RemoveChild(Control* child)
 65         {
 66             UniquePtr<Component> childComponent = children.RemoveChild(child);
 67             ControlEventArgs args(child);
 68             auto result = OnControlRemoved(args);
 69             if (result.Error()) return Result<UniquePtr<Control>>(ErrorId(result.GetErrorId()));
 70             if (args.errorId != 0)
 71             {
 72                 return Result<UniquePtr<Control>>(ErrorId(args.errorId));
 73             }
 74             return UniquePtr<Control>(childComponent.Release() as Control*);
 75         }
 76         [nodiscard]
 77         public Result<bool> InsertChildBefore(Control* childControl* before)
 78         {
 79             auto result = children.InsertBefore(childbefore);
 80             if (result.Error()) return result;
 81             ControlEventArgs args(child);
 82             result = OnControlAdded(args);
 83             if (result.Error()) return result;
 84             if (args.errorId != 0)
 85             {
 86                 return Result<bool>(ErrorId(args.errorId));
 87             }
 88             return Result<bool>(true);
 89         }
 90         [nodiscard]
 91         public Result<bool> InsertChildAfter(Control* childControl* after)
 92         {
 93             auto result = children.InsertAfter(childafter);
 94             if (result.Error()) return result;
 95             ControlEventArgs args(child);
 96             result = OnControlAdded(args);
 97             if (result.Error()) return result;
 98             if (args.errorId != 0)
 99             {
100                 return Result<bool>(ErrorId(args.errorId));
101             }
102             return Result<bool>(true);
103         }
104         public const ComponentContainer& Children() const
105         {
106             return children;
107         }
108         public inline RadioButton* CheckedRadioButton() const
109         {
110             return checkedRadioButton;
111         }
112         public void SetCheckedRadioButton(RadioButton* radioButton)
113         {
114             if (radioButton != checkedRadioButton)
115             {
116                 if (checkedRadioButton != null)
117                 {
118                     checkedRadioButton->SetChecked(false);
119                 }
120                 checkedRadioButton = radioButton;
121                 if (checkedRadioButton != null)
122                 {
123                     checkedRadioButton->SetChecked(true);
124                 }
125             }
126         }
127         internal inline void ResetCheckedRadioButton()
128         {
129             checkedRadioButton = null;
130         }
131         protected override Result<bool> OnCreated()
132         {
133             auto result = base->OnCreated();
134             if (result.Error())
135             {
136                 return Result<bool>(ErrorId(result.GetErrorId()));
137             }
138             auto graphicsResult = Graphics.FromWindowHandle(Handle());
139             if (graphicsResult.Error())
140             {
141                 return Result<bool>(ErrorId(graphicsResult.GetErrorId()));
142             }
143             Graphics& graphics = graphicsResult.Value();
144             auto fontHandleResult = GetFontHandle(graphics);
145             if (fontHandleResult.Error())
146             {
147                 return Result<bool>(ErrorId(fontHandleResult.GetErrorId()));
148             }
149             FontHandle* fontHandle = fontHandleResult.Value();
150             if (!fontHandle->IsNull())
151             {
152                 SendSetFontMessage(*fontHandle);
153             }
154             SubClassCommandWndProc();
155             return Result<bool>(true);
156         }
157         [nodiscard]
158         protected override Result<bool> OnControlAdded(ControlEventArgs& args)
159         {
160             auto result = base->OnControlAdded(args);
161             if (result.Error()) return result;
162             if (args.control is RadioButton*)
163             {
164                 if (checkedRadioButton == null)
165                 {
166                     SetCheckedRadioButton(cast<RadioButton*>(args.control));
167                 }
168             }
169             return Result<bool>(true);
170         }
171         [nodiscard]
172         protected override Result<bool> OnControlRemoved(ControlEventArgs& args)
173         {
174             auto result = base->OnControlRemoved(args);
175             if (result.Error()) return result;
176             if (args.control is RadioButton*)
177             {
178                 if (checkedRadioButton == cast<RadioButton*>(args.control))
179                 {
180                     ResetCheckedRadioButton();
181                 }
182             }
183             return Result<bool>(true);
184         }
185         [nodiscard]
186         protected override Result<bool> OnChildGotFocus(ControlEventArgs& args)
187         {
188             auto result = base->OnChildGotFocus(args);
189             if (result.Error()) return result;
190             Control* parentControl = ParentControl();
191             if (parentControl != null)
192             {
193                 result = parentControl->OnChildGotFocus(args);
194                 if (result.Error()) return result;
195             }
196             return Result<bool>(true);
197         }
198         [nodiscard]
199         protected override Result<bool> OnChildLostFocus(ControlEventArgs& args)
200         {
201             auto result = base->OnChildLostFocus(args);
202             if (result.Error()) return result;
203             Control* parentControl = ParentControl();
204             if (parentControl != null)
205             {
206                 result = parentControl->OnChildLostFocus(args);
207                 if (result.Error()) return result;
208             }
209             return Result<bool>(true);
210         }
211         internal override Control* GetFirstEnabledTabStopControl() const
212         {
213             Component* child = children.FirstChild();
214             while (child != null)
215             {
216                 if (child is Control*)
217                 {
218                     Control* control = cast<Control*>(child);
219                     Control* tabStopChild = control->GetFirstEnabledTabStopControl();
220                     if (tabStopChild != null)
221                     {
222                         return tabStopChild;
223                     }
224                 }
225                 child = child->NextSibling();
226             }
227             return null;
228         }
229         internal override Control* GetLastEnabledTabStopControl() const
230         {
231             Component* child = children.LastChild();
232             while (child != null)
233             {
234                 if (child is Control*)
235                 {
236                     Control* control = cast<Control*>(child);
237                     Control* tabStopChild = control->GetLastEnabledTabStopControl();
238                     if (tabStopChild != null)
239                     {
240                         return tabStopChild;
241                     }
242                 }
243                 child = child->PrevSibling();
244             }
245             return null;
246         }
247         private ComponentContainer children;
248         private RadioButton* checkedRadioButton;
249     }