新登录页面UI

This commit is contained in:
2026-02-07 14:50:39 +08:00
parent ae56d2f5b1
commit 6e87e44a15
3 changed files with 893 additions and 118 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace CMLeonOS.UI
{
@@ -589,4 +590,514 @@ namespace CMLeonOS.UI
RenderContent?.Invoke();
}
}
public class ListBox
{
public Rect Bounds { get; set; }
public List<string> Items { get; set; } = new List<string>();
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 bool MultiSelect { get; set; } = false;
public List<int> SelectedIndices { get; set; } = new List<int>();
public ListBox()
{
}
public ListBox(Rect bounds)
{
Bounds = bounds;
}
public void Render()
{
TUIHelper.SetColors(BorderColor, BackgroundColor);
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) ? "> " : " ";
if (MultiSelect && SelectedIndices.Contains(i))
{
prefix = "[x] ";
}
else if (MultiSelect)
{
prefix = "[ ] ";
}
TUIHelper.SetColors(color, BackgroundColor);
Console.SetCursorPosition(Bounds.Left + 1, y);
Console.Write(prefix + TUIHelper.TruncateText(Items[i], Bounds.Width - 3));
}
if (Items.Count > maxHeight)
{
int scrollY = Bounds.Bottom - 1;
TUIHelper.SetColors(ConsoleColor.Gray, BackgroundColor);
Console.SetCursorPosition(Bounds.Right - 10, 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 (MultiSelect)
{
if (SelectedIndices.Contains(SelectedIndex))
{
SelectedIndices.Remove(SelectedIndex);
}
else
{
SelectedIndices.Add(SelectedIndex);
}
}
return true;
}
if (key.Key == ConsoleKey.Spacebar && MultiSelect)
{
if (SelectedIndices.Contains(SelectedIndex))
{
SelectedIndices.Remove(SelectedIndex);
}
else
{
SelectedIndices.Add(SelectedIndex);
}
return true;
}
return false;
}
}
public class CheckBox
{
public Point Position { get; set; }
public string Text { get; set; }
public bool IsChecked { get; set; } = false;
public bool IsFocused { get; set; } = false;
public ConsoleColor TextColor { get; set; } = ConsoleColor.White;
public ConsoleColor BoxColor { get; set; } = ConsoleColor.White;
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.Black;
public ConsoleColor FocusedTextColor { get; set; } = ConsoleColor.Yellow;
public ConsoleColor FocusedBoxColor { get; set; } = ConsoleColor.Yellow;
public ConsoleColor FocusedBackgroundColor { get; set; } = ConsoleColor.DarkBlue;
public CheckBox()
{
}
public CheckBox(Point position, string text)
{
Position = position;
Text = text;
}
public void Render()
{
if (IsFocused)
{
TUIHelper.SetColors(FocusedTextColor, FocusedBackgroundColor);
Console.SetCursorPosition(Position.X, Position.Y);
Console.Write(IsChecked ? "[X] " : "[ ] ");
Console.Write(Text);
}
else
{
TUIHelper.SetColors(TextColor, BackgroundColor);
Console.SetCursorPosition(Position.X, Position.Y);
Console.Write(IsChecked ? "[x] " : "[ ] ");
Console.Write(Text);
}
}
public bool HandleKey(ConsoleKeyInfo key)
{
if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Spacebar)
{
IsChecked = !IsChecked;
return true;
}
return false;
}
}
public class RadioButton
{
public Point Position { get; set; }
public string Text { get; set; }
public bool IsChecked { get; set; } = false;
public bool IsFocused { get; set; } = false;
public ConsoleColor TextColor { get; set; } = ConsoleColor.White;
public ConsoleColor BoxColor { get; set; } = ConsoleColor.White;
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.Black;
public string GroupName { get; set; } = string.Empty;
public ConsoleColor FocusedTextColor { get; set; } = ConsoleColor.Yellow;
public ConsoleColor FocusedBoxColor { get; set; } = ConsoleColor.Yellow;
public ConsoleColor FocusedBackgroundColor { get; set; } = ConsoleColor.DarkBlue;
public RadioButton()
{
}
public RadioButton(Point position, string text)
{
Position = position;
Text = text;
}
public void Render()
{
if (IsFocused)
{
TUIHelper.SetColors(FocusedTextColor, FocusedBackgroundColor);
Console.SetCursorPosition(Position.X, Position.Y);
Console.Write(IsChecked ? "(*) " : "( ) ");
Console.Write(Text);
}
else
{
TUIHelper.SetColors(TextColor, BackgroundColor);
Console.SetCursorPosition(Position.X, Position.Y);
Console.Write(IsChecked ? "(*) " : "( ) ");
Console.Write(Text);
}
}
public bool HandleKey(ConsoleKeyInfo key)
{
if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Spacebar)
{
IsChecked = !IsChecked;
return true;
}
return false;
}
}
public class TreeViewNode
{
public string Text { get; set; }
public List<TreeViewNode> Children { get; set; } = new List<TreeViewNode>();
public bool IsExpanded { get; set; } = false;
public int Level { get; set; } = 0;
public TreeViewNode Parent { get; set; }
public bool HasChildren => Children.Count > 0;
public TreeViewNode()
{
}
public TreeViewNode(string text)
{
Text = text;
}
}
public class TreeView
{
public Rect Bounds { get; set; }
public TreeViewNode Root { get; set; }
public List<TreeViewNode> SelectedNodes { get; set; } = new List<TreeViewNode>();
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 int ScrollOffset { get; set; } = 0;
public TreeView()
{
}
public TreeView(Rect bounds)
{
Bounds = bounds;
}
public void Render()
{
TUIHelper.SetColors(BorderColor, BackgroundColor);
TUIHelper.DrawBox(Bounds, string.Empty, BorderColor);
int startY = Bounds.Top + 1;
int maxHeight = Bounds.Height - 2;
List<TreeViewNode> visibleNodes = GetVisibleNodes();
for (int i = ScrollOffset; i < visibleNodes.Count && i < ScrollOffset + maxHeight; i++)
{
int y = startY + (i - ScrollOffset);
var node = visibleNodes[i];
ConsoleColor color = SelectedNodes.Contains(node) ? SelectedColor : NormalColor;
string prefix = GetNodePrefix(node);
TUIHelper.SetColors(color, BackgroundColor);
Console.SetCursorPosition(Bounds.Left + 1, y);
Console.Write(prefix + TUIHelper.TruncateText(node.Text, Bounds.Width - 3 - node.Level * 2));
}
if (visibleNodes.Count > maxHeight)
{
int scrollY = Bounds.Bottom - 1;
TUIHelper.SetColors(ConsoleColor.Gray, BackgroundColor);
Console.SetCursorPosition(Bounds.Right - 10, scrollY);
Console.Write($"({ScrollOffset + 1}/{(int)Math.Ceiling((double)visibleNodes.Count / maxHeight)})");
}
}
private List<TreeViewNode> GetVisibleNodes()
{
List<TreeViewNode> nodes = new List<TreeViewNode>();
if (Root != null)
{
AddVisibleNodes(Root, nodes);
}
return nodes;
}
private void AddVisibleNodes(TreeViewNode node, List<TreeViewNode> nodes)
{
nodes.Add(node);
if (node.IsExpanded)
{
foreach (var child in node.Children)
{
AddVisibleNodes(child, nodes);
}
}
}
private string GetNodePrefix(TreeViewNode node)
{
string prefix = "";
for (int i = 0; i < node.Level; i++)
{
prefix += " ";
}
if (node.HasChildren)
{
prefix += node.IsExpanded ? "- " : "+ ";
}
else
{
prefix += "+ ";
}
return prefix;
}
public bool HandleKey(ConsoleKeyInfo key)
{
var visibleNodes = GetVisibleNodes();
if (visibleNodes.Count == 0) return false;
if (key.Key == ConsoleKey.UpArrow || key.Key == ConsoleKey.PageUp)
{
int currentIndex = visibleNodes.FindIndex(n => SelectedNodes.Contains(n));
if (currentIndex > 0)
{
SelectedNodes.Clear();
SelectedNodes.Add(visibleNodes[currentIndex - 1]);
if (currentIndex - 1 < ScrollOffset) ScrollOffset = currentIndex - 1;
}
return true;
}
if (key.Key == ConsoleKey.DownArrow || key.Key == ConsoleKey.PageDown)
{
int currentIndex = visibleNodes.FindIndex(n => SelectedNodes.Contains(n));
if (currentIndex < visibleNodes.Count - 1)
{
SelectedNodes.Clear();
SelectedNodes.Add(visibleNodes[currentIndex + 1]);
int maxScroll = visibleNodes.Count - (Bounds.Height - 2);
if (currentIndex + 1 >= ScrollOffset + (Bounds.Height - 2))
{
ScrollOffset = (currentIndex + 1) - (Bounds.Height - 3);
}
}
return true;
}
if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Spacebar)
{
var currentNode = visibleNodes.FirstOrDefault(n => SelectedNodes.Contains(n));
if (currentNode != null && currentNode.HasChildren)
{
currentNode.IsExpanded = !currentNode.IsExpanded;
}
else if (currentNode != null)
{
if (SelectedNodes.Contains(currentNode))
{
SelectedNodes.Remove(currentNode);
}
else
{
SelectedNodes.Add(currentNode);
}
}
return true;
}
return false;
}
}
public class ScrollBar
{
public Point Position { get; set; }
public int Height { get; set; }
public int MaxValue { get; set; }
public int Value { get; set; } = 0;
public ConsoleColor BarColor { get; set; } = ConsoleColor.White;
public ConsoleColor BackgroundColor { get; set; } = ConsoleColor.DarkGray;
public ConsoleColor BorderColor { get; set; } = ConsoleColor.White;
public bool IsVertical { get; set; } = true;
public ScrollBar()
{
}
public ScrollBar(Point position, int height)
{
Position = position;
Height = height;
}
public void Render()
{
TUIHelper.SetColors(BorderColor, BackgroundColor);
if (IsVertical)
{
Console.SetCursorPosition(Position.X, Position.Y);
Console.Write('┌');
for (int i = 0; i < Height - 2; i++)
{
Console.SetCursorPosition(Position.X, Position.Y + 1 + i);
Console.Write('│');
}
Console.SetCursorPosition(Position.X, Position.Y + Height - 1);
Console.Write('└');
int barHeight = Height - 2;
int barPosition = (int)((double)Value / MaxValue * barHeight);
for (int i = 0; i < barHeight; i++)
{
Console.SetCursorPosition(Position.X, Position.Y + 1 + i);
if (i >= barPosition && i < barPosition + (int)((double)barHeight / MaxValue * Value))
{
Console.Write('█');
}
else
{
Console.Write('░');
}
}
}
else
{
Console.SetCursorPosition(Position.X, Position.Y);
Console.Write('┌');
for (int i = 0; i < Height - 2; i++)
{
Console.SetCursorPosition(Position.X + 1 + i, Position.Y);
Console.Write('─');
}
Console.SetCursorPosition(Position.X + Height - 1, Position.Y);
Console.Write('┐');
int barWidth = Height - 2;
int barPosition = (int)((double)Value / MaxValue * barWidth);
for (int i = 0; i < barWidth; i++)
{
Console.SetCursorPosition(Position.X + 1 + i, Position.Y);
if (i >= barPosition && i < barPosition + (int)((double)barWidth / MaxValue * Value))
{
Console.Write('█');
}
else
{
Console.Write('░');
}
}
}
}
public bool HandleKey(ConsoleKeyInfo key)
{
if (IsVertical)
{
if (key.Key == ConsoleKey.UpArrow)
{
Value = Math.Max(0, Value - 1);
return true;
}
if (key.Key == ConsoleKey.DownArrow)
{
Value = Math.Min(MaxValue, Value + 1);
return true;
}
if (key.Key == ConsoleKey.PageUp)
{
Value = Math.Max(0, Value - 10);
return true;
}
if (key.Key == ConsoleKey.PageDown)
{
Value = Math.Min(MaxValue, Value + 10);
return true;
}
}
else
{
if (key.Key == ConsoleKey.LeftArrow)
{
Value = Math.Max(0, Value - 1);
return true;
}
if (key.Key == ConsoleKey.RightArrow)
{
Value = Math.Min(MaxValue, Value + 1);
return true;
}
}
return false;
}
}
}