1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Screen
  9 {
 10     public class ButtonCreateParams
 11     {
 12         public nothrow ButtonCreateParams() : 
 13             controlCreateParams()
 14             text()
 15             highlightColor(ConsoleColor.defaultColor)
 16             disabledColor(ConsoleColor.defaultColor)
 17             focusedItemForeColor(ConsoleColor.defaultColor)
 18             focusedItemBackColor(ConsoleColor.defaultColor)
 19         {
 20         }
 21         public nothrow ButtonCreateParams& Defaults()
 22         {
 23             return *this;
 24         }
 25         public nothrow ButtonCreateParams& Text(const string& text_)
 26         {
 27             text = ToUtf32(text_);
 28             return *this;
 29         }
 30         public nothrow ButtonCreateParams& HighlightColor(ConsoleColor highlightColor_)
 31         {
 32             highlightColor = highlightColor_;
 33             return *this;
 34         }
 35         public nothrow ButtonCreateParams& DisabledColor(ConsoleColor disabledColor_)
 36         {
 37             disabledColor = disabledColor_;
 38             return *this;
 39         }
 40         public nothrow ButtonCreateParams& FocusedItemForeColor(ConsoleColor focusedItemForeColor_)
 41         {
 42             focusedItemForeColor = focusedItemForeColor_;
 43             return *this;
 44         }
 45         public nothrow ButtonCreateParams& FocusedItemBackColor(ConsoleColor focusedItemBackColor_)
 46         {
 47             focusedItemBackColor = focusedItemBackColor_;
 48             return *this;
 49         }
 50         public ControlCreateParams controlCreateParams;
 51         public ustring text;
 52         public ConsoleColor highlightColor;
 53         public ConsoleColor disabledColor;
 54         public ConsoleColor focusedItemForeColor;
 55         public ConsoleColor focusedItemBackColor;
 56     }
 57     
 58     public enum ButtonFlags
 59     {
 60         none = 0defaultButton = 1 << 0
 61     }
 62 
 63     public class Button : Control
 64     {
 65         public nothrow Button(ButtonCreateParams& createParams) : base(createParams.controlCreateParams)flags(ButtonFlags.none)text(createParams.text)
 66         {
 67             InvalidateGuard invalidateGuard(thisInvalidateKind.dontInvalidate);
 68             if (createParams.controlCreateParams.foreColor == ConsoleColor.defaultColor)
 69             {
 70                 SetForeColor(ConsoleColor.black);
 71             }
 72             if (createParams.controlCreateParams.backColor == ConsoleColor.defaultColor)
 73             {
 74                 SetBackColor(ConsoleColor.gray);
 75             }
 76             if (createParams.highlightColor == ConsoleColor.defaultColor)
 77             {
 78                 highlightColor = ConsoleColor.red;
 79             }
 80             else
 81             {
 82                 highlightColor = createParams.highlightColor;
 83             }
 84             if (createParams.disabledColor == ConsoleColor.defaultColor)
 85             {
 86                 disabledColor = ConsoleColor.darkGray;
 87             }
 88             else
 89             {
 90                 disabledColor = createParams.disabledColor;
 91             }
 92             if (createParams.focusedItemForeColor == ConsoleColor.defaultColor)
 93             {
 94                 focusedItemForeColor = cast<ConsoleColor>(defaultFocusedControlForeColor);
 95             }
 96             else
 97             {
 98                 focusedItemForeColor = createParams.focusedItemForeColor;
 99             }
100             if (createParams.focusedItemBackColor == ConsoleColor.defaultColor)
101             {
102                 focusedItemBackColor = cast<ConsoleColor>(defaultFocusedControlBackColor);
103             }
104             else
105             {
106                 focusedItemBackColor = createParams.focusedItemBackColor;
107             }
108             if (GetSize().IsDefault())
109             {
110                 SetSize(Size(Max(cast<int>(10)cast<int>(text.Length() + 2))cast<int>(1)));
111             }
112             SetAccessKey();
113         }
114         public nothrow bool IsDefault() const
115         {
116             return (flags & ButtonFlags.defaultButton) != ButtonFlags.none;
117         }
118         public nothrow void SetDefault()
119         {
120             flags = cast<ButtonFlags>(flags | ButtonFlags.defaultButton);
121         }
122         public nothrow void ResetDefault()
123         {
124             flags = cast<ButtonFlags>(flags & ~ButtonFlags.defaultButton);
125         }
126         public nothrow DialogResult GetDialogResult() const
127         {
128             return dialogResult;
129         }
130         public nothrow void SetDialogResult(DialogResult dialogResult_)
131         {
132             dialogResult = dialogResult_;
133         }
134         public void Press()
135         {
136             if (IsEnabled())
137             {
138                 OnPressed();
139             }
140         }
141         public int TextLength() const
142         {
143             int ampPos = cast<int>(text.Find('&'));
144             if (ampPos != -1)
145             {
146                 return cast<int>(text.Length() - 1);
147             }
148             else
149             {
150                 return cast<int>(text.Length());
151             }
152         }
153         public override void OnWriteScreen(WriteScreenEventArgs& args)
154         {
155             bool isFocused = IsFocused();
156             if (isFocused)
157             {
158                 Terminal.Out() << SetColors(focusedItemForeColorfocusedItemBackColor);
159             }
160             Point location = Location();
161             Size sz = GetSize();
162             Point cursorPos(location.x + (sz.w - TextLength()) / 2location.y);
163             SetControlCursorPos(cursorPos);
164             SetCursorPos(cursorPos.xcursorPos.y);
165             ConsoleColor foreColor = ForeColor();
166             ConsoleColor hiliteColor = highlightColor;
167             if (!isFocused)
168             {
169                 if (IsDisabled())
170                 {
171                     foreColor = disabledColor;
172                     hiliteColor = disabledColor;
173                 }
174                 Terminal.Out() << SetColors(foreColorBackColor());
175             }
176             int ampPos = cast<int>(text.Find('&'));
177             if (ampPos != -1)
178             {
179                 if (!isFocused)
180                 {
181                     Terminal.Out() << SetColors(foreColorBackColor());
182                 }
183                 ustring prefix = text.Substring(0ampPos);
184                 Terminal.Out() << prefix;
185                 ustring highlightStr = text.Substring(ampPos + 11);
186                 if (!isFocused)
187                 {
188                     Terminal.Out() << SetColors(hiliteColorBackColor());
189                 }
190                 Terminal.Out() << highlightStr;
191                 if (!isFocused)
192                 {
193                     Terminal.Out() << SetColors(foreColorBackColor());
194                 }
195                 ustring suffix = text.Substring(ampPos + 2);
196                 Terminal.Out() << suffix;
197             }
198             else
199             {
200                 Terminal.Out() << SetColors(foreColorBackColor());
201                 Terminal.Out() << text;
202             }
203         }
204         public override void OnKeyPressed(KeyEventArgs& args)
205         {
206             if (IsEnabled())
207             {
208                 Window* window = GetWindow();
209                 if (window != null)
210                 {
211                     switch (args.Key())
212                     {
213                         case keyNewline:
214                         case ' ':
215                         {
216                             Press();
217                             args.SetHandled();
218                             break;
219                         }
220                     }
221                 }
222             }
223         }
224         public virtual void OnPressed()
225         {
226             Window* window = GetWindow();
227             if (window != null)
228             {
229                 window->SetDialogResult(dialogResult);
230             }
231             pressedEvent.Fire();
232         }
233         public Event<PressedEventHandler>& PressedEvent()
234         {
235             return pressedEvent;
236         }
237         public nothrow uchar AccessKey() const
238         {
239             return accessKey;
240         }
241         public nothrow void SetAccessKey()
242         {
243             int ampPos = cast<int>(text.Find('&'));
244             if (ampPos != -1 && ampPos < text.Length() - 1)
245             {
246                 accessKey = ToUpper(text[ampPos + 1]);
247             }
248             else
249             {
250                 accessKey = '\0';
251             }
252         }
253         public static Button* OK()
254         {
255             Button* okButton = new Button(ButtonCreateParams().Text("[ O&K ]"));
256             okButton->SetDialogResult(DialogResult.ok);
257             return okButton;
258         }
259         public static Button* Cancel()
260         {
261             Button* cancelButton = new Button(ButtonCreateParams().Text("[ &Cancel ]"));
262             cancelButton->SetDialogResult(DialogResult.cancel);
263             return cancelButton;
264         }
265         public static Button* Yes()
266         {
267             Button* yesButton = new Button(ButtonCreateParams().Text("[ &Yes ]"));
268             yesButton->SetDialogResult(DialogResult.yes);
269             return yesButton;
270         }
271         public static Button* No()
272         {
273             Button* noButton = new Button(ButtonCreateParams().Text("[ &No ]"));
274             noButton->SetDialogResult(dialogResult.no);
275             return noButton;
276         }
277         private ButtonFlags flags;
278         private ustring text;
279         private uchar accessKey;
280         private ConsoleColor highlightColor;
281         private ConsoleColor disabledColor;
282         private ConsoleColor focusedItemForeColor;
283         private ConsoleColor focusedItemBackColor;
284         private DialogResult dialogResult;
285         private Event<PressedEventHandler> pressedEvent;
286     }
287 }