更新GUI登录UI,更新UILib

This commit is contained in:
2026-03-23 21:34:21 +08:00
parent 9162e2d69d
commit 9197dfbaa3
13 changed files with 332 additions and 102 deletions

View File

@@ -1 +1 @@
2026-03-22 19:16:27
2026-03-23 21:30:51

View File

@@ -1 +1 @@
e43417c
9162e2d

View File

@@ -20,6 +20,7 @@ using CMLeonOS.Gui.UILib;
using CMLeonOS.Logger;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace CMLeonOS.Gui.ShellComponents
@@ -33,6 +34,7 @@ namespace CMLeonOS.Gui.ShellComponents
Table userTable;
TextBox passwordBox;
Button logOnButton;
WindowManager wm = ProcessManager.GetProcess<WindowManager>();
@@ -43,21 +45,122 @@ namespace CMLeonOS.Gui.ShellComponents
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Lock.Key.bmp")]
private static byte[] _iconBytes_Key;
internal static Bitmap Icon_Key = new Bitmap(_iconBytes_Key);
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Lock.User.bmp")]
private static byte[] _iconBytes_User;
internal static Bitmap Icon_User = new Bitmap(_iconBytes_User);
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Lock.UserArrow.bmp")]
private static byte[] _iconBytes_UserArrow;
internal static Bitmap Icon_UserArrow = new Bitmap(_iconBytes_UserArrow);
}
private const int width = 352;
private const int height = 200;
private const int padding = 12;
private const int width = 700;
private const int height = 420;
private const int leftPanelWidth = 240;
private const int rightContentPadding = 28;
private const int rightContentBottomPadding = 30;
private const int accountsLabelY = 102;
private const int tableY = 124;
private const int tableHeight = 140;
private const int passwordLabelY = tableY + tableHeight + 18;
private const int passwordY = passwordLabelY + 22;
private const int passwordHeight = 30;
private const int logOnButtonY = passwordY + 44;
private const int logOnButtonHeight = 38;
private readonly Color windowBackground = Color.FromArgb(232, 238, 246);
private readonly Color outerBorder = Color.FromArgb(169, 181, 198);
private readonly Color leftPanel = Color.FromArgb(34, 53, 84);
private readonly Color leftPanelAccent = Color.FromArgb(74, 124, 201);
private readonly Color leftPanelSoft = Color.FromArgb(53, 77, 116);
private readonly Color rightPanel = Color.FromArgb(247, 250, 253);
private readonly Color titleColor = Color.FromArgb(28, 39, 56);
private readonly Color bodyColor = Color.FromArgb(92, 103, 119);
private readonly Color hintColor = Color.FromArgb(132, 142, 156);
private readonly Color inputBackground = Color.White;
private readonly Color inputForeground = Color.FromArgb(31, 42, 55);
private readonly Color selectionBackground = Color.FromArgb(223, 236, 255);
private readonly Color selectionBorder = Color.FromArgb(91, 140, 223);
private readonly Color primaryButton = Color.FromArgb(53, 111, 214);
private readonly Color primaryButtonBorder = Color.FromArgb(33, 83, 171);
private readonly Color primaryButtonText = Color.White;
private double shakiness = 0;
private List<User> users = new List<User>();
private void RenderBackground()
{
window.Clear(Color.LightGray);
window.Clear(windowBackground);
window.DrawRectangle(0, 0, width, height, outerBorder);
window.DrawImageAlpha(Images.Icon_Key, padding, padding);
int leftWidth = leftPanelWidth;
int rightX = leftWidth + 1;
int rightWidth = width - rightX;
window.DrawString("Select a user and enter password,\nthen press Enter to log on", Color.Black, (int)(padding + Images.Icon_Key.Width + padding), padding);
window.DrawFilledRectangle(0, 0, leftWidth, height, leftPanel);
window.DrawFilledRectangle(leftWidth - 6, 0, 6, height, leftPanelAccent);
window.DrawFilledRectangle(rightX, 0, rightWidth, height, rightPanel);
window.DrawFilledRectangle(20, 22, 56, 56, leftPanelSoft);
window.DrawRectangle(20, 22, 56, 56, Color.FromArgb(109, 149, 214));
window.DrawImageAlpha(Images.Icon_Key, 32, 34);
window.DrawString("Welcome Back", Color.White, 20, 96);
window.DrawString("CMLeonOS Desktop", Color.FromArgb(190, 208, 233), 20, 120);
string selectedUserName = GetSelectedUser()?.Username ?? "Guest";
window.DrawString("Selected account", Color.FromArgb(171, 190, 217), 20, 168);
window.DrawString(selectedUserName, Color.White, 20, 190);
window.DrawString(GetSelectedUserSubtitle(), Color.FromArgb(176, 197, 224), 20, 214);
window.DrawFilledRectangle(20, height - 72, leftWidth - 40, 44, leftPanelSoft);
window.DrawRectangle(20, height - 72, leftWidth - 40, 44, Color.FromArgb(88, 118, 171));
window.DrawString("Tip: type password.", Color.White, 32, height - 62);
window.DrawString("Press Enter to sign in.", Color.FromArgb(190, 208, 233), 32, height - 44);
int rightContentX = leftWidth + rightContentPadding;
window.DrawString("Sign in", titleColor, rightContentX, 28);
window.DrawString("Choose an account, then enter your password.", bodyColor, rightContentX, 54);
window.DrawString("Continue to the desktop when ready.", bodyColor, rightContentX, 72);
window.DrawString("Accounts", hintColor, rightContentX, accountsLabelY);
window.DrawString("Password", hintColor, rightContentX, passwordLabelY);
window.DrawString("Secure local session", Color.FromArgb(118, 128, 141), rightContentX, height - rightContentBottomPadding);
}
private User GetSelectedUser()
{
if (userTable == null || users == null || users.Count == 0)
{
return null;
}
if (userTable.SelectedCellIndex < 0 || userTable.SelectedCellIndex >= users.Count)
{
return null;
}
return users[userTable.SelectedCellIndex];
}
private string GetSelectedUserSubtitle()
{
User selectedUser = GetSelectedUser();
if (selectedUser == null)
{
return "No local users available";
}
return selectedUser.Admin ? "Administrator account" : "Standard local account";
}
private void RefreshLayout()
{
RenderBackground();
wm.Update(window);
}
private void ShowError(string text)
@@ -78,12 +181,11 @@ namespace CMLeonOS.Gui.ShellComponents
return;
}
if (userTable.SelectedCellIndex >= UserSystem.GetUsers().Count)
if (userTable.SelectedCellIndex >= users.Count)
{
return;
}
var users = UserSystem.GetUsers();
User selectedUser = users[userTable.SelectedCellIndex];
string password = passwordBox.Text.Trim();
@@ -145,7 +247,7 @@ namespace CMLeonOS.Gui.ShellComponents
{
base.Start();
var users = UserSystem.GetUsers();
users = UserSystem.GetUsers() ?? new List<User>();
Logger.Logger.Instance.Info("Lock", $"Lock started. Total users: {users?.Count ?? 0}");
if (users != null)
{
@@ -164,21 +266,21 @@ namespace CMLeonOS.Gui.ShellComponents
RenderBackground();
int contentHeight = 110;
int contentWidth = 160;
int startX = (width - contentWidth) / 2;
int startY = (height - contentHeight) / 2;
int contentX = leftPanelWidth + rightContentPadding;
int contentWidth = width - contentX - rightContentPadding;
userTable = new Table(window, startX, startY, contentWidth, 80);
userTable.CellHeight = 25;
userTable.Background = Color.White;
userTable.Foreground = Color.Black;
userTable.Border = Color.Gray;
userTable.SelectedBackground = Color.FromArgb(221, 246, 255);
userTable.SelectedForeground = Color.Black;
userTable.SelectedBorder = Color.FromArgb(126, 205, 234);
userTable = new Table(window, contentX, tableY, contentWidth, tableHeight);
userTable.CellHeight = 40;
userTable.Background = inputBackground;
userTable.Foreground = inputForeground;
userTable.Border = Color.FromArgb(203, 212, 224);
userTable.SelectedBackground = selectionBackground;
userTable.SelectedForeground = inputForeground;
userTable.SelectedBorder = selectionBorder;
userTable.AllowSelection = true;
userTable.AllowDeselection = false;
userTable.ScrollbarThickness = 18;
userTable.TableCellSelected = _ => RefreshLayout();
foreach (var user in users)
{
@@ -193,13 +295,27 @@ namespace CMLeonOS.Gui.ShellComponents
wm.AddWindow(userTable);
passwordBox = new TextBox(window, startX, startY + 90, contentWidth, 20);
passwordBox = new TextBox(window, contentX, passwordY, contentWidth, passwordHeight);
passwordBox.Shield = true;
passwordBox.PlaceholderText = "Password";
passwordBox.PlaceholderText = "Enter password";
passwordBox.Background = inputBackground;
passwordBox.Foreground = inputForeground;
passwordBox.PlaceholderForeground = hintColor;
passwordBox.Changed = RefreshLayout;
passwordBox.Submitted = LogOn;
wm.AddWindow(passwordBox);
wm.Update(window);
logOnButton = new Button(window, contentX, logOnButtonY, contentWidth, logOnButtonHeight);
logOnButton.Text = "Log On";
logOnButton.Background = primaryButton;
logOnButton.Border = primaryButtonBorder;
logOnButton.Foreground = primaryButtonText;
logOnButton.Image = Images.Icon_UserArrow;
logOnButton.ImageLocation = Button.ButtonImageLocation.Left;
logOnButton.OnClick = LogOnClick;
wm.AddWindow(logOnButton);
RefreshLayout();
}
public override void Run()

View File

@@ -236,14 +236,36 @@ namespace CMLeonOS.Gui.UILib
private void RenderDecoration()
{
decorationWindow.Clear(Color.FromArgb(56, 56, 71));
decorationWindow.Clear(UITheme.WindowTitleBackground);
decorationWindow.DrawHorizontalLine(Width, 0, 0, UITheme.WindowTitleTopHighlight);
decorationWindow.DrawHorizontalLine(Width, 0, titlebarHeight - 1, UITheme.WindowTitleBottomBorder);
int buttonSpace = 0;
if (_canClose)
{
buttonSpace += titlebarHeight;
}
if (_canResize)
{
buttonSpace += titlebarHeight;
}
if (buttonSpace > 0)
{
decorationWindow.DrawFilledRectangle(Width - buttonSpace, 1, buttonSpace, titlebarHeight - 2, UITheme.WindowButtonBackground);
}
if (_smallIcon != null)
{
decorationWindow.DrawImageAlpha(_smallIcon, 2, 2);
decorationWindow.DrawImageAlpha(_smallIcon, 3, 2);
}
decorationWindow.DrawString(Title, Color.White, (Width / 2) - ((FontData.Width * Title.Length) / 2), 4);
int maxTitleChars = Math.Max(4, (Width - buttonSpace - 42) / FontData.Width);
string displayTitle = Title;
if (displayTitle.Length > maxTitleChars)
{
displayTitle = displayTitle.Substring(0, Math.Max(1, maxTitleChars - 1)) + "~";
}
decorationWindow.DrawString(displayTitle, UITheme.WindowTitleText, 28, 4);
if (_canClose)
{

View File

@@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using Cosmos.System.Graphics;
using Cosmos.System;
using System;
using System.Drawing;
@@ -24,6 +25,11 @@ namespace CMLeonOS.Gui.UILib
{
public Button(Window parent, int x, int y, int width, int height) : base(parent, x, y, width, height)
{
OnDown = (_, _) =>
{
held = true;
Render();
};
}
internal enum ButtonImageLocation
@@ -60,7 +66,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _background = Color.FromArgb(48, 48, 48);
private Color _background = UITheme.Accent;
internal Color Background
{
get
@@ -88,7 +94,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _border = Color.Black;
private Color _border = UITheme.AccentDark;
internal Color Border
{
get
@@ -116,29 +122,58 @@ namespace CMLeonOS.Gui.UILib
}
}
private bool held = false;
internal override void Render()
{
Clear(Background);
if (held && MouseManager.MouseState != MouseState.Left)
{
held = false;
}
Color buttonBackground = held
? Color.FromArgb(Math.Max(0, Background.R - 24), Math.Max(0, Background.G - 24), Math.Max(0, Background.B - 24))
: Background;
Clear(UITheme.Surface);
DrawFilledRectangle(0, 0, Width, Height, buttonBackground);
DrawHorizontalLine(Width - 2, 1, 1, Color.FromArgb(
Math.Min(255, buttonBackground.R + 20),
Math.Min(255, buttonBackground.G + 20),
Math.Min(255, buttonBackground.B + 20)));
if (_image != null)
{
switch (_imageLocation)
{
case ButtonImageLocation.Left:
DrawImageAlpha(_image, (int)((Width / 2) - ((8 / 2) * Text.Length) - 8 - _image.Width), (int)((Height / 2) - (_image.Height / 2)));
DrawString(Text, Foreground, (Width / 2) - ((8 / 2) * Text.Length), (Height / 2) - (16 / 2));
{
int imageWidth = (int)_image.Width;
int imageHeight = (int)_image.Height;
int textWidth = 8 * Text.Length;
int contentWidth = imageWidth + 6 + textWidth;
int imageX = Math.Max(4, (Width / 2) - (contentWidth / 2));
int imageY = (Height / 2) - (imageHeight / 2);
int textXLeft = imageX + imageWidth + 6;
int textYLeft = (Height / 2) - (16 / 2);
DrawImageAlpha(_image, imageX, imageY);
DrawString(Text, Foreground, textXLeft, textYLeft);
break;
}
case ButtonImageLocation.AboveText:
DrawImageAlpha(_image, (int)((Width / 2) - (_image.Width / 2)), (int)((Height / 2) - (_image.Height / 2)));
DrawString(Text, Foreground, (Width / 2) - (4 * Text.Length), Height - 16);
{
DrawImageAlpha(_image, (int)((Width / 2) - (_image.Width / 2)), Math.Max(1, (int)((Height / 2) - (_image.Height / 2) - 4)));
DrawString(Text, Foreground, (Width / 2) - (4 * Text.Length), Height - 17);
break;
}
default:
throw new Exception("Unrecognised image location in button.");
}
}
else
{
DrawString(Text, Foreground, (Width / 2) - (4 * Text.Length), (Height / 2) - 8);
DrawString(Text, Foreground, (Width / 2) - (4 * Text.Length), (Height / 2) - 8 + (held ? 1 : 0));
}
DrawRectangle(0, 0, Width, Height, Border);

View File

@@ -74,7 +74,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _background = Color.White;
private Color _background = UITheme.Surface;
internal Color Background
{
get
@@ -88,7 +88,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _foreground = Color.Black;
private Color _foreground = UITheme.TextPrimary;
internal Color Foreground
{
get
@@ -117,7 +117,8 @@ namespace CMLeonOS.Gui.UILib
int textX = iconSize + 8;
int textY = (Height / 2) - (16 / 2);
DrawFilledRectangle(iconX, iconY, iconSize, iconSize, Color.LightGray);
DrawFilledRectangle(iconX, iconY, iconSize, iconSize, _checked ? UITheme.AccentLight : UITheme.SurfaceMuted);
DrawRectangle(iconX, iconY, iconSize, iconSize, _checked ? UITheme.Accent : UITheme.SurfaceBorder);
if (_checked)
{
DrawImageAlpha(checkBitmap, iconX, iconY);

View File

@@ -44,16 +44,19 @@ namespace CMLeonOS.Gui.UILib
int width = Math.Max(192, (Padding * 2) + (8 * longestLineLength));
int height = 128 + ((Message.Split('\n').Length - 1) * 16);
AppWindow window = new AppWindow(Process, (int)((wm.ScreenWidth / 2) - (height / 2)), (int)((wm.ScreenWidth / 2) - (width / 2)), width, height);
AppWindow window = new AppWindow(Process, (int)((wm.ScreenWidth / 2) - (width / 2)), (int)((wm.ScreenHeight / 2) - (height / 2)), width, height);
window.Title = Title;
wm.AddWindow(window);
window.Clear(Color.LightGray);
window.DrawFilledRectangle(0, window.Height - (Padding * 2) - 20, window.Width, (Padding * 2) + 20, Color.Gray);
window.DrawString(Message, Color.Black, Padding, Padding);
window.Clear(UITheme.Surface);
window.DrawRectangle(0, 0, window.Width, window.Height, UITheme.SurfaceBorder);
window.DrawFilledRectangle(0, window.Height - (Padding * 2) - 20, window.Width, (Padding * 2) + 20, UITheme.SurfaceMuted);
window.DrawString(Message, UITheme.TextPrimary, Padding, Padding);
Button ok = new Button(window, window.Width - 80 - Padding, window.Height - 20 - Padding, 80, 20);
ok.Text = "OK";
ok.Background = UITheme.Accent;
ok.Border = UITheme.AccentDark;
ok.OnClick = (int x, int y) =>
{
wm.RemoveWindow(window);

View File

@@ -42,13 +42,14 @@ namespace CMLeonOS.Gui.UILib
int width = Math.Max(256, (Padding * 2) + (8 * longestLineLength));
int height = 128 + ((Message.Split('\n').Length - 1) * 16);
AppWindow window = new AppWindow(Process, (int)((wm.ScreenWidth / 2) - (height / 2)), (int)((wm.ScreenWidth / 2) - (width / 2)), width, height);
AppWindow window = new AppWindow(Process, (int)((wm.ScreenWidth / 2) - (width / 2)), (int)((wm.ScreenHeight / 2) - (height / 2)), width, height);
window.Title = Title;
wm.AddWindow(window);
window.Clear(Color.LightGray);
window.DrawFilledRectangle(0, window.Height - (Padding * 2) - 20, window.Width, (Padding * 2) + 20, Color.Gray);
window.DrawString(Message, Color.Black, Padding, Padding);
window.Clear(UITheme.Surface);
window.DrawRectangle(0, 0, window.Width, window.Height, UITheme.SurfaceBorder);
window.DrawFilledRectangle(0, window.Height - (Padding * 2) - 20, window.Width, (Padding * 2) + 20, UITheme.SurfaceMuted);
window.DrawString(Message, UITheme.TextPrimary, Padding, Padding);
TextBox textBox = new TextBox(window, Padding, Padding + FontData.Height + 8, 192, 20);
textBox.PlaceholderText = Placeholder;
@@ -56,6 +57,8 @@ namespace CMLeonOS.Gui.UILib
Button ok = new Button(window, window.Width - 80 - Padding, window.Height - 20 - Padding, 80, 20);
ok.Text = "OK";
ok.Background = UITheme.Accent;
ok.Border = UITheme.AccentDark;
ok.OnClick = (int x, int y) =>
{
wm.RemoveWindow(window);

View File

@@ -41,7 +41,7 @@ namespace CMLeonOS.Gui.UILib
Render();
}
private Color _background = Color.White;
private Color _background = UITheme.Surface;
internal Color Background
{
get
@@ -55,7 +55,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _foreground = Color.Gray;
private Color _foreground = UITheme.TextSecondary;
internal Color Foreground
{
get
@@ -143,9 +143,9 @@ namespace CMLeonOS.Gui.UILib
private bool held = false;
private static int slotHeight = 3;
private static int sliderHeight = 15;
private static int sliderWidth = 5;
private static int slotHeight = 4;
private static int sliderHeight = 16;
private static int sliderWidth = 8;
private void RangeSliderDown(int x, int y)
{
@@ -187,7 +187,9 @@ namespace CMLeonOS.Gui.UILib
}
// Slot
DrawFilledRectangle(0, slotY, Width, slotHeight, Color.FromArgb(168, 168, 168));
DrawFilledRectangle(0, slotY, Width, slotHeight, UITheme.SurfaceBorder);
int fillWidth = (int)(_value.Map((float)_minimum, (float)_maximum, 0, Width - sliderWidth)) + (sliderWidth / 2);
DrawFilledRectangle(0, slotY, Math.Max(0, fillWidth), slotHeight, UITheme.AccentLight);
// Slider
DrawFilledRectangle(
@@ -195,7 +197,14 @@ namespace CMLeonOS.Gui.UILib
sliderY,
sliderWidth,
sliderHeight,
held ? Color.FromArgb(0, 71, 112) : Color.FromArgb(0, 115, 186)
held ? UITheme.AccentDark : UITheme.Accent
);
DrawRectangle(
(int)(_value.Map((float)_minimum, (float)_maximum, 0, Width - sliderWidth)),
sliderY,
sliderWidth,
sliderHeight,
UITheme.AccentDark
);
if (_rangeLabels)

View File

@@ -15,8 +15,8 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using Cosmos.System;
using Cosmos.System.Graphics;
using System;
using System.Drawing;
namespace CMLeonOS.Gui.UILib
{
@@ -28,19 +28,10 @@ namespace CMLeonOS.Gui.UILib
OnClick = null;
}
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.SwitchOff.bmp")]
private static byte[] offBytes;
private static Bitmap offBitmap = new Bitmap(offBytes);
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.SwitchOn.bmp")]
private static byte[] onBytes;
private static Bitmap onBitmap = new Bitmap(onBytes);
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.SwitchKnob.bmp")]
private static byte[] knobBytes;
private static Bitmap knobBitmap = new Bitmap(knobBytes);
private const int maximumToggleDrag = 4;
private const int switchWidth = 34;
private const int switchHeight = 18;
private const int knobSize = 14;
private int lastMouseX = 0;
private int totalDragged = 0;
@@ -67,7 +58,7 @@ namespace CMLeonOS.Gui.UILib
// Interpret as a drag rather than a toggle,
// setting the Checked state based on where
// the switch knob is.
Checked = knobX >= (offBitmap.Width / 2) - (knobBitmap.Width / 2);
Checked = knobX >= (switchWidth - knobSize) / 2d;
}
}
@@ -76,7 +67,7 @@ namespace CMLeonOS.Gui.UILib
internal override void Render()
{
knobGoal = (int)(Checked ? offBitmap.Width - knobBitmap.Width : 0);
knobGoal = Checked ? switchWidth - knobSize : 0;
if (held && MouseManager.MouseState != MouseState.Left)
{
@@ -88,7 +79,7 @@ namespace CMLeonOS.Gui.UILib
int diff = (int)(MouseManager.X - lastMouseX);
lastMouseX = (int)MouseManager.X;
totalDragged += Math.Abs(diff);
knobX = Math.Clamp(knobX + diff, 0, offBitmap.Width - knobBitmap.Width);
knobX = Math.Clamp(knobX + diff, 0, switchWidth - knobSize);
WM.UpdateQueue.Enqueue(this);
}
@@ -118,13 +109,17 @@ namespace CMLeonOS.Gui.UILib
Clear(Background);
int switchX = 0;
int switchY = (Height / 2) - ((int)offBitmap.Height / 2);
int switchY = (Height / 2) - (switchHeight / 2);
int textX = (int)(offBitmap.Width + 8);
int textX = switchWidth + 8;
int textY = (Height / 2) - (16 / 2);
DrawImageAlpha(Checked ? onBitmap : offBitmap, switchX, switchY);
DrawImageAlpha(knobBitmap, (int)knobX, switchY);
DrawFilledRectangle(switchX, switchY, switchWidth, switchHeight, Checked ? UITheme.Accent : UITheme.SurfaceMuted);
DrawRectangle(switchX, switchY, switchWidth, switchHeight, Checked ? UITheme.AccentDark : UITheme.SurfaceBorder);
int knobY = switchY + ((switchHeight - knobSize) / 2);
DrawFilledRectangle((int)knobX + 1, knobY, knobSize, knobSize, Color.White);
DrawRectangle((int)knobX + 1, knobY, knobSize, knobSize, UITheme.SurfaceBorder);
DrawString(Text, Foreground, textX, textY);

View File

@@ -82,7 +82,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _background = Color.LightGray;
private Color _background = UITheme.Surface;
internal Color Background
{
get
@@ -96,7 +96,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _foreground = Color.Black;
private Color _foreground = UITheme.TextPrimary;
internal Color Foreground
{
get
@@ -110,7 +110,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _border = Color.Gray;
private Color _border = UITheme.SurfaceBorder;
internal Color Border
{
get
@@ -124,7 +124,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _selectedBackground = Color.FromArgb(221, 246, 255);
private Color _selectedBackground = UITheme.AccentLight;
internal Color SelectedBackground
{
get
@@ -138,7 +138,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _selectedForeground = Color.Black;
private Color _selectedForeground = UITheme.TextPrimary;
internal Color SelectedForeground
{
get
@@ -152,7 +152,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _selectedBorder = Color.FromArgb(126, 205, 234);
private Color _selectedBorder = UITheme.Accent;
internal Color SelectedBorder
{
get
@@ -258,7 +258,7 @@ namespace CMLeonOS.Gui.UILib
if (CanScrollUp || CanScrollDown)
{
/* Background */
DrawFilledRectangle(Width - _scrollbarThickness, 0, _scrollbarThickness, Height, _border);
DrawFilledRectangle(Width - _scrollbarThickness, 0, _scrollbarThickness, Height, UITheme.SurfaceMuted);
/* Track */
int trackAvailableHeight = Height - (ScrollbarThickness * 2);
@@ -266,22 +266,22 @@ namespace CMLeonOS.Gui.UILib
double trackProgress = (double)scrollY / (double)((Cells.Count * CellHeight) - Height);
int trackY = (int)(_scrollbarThickness + (((double)trackAvailableHeight - ((double)trackAvailableHeight * trackSize)) * trackProgress));
// Border
DrawFilledRectangle(Width - _scrollbarThickness, 0, _scrollbarThickness, Height, _border);
DrawFilledRectangle(Width - _scrollbarThickness, 0, _scrollbarThickness, Height, UITheme.SurfaceBorder);
// Background
DrawFilledRectangle(Width - _scrollbarThickness + 1, trackY + 1, _scrollbarThickness - 2, (int)(trackSize * trackAvailableHeight) - 2, _background);
DrawFilledRectangle(Width - _scrollbarThickness + 1, trackY + 1, _scrollbarThickness - 2, (int)(trackSize * trackAvailableHeight) - 2, UITheme.AccentLight);
/* Up arrow */
// Border
DrawFilledRectangle(Width - _scrollbarThickness, 0, _scrollbarThickness, _scrollbarThickness, _border);
DrawFilledRectangle(Width - _scrollbarThickness, 0, _scrollbarThickness, _scrollbarThickness, UITheme.SurfaceBorder);
// Background
DrawFilledRectangle(Width - _scrollbarThickness + 1, 1, _scrollbarThickness - 2, _scrollbarThickness - 2, CanScrollUp ? _background : _border);
DrawFilledRectangle(Width - _scrollbarThickness + 1, 1, _scrollbarThickness - 2, _scrollbarThickness - 2, CanScrollUp ? UITheme.Surface : UITheme.SurfaceMuted);
DrawImageAlpha(scrollbarUpBitmap, (int)((Width - _scrollbarThickness) + ((_scrollbarThickness / 2) - (scrollbarUpBitmap.Width / 2))), (int)((_scrollbarThickness / 2) - (scrollbarUpBitmap.Height / 2)));
/* Down arrow */
// Border
DrawFilledRectangle(Width - _scrollbarThickness, Height - _scrollbarThickness, _scrollbarThickness, _scrollbarThickness, _border);
DrawFilledRectangle(Width - _scrollbarThickness, Height - _scrollbarThickness, _scrollbarThickness, _scrollbarThickness, UITheme.SurfaceBorder);
// Background
DrawFilledRectangle(Width - _scrollbarThickness + 1, Height - _scrollbarThickness + 1, _scrollbarThickness - 2, _scrollbarThickness - 2, CanScrollDown ? _background : _border);
DrawFilledRectangle(Width - _scrollbarThickness + 1, Height - _scrollbarThickness + 1, _scrollbarThickness - 2, _scrollbarThickness - 2, CanScrollDown ? UITheme.Surface : UITheme.SurfaceMuted);
DrawImageAlpha(scrollbarDownBitmap, (int)((Width - _scrollbarThickness) + ((_scrollbarThickness / 2) - (scrollbarUpBitmap.Width / 2))), (int)((Height - _scrollbarThickness) + ((_scrollbarThickness / 2) - (scrollbarUpBitmap.Height / 2))));
}
}
@@ -344,7 +344,8 @@ namespace CMLeonOS.Gui.UILib
{
TableCell cell = Cells[i];
bool selected = _selectedCellIndex == i;
Rectangle cellRect = new Rectangle(0, (int)((i * _cellHeight) - scrollY), Width, _cellHeight);
int contentWidth = Width - ((CanScrollUp || CanScrollDown) ? _scrollbarThickness : 0);
Rectangle cellRect = new Rectangle(0, (int)((i * _cellHeight) - scrollY), contentWidth, _cellHeight);
if (cellRect.Y < -cellRect.Height || cellRect.Y > Height)
{
@@ -368,7 +369,7 @@ namespace CMLeonOS.Gui.UILib
switch (_textAlignment)
{
case Alignment.Start:
textX = cellRect.X + (cell.Image != null ? (CellHeight - FontData.Height) / 2 : 0);
textX = cellRect.X + 6 + (cell.Image != null ? (CellHeight - FontData.Height) / 2 : 0);
break;
case Alignment.Middle:
textX = cellRect.X + (cellRect.Width / 2) - (cell.Text.Length * FontData.Width / 2);
@@ -385,8 +386,8 @@ namespace CMLeonOS.Gui.UILib
if (cell.Image != null)
{
textX += (int)cell.Image.Width;
DrawImageAlpha(cell.Image, cellRect.X, (int)(cellRect.Y + (cellRect.Height / 2) - (cell.Image.Height / 2)));
textX += (int)cell.Image.Width + 6;
DrawImageAlpha(cell.Image, cellRect.X + 4, (int)(cellRect.Y + (cellRect.Height / 2) - (cell.Image.Height / 2)));
}
if (cell.ForegroundColourOverride != null)
@@ -397,6 +398,8 @@ namespace CMLeonOS.Gui.UILib
{
DrawString(cell.Text, selected ? SelectedForeground : Foreground, textX, textY);
}
DrawHorizontalLine(cellRect.Width - 2, 1, cellRect.Y + cellRect.Height - 1, UITheme.SurfaceBorder);
}
//DrawString($"{scrollY.ToString()} {dragging.ToString()} {scrollMax.ToString()}", Color.Red, 0, 0);

View File

@@ -87,7 +87,7 @@ namespace CMLeonOS.Gui.UILib
internal bool Shield { get; set; } = false;
private Color _background = Color.White;
private Color _background = UITheme.Surface;
internal Color Background
{
get
@@ -103,7 +103,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _foreground = Color.Black;
private Color _foreground = UITheme.TextPrimary;
internal Color Foreground
{
get
@@ -118,7 +118,7 @@ namespace CMLeonOS.Gui.UILib
}
}
private Color _placeholderForeground = Color.Gray;
private Color _placeholderForeground = UITheme.TextSecondary;
internal Color PlaceholderForeground
{
get
@@ -339,6 +339,7 @@ namespace CMLeonOS.Gui.UILib
private const int fontWidth = 8;
private const int fontHeight = 16;
private const int horizontalPadding = 4;
private int caretLine = -1;
private int caretCol = 0;
@@ -364,12 +365,12 @@ namespace CMLeonOS.Gui.UILib
if (Text == string.Empty)
{
DrawRectangle(0, 0, Width, Height, Color.Gray);
DrawString(PlaceholderText, PlaceholderForeground, 0, 0);
DrawRectangle(0, 0, Width, Height, caretLine == -1 ? UITheme.SurfaceBorder : UITheme.AccentDark);
DrawString(PlaceholderText, PlaceholderForeground, horizontalPadding, 2);
if (caretLine == 0 && cursorVisible)
{
DrawVerticalLine(fontHeight, 1, 0, Foreground);
DrawVerticalLine(fontHeight, horizontalPadding, 2, Foreground);
}
WM.Update(this);
@@ -392,11 +393,11 @@ namespace CMLeonOS.Gui.UILib
if (i < lines.Count)
{
string lineText = Shield ? new string('*', lines[i].Length) : lines[i];
RenderLine(i, lineText, lineY, -scrollX);
RenderLine(i, lineText, lineY + 2, horizontalPadding - scrollX);
if (caretLine == i && cursorVisible)
{
DrawVerticalLine(fontHeight, ((caretCol * fontWidth) - scrollX) + 1, (caretLine * fontHeight) - scrollY, Foreground);
DrawVerticalLine(fontHeight, ((caretCol * fontWidth) - scrollX) + horizontalPadding, ((caretLine * fontHeight) - scrollY) + 2, Foreground);
}
}
}
@@ -404,7 +405,7 @@ namespace CMLeonOS.Gui.UILib
markedLinesBegin = -1;
markedLinesEnd = -1;
DrawRectangle(0, 0, Width, Height, Color.Gray);
DrawRectangle(0, 0, Width, Height, caretLine == -1 ? UITheme.SurfaceBorder : UITheme.AccentDark);
WM.Update(this);
}

42
Gui/UILib/UITheme.cs Normal file
View File

@@ -0,0 +1,42 @@
// The CMLeonOS Project (https://github.com/Leonmmcoset/CMLeonOS)
// Copyright (C) 2025-present LeonOS 2 Developer Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
using System.Drawing;
namespace CMLeonOS.Gui.UILib
{
internal static class UITheme
{
internal static readonly Color WindowTitleBackground = Color.FromArgb(26, 34, 46);
internal static readonly Color WindowTitleTopHighlight = Color.FromArgb(52, 67, 90);
internal static readonly Color WindowTitleBottomBorder = Color.FromArgb(14, 18, 26);
internal static readonly Color WindowTitleText = Color.FromArgb(239, 244, 252);
internal static readonly Color WindowButtonBackground = Color.FromArgb(38, 49, 66);
internal static readonly Color Surface = Color.FromArgb(245, 248, 252);
internal static readonly Color SurfaceMuted = Color.FromArgb(228, 235, 245);
internal static readonly Color SurfaceBorder = Color.FromArgb(149, 164, 183);
internal static readonly Color TextPrimary = Color.FromArgb(33, 43, 56);
internal static readonly Color TextSecondary = Color.FromArgb(96, 109, 128);
internal static readonly Color Accent = Color.FromArgb(45, 117, 222);
internal static readonly Color AccentDark = Color.FromArgb(28, 89, 184);
internal static readonly Color AccentLight = Color.FromArgb(204, 225, 255);
internal static readonly Color Success = Color.FromArgb(45, 152, 99);
internal static readonly Color Warning = Color.FromArgb(210, 139, 54);
}
}