mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-03-03 15:30:27 +00:00
564 lines
15 KiB
C#
564 lines
15 KiB
C#
using Cosmos.Core;
|
|
using Cosmos.System;
|
|
using Cosmos.System.Graphics;
|
|
using CMLeonOS;
|
|
using System;
|
|
using System.Drawing;
|
|
|
|
namespace CMLeonOS.Gui
|
|
{
|
|
internal class Window
|
|
{
|
|
internal Window(Process process, int x, int y, int width, int height)
|
|
{
|
|
WM = ProcessManager.GetProcess<WindowManager>();
|
|
|
|
Process = process;
|
|
X = x;
|
|
Y = y;
|
|
|
|
this.width = width;
|
|
this.height = height;
|
|
ResizeBuffer();
|
|
}
|
|
|
|
internal Window(Process process, Window parent, int x, int y, int width, int height)
|
|
{
|
|
WM = ProcessManager.GetProcess<WindowManager>();
|
|
|
|
Process = process;
|
|
_relativeTo = parent;
|
|
X = x;
|
|
Y = y;
|
|
|
|
this.width = width;
|
|
this.height = height;
|
|
ResizeBuffer();
|
|
}
|
|
|
|
internal int[] Buffer { get; private set; }
|
|
|
|
private Window _relativeTo = null;
|
|
|
|
internal Process Process { get; private set; }
|
|
|
|
protected WindowManager WM;
|
|
|
|
private int x;
|
|
private int y;
|
|
|
|
private int width;
|
|
private int height;
|
|
|
|
private const int bytesPerPixel = 4;
|
|
|
|
#region Events
|
|
internal Action<int, int> OnDown;
|
|
internal Action<int, int> OnClick;
|
|
internal Action<int, int> OnDoubleClick;
|
|
internal Action<KeyEvent> OnKeyPressed;
|
|
internal Action OnFocused;
|
|
internal Action OnUnfocused;
|
|
internal Action UserResized;
|
|
#endregion
|
|
|
|
private void ResizeBuffer()
|
|
{
|
|
Buffer = new int[Width * Height];
|
|
Cosmos.Core.MemoryOperations.Fill(Buffer, Color.White.ToArgb());
|
|
}
|
|
|
|
internal void Move(int x, int y, bool sendWMEvent = true)
|
|
{
|
|
if (x != X || y != Y)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
if (sendWMEvent)
|
|
{
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void Resize(int width, int height, bool sendWMEvent = true)
|
|
{
|
|
if (width != Width || height != Height)
|
|
{
|
|
this.width = width;
|
|
this.height = height;
|
|
ResizeBuffer();
|
|
if (sendWMEvent)
|
|
{
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal void MoveAndResize(int x, int y, int width, int height, bool sendWMEvent = true)
|
|
{
|
|
Move(x, y, sendWMEvent: false);
|
|
Resize(width, height, sendWMEvent: false);
|
|
if (sendWMEvent)
|
|
{
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
}
|
|
|
|
#region Graphics
|
|
private Color AlphaBlend(Color to, Color from, byte alpha)
|
|
{
|
|
byte R = (byte)((to.R * alpha + from.R * (255 - alpha)) >> 8);
|
|
byte G = (byte)((to.G * alpha + from.G * (255 - alpha)) >> 8);
|
|
byte B = (byte)((to.B * alpha + from.B * (255 - alpha)) >> 8);
|
|
return Color.FromArgb(R, G, B);
|
|
}
|
|
|
|
// https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs
|
|
private void TrimLine(ref int x1, ref int y1, ref int x2, ref int y2)
|
|
{
|
|
if (x1 == x2)
|
|
{
|
|
x1 = Math.Min(width - 1, Math.Max(0, x1));
|
|
x2 = x1;
|
|
y1 = Math.Min(height - 1, Math.Max(0, y1));
|
|
y2 = Math.Min(height - 1, Math.Max(0, y2));
|
|
return;
|
|
}
|
|
|
|
float x1_out = x1, y1_out = y1;
|
|
float x2_out = x2, y2_out = y2;
|
|
|
|
float m = (y2_out - y1_out) / (x2_out - x1_out);
|
|
float c = y1_out - m * x1_out;
|
|
|
|
if (x1_out < 0)
|
|
{
|
|
x1_out = 0;
|
|
y1_out = c;
|
|
}
|
|
else if (x1_out >= width)
|
|
{
|
|
x1_out = width - 1;
|
|
y1_out = (width - 1) * m + c;
|
|
}
|
|
|
|
if (x2_out < 0)
|
|
{
|
|
x2_out = 0;
|
|
y2_out = c;
|
|
}
|
|
else if (x2_out >= width)
|
|
{
|
|
x2_out = width - 1;
|
|
y2_out = (width - 1) * m + c;
|
|
}
|
|
|
|
if (y1_out < 0)
|
|
{
|
|
x1_out = -c / m;
|
|
y1_out = 0;
|
|
}
|
|
else if (y1_out >= height)
|
|
{
|
|
x1_out = (height - 1 - c) / m;
|
|
y1_out = height - 1;
|
|
}
|
|
|
|
if (y2_out < 0)
|
|
{
|
|
x2_out = -c / m;
|
|
y2_out = 0;
|
|
}
|
|
else if (y2_out >= width)
|
|
{
|
|
x2_out = (width - 1 - c) / m;
|
|
y2_out = width - 1;
|
|
}
|
|
|
|
if (x1_out < 0 || x1_out >= width || y1_out < 0 || y1_out >= height)
|
|
{
|
|
x1_out = 0; x2_out = 0;
|
|
y1_out = 0; y2_out = 0;
|
|
}
|
|
|
|
if (x2_out < 0 || x2_out >= width || y2_out < 0 || y2_out >= height)
|
|
{
|
|
x1_out = 0; x2_out = 0;
|
|
y1_out = 0; y2_out = 0;
|
|
}
|
|
|
|
x1 = (int)x1_out; y1 = (int)y1_out;
|
|
x2 = (int)x2_out; y2 = (int)y2_out;
|
|
}
|
|
|
|
// https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs
|
|
internal void DrawHorizontalLine(int dx, int x1, int y1, Color color)
|
|
{
|
|
int i;
|
|
|
|
if (dx > 0)
|
|
{
|
|
for (i = 0; i < dx; i++)
|
|
{
|
|
DrawPoint(x1 + i, y1, color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i > dx; i--)
|
|
{
|
|
DrawPoint(x1 + i, y1, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
// https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs
|
|
internal void DrawVerticalLine(int dy, int x1, int y1, Color color)
|
|
{
|
|
int i;
|
|
|
|
if (dy > 0)
|
|
{
|
|
for (i = 0; i < dy; i++)
|
|
{
|
|
DrawPoint(x1, y1 + i, color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i > dy; i--)
|
|
{
|
|
DrawPoint(x1, y1 + i, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
// https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs
|
|
private void DrawDiagonalLine(int dx, int dy, int x1, int y1, Color color)
|
|
{
|
|
int i, sdx, sdy, dxabs, dyabs, x, y, px, py;
|
|
|
|
dxabs = Math.Abs(dx);
|
|
dyabs = Math.Abs(dy);
|
|
sdx = Math.Sign(dx);
|
|
sdy = Math.Sign(dy);
|
|
x = dyabs >> 1;
|
|
y = dxabs >> 1;
|
|
px = x1;
|
|
py = y1;
|
|
|
|
if (dxabs >= dyabs)
|
|
{
|
|
for (i = 0; i < dxabs; i++)
|
|
{
|
|
y += dyabs;
|
|
if (y >= dxabs)
|
|
{
|
|
y -= dxabs;
|
|
py += sdy;
|
|
}
|
|
px += sdx;
|
|
DrawPoint(px, py, color);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < dyabs; i++)
|
|
{
|
|
x += dxabs;
|
|
if (x >= dyabs)
|
|
{
|
|
x -= dyabs;
|
|
px += sdx;
|
|
}
|
|
py += sdy;
|
|
DrawPoint(px, py, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Clear(Color color)
|
|
{
|
|
MemoryOperations.Fill(Buffer, color.ToArgb());
|
|
}
|
|
|
|
// To-do: Optimise.
|
|
public void DrawFilledRectangle(int x, int y, int width, int height, Color color)
|
|
{
|
|
int argb = color.ToArgb();
|
|
for (int i = Math.Max(0, x); i < Math.Min(Width, x + width); i++)
|
|
{
|
|
for (int j = Math.Max(0, y); j < Math.Min(Height, y + height); j++)
|
|
{
|
|
Buffer[(j * Width) + i] = argb;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void DrawRectangle(int x, int y, int width, int height, Color color)
|
|
{
|
|
DrawHorizontalLine(width, x, y, color);
|
|
DrawHorizontalLine(width, x, y + height - 1, color);
|
|
DrawVerticalLine(height - 1, x, y + 1, color);
|
|
DrawVerticalLine(height - 1, x + width - 1, y + 1, color);
|
|
}
|
|
|
|
public void DrawPoint(int x, int y, Color color)
|
|
{
|
|
if (x < 0 || x >= width) return;
|
|
if (y < 0 || y >= height) return;
|
|
|
|
int index = x + (y * width);
|
|
|
|
Buffer[index] = color.ToArgb();
|
|
}
|
|
|
|
public Color GetPixel(int x, int y)
|
|
{
|
|
if (x < 0 || x >= width) return Color.Transparent;
|
|
if (y < 0 || y >= height) return Color.Transparent;
|
|
|
|
int index = x + (y * width);
|
|
|
|
return Color.FromArgb(Buffer[index]);
|
|
}
|
|
|
|
// https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs
|
|
public void DrawCircle(int x, int y, int radius, Color color)
|
|
{
|
|
int i = radius;
|
|
int j = 0;
|
|
int e = 0;
|
|
|
|
while (i >= j)
|
|
{
|
|
DrawPoint(x + i, y + j, color);
|
|
DrawPoint(x + j, y + i, color);
|
|
DrawPoint(x - j, y + i, color);
|
|
DrawPoint(x - i, y + j, color);
|
|
DrawPoint(x - i, y - j, color);
|
|
DrawPoint(x - j, y - i, color);
|
|
DrawPoint(x + j, y - i, color);
|
|
DrawPoint(x + i, y - j, color);
|
|
|
|
j++;
|
|
if (e <= 0)
|
|
{
|
|
e += 2 * j + 1;
|
|
}
|
|
if (e > 0)
|
|
{
|
|
i--;
|
|
e -= 2 * i + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// https://github.com/CosmosOS/Cosmos/blob/master/source/Cosmos.System2/Graphics/Canvas.cs
|
|
public void DrawLine(int x1, int y1, int x2, int y2, Color color)
|
|
{
|
|
TrimLine(ref x1, ref y1, ref x2, ref y2);
|
|
|
|
int dx, dy;
|
|
|
|
dx = x2 - x1;
|
|
dy = y2 - y1;
|
|
|
|
if (dy == 0)
|
|
{
|
|
DrawHorizontalLine(dx, x1, y1, color);
|
|
return;
|
|
}
|
|
|
|
if (dx == 0)
|
|
{
|
|
DrawVerticalLine(dy, x1, y1, color);
|
|
return;
|
|
}
|
|
|
|
DrawDiagonalLine(dx, dy, x1, y1, color);
|
|
}
|
|
|
|
public void DrawString(string str, Color color, int x, int y)
|
|
{
|
|
//Asc16.DrawAsciiString(str, color, x, y, Buffer, width, height);
|
|
SmoothMono.TextRenderer.DrawString(str, color, Buffer, width, height, x, y);
|
|
}
|
|
|
|
public void DrawImage(Bitmap bitmap, int x, int y)
|
|
{
|
|
/*if (bitmap.rawData.Length != bitmap.Width * bitmap.Height)
|
|
{
|
|
throw new Exception("Invalid bitmap.");
|
|
}
|
|
for (int i = 0; i < y; i++)
|
|
{
|
|
int destOffset = ((i + y) * width) + x;
|
|
int srcOffset = (int)(i * bitmap.Width);
|
|
fixed (int* destPtr = &Buffer[destOffset])
|
|
fixed (int* sourcePtr = &bitmap.rawData[srcOffset])
|
|
{
|
|
MemoryOperations.Copy(destPtr, sourcePtr, (int)bitmap.Width);
|
|
}
|
|
}*/
|
|
for (int i = 0; i < bitmap.Height; i++)
|
|
{
|
|
for (int j = 0; j < bitmap.Width; j++)
|
|
{
|
|
DrawPoint(x + j, y + i, Color.FromArgb(bitmap.RawData[(i * bitmap.Width) + j]));
|
|
}
|
|
}
|
|
}
|
|
|
|
public void DrawImageAlpha(Bitmap bitmap, int x, int y)
|
|
{
|
|
/*if (bitmap.rawData.Length != bitmap.Width * bitmap.Height)
|
|
{
|
|
throw new Exception("Invalid bitmap.");
|
|
}
|
|
for (int i = 0; i < y; i++)
|
|
{
|
|
int destOffset = ((i + y) * width) + x;
|
|
int srcOffset = (int)(i * bitmap.Width);
|
|
fixed (int* destPtr = &Buffer[destOffset])
|
|
fixed (int* sourcePtr = &bitmap.rawData[srcOffset])
|
|
{
|
|
MemoryOperations.Copy(destPtr, sourcePtr, (int)bitmap.Width);
|
|
}
|
|
}*/
|
|
for (int i = 0; i < bitmap.Height; i++)
|
|
{
|
|
for (int j = 0; j < bitmap.Width; j++)
|
|
{
|
|
Color from = GetPixel(x + j, y + i);
|
|
Color to = Color.FromArgb(bitmap.RawData[(i * bitmap.Width) + j]);
|
|
DrawPoint(x + j, y + i, AlphaBlend(to, from, to.A));
|
|
}
|
|
}
|
|
}
|
|
#endregion Graphics
|
|
|
|
public int X
|
|
{
|
|
get
|
|
{
|
|
return x;
|
|
}
|
|
set
|
|
{
|
|
if (value != x)
|
|
{
|
|
x = value;
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Y
|
|
{
|
|
get
|
|
{
|
|
return y;
|
|
}
|
|
set
|
|
{
|
|
if (value != y)
|
|
{
|
|
y = value;
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Width
|
|
{
|
|
get
|
|
{
|
|
return width;
|
|
}
|
|
set
|
|
{
|
|
if (value != width)
|
|
{
|
|
if (value < width)
|
|
{
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
width = value;
|
|
ResizeBuffer();
|
|
}
|
|
}
|
|
}
|
|
public int Height
|
|
{
|
|
get
|
|
{
|
|
return height;
|
|
}
|
|
set
|
|
{
|
|
if (value != height)
|
|
{
|
|
if (value < height)
|
|
{
|
|
ProcessManager.GetProcess<WindowManager>().RerenderAll();
|
|
}
|
|
height = value;
|
|
ResizeBuffer();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int BytesPerPixel
|
|
{
|
|
get
|
|
{
|
|
return bytesPerPixel;
|
|
}
|
|
}
|
|
|
|
public int ScreenX
|
|
{
|
|
get
|
|
{
|
|
if (_relativeTo != null)
|
|
{
|
|
return x + _relativeTo.ScreenX;
|
|
}
|
|
else
|
|
{
|
|
return x;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int ScreenY
|
|
{
|
|
get
|
|
{
|
|
if (_relativeTo != null)
|
|
{
|
|
return y + _relativeTo.ScreenY;
|
|
}
|
|
else
|
|
{
|
|
return y;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Window RelativeTo
|
|
{
|
|
get
|
|
{
|
|
return _relativeTo;
|
|
}
|
|
set
|
|
{
|
|
_relativeTo = value;
|
|
}
|
|
}
|
|
}
|
|
}
|