Code/XGUI/WindowNew.razor
@using System;
@using System.Collections.Generic;
@using Sandbox;
@using Sandbox.UI;
@using Sandbox.Razor;
@namespace XGUI
@inherits Panel
<root class="window">
@* Title bar *@
<div class="TitleBar">
<div class="TitleIcon"></div>
<div class="TitleLabel">@Title</div>
<div class="TitleSpacer" @onmousedown="DragBarDown" @onmouseup="DragBarUp" @onmousemove="Drag"></div>
@if (HasMinimise)
{
<button class="Control MinimiseButton" @onclick="Minimise">0</button>
}
@if (HasMaximise)
{
<button class="Control MaximiseButton" @onclick="Maximise">1</button>
}
@if (HasClose)
{
<button class="Control CloseButton" @onclick="Close">r</button>
}
</div>
@* Content area *@
<div class="window-content">
@ChildContent
</div>
</root>
@code {
//[Parameter] public virtual RenderFragment ChildContent { get; set; }
public Vector2 Position;
public Vector2 Size;
public Vector2 MinSize = new Vector2();
// Window properties
public string Title { get; set; } = "Window";
public bool HasMinimise { get; set; } = false;
public bool HasMaximise { get; set; } = false;
public bool HasClose { get; set; } = true;
public bool IsResizable = true;
public bool IsDraggable = true;
public WindowNew()
{
AddClass("Panel");
AddClass("Window");
Style.Position = PositionMode.Absolute;
Style.FlexDirection = FlexDirection.Column;
}
public override void Tick()
{
base.Tick();
// Apply position to styles
Style.Left = Position.x;
Style.Top = Position.y;
}
// Window functionality
private bool _dragging = false;
private float _dragOffsetX = 0;
private float _dragOffsetY = 0;
public void DragBarDown()
{
var mousePos = FindRootPanel().MousePosition;
_dragOffsetX = mousePos.x - Position.x;
_dragOffsetY = mousePos.y - Position.y;
_dragging = true;
}
public void DragBarUp()
{
_dragging = false;
}
public void Drag()
{
if (!_dragging) return;
var mousePos = FindRootPanel().MousePosition;
Position = new Vector2(
mousePos.x - _dragOffsetX,
mousePos.y - _dragOffsetY
);
}
public void Minimise()
{
// Implement minimize functionality
}
public void Maximise()
{
// Implement maximize functionality
}
public void Close()
{
Delete();
}
// -------------
// Resizing
// -------------
// I feel like everything about resizing sucks.
Vector2 MousePos()
{
if (FindRootPanel().IsWorldPanel && Game.ActiveScene.IsValid() && Game.ActiveScene.IsValid())
{
Ray ray = Game.ActiveScene.Camera.ScreenPixelToRay(Mouse.Position);
FindRootPanel().RayToLocalPosition(ray, out var pos, out var distance);
return pos;
}
return FindRootPanel().MousePosition;
}
internal bool draggingR = false;
internal bool draggingL = false;
internal bool draggingT = false;
internal bool draggingB = false;
public void ResizeDown()
{
if (!IsResizable) return;
// TODO FIXME: Don't resize if were dragging a window by the title bar!!
var Distance = 5;
var mousePos = FindRootPanel().MousePosition;
if (mousePos.y.AlmostEqual(this.Box.Rect.Bottom, Distance)) draggingB = true;
if (mousePos.x.AlmostEqual(this.Box.Rect.Right, Distance)) draggingR = true;
if (mousePos.y.AlmostEqual(this.Box.Rect.Top, Distance)) draggingT = true;
if (mousePos.x.AlmostEqual(this.Box.Rect.Left, Distance)) draggingL = true;
//draggingT = true;
//draggingL = true;
xoff1 = (float)((FindRootPanel().MousePosition.x) - this.Box.Rect.Right);
yoff1 = (float)((FindRootPanel().MousePosition.y) - this.Box.Rect.Bottom);
xoff2 = (float)((FindRootPanel().MousePosition.x) - this.Box.Rect.Left);
yoff2 = (float)((FindRootPanel().MousePosition.y) - this.Box.Rect.Top);
}
public void ResizeUp()
{
draggingB = false;
draggingR = false;
draggingT = false;
draggingL = false;
}
internal float xoff1 = 0;
internal float yoff1 = 0;
internal float xoff2 = 0;
internal float yoff2 = 0;
public void ResizeMove()
{
var mousePos = MousePos();
if (IsResizable)
{
var Distance = 5;
var almostbottom = mousePos.y.AlmostEqual(this.Box.Rect.Bottom, Distance);
var almostright = mousePos.x.AlmostEqual(this.Box.Rect.Right, Distance);
var almosttop = mousePos.y.AlmostEqual(this.Box.Rect.Top, Distance);
var almostleft = mousePos.x.AlmostEqual(this.Box.Rect.Left, Distance);
if ((almostleft && almostbottom) || (draggingL && draggingB)) Style.Cursor = "nesw-resize";
else if ((almostright && almosttop) || (draggingR && draggingT)) Style.Cursor = "nesw-resize";
else if ((almostright && almostbottom) || (draggingR && draggingB)) Style.Cursor = "nwse-resize";
else if ((almostleft && almosttop) || (draggingL && draggingT)) Style.Cursor = "nwse-resize";
else if (almostbottom || draggingB) Style.Cursor = "ns-resize";
else if (almostright || draggingR) Style.Cursor = "ew-resize";
else if (almosttop || draggingT) Style.Cursor = "ns-resize";
else if (almostleft || draggingL) Style.Cursor = "ew-resize";
else Style.Cursor = "unset";
}
/*if ( Mouse )
{
ResizeUp( e );
}*/
// This sucks.
if (draggingB)
{
//Parent.Style.Width = (FindRootPanel().MousePosition.x - Parent.Box.Rect.Left) - xoff;
var newheight = (mousePos.y - Box.Rect.Top) - yoff1;
if (newheight > MinSize.y)
{
Style.Height = newheight;
}
}
if (draggingR)
{
var newwidth = (mousePos.x - Box.Rect.Left) - xoff1;
if (newwidth > MinSize.x)
{
Style.Width = newwidth;
}
//Parent.Style.Height = (FindRootPanel().MousePosition.y - Parent.Box.Rect.Top) - yoff;
}
if (draggingT)
{
var newheight = Box.Rect.Height - ((mousePos.y - yoff2) - Box.Rect.Top);
if (newheight > MinSize.y)
{
Style.Height = newheight;
Position.y = mousePos.y - yoff2;
}
}
if (draggingL)
{
var newwidth = Box.Rect.Width - ((mousePos.x - xoff2) - Box.Rect.Left);
if (newwidth > MinSize.x)
{
Style.Width = newwidth;
Position.x = mousePos.x - xoff2;
}
}
}
// Override SetProperty to handle window attributes
public override void SetProperty(string name, string value)
{
switch (name)
{
case "title":
Title = value;
break;
case "hasminimise":
HasMinimise = bool.Parse(value);
break;
case "hasmaximise":
HasMaximise = bool.Parse(value);
break;
case "hasclose":
HasClose = bool.Parse(value);
break;
case "x":
if (float.TryParse(value, out float x))
Position = new Vector2(x, Position.y);
break;
case "y":
if (float.TryParse(value, out float y))
Position = new Vector2(Position.x, y);
break;
default:
base.SetProperty(name, value);
break;
}
}
}