mirror of
https://github.com/Stone-Red-Code/RemSox.git
synced 2026-09-04 09:06:23 +02:00
214 lines
6.4 KiB
C#
214 lines
6.4 KiB
C#
using Cosmos.Kernel.System.Graphics;
|
|
|
|
using RemSox.Processing;
|
|
using RemSox.UI.GUI.Layout;
|
|
using RemSox.UI.GUI.Rendering;
|
|
using RemSox.UI.GUI.UIEelements.Controls;
|
|
using RemSox.UI.GUI.Windows;
|
|
|
|
using System.Drawing;
|
|
|
|
namespace RemSox.Processes;
|
|
|
|
internal class DesktopProcess() : Process("Desktop Manager")
|
|
{
|
|
private static bool isGraphicsInitialized = false;
|
|
|
|
private static readonly (string Name, Func<int> Spawn)[] AvailableApps = [
|
|
("Terminal", () => ProcessManager.SpawnProcess<TerminalProcess>()),
|
|
("Test Process",() => ProcessManager.SpawnProcess<TestProcess>()),
|
|
("YesNt", () => ProcessManager.SpawnProcess<YesNtInterpreterProcess>()),
|
|
];
|
|
|
|
private Window taskbar = null!;
|
|
private Window? startMenu;
|
|
private Button startButton = null!;
|
|
|
|
private readonly List<(int WindowId, Button Button)> windowButtons = [];
|
|
private int tickCount;
|
|
|
|
internal override void Start(string[] args)
|
|
{
|
|
if (!isGraphicsInitialized)
|
|
{
|
|
WindowManager.AddRenderSource(new CanvasRenderSource());
|
|
isGraphicsInitialized = true;
|
|
}
|
|
|
|
WindowManager.InvalidateAll();
|
|
CreateTaskbar();
|
|
}
|
|
|
|
private void CreateTaskbar()
|
|
{
|
|
Canvas canvas = FullScreenCanvas.GetFullScreenCanvas();
|
|
int screenW = (int)canvas.Mode.Width;
|
|
int screenH = (int)canvas.Mode.Height;
|
|
const int taskbarH = 36;
|
|
|
|
taskbar = WindowManager.CreateWindow(this, "Taskbar",
|
|
new Size(screenW, taskbarH),
|
|
new Point(0, screenH - taskbarH));
|
|
taskbar.HasChrome = false;
|
|
taskbar.IsResizable = false;
|
|
taskbar.IsDraggable = false;
|
|
taskbar.ZIndex = int.MaxValue;
|
|
taskbar.AutoFlush = true;
|
|
|
|
startButton = taskbar.CreateUIElement<Button>(b =>
|
|
{
|
|
b.Position = new Point(2, 2);
|
|
b.Size = new Size(50, taskbarH - 4);
|
|
b.Text = "Start";
|
|
b.BackgroundColor = Color.FromArgb(0, 100, 180);
|
|
b.TextColor = Color.White;
|
|
});
|
|
|
|
startButton.OnClick += (_, _) => ToggleStartMenu();
|
|
}
|
|
|
|
private void ToggleStartMenu()
|
|
{
|
|
if (startMenu is not null)
|
|
{
|
|
WindowManager.CloseWindow(startMenu);
|
|
startMenu = null;
|
|
return;
|
|
}
|
|
|
|
Canvas canvas = FullScreenCanvas.GetFullScreenCanvas();
|
|
int screenH = (int)canvas.Mode.Height;
|
|
int menuW = 150;
|
|
int itemH = 22;
|
|
int menuH = (AvailableApps.Length * itemH) + 10;
|
|
int menuX = 2;
|
|
int menuY = screenH - 36 - menuH;
|
|
|
|
startMenu = WindowManager.CreateWindow(this, "Start Menu",
|
|
new Size(menuW, menuH),
|
|
new Point(menuX, menuY));
|
|
startMenu.HasChrome = false;
|
|
startMenu.IsResizable = false;
|
|
startMenu.IsDraggable = false;
|
|
startMenu.ZIndex = int.MaxValue - 1;
|
|
startMenu.AutoFlush = true;
|
|
|
|
StackLayout stack = startMenu.CreateStackLayout(5, 5, 2);
|
|
stack.UniformWidth = menuW - 10;
|
|
|
|
foreach ((string? name, Func<int>? spawn) in AvailableApps)
|
|
{
|
|
Button appBtn = stack.Add<Button>(b =>
|
|
{
|
|
b.Size = new Size(menuW - 10, itemH);
|
|
b.Text = name;
|
|
b.BackgroundColor = Color.FromArgb(60, 60, 65);
|
|
b.TextColor = Color.White;
|
|
});
|
|
|
|
appBtn.OnClick += (_, _) =>
|
|
{
|
|
_ = spawn();
|
|
WindowManager.CloseWindow(startMenu);
|
|
startMenu = null;
|
|
};
|
|
}
|
|
}
|
|
|
|
internal override void Tick()
|
|
{
|
|
WindowManager.Update();
|
|
|
|
if (tickCount % 5 == 0)
|
|
{
|
|
UpdateWindowButtons();
|
|
}
|
|
|
|
tickCount++;
|
|
|
|
if (!ProcessManager.IsProcessRunning<TerminalProcess>())
|
|
{
|
|
_ = ProcessManager.SpawnProcess<TerminalProcess>();
|
|
}
|
|
}
|
|
|
|
private void UpdateWindowButtons()
|
|
{
|
|
List<Window> allWindows = WindowManager.GetAllWindows()
|
|
.Where(w => w != taskbar && w != startMenu && w.HasChrome)
|
|
.ToList();
|
|
|
|
// Build lookup of current window IDs
|
|
HashSet<int> currentIds = [];
|
|
foreach (Window w in allWindows)
|
|
{
|
|
_ = currentIds.Add(w.Id);
|
|
}
|
|
|
|
// Remove buttons for windows that no longer exist
|
|
for (int i = windowButtons.Count - 1; i >= 0; i--)
|
|
{
|
|
(int winId, Button btn) = windowButtons[i];
|
|
if (!currentIds.Contains(winId))
|
|
{
|
|
taskbar.RemoveUIElement(btn.Id);
|
|
windowButtons.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
// Build lookup of existing tracked windows
|
|
Dictionary<int, Button> tracked = [];
|
|
foreach (var (winId, btn) in windowButtons)
|
|
{
|
|
tracked[winId] = btn;
|
|
}
|
|
|
|
// Add new buttons and reposition everything in one pass
|
|
int btnX = 56;
|
|
windowButtons.Clear();
|
|
foreach (Window win in allWindows)
|
|
{
|
|
if (tracked.TryGetValue(win.Id, out Button? existing))
|
|
{
|
|
// Reposition existing button
|
|
existing.Position = new Point(btnX, 2);
|
|
}
|
|
else
|
|
{
|
|
// Create new button
|
|
existing = taskbar.CreateUIElement<Button>(b =>
|
|
{
|
|
b.Position = new Point(btnX, 2);
|
|
b.Size = new Size(100, 32);
|
|
b.Text = TruncateTitle(win.Title, 12);
|
|
b.BackgroundColor = Color.FromArgb(55, 55, 60);
|
|
b.TextColor = Color.White;
|
|
});
|
|
|
|
int capturedId = win.Id;
|
|
existing.OnClick += (_, _) =>
|
|
{
|
|
Window? target = WindowManager.GetAllWindows().FirstOrDefault(w => w.Id == capturedId);
|
|
if (target is not null)
|
|
{
|
|
WindowManager.FocusWindow(target);
|
|
}
|
|
};
|
|
}
|
|
|
|
// Update highlight for focused window
|
|
existing.BackgroundColor = win.IsFocused
|
|
? Color.FromArgb(0, 90, 160)
|
|
: Color.FromArgb(55, 55, 60);
|
|
|
|
windowButtons.Add((win.Id, existing));
|
|
btnX += 104;
|
|
}
|
|
}
|
|
|
|
private static string TruncateTitle(string title, int maxLen)
|
|
{
|
|
return title.Length <= maxLen ? title : title[..(maxLen - 1)] + "\u2026";
|
|
}
|
|
}
|