GUI桌面环境

This commit is contained in:
2026-03-01 17:03:49 +08:00
parent 545f40cf95
commit f0a9223520
162 changed files with 9170 additions and 135 deletions

View File

@@ -0,0 +1,22 @@
using CMLeonOS;
using CMLeonOS.Gui.UILib;
namespace CMLeonOS.Gui.ShellComponents.Dock
{
internal class AppDockIcon : BaseDockIcon
{
internal AppDockIcon(AppWindow appWindow) : base(
image: appWindow.Icon,
doAnimation: true)
{
AppWindow = appWindow;
}
internal AppWindow AppWindow { get; init; }
internal override void Clicked()
{
ProcessManager.GetProcess<WindowManager>().Focus = AppWindow;
}
}
}

View File

@@ -0,0 +1,82 @@
using Cosmos.System.Graphics;
namespace CMLeonOS.Gui.ShellComponents.Dock
{
internal abstract class BaseDockIcon
{
internal BaseDockIcon(Bitmap image, bool doAnimation = true)
{
if (doAnimation)
{
Size = 1;
}
else
{
// Skip to the end of the animation.
Size = Dock.IconSize;
}
Image = image;
}
private double _size;
internal double Size
{
get
{
return _size;
}
set
{
_size = value;
if (_image != null)
{
SizedImage = _image.ResizeWidthKeepRatio((uint)Size);
}
}
}
private Bitmap _image;
internal Bitmap Image
{
get
{
return _image;
}
set
{
_image = value;
SizedImage = value.ResizeWidthKeepRatio((uint)Size);
}
}
internal Bitmap SizedImage { get; private set; }
internal bool Closing { get; set; } = false;
internal bool CloseAnimationComplete
{
get
{
return Closing && (int)_size == 1;
}
}
/// <summary>
/// Run the dock icon's animation.
/// </summary>
/// <returns>If the dock needs to be rerendered.</returns>
internal bool RunAnimation()
{
int oldSize = (int)Size;
int goalSize = Closing ? 1 : Dock.IconSize;
Size += (goalSize - Size) / 16;
return (int)Size != (int)oldSize;
}
internal abstract void Clicked();
}
}

View File

@@ -0,0 +1,190 @@
using Cosmos.System.Graphics;
using CMLeonOS;
using CMLeonOS.Gui.UILib;
using CMLeonOS.UILib.Animations;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace CMLeonOS.Gui.ShellComponents.Dock
{
internal class Dock : Process
{
internal Dock() : base("Dock", ProcessType.Application)
{
}
internal static Dock CurrentDock
{
get
{
Dock dock = ProcessManager.GetProcess<Dock>();
return dock;
}
}
Window window;
List<BaseDockIcon> Icons = new List<BaseDockIcon>();
WindowManager wm = ProcessManager.GetProcess<WindowManager>();
SettingsService settingsService = ProcessManager.GetProcess<SettingsService>();
internal static readonly int IconSize = 64;
internal static readonly int IconImageMaxSize = 48;
private void Render()
{
int newDockWidth = 0;
foreach (var icon in Icons)
{
newDockWidth += (int)icon.Size;
}
if (newDockWidth != window.Width)
{
window.MoveAndResize((int)(wm.ScreenWidth / 2 - newDockWidth / 2), window.Y, newDockWidth, window.Height);
}
window.Clear(Color.FromArgb(130, 202, 255));
int x = 0;
foreach (var icon in Icons)
{
if (icon.Image != null)
{
Bitmap resizedImage = icon.Image.ResizeWidthKeepRatio((uint)Math.Min(IconImageMaxSize, icon.Size));
int imageX = (int)(x + ((icon.Size / 2) - (resizedImage.Width / 2)));
window.DrawImageAlpha(resizedImage, imageX, (int)((window.Height / 2) - (resizedImage.Height / 2)));
}
x += (int)icon.Size;
}
wm.Update(window);
}
internal int GetDockHeight()
{
return window.Height;
}
internal void UpdateWindows()
{
// Add new windows and update icons.
foreach (var window in wm.Windows)
{
if (window is not AppWindow appWindow)
{
continue;
}
bool found = false;
foreach (BaseDockIcon icon in Icons)
{
if (icon is AppDockIcon appDockIcon && appDockIcon.AppWindow == appWindow)
{
icon.Image = appWindow.Icon;
found = true;
}
}
if (!found)
{
Icons.Add(new AppDockIcon(appWindow));
}
}
// Remove deleted windows.
foreach (BaseDockIcon icon in Icons)
{
if (icon is not AppDockIcon appDockIcon)
{
continue;
}
bool found = false;
foreach (Window window in wm.Windows)
{
if (window == appDockIcon.AppWindow)
{
found = true;
}
}
if (!found)
{
icon.Closing = true;
}
}
Render();
}
private void DockClick(int x, int y)
{
int end = 0;
foreach (var icon in Icons)
{
end += (int)icon.Size;
if (x < end)
{
icon.Clicked();
return;
}
}
}
public override void Start()
{
base.Start();
window = new Window(this, (int)(wm.ScreenWidth / 2), (int)(wm.ScreenHeight + IconSize), IconSize, IconSize);
window.OnClick = DockClick;
wm.AddWindow(window);
Icons.Add(new StartMenuDockIcon());
Render();
MovementAnimation animation = new MovementAnimation(window)
{
From = new Rectangle(window.X, window.Y, window.Width, window.Height),
To = new Rectangle(window.X, (int)(wm.ScreenHeight - IconSize), window.Width, window.Height),
Duration = 10
};
animation.Start();
}
public override void Run()
{
bool rerenderNeeded = false;
for (int i = Icons.Count - 1; i >= 0; i--)
{
BaseDockIcon icon = Icons[i];
if (icon.RunAnimation())
{
rerenderNeeded = true;
}
if (icon.CloseAnimationComplete)
{
Icons.Remove(icon);
}
}
if (rerenderNeeded)
{
Render();
}
}
}
}

View File

@@ -0,0 +1,22 @@
using Cosmos.System.Graphics;
namespace CMLeonOS.Gui.ShellComponents.Dock
{
internal class StartMenuDockIcon : BaseDockIcon
{
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Dock.StartMenu.bmp")]
private static byte[] _iconBytes_StartMenu;
internal static Bitmap Icon_StartMenu = new Bitmap(_iconBytes_StartMenu);
internal StartMenuDockIcon() : base(
image: Icon_StartMenu,
doAnimation: false)
{
}
internal override void Clicked()
{
StartMenu.CurrentStartMenu.ToggleStartMenu();
}
}
}