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,89 @@
using CMLeonOS.Gui.UILib;
using System.Collections.Generic;
using System.Drawing;
namespace CMLeonOS.Gui.Apps.Paint
{
internal class ColourPicker : Window
{
private Paint paintInstance;
private Table table;
internal readonly List<Color> Colours = new List<Color>()
{
Color.Black,
Color.White,
Color.Red,
Color.Blue,
Color.Orange,
Color.Green,
Color.Pink,
Color.Gray,
Color.Purple,
Color.DarkGoldenrod,
Color.DarkGray,
Color.DarkGreen,
Color.DarkCyan,
Color.Cyan,
Color.BlueViolet,
Color.AliceBlue,
Color.Brown,
Color.CornflowerBlue,
Color.Azure,
Color.Beige,
Color.DarkBlue,
Color.DarkSlateBlue,
Color.SeaGreen
};
private void TableClicked(int x, int y)
{
// Clear 'Selected' text on previously selected colour.
foreach (var cell in table.Cells)
{
cell.Text = string.Empty;
}
var selectedCell = table.Cells[table.SelectedCellIndex];
Color color = (Color)selectedCell.Tag;
paintInstance.SelectedColor = color;
selectedCell.Text = "Selected";
table.Render();
}
internal ColourPicker(Paint paint, int x, int y, int width, int height) : base(paint, x, y, width, height)
{
paintInstance = paint;
Clear(Color.FromArgb(107, 107, 107));
DrawString("Colours", Color.White, 8, 8);
table = new Table(this, 0, 32, Width, Height - 32);
table.AllowDeselection = false;
table.CellHeight = 20;
table.TextAlignment = Alignment.Middle;
table.OnClick = TableClicked;
foreach (Color colour in Colours)
{
TableCell cell = new(string.Empty, tag: colour);
cell.BackgroundColourOverride = colour;
cell.ForegroundColourOverride = colour.GetForegroundColour();
if (colour == paint.SelectedColor)
{
cell.Text = "Selected";
}
table.Cells.Add(cell);
}
table.Render();
WM.AddWindow(this);
WM.AddWindow(table);
}
}
}

88
Gui/Apps/Paint/Paint.cs Normal file
View File

@@ -0,0 +1,88 @@
using Cosmos.System;
using CMLeonOS;
using CMLeonOS.Gui.UILib;
using System.Drawing;
namespace CMLeonOS.Gui.Apps.Paint
{
internal class Paint : Process
{
internal Paint() : base("Paint", ProcessType.Application)
{
}
AppWindow window;
Window canvas;
ToolBox toolBox;
ColourPicker colourPicker;
WindowManager wm = ProcessManager.GetProcess<WindowManager>();
private bool down = false;
internal Color SelectedColor { get; set; } = Color.Black;
internal bool IsInBounds(int x, int y)
{
if (x >= canvas.Width || y >= canvas.Height) return false;
if (x < 0 || y < 0) return false;
return true;
}
private void CanvasDown(int x, int y)
{
down = true;
}
public override void Start()
{
base.Start();
window = new AppWindow(this, 256, 256, 768, 448);
window.Title = "Paint";
window.Icon = AppManager.GetAppMetadata("Paint").Icon;
window.Closing = TryStop;
window.Clear(Color.FromArgb(73, 73, 73));
wm.AddWindow(window);
int canvasWidth = 384;
int canvasHeight = 256;
canvas = new Window(this, (window.Width / 2) - (canvasWidth / 2), (window.Height / 2) - (canvasHeight / 2), canvasWidth, canvasHeight);
canvas.RelativeTo = window;
canvas.OnDown = CanvasDown;
canvas.Clear(Color.White);
wm.AddWindow(canvas);
toolBox = new ToolBox(this, 0, 0, 128, window.Height);
toolBox.RelativeTo = window;
colourPicker = new ColourPicker(this, window.Width - 128, 0, 128, window.Height);
colourPicker.RelativeTo = window;
wm.Update(window);
}
public override void Run()
{
if (down)
{
if (MouseManager.MouseState == MouseState.None)
{
down = false;
}
toolBox.SelectedTool.Run(
this,
canvas,
MouseManager.MouseState,
(int)(MouseManager.X - canvas.ScreenX),
(int)(MouseManager.Y - canvas.ScreenY)
);
wm.Update(canvas);
}
}
}
}

24
Gui/Apps/Paint/Tool.cs Normal file
View File

@@ -0,0 +1,24 @@
using Cosmos.System;
namespace CMLeonOS.Gui.Apps.Paint
{
internal abstract class Tool
{
internal Tool(string name)
{
Name = name;
}
internal abstract void Run(Paint paint, Window canvas, MouseState mouseState, int mouseX, int mouseY);
internal virtual void Selected()
{
}
internal virtual void Deselected()
{
}
internal string Name { get; init; }
}
}

60
Gui/Apps/Paint/ToolBox.cs Normal file
View File

@@ -0,0 +1,60 @@
using CMLeonOS.Gui.UILib;
using System.Collections.Generic;
using System.Drawing;
namespace CMLeonOS.Gui.Apps.Paint
{
internal class ToolBox : Window
{
private Paint paintInstance;
private Table table;
internal Tool SelectedTool;
internal readonly List<Tool> Tools = new List<Tool>()
{
new Tools.Pencil(),
new Tools.CircleBrush()
};
private void TableClicked(int x, int y)
{
Tool tool = table.Cells[table.SelectedCellIndex].Tag as Tool;
if (tool != SelectedTool)
{
SelectedTool.Deselected();
SelectedTool = tool;
}
}
internal ToolBox(Paint paint, int x, int y, int width, int height) : base(paint, x, y, width, height)
{
paintInstance = paint;
Clear(Color.FromArgb(107, 107, 107));
DrawString("Toolbox", Color.White, 8, 8);
table = new Table(this, 0, 32, Width, Height - 32);
table.AllowDeselection = false;
table.CellHeight = 24;
table.TextAlignment = Alignment.Middle;
table.OnClick = TableClicked;
foreach (Tool tool in Tools)
{
table.Cells.Add(new TableCell(tool.Name, tool));
}
SelectedTool = Tools[0];
table.SelectedCellIndex = 0;
table.Render();
WM.AddWindow(this);
WM.AddWindow(table);
}
}
}

View File

@@ -0,0 +1,19 @@
using Cosmos.System;
namespace CMLeonOS.Gui.Apps.Paint.Tools
{
internal class CircleBrush : Tool
{
public CircleBrush() : base("Circle brush")
{
}
internal override void Run(Paint paint, Window canvas, MouseState mouseState, int mouseX, int mouseY)
{
if (mouseState == MouseState.Left)
{
canvas.DrawCircle(mouseX, mouseY, 5, paint.SelectedColor);
}
}
}
}

View File

@@ -0,0 +1,42 @@
using Cosmos.System;
namespace CMLeonOS.Gui.Apps.Paint.Tools
{
internal class Pencil : Tool
{
public Pencil() : base("Pencil")
{
}
private bool joinLine;
private int joinX;
private int joinY;
internal override void Run(Paint paint, Window canvas, MouseState mouseState, int mouseX, int mouseY)
{
if (mouseState == MouseState.Left)
{
if (joinLine)
{
canvas.DrawLine(joinX, joinY, mouseX, mouseY, paint.SelectedColor);
}
else
{
canvas.DrawPoint(mouseX, mouseY, paint.SelectedColor);
}
joinLine = true;
joinX = mouseX;
joinY = mouseY;
}
else
{
joinLine = false;
}
}
internal override void Deselected()
{
joinLine = false;
}
}
}