ShiftOS_TheReturn/ShiftOS.Frontend/Desktop/WindowManager.cs

516 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework.Graphics;
using ShiftOS.Engine;
using ShiftOS.Frontend.GraphicsSubsystem;
using static ShiftOS.Engine.SkinEngine;
namespace ShiftOS.Frontend.Desktop
{
public class WindowManager : Engine.WindowManager
{
public override void Close(IShiftOSWindow win)
{
var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win);
if (brdr != null)
{
brdr.Close();
win = null;
}
}
private List<WindowBorder> RunningBorders = new List<WindowBorder>();
public override void InvokeAction(Action act)
{
UIManager.CrossThreadOperations.Enqueue(act);
}
public override void Maximize(IWindowBorder border)
{
throw new NotImplementedException();
}
public override void Minimize(IWindowBorder border)
{
throw new NotImplementedException();
}
public override void SetTitle(IShiftOSWindow win, string title)
{
var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win);
if (brdr != null)
brdr.Text = title;
}
public override void SetupDialog(IShiftOSWindow win)
{
var wb = new WindowBorder();
wb.Width = (win as GUI.Control).Width + LoadedSkin.LeftBorderWidth + LoadedSkin.RightBorderWidth;
wb.Height = (win as GUI.Control).Height + LoadedSkin.TitlebarHeight + LoadedSkin.BottomBorderWidth;
wb.ParentWindow = win;
wb.IsDialog = true;
UIManager.AddTopLevel(wb);
RunningBorders.Add(wb);
win.OnLoad();
win.OnUpgrade();
win.OnSkinLoad();
}
private int MaxCount
{
get
{
if (Shiftorium.UpgradeInstalled("wm_unlimited_windows"))
return int.MaxValue;
if (Shiftorium.UpgradeInstalled("wm_4_windows"))
return 4;
if (Shiftorium.UpgradeInstalled("wm_2_windows"))
return 2;
return 1;
}
}
public override void SetupWindow(IShiftOSWindow win)
{
if (!Shiftorium.UpgradeAttributesUnlocked(win.GetType()))
{
Console.WriteLine("Application not found on system.");
return;
}
while(AppearanceManager.OpenForms.Count > MaxCount)
{
AppearanceManager.OpenForms[0].Close();
AppearanceManager.OpenForms.RemoveAt(0);
}
var wb = new WindowBorder();
wb.Width = (win as GUI.Control).Width + LoadedSkin.LeftBorderWidth + LoadedSkin.RightBorderWidth;
wb.Height = (win as GUI.Control).Height + LoadedSkin.TitlebarHeight + LoadedSkin.BottomBorderWidth;
wb.ParentWindow = win;
wb.IsDialog = true;
UIManager.AddTopLevel(wb);
AppearanceManager.OpenForms.Add(wb);
RunningBorders.Add(wb);
win.OnLoad();
win.OnUpgrade();
win.OnSkinLoad();
if (!Shiftorium.UpgradeInstalled("wm_free_placement"))
{
TileWindows();
}
}
public void TileWindows()
{
if (AppearanceManager.OpenForms.Count == 0)
return;
else if(AppearanceManager.OpenForms.Count == 1)
{
var wb = (WindowBorder)AppearanceManager.OpenForms[0];
wb.X = 0;
wb.Y = 0;
wb.ResizeWindow(UIManager.Viewport.Width, UIManager.Viewport.Height);
}
}
}
public class WindowBorder : GUI.Control, IWindowBorder
{
private string _text = "ShiftOS window";
private GUI.Control _hostedwindow = null;
public void ResizeWindow(int width, int height)
{
int titleheight = Shiftorium.UpgradeInstalled("wm_titlebar") ? LoadedSkin.TitlebarHeight : 0;
int leftwidth = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.LeftBorderWidth : 0;
int bottomheight = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.BottomBorderWidth : 0;
int rightwidth = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.RightBorderWidth : 0;
_hostedwindow.Width = width - leftwidth - rightwidth;
_hostedwindow.Height = width - bottomheight - titleheight;
Width = width;
Height = height;
}
public WindowBorder()
{
X = 720;
Y = 480;
}
public IShiftOSWindow ParentWindow
{
get
{
return (IShiftOSWindow)_hostedwindow;
}
set
{
_hostedwindow = (GUI.Control)value;
ClearControls();
AddControl(_hostedwindow);
Width = LoadedSkin.LeftBorderWidth + _hostedwindow.Width + LoadedSkin.RightBorderWidth;
Height = LoadedSkin.BottomBorderWidth + _hostedwindow.Height + LoadedSkin.TitlebarHeight;
}
}
public bool IsDialog { get; set; }
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public void Close()
{
Visible = false;
UIManager.StopHandling(this);
}
private int lastmousex, lastmousey = 0;
protected override void OnLayout()
{
if (moving)
{
var screenpoint = PointToScreen(MouseX, MouseY);
this.X = lastmousex + screenpoint.X;
this.Y = lastmousey + screenpoint.Y;
}
int titlebarheight = Shiftorium.UpgradeInstalled("wm_titlebar") ? LoadedSkin.TitlebarHeight : 0;
int borderleft = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.LeftBorderWidth : 0;
int borderright = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.RightBorderWidth : 0;
int borderbottom = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.BottomBorderWidth : 0;
_hostedwindow.X = borderleft;
_hostedwindow.Y = titlebarheight;
Width = _hostedwindow.X + _hostedwindow.Width + LoadedSkin.RightBorderWidth;
Height = _hostedwindow.Y + _hostedwindow.Height + LoadedSkin.BottomBorderWidth;
}
private bool moving = false;
public override void MouseStateChanged()
{
if (Shiftorium.UpgradeInstalled("wm_titlebar"))
{
if (Shiftorium.UpgradeInstalled("close_button"))
{
var closebuttonsize = LoadedSkin.CloseButtonSize;
var closebuttonloc = LoadedSkin.CloseButtonFromSide;
if (LoadedSkin.TitleButtonPosition == 0)
closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y);
if(MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height)
{
Close();
}
}
if (Shiftorium.UpgradeInstalled("minimize_button"))
{
var closebuttonsize = LoadedSkin.MinimizeButtonSize;
var closebuttonloc = LoadedSkin.MinimizeButtonFromSide;
if (LoadedSkin.TitleButtonPosition == 0)
closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y);
if (MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height)
{
if (IsFocusedControl || ContainsFocusedControl)
UIManager.FocusedControl = null;
Visible = false;
}
}
if (Shiftorium.UpgradeInstalled("maximize_button"))
{
var closebuttonsize = LoadedSkin.MaximizeButtonSize;
var closebuttonloc = LoadedSkin.MaximizeButtonFromSide;
if (LoadedSkin.TitleButtonPosition == 0)
closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y);
if (MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height)
{
AppearanceManager.Maximize(this);
}
}
if (MouseY < LoadedSkin.TitlebarHeight)
{
var screenpoint = PointToScreen(MouseX, MouseY);
lastmousex = this.X - screenpoint.X;
lastmousey = this.Y - screenpoint.Y;
moving = MouseLeftDown;
CaptureMouse = moving;
}
}
}
[DebuggerStepThrough]
protected override void OnPaint(GraphicsContext gfx)
{
int titleheight = LoadedSkin.TitlebarHeight;
int leftborderwidth = LoadedSkin.LeftBorderWidth;
int rightborderwidth = LoadedSkin.RightBorderWidth;
int bottomborderwidth = LoadedSkin.BottomBorderWidth;
if (Shiftorium.UpgradeInstalled("wm_titlebar"))
{
var titlebarcolor = LoadedSkin.TitleBackgroundColor;
var titlefont = LoadedSkin.TitleFont;
var titletextcolor = LoadedSkin.TitleTextColor;
var titletextleft = LoadedSkin.TitleTextLeft;
bool titletextcentered = LoadedSkin.TitleTextCentered;
var titlebarbg = GetImage("titlebar");
var titlebarlayout = GetImageLayout("titlebar");
var drawcorners = LoadedSkin.ShowTitleCorners;
int titlebarleft = 0;
int titlebarwidth = Width;
if (drawcorners)
{
//set titleleft to the first corner width
titlebarleft = LoadedSkin.TitleLeftCornerWidth;
titlebarwidth -= titlebarleft;
titlebarwidth -= LoadedSkin.TitleRightCornerWidth;
//Let's get the left and right images.
var leftimage = GetImage("titleleft");
var rightimage = GetImage("titleright");
//and the colors
var leftcolor = LoadedSkin.TitleLeftCornerBackground;
var rightcolor = LoadedSkin.TitleRightCornerBackground;
//and the layouts...
var leftlayout = GetImageLayout("titlebarleft");
var rightlayout = GetImageLayout("titlebarright");
//and the widths
var leftwidth = LoadedSkin.TitleLeftCornerWidth;
var rightwidth = LoadedSkin.TitleRightCornerWidth;
//draw left corner
if(leftimage != null)
{
gfx.DrawRectangle(0, 0, leftwidth, titleheight, leftimage.ToTexture2D(gfx.Device));
}
else
{
gfx.DrawRectangle(0, 0, leftwidth, titleheight, leftcolor.ToMonoColor());
}
//draw right corner
if (rightimage != null)
{
gfx.DrawRectangle(titlebarleft + titlebarwidth, 0, rightwidth, titleheight, rightimage.ToTexture2D(gfx.Device));
}
else
{
gfx.DrawRectangle(titlebarleft + titlebarwidth, 0, rightwidth, titleheight, rightcolor.ToMonoColor());
}
}
if (titlebarbg == null)
{
//draw the title bg
gfx.DrawRectangle(titlebarleft, 0, titlebarwidth, titleheight, titlebarcolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(titlebarleft, 0, titlebarwidth, titleheight, titlebarbg.ToTexture2D(gfx.Device));
}
//Now we draw the title text.
var textMeasure = gfx.MeasureString(_text, titlefont);
PointF textloc;
if (titletextcentered)
textloc = new PointF((titlebarwidth - textMeasure.X) / 2,
titletextleft.Y);
else
textloc = new PointF(titlebarleft + titletextleft.X, titletextleft.Y);
gfx.DrawString(_text, (int)textloc.X, (int)textloc.Y, titletextcolor.ToMonoColor(), titlefont);
var tbuttonpos = LoadedSkin.TitleButtonPosition;
//Draw close button
if(Shiftorium.UpgradeInstalled("close_button"))
{
var closebuttoncolor = LoadedSkin.CloseButtonColor;
var closebuttonsize = LoadedSkin.CloseButtonSize;
var closebuttonright = LoadedSkin.CloseButtonFromSide;
if (LoadedSkin.TitleButtonPosition == 0)
closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y);
var img = GetImage("closebutton");
if (img == null)
{
gfx.DrawRectangle(closebuttonright.X, closebuttonright.Y, closebuttonsize.Width, closebuttonsize.Height, closebuttoncolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(closebuttonright.X, closebuttonright.Y, closebuttonsize.Width, closebuttonsize.Height, img.ToTexture2D(gfx.Device));
}
}
//Draw maximize button
if (Shiftorium.UpgradeInstalled("maximize_button"))
{
var closebuttoncolor = LoadedSkin.MaximizeButtonColor;
var closebuttonsize = LoadedSkin.MaximizeButtonSize;
var closebuttonright = LoadedSkin.MaximizeButtonFromSide;
if (LoadedSkin.TitleButtonPosition == 0)
closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y);
var img = GetImage("maximizebutton");
if (img == null)
{
gfx.DrawRectangle(closebuttonright.X, closebuttonright.Y, closebuttonsize.Width, closebuttonsize.Height, closebuttoncolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(closebuttonright.X, closebuttonright.Y, closebuttonsize.Width, closebuttonsize.Height, img.ToTexture2D(gfx.Device));
}
}
//Draw minimize button
if (Shiftorium.UpgradeInstalled("minimize_button"))
{
var closebuttoncolor = LoadedSkin.MinimizeButtonColor;
var closebuttonsize = LoadedSkin.MinimizeButtonSize;
var closebuttonright = LoadedSkin.MinimizeButtonFromSide;
if (LoadedSkin.TitleButtonPosition == 0)
closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y);
var img = GetImage("minimizebutton");
if (img == null)
{
gfx.DrawRectangle(closebuttonright.X, closebuttonright.Y, closebuttonsize.Width, closebuttonsize.Height, closebuttoncolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(closebuttonright.X, closebuttonright.Y, closebuttonsize.Width, closebuttonsize.Height, img.ToTexture2D(gfx.Device));
}
}
}
else
{
//Set the titleheight to 0.
titleheight = 0;
}
if (Shiftorium.UpgradeInstalled("window_borders"))
{
//Some variables we'll need...
int bottomlocy = Height - LoadedSkin.BottomBorderWidth;
int bottomlocx = leftborderwidth;
int bottomwidth = Width - bottomlocx - rightborderwidth;
int brightlocx = Width - rightborderwidth;
var borderleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderLeftBackground : LoadedSkin.BorderInactiveLeftBackground;
var borderrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderRightBackground : LoadedSkin.BorderInactiveRightBackground;
var borderbottomcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomBackground : LoadedSkin.BorderInactiveBottomBackground;
var borderbleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomLeftBackground : LoadedSkin.BorderInactiveBottomLeftBackground;
var borderbrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomRightBackground : LoadedSkin.BorderInactiveBottomRightBackground;
//draw border corners
//BOTTOM LEFT
var bottomlimg = GetImage("bottomlborder");
if (bottomlimg == null)
{
gfx.DrawRectangle(0, bottomlocy, leftborderwidth, bottomborderwidth, borderbleftcolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(0, bottomlocy, leftborderwidth, bottomborderwidth, bottomlimg.ToTexture2D(gfx.Device));
}
//BOTTOM RIGHT
var bottomrimg = GetImage("bottomrborder");
if (bottomrimg == null)
{
gfx.DrawRectangle(brightlocx, bottomlocy, rightborderwidth, bottomborderwidth, borderbrightcolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(brightlocx, bottomlocy, rightborderwidth, bottomborderwidth, bottomrimg.ToTexture2D(gfx.Device));
}
//BOTTOM
var bottomimg = GetImage("bottomborder");
if (bottomimg == null)
{
gfx.DrawRectangle(leftborderwidth, bottomlocy, bottomwidth, bottomborderwidth, borderbottomcolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(leftborderwidth, bottomlocy, bottomwidth, bottomborderwidth, bottomimg.ToTexture2D(gfx.Device));
}
//LEFT
var leftimg = GetImage("leftborder");
if (leftimg == null)
{
gfx.DrawRectangle(0, titleheight, leftborderwidth, Height - titleheight - bottomborderwidth, borderleftcolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(0, titleheight, leftborderwidth, Height - titleheight - bottomborderwidth, leftimg.ToTexture2D(gfx.Device));
}
//RIGHT
var rightimg = GetImage("rightborder");
if (rightimg == null)
{
gfx.DrawRectangle(brightlocx, titleheight, rightborderwidth, Height - titleheight - bottomborderwidth, borderrightcolor.ToMonoColor());
}
else
{
gfx.DrawRectangle(brightlocx, titleheight, rightborderwidth, Height - titleheight - bottomborderwidth, rightimg.ToTexture2D(gfx.Device));
}
}
gfx.DrawRectangle(leftborderwidth, titleheight, Width - leftborderwidth - rightborderwidth, Height - titleheight - bottomborderwidth, LoadedSkin.ControlColor.ToMonoColor());
//So here's what we're gonna do now.
//Now that we have a titlebar and window borders...
//We're going to composite the hosted window
//and draw it to the remaining area.
//Painting of the canvas is done by the Paint() method.
}
}
public static class ImageExtensioons
{
public static Texture2D ToTexture2D(this Image image, GraphicsDevice device)
{
var bmp = (Bitmap)image;
var lck = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var data = new byte[Math.Abs(lck.Stride) * lck.Height];
Marshal.Copy(lck.Scan0, data, 0, data.Length);
bmp.UnlockBits(lck);
for(int i = 0; i < data.Length; i += 4)
{
byte r = data[i];
byte b = data[i + 2];
data[i] = b;
data[i + 2] = r;
}
var tex2 = new Texture2D(device, bmp.Width, bmp.Height);
tex2.SetData<byte>(data);
return tex2;
}
}
}