mirror of
https://github.com/Stone-Red-Code/RemSox.git
synced 2026-09-04 00:56:19 +02:00
Add windowed terminal, basic text, rectangle rendering, and keyboard events
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cosmos.Kernel.System.Graphics;
|
||||
using Cosmos.Kernel.System.Graphics.Fonts;
|
||||
|
||||
namespace RemSox.UI.GUI.Rendering;
|
||||
|
||||
@@ -12,15 +13,32 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
private static readonly Dictionary<int, Point> windowPositions = new();
|
||||
private static readonly Dictionary<int, int> windowZIndices = new();
|
||||
|
||||
private static bool isDirty = true;
|
||||
private static Point lastPointerPosition = new Point(-1, -1);
|
||||
private static List<int> orderedWindowsCache = new();
|
||||
private static bool isZOrderDirty = true;
|
||||
|
||||
public void Render(IEnumerable<RenderCommand> commands)
|
||||
{
|
||||
bool changed = false;
|
||||
foreach (RenderCommand command in commands)
|
||||
{
|
||||
changed = true;
|
||||
if (command.ElementType == "WindowClose")
|
||||
{
|
||||
windowCanvases.Remove(command.WindowId);
|
||||
windowPositions.Remove(command.WindowId);
|
||||
windowZIndices.Remove(command.WindowId);
|
||||
isZOrderDirty = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.ElementType == "Window" || command.ElementType == "WindowMove")
|
||||
{
|
||||
if (command.Properties.TryGetValue("ZIndex", out object? rawZIndex) && rawZIndex is int z)
|
||||
{
|
||||
windowZIndices[command.WindowId] = z;
|
||||
isZOrderDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,14 +48,14 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
? windowSize
|
||||
: new Size(160, 120);
|
||||
|
||||
if (!windowCanvases.TryGetValue(command.WindowId, out Canvas? currentCanvas) ||
|
||||
currentCanvas.Mode.Width != size.Width ||
|
||||
if (!windowCanvases.TryGetValue(command.WindowId, out Canvas? currentCanvas) ||
|
||||
currentCanvas.Mode.Width != size.Width ||
|
||||
currentCanvas.Mode.Height != size.Height)
|
||||
{
|
||||
windowCanvases[command.WindowId] = new Canvas(size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!windowCanvases.ContainsKey(command.WindowId))
|
||||
{
|
||||
windowCanvases[command.WindowId] = new Canvas(160, 120);
|
||||
@@ -62,16 +80,40 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
{
|
||||
RenderCircle(windowCanvas, command);
|
||||
}
|
||||
|
||||
if (command.ElementType == "Rectangle")
|
||||
{
|
||||
RenderRectangle(windowCanvas, command);
|
||||
}
|
||||
|
||||
if (command.ElementType == "Text")
|
||||
{
|
||||
RenderText(windowCanvas, command);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CompositeAndDisplay(Canvas screenCanvas, Point pointerPosition)
|
||||
{
|
||||
screenCanvas.Clear(Color.Black);
|
||||
if (!isDirty && pointerPosition == lastPointerPosition)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var orderedWindows = windowPositions.Keys.OrderBy(id => windowZIndices.TryGetValue(id, out int z) ? z : 0);
|
||||
if (isZOrderDirty)
|
||||
{
|
||||
orderedWindowsCache = windowPositions.Keys.OrderBy(id => windowZIndices.TryGetValue(id, out int z) ? z : 0).ToList();
|
||||
isZOrderDirty = false;
|
||||
}
|
||||
|
||||
foreach (var windowId in orderedWindows)
|
||||
//screenCanvas.Clear(Color.Black);
|
||||
|
||||
foreach (var windowId in orderedWindowsCache)
|
||||
{
|
||||
if (windowPositions.TryGetValue(windowId, out Point position) && windowCanvases.TryGetValue(windowId, out Canvas? windowCanvas))
|
||||
{
|
||||
@@ -81,6 +123,9 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
|
||||
screenCanvas.DrawFilledCircle(Color.White, pointerPosition.X, pointerPosition.Y, 5);
|
||||
screenCanvas.Display();
|
||||
|
||||
lastPointerPosition = pointerPosition;
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
private static void RenderWindow(Canvas canvas, RenderCommand command)
|
||||
@@ -115,4 +160,42 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
|
||||
canvas.DrawFilledCircle(color, centerX, centerY, radius);
|
||||
}
|
||||
|
||||
private static void RenderRectangle(Canvas canvas, RenderCommand command)
|
||||
{
|
||||
Color color = command.Properties.TryGetValue("Color", out object? rawColor) && rawColor is Color rectColor
|
||||
? rectColor
|
||||
: Color.White;
|
||||
|
||||
Size size = command.Properties.TryGetValue("Size", out object? rawSize) && rawSize is Size rectSize
|
||||
? rectSize
|
||||
: new Size(10, 10);
|
||||
|
||||
bool isFilled = command.Properties.TryGetValue("IsFilled", out object? rawFilled) && rawFilled is bool filled && filled;
|
||||
|
||||
if (isFilled)
|
||||
{
|
||||
canvas.DrawFilledRectangle(color, command.Position.X, command.Position.Y, size.Width, size.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas.DrawRectangle(color, command.Position.X, command.Position.Y, size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderText(Canvas canvas, RenderCommand command)
|
||||
{
|
||||
Color color = command.Properties.TryGetValue("Color", out object? rawColor) && rawColor is Color textColor
|
||||
? textColor
|
||||
: Color.White;
|
||||
|
||||
string content = command.Properties.TryGetValue("Content", out object? rawContent) && rawContent is string textContent
|
||||
? textContent
|
||||
: string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(content))
|
||||
{
|
||||
canvas.DrawString(content, Cosmos.Kernel.System.Graphics.Fonts.PCScreenFont.DefaultFont, color, command.Position.X, command.Position.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace RemSox.UI.GUI.UIEelements.Shapes;
|
||||
|
||||
public class Rectangle() : Shape("Rectangle")
|
||||
{
|
||||
public Size Size
|
||||
{
|
||||
get;
|
||||
set => SetProperty(nameof(Size), ref field, value);
|
||||
}
|
||||
|
||||
public bool IsFilled
|
||||
{
|
||||
get;
|
||||
set => SetProperty(nameof(IsFilled), ref field, value);
|
||||
} = true;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace RemSox.UI.GUI.UIEelements;
|
||||
|
||||
public class Text() : UIElement("Text")
|
||||
{
|
||||
public string Content
|
||||
{
|
||||
get;
|
||||
set => SetProperty(nameof(Content), ref field, value);
|
||||
} = string.Empty;
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get;
|
||||
set => SetProperty(nameof(Color), ref field, value);
|
||||
} = Color.White;
|
||||
}
|
||||
@@ -18,6 +18,13 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
|
||||
public bool AutoFlush { get; set; } = false;
|
||||
|
||||
public event Action<Cosmos.Kernel.System.Keyboard.KeyEvent>? OnKeyEvent;
|
||||
|
||||
public void HandleKeyEvent(Cosmos.Kernel.System.Keyboard.KeyEvent keyEvent)
|
||||
{
|
||||
OnKeyEvent?.Invoke(keyEvent);
|
||||
}
|
||||
|
||||
public bool IsFocused
|
||||
{
|
||||
get => WindowManager.IsWindowFocused(this);
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Drawing;
|
||||
using System.Linq;
|
||||
using Cosmos.Kernel.System.Graphics;
|
||||
using Cosmos.Kernel.System.Mouse;
|
||||
using Cosmos.Kernel.System.Keyboard;
|
||||
using RemSox.Processing;
|
||||
using RemSox.UI.GUI.Rendering;
|
||||
|
||||
@@ -51,6 +52,11 @@ public static class WindowManager
|
||||
|
||||
wasLeftButtonDown = leftButtonDown;
|
||||
|
||||
if (KeyboardManager.TryReadKey(out KeyEvent keyEvent))
|
||||
{
|
||||
focusedWindow?.HandleKeyEvent(keyEvent);
|
||||
}
|
||||
|
||||
Canvas canvas = FullScreenCanvas.GetFullScreenCanvas();
|
||||
CanvasRenderSource.CompositeAndDisplay(canvas, pointerPosition);
|
||||
|
||||
@@ -86,6 +92,8 @@ public static class WindowManager
|
||||
{
|
||||
processWindows.Remove(window);
|
||||
}
|
||||
|
||||
renderSource.Render(new[] { new RenderCommand { WindowId = window.Id, ElementId = window.Id, ElementType = "WindowClose", Position = window.Position, Properties = new Dictionary<string, object?>() } });
|
||||
}
|
||||
|
||||
public static List<Window> GetWindowsForProcess(Process process)
|
||||
|
||||
Reference in New Issue
Block a user