1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.Screen
 10 {
 11     public enum MessageBoxButtons
 12     {
 13         none = 0ok = 1 << 0cancel = 1 << 1yes = 1 << 2no = 1 << 3
 14     }
 15 
 16     public class MessageBoxCreateParams
 17     {
 18         public nothrow MessageBoxCreateParams() : 
 19             controlCreateParams()
 20         {
 21         }
 22         public nothrow MessageBoxCreateParams& Defaults()
 23         {
 24             return *this;
 25         }
 26         public nothrow MessageBoxCreateParams& Caption(const string& caption_)
 27         {
 28             caption = caption_;
 29             return *this;
 30         }
 31         public nothrow MessageBoxCreateParams& Text(const string& text_)
 32         {
 33             text = text_;
 34             return *this;
 35         }
 36         public nothrow MessageBoxCreateParams& Buttons(MessageBoxButtons buttons_)
 37         {
 38             buttons = buttons_;
 39             return *this;
 40         }
 41         public ControlCreateParams controlCreateParams;
 42         public string caption;
 43         public string text;
 44         public MessageBoxButtons buttons;
 45     }
 46 
 47     public class MessageBox : Window
 48     {
 49         public nothrow MessageBox(MessageBoxCreateParams& createParams) : base(createParams.controlCreateParams)caption(createParams.caption)text(createParams.text)buttons(createParams.buttons)
 50         {
 51             InvalidateGuard guard(thisInvalidateKind.invalidateIfNotDefault);
 52             bool setLoc = false;
 53             if (Location().IsDefault())
 54             {
 55                 SetLocation(Point(00));
 56                 setLoc = true;
 57             }
 58             if (GetSize().IsDefault())
 59             {
 60                 SetSize(Size(404));
 61             }
 62             if (ForeColor() == ConsoleColor.defaultColor)
 63             {
 64                 SetForeColor(ConsoleColor.black);
 65             }
 66             if (BackColor() == ConsoleColor.defaultColor)
 67             {
 68                 SetBackColor(ConsoleColor.cyan);
 69             }
 70             if (buttons == MessageBoxButtons.none)
 71             {
 72                 buttons = MessageBoxButtons.ok;
 73             }
 74             if ((buttons & MessageBoxButtons.ok) != MessageBoxButtons.none)
 75             {
 76                 Button* okButton = Button.OK();
 77                 okButton->SetDefault();
 78                 AddChild(okButton);
 79             }
 80             if ((buttons & MessageBoxButtons.yes) != MessageBoxButtons.none)
 81             {
 82                 Button* yesButton = Button.Yes();
 83                 AddChild(yesButton);
 84             }
 85             if ((buttons & MessageBoxButtons.no) != MessageBoxButtons.none)
 86             {
 87                 Button* noButton = Button.No();
 88                 AddChild(noButton);
 89             }
 90             if ((buttons & MessageBoxButtons.cancel) != MessageBoxButtons.none)
 91             {
 92                 Button* cancelButton = Button.Cancel();
 93                 AddChild(cancelButton);
 94             }
 95             Measure(setLoc);
 96             Control* firstFocusableControl = FirstFocusabledControl();
 97             if (firstFocusableControl != null)
 98             {
 99                 firstFocusableControl->SetFocus();
100             }
101         }
102         public override nothrow Button* DefaultButton() const
103         {
104             Component* child = Controls().FirstChild();
105             while (child != null)
106             {
107                 if (child is Button*)
108                 {
109                     Button* button = cast<Button*>(child);
110                     if (button->IsDefault())
111                     {
112                         return button;
113                     }
114                 }
115                 child = child->NextSibling();
116             }
117             return null;
118         }
119         public override void OnWriteScreen(WriteScreenEventArgs& args)
120         {
121             base->OnWriteScreen(args);
122             Rect rect = GetRect();
123             WriteBox(rectForeColor()BackColor());
124             if (!caption.IsEmpty())
125             {
126                 WriteCaption(u" " + ToUtf32(caption) + u" ");
127             }
128             if (!text.IsEmpty())
129             {
130                 WriteText();
131             }
132             WriteChildren(args);
133         }
134         private void Measure(bool setLoc)
135         {
136             Size sz = GetSize();
137             Rect rect = GetRect();
138             rect.Inflate(11);
139             SetLocation(rect.location);
140             SetSize(rect.size);
141             List<Control*> children;
142             float sw = MeasureChildWidth(sz.wchildren);
143             textLines = SplitIntoLines(ToUtf32(text)sz.w - 4);
144             sz.h = Max(sz.h4 + cast<int>(textLines.Count()));
145             SetSize(sz);
146             if (setLoc)
147             {
148                 int x = Max(cast<int>(0)(TerminalWindowWidth() - sz.w) / 2);
149                 int y = Max(cast<int>(0)(TerminalWindowHeight() - sz.h) / 2);
150                 SetLocation(Point(xy));
151             }
152             SetChildLocations(swsz.h - 1children);
153         }
154         private float MeasureChildWidth(int& widthList<Control*>& children)
155         {
156             Component* child = Controls().FirstChild();
157             while (child != null)
158             {
159                 if (child is Control*)
160                 {
161                     Control* control = cast<Control*>(child);
162                     children.Add(control);
163                 }
164                 child = child->NextSibling();
165             }
166             int w = 0;
167             for (Control* control : children)
168             {
169                 Size sz = control->GetSize();
170                 w = w + sz.w;
171             }
172             if (width < w)
173             {
174                 width = w;
175             }
176             float sw = (cast<float>(width) - cast<float>(w)) / (children.Count() + 1);
177             return sw;
178         }
179         private void SetChildLocations(float swint heightList<Control*>& children)
180         {
181             Point loc = Location();
182             loc.x = loc.x + cast<int>(sw);
183             if (children.Count() > 1)
184             {
185                 loc.x = loc.x + 1;
186             }
187             loc.y = loc.y + height - 1;
188             for (Control* child : children)
189             {
190                 child->SetLocation(loc);
191                 Size sz = child->GetSize();
192                 loc.x = loc.x + sz.w + cast<int>(sw);
193             }
194         }
195         private void WriteCaption(const ustring& captionStr)
196         {
197             Point loc = Location();
198             Size sz = GetSize();
199             int offset = Max(cast<int>(0)cast<int>(sz.w - captionStr.Length()));
200             int x = loc.x + offset / 2;
201             int y = loc.y;
202             SetCursorPos(xy);
203             Terminal.Out() << captionStr;
204         }
205         private void WriteText()
206         {
207             Point loc = Location();
208             Size sz = GetSize();
209             int x = loc.x + 2;
210             int y = loc.y + 1;
211             for (const ustring& line : textLines)
212             {
213                 int offset = Max(cast<int>(0)cast<int>((sz.w - 4 - line.Length()) / 2));
214                 SetCursorPos(x + offsety);
215                 Terminal.Out() << line;
216                 y = y + 1;
217             }
218         }
219         private void WriteChildren(WriteScreenEventArgs& args)
220         {
221             Component* child = Controls().FirstChild();
222             while (child != null)
223             {
224                 if (child is Control*)
225                 {
226                     Control* control = cast<Control*>(child);
227                     control->OnWriteScreen(args);
228                 }
229                 child = child->NextSibling();
230             }
231         }
232         private string caption;
233         private string text;
234         private List<ustring> textLines;
235         private MessageBoxButtons buttons;
236         
237     }
238 }