mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-03-03 15:30:27 +00:00
TUI+统计
This commit is contained in:
592
UI/Components.cs
Normal file
592
UI/Components.cs
Normal file
@@ -0,0 +1,592 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CMLeonOS.UI
|
||||
{
|
||||
public delegate void ButtonClickHandler();
|
||||
|
||||
public class Button
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public string Text { get; set; }
|
||||
public ConsoleColor ForegroundColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkBlue;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
public bool IsFocused { get; set; } = false;
|
||||
public ButtonClickHandler OnClick { get; set; }
|
||||
|
||||
public Button(Rect bounds, string text)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public Button(Rect bounds, string text, ConsoleColor foregroundColor, ConsoleColor backgroundColor, ConsoleColor borderColor)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Text = text;
|
||||
ForegroundColor = foregroundColor;
|
||||
BackgroundColor = backgroundColor;
|
||||
BorderColor = borderColor;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
if (!IsEnabled)
|
||||
{
|
||||
TUIHelper.SetColors(ConsoleColor.DarkGray, ConsoleColor.Black);
|
||||
TUIHelper.DrawBox(Bounds, Text, ConsoleColor.DarkGray);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsFocused)
|
||||
{
|
||||
TUIHelper.SetColors(ForegroundColor, BackgroundColor);
|
||||
TUIHelper.DrawBox(Bounds, Text, BorderColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TUIHelper.SetColors(ConsoleColor.Gray, ConsoleColor.Black);
|
||||
TUIHelper.DrawBox(Bounds, Text, ConsoleColor.DarkGray);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HandleKey(ConsoleKeyInfo key)
|
||||
{
|
||||
if (!IsEnabled) return false;
|
||||
|
||||
if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Spacebar)
|
||||
{
|
||||
OnClick?.Invoke();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class InputBox
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Value { get; set; } = string.Empty;
|
||||
public string Placeholder { get; set; } = string.Empty;
|
||||
public int MaxLength { get; set; } = 50;
|
||||
public bool IsPassword { get; set; } = false;
|
||||
public bool IsFocused { get; set; } = false;
|
||||
public ConsoleColor ForegroundColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.Black;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
|
||||
public InputBox(Rect bounds, string label, string placeholder, int maxLength, bool isPassword, ConsoleColor foregroundColor, ConsoleColor backgroundColor, ConsoleColor borderColor)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Label = label;
|
||||
Placeholder = placeholder;
|
||||
MaxLength = maxLength;
|
||||
IsPassword = isPassword;
|
||||
ForegroundColor = foregroundColor;
|
||||
BackgroundColor = backgroundColor;
|
||||
BorderColor = borderColor;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
TUIHelper.SetColors(ForegroundColor, BackgroundColor);
|
||||
TUIHelper.DrawBox(Bounds, Label, BorderColor);
|
||||
|
||||
int inputY = Bounds.Top + 1;
|
||||
string displayValue = IsPassword ? new string('*', Value.Length) : Value;
|
||||
string displayText = string.IsNullOrEmpty(Value) ? Placeholder : displayValue;
|
||||
|
||||
Console.SetCursorPosition(Bounds.Left + 1, inputY);
|
||||
Console.Write(TUIHelper.PadText(displayText, Bounds.Width - 2));
|
||||
|
||||
if (IsFocused)
|
||||
{
|
||||
TUIHelper.SaveCursor();
|
||||
Console.SetCursorPosition(Bounds.Left + 1 + displayText.Length, inputY);
|
||||
TUIHelper.ShowCursor();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HandleKey(ConsoleKeyInfo key)
|
||||
{
|
||||
if (!IsFocused) return false;
|
||||
|
||||
if (key.Key == ConsoleKey.Backspace)
|
||||
{
|
||||
if (Value.Length > 0)
|
||||
{
|
||||
Value = Value.Substring(0, Value.Length - 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (char.IsLetterOrDigit(key.KeyChar))
|
||||
{
|
||||
if (Value.Length < MaxLength)
|
||||
{
|
||||
Value += key.KeyChar;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class Dialog
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Message { get; set; }
|
||||
public List<Button> Buttons { get; set; } = new List<Button>();
|
||||
public int SelectedButtonIndex { get; set; } = 0;
|
||||
public ConsoleColor TitleColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor MessageColor { get; set; } = ConsoleColor.Gray;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkBlue;
|
||||
|
||||
public Dialog(Rect bounds, string title, string message)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public Dialog(Rect bounds, string title, string message, List<Button> buttons)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
Message = message;
|
||||
Buttons = buttons;
|
||||
}
|
||||
|
||||
public Dialog(Rect bounds, string title, string message, List<Button> buttons, int selectedIndex)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
Message = message;
|
||||
Buttons = buttons;
|
||||
SelectedButtonIndex = selectedIndex;
|
||||
|
||||
for (int i = 0; i < Buttons.Count; i++)
|
||||
{
|
||||
Buttons[i].IsFocused = (i == SelectedButtonIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public Dialog(Rect bounds, string title, string message, List<Button> buttons, int selectedIndex, ConsoleColor titleColor, ConsoleColor messageColor, ConsoleColor borderColor)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
Message = message;
|
||||
Buttons = buttons;
|
||||
SelectedButtonIndex = selectedIndex;
|
||||
TitleColor = titleColor;
|
||||
MessageColor = messageColor;
|
||||
BorderColor = borderColor;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
TUIHelper.SetColors(TitleColor, BackgroundColor);
|
||||
TUIHelper.DrawBox(Bounds, Title, BorderColor);
|
||||
|
||||
int messageY = Bounds.Top + 2;
|
||||
TUIHelper.SetColors(MessageColor, BackgroundColor);
|
||||
Console.SetCursorPosition(Bounds.Left + 1, messageY);
|
||||
Console.Write(TUIHelper.TruncateText(Message, Bounds.Width - 2));
|
||||
|
||||
int buttonY = Bounds.Bottom - 2;
|
||||
int buttonWidth = Bounds.Width / Buttons.Count;
|
||||
int buttonX = Bounds.Left + 1;
|
||||
|
||||
for (int i = 0; i < Buttons.Count; i++)
|
||||
{
|
||||
Buttons[i].IsFocused = (i == SelectedButtonIndex);
|
||||
Buttons[i].Bounds = new Rect(buttonX, buttonY, buttonWidth - 2, 3);
|
||||
Buttons[i].Render();
|
||||
buttonX += buttonWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HandleKey(ConsoleKeyInfo key)
|
||||
{
|
||||
if (key.Key == ConsoleKey.LeftArrow)
|
||||
{
|
||||
Buttons[SelectedButtonIndex].IsFocused = false;
|
||||
SelectedButtonIndex = (SelectedButtonIndex - 1 + Buttons.Count) % Buttons.Count;
|
||||
Buttons[SelectedButtonIndex].IsFocused = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.Key == ConsoleKey.RightArrow)
|
||||
{
|
||||
Buttons[SelectedButtonIndex].IsFocused = false;
|
||||
SelectedButtonIndex = (SelectedButtonIndex + 1) % Buttons.Count;
|
||||
Buttons[SelectedButtonIndex].IsFocused = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
{
|
||||
if (SelectedButtonIndex >= 0 && SelectedButtonIndex < Buttons.Count)
|
||||
{
|
||||
Buttons[SelectedButtonIndex].OnClick?.Invoke();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class Menu
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public List<MenuItem> Items { get; set; } = new List<MenuItem>();
|
||||
public int SelectedIndex { get; set; } = 0;
|
||||
public int ScrollOffset { get; set; } = 0;
|
||||
public ConsoleColor SelectedColor { get; set; } = ConsoleColor.Yellow;
|
||||
public ConsoleColor NormalColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkBlue;
|
||||
|
||||
public Menu(Rect bounds)
|
||||
{
|
||||
Bounds = bounds;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
TUIHelper.DrawBox(Bounds, string.Empty, BorderColor);
|
||||
|
||||
int startY = Bounds.Top + 1;
|
||||
int maxHeight = Bounds.Height - 2;
|
||||
|
||||
for (int i = ScrollOffset; i < Items.Count && i < ScrollOffset + maxHeight; i++)
|
||||
{
|
||||
int y = startY + (i - ScrollOffset);
|
||||
ConsoleColor color = (i == SelectedIndex) ? SelectedColor : NormalColor;
|
||||
string prefix = (i == SelectedIndex) ? "> " : " ";
|
||||
|
||||
TUIHelper.SetColors(color, BackgroundColor);
|
||||
Console.SetCursorPosition(Bounds.Left + 1, y);
|
||||
Console.Write(prefix + TUIHelper.TruncateText(Items[i].Text, Bounds.Width - 3));
|
||||
}
|
||||
|
||||
if (Items.Count > maxHeight)
|
||||
{
|
||||
int scrollY = Bounds.Bottom - 1;
|
||||
TUIHelper.SetColors(ConsoleColor.Gray, BackgroundColor);
|
||||
Console.SetCursorPosition(Bounds.Right - 5, scrollY);
|
||||
Console.Write($"({ScrollOffset + 1}/{(int)Math.Ceiling((double)Items.Count / maxHeight)})");
|
||||
}
|
||||
}
|
||||
|
||||
public bool HandleKey(ConsoleKeyInfo key)
|
||||
{
|
||||
if (key.Key == ConsoleKey.UpArrow || key.Key == ConsoleKey.PageUp)
|
||||
{
|
||||
SelectedIndex = (SelectedIndex - 1 + Items.Count) % Items.Count;
|
||||
if (SelectedIndex < ScrollOffset) ScrollOffset = SelectedIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.Key == ConsoleKey.DownArrow || key.Key == ConsoleKey.PageDown)
|
||||
{
|
||||
SelectedIndex = (SelectedIndex + 1) % Items.Count;
|
||||
int maxScroll = Items.Count - (Bounds.Height - 2);
|
||||
if (SelectedIndex >= ScrollOffset + (Bounds.Height - 2))
|
||||
{
|
||||
ScrollOffset = SelectedIndex - (Bounds.Height - 3);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.Key == ConsoleKey.Enter)
|
||||
{
|
||||
if (SelectedIndex >= 0 && SelectedIndex < Items.Count)
|
||||
{
|
||||
Items[SelectedIndex].OnSelect?.Invoke();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class MenuItem
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public Action OnSelect { get; set; }
|
||||
|
||||
public MenuItem(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public MenuItem(string text, Action onSelect)
|
||||
{
|
||||
Text = text;
|
||||
OnSelect = onSelect;
|
||||
}
|
||||
}
|
||||
|
||||
public class Label
|
||||
{
|
||||
public Point Position { get; set; }
|
||||
public string Text { get; set; }
|
||||
public ConsoleColor ForegroundColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor? BackgroundColor { get; set; } = null;
|
||||
|
||||
public Label(Point position, string text)
|
||||
{
|
||||
Position = position;
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
if (BackgroundColor != null)
|
||||
{
|
||||
TUIHelper.SetColors(ForegroundColor, BackgroundColor.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
TUIHelper.SetColors(ForegroundColor, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
Console.SetCursorPosition(Position.X, Position.Y);
|
||||
Console.Write(Text);
|
||||
TUIHelper.ResetColors();
|
||||
}
|
||||
}
|
||||
|
||||
public class ProgressBar
|
||||
{
|
||||
public Point Position { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Value { get; set; }
|
||||
public int MaxValue { get; set; }
|
||||
public ConsoleColor FillColor { get; set; } = ConsoleColor.DarkGreen;
|
||||
public ConsoleColor EmptyColor { get; set; } = ConsoleColor.DarkGray;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.Black;
|
||||
public bool ShowPercentage { get; set; } = true;
|
||||
|
||||
public ProgressBar(Point position, int width, int maxValue)
|
||||
{
|
||||
Position = position;
|
||||
Width = width;
|
||||
MaxValue = maxValue;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
int fillWidth = (int)((double)Value / MaxValue * Width);
|
||||
int emptyWidth = Width - fillWidth;
|
||||
|
||||
TUIHelper.SetColors(FillColor, BackgroundColor);
|
||||
Console.SetCursorPosition(Position.X, Position.Y);
|
||||
Console.Write('[');
|
||||
|
||||
for (int i = 0; i < fillWidth; i++)
|
||||
{
|
||||
Console.Write('#');
|
||||
}
|
||||
|
||||
TUIHelper.SetColors(EmptyColor, BackgroundColor);
|
||||
for (int i = 0; i < emptyWidth; i++)
|
||||
{
|
||||
Console.Write('-');
|
||||
}
|
||||
|
||||
TUIHelper.SetColors(BorderColor, BackgroundColor);
|
||||
Console.Write(']');
|
||||
|
||||
if (ShowPercentage)
|
||||
{
|
||||
string percentage = ((double)Value / MaxValue * 100).ToString("F0") + "%";
|
||||
TUIHelper.SetColors(ConsoleColor.White, BackgroundColor);
|
||||
Console.Write($" {percentage}");
|
||||
}
|
||||
|
||||
TUIHelper.ResetColors();
|
||||
}
|
||||
|
||||
public void SetValue(int value)
|
||||
{
|
||||
Value = Math.Max(0, Math.Min(value, MaxValue));
|
||||
}
|
||||
}
|
||||
|
||||
public class TabControl
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public List<TabPage> Pages { get; set; } = new List<TabPage>();
|
||||
public int SelectedIndex { get; set; } = 0;
|
||||
public ConsoleColor SelectedColor { get; set; } = ConsoleColor.Yellow;
|
||||
public ConsoleColor NormalColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkBlue;
|
||||
|
||||
public TabControl(Rect bounds)
|
||||
{
|
||||
Bounds = bounds;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
TUIHelper.DrawBox(Bounds, string.Empty, BorderColor);
|
||||
|
||||
int tabWidth = Bounds.Width / Pages.Count;
|
||||
int tabX = Bounds.Left + 1;
|
||||
|
||||
for (int i = 0; i < Pages.Count; i++)
|
||||
{
|
||||
string prefix = (i == SelectedIndex) ? "[" : " ";
|
||||
string suffix = (i == SelectedIndex) ? "]" : " ";
|
||||
|
||||
TUIHelper.SetColors((i == SelectedIndex) ? SelectedColor : NormalColor, BackgroundColor);
|
||||
Console.SetCursorPosition(tabX, Bounds.Top);
|
||||
Console.Write(prefix + Pages[i].Title + suffix);
|
||||
|
||||
tabX += tabWidth;
|
||||
}
|
||||
|
||||
TUIHelper.SetColors(ConsoleColor.Gray, BackgroundColor);
|
||||
Console.SetCursorPosition(Bounds.Left + 1, Bounds.Bottom - 1);
|
||||
Console.Write(new string(' ', Bounds.Width - 2));
|
||||
|
||||
Pages[SelectedIndex].Render();
|
||||
}
|
||||
|
||||
public bool HandleKey(ConsoleKeyInfo key)
|
||||
{
|
||||
if (key.Key == ConsoleKey.LeftArrow)
|
||||
{
|
||||
SelectedIndex = (SelectedIndex - 1 + Pages.Count) % Pages.Count;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key.Key == ConsoleKey.RightArrow)
|
||||
{
|
||||
SelectedIndex = (SelectedIndex + 1) % Pages.Count;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class TabPage
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public string Title { get; set; }
|
||||
public Action Render { get; set; }
|
||||
|
||||
public TabPage(Rect bounds, string title, Action render)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
Render = render;
|
||||
}
|
||||
}
|
||||
|
||||
public class StatusBar
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public List<StatusBarItem> Items { get; set; } = new List<StatusBarItem>();
|
||||
public ConsoleColor ForegroundColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkBlue;
|
||||
|
||||
public StatusBar(Rect bounds)
|
||||
{
|
||||
Bounds = bounds;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
TUIHelper.SetColors(ForegroundColor, BackgroundColor);
|
||||
TUIHelper.DrawHorizontalLine(Bounds.Left, Bounds.Top, Bounds.Width, '-', null);
|
||||
|
||||
int x = Bounds.Left + 1;
|
||||
foreach (var item in Items)
|
||||
{
|
||||
TUIHelper.SetColors(item.Color, BackgroundColor);
|
||||
Console.SetCursorPosition(x, Bounds.Top);
|
||||
Console.Write(item.Text);
|
||||
x += item.Text.Length + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class StatusBarItem
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public ConsoleColor Color { get; set; } = ConsoleColor.White;
|
||||
|
||||
public StatusBarItem(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public StatusBarItem(string text, ConsoleColor color)
|
||||
{
|
||||
Text = text;
|
||||
Color = color;
|
||||
}
|
||||
}
|
||||
|
||||
public class Window
|
||||
{
|
||||
public Rect Bounds { get; set; }
|
||||
public string Title { get; set; }
|
||||
public Action RenderContent { get; set; }
|
||||
public bool HasBorder { get; set; } = true;
|
||||
public ConsoleColor TitleColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
|
||||
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkBlue;
|
||||
|
||||
public Window(Rect bounds, string title, Action renderContent)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
RenderContent = renderContent;
|
||||
}
|
||||
|
||||
public Window(Rect bounds, string title, Action renderContent, bool hasBorder)
|
||||
{
|
||||
Bounds = bounds;
|
||||
Title = title;
|
||||
RenderContent = renderContent;
|
||||
HasBorder = hasBorder;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
TUIHelper.SetColors(TitleColor, BackgroundColor);
|
||||
|
||||
if (HasBorder)
|
||||
{
|
||||
TUIHelper.DrawBox(Bounds, Title, BorderColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
TUIHelper.DrawHorizontalLine(Bounds.Left, Bounds.Top, Bounds.Width, '-', null);
|
||||
}
|
||||
|
||||
RenderContent?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
289
UI/TUI.cs
Normal file
289
UI/TUI.cs
Normal file
@@ -0,0 +1,289 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CMLeonOS.UI
|
||||
{
|
||||
public struct Point
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
|
||||
public Point(int x, int y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public static Point operator +(Point a, Point b)
|
||||
{
|
||||
return new Point(a.X + b.X, a.Y + b.Y);
|
||||
}
|
||||
|
||||
public static Point operator -(Point a, Point b)
|
||||
{
|
||||
return new Point(a.X - b.X, a.Y - b.Y);
|
||||
}
|
||||
}
|
||||
|
||||
public struct Size
|
||||
{
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
|
||||
public Size(int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Rect
|
||||
{
|
||||
public Point Position { get; set; }
|
||||
public Size Size { get; set; }
|
||||
|
||||
public Rect(Point position, Size size)
|
||||
{
|
||||
Position = position;
|
||||
Size = size;
|
||||
}
|
||||
|
||||
public Rect(int x, int y, int width, int height)
|
||||
{
|
||||
Position = new Point(x, y);
|
||||
Size = new Size(width, height);
|
||||
}
|
||||
|
||||
public int Left => Position.X;
|
||||
public int Top => Position.Y;
|
||||
public int Right => Position.X + Size.Width;
|
||||
public int Bottom => Position.Y + Size.Height;
|
||||
public int Width => Size.Width;
|
||||
public int Height => Size.Height;
|
||||
|
||||
public bool Contains(Point point)
|
||||
{
|
||||
return point.X >= Left && point.X < Right && point.Y >= Top && point.Y < Bottom;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConsoleColorEx
|
||||
{
|
||||
Black = ConsoleColor.Black,
|
||||
DarkBlue = ConsoleColor.DarkBlue,
|
||||
DarkGreen = ConsoleColor.DarkGreen,
|
||||
DarkCyan = ConsoleColor.DarkCyan,
|
||||
DarkRed = ConsoleColor.DarkRed,
|
||||
DarkMagenta = ConsoleColor.DarkMagenta,
|
||||
DarkYellow = ConsoleColor.DarkYellow,
|
||||
Gray = ConsoleColor.Gray,
|
||||
DarkGray = ConsoleColor.DarkGray,
|
||||
Blue = ConsoleColor.Blue,
|
||||
Green = ConsoleColor.Green,
|
||||
Cyan = ConsoleColor.Cyan,
|
||||
Red = ConsoleColor.Red,
|
||||
Magenta = ConsoleColor.Magenta,
|
||||
Yellow = ConsoleColor.Yellow,
|
||||
White = ConsoleColor.White
|
||||
}
|
||||
|
||||
public static class TUIHelper
|
||||
{
|
||||
public static int ConsoleWidth => 80;
|
||||
public static int ConsoleHeight => 25;
|
||||
|
||||
public static void SetColors(ConsoleColor foreground, ConsoleColor background)
|
||||
{
|
||||
Console.ForegroundColor = foreground;
|
||||
Console.BackgroundColor = background;
|
||||
}
|
||||
|
||||
public static void ResetColors()
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
}
|
||||
|
||||
public static void DrawBox(Rect rect, char horizontal = '-', char vertical = '|', char corner = '+', ConsoleColor? borderColor = null)
|
||||
{
|
||||
if (borderColor != null)
|
||||
{
|
||||
SetColors(borderColor.Value, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
for (int y = rect.Top; y < rect.Bottom; y++)
|
||||
{
|
||||
Console.SetCursorPosition(rect.Left, y);
|
||||
|
||||
if (y == rect.Top || y == rect.Bottom - 1)
|
||||
{
|
||||
Console.Write(corner);
|
||||
for (int x = rect.Left + 1; x < rect.Right - 1; x++)
|
||||
{
|
||||
Console.Write(horizontal);
|
||||
}
|
||||
Console.Write(corner);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write(vertical);
|
||||
for (int x = rect.Left + 1; x < rect.Right - 1; x++)
|
||||
{
|
||||
Console.Write(' ');
|
||||
}
|
||||
Console.Write(vertical);
|
||||
}
|
||||
}
|
||||
|
||||
ResetColors();
|
||||
}
|
||||
|
||||
public static void DrawBox(Rect rect, string title, ConsoleColor? borderColor = null)
|
||||
{
|
||||
if (borderColor != null)
|
||||
{
|
||||
SetColors(borderColor.Value, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
char horizontal = '-';
|
||||
char vertical = '|';
|
||||
char corner = '+';
|
||||
|
||||
for (int y = rect.Top; y < rect.Bottom; y++)
|
||||
{
|
||||
Console.SetCursorPosition(rect.Left, y);
|
||||
|
||||
if (y == rect.Top)
|
||||
{
|
||||
Console.Write(corner);
|
||||
for (int x = rect.Left + 1; x < rect.Right - 1; x++)
|
||||
{
|
||||
Console.Write(horizontal);
|
||||
}
|
||||
Console.Write(corner);
|
||||
}
|
||||
else if (y == rect.Bottom - 1)
|
||||
{
|
||||
Console.Write(corner);
|
||||
for (int x = rect.Left + 1; x < rect.Right - 1; x++)
|
||||
{
|
||||
Console.Write(horizontal);
|
||||
}
|
||||
Console.Write(corner);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write(vertical);
|
||||
for (int x = rect.Left + 1; x < rect.Right - 1; x++)
|
||||
{
|
||||
Console.Write(' ');
|
||||
}
|
||||
Console.Write(vertical);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(title))
|
||||
{
|
||||
int titleX = rect.Left + (rect.Width - title.Length) / 2;
|
||||
Console.SetCursorPosition(titleX, rect.Top);
|
||||
Console.Write(title);
|
||||
}
|
||||
|
||||
ResetColors();
|
||||
}
|
||||
|
||||
public static void DrawText(Point position, string text, ConsoleColor? color = null)
|
||||
{
|
||||
if (color != null)
|
||||
{
|
||||
SetColors(color.Value, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
Console.SetCursorPosition(position.X, position.Y);
|
||||
Console.Write(text);
|
||||
ResetColors();
|
||||
}
|
||||
|
||||
public static void DrawCenteredText(int y, string text, ConsoleColor? color = null)
|
||||
{
|
||||
if (color != null)
|
||||
{
|
||||
SetColors(color.Value, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
int x = (ConsoleWidth - text.Length) / 2;
|
||||
Console.SetCursorPosition(x, y);
|
||||
Console.Write(text);
|
||||
ResetColors();
|
||||
}
|
||||
|
||||
public static void DrawHorizontalLine(int x, int y, int width, char c = '-', ConsoleColor? color = null)
|
||||
{
|
||||
if (color != null)
|
||||
{
|
||||
SetColors(color.Value, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
Console.SetCursorPosition(x, y);
|
||||
Console.Write(new string(c, width));
|
||||
ResetColors();
|
||||
}
|
||||
|
||||
public static void DrawVerticalLine(int x, int y, int height, char c = '|', ConsoleColor? color = null)
|
||||
{
|
||||
if (color != null)
|
||||
{
|
||||
SetColors(color.Value, ConsoleColor.Black);
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
Console.SetCursorPosition(x, y + i);
|
||||
Console.Write(c);
|
||||
}
|
||||
ResetColors();
|
||||
}
|
||||
|
||||
public static void ClearArea(Rect rect)
|
||||
{
|
||||
for (int y = rect.Top; y < rect.Bottom; y++)
|
||||
{
|
||||
Console.SetCursorPosition(rect.Left, y);
|
||||
Console.Write(new string(' ', rect.Width));
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveCursor()
|
||||
{
|
||||
Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop);
|
||||
}
|
||||
|
||||
public static void HideCursor()
|
||||
{
|
||||
Console.CursorVisible = false;
|
||||
}
|
||||
|
||||
public static void ShowCursor()
|
||||
{
|
||||
Console.CursorVisible = true;
|
||||
}
|
||||
|
||||
public static string TruncateText(string text, int maxLength)
|
||||
{
|
||||
if (text.Length <= maxLength)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
return text.Substring(0, maxLength - 3) + "...";
|
||||
}
|
||||
|
||||
public static string PadText(string text, int totalWidth, char padChar = ' ')
|
||||
{
|
||||
if (text.Length >= totalWidth)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
return text + new string(padChar, totalWidth - text.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
332
UI/TUIDemo.cs
Normal file
332
UI/TUIDemo.cs
Normal file
@@ -0,0 +1,332 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using CMLeonOS.UI;
|
||||
|
||||
namespace CMLeonOS.UI.Examples
|
||||
{
|
||||
public static class TUIDemo
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
Console.Clear();
|
||||
Console.Title = "CMLeonOS TUI Library Demo";
|
||||
|
||||
bool running = true;
|
||||
while (running)
|
||||
{
|
||||
ShowMainMenu();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowMainMenu()
|
||||
{
|
||||
Console.Clear();
|
||||
|
||||
var menu = new Menu(new Rect(5, 5, 70, 15));
|
||||
menu.Items.Add(new MenuItem("Button Demo", () => ShowButtonDemo()));
|
||||
menu.Items.Add(new MenuItem("Input Box Demo", () => ShowInputBoxDemo()));
|
||||
menu.Items.Add(new MenuItem("Dialog Demo", () => ShowDialogDemo()));
|
||||
menu.Items.Add(new MenuItem("Progress Bar Demo", () => ShowProgressBarDemo()));
|
||||
menu.Items.Add(new MenuItem("Tab Control Demo", () => ShowTabControlDemo()));
|
||||
menu.Items.Add(new MenuItem("Exit", () => Environment.Exit(0)));
|
||||
|
||||
menu.Render();
|
||||
|
||||
bool menuRunning = true;
|
||||
while (menuRunning)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
if (menu.HandleKey(key))
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
else if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
menuRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowButtonDemo()
|
||||
{
|
||||
Console.Clear();
|
||||
|
||||
var titleBar = new Window(new Rect(0, 0, 80, 3), "Button Demo", () =>
|
||||
{
|
||||
Console.Clear();
|
||||
ShowMainMenu();
|
||||
}, false);
|
||||
titleBar.Render();
|
||||
|
||||
var button1 = new Button(new Rect(10, 8, 20, 3), "Click Me!", ConsoleColor.Cyan, ConsoleColor.DarkBlue, ConsoleColor.White);
|
||||
var button2 = new Button(new Rect(35, 8, 20, 3), "Disabled", ConsoleColor.Gray, ConsoleColor.Black, ConsoleColor.DarkGray);
|
||||
button2.IsEnabled = false;
|
||||
var button3 = new Button(new Rect(60, 8, 20, 3), "Hover Me", ConsoleColor.Yellow, ConsoleColor.DarkRed, ConsoleColor.White);
|
||||
|
||||
button1.Render();
|
||||
button2.Render();
|
||||
button3.Render();
|
||||
|
||||
var label = new Label(new Point(10, 13), "Button Component Examples:");
|
||||
label.Render();
|
||||
|
||||
var statusBar = new StatusBar(new Rect(0, 24, 80, 1));
|
||||
statusBar.Items.Add(new StatusBarItem("Press ENTER to click, ESC to return"));
|
||||
statusBar.Render();
|
||||
|
||||
int focusedButton = 0;
|
||||
button1.IsFocused = true;
|
||||
|
||||
bool demoRunning = true;
|
||||
while (demoRunning)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
|
||||
if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
demoRunning = false;
|
||||
}
|
||||
else if (key.Key == ConsoleKey.Enter)
|
||||
{
|
||||
if (focusedButton == 0 && button1.IsEnabled)
|
||||
{
|
||||
Console.SetCursorPosition(10, 14);
|
||||
Console.Write("Clicked!");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
else if (key.Key == ConsoleKey.LeftArrow)
|
||||
{
|
||||
button1.IsFocused = false;
|
||||
button3.IsFocused = false;
|
||||
focusedButton = (focusedButton - 1 + 3) % 3;
|
||||
|
||||
if (focusedButton == 0 && button1.IsEnabled) button1.IsFocused = true;
|
||||
if (focusedButton == 2 && button2.IsEnabled) button2.IsFocused = true;
|
||||
if (focusedButton == 1 && button3.IsEnabled) button3.IsFocused = true;
|
||||
}
|
||||
else if (key.Key == ConsoleKey.RightArrow)
|
||||
{
|
||||
button1.IsFocused = false;
|
||||
button3.IsFocused = false;
|
||||
focusedButton = (focusedButton + 1) % 3;
|
||||
|
||||
if (focusedButton == 0 && button1.IsEnabled) button1.IsFocused = true;
|
||||
if (focusedButton == 2 && button2.IsEnabled) button2.IsFocused = true;
|
||||
if (focusedButton == 1 && button3.IsEnabled) button3.IsFocused = true;
|
||||
}
|
||||
|
||||
button1.Render();
|
||||
button2.Render();
|
||||
button3.Render();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowInputBoxDemo()
|
||||
{
|
||||
Console.Clear();
|
||||
|
||||
var titleBar = new Window(new Rect(0, 0, 80, 3), "Input Box Demo", () =>
|
||||
{
|
||||
Console.Clear();
|
||||
ShowMainMenu();
|
||||
}, false);
|
||||
titleBar.Render();
|
||||
|
||||
var inputBox = new InputBox(new Rect(20, 8, 40, 3), "Enter your name:", "John Doe", 20, false, ConsoleColor.White, ConsoleColor.Black, ConsoleColor.White);
|
||||
inputBox.MaxLength = 20;
|
||||
|
||||
var button = new Button(new Rect(65, 8, 15, 3), "Submit");
|
||||
button.OnClick = () =>
|
||||
{
|
||||
Console.SetCursorPosition(20, 12);
|
||||
Console.Write($"Submitted: {inputBox.Value}");
|
||||
Thread.Sleep(2000);
|
||||
};
|
||||
|
||||
inputBox.Render();
|
||||
button.Render();
|
||||
|
||||
var statusBar = new StatusBar(new Rect(0, 24, 80, 1));
|
||||
statusBar.Items.Add(new StatusBarItem("Press ENTER to submit, ESC to return"));
|
||||
statusBar.Render();
|
||||
|
||||
bool demoRunning = true;
|
||||
while (demoRunning)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
|
||||
if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
demoRunning = false;
|
||||
}
|
||||
else if (inputBox.HandleKey(key))
|
||||
{
|
||||
inputBox.Render();
|
||||
}
|
||||
else if (button.HandleKey(key))
|
||||
{
|
||||
button.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowDialogDemo()
|
||||
{
|
||||
Console.Clear();
|
||||
|
||||
var titleBar = new Window(new Rect(0, 0, 80, 3), "Dialog Demo", () =>
|
||||
{
|
||||
Console.Clear();
|
||||
ShowMainMenu();
|
||||
}, false);
|
||||
titleBar.Render();
|
||||
|
||||
var dialog = new Dialog(new Rect(15, 5, 50, 7), "Confirm Action", "Are you sure you want to proceed?");
|
||||
|
||||
dialog.Buttons.Add(new Button(new Rect(17, 14, 12, 3), "Yes", ConsoleColor.White, ConsoleColor.DarkGreen, ConsoleColor.White));
|
||||
dialog.Buttons[0].OnClick = () =>
|
||||
{
|
||||
Console.SetCursorPosition(15, 13);
|
||||
Console.Write("Confirmed!");
|
||||
Thread.Sleep(1500);
|
||||
};
|
||||
|
||||
dialog.Buttons.Add(new Button(new Rect(31, 14, 12, 3), "No", ConsoleColor.White, ConsoleColor.DarkRed, ConsoleColor.White));
|
||||
dialog.Buttons[1].OnClick = () =>
|
||||
{
|
||||
Console.SetCursorPosition(31, 13);
|
||||
Console.Write("Cancelled!");
|
||||
Thread.Sleep(1500);
|
||||
};
|
||||
|
||||
dialog.Render();
|
||||
|
||||
var statusBar = new StatusBar(new Rect(0, 24, 80, 1));
|
||||
statusBar.Items.Add(new StatusBarItem("Use LEFT/RIGHT to select, ENTER to choose"));
|
||||
statusBar.Render();
|
||||
|
||||
bool demoRunning = true;
|
||||
while (demoRunning)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
|
||||
if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
demoRunning = false;
|
||||
}
|
||||
else if (dialog.HandleKey(key))
|
||||
{
|
||||
dialog.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowProgressBarDemo()
|
||||
{
|
||||
Console.Clear();
|
||||
|
||||
var titleBar = new Window(new Rect(0, 0, 80, 3), "Progress Bar Demo", () =>
|
||||
{
|
||||
Console.Clear();
|
||||
ShowMainMenu();
|
||||
}, false);
|
||||
titleBar.Render();
|
||||
|
||||
var progressBar = new ProgressBar(new Point(15, 10), 50, 100);
|
||||
progressBar.Value = 0;
|
||||
|
||||
var button = new Button(new Rect(35, 13, 15, 3), "Start");
|
||||
button.OnClick = () =>
|
||||
{
|
||||
for (int i = 0; i <= 100; i++)
|
||||
{
|
||||
progressBar.SetValue(i);
|
||||
progressBar.Render();
|
||||
Thread.Sleep(30);
|
||||
}
|
||||
};
|
||||
|
||||
progressBar.Render();
|
||||
button.Render();
|
||||
|
||||
var statusBar = new StatusBar(new Rect(0, 24, 80, 1));
|
||||
statusBar.Items.Add(new StatusBarItem("Press ENTER to start, ESC to return"));
|
||||
statusBar.Render();
|
||||
|
||||
bool demoRunning = true;
|
||||
while (demoRunning)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
|
||||
if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
demoRunning = false;
|
||||
}
|
||||
else if (button.HandleKey(key))
|
||||
{
|
||||
button.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowTabControlDemo()
|
||||
{
|
||||
Console.Clear();
|
||||
|
||||
var titleBar = new Window(new Rect(0, 0, 80, 3), "Tab Control Demo", () =>
|
||||
{
|
||||
Console.Clear();
|
||||
ShowMainMenu();
|
||||
}, false);
|
||||
titleBar.Render();
|
||||
|
||||
var tabControl = new TabControl(new Rect(5, 5, 70, 15));
|
||||
|
||||
tabControl.Pages.Add(new TabPage(new Rect(5, 8, 70, 11), "Tab 1", () =>
|
||||
{
|
||||
TUIHelper.SetColors(ConsoleColor.Cyan, ConsoleColor.Black);
|
||||
Console.SetCursorPosition(10, 10);
|
||||
Console.Write("Tab 1 Content");
|
||||
TUIHelper.ResetColors();
|
||||
}));
|
||||
|
||||
tabControl.Pages.Add(new TabPage(new Rect(5, 8, 70, 11), "Tab 2", () =>
|
||||
{
|
||||
TUIHelper.SetColors(ConsoleColor.Green, ConsoleColor.Black);
|
||||
Console.SetCursorPosition(10, 10);
|
||||
Console.Write("Tab 2 Content");
|
||||
TUIHelper.ResetColors();
|
||||
}));
|
||||
|
||||
tabControl.Pages.Add(new TabPage(new Rect(5, 8, 70, 11), "Tab 3", () =>
|
||||
{
|
||||
TUIHelper.SetColors(ConsoleColor.Magenta, ConsoleColor.Black);
|
||||
Console.SetCursorPosition(10, 10);
|
||||
Console.Write("Tab 3 Content");
|
||||
TUIHelper.ResetColors();
|
||||
}));
|
||||
|
||||
tabControl.Render();
|
||||
|
||||
var statusBar = new StatusBar(new Rect(0, 24, 80, 1));
|
||||
statusBar.Items.Add(new StatusBarItem("Use LEFT/RIGHT to switch tabs, ESC to return"));
|
||||
statusBar.Render();
|
||||
|
||||
bool demoRunning = true;
|
||||
while (demoRunning)
|
||||
{
|
||||
var key = Console.ReadKey(true);
|
||||
|
||||
if (key.Key == ConsoleKey.Escape)
|
||||
{
|
||||
demoRunning = false;
|
||||
}
|
||||
else if (tabControl.HandleKey(key))
|
||||
{
|
||||
tabControl.Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user