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 class StatusBar : Control
 12     {
 13         private enum Flags : sbyte
 14         {
 15             none = 0changed = 1 << 0
 16         }
 17 
 18         private const int initialHeight = 20;
 19         private const int topLineWidth = 1;
 20 
 21         public StatusBar(const Font& font_const Color& backgroundColorconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
 22             base("System.Windows.StatusBar"DefaultWindowClassStyle()DefaultChildWindowStyle()DefaultExtendedWindowStyle()
 23             backgroundColor"statusBar"locationsizedockanchors)flags(Flags.none)font(font_)stringFormat()textColor(Color.Black())
 24             textBrush(textColor)
 25             topLineColor(215u215u215u)topLinePen(topLineColor1.000000f)
 26             sunkenBorderOuterTopLeftColor(160u160u160u)sunkenBorderOuterTopLeftPen(sunkenBorderOuterTopLeftColor1.000000f)
 27             sunkenBorderInnerTopLeftColor(105u105u105u)sunkenBorderInnerTopLeftPen(sunkenBorderInnerTopLeftColor1.000000f)
 28             sunkenBorderOuterRightBottomColor(Color.White())sunkenBorderOuterRightBottomPen(sunkenBorderOuterRightBottomColor1.000000f)
 29             sunkenBorderInnerRightBottomColor(227u227u227u)sunkenBorderInnerRightBottomPen(sunkenBorderInnerRightBottomColor1.000000f)
 30             raisedBorderOuterTopLeftColor(227u227u227u)raisedBorderOuterTopLeftPen(raisedBorderOuterTopLeftColor1.000000f)
 31             raisedBorderOuterRightBottomColor(105u105u105u)raisedBorderOuterRightBottomPen(raisedBorderOuterRightBottomColor1.000000f)
 32             raisedBorderInnerTopLeftColor(Color.White())raisedBorderInnerTopLeftPen(raisedBorderInnerTopLeftColor1.000000f)
 33             raisedBorderInnerRightBottomColor(160u160u160u)raisedBorderInnerRightBottomPen(raisedBorderInnerRightBottomColor1.000000f)
 34         {
 35             SetChanged();
 36             if (topLinePen.Error())
 37             {
 38                 SetErrorId(topLinePen.GetErrorId());
 39                 return;
 40             }
 41             if (sunkenBorderOuterTopLeftPen.Error())
 42             {
 43                 SetErrorId(sunkenBorderOuterTopLeftPen.GetErrorId());
 44                 return;
 45             }
 46             if (sunkenBorderOuterRightBottomPen.Error())
 47             {
 48                 SetErrorId(sunkenBorderOuterRightBottomPen.GetErrorId());
 49                 return;
 50             }
 51             if (sunkenBorderInnerRightBottomPen.Error())
 52             {
 53                 SetErrorId(sunkenBorderInnerRightBottomPen.GetErrorId());
 54                 return;
 55             }
 56             if (raisedBorderOuterTopLeftPen.Error())
 57             {
 58                 SetErrorId(raisedBorderOuterTopLeftPen.GetErrorId());
 59                 return;
 60             }
 61             if (raisedBorderOuterRightBottomPen.Error())
 62             {
 63                 SetErrorId(raisedBorderOuterRightBottomPen.GetErrorId());
 64                 return;
 65             }
 66             if (raisedBorderInnerTopLeftPen.Error())
 67             {
 68                 SetErrorId(raisedBorderInnerTopLeftPen.GetErrorId());
 69                 return;
 70             }
 71             if (raisedBorderInnerRightBottomPen.Error())
 72             {
 73                 SetErrorId(raisedBorderInnerRightBottomPen.GetErrorId());
 74                 return;
 75             }
 76         }
 77         public StatusBar() : this(Font(FontFamily("Segoe UI")9.000000f)DefaultControlBackgroundColor()Point(00)Size(0initialHeight)Dock.bottomAnchors.none)
 78         {
 79         }
 80         public void AddItem(StatusBarItem* statusBarItem)
 81         {
 82             statusBarItem->SetStatusBar(this);
 83             statusBarItems.Add(UniquePtr<StatusBarItem>(statusBarItem));
 84             SetChanged();
 85         }
 86         public inline const Color& TextColor() const
 87         {
 88             return textColor;
 89         }
 90         public void SetTextColor(const Color& textColor_)
 91         {
 92             if (textColor != textColor_)
 93             {
 94                 SetChanged();
 95                 textColor = textColor_;
 96                 textBrush = SolidBrush(textColor);
 97             }
 98         }
 99         internal inline const Brush& TextBrush() const
100         {
101             return textBrush;
102         }
103         internal inline const Font& TextFont() const
104         {
105             return font;
106         }
107         internal inline const Pen& TopLinePen() const
108         {
109             return topLinePen;
110         }
111         public inline const Color& TopLineColor() const
112         {
113             return topLineColor;
114         }
115         public void SetTopLineColor(const Color& topLineColor_)
116         {
117             if (topLineColor != topLineColor_)
118             {
119                 SetChanged();
120                 topLineColor = topLineColor_;
121                 topLinePen = Pen(topLineColor1.000000f);
122             }
123         }
124         public inline const Color& SunkenBorderOuterTopLeftColor() const
125         {
126             return sunkenBorderOuterTopLeftColor;
127         }
128         public void SetSunkenBorderOuterTopLeftColor(const Color& sunkenBorderOuterTopLeftColor_)
129         {
130             if (sunkenBorderOuterTopLeftColor != sunkenBorderOuterTopLeftColor_)
131             {
132                 SetChanged();
133                 sunkenBorderOuterTopLeftColor = sunkenBorderOuterTopLeftColor_;
134                 sunkenBorderOuterTopLeftPen = Pen(sunkenBorderOuterTopLeftColor1.000000f);
135             }
136         }
137         internal inline const Pen& SunkenBorderOuterTopLeftPen() const
138         {
139             return sunkenBorderOuterTopLeftPen;
140         }
141         public inline const Color& SunkenBorderInnerTopLeftColor() const
142         {
143             return sunkenBorderInnerTopLeftColor;
144         }
145         public void SetSunkenBorderInnerTopLeftColor(const Color& sunkenBorderInnerTopLeftColor_)
146         {
147             if (sunkenBorderInnerTopLeftColor != sunkenBorderInnerTopLeftColor_)
148             {
149                 SetChanged();
150                 sunkenBorderInnerTopLeftColor = sunkenBorderInnerTopLeftColor_;
151                 sunkenBorderInnerTopLeftPen = Pen(sunkenBorderInnerTopLeftColor1.000000f);
152             }
153         }
154         internal inline const Pen& SunkenBorderInnerTopLeftPen() const
155         {
156             return sunkenBorderInnerTopLeftPen;
157         }
158         public inline const Color& SunkenBorderOuterRightBottomColor() const
159         {
160             return sunkenBorderOuterRightBottomColor;
161         }
162         public void SetSunkenBorderOuterRightBottomColor(const Color& sunkenBorderOuterRightBottomColor_)
163         {
164             if (sunkenBorderOuterRightBottomColor != sunkenBorderOuterRightBottomColor_)
165             {
166                 SetChanged();
167                 sunkenBorderOuterRightBottomColor = sunkenBorderOuterRightBottomColor_;
168                 sunkenBorderOuterRightBottomPen = Pen(sunkenBorderOuterRightBottomColor1.000000f);
169             }
170         }
171         internal inline const Pen& SunkenBorderOuterRightBottomPen() const
172         {
173             return sunkenBorderOuterRightBottomPen;
174         }
175         public inline const Color& SunkenBorderInnerRightBottomColor() const
176         {
177             return sunkenBorderInnerRightBottomColor;
178         }
179         public void SetSunkenBorderInnerRightBottomColor(const Color& sunkenBorderInnerRightBottomColor_)
180         {
181             if (sunkenBorderInnerRightBottomColor != sunkenBorderInnerRightBottomColor_)
182             {
183                 SetChanged();
184                 sunkenBorderInnerRightBottomColor = sunkenBorderInnerRightBottomColor_;
185                 sunkenBorderInnerRightBottomPen = Pen(sunkenBorderInnerRightBottomColor1.000000f);
186             }
187         }
188         internal inline const Pen& SunkenBorderInnerRightBottomPen() const
189         {
190             return sunkenBorderInnerRightBottomPen;
191         }
192         public inline const Color& RaisedBorderOuterTopLeftColor() const
193         {
194             return raisedBorderOuterTopLeftColor;
195         }
196         public void SetRaisedBorderOuterTopLeftColor(const Color& raisedBorderOuterTopLeftColor_)
197         {
198             if (raisedBorderOuterTopLeftColor != raisedBorderOuterTopLeftColor_)
199             {
200                 SetChanged();
201                 raisedBorderOuterTopLeftColor = raisedBorderOuterTopLeftColor_;
202                 raisedBorderOuterTopLeftPen = Pen(raisedBorderOuterTopLeftColor1.000000f);
203             }
204         }
205         internal inline const Pen& RaisedBorderOuterTopLeftPen() const
206         {
207             return raisedBorderOuterTopLeftPen;
208         }
209         public inline const Color& RaisedBorderOuterRightBottomColor() const
210         {
211             return raisedBorderOuterRightBottomColor;
212         }
213         public void SetRaisedBorderRightBottomColor(const Color& raisedBorderOuterRightBottomColor_)
214         {
215             if (raisedBorderOuterRightBottomColor != raisedBorderOuterRightBottomColor_)
216             {
217                 SetChanged();
218                 raisedBorderOuterRightBottomColor = raisedBorderOuterRightBottomColor_;
219                 raisedBorderOuterRightBottomPen = Pen(raisedBorderOuterRightBottomColor1.000000f);
220             }
221         }
222         internal inline const Pen& RaisedBorderOuterRightBottomPen() const
223         {
224             return raisedBorderOuterRightBottomPen;
225         }
226         public inline const Color& RaisedBorderInnerTopLeftColor() const
227         {
228             return raisedBorderInnerTopLeftColor;
229         }
230         public void SetRaisedBorderInnerTopLeftColor(const Color& raisedBorderInnerTopLeftColor_)
231         {
232             if (raisedBorderInnerTopLeftColor != raisedBorderInnerTopLeftColor_)
233             {
234                 SetChanged();
235                 raisedBorderInnerTopLeftColor = raisedBorderInnerTopLeftColor_;
236                 raisedBorderInnerTopLeftPen = Pen(raisedBorderInnerTopLeftColor1.000000f);
237             }
238         }
239         internal inline const Pen& RaisedBorderInnerTopLeftPen() const
240         {
241             return raisedBorderInnerTopLeftPen;
242         }
243 
244         public inline const Color& RaisedBorderInnerRightBottomColor() const
245         {
246             return raisedBorderInnerRightBottomColor;
247         }
248         public void SetRaisedBorderInnerRightBottomColor(const Color& raisedBorderInnerRightBottomColor_)
249         {
250             if (raisedBorderInnerRightBottomColor != raisedBorderInnerRightBottomColor_)
251             {
252                 SetChanged();
253                 raisedBorderInnerRightBottomColor = raisedBorderInnerRightBottomColor_;
254                 raisedBorderInnerRightBottomPen = Pen(raisedBorderInnerRightBottomColor1.000000f);
255             }
256         }
257         internal inline const Pen& RaisedBorderInnerRightBottomPen() const
258         {
259             return raisedBorderInnerRightBottomPen;
260         }
261         protected override Padding DefaultPadding() const
262         {
263             return Padding(4444);
264         }
265         [nodiscard]
266         protected override Result<bool> OnPaint(PaintEventArgs& args)
267         {
268             if (Changed())
269             {
270                 ResetChanged();
271                 auto result = Measure(args.graphics);
272                 if (result.Error())
273                 {
274                     return Result<bool>(ErrorId(result.GetErrorId()));
275                 }
276             }
277             auto result = args.graphics.Clear(BackgroundColor());
278             if (result.Error())
279             {
280                 return Result<bool>(ErrorId(result.GetErrorId()));
281             }
282             result = DrawTopLine(args.graphics);
283             if (result.Error())
284             {
285                 return Result<bool>(ErrorId(result.GetErrorId()));
286             }
287             result = DrawItems(args.graphics);
288             if (result.Error())
289             {
290                 return Result<bool>(ErrorId(result.GetErrorId()));
291             }
292             return base->OnPaint(args);
293         }
294         private Result<bool> DrawTopLine(Graphics& graphics)
295         {
296             Size size = GetSize();
297             Point start(00);
298             Point end(size.w - 10);
299             auto result = graphics.DrawLine(topLinePenstartend);
300             if (result.Error())
301             {
302                 return Result<bool>(ErrorId(result.GetErrorId()));
303             }
304             return Result<bool>(true);
305         }
306         private Result<bool> DrawItems(Graphics& graphics)
307         {
308             long n = statusBarItems.Count();
309             for (long i = 0; i < n; ++i;)
310             {
311                 StatusBarItem* item = statusBarItems[i].Get();
312                 auto result = item->Draw(graphics);
313                 if (result.Error())
314                 {
315                     return Result<bool>(ErrorId(result.GetErrorId()));
316                 }
317             }
318             return Result<bool>(true);
319         }
320         [nodiscard]
321         private Result<bool> Measure(Graphics& graphics)
322         {
323             LogView* logView = Application.GetLogView();
324             Padding padding = DefaultPadding();
325             int statusBarItemBorderWidth = StatusBarItem.BorderWidth();
326             int statusBarItemHorizontalPadding = StatusBarItem.HorizontalPadding();
327             int textHeight = 0;
328             long n = statusBarItems.Count();
329             for (long i = 0; i < n; ++i;)
330             {
331                 StatusBarItem* item = statusBarItems[i].Get();
332                 string s = item->Text();
333                 auto utf32Result = ToUtf32(s);
334                 if (utf32Result.Error())
335                 {
336                     return Result<bool>(ErrorId(utf32Result.GetErrorId()));
337                 }
338                 ustring u(Rvalue(utf32Result.Value()));
339                 string z('0'u.Length());
340                 auto result = graphics.MeasureStringRectF(zfontPointF(00)stringFormat);
341                 if (result.Error())
342                 {
343                     return Result<bool>(ErrorId(result.GetErrorId()));
344                 }
345                 RectF rect = result.Value();
346                 textHeight = Max(textHeightcast<int>(rect.size.h));
347                 item->SetTextWidth(cast<int>(rect.size.w));
348             }
349             if (textHeight != 0)
350             {
351                 int height = topLineWidth + padding.Vertical() + 2 * statusBarItemBorderWidth + textHeight;
352                 Size size = GetSize();
353                 size.h = height;
354                 auto result = SetSize(size);
355                 if (result.Error()) return result;
356                 result = DockWindow();
357                 if (result.Error()) return result;
358                 Point leftOrigin(padding.lefttopLineWidth + padding.top);
359                 long springIndex = -1;
360                 for (long i = 0; i < n; ++i;)
361                 {
362                     StatusBarItem* item = statusBarItems[i].Get();
363                     if (item->Spring())
364                     {
365                         springIndex = i;
366                         break;
367                     }
368                     item->SetLocation(leftOrigin);
369                     item->SetSize(Size(2 * statusBarItemBorderWidth + statusBarItemHorizontalPadding + item->TextWidth()2 * statusBarItemBorderWidth + textHeight));
370                     leftOrigin.x = leftOrigin.x + item->GetSize().w;
371                 }
372                 Point rightOrigin(size.w - 1 - padding.righttopLineWidth + padding.top);
373                 if (springIndex != -1)
374                 {
375                     for (long i = n - 1; i > springIndex; --i;)
376                     {
377                         StatusBarItem* item = statusBarItems[i].Get();
378                         if (item->Spring())
379                         {
380                             break;
381                         }
382                         item->SetSize(Size(2 * statusBarItemBorderWidth + statusBarItemHorizontalPadding + item->TextWidth()2 * statusBarItemBorderWidth + textHeight));
383                         rightOrigin.x = rightOrigin.x - item->GetSize().w;
384                         item->SetLocation(rightOrigin);
385                     }
386                     StatusBarItem* springItem = statusBarItems[springIndex].Get();
387                     springItem->SetLocation(leftOrigin);
388                     springItem->SetSize(Size(rightOrigin.x - leftOrigin.x + 12 * statusBarItemBorderWidth + textHeight));
389                 }
390             }
391             return Result<bool>(true);
392         }
393         private inline bool Changed() const
394         {
395             return (flags & Flags.changed) != Flags.none;
396         }
397         public inline void SetChanged()
398         {
399             flags = cast<Flags>(flags | Flags.changed);
400         }
401         private inline void ResetChanged()
402         {
403             flags = cast<Flags>(flags & ~Flags.changed);
404         }
405         private Flags flags;
406         private Font font;
407         private StringFormat stringFormat;
408         private List<UniquePtr<StatusBarItem>> statusBarItems;
409         private Color textColor;
410         private SolidBrush textBrush;
411         private Color topLineColor;
412         private Pen topLinePen;
413         private Color sunkenBorderOuterTopLeftColor;
414         private Pen sunkenBorderOuterTopLeftPen;
415         private Color sunkenBorderInnerTopLeftColor;
416         private Pen sunkenBorderInnerTopLeftPen;
417         private Color sunkenBorderOuterRightBottomColor;
418         private Pen sunkenBorderOuterRightBottomPen;
419         private Color sunkenBorderInnerRightBottomColor;
420         private Pen sunkenBorderInnerRightBottomPen;
421         private Color raisedBorderOuterTopLeftColor;
422         private Pen raisedBorderOuterTopLeftPen;
423         private Color raisedBorderOuterRightBottomColor;
424         private Pen raisedBorderOuterRightBottomPen;
425         private Color raisedBorderInnerTopLeftColor;
426         private Pen raisedBorderInnerTopLeftPen;
427         private Color raisedBorderInnerRightBottomColor;
428         private Pen raisedBorderInnerRightBottomPen;
429     }
430 
431     public class StatusBarItem
432     {
433         public enum BorderStyle : sbyte
434         {
435             flatsunkenraised
436         }
437         public static int BorderWidth()
438         {
439             return 2;
440         }
441         public static int HorizontalPadding()
442         {
443             return 8;
444         }
445         public StatusBarItem(const string& text_BorderStyle borderStyle_bool spring_) : statusBar(null)text(text_)borderStyle(borderStyle_)spring(spring_)
446         {
447         }
448         public StatusBarItem(const string& textBorderStyle borderStyle) : this(textborderStylefalse)
449         {
450         }
451         public StatusBarItem(const string& text) : this(textBorderStyle.flat)
452         {
453         }
454         public StatusBarItem() : this(string())
455         {
456         }
457         public const Point& Location() const
458         {
459             return location;
460         }
461         public void SetLocation(const Point& location_)
462         {
463             location = location_;
464         }
465         public const Size& GetSize() const
466         {
467             return size;
468         }
469         public void SetSize(const Size& size_)
470         {
471             size = size_;
472         }
473         public inline const string& Text() const
474         {
475             return text;
476         }
477         [nodiscard]
478         public Result<bool> SetText(const string& text_)
479         {
480             if (text != text_)
481             {
482                 text = text_;
483                 auto result = Invalidate();
484                 if (result.Error()) return result;
485             }
486             return Result<bool>(true);
487         }
488         public inline int TextWidth() const
489         {
490             return textWidth;
491         }
492         public inline void SetTextWidth(int textWidth_)
493         {
494             textWidth = textWidth_;
495         }
496         public inline BorderStyle GetBorderStyle() const
497         {
498             return borderStyle;
499         }
500         [nodiscard]
501         public Result<bool> SetBorderStyle(BorderStyle borderStyle_)
502         {
503             if (borderStyle != borderStyle_)
504             {
505                 borderStyle = borderStyle_;
506                 auto result = Invalidate();
507                 if (result.Error()) return result;
508             }
509             return Result<bool>(true);
510         }
511         public inline bool Spring() const
512         {
513             return spring;
514         }
515         [nodiscard]
516         public Result<bool> SetSpring(bool spring_)
517         {
518             if (spring != spring_)
519             {
520                 spring = spring_;
521                 auto result = Invalidate();
522                 if (result.Error()) return result;
523             }
524             return Result<bool>(true);
525         }
526         public virtual default ~StatusBarItem();
527         [nodiscard]
528         public Result<bool> Draw(Graphics& graphics)
529         {
530             auto result = DrawBorder(graphics);
531             if (result.Error())
532             {
533                 return Result<bool>(ErrorId(result.GetErrorId()));
534             }
535             result = DrawText(graphics);
536             if (result.Error())
537             {
538                 return Result<bool>(ErrorId(result.GetErrorId()));
539             }
540             return Result<bool>(true);
541         }
542         private Result<bool> DrawText(Graphics& graphics)
543         {
544             const Brush& brush = statusBar->TextBrush();
545             const Font& font = statusBar->TextFont();
546             PointF origin(location.x + 2 + HorizontalPadding() / 2location.y + 2);
547             auto result = graphics.DrawString(textfontoriginbrush);
548             if (result.Error())
549             {
550                 return Result<bool>(ErrorId(result.GetErrorId()));
551             }
552             return Result<bool>(true);
553         }
554         private Result<bool> DrawBorder(Graphics& graphics)
555         {
556             switch (borderStyle)
557             {
558                 case BorderStyle.sunken:
559                 {
560                     auto result = DrawSunkenBorder(graphics);
561                     if (result.Error())
562                     {
563                         return Result<bool>(ErrorId(result.GetErrorId()));
564                     }
565                     break;
566                 }
567                 case BorderStyle.raised:
568                 {
569                     auto result = DrawRaisedBorder(graphics);
570                     if (result.Error())
571                     {
572                         return Result<bool>(ErrorId(result.GetErrorId()));
573                     }
574                     break;
575                 }
576             }
577             return Result<bool>(true);
578         }
579         private Result<bool> DrawSunkenBorder(Graphics& graphics)
580         {
581             const Pen& outerTopLeftPen = statusBar->SunkenBorderOuterTopLeftPen();
582             auto result = graphics.DrawLine(outerTopLeftPenlocationPoint(location.x + size.w - 2location.y));
583             if (result.Error()) return result;
584             result = graphics.DrawLine(outerTopLeftPenlocationPoint(location.xlocation.y + size.h - 2));
585             if (result.Error()) return result;
586             const Pen& outerRightBottomPen = statusBar->SunkenBorderOuterRightBottomPen();
587             result = graphics.DrawLine(outerRightBottomPenPoint(location.x + size.w - 1location.y)Point(location.x + size.w - 1location.y + size.h - 1));
588             if (result.Error()) return result;
589             result = graphics.DrawLine(outerRightBottomPenPoint(location.xlocation.y + size.h - 1)Point(location.x + size.w - 1location.y + size.h - 1));
590             if (result.Error()) return result;
591             const Pen& innerTopLeftPen = statusBar->SunkenBorderInnerTopLeftPen();
592             result = graphics.DrawLine(innerTopLeftPenPoint(location.x + 1location.y + 1)Point(location.x + size.w - 3location.y + 1));
593             if (result.Error()) return result;
594             result = graphics.DrawLine(innerTopLeftPenPoint(location.x + 1location.y + 1)Point(location.x + 1location.y + size.h - 3));
595             if (result.Error()) return result;
596             const Pen& innerRightBottomPen = statusBar->SunkenBorderInnerRightBottomPen();
597             result = graphics.DrawLine(innerRightBottomPenPoint(location.x + size.w - 2location.y + 1)Point(location.x + size.w - 2location.y + size.h - 2));
598             if (result.Error()) return result;
599             result = graphics.DrawLine(innerRightBottomPenPoint(location.x + 1location.y + size.h - 2)Point(location.x + size.w - 2location.y + size.h - 2));
600             if (result.Error()) return result;
601             return Result<bool>(true);
602         }
603         private Result<bool> DrawRaisedBorder(Graphics& graphics)
604         {
605             const Pen& outerTopLeftPen = statusBar->RaisedBorderOuterTopLeftPen();
606             auto result = graphics.DrawLine(outerTopLeftPenlocationPoint(location.x + size.w - 2location.y));
607             if (result.Error()) return result;
608             result = graphics.DrawLine(outerTopLeftPenlocationPoint(location.xlocation.y + size.h - 2));
609             if (result.Error()) return result;
610             const Pen& outerRightBottomPen = statusBar->RaisedBorderOuterRightBottomPen();
611             result = graphics.DrawLine(outerRightBottomPenPoint(location.x + size.w - 1location.y)Point(location.x + size.w - 1location.y + size.h - 1));
612             if (result.Error()) return result;
613             result = graphics.DrawLine(outerRightBottomPenPoint(location.xlocation.y + size.h - 1)Point(location.x + size.w - 1location.y + size.h - 1));
614             if (result.Error()) return result;
615             const Pen& innerTopLeftPen = statusBar->RaisedBorderInnerTopLeftPen();
616             result = graphics.DrawLine(innerTopLeftPenPoint(location.x + 1location.y + 1)Point(location.x + size.w - 3location.y + 1));
617             if (result.Error()) return result;
618             result = graphics.DrawLine(innerTopLeftPenPoint(location.x + 1location.y + 1)Point(location.x + 1location.y + size.h - 3));
619             if (result.Error()) return result;
620             const Pen& innerRightBottomPen = statusBar->RaisedBorderInnerRightBottomPen();
621             result = graphics.DrawLine(innerRightBottomPenPoint(location.x + size.w - 2location.y + 1)Point(location.x + size.w - 2location.y + size.h - 2));
622             if (result.Error()) return result;
623             result = graphics.DrawLine(innerRightBottomPenPoint(location.x + 1location.y + size.h - 2)Point(location.x + size.w - 2location.y + size.h - 2));
624             if (result.Error()) return result;
625             return Result<bool>(true);
626         }
627         internal void SetStatusBar(StatusBar* statusBar_)
628         {
629             statusBar = statusBar_;
630         }
631         [nodiscard]
632         public Result<bool> Invalidate()
633         {
634             if (statusBar != null)
635             {
636                 statusBar->SetChanged();
637                 auto result = statusBar->Invalidate();
638                 if (result.Error()) return result;
639             }
640             return Result<bool>(true);
641         }
642         private StatusBar* statusBar;
643         private Point location;
644         private Size size;
645         private int textWidth;
646         private string text;
647         private BorderStyle borderStyle;
648         private bool spring;
649     }