A day's worth of hell... which is turning into heaven.
This commit is contained in:
parent
5d5f351138
commit
6f3a5cba2e
18 changed files with 1476 additions and 83 deletions
85
ShiftOS.Frontend/Desktop/Desktop.cs
Normal file
85
ShiftOS.Frontend/Desktop/Desktop.cs
Normal file
|
@ -0,0 +1,85 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShiftOS.Engine;
|
||||
|
||||
namespace ShiftOS.Frontend.Desktop
|
||||
{
|
||||
public class Desktop : GUI.Control, IDesktop
|
||||
{
|
||||
public string DesktopName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "ShiftOS MonoGame Desktop";
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Size GetSize()
|
||||
{
|
||||
return new Size(Width, Height);
|
||||
}
|
||||
|
||||
public void HideAppLauncher()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void InvokeOnWorkerThread(Action act)
|
||||
{
|
||||
act?.Invoke();
|
||||
}
|
||||
|
||||
public void KillWindow(IWindowBorder border)
|
||||
{
|
||||
}
|
||||
|
||||
public void MaximizeWindow(IWindowBorder brdr)
|
||||
{
|
||||
}
|
||||
|
||||
public void MinimizeWindow(IWindowBorder brdr)
|
||||
{
|
||||
}
|
||||
|
||||
public void OpenAppLauncher(Point loc)
|
||||
{
|
||||
}
|
||||
|
||||
public void PopulateAppLauncher(LauncherItem[] items)
|
||||
{
|
||||
}
|
||||
|
||||
public void PopulatePanelButtons()
|
||||
{
|
||||
}
|
||||
|
||||
public void PushNotification(string app, string title, string message)
|
||||
{
|
||||
}
|
||||
|
||||
public void RestoreWindow(IWindowBorder brdr)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetupDesktop()
|
||||
{
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
}
|
||||
|
||||
public void ShowWindow(IWindowBorder border)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShiftOS.Engine;
|
||||
using ShiftOS.Frontend.GraphicsSubsystem;
|
||||
using static ShiftOS.Engine.SkinEngine;
|
||||
|
||||
namespace ShiftOS.Frontend.Desktop
|
||||
{
|
||||
|
@ -12,9 +14,16 @@ namespace ShiftOS.Frontend.Desktop
|
|||
{
|
||||
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)
|
||||
{
|
||||
act?.Invoke();
|
||||
|
@ -32,17 +41,44 @@ namespace ShiftOS.Frontend.Desktop
|
|||
|
||||
public override void SetTitle(IShiftOSWindow win, string title)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win);
|
||||
if (brdr != null)
|
||||
brdr.Text = title;
|
||||
}
|
||||
|
||||
public override void SetupDialog(IShiftOSWindow win)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
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();
|
||||
}
|
||||
|
||||
public override void SetupWindow(IShiftOSWindow win)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (!Shiftorium.UpgradeAttributesUnlocked(win.GetType()))
|
||||
{
|
||||
Console.WriteLine("Application not found on system.");
|
||||
return;
|
||||
}
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,9 +97,13 @@ namespace ShiftOS.Frontend.Desktop
|
|||
set
|
||||
{
|
||||
_hostedwindow = (GUI.Control)value;
|
||||
ClearControls();
|
||||
AddControl(_hostedwindow);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDialog { get; set; }
|
||||
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
|
@ -83,10 +123,138 @@ namespace ShiftOS.Frontend.Desktop
|
|||
UIManager.StopHandling(this);
|
||||
}
|
||||
|
||||
public override void MouseStateChanged()
|
||||
public override void Paint(Graphics gfx)
|
||||
{
|
||||
//todo: close, minimize, maximize, drag, resize
|
||||
int titleheight = LoadedSkin.TitlebarHeight;
|
||||
int leftborderwidth = LoadedSkin.LeftBorderWidth;
|
||||
int rightborderwidth = LoadedSkin.RightBorderWidth;
|
||||
int bottomborderwidth = LoadedSkin.BottomBorderWidth;
|
||||
|
||||
if (Shiftorium.UpgradeInstalled("wm_titlebar") || true)
|
||||
{
|
||||
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("titlebarleft");
|
||||
var rightimage = GetImage("titlebarright");
|
||||
//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)
|
||||
{
|
||||
var resized = ResizeImage(leftimage, leftwidth, titleheight);
|
||||
gfx.DrawImage(resized, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx.FillRectangle(new SolidBrush(leftcolor), new Rectangle(0, 0, leftwidth, titleheight));
|
||||
}
|
||||
|
||||
//draw right corner
|
||||
if (rightimage != null)
|
||||
{
|
||||
var resized = ResizeImage(rightimage, rightwidth, titleheight);
|
||||
gfx.DrawImage(resized, titlebarleft+titlebarwidth, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx.FillRectangle(new SolidBrush(rightcolor), new Rectangle(titlebarleft+titlebarwidth, 0, rightwidth, titleheight));
|
||||
}
|
||||
}
|
||||
|
||||
if (titlebarbg == null)
|
||||
{
|
||||
//draw the title bg
|
||||
gfx.FillRectangle(new SolidBrush(titlebarcolor), new Rectangle(titlebarleft, 0, titlebarwidth, titleheight));
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var resized = ResizeImage(titlebarbg, titlebarwidth, titleheight);
|
||||
gfx.DrawImage(resized, titlebarleft, 0);
|
||||
}
|
||||
//Now we draw the title text.
|
||||
var textMeasure = gfx.MeasureString(_text, titlefont);
|
||||
PointF textloc;
|
||||
if (titletextcentered)
|
||||
textloc = new PointF((titlebarwidth - textMeasure.Width) / 2,
|
||||
titletextleft.Y);
|
||||
else
|
||||
textloc = new PointF(titlebarleft + titletextleft.X, titletextleft.Y);
|
||||
|
||||
gfx.DrawString(_text, titlefont, new SolidBrush(titletextcolor), textloc);
|
||||
|
||||
var tbuttonpos = LoadedSkin.TitleButtonPosition;
|
||||
|
||||
//Draw close button
|
||||
if(Shiftorium.UpgradeInstalled("close_button") || true)
|
||||
{
|
||||
var closebuttoncolor = LoadedSkin.CloseButtonColor;
|
||||
var closebuttonsize = LoadedSkin.CloseButtonSize;
|
||||
var closebuttonright = LoadedSkin.CloseButtonFromSide;
|
||||
|
||||
gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Set the titleheight to 0.
|
||||
titleheight = 0;
|
||||
|
||||
}
|
||||
|
||||
//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.
|
||||
|
||||
//First let's GET the window.
|
||||
if(_hostedwindow != null)
|
||||
{
|
||||
var win = _hostedwindow;
|
||||
//Now let's create a new bitmap to draw onto, the same size as the client area.
|
||||
using(var bmp = new Bitmap(Width, Height - titleheight))
|
||||
{
|
||||
//Now, let's create a graphics object.
|
||||
using(var cgfx = Graphics.FromImage(bmp))
|
||||
{
|
||||
//And composite...
|
||||
win.Paint(cgfx);
|
||||
|
||||
}
|
||||
//Now draw the bitmap to our client area
|
||||
gfx.DrawImage(bmp, 0, titleheight);
|
||||
//We now have a full window.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
50
ShiftOS.Frontend/GUI/Button.cs
Normal file
50
ShiftOS.Frontend/GUI/Button.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShiftOS.Engine;
|
||||
|
||||
namespace ShiftOS.Frontend.GUI
|
||||
{
|
||||
public class Button : TextControl
|
||||
{
|
||||
public Button()
|
||||
{
|
||||
TextAlign = TextAlign.MiddleCenter;
|
||||
Text = "Click me!";
|
||||
}
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
if(AutoSize == true)
|
||||
{
|
||||
int borderwidth = SkinEngine.LoadedSkin.ButtonBorderWidth * 2;
|
||||
|
||||
using (var gfx = Graphics.FromImage(new Bitmap(1, 1)))
|
||||
{
|
||||
var measure = gfx.MeasureString(this.Text, this.Font);
|
||||
Width = borderwidth + (int)measure.Width + 4;
|
||||
Height = borderwidth + (int)measure.Height + 8;
|
||||
}
|
||||
}
|
||||
base.OnLayout();
|
||||
}
|
||||
|
||||
public override void Paint(Graphics gfx)
|
||||
{
|
||||
Color bgCol = SkinEngine.LoadedSkin.ButtonBackgroundColor;
|
||||
Color fgCol = SkinEngine.LoadedSkin.ControlTextColor;
|
||||
if (ContainsMouse)
|
||||
bgCol = SkinEngine.LoadedSkin.ButtonHoverColor;
|
||||
if (MouseLeftDown)
|
||||
bgCol = SkinEngine.LoadedSkin.ButtonPressedColor;
|
||||
|
||||
gfx.Clear(bgCol);
|
||||
gfx.DrawRectangle(new Pen(new SolidBrush(fgCol), SkinEngine.LoadedSkin.ButtonBorderWidth), new Rectangle(0, 0, Width, Height));
|
||||
base.Paint(gfx);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,11 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System.Drawing;
|
||||
using ShiftOS.Frontend.GraphicsSubsystem;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Drawing.Drawing2D;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace ShiftOS.Frontend.GUI
|
||||
{
|
||||
|
@ -21,6 +26,77 @@ namespace ShiftOS.Frontend.GUI
|
|||
private bool _rightState = false;
|
||||
private bool _middleState = false;
|
||||
private bool _visible = true;
|
||||
private DockStyle _dock = DockStyle.None;
|
||||
private bool _focused = false;
|
||||
private bool _autoSize = false;
|
||||
private double _opacity = 1.0;
|
||||
|
||||
public double Opacity
|
||||
{
|
||||
get
|
||||
{
|
||||
return _opacity;
|
||||
}
|
||||
set
|
||||
{
|
||||
_opacity = (double)MathHelper.Clamp((float)value, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _autoSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
_autoSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
//Thank you, StackOverflow.
|
||||
public static Bitmap ResizeImage(Image image, int width, int height)
|
||||
{
|
||||
var destRect = new System.Drawing.Rectangle(0, 0, width, height);
|
||||
var destImage = new Bitmap(width, height);
|
||||
|
||||
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
|
||||
|
||||
using (var graphics = Graphics.FromImage(destImage))
|
||||
{
|
||||
graphics.CompositingMode = CompositingMode.SourceCopy;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
using (var wrapMode = new ImageAttributes())
|
||||
{
|
||||
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
||||
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
|
||||
}
|
||||
}
|
||||
|
||||
return destImage;
|
||||
}
|
||||
|
||||
public DockStyle Dock
|
||||
{
|
||||
get
|
||||
{
|
||||
return _dock;
|
||||
}
|
||||
set
|
||||
{
|
||||
_dock = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsMouse
|
||||
{
|
||||
get { return _wasMouseInControl; }
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
|
@ -150,6 +226,11 @@ namespace ShiftOS.Frontend.GUI
|
|||
return parentCoords;
|
||||
}
|
||||
|
||||
public void ClearControls()
|
||||
{
|
||||
_children.Clear();
|
||||
}
|
||||
|
||||
public Point PointToLocal(int x, int y)
|
||||
{
|
||||
return new GUI.Point(x - _x, y - _y);
|
||||
|
@ -168,13 +249,90 @@ namespace ShiftOS.Frontend.GUI
|
|||
using (var cBmp = new System.Drawing.Bitmap(child.Width, child.Height))
|
||||
{
|
||||
child.Paint(System.Drawing.Graphics.FromImage(cBmp));
|
||||
cBmp.SetOpacity((float)child.Opacity);
|
||||
gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Layout()
|
||||
{
|
||||
//Dock style
|
||||
if(_parent != null)
|
||||
{
|
||||
switch (_dock)
|
||||
{
|
||||
case DockStyle.Top:
|
||||
X = 0;
|
||||
Y = 0;
|
||||
Width = _parent.Width;
|
||||
break;
|
||||
case DockStyle.Left:
|
||||
X = 0;
|
||||
Y = 0;
|
||||
Height = _parent.Height;
|
||||
break;
|
||||
case DockStyle.Right:
|
||||
Y = 0;
|
||||
X = _parent.Width - Width;
|
||||
Height = _parent.Height;
|
||||
break;
|
||||
case DockStyle.Bottom:
|
||||
X = 0;
|
||||
Y = _parent.Height - Height;
|
||||
Width = _parent.Width;
|
||||
break;
|
||||
case DockStyle.Fill:
|
||||
X = 0;
|
||||
Y = 0;
|
||||
Width = _parent.Width;
|
||||
Height = _parent.Height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
OnLayout();
|
||||
foreach (var child in _children)
|
||||
child.Layout();
|
||||
}
|
||||
|
||||
protected virtual void OnLayout()
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
public bool IsFocusedControl
|
||||
{
|
||||
get
|
||||
{
|
||||
return UIManager.FocusedControl == this;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsFocusedControl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (UIManager.FocusedControl == null)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
bool contains = false;
|
||||
|
||||
var ctrl = UIManager.FocusedControl;
|
||||
while(ctrl.Parent != null)
|
||||
{
|
||||
ctrl = ctrl.Parent;
|
||||
if (ctrl == this)
|
||||
contains = true;
|
||||
}
|
||||
return contains;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool ProcessMouseState(MouseState state)
|
||||
{
|
||||
//If we aren't rendering the control, we aren't accepting input.
|
||||
|
@ -230,6 +388,10 @@ namespace ShiftOS.Frontend.GUI
|
|||
{
|
||||
fire = true;
|
||||
}
|
||||
if (_leftState == true && ld == false)
|
||||
Click?.Invoke();
|
||||
if (_leftState == false && ld == true)
|
||||
UIManager.FocusedControl = this;
|
||||
_leftState = ld;
|
||||
_middleState = md;
|
||||
_rightState = rd;
|
||||
|
@ -240,6 +402,10 @@ namespace ShiftOS.Frontend.GUI
|
|||
}
|
||||
else
|
||||
{
|
||||
_leftState = false;
|
||||
_rightState = false;
|
||||
_middleState = false;
|
||||
MouseStateChanged();
|
||||
//If the mouse was in local space before, fire MouseLeave
|
||||
if(_wasMouseInControl == true)
|
||||
{
|
||||
|
@ -251,9 +417,22 @@ namespace ShiftOS.Frontend.GUI
|
|||
return false;
|
||||
}
|
||||
|
||||
protected virtual void OnKeyEvent(KeyEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ProcessKeyEvent(KeyEvent e)
|
||||
{
|
||||
OnKeyEvent(e);
|
||||
KeyEvent?.Invoke(e);
|
||||
}
|
||||
|
||||
public event Action<Point> MouseMove;
|
||||
public event Action MouseEnter;
|
||||
public event Action MouseLeave;
|
||||
public event Action Click;
|
||||
public event Action<KeyEvent> KeyEvent;
|
||||
}
|
||||
|
||||
public struct Point
|
||||
|
@ -268,4 +447,43 @@ namespace ShiftOS.Frontend.GUI
|
|||
public int Y { get; set; }
|
||||
}
|
||||
|
||||
public enum DockStyle
|
||||
{
|
||||
None,
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
Fill
|
||||
}
|
||||
|
||||
//Thanks, StackOverflow.
|
||||
public static class BitmapExtensions
|
||||
{
|
||||
public static Image SetOpacity(this Image image, float opacity)
|
||||
{
|
||||
var colorMatrix = new ColorMatrix();
|
||||
colorMatrix.Matrix33 = opacity;
|
||||
var imageAttributes = new ImageAttributes();
|
||||
imageAttributes.SetColorMatrix(
|
||||
colorMatrix,
|
||||
ColorMatrixFlag.Default,
|
||||
ColorAdjustType.Bitmap);
|
||||
var output = new Bitmap(image.Width, image.Height);
|
||||
using (var gfx = Graphics.FromImage(output))
|
||||
{
|
||||
gfx.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
gfx.DrawImage(
|
||||
image,
|
||||
new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
|
||||
0,
|
||||
0,
|
||||
image.Width,
|
||||
image.Height,
|
||||
GraphicsUnit.Pixel,
|
||||
imageAttributes);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
64
ShiftOS.Frontend/GUI/ItemGroup.cs
Normal file
64
ShiftOS.Frontend/GUI/ItemGroup.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShiftOS.Frontend.GUI
|
||||
{
|
||||
public class ItemGroup : Control
|
||||
{
|
||||
private int _gap = 3;
|
||||
private FlowDirection _flowDir = FlowDirection.LeftToRight;
|
||||
private int _initialgap = 2;
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
if (AutoSize)
|
||||
{
|
||||
int _highesty = _initialgap;
|
||||
int _xx = _initialgap;
|
||||
foreach(var ctrl in Children)
|
||||
{
|
||||
_xx += ctrl.Width + _gap;
|
||||
if (_highesty < ctrl.Height + _initialgap + _gap)
|
||||
_highesty = ctrl.Height + _initialgap + _gap;
|
||||
}
|
||||
Width = _xx;
|
||||
Height = _highesty;
|
||||
}
|
||||
|
||||
int _x = _initialgap;
|
||||
int _y = _initialgap;
|
||||
int _maxYForRow = 0;
|
||||
foreach (var ctrl in Children)
|
||||
{
|
||||
if (_x + ctrl.Width + _gap > Width)
|
||||
{
|
||||
_x = _initialgap;
|
||||
_y = _maxYForRow;
|
||||
_maxYForRow = 0;
|
||||
if (_maxYForRow < ctrl.Height + _gap)
|
||||
_maxYForRow = ctrl.Height + _gap;
|
||||
}
|
||||
ctrl.X = _x;
|
||||
ctrl.Y = _y;
|
||||
ctrl.Dock = DockStyle.None;
|
||||
ctrl.Layout();
|
||||
_x += ctrl.Width + _gap;
|
||||
|
||||
if (_maxYForRow < ctrl.Height + _gap)
|
||||
_maxYForRow = ctrl.Height + _gap;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum FlowDirection
|
||||
{
|
||||
LeftToRight,
|
||||
TopDown,
|
||||
RightToLeft,
|
||||
BottomUp
|
||||
}
|
||||
}
|
146
ShiftOS.Frontend/GUI/PictureBox.cs
Normal file
146
ShiftOS.Frontend/GUI/PictureBox.cs
Normal file
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShiftOS.Engine;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace ShiftOS.Frontend.GUI
|
||||
{
|
||||
public class PictureBox : Control
|
||||
{
|
||||
private System.Drawing.Image img = null;
|
||||
private ImageLayout _layout = ImageLayout.Fit;
|
||||
|
||||
public ImageLayout ImageLayout
|
||||
{
|
||||
get
|
||||
{
|
||||
return _layout;
|
||||
}
|
||||
set
|
||||
{
|
||||
_layout = value;
|
||||
}
|
||||
}
|
||||
|
||||
public System.Drawing.Image Image
|
||||
{
|
||||
get
|
||||
{
|
||||
return img;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (img != null)
|
||||
img.Dispose();
|
||||
img = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
if (AutoSize)
|
||||
{
|
||||
Width = (img == null) ? 0 : img.Width;
|
||||
Height = (img == null) ? 0 : img.Height;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Paint(Graphics gfx)
|
||||
{
|
||||
if(img != null)
|
||||
switch (_layout)
|
||||
{
|
||||
case ImageLayout.None:
|
||||
//Just draw the image.
|
||||
gfx.DrawImage(img, new PointF(0, 0));
|
||||
break;
|
||||
case ImageLayout.Stretch:
|
||||
//Stretch the image, with no regard for aspect ratio.
|
||||
var stretched = ResizeImage(img, Width, Height);
|
||||
gfx.DrawImage(stretched, 0, 0);
|
||||
break;
|
||||
case ImageLayout.Fit:
|
||||
//Resize image to fit the control but keep aspect ratio.
|
||||
var fitted = FixedSize(img, Width, Height);
|
||||
gfx.DrawImage(fitted, 0, 0);
|
||||
break;
|
||||
case ImageLayout.Tile:
|
||||
//Keep original size but tile the image.
|
||||
|
||||
for(int x = 0; x < Width; x += img.Width)
|
||||
{
|
||||
for (int y = 0; y < Height; y += img.Height)
|
||||
{
|
||||
gfx.DrawImage(img, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Again, thanks StackOverflow
|
||||
static Image FixedSize(Image imgPhoto, int Width, int Height)
|
||||
{
|
||||
int sourceWidth = imgPhoto.Width;
|
||||
int sourceHeight = imgPhoto.Height;
|
||||
int sourceX = 0;
|
||||
int sourceY = 0;
|
||||
int destX = 0;
|
||||
int destY = 0;
|
||||
|
||||
float nPercent = 0;
|
||||
float nPercentW = 0;
|
||||
float nPercentH = 0;
|
||||
|
||||
nPercentW = ((float)Width / (float)sourceWidth);
|
||||
nPercentH = ((float)Height / (float)sourceHeight);
|
||||
if (nPercentH < nPercentW)
|
||||
{
|
||||
nPercent = nPercentH;
|
||||
destX = System.Convert.ToInt16((Width -
|
||||
(sourceWidth * nPercent)) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
nPercent = nPercentW;
|
||||
destY = System.Convert.ToInt16((Height -
|
||||
(sourceHeight * nPercent)) / 2);
|
||||
}
|
||||
|
||||
int destWidth = (int)(sourceWidth * nPercent);
|
||||
int destHeight = (int)(sourceHeight * nPercent);
|
||||
|
||||
Bitmap bmPhoto = new Bitmap(Width, Height,
|
||||
PixelFormat.Format24bppRgb);
|
||||
bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
|
||||
imgPhoto.VerticalResolution);
|
||||
|
||||
Graphics grPhoto = Graphics.FromImage(bmPhoto);
|
||||
grPhoto.Clear(SkinEngine.LoadedSkin.ControlColor);
|
||||
grPhoto.InterpolationMode =
|
||||
InterpolationMode.HighQualityBicubic;
|
||||
|
||||
grPhoto.DrawImage(imgPhoto,
|
||||
new Rectangle(destX, destY, destWidth, destHeight),
|
||||
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
|
||||
GraphicsUnit.Pixel);
|
||||
|
||||
grPhoto.Dispose();
|
||||
return bmPhoto;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ImageLayout
|
||||
{
|
||||
None,
|
||||
Stretch,
|
||||
Tile,
|
||||
Fit,
|
||||
}
|
||||
}
|
57
ShiftOS.Frontend/GUI/ProgressBar.cs
Normal file
57
ShiftOS.Frontend/GUI/ProgressBar.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static ShiftOS.Engine.SkinEngine;
|
||||
|
||||
namespace ShiftOS.Frontend.GUI
|
||||
{
|
||||
public class ProgressBar : Control
|
||||
{
|
||||
private int _maximum = 100;
|
||||
private int _value = 0;
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maximum;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maximum = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Paint(Graphics gfx)
|
||||
{
|
||||
gfx.Clear(LoadedSkin.ProgressBarBackgroundColor);
|
||||
int w = (int)linear(_value, 0, _maximum, 0, Width);
|
||||
gfx.FillRectangle(new SolidBrush(LoadedSkin.ProgressColor), new Rectangle(0, 0, w, Height));
|
||||
}
|
||||
|
||||
static public double linear(double x, double x0, double x1, double y0, double y1)
|
||||
{
|
||||
if ((x1 - x0) == 0)
|
||||
{
|
||||
return (y0 + y1) / 2;
|
||||
}
|
||||
return y0 + (x - x0) * (y1 - y0) / (x1 - x0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -13,6 +13,22 @@ namespace ShiftOS.Frontend.GUI
|
|||
private TextAlign _textAlign = TextAlign.TopLeft;
|
||||
private Font _font = new Font("Tahoma", 9f);
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
if (AutoSize)
|
||||
{
|
||||
using (var bmp = new Bitmap(1, 1))
|
||||
{
|
||||
using(var gfx = Graphics.FromImage(bmp))
|
||||
{
|
||||
var measure = gfx.MeasureString(_text, _font);
|
||||
Width = (int)measure.Width;
|
||||
Height = (int)measure.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return _text; }
|
||||
|
|
46
ShiftOS.Frontend/GUI/TextInput.cs
Normal file
46
ShiftOS.Frontend/GUI/TextInput.cs
Normal file
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShiftOS.Frontend.GraphicsSubsystem;
|
||||
using static ShiftOS.Engine.SkinEngine;
|
||||
|
||||
namespace ShiftOS.Frontend.GUI
|
||||
{
|
||||
public class TextInput : Control
|
||||
{
|
||||
private string _label = "Type here!";
|
||||
private string _text = "";
|
||||
private int _index = 0;
|
||||
|
||||
protected override void OnKeyEvent(KeyEvent e)
|
||||
{
|
||||
if(e.Key == Microsoft.Xna.Framework.Input.Keys.Left)
|
||||
{
|
||||
if (_index > 0)
|
||||
_index--;
|
||||
}
|
||||
if (e.Key == Microsoft.Xna.Framework.Input.Keys.Right)
|
||||
if (_index < _text.Length)
|
||||
_index++;
|
||||
if (e.KeyChar != '\0')
|
||||
_text.Insert(_index, e.KeyChar.ToString());
|
||||
base.OnKeyEvent(e);
|
||||
}
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
base.OnLayout();
|
||||
}
|
||||
|
||||
private int _textOffset = 0;
|
||||
|
||||
public override void Paint(Graphics gfx)
|
||||
{
|
||||
gfx.Clear(LoadedSkin.ControlColor);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||
using Microsoft.Xna.Framework.Input;
|
||||
using ShiftOS.Engine;
|
||||
using ShiftOS.Frontend.Desktop;
|
||||
using ShiftOS.Frontend.GUI;
|
||||
|
||||
namespace ShiftOS.Frontend.GraphicsSubsystem
|
||||
{
|
||||
|
@ -16,6 +17,30 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
|
|||
{
|
||||
private static List<GUI.Control> topLevels = new List<GUI.Control>();
|
||||
|
||||
public static GUI.Control FocusedControl = null;
|
||||
|
||||
public static void LayoutUpdate()
|
||||
{
|
||||
foreach (var toplevel in topLevels)
|
||||
toplevel.Layout();
|
||||
}
|
||||
|
||||
public static void Animate(object owner, System.Reflection.PropertyInfo prop, double from, double to, int timeMs)
|
||||
{
|
||||
var t = new System.Threading.Thread(() =>
|
||||
{
|
||||
for(int i = 0; i < timeMs; i++)
|
||||
{
|
||||
double value = ProgressBar.linear(i, 0, timeMs, from, to);
|
||||
prop.SetValue(owner, value);
|
||||
System.Threading.Thread.Sleep(1);
|
||||
}
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
}
|
||||
|
||||
|
||||
public static void DrawControls(GraphicsDevice graphics, SpriteBatch batch)
|
||||
{
|
||||
foreach (var ctrl in topLevels)
|
||||
|
@ -24,11 +49,19 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
|
|||
{
|
||||
var gfx = System.Drawing.Graphics.FromImage(bmp);
|
||||
ctrl.Paint(gfx);
|
||||
bmp.SetOpacity((float)ctrl.Opacity);
|
||||
//get the bits of the bitmap
|
||||
var data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
byte[] rgb = new byte[Math.Abs(data.Stride) * data.Height];
|
||||
Marshal.Copy(data.Scan0, rgb, 0, rgb.Length);
|
||||
bmp.UnlockBits(data);
|
||||
for(int i = 0; i < rgb.Length; i+=4)
|
||||
{
|
||||
byte r = rgb[i];
|
||||
byte b = rgb[i + 2];
|
||||
rgb[i] = b;
|
||||
rgb[i + 2] = r;
|
||||
}
|
||||
var tex2 = new Texture2D(graphics, bmp.Width, bmp.Height);
|
||||
tex2.SetData<byte>(rgb);
|
||||
batch.Draw(tex2, new Rectangle(ctrl.X, ctrl.Y, ctrl.Width, ctrl.Height), Color.White);
|
||||
|
@ -40,18 +73,21 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
|
|||
{
|
||||
if (!topLevels.Contains(ctrl))
|
||||
topLevels.Add(ctrl);
|
||||
ctrl.Layout();
|
||||
}
|
||||
|
||||
public static void ProcessMouseState(MouseState state)
|
||||
{
|
||||
foreach(var ctrl in topLevels)
|
||||
{
|
||||
if (ctrl.ProcessMouseState(state) == true)
|
||||
break;
|
||||
ctrl.ProcessMouseState(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void ProcessKeyEvent(KeyEvent e)
|
||||
{
|
||||
FocusedControl?.ProcessKeyEvent(e);
|
||||
}
|
||||
|
||||
public static void DrawBackgroundLayer(GraphicsDevice graphics, SpriteBatch batch, int width, int height)
|
||||
{
|
||||
|
@ -79,4 +115,239 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
|
|||
ctrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyEvent
|
||||
{
|
||||
public KeyEvent(bool control, bool alt, bool shift, Keys key)
|
||||
{
|
||||
ControlDown = control;
|
||||
AltDown = alt;
|
||||
ShiftDown = shift;
|
||||
Key = key;
|
||||
KeyChar = key.ToCharacter(shift);
|
||||
}
|
||||
|
||||
public bool ControlDown { get; private set; }
|
||||
public bool AltDown { get; private set; }
|
||||
public bool ShiftDown { get; set; }
|
||||
public Keys Key { get; private set; }
|
||||
|
||||
public char KeyChar { get; private set; }
|
||||
}
|
||||
|
||||
public static class KeysExtensions
|
||||
{
|
||||
public static char ToCharacter(this Keys key, bool shift)
|
||||
{
|
||||
char c = ' ';
|
||||
switch (key)
|
||||
{
|
||||
case Keys.Space:
|
||||
c = ' ';
|
||||
break;
|
||||
case Keys.A:
|
||||
c = 'a';
|
||||
break;
|
||||
case Keys.B:
|
||||
c = 'b';
|
||||
break;
|
||||
case Keys.C:
|
||||
c = 'c';
|
||||
break;
|
||||
case Keys.D:
|
||||
c = 'd';
|
||||
break;
|
||||
case Keys.E:
|
||||
c = 'e';
|
||||
break;
|
||||
case Keys.F:
|
||||
c = 'f';
|
||||
break;
|
||||
case Keys.G:
|
||||
c = 'g';
|
||||
break;
|
||||
case Keys.H:
|
||||
c = 'h';
|
||||
break;
|
||||
case Keys.I:
|
||||
c = 'i';
|
||||
break;
|
||||
case Keys.J:
|
||||
c = 'j';
|
||||
break;
|
||||
case Keys.K:
|
||||
c = 'k';
|
||||
break;
|
||||
case Keys.L:
|
||||
c = 'l';
|
||||
break;
|
||||
case Keys.M:
|
||||
c = 'm';
|
||||
break;
|
||||
case Keys.N:
|
||||
c = 'n';
|
||||
break;
|
||||
case Keys.O:
|
||||
c = 'o';
|
||||
break;
|
||||
case Keys.P:
|
||||
c = 'p';
|
||||
break;
|
||||
case Keys.Q:
|
||||
c = 'q';
|
||||
break;
|
||||
case Keys.R:
|
||||
c = 'r';
|
||||
break;
|
||||
case Keys.S:
|
||||
c = 's';
|
||||
break;
|
||||
case Keys.T:
|
||||
c = 't';
|
||||
break;
|
||||
case Keys.U:
|
||||
c = 'u';
|
||||
break;
|
||||
case Keys.V:
|
||||
c = 'v';
|
||||
break;
|
||||
case Keys.W:
|
||||
c = 'w';
|
||||
break;
|
||||
case Keys.X:
|
||||
c = 'x';
|
||||
break;
|
||||
case Keys.Y:
|
||||
c = 'y';
|
||||
break;
|
||||
case Keys.Z:
|
||||
c = 'z';
|
||||
break;
|
||||
case Keys.D0:
|
||||
if (shift)
|
||||
c = ')';
|
||||
else
|
||||
c = '0';
|
||||
break;
|
||||
case Keys.D1:
|
||||
if (shift)
|
||||
c = '!';
|
||||
else
|
||||
c = '1';
|
||||
break;
|
||||
case Keys.D2:
|
||||
if (shift)
|
||||
c = '@';
|
||||
else
|
||||
c = '2';
|
||||
break;
|
||||
case Keys.D3:
|
||||
if (shift)
|
||||
c = '#';
|
||||
else
|
||||
c = '3';
|
||||
break;
|
||||
case Keys.D4:
|
||||
if (shift)
|
||||
c = '$';
|
||||
else
|
||||
c = '4';
|
||||
break;
|
||||
case Keys.D5:
|
||||
if (shift)
|
||||
c = '%';
|
||||
else
|
||||
c = '5';
|
||||
break;
|
||||
case Keys.D6:
|
||||
if (shift)
|
||||
c = '^';
|
||||
else
|
||||
c = '6';
|
||||
break;
|
||||
case Keys.D7:
|
||||
if (shift)
|
||||
c = '&';
|
||||
else
|
||||
c = '7';
|
||||
break;
|
||||
case Keys.D8:
|
||||
if (shift)
|
||||
c = '*';
|
||||
else
|
||||
c = '8';
|
||||
break;
|
||||
case Keys.D9:
|
||||
if (shift)
|
||||
c = '(';
|
||||
else
|
||||
c = '9';
|
||||
break;
|
||||
case Keys.OemBackslash:
|
||||
if (shift)
|
||||
c = '|';
|
||||
else
|
||||
c = '\\';
|
||||
break;
|
||||
case Keys.OemCloseBrackets:
|
||||
if (shift)
|
||||
c = '}';
|
||||
else
|
||||
c = ']';
|
||||
break;
|
||||
case Keys.OemComma:
|
||||
if (shift)
|
||||
c = '<';
|
||||
else
|
||||
c = ',';
|
||||
break;
|
||||
case Keys.OemPeriod:
|
||||
if (shift)
|
||||
c = '>';
|
||||
else
|
||||
c = '.';
|
||||
break;
|
||||
case Keys.OemQuestion:
|
||||
if (shift)
|
||||
c = '?';
|
||||
else
|
||||
c = '/';
|
||||
break;
|
||||
case Keys.OemSemicolon:
|
||||
if (shift)
|
||||
c = ':';
|
||||
else
|
||||
c = ';';
|
||||
break;
|
||||
case Keys.OemQuotes:
|
||||
if (shift)
|
||||
c = '"';
|
||||
else
|
||||
c = '\'';
|
||||
break;
|
||||
case Keys.OemTilde:
|
||||
if (shift)
|
||||
c = '~';
|
||||
else
|
||||
c = '`';
|
||||
break;
|
||||
case Keys.OemMinus:
|
||||
if (shift)
|
||||
c = '_';
|
||||
else
|
||||
c = '-';
|
||||
break;
|
||||
case Keys.OemPlus:
|
||||
if (shift)
|
||||
c = '+';
|
||||
else
|
||||
c = '=';
|
||||
break;
|
||||
}
|
||||
if (char.IsLetter(c))
|
||||
if (shift)
|
||||
c = char.ToUpper(c);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
179
ShiftOS.Frontend/Infobox.cs
Normal file
179
ShiftOS.Frontend/Infobox.cs
Normal file
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShiftOS.Engine;
|
||||
using ShiftOS.Frontend.GUI;
|
||||
|
||||
namespace ShiftOS.Frontend
|
||||
{
|
||||
public class Infobox : IInfobox
|
||||
{
|
||||
public void Open(string title, string msg, Action callback = null)
|
||||
{
|
||||
var imsg = new InfoboxMessage(title, msg);
|
||||
imsg.ShowPrompt(callback);
|
||||
}
|
||||
|
||||
public void PromptText(string title, string message, Action<string> callback, bool isPassword)
|
||||
{
|
||||
var imsg = new InfoboxMessage(title, message);
|
||||
imsg.ShowText(callback);
|
||||
}
|
||||
|
||||
public void PromptYesNo(string title, string message, Action<bool> callback)
|
||||
{
|
||||
var imsg = new InfoboxMessage(title, message);
|
||||
imsg.ShowYesNo(callback);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class InfoboxMessage : GUI.Control, IShiftOSWindow
|
||||
{
|
||||
public InfoboxMessage(string title, string message)
|
||||
{
|
||||
InitializeComponent();
|
||||
lbmessage.Text = Localization.Parse(message);
|
||||
Title = title;
|
||||
}
|
||||
|
||||
public string Title { get; private set; }
|
||||
|
||||
public void OnLoad()
|
||||
{
|
||||
AppearanceManager.SetWindowTitle(this, Title);
|
||||
}
|
||||
|
||||
public void ShowPrompt(Action callback)
|
||||
{
|
||||
AppearanceManager.SetupDialog(this);
|
||||
flyesno.Visible = false;
|
||||
txtinput.Visible = false;
|
||||
btnok.Visible = true;
|
||||
btnok.Click += callback;
|
||||
}
|
||||
|
||||
public void ShowYesNo(Action<bool> callback)
|
||||
{
|
||||
AppearanceManager.SetupDialog(this);
|
||||
flyesno.Visible = true;
|
||||
txtinput.Visible = false;
|
||||
btnok.Visible = false;
|
||||
btnyes.Click += () =>
|
||||
{
|
||||
callback?.Invoke(true);
|
||||
};
|
||||
btnno.Click += () =>
|
||||
{
|
||||
callback?.Invoke(false);
|
||||
};
|
||||
}
|
||||
|
||||
public void ShowText(Action<string> callback)
|
||||
{
|
||||
Title = "Not yet implemented.";
|
||||
lbmessage.Text = "This feature hasn't yet been implemented.";
|
||||
ShowPrompt(null);
|
||||
|
||||
}
|
||||
|
||||
public void OnSkinLoad()
|
||||
{
|
||||
}
|
||||
|
||||
public bool OnUnload()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnUpgrade()
|
||||
{
|
||||
}
|
||||
|
||||
//NOTE: The following code is ported over from Windows Forms.
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.txtinput = new TextInput();
|
||||
this.lbmessage = new TextControl();
|
||||
this.flyesno = new ItemGroup();
|
||||
this.btnyes = new Button();
|
||||
this.btnno = new Button();
|
||||
this.btnok = new Button();
|
||||
this.pbicon = new PictureBox();
|
||||
//
|
||||
// txtinput
|
||||
//
|
||||
this.txtinput.X = 88;
|
||||
this.txtinput.Y = 116;
|
||||
this.txtinput.Width = 250;
|
||||
this.txtinput.Height = 20;
|
||||
//
|
||||
// lbmessage
|
||||
//
|
||||
this.lbmessage.X = 85;
|
||||
this.lbmessage.Y = 19;
|
||||
this.lbmessage.Width = 253;
|
||||
this.lbmessage.Height = 94;
|
||||
this.lbmessage.Text = "label1";
|
||||
this.lbmessage.TextAlign = TextAlign.MiddleLeft;
|
||||
//
|
||||
// flyesno
|
||||
//
|
||||
this.flyesno.AutoSize = true;
|
||||
this.flyesno.AddControl(this.btnyes);
|
||||
this.flyesno.AddControl(this.btnno);
|
||||
this.flyesno.X = 129;
|
||||
this.flyesno.Y = 134;
|
||||
//
|
||||
// btnyes
|
||||
//
|
||||
this.btnyes.AutoSize = true;
|
||||
this.btnyes.Text = Localization.Parse("{GEN_YES}");
|
||||
//
|
||||
// btnno
|
||||
//
|
||||
this.btnno.AutoSize = true;
|
||||
this.btnno.Text = Localization.Parse("{GEN_NO}");
|
||||
//
|
||||
// btnok
|
||||
//
|
||||
this.btnok.AutoSize = true;
|
||||
this.btnok.Text = Localization.Parse("{GEN_OK}");
|
||||
//
|
||||
// pbicon
|
||||
//
|
||||
this.pbicon.X = 14;
|
||||
this.pbicon.Y = 19;
|
||||
this.pbicon.Width = 64;
|
||||
this.pbicon.Height = 64;
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
this.Width = 341;
|
||||
this.Height = 127;
|
||||
this.AddControl(pbicon);
|
||||
this.AddControl(btnok);
|
||||
this.AddControl(flyesno);
|
||||
this.AddControl(lbmessage);
|
||||
|
||||
this.Layout();
|
||||
}
|
||||
|
||||
|
||||
private Control panel1;
|
||||
private TextControl lbmessage;
|
||||
private ItemGroup flyesno;
|
||||
private Button btnyes;
|
||||
private Button btnno;
|
||||
private Button btnok;
|
||||
private PictureBox pbicon;
|
||||
private TextInput txtinput;
|
||||
|
||||
}
|
||||
}
|
10
ShiftOS.Frontend/Properties/Resources.Designer.cs
generated
10
ShiftOS.Frontend/Properties/Resources.Designer.cs
generated
|
@ -69,5 +69,15 @@ namespace ShiftOS.Frontend.Properties {
|
|||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap justthes {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("justthes", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,4 +121,7 @@
|
|||
<data name="cursor_9x_pointer" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\cursor_9x_pointer.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="justthes" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\justthes.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
BIN
ShiftOS.Frontend/Resources/justthes.png
Normal file
BIN
ShiftOS.Frontend/Resources/justthes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
|
@ -42,10 +42,17 @@
|
|||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Desktop\Desktop.cs" />
|
||||
<Compile Include="Desktop\WindowManager.cs" />
|
||||
<Compile Include="GraphicsSubsystem\UIManager.cs" />
|
||||
<Compile Include="GUI\Button.cs" />
|
||||
<Compile Include="GUI\Control.cs" />
|
||||
<Compile Include="GUI\ItemGroup.cs" />
|
||||
<Compile Include="GUI\PictureBox.cs" />
|
||||
<Compile Include="GUI\ProgressBar.cs" />
|
||||
<Compile Include="GUI\TextControl.cs" />
|
||||
<Compile Include="GUI\TextInput.cs" />
|
||||
<Compile Include="Infobox.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
|
@ -62,6 +69,7 @@
|
|||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -133,6 +141,9 @@
|
|||
<ItemGroup>
|
||||
<None Include="Resources\cursor_9x_pointer.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\justthes.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using ShiftOS.Engine;
|
||||
using ShiftOS.Frontend.GraphicsSubsystem;
|
||||
|
||||
namespace ShiftOS.Frontend
|
||||
|
@ -18,15 +20,14 @@ namespace ShiftOS.Frontend
|
|||
public ShiftOS()
|
||||
{
|
||||
GraphicsDevice = new GraphicsDeviceManager(this);
|
||||
Content.RootDirectory = "Content";
|
||||
//Make the mouse cursor visible.
|
||||
this.IsMouseVisible = true;
|
||||
GraphicsDevice.PreferredBackBufferHeight = 1080;
|
||||
GraphicsDevice.PreferredBackBufferWidth = 1920;
|
||||
|
||||
//Don't allow ALT+F4
|
||||
this.Window.AllowAltF4 = false;
|
||||
Content.RootDirectory = "Content";
|
||||
|
||||
|
||||
//Make window borderless
|
||||
Window.IsBorderless = true;
|
||||
Window.IsBorderless = false;
|
||||
|
||||
//Set the title
|
||||
Window.Title = "ShiftOS";
|
||||
|
@ -34,10 +35,12 @@ namespace ShiftOS.Frontend
|
|||
|
||||
|
||||
//Fullscreen
|
||||
GraphicsDevice.IsFullScreen = true;
|
||||
GraphicsDevice.IsFullScreen = false;
|
||||
|
||||
}
|
||||
|
||||
private GUI.TextControl _titleLabel = null;
|
||||
|
||||
/// <summary>
|
||||
/// Allows the game to perform any initialization it needs to before starting to run.
|
||||
/// This is where it can query for any required services and load any non-graphic
|
||||
|
@ -46,21 +49,39 @@ namespace ShiftOS.Frontend
|
|||
/// </summary>
|
||||
protected override void Initialize()
|
||||
{
|
||||
//We'll start by initializing the BARE FUNDAMENTALS of the ShiftOS engine.
|
||||
//This'll be enough to do skinning, fs, windowmanagement etc
|
||||
//so that we can make the main menu and yeah
|
||||
//Before we do ANYTHING, we've got to initiate the ShiftOS engine.
|
||||
|
||||
//Let's add a control to test something
|
||||
var textControl = new GUI.TextControl();
|
||||
textControl.Width = 640;
|
||||
textControl.Height = 480;
|
||||
UIManager.AddTopLevel(textControl);
|
||||
//First things first, let's initiate the window manager.
|
||||
AppearanceManager.Initiate(new Desktop.WindowManager());
|
||||
//Cool. Now the engine's window management system talks to us.
|
||||
|
||||
UIManager.AddTopLevel(framerate);
|
||||
framerate.Width = 640;
|
||||
framerate.Height = 480;
|
||||
framerate.TextAlign = GUI.TextAlign.BottomRight;
|
||||
|
||||
//Also initiate the desktop
|
||||
Engine.Desktop.Init(new Desktop.Desktop());
|
||||
|
||||
//Now we can initiate the Infobox subsystem
|
||||
Engine.Infobox.Init(new Infobox());
|
||||
|
||||
|
||||
//Let's give it a try.
|
||||
Engine.Infobox.Show("Welcome to ShiftOS!", "This is a test infobox. Clicking OK will dismiss it.");
|
||||
|
||||
//Let's set up the Main Menu UI.
|
||||
|
||||
var justthes = new GUI.PictureBox();
|
||||
justthes.AutoSize = true;
|
||||
justthes.ImageLayout = GUI.ImageLayout.Stretch;
|
||||
justthes.Image = Properties.Resources.justthes;
|
||||
justthes.X = 15;
|
||||
justthes.Y = 15;
|
||||
UIManager.AddTopLevel(justthes);
|
||||
|
||||
_titleLabel = new GUI.TextControl();
|
||||
_titleLabel.Text = " - main menu - ";
|
||||
_titleLabel.AutoSize = true;
|
||||
_titleLabel.X = justthes.X;
|
||||
_titleLabel.Y = justthes.Y + justthes.Height + 15;
|
||||
_titleLabel.Font = SkinEngine.LoadedSkin.HeaderFont;
|
||||
UIManager.AddTopLevel(_titleLabel);
|
||||
|
||||
base.Initialize();
|
||||
|
||||
|
@ -100,9 +121,43 @@ namespace ShiftOS.Frontend
|
|||
//Now let's process it.
|
||||
UIManager.ProcessMouseState(mouseState);
|
||||
|
||||
//Cause layout update on all elements
|
||||
UIManager.LayoutUpdate();
|
||||
|
||||
//set framerate
|
||||
framerate.Text = "ShiftOS 1.0 Beta 4\r\nCopyright (c) 2017 ShiftOS\r\nFPS: " + (1 / gameTime.ElapsedGameTime.TotalSeconds);
|
||||
|
||||
//So we have mouse input, and the UI layout system working...
|
||||
|
||||
//But an OS isn't useful without the keyboard!
|
||||
|
||||
//Let's see how keyboard input works.
|
||||
|
||||
//Hmmm... just like the mouse...
|
||||
var keystate = Keyboard.GetState();
|
||||
|
||||
//Simple... just iterate through this list and generate some key events?
|
||||
var keys = keystate.GetPressedKeys();
|
||||
if (keys.Length > 0)
|
||||
{
|
||||
//Of course, we need modifier keys...
|
||||
//First for Control.
|
||||
bool controlDown = keys.Contains(Keys.LeftControl) || keys.Contains(Keys.RightControl);
|
||||
//Now SHIFT.
|
||||
bool shiftDown = keys.Contains(Keys.LeftShift) || keys.Contains(Keys.RightShift);
|
||||
//And ALT.
|
||||
bool altDown = keys.Contains(Keys.LeftAlt) || keys.Contains(Keys.RightAlt);
|
||||
|
||||
foreach(var key in keys)
|
||||
{
|
||||
//This'll make it so we skip the modifier keys.
|
||||
if(key != Keys.LeftAlt && key != Keys.RightAlt && key != Keys.LeftControl && key != Keys.RightControl && key != Keys.LeftShift && key != Keys.RightShift)
|
||||
{
|
||||
var keyevent = new KeyEvent(controlDown, altDown, shiftDown, key);
|
||||
UIManager.ProcessKeyEvent(keyevent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
|
|
@ -246,7 +246,14 @@ namespace ShiftOS.Engine
|
|||
|
||||
public static void InvokeOnWorkerThread(Action act)
|
||||
{
|
||||
_desktop.InvokeOnWorkerThread(act);
|
||||
try
|
||||
{
|
||||
_desktop.InvokeOnWorkerThread(act);
|
||||
}
|
||||
catch
|
||||
{
|
||||
act?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ResetPanelButtons()
|
||||
|
|
|
@ -99,63 +99,65 @@ namespace ShiftOS.Engine
|
|||
|
||||
public static string Parse(string original, Dictionary<string, string> replace)
|
||||
{
|
||||
Dictionary<string, string> localizationStrings = new Dictionary<string, string>();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(_provider.GetCurrentTranscript());
|
||||
}
|
||||
catch
|
||||
{
|
||||
localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utils.ReadAllText(Paths.GetPath("english.local"))); //if no provider fall back to english
|
||||
}
|
||||
Dictionary<string, string> localizationStrings = new Dictionary<string, string>();
|
||||
|
||||
foreach (var kv in localizationStrings.Where(x=>original.Contains(x.Key)))
|
||||
{
|
||||
original = original.Replace(kv.Key, kv.Value); // goes through and replaces all the localization blocks
|
||||
}
|
||||
|
||||
//string original2 = Parse(original);
|
||||
|
||||
string usernameReplace = "";
|
||||
string domainReplace = "";
|
||||
|
||||
// if the user has saved then store their username and systemname in these string variables please
|
||||
if (SaveSystem.CurrentSave != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
usernameReplace = SaveSystem.CurrentUser.Username;
|
||||
localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(_provider.GetCurrentTranscript());
|
||||
}
|
||||
catch
|
||||
{
|
||||
localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utils.ReadAllText(Paths.GetPath("english.local"))); //if no provider fall back to english
|
||||
}
|
||||
|
||||
foreach (var kv in localizationStrings.Where(x => original.Contains(x.Key)))
|
||||
{
|
||||
original = original.Replace(kv.Key, kv.Value); // goes through and replaces all the localization blocks
|
||||
}
|
||||
|
||||
//string original2 = Parse(original);
|
||||
|
||||
string usernameReplace = "";
|
||||
string domainReplace = "";
|
||||
|
||||
// if the user has saved then store their username and systemname in these string variables please
|
||||
if (SaveSystem.CurrentSave != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
usernameReplace = SaveSystem.CurrentUser.Username;
|
||||
}
|
||||
catch
|
||||
{
|
||||
usernameReplace = "user";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
domainReplace = SaveSystem.CurrentSave.SystemName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
domainReplace = "system";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
string namespaceReplace = "";
|
||||
string commandReplace = "";
|
||||
|
||||
// if the user did a command in the terminal and it had a period in it then split it up into the part before the period and the part after and then store them into these two string variables please
|
||||
if (TerminalBackend.latestCommmand != "" && TerminalBackend.latestCommmand.IndexOf('.') > -1)
|
||||
{
|
||||
domainReplace = SaveSystem.CurrentSave.SystemName;
|
||||
namespaceReplace = TerminalBackend.latestCommmand.Split('.')[0];
|
||||
commandReplace = TerminalBackend.latestCommmand.Split('.')[1];
|
||||
}
|
||||
catch
|
||||
{
|
||||
domainReplace = "system";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
string namespaceReplace = "";
|
||||
string commandReplace = "";
|
||||
|
||||
// if the user did a command in the terminal and it had a period in it then split it up into the part before the period and the part after and then store them into these two string variables please
|
||||
if (TerminalBackend.latestCommmand != "" && TerminalBackend.latestCommmand.IndexOf('.') > -1)
|
||||
{
|
||||
namespaceReplace = TerminalBackend.latestCommmand.Split('.')[0];
|
||||
commandReplace = TerminalBackend.latestCommmand.Split('.')[1];
|
||||
}
|
||||
|
||||
// if you see these then replace them with what you need to
|
||||
Dictionary<string, string> defaultReplace = new Dictionary<string, string>() {
|
||||
// if you see these then replace them with what you need to
|
||||
Dictionary<string, string> defaultReplace = new Dictionary<string, string>() {
|
||||
{"%username", usernameReplace},
|
||||
{"%domain", domainReplace},
|
||||
{"%ns", namespaceReplace},
|
||||
|
@ -165,19 +167,24 @@ namespace ShiftOS.Engine
|
|||
#endif
|
||||
};
|
||||
|
||||
// actually do the replacement
|
||||
foreach (KeyValuePair<string, string> replacement in replace.Where(x => original.Contains(x.Key)))
|
||||
{
|
||||
original = original.Replace(replacement.Key, Parse(replacement.Value));
|
||||
}
|
||||
// actually do the replacement
|
||||
foreach (KeyValuePair<string, string> replacement in replace.Where(x => original.Contains(x.Key)))
|
||||
{
|
||||
original = original.Replace(replacement.Key, Parse(replacement.Value));
|
||||
}
|
||||
|
||||
// do the replacement but default
|
||||
foreach (KeyValuePair<string, string> replacement in defaultReplace.Where(x => original.Contains(x.Key)))
|
||||
{
|
||||
original = original.Replace(replacement.Key, replacement.Value);
|
||||
}
|
||||
// do the replacement but default
|
||||
foreach (KeyValuePair<string, string> replacement in defaultReplace.Where(x => original.Contains(x.Key)))
|
||||
{
|
||||
original = original.Replace(replacement.Key, replacement.Value);
|
||||
}
|
||||
|
||||
return original; // returns the now replaced string
|
||||
return original; // returns the now replaced string
|
||||
}
|
||||
catch
|
||||
{
|
||||
return original;
|
||||
}
|
||||
}
|
||||
|
||||
// a few things are defined here
|
||||
|
|
Reference in a new issue