aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ShiftOS.Frontend/Desktop/Desktop.cs85
-rw-r--r--ShiftOS.Frontend/Desktop/WindowManager.cs180
-rw-r--r--ShiftOS.Frontend/GUI/Button.cs50
-rw-r--r--ShiftOS.Frontend/GUI/Control.cs218
-rw-r--r--ShiftOS.Frontend/GUI/ItemGroup.cs64
-rw-r--r--ShiftOS.Frontend/GUI/PictureBox.cs146
-rw-r--r--ShiftOS.Frontend/GUI/ProgressBar.cs57
-rw-r--r--ShiftOS.Frontend/GUI/TextControl.cs16
-rw-r--r--ShiftOS.Frontend/GUI/TextInput.cs46
-rw-r--r--ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs277
-rw-r--r--ShiftOS.Frontend/Infobox.cs179
-rw-r--r--ShiftOS.Frontend/Properties/Resources.Designer.cs10
-rw-r--r--ShiftOS.Frontend/Properties/Resources.resx3
-rw-r--r--ShiftOS.Frontend/Resources/justthes.pngbin0 -> 10030 bytes
-rw-r--r--ShiftOS.Frontend/ShiftOS.Frontend.csproj11
-rw-r--r--ShiftOS.Frontend/ShiftOS.cs99
-rw-r--r--ShiftOS_TheReturn/Desktop.cs9
-rw-r--r--ShiftOS_TheReturn/Localization.cs105
18 files changed, 1474 insertions, 81 deletions
diff --git a/ShiftOS.Frontend/Desktop/Desktop.cs b/ShiftOS.Frontend/Desktop/Desktop.cs
new file mode 100644
index 0000000..5bcf3a9
--- /dev/null
+++ b/ShiftOS.Frontend/Desktop/Desktop.cs
@@ -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)
+ {
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/Desktop/WindowManager.cs b/ShiftOS.Frontend/Desktop/WindowManager.cs
index d17cd37..2450986 100644
--- a/ShiftOS.Frontend/Desktop/WindowManager.cs
+++ b/ShiftOS.Frontend/Desktop/WindowManager.cs
@@ -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.
+ }
+ }
}
+
}
}
diff --git a/ShiftOS.Frontend/GUI/Button.cs b/ShiftOS.Frontend/GUI/Button.cs
new file mode 100644
index 0000000..c2e41a3
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/Button.cs
@@ -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);
+
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs
index 975c69a..fcbd429 100644
--- a/ShiftOS.Frontend/GUI/Control.cs
+++ b/ShiftOS.Frontend/GUI/Control.cs
@@ -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;
+ }
+ }
}
diff --git a/ShiftOS.Frontend/GUI/ItemGroup.cs b/ShiftOS.Frontend/GUI/ItemGroup.cs
new file mode 100644
index 0000000..e52a17f
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ItemGroup.cs
@@ -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
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/PictureBox.cs b/ShiftOS.Frontend/GUI/PictureBox.cs
new file mode 100644
index 0000000..2447416
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/PictureBox.cs
@@ -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,
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/ProgressBar.cs b/ShiftOS.Frontend/GUI/ProgressBar.cs
new file mode 100644
index 0000000..f0dd626
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/ProgressBar.cs
@@ -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);
+ }
+
+ }
+}
diff --git a/ShiftOS.Frontend/GUI/TextControl.cs b/ShiftOS.Frontend/GUI/TextControl.cs
index c8eb56b..79da213 100644
--- a/ShiftOS.Frontend/GUI/TextControl.cs
+++ b/ShiftOS.Frontend/GUI/TextControl.cs
@@ -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; }
diff --git a/ShiftOS.Frontend/GUI/TextInput.cs b/ShiftOS.Frontend/GUI/TextInput.cs
new file mode 100644
index 0000000..fc142a0
--- /dev/null
+++ b/ShiftOS.Frontend/GUI/TextInput.cs
@@ -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);
+
+ }
+ }
+}
diff --git a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs
index fdd5f99..a688757 100644
--- a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs
+++ b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs
@@ -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;
+ }
+ }
}
diff --git a/ShiftOS.Frontend/Infobox.cs b/ShiftOS.Frontend/Infobox.cs
new file mode 100644
index 0000000..68c681d
--- /dev/null
+++ b/ShiftOS.Frontend/Infobox.cs
@@ -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;
+
+ }
+}
diff --git a/ShiftOS.Frontend/Properties/Resources.Designer.cs b/ShiftOS.Frontend/Properties/Resources.Designer.cs
index b3bb6d7..fc35525 100644
--- a/ShiftOS.Frontend/Properties/Resources.Designer.cs
+++ b/ShiftOS.Frontend/Properties/Resources.Designer.cs
@@ -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));
+ }
+ }
}
}
diff --git a/ShiftOS.Frontend/Properties/Resources.resx b/ShiftOS.Frontend/Properties/Resources.resx
index 9510e93..e309997 100644
--- a/ShiftOS.Frontend/Properties/Resources.resx
+++ b/ShiftOS.Frontend/Properties/Resources.resx
@@ -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> \ No newline at end of file
diff --git a/ShiftOS.Frontend/Resources/justthes.png b/ShiftOS.Frontend/Resources/justthes.png
new file mode 100644
index 0000000..a85ba27
--- /dev/null
+++ b/ShiftOS.Frontend/Resources/justthes.png
Binary files differ
diff --git a/ShiftOS.Frontend/ShiftOS.Frontend.csproj b/ShiftOS.Frontend/ShiftOS.Frontend.csproj
index 48748a9..61ff0c6 100644
--- a/ShiftOS.Frontend/ShiftOS.Frontend.csproj
+++ b/ShiftOS.Frontend/ShiftOS.Frontend.csproj
@@ -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.
diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs
index f50c7d9..a2b1d67 100644
--- a/ShiftOS.Frontend/ShiftOS.cs
+++ b/ShiftOS.Frontend/ShiftOS.cs
@@ -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
-
- //Let's add a control to test something
- var textControl = new GUI.TextControl();
- textControl.Width = 640;
- textControl.Height = 480;
- UIManager.AddTopLevel(textControl);
-
- UIManager.AddTopLevel(framerate);
- framerate.Width = 640;
- framerate.Height = 480;
- framerate.TextAlign = GUI.TextAlign.BottomRight;
-
+ //Before we do ANYTHING, we've got to initiate the ShiftOS engine.
+
+ //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.
+
+ //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);
}
diff --git a/ShiftOS_TheReturn/Desktop.cs b/ShiftOS_TheReturn/Desktop.cs
index fac5e6b..714d457 100644
--- a/ShiftOS_TheReturn/Desktop.cs
+++ b/ShiftOS_TheReturn/Desktop.cs
@@ -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()
diff --git a/ShiftOS_TheReturn/Localization.cs b/ShiftOS_TheReturn/Localization.cs
index 8adfa5a..2414bd9 100644
--- a/ShiftOS_TheReturn/Localization.cs
+++ b/ShiftOS_TheReturn/Localization.cs
@@ -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
- }
-
- 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
- }
+ Dictionary<string, string> localizationStrings = new Dictionary<string, string>();
- //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
{
- usernameReplace = "user";
+ localizationStrings = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utils.ReadAllText(Paths.GetPath("english.local"))); //if no provider fall back to english
}
- try
+ foreach (var kv in localizationStrings.Where(x => original.Contains(x.Key)))
{
- domainReplace = SaveSystem.CurrentSave.SystemName;
+ original = original.Replace(kv.Key, kv.Value); // goes through and replaces all the localization blocks
}
- catch
+
+ //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)
{
- domainReplace = "system";
+ try
+ {
+ usernameReplace = SaveSystem.CurrentUser.Username;
+ }
+ catch
+ {
+ usernameReplace = "user";
+ }
+
+ try
+ {
+ domainReplace = SaveSystem.CurrentSave.SystemName;
+ }
+ catch
+ {
+ domainReplace = "system";
+ }
+
}
-
- }
- string namespaceReplace = "";
- string commandReplace = "";
+ 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 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)))
+ return original; // returns the now replaced string
+ }
+ catch
{
- original = original.Replace(replacement.Key, replacement.Value);
+ return original;
}
-
- return original; // returns the now replaced string
}
// a few things are defined here