mirror of
https://github.com/Stone-Red-Code/RemSox.git
synced 2026-09-04 09:06:23 +02:00
Implement z-index for windows and ensure correct stacking order on interaction
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cosmos.Kernel.System.Graphics;
|
||||
|
||||
namespace RemSox.UI.GUI.Rendering;
|
||||
@@ -9,11 +10,20 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
{
|
||||
private static readonly Dictionary<int, Canvas> windowCanvases = new();
|
||||
private static readonly Dictionary<int, Point> windowPositions = new();
|
||||
private static readonly Dictionary<int, int> windowZIndices = new();
|
||||
|
||||
public void Render(IEnumerable<RenderCommand> commands)
|
||||
{
|
||||
foreach (RenderCommand command in commands)
|
||||
{
|
||||
if (command.ElementType == "Window" || command.ElementType == "WindowMove")
|
||||
{
|
||||
if (command.Properties.TryGetValue("ZIndex", out object? rawZIndex) && rawZIndex is int z)
|
||||
{
|
||||
windowZIndices[command.WindowId] = z;
|
||||
}
|
||||
}
|
||||
|
||||
if (command.ElementType == "Window")
|
||||
{
|
||||
Size size = command.Properties.TryGetValue("Size", out object? rawSize) && rawSize is Size windowSize
|
||||
@@ -59,11 +69,11 @@ public sealed class CanvasRenderSource : IRenderSource
|
||||
{
|
||||
screenCanvas.Clear(Color.Black);
|
||||
|
||||
foreach (var kvp in windowPositions)
|
||||
var orderedWindows = windowPositions.Keys.OrderBy(id => windowZIndices.TryGetValue(id, out int z) ? z : 0);
|
||||
|
||||
foreach (var windowId in orderedWindows)
|
||||
{
|
||||
int windowId = kvp.Key;
|
||||
Point position = kvp.Value;
|
||||
if (windowCanvases.TryGetValue(windowId, out Canvas? windowCanvas))
|
||||
if (windowPositions.TryGetValue(windowId, out Point position) && windowCanvases.TryGetValue(windowId, out Canvas? windowCanvas))
|
||||
{
|
||||
screenCanvas.DrawCanvas(windowCanvas, position.X, position.Y);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
|
||||
public string Title { get; set; } = title;
|
||||
|
||||
public int ZIndex { get; set; }
|
||||
|
||||
public bool AutoFlush { get; set; } = false;
|
||||
|
||||
public bool IsFocused
|
||||
@@ -51,6 +53,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
private Size lastRenderedSize = new Size(-1, -1);
|
||||
private bool lastRenderedIsFocused = false;
|
||||
private string lastRenderedTitle = string.Empty;
|
||||
private int lastRenderedZIndex = -1;
|
||||
private bool isFirstRender = true;
|
||||
|
||||
public T CreateUIElement<T>(Action<T>? options = null) where T : UIElement, new()
|
||||
@@ -92,6 +95,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
bool windowStateChanged = isFirstRender || Size != lastRenderedSize || IsFocused != lastRenderedIsFocused || Title != lastRenderedTitle;
|
||||
bool anyChildChanged = uiElements.Values.Any(e => e.AnyPropertyChanged);
|
||||
bool positionChanged = Position != lastRenderedPosition;
|
||||
bool zIndexChanged = ZIndex != lastRenderedZIndex;
|
||||
|
||||
bool fullRedraw = windowStateChanged || anyChildChanged;
|
||||
|
||||
@@ -111,7 +115,8 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
[nameof(Size)] = Size,
|
||||
[nameof(IsFocused)] = IsFocused,
|
||||
[nameof(IsResizable)] = IsResizable,
|
||||
[nameof(IsDraggable)] = IsDraggable
|
||||
[nameof(IsDraggable)] = IsDraggable,
|
||||
[nameof(ZIndex)] = ZIndex
|
||||
}
|
||||
});
|
||||
|
||||
@@ -128,7 +133,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
element.ClearChangedProperties();
|
||||
}
|
||||
}
|
||||
else if (positionChanged)
|
||||
else if (positionChanged || zIndexChanged)
|
||||
{
|
||||
commands.Add(new RenderCommand
|
||||
{
|
||||
@@ -136,7 +141,10 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
ElementId = Id,
|
||||
ElementType = "WindowMove",
|
||||
Position = Position,
|
||||
Properties = new Dictionary<string, object?>()
|
||||
Properties = new Dictionary<string, object?>
|
||||
{
|
||||
[nameof(ZIndex)] = ZIndex
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -147,6 +155,7 @@ public sealed class Window(string title, int processId, int id, IRenderSource re
|
||||
lastRenderedSize = Size;
|
||||
lastRenderedIsFocused = IsFocused;
|
||||
lastRenderedTitle = Title;
|
||||
lastRenderedZIndex = ZIndex;
|
||||
isFirstRender = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using RemSox.Processing;
|
||||
using RemSox.UI.GUI.Rendering;
|
||||
|
||||
@@ -12,6 +14,7 @@ public static class WindowManager
|
||||
private static readonly ConcurrentDictionary<int, List<Window>> windows = new();
|
||||
|
||||
private static int nextWindowId = 1;
|
||||
private static int nextZIndex = 1;
|
||||
|
||||
private static Window? focusedWindow;
|
||||
|
||||
@@ -26,7 +29,8 @@ public static class WindowManager
|
||||
Window window = new(title, process.Id, GetNextWindowId(), renderSource)
|
||||
{
|
||||
Position = position,
|
||||
Size = size
|
||||
Size = size,
|
||||
ZIndex = nextZIndex++
|
||||
};
|
||||
|
||||
if (!windows.ContainsKey(process.Id))
|
||||
@@ -69,6 +73,11 @@ public static class WindowManager
|
||||
return;
|
||||
}
|
||||
|
||||
if (window != null)
|
||||
{
|
||||
window.ZIndex = nextZIndex++;
|
||||
}
|
||||
|
||||
Window? previousFocusedWindow = focusedWindow;
|
||||
focusedWindow = window;
|
||||
|
||||
@@ -81,6 +90,19 @@ public static class WindowManager
|
||||
return focusedWindow == window;
|
||||
}
|
||||
|
||||
public static Window? TryBeginInteract(Point pointerPosition)
|
||||
{
|
||||
var allWindows = windows.Values.SelectMany(w => w).OrderByDescending(w => w.ZIndex);
|
||||
foreach (var window in allWindows)
|
||||
{
|
||||
if (window.TryBeginInteract(pointerPosition))
|
||||
{
|
||||
return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int GetNextWindowId()
|
||||
{
|
||||
return nextWindowId++;
|
||||
|
||||
Reference in New Issue
Block a user