1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Windows
  9 {
 10     public enum BorderStyle : sbyte
 11     {
 12         singlestyle3D
 13     }
 14 
 15     public inline nothrow int DefaultSingleBorderWidth()
 16     {
 17         return 1;
 18     }
 19 
 20     public inline nothrow int Default3DBorderWidth()
 21     {
 22         return 2;
 23     }
 24 
 25     public nothrow int GetBorderWidth(BorderStyle borderStyle)
 26     {
 27         switch (borderStyle)
 28         {
 29             case BorderStyle.single: return DefaultSingleBorderWidth();
 30             case BorderStyle.style3D: return Default3DBorderWidth();
 31         }
 32         return 0;
 33     }
 34 
 35     public nothrow Color DefaultBorderedControlNormalBorderdColor()
 36     {
 37         return Color.Black();
 38     }
 39 
 40     public nothrow Color DefaultBorderedControlFocusedBorderColor()
 41     {
 42         return Color.Blue();
 43     }
 44 
 45     public nothrow ControlCreateParams& BorderedControlControlCreateParams(ControlCreateParams& controlCreateParamsControl* child)
 46     {
 47         return controlCreateParams.SetWindowClassName("System.Windows.BorderedControl").SetBackgroundColor(child->BackgroundColor());
 48     }
 49 
 50     public class BorderedControlCreateParams
 51     {
 52         public nothrow BorderedControlCreateParams(ControlCreateParams& controlCreateParams_Control* child_) : 
 53             controlCreateParams(controlCreateParams_)
 54             child(child_)
 55             borderStyle(BorderStyle.single)
 56             borderWidth(GetBorderWidth(borderStyle))
 57             normalBorderColor(DefaultBorderedControlNormalBorderdColor())
 58             focusedBorderColor(DefaultBorderedControlFocusedBorderColor())
 59         {
 60         }
 61         public nothrow BorderedControlCreateParams& Defaults()
 62         {
 63             return *this;
 64         }
 65         public nothrow BorderedControlCreateParams& SetBordedStyle(BorderStyle borderStyle_)
 66         {
 67             borderStyle = borderStyle_;
 68             return *this;
 69         }
 70         public nothrow BorderedControlCreateParams& SetBorderWidth(int borderWidth_)
 71         {
 72             borderWidth = borderWidth_;
 73             return *this;
 74         }
 75         public nothrow BorderedControlCreateParams& SetNormalBorderColor(const Color& normalBorderColor_)
 76         {
 77             normalBorderColor = normalBorderColor_;
 78             return *this;
 79         }
 80         public nothrow  BorderedControlCreateParams& SetFocusedBorderColor(const Color& focusedBorderColor_)
 81         {
 82             focusedBorderColor = focusedBorderColor_;
 83             return *this;
 84         }
 85         public ControlCreateParams& controlCreateParams;
 86         public Control* child;
 87         public BorderStyle borderStyle;
 88         public int borderWidth;
 89         public Color normalBorderColor;
 90         public Color focusedBorderColor;
 91     }
 92 
 93     public class BorderedControl : Control
 94     {
 95         private enum Flags : sbyte
 96         {
 97             none = 0childFocused = 1 << 0
 98         }
 99         public BorderedControl(Control* child_BorderStyle borderStyle_const Color& normalBorderColor_const Color& focusedBorderColor_
100             const Point& locationconst Size& sizeDock dockAnchors anchors) : 
101             base("System.Windows.BorderedControl"DefaultWindowClassStyle()DefaultChildWindowStyle()DefaultExtendedWindowStyle()
102             child_->BackgroundColor()"borderedControl"locationsizedockanchors)
103             container(this)borderStyle(borderStyle_)normalBorderColor(normalBorderColor_)focusedBorderColor(focusedBorderColor_)
104             borderWidth(GetBorderWidth(borderStyle))child(child_)
105         {
106             container.AddChild(child);
107             SetChildPos();
108         }
109         public BorderedControl(Control* childBorderStyle borderStyleconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
110             this(childborderStyleColor.Black()Color.Blue()locationsizedockanchors)
111         {
112         }
113         public BorderedControl(Control* childconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
114             this(childBorderStyle.singlelocationsizedockanchors)
115         {
116         }
117         public BorderedControl(Control* child) : this(childPoint()Size()Dock.noneAnchors.none)
118         {
119         }
120         public BorderedControl(BorderedControlCreateParams& createParams) : 
121             base(createParams.controlCreateParams)
122             container(this)
123             borderStyle(createParams.borderStyle)
124             borderWidth(createParams.borderWidth)
125             normalBorderColor(createParams.normalBorderColor)
126             focusedBorderColor(createParams.focusedBorderColor)
127             child(createParams.child)
128             flags(Flags.none)
129         {
130             container.AddChild(child);
131             SetChildPos();
132         }
133         public nothrow void SetNormalBorderColor(const Color& normalBorderColor_)
134         {
135             if (normalBorderColor != normalBorderColor_)
136             {
137                 normalBorderColor = normalBorderColor_;
138                 Invalidate();
139             }
140         }
141         public nothrow void SetFocusedBorderColor(const Color& focusedBorderColor_)
142         {
143             if (focusedBorderColor != focusedBorderColor_)
144             {
145                 focusedBorderColor = focusedBorderColor_;
146                 Invalidate();
147             }
148         }
149         public nothrow void SetBorderWidth(int borderWidth_)
150         {
151             borderWidth = borderWidth_;
152             Invalidate();
153         }
154         protected override nothrow bool IsDecoratorControl() const
155         {
156             return true;
157         }
158         public override nothrow ContainerControl* GetContainerControl() const
159         {
160             if (child is ContainerControl*)
161             {
162                 return cast<ContainerControl*>(child);
163             }
164             return base->GetContainerControl();
165         }
166         internal override nothrow Control* GetFirstEnabledTabStopControl() const
167         {
168             return child->GetFirstEnabledTabStopControl();
169         }
170         internal override nothrow Control* GetLastEnabledTabStopControl() const
171         {
172             return child->GetLastEnabledTabStopControl();
173         }
174         protected override void OnChildContentLocationChanged(ControlEventArgs& args)
175         {
176             base->OnChildContentLocationChanged(args);
177             Control* parentControl = ParentControl();
178             if (parentControl != null)
179             {
180                 parentControl->OnChildContentLocationChanged(args);
181             }
182         }
183         protected override void OnChildContentChanged(ControlEventArgs& args)
184         {
185             base->OnChildContentChanged(args);
186             Control* parentControl = ParentControl();
187             if (parentControl != null)
188             {
189                 parentControl->OnChildContentChanged(args);
190             }
191         }
192         protected override void OnChildContentSizeChanged(ControlEventArgs& args)
193         {
194             base->OnChildContentSizeChanged(args);
195             Control* parentControl = ParentControl();
196             if (parentControl != null)
197             {
198                 parentControl->OnChildContentSizeChanged(args);
199             }
200         }
201         protected override void OnChildGotFocus(ControlEventArgs& args)
202         {
203             base->OnChildGotFocus(args);
204             SetChildFocused();
205             Control* parentControl = ParentControl();
206             if (parentControl != null)
207             {
208                 parentControl->OnChildGotFocus(args);
209             }
210             Invalidate();
211         }
212         protected override void OnChildLostFocus(ControlEventArgs& args)
213         {
214             base->OnChildLostFocus(args);
215             ResetChildFocused();
216             Control* parentControl = ParentControl();
217             if (parentControl != null)
218             {
219                 parentControl->OnChildLostFocus(args);
220             }
221             Invalidate();
222         }
223         public override void PrintWindowTree(int level)
224         {
225             LogView* log = Application.GetLogView();
226             if (log != null)
227             {
228                 log->WriteLine(string(' 'level) + "BorderedControl." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Location()GetSize()).ToString() + "]");
229             }
230             Component* child = container.FirstChild();
231             while (child != null)
232             {
233                 if (child is Control*)
234                 {
235                     Control* childControl = cast<Control*>(child);
236                     childControl->PrintWindowTree(level + 1);
237                 }
238                 child = child->NextSibling();
239             }
240         }
241         protected override void OnLocationChanged()
242         {
243             base->OnLocationChanged();
244             SetChildPos();
245         }
246         protected override void OnSizeChanged(uint windowState)
247         {
248             base->OnSizeChanged(windowState);
249             SetChildPos();
250         }
251         protected override void OnChildSizeChanged(ControlEventArgs& args)
252         {
253             base->OnChildSizeChanged(args);
254             Control* parentControl = ParentControl();
255             if (parentControl != null)
256             {
257                 parentControl->FireChildSizeChanged(args);
258             }
259         }
260         protected override void OnPaint(PaintEventArgs& args)
261         {
262             if (Debug.Paint())
263             {
264                 Rect r(Point()GetSize());
265                 LogView* log = Application.GetLogView();
266                 if (log != null)
267                 {
268                     log->WriteLine("BorderedControl.OnPaint: " + r.ToString());
269                 }
270             }
271             DrawBorder(args.graphics);
272             base->OnPaint(args);
273         }
274         private void SetChildPos()
275         {
276             Point loc;
277             Size size = GetSize();
278             Rect childRect(locsize);
279             childRect.Inflate(-borderWidth-borderWidth);
280             child->SetLocation(childRect.location);
281             child->SetSize(childRect.size);
282         }
283         private void DrawBorder(Graphics& graphics)
284         {
285             switch (borderStyle)
286             {
287                 case BorderStyle.single: DrawSingleBorder(graphics); break;
288                 case BorderStyle.style3D: Draw3DBorder(graphics); break;
289             }
290         }
291         private void DrawSingleBorder(Graphics& graphics)
292         {
293             Rect r(Point()GetSize());
294             r.size.w = r.size.w - 1;
295             r.size.h = r.size.h - 1;
296             if (ChildFocused())
297             {
298                 Pen pen(focusedBorderColor1);
299                 graphics.DrawRectangleChecked(penr);
300             }
301             else
302             {
303                 Pen pen(normalBorderColor1);
304                 graphics.DrawRectangleChecked(penr);
305             }
306         }
307         private void Draw3DBorder(Graphics& graphics)
308         {
309             Rect r(Point()GetSize());
310             r.size.w = r.size.w - 1;
311             r.size.h = r.size.h - 1;
312             Pen outerLeftTopEdgePen(Color(160u160u160u)1);
313             graphics.DrawLineChecked(outerLeftTopEdgePenr.locationPoint(r.location.x + r.size.w - 1r.location.y));
314             graphics.DrawLineChecked(outerLeftTopEdgePenr.locationPoint(r.location.xr.location.y + r.size.h - 1));
315             Pen outerRightBottomEdgePen(Color.White()1);
316             graphics.DrawLineChecked(outerRightBottomEdgePenPoint(r.location.x + r.size.wr.location.y)Point(r.location.x + r.size.wr.location.y + r.size.h));
317             graphics.DrawLineChecked(outerRightBottomEdgePenPoint(r.location.xr.location.y + r.size.h)Point(r.location.x + r.size.wr.location.y + r.size.h));
318             r.Inflate(-1-1);
319             Pen innerLeftTopEdgePen(Color(105u105u105u)1);
320             graphics.DrawLineChecked(innerLeftTopEdgePenr.locationPoint(r.location.x + r.size.w - 1r.location.y));
321             graphics.DrawLineChecked(innerLeftTopEdgePenr.locationPoint(r.location.xr.location.y + r.size.h - 1));
322             Pen innerRightBottomEdgePen(Color(227u227u227u)1);
323             graphics.DrawLineChecked(innerRightBottomEdgePenPoint(r.location.x + r.size.wr.location.y)Point(r.location.x + r.size.wr.location.y + r.size.h));
324             graphics.DrawLineChecked(innerRightBottomEdgePenPoint(r.location.xr.location.y + r.size.h)Point(r.location.x + r.size.wr.location.y + r.size.h));
325         }
326         private inline nothrow bool ChildFocused() const
327         {
328             return (flags & Flags.childFocused) != Flags.none;
329         }
330         private inline nothrow void SetChildFocused()
331         {
332             flags = cast<Flags>(flags | Flags.childFocused);
333         }
334         private inline nothrow void ResetChildFocused()
335         {
336             flags = cast<Flags>(flags & ~Flags.childFocused);
337         }
338         private Container container;
339         private BorderStyle borderStyle;
340         private int borderWidth;
341         private Color normalBorderColor;
342         private Color focusedBorderColor;
343         private Control* child;
344         private Flags flags;
345     }
346 }