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 enum WindowFlags
 11     {
 12         none = 0mainWindow = 1 << 0showingDialog = 1 << 1
 13     }
 14     
 15     public class ShowDialogGuard
 16     {
 17         public nothrow ShowDialogGuard(Window* window_) : window(window_)
 18         {
 19             window->SetShowingDialog();
 20         }
 21         public ~ShowDialogGuard()
 22         {
 23             window->ResetShowingDialog();
 24         }
 25         private Window* window;
 26     }
 27 
 28     public class Window : ContainerControl
 29     {
 30         public nothrow Window(ControlCreateParams& createParams) : base(createParams)flags(WindowFlags.none)
 31         {
 32         }
 33         public nothrow bool IsMainWindow()
 34         {
 35             return (flags & WindowFlags.mainWindow) != WindowFlags.none;
 36         }
 37         public nothrow void SetMainWindow()
 38         {
 39             flags = cast<WindowFlags>(flags | WindowFlags.mainWindow);
 40         }
 41         public nothrow bool ShowingDialog() const
 42         {
 43             return (flags & WindowFlags.showingDialog) != WindowFlags.none;
 44         }
 45         public nothrow void SetShowingDialog()
 46         {
 47             flags = cast<WindowFlags>(flags | WindowFlags.showingDialog);
 48         }
 49         public nothrow void ResetShowingDialog()
 50         {
 51             flags = cast<WindowFlags>(flags & ~WindowFlags.showingDialog);
 52         }
 53         public virtual nothrow Button* DefaultButton() const
 54         {
 55             return null;
 56         }
 57         public virtual nothrow Button* CancelButton() const
 58         {
 59             Component* child = Controls().FirstChild();
 60             while (child != null)
 61             {
 62                 if (child is Button*)
 63                 {
 64                     Button* button = cast<Button*>(child);
 65                     if (button->GetDialogResult() == DialogResult.cancel)
 66                     {
 67                         return button;
 68                     }
 69                 }
 70                 child = child->NextSibling();
 71             }
 72             return null;
 73         }
 74         public nothrow Control* FirstControl() const
 75         {
 76             Component* child = Controls().FirstChild();
 77             while (child != null)
 78             {
 79                 if (child is Control*)
 80                 {
 81                     return cast<Control*>(child);
 82                 }
 83                 child = child->NextSibling();
 84             }
 85             return null;
 86         }
 87         public nothrow Control* LastControl() const
 88         {
 89             Component* child = Controls().LastChild();
 90             while (child != null)
 91             {
 92                 if (child is Control*)
 93                 {
 94                     return cast<Control*>(child);
 95                 }
 96                 child = child->PrevSibling();
 97             }
 98             return null;
 99         }
100         public nothrow Control* FirstFocusabledControl() const
101         {
102             Control* control = FirstControl();
103             while (control != null)
104             {
105                 if (control->CanFocus())
106                 {
107                     return control;
108                 }
109                 control = control->NextControl();
110             }
111             return null;
112         }
113         public nothrow Control* LastFocusableControl() const
114         {
115             Control* control = LastControl();
116             while (control != null)
117             {
118                 if (control->CanFocus())
119                 {
120                     return control;
121                 }
122                 control = control->PrevControl();
123             }
124             return null;
125         }
126         public DialogResult ShowDialog()
127         {
128             ShowDialogGuard guard(this);
129             dialogResult = DialogResult.none;
130             Application.Instance().RunDialog(this);
131             return dialogResult;
132         }
133         public override void OnKeyPressed(KeyEventArgs& args)
134         {
135             if (ShowingDialog())
136             {
137                 base->OnKeyPressed(args);
138                 if (!args.Handled())
139                 {
140                     switch (args.Key())
141                     {
142                         case keyNewline:
143                         {
144                             Button* defaultButton = DefaultButton();
145                             if (defaultButton != null && defaultButton->IsEnabled())
146                             {
147                                 args.SetHandled();
148                                 defaultButton->Press();
149                             }
150                             break;
151                         }
152                         case keyEscape:
153                         {
154                             Button* cancelButton = CancelButton();
155                             if (cancelButton != null && cancelButton->IsEnabled())
156                             {
157                                 args.SetHandled();
158                                 cancelButton->Press();
159                             }
160                             break;
161                         }
162                         case keyTab:
163                         {
164                             Control* focusedControl = Application.Instance().FocusedControl();
165                             if (focusedControl != null)
166                             {
167                                 Control* nextFocusableControl = focusedControl->NextFocusableControl();
168                                 if (nextFocusableControl == null)
169                                 {
170                                     nextFocusableControl = FirstFocusabledControl();
171                                 }
172                                 if (nextFocusableControl != null)
173                                 {
174                                     nextFocusableControl->SetFocus();
175                                 }
176                             }
177                             break;
178                         }
179                         case keyShiftTab:
180                         {
181                             Control* focusedControl = Application.Instance().FocusedControl();
182                             if (focusedControl != null)
183                             {
184                                 Control* prevFocusableControl = focusedControl->PrevFocusableControl();
185                                 if (prevFocusableControl == null)
186                                 {
187                                     prevFocusableControl = LastFocusableControl();
188                                 }
189                                 if (prevFocusableControl != null)
190                                 {
191                                     prevFocusableControl->SetFocus();
192                                 }
193                             }
194                             break;
195                         }
196                     }
197                     if (!args.Handled())
198                     {
199                         uchar key = ToUpper(args.Key());
200                         Component* child = Controls().FirstChild();
201                         while (child != null)
202                         {
203                             if (child is Button*)
204                             {
205                                 Button* button = cast<Button*>(child);
206                                 if (button->IsEnabled())
207                                 {
208                                     if (button->AccessKey() == key)
209                                     {
210                                         args.SetHandled();
211                                         button->Press();
212                                         return;
213                                     }
214                                 }
215                             }
216                             child = child->NextSibling();
217                         }
218                     }
219                 }
220             }
221         }
222         public override bool HandleWriteScreen(WriteScreenMessage* message)
223         {
224             bool handled = base->HandleWriteScreen(message);
225             if (handled)
226             {
227                 Control* focusedControl = Application.Instance().FocusedControl();
228                 if (focusedControl != null)
229                 {
230                     Point cursorPos = focusedControl->ControlCursorPos();
231                     SetCursorPos(cursorPos.xcursorPos.y);
232                 }
233             }
234             return handled;
235         }
236         public nothrow DialogResult GetDialogResult() const
237         {
238             return dialogResult;
239         }
240         public nothrow void SetDialogResult(DialogResult dialogResult_)
241         {
242             dialogResult = dialogResult_;
243         }
244         private WindowFlags flags;
245         private DialogResult dialogResult;
246     }
247 }