mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-04-21 19:24:00 +00:00
增加更多UILib控件
This commit is contained in:
131
Gui/UILib/Notification.cs
Normal file
131
Gui/UILib/Notification.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using CMLeonOS;
|
||||
using CMLeonOS.UILib.Animations;
|
||||
using System.Drawing;
|
||||
|
||||
namespace CMLeonOS.Gui.UILib
|
||||
{
|
||||
internal class Notification
|
||||
{
|
||||
internal Notification(Process process, string title, string message)
|
||||
{
|
||||
owner = process;
|
||||
Title = title;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
private readonly Process owner;
|
||||
internal string Title { get; }
|
||||
internal string Message { get; }
|
||||
internal void Show()
|
||||
{
|
||||
ProcessManager.AddProcess(owner, new NotificationProcess(owner, Title, Message)).Start();
|
||||
}
|
||||
|
||||
private class NotificationProcess : Process
|
||||
{
|
||||
internal NotificationProcess(Process parent, string title, string message) : base("Notification", ProcessType.Background, parent)
|
||||
{
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
private readonly string title;
|
||||
private readonly string message;
|
||||
|
||||
private Window window;
|
||||
private Button closeButton;
|
||||
private readonly WindowManager wm = ProcessManager.GetProcess<WindowManager>();
|
||||
private bool closeAnimationRunning = false;
|
||||
private int targetX;
|
||||
private int targetY;
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
int width = 280;
|
||||
int height = 84;
|
||||
targetX = (int)wm.ScreenWidth - width - 16;
|
||||
targetY = (int)wm.ScreenHeight - height - 44;
|
||||
int startX = (int)wm.ScreenWidth + 12;
|
||||
|
||||
window = new Window(this, startX, targetY, width, height);
|
||||
window.Clear(UITheme.WindowTitleBackground);
|
||||
window.DrawFilledRectangle(0, 0, window.Width, window.Height, UITheme.WindowTitleBackground);
|
||||
window.DrawRectangle(0, 0, window.Width, window.Height, UITheme.SurfaceBorder);
|
||||
window.DrawFilledRectangle(0, 0, window.Width, 22, UITheme.Accent);
|
||||
window.DrawString(title, UITheme.WindowTitleText, 10, 4);
|
||||
window.DrawString(message, Color.White, 10, 30);
|
||||
wm.AddWindow(window);
|
||||
|
||||
closeButton = new Button(window, window.Width - 54, window.Height - 28, 44, 20);
|
||||
closeButton.Text = "Close";
|
||||
closeButton.OnClick = (_, _) => BeginCloseAnimation();
|
||||
wm.AddWindow(closeButton);
|
||||
|
||||
wm.Update(window);
|
||||
StartOpenAnimation(startX, targetY, width, height);
|
||||
}
|
||||
|
||||
private void StartOpenAnimation(int startX, int startY, int width, int height)
|
||||
{
|
||||
MovementAnimation animation = new MovementAnimation(window)
|
||||
{
|
||||
From = new Rectangle(startX, startY, width, height),
|
||||
To = new Rectangle(targetX, targetY, width, height),
|
||||
Duration = 10,
|
||||
EasingType = EasingType.Sine,
|
||||
EasingDirection = EasingDirection.Out
|
||||
};
|
||||
animation.Completed = () =>
|
||||
{
|
||||
wm.Update(window);
|
||||
closeButton.Render();
|
||||
};
|
||||
animation.Start();
|
||||
}
|
||||
|
||||
private void BeginCloseAnimation()
|
||||
{
|
||||
if (closeAnimationRunning || window == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
closeAnimationRunning = true;
|
||||
|
||||
int endX = (int)wm.ScreenWidth + 12;
|
||||
int width = window.Width;
|
||||
int height = window.Height;
|
||||
|
||||
MovementAnimation animation = new MovementAnimation(window)
|
||||
{
|
||||
From = new Rectangle(window.X, window.Y, width, height),
|
||||
To = new Rectangle(endX, targetY, width, height),
|
||||
Duration = 9,
|
||||
EasingType = EasingType.Sine,
|
||||
EasingDirection = EasingDirection.In
|
||||
};
|
||||
animation.Completed = TryStop;
|
||||
animation.Start();
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
base.Stop();
|
||||
if (closeButton != null)
|
||||
{
|
||||
wm.RemoveWindow(closeButton);
|
||||
}
|
||||
if (window != null)
|
||||
{
|
||||
wm.RemoveWindow(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
110
Gui/UILib/NumericUpDown.cs
Normal file
110
Gui/UILib/NumericUpDown.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace CMLeonOS.Gui.UILib
|
||||
{
|
||||
internal class NumericUpDown : Control
|
||||
{
|
||||
public NumericUpDown(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
|
||||
{
|
||||
OnClick = NumericUpDownClicked;
|
||||
}
|
||||
|
||||
internal Action<int> Changed;
|
||||
|
||||
private Color _background = UITheme.Surface;
|
||||
internal Color Background
|
||||
{
|
||||
get { return _background; }
|
||||
set { _background = value; Render(); }
|
||||
}
|
||||
|
||||
private Color _foreground = UITheme.TextPrimary;
|
||||
internal Color Foreground
|
||||
{
|
||||
get { return _foreground; }
|
||||
set { _foreground = value; Render(); }
|
||||
}
|
||||
|
||||
private Color _border = UITheme.SurfaceBorder;
|
||||
internal Color Border
|
||||
{
|
||||
get { return _border; }
|
||||
set { _border = value; Render(); }
|
||||
}
|
||||
|
||||
private int _minimum = 0;
|
||||
internal int Minimum
|
||||
{
|
||||
get { return _minimum; }
|
||||
set { _minimum = value; if (_value < _minimum) { _value = _minimum; } Render(); }
|
||||
}
|
||||
|
||||
private int _maximum = 100;
|
||||
internal int Maximum
|
||||
{
|
||||
get { return _maximum; }
|
||||
set { _maximum = value; if (_value > _maximum) { _value = _maximum; } Render(); }
|
||||
}
|
||||
|
||||
private int _step = 1;
|
||||
internal int Step
|
||||
{
|
||||
get { return _step; }
|
||||
set { _step = Math.Max(1, value); Render(); }
|
||||
}
|
||||
|
||||
private int _value = 0;
|
||||
internal int Value
|
||||
{
|
||||
get { return _value; }
|
||||
set
|
||||
{
|
||||
int newValue = Math.Clamp(value, _minimum, _maximum);
|
||||
if (_value != newValue)
|
||||
{
|
||||
_value = newValue;
|
||||
Render();
|
||||
Changed?.Invoke(_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void NumericUpDownClicked(int x, int y)
|
||||
{
|
||||
int buttonWidth = 22;
|
||||
if (x >= Width - buttonWidth)
|
||||
{
|
||||
if (y < Height / 2)
|
||||
{
|
||||
Value += _step;
|
||||
}
|
||||
else
|
||||
{
|
||||
Value -= _step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal override void Render()
|
||||
{
|
||||
int buttonWidth = 22;
|
||||
|
||||
Clear(Background);
|
||||
DrawFilledRectangle(0, 0, Width, Height, Background);
|
||||
DrawRectangle(0, 0, Width, Height, Border);
|
||||
|
||||
DrawFilledRectangle(Width - buttonWidth, 0, buttonWidth, Height, UITheme.SurfaceMuted);
|
||||
DrawRectangle(Width - buttonWidth, 0, buttonWidth, Height, Border);
|
||||
DrawHorizontalLine(buttonWidth, Width - buttonWidth, Height / 2, Border);
|
||||
|
||||
string text = _value.ToString();
|
||||
DrawString(text, Foreground, 6, (Height / 2) - 8);
|
||||
|
||||
DrawString("+", Foreground, Width - buttonWidth + 7, 2);
|
||||
DrawString("-", Foreground, Width - buttonWidth + 7, (Height / 2) - 2);
|
||||
|
||||
WM.Update(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Gui/UILib/StatusBar.cs
Normal file
62
Gui/UILib/StatusBar.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace CMLeonOS.Gui.UILib
|
||||
{
|
||||
internal class StatusBar : Control
|
||||
{
|
||||
public StatusBar(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
private string _text = "Ready";
|
||||
internal string Text
|
||||
{
|
||||
get { return _text; }
|
||||
set { _text = value ?? string.Empty; Render(); }
|
||||
}
|
||||
|
||||
private string _detailText = string.Empty;
|
||||
internal string DetailText
|
||||
{
|
||||
get { return _detailText; }
|
||||
set { _detailText = value ?? string.Empty; Render(); }
|
||||
}
|
||||
|
||||
private Color _background = UITheme.SurfaceMuted;
|
||||
internal Color Background
|
||||
{
|
||||
get { return _background; }
|
||||
set { _background = value; Render(); }
|
||||
}
|
||||
|
||||
private Color _foreground = UITheme.TextPrimary;
|
||||
internal Color Foreground
|
||||
{
|
||||
get { return _foreground; }
|
||||
set { _foreground = value; Render(); }
|
||||
}
|
||||
|
||||
private Color _border = UITheme.SurfaceBorder;
|
||||
internal Color Border
|
||||
{
|
||||
get { return _border; }
|
||||
set { _border = value; Render(); }
|
||||
}
|
||||
|
||||
internal override void Render()
|
||||
{
|
||||
Clear(Background);
|
||||
DrawFilledRectangle(0, 0, Width, Height, Background);
|
||||
DrawHorizontalLine(Width, 0, 0, Border);
|
||||
|
||||
DrawString(Text, Foreground, 6, (Height / 2) - 8);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DetailText))
|
||||
{
|
||||
DrawString(DetailText, Foreground, Width - (DetailText.Length * 8) - 6, (Height / 2) - 8);
|
||||
}
|
||||
|
||||
WM.Update(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
127
Gui/UILib/Tabs.cs
Normal file
127
Gui/UILib/Tabs.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace CMLeonOS.Gui.UILib
|
||||
{
|
||||
internal class Tabs : Control
|
||||
{
|
||||
public Tabs(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
|
||||
{
|
||||
OnClick = TabsClicked;
|
||||
}
|
||||
|
||||
internal Action<int, string> SelectionChanged;
|
||||
|
||||
internal List<string> Items { get; } = new List<string>();
|
||||
|
||||
private Color _background = UITheme.Surface;
|
||||
internal Color Background
|
||||
{
|
||||
get { return _background; }
|
||||
set { _background = value; Render(); }
|
||||
}
|
||||
|
||||
private Color _foreground = UITheme.TextPrimary;
|
||||
internal Color Foreground
|
||||
{
|
||||
get { return _foreground; }
|
||||
set { _foreground = value; Render(); }
|
||||
}
|
||||
|
||||
private Color _border = UITheme.SurfaceBorder;
|
||||
internal Color Border
|
||||
{
|
||||
get { return _border; }
|
||||
set { _border = value; Render(); }
|
||||
}
|
||||
|
||||
private int _selectedIndex = 0;
|
||||
internal int SelectedIndex
|
||||
{
|
||||
get { return _selectedIndex; }
|
||||
set
|
||||
{
|
||||
int newIndex = Math.Clamp(value, 0, Math.Max(0, Items.Count - 1));
|
||||
if (_selectedIndex != newIndex)
|
||||
{
|
||||
_selectedIndex = newIndex;
|
||||
Render();
|
||||
if (Items.Count > 0)
|
||||
{
|
||||
SelectionChanged?.Invoke(_selectedIndex, Items[_selectedIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal string SelectedText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Items.Count == 0 || _selectedIndex < 0 || _selectedIndex >= Items.Count)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return Items[_selectedIndex];
|
||||
}
|
||||
}
|
||||
|
||||
internal void RefreshItems()
|
||||
{
|
||||
if (_selectedIndex >= Items.Count)
|
||||
{
|
||||
_selectedIndex = Math.Max(0, Items.Count - 1);
|
||||
}
|
||||
Render();
|
||||
}
|
||||
|
||||
private void TabsClicked(int x, int y)
|
||||
{
|
||||
if (Items.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int tabWidth = Math.Max(1, Width / Items.Count);
|
||||
int index = Math.Min(Items.Count - 1, Math.Max(0, x / tabWidth));
|
||||
SelectedIndex = index;
|
||||
}
|
||||
|
||||
internal override void Render()
|
||||
{
|
||||
Clear(Background);
|
||||
DrawFilledRectangle(0, 0, Width, Height, Background);
|
||||
DrawRectangle(0, 0, Width, Height, Border);
|
||||
|
||||
if (Items.Count == 0)
|
||||
{
|
||||
WM.Update(this);
|
||||
return;
|
||||
}
|
||||
|
||||
int tabWidth = Math.Max(1, Width / Items.Count);
|
||||
for (int i = 0; i < Items.Count; i++)
|
||||
{
|
||||
int tabX = i * tabWidth;
|
||||
int actualWidth = i == Items.Count - 1 ? Width - tabX : tabWidth;
|
||||
bool selected = i == _selectedIndex;
|
||||
|
||||
DrawFilledRectangle(tabX, 0, actualWidth, Height, selected ? UITheme.AccentLight : UITheme.SurfaceMuted);
|
||||
DrawRectangle(tabX, 0, actualWidth, Height, selected ? UITheme.Accent : Border);
|
||||
|
||||
string text = Items[i];
|
||||
int maxChars = Math.Max(1, (actualWidth - 8) / 8);
|
||||
if (text.Length > maxChars)
|
||||
{
|
||||
text = text.Substring(0, Math.Max(1, maxChars - 1)) + "~";
|
||||
}
|
||||
|
||||
DrawString(text, Foreground, tabX + (actualWidth / 2) - (text.Length * 4), (Height / 2) - 8);
|
||||
}
|
||||
|
||||
WM.Update(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user