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 abstract class StatusBarItem : Component
 11     {
 12         public virtual void Measure(Point& locbool afterSpring) {}
 13         public virtual void WriteScreen() {}
 14         public nothrow void SetStatusBar(StatusBar* statusBar_)
 15         {
 16             statusBar = statusBar_;
 17         }
 18         public nothrow StatusBar* GetStatusBar() const
 19         {
 20             return statusBar;
 21         }
 22         private StatusBar* statusBar;
 23     }
 24     
 25     public class StatusBarTextItem : StatusBarItem
 26     {
 27         public StatusBarTextItem(const string& text_) : text(ToUtf32(text_))minWidth(0)
 28         {
 29         }
 30         public nothrow int MinWidth() const
 31         {
 32             return minWidth;
 33         }
 34         public nothrow void SetMinWidth(int minWidth_)
 35         {
 36             minWidth = minWidth_;
 37         }
 38         public void SetText(const string& text_)
 39         {
 40             text = ToUtf32(text_);
 41             StatusBar* statusBar = GetStatusBar();
 42             statusBar->SetChanged();
 43             statusBar->Invalidate();
 44         }
 45         public override void Measure(Point& locbool afterSpring)
 46         {
 47             location = loc;
 48             int width = Max(minWidthcast<int>(text.Length()));
 49             if (afterSpring)
 50             {
 51                 location.x = location.x - width;
 52                 loc = location;
 53                 loc.x = loc.x - 1;
 54             }
 55             else
 56             {
 57                 loc.x = loc.x + width + 1;
 58             }
 59         }
 60         public override void WriteScreen()
 61         {
 62             SetCursorPos(location.xlocation.y);
 63             Terminal.Out() << text;
 64         }
 65         private Point location;
 66         private int minWidth;
 67         private ustring text;
 68     }
 69 
 70     public class StatusBarSpringItem : StatusBarItem
 71     {
 72     }
 73 
 74     public class StatusBarCreateParams
 75     {
 76         public nothrow StatusBarCreateParams() : controlCreateParams()
 77         {
 78         }
 79         public nothrow StatusBarCreateParams& Defaults()
 80         {
 81             return *this;
 82         }
 83         public ControlCreateParams controlCreateParams;
 84     }
 85     
 86     public enum StatusBarFlags
 87     {
 88         none = 0changed = 1 << 0
 89     }
 90     
 91     public class StatusBar : ContainerControl
 92     {
 93         public nothrow StatusBar(StatusBarCreateParams& createParams) : base(createParams.controlCreateParams)
 94         {
 95             InvalidateGuard guard(thisInvalidateKind.dontInvalidate);
 96             if (Location().IsDefault())
 97             {
 98                 SetLocation(Point(0TerminalWindowHeight() - 1));
 99             }
100             if (GetSize().IsDefault())
101             {
102                 SetSize(Size(TerminalWindowWidth()1));
103             }
104             if (ForeColor() == ConsoleColor.defaultColor)
105             {
106                 SetForeColor(ConsoleColor.black);
107             }
108             if (BackColor() == ConsoleColor.defaultColor)
109             {
110                 SetBackColor(ConsoleColor.gray);
111             }
112             SetChanged();
113         }
114         public nothrow bool IsChanged() const
115         {
116             return (flags & StatusBarFlags.changed) != StatusBarFlags.none;
117         }
118         public nothrow void SetChanged()
119         {
120             flags = cast<StatusBarFlags>(flags | StatusBarFlags.changed);
121         }
122         public nothrow void ResetChanged()
123         {
124             flags = cast<StatusBarFlags>(flags & ~StatusBarFlags.changed);
125         }
126         public void AddItem(StatusBarItem* item)
127         {
128             item->SetStatusBar(this);
129             Controls().AddChild(item);
130         }
131         public override void OnWriteScreen(WriteScreenEventArgs& args)
132         {
133             Control* focusedControl = Application.Instance().FocusedControl();
134             base->OnWriteScreen(args);
135             Rect rect = args.GetRect();
136             if (rect.IsDefault())
137             {
138                 rect = GetRect();
139             }
140             Clear(rectForeColor()BackColor());
141             if (IsChanged())
142             {
143                 Measure();
144             }
145             Component* child = Controls().FirstChild();
146             while (child != null)
147             {
148                 if (child is StatusBarItem*)
149                 {
150                     StatusBarItem* item = cast<StatusBarItem*>(child);
151                     item->WriteScreen();
152                 }
153                 child = child->NextSibling();
154             }
155             focusedControl->SetFocus();
156         }
157         private void Measure()
158         {
159             Point loc = Location();
160             loc.x = loc.x + 1;
161             Component* child = Controls().FirstChild();
162             while (child != null)
163             {
164                 if (child is StatusBarSpringItem*)
165                 {
166                     break;
167                 }
168                 else if (child is StatusBarItem*)
169                 {
170                     StatusBarItem* item = cast<StatusBarItem*>(child);
171                     item->Measure(locfalse);
172                 }
173                 child = child->NextSibling();
174             }
175             Size sz = GetSize();
176             loc = Location();
177             loc.x = loc.x + sz.w - 1;
178             child = Controls().LastChild();
179             while (child != null)
180             {
181                 if (child is StatusBarSpringItem*)
182                 {
183                     break;
184                 }
185                 else if (child is StatusBarItem*)
186                 {
187                     StatusBarItem* item = cast<StatusBarItem*>(child);
188                     item->Measure(loctrue);
189                 }
190                 child = child->PrevSibling();
191             }
192         }
193         private StatusBarFlags flags;
194     }
195 }