diff options
39 files changed, 3144 insertions, 99 deletions
diff --git a/ShiftOS.Frontend/Content/Content.mgcb b/ShiftOS.Frontend/Content/Content.mgcb new file mode 100644 index 0000000..ddc4c36 --- /dev/null +++ b/ShiftOS.Frontend/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + 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 new file mode 100644 index 0000000..5efb30e --- /dev/null +++ b/ShiftOS.Frontend/Desktop/WindowManager.cs @@ -0,0 +1,383 @@ +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 +{ + public class WindowManager : Engine.WindowManager + { + public override void Close(IShiftOSWindow win) + { + var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win); + if (brdr != null) + { + brdr.Close(); + win = null; + } + } + + private List<WindowBorder> RunningBorders = new List<WindowBorder>(); + + public override void InvokeAction(Action act) + { + act?.Invoke(); + } + + public override void Maximize(IWindowBorder border) + { + throw new NotImplementedException(); + } + + public override void Minimize(IWindowBorder border) + { + throw new NotImplementedException(); + } + + public override void SetTitle(IShiftOSWindow win, string title) + { + var brdr = RunningBorders.FirstOrDefault(x => x.ParentWindow == win); + if (brdr != null) + brdr.Text = title; + } + + public override void SetupDialog(IShiftOSWindow win) + { + var wb = new WindowBorder(); + wb.Width = (win as GUI.Control).Width + LoadedSkin.LeftBorderWidth + LoadedSkin.RightBorderWidth; + wb.Height = (win as GUI.Control).Height + LoadedSkin.TitlebarHeight + LoadedSkin.BottomBorderWidth; + wb.ParentWindow = win; + wb.IsDialog = true; + UIManager.AddTopLevel(wb); + RunningBorders.Add(wb); + win.OnLoad(); + win.OnUpgrade(); + win.OnSkinLoad(); + } + + public override void SetupWindow(IShiftOSWindow win) + { + 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(); + + } + } + + public class WindowBorder : GUI.Control, IWindowBorder + { + private string _text = "ShiftOS window"; + private GUI.Control _hostedwindow = null; + + public WindowBorder() + { + X = 720; + Y = 480; + } + + public IShiftOSWindow ParentWindow + { + get + { + return (IShiftOSWindow)_hostedwindow; + } + + set + { + _hostedwindow = (GUI.Control)value; + ClearControls(); + AddControl(_hostedwindow); + Width = (LoadedSkin.LeftBorderWidth*2) + _hostedwindow.Width + LoadedSkin.RightBorderWidth; + Height = LoadedSkin.BottomBorderWidth + _hostedwindow.Height + (LoadedSkin.TitlebarHeight*2); + + } + } + + public bool IsDialog { get; set; } + + public string Text + { + get + { + return _text; + } + + set + { + _text = value; + } + } + + public void Close() + { + Visible = false; + UIManager.StopHandling(this); + } + + private int lastmousex, lastmousey = 0; + + protected override void OnLayout() + { + if (moving) + { + var screenpoint = PointToScreen(MouseX, MouseY); + this.X = lastmousex + screenpoint.X; + this.Y = lastmousey + screenpoint.Y; + } + int titlebarheight = Shiftorium.UpgradeInstalled("wm_titlebar") ? LoadedSkin.TitlebarHeight : 0; + int borderleft = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.LeftBorderWidth : 0; + int borderright = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.RightBorderWidth : 0; + int borderbottom = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.BottomBorderWidth : 0; + _hostedwindow.X = borderleft; + _hostedwindow.Y = titlebarheight; + } + + private bool moving = false; + + public override void MouseStateChanged() + { + if (Shiftorium.UpgradeInstalled("wm_titlebar")) + { + if (Shiftorium.UpgradeInstalled("close_button")) + { + var closebuttonsize = LoadedSkin.CloseButtonSize; + var closebuttonloc = LoadedSkin.CloseButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y); + if(MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height) + { + Close(); + } + } + if (Shiftorium.UpgradeInstalled("minimize_button")) + { + var closebuttonsize = LoadedSkin.MinimizeButtonSize; + var closebuttonloc = LoadedSkin.MinimizeButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y); + if (MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height) + { + if (IsFocusedControl || ContainsFocusedControl) + UIManager.FocusedControl = null; + Visible = false; + } + } + if (Shiftorium.UpgradeInstalled("maximize_button")) + { + var closebuttonsize = LoadedSkin.MaximizeButtonSize; + var closebuttonloc = LoadedSkin.MaximizeButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonloc = new Point(Width - closebuttonsize.Width - closebuttonloc.X, closebuttonloc.Y); + if (MouseX > closebuttonloc.X && MouseY > closebuttonloc.Y && MouseX < closebuttonloc.X + closebuttonsize.Width && MouseY < closebuttonloc.Y + closebuttonsize.Height) + { + AppearanceManager.Maximize(this); + } + } + if (MouseY < LoadedSkin.TitlebarHeight) + { + var screenpoint = PointToScreen(MouseX, MouseY); + lastmousex = this.X - screenpoint.X; + lastmousey = this.Y - screenpoint.Y; + + moving = MouseLeftDown; + CaptureMouse = moving; + } + } + } + + protected override void OnPaint(Graphics gfx) + { + int titleheight = LoadedSkin.TitlebarHeight; + int leftborderwidth = LoadedSkin.LeftBorderWidth; + int rightborderwidth = LoadedSkin.RightBorderWidth; + int bottomborderwidth = LoadedSkin.BottomBorderWidth; + + if (Shiftorium.UpgradeInstalled("wm_titlebar")) + { + var titlebarcolor = LoadedSkin.TitleBackgroundColor; + var titlefont = LoadedSkin.TitleFont; + var titletextcolor = LoadedSkin.TitleTextColor; + var titletextleft = LoadedSkin.TitleTextLeft; + bool titletextcentered = LoadedSkin.TitleTextCentered; + + var titlebarbg = GetImage("titlebar"); + var titlebarlayout = GetImageLayout("titlebar"); + + var drawcorners = LoadedSkin.ShowTitleCorners; + int titlebarleft = 0; + int titlebarwidth = Width; + if (drawcorners) + { + //set titleleft to the first corner width + titlebarleft = LoadedSkin.TitleLeftCornerWidth; + titlebarwidth -= titlebarleft; + titlebarwidth -= LoadedSkin.TitleRightCornerWidth; + + //Let's get the left and right images. + var leftimage = GetImage("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")) + { + var closebuttoncolor = LoadedSkin.CloseButtonColor; + var closebuttonsize = LoadedSkin.CloseButtonSize; + var closebuttonright = LoadedSkin.CloseButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y); + + gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize)); + + } + //Draw maximize button + if (Shiftorium.UpgradeInstalled("maximize_button")) + { + var closebuttoncolor = LoadedSkin.MaximizeButtonColor; + var closebuttonsize = LoadedSkin.MaximizeButtonSize; + var closebuttonright = LoadedSkin.MaximizeButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y); + + gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize)); + + } + //Draw minimize button + if (Shiftorium.UpgradeInstalled("minimize_button")) + { + var closebuttoncolor = LoadedSkin.MinimizeButtonColor; + var closebuttonsize = LoadedSkin.MinimizeButtonSize; + var closebuttonright = LoadedSkin.MinimizeButtonFromSide; + if (LoadedSkin.TitleButtonPosition == 0) + closebuttonright = new Point(Width - closebuttonsize.Width - closebuttonright.X, closebuttonright.Y); + + gfx.FillRectangle(new SolidBrush(closebuttoncolor), new Rectangle(closebuttonright, closebuttonsize)); + + } + } + else + { + //Set the titleheight to 0. + titleheight = 0; + + } + + if (Shiftorium.UpgradeInstalled("window_borders")) + { + //Some variables we'll need... + int bottomlocy = Height - LoadedSkin.BottomBorderWidth; + int bottomlocx = leftborderwidth; + int bottomwidth = Width - bottomlocx - rightborderwidth; + int brightlocx = Width - rightborderwidth; + + var borderleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderLeftBackground : LoadedSkin.BorderInactiveLeftBackground; + var borderrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderRightBackground : LoadedSkin.BorderInactiveRightBackground; + var borderbottomcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomBackground : LoadedSkin.BorderInactiveBottomBackground; + var borderbleftcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomLeftBackground : LoadedSkin.BorderInactiveBottomLeftBackground; + var borderbrightcolor = (ContainsFocusedControl || IsFocusedControl) ? LoadedSkin.BorderBottomRightBackground : LoadedSkin.BorderInactiveBottomRightBackground; + + + //draw border corners + //BOTTOM LEFT + gfx.FillRectangle(new SolidBrush(borderbleftcolor), new Rectangle(0, bottomlocy, leftborderwidth, bottomborderwidth)); + + + //BOTTOM RIGHT + gfx.FillRectangle(new SolidBrush(borderbrightcolor), new Rectangle(brightlocx, bottomlocy, rightborderwidth, bottomborderwidth)); + + //BOTTOM + gfx.FillRectangle(new SolidBrush(borderbottomcolor), new Rectangle(bottomlocx, bottomlocy, bottomwidth, bottomborderwidth)); + + //LEFT + gfx.FillRectangle(new SolidBrush(borderleftcolor), new Rectangle(0, titleheight, leftborderwidth, Height - titleheight - bottomborderwidth)); + + //RIGHT + gfx.FillRectangle(new SolidBrush(borderrightcolor), new Rectangle(brightlocx, titleheight, rightborderwidth, Height - titleheight - bottomborderwidth)); + + + } + + //So here's what we're gonna do now. + //Now that we have a titlebar and window borders... + //We're going to composite the hosted window + //and draw it to the remaining area. + + //Painting of the canvas is done by the Paint() method. + } + + } +} diff --git a/ShiftOS.Frontend/GUI/Button.cs b/ShiftOS.Frontend/GUI/Button.cs new file mode 100644 index 0000000..551d0d4 --- /dev/null +++ b/ShiftOS.Frontend/GUI/Button.cs @@ -0,0 +1,49 @@ +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 + 16; + Height = borderwidth + (int)measure.Height + 12; + } + } + } + + protected override void OnPaint(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.OnPaint(gfx); + + } + } +} diff --git a/ShiftOS.Frontend/GUI/Control.cs b/ShiftOS.Frontend/GUI/Control.cs new file mode 100644 index 0000000..90e7ba5 --- /dev/null +++ b/ShiftOS.Frontend/GUI/Control.cs @@ -0,0 +1,642 @@ +using System; +using System.Collections.Generic; +using System.Linq; +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 +{ + public abstract class Control + { + private int _x = 0; + private int _y = 0; + private int _w = 0; + private int _h = 0; + private Control _parent = null; + private List<Control> _children = new List<Control>(); + private bool _wasMouseInControl = false; + private bool _leftState = false; + 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; + private bool _invalidated = true; + private Bitmap _texCache = null; + private Anchor _anchor = null; + private int _mouseX = 0; + private int _mouseY = 0; + private bool _captureMouse = false; + + public bool CaptureMouse + { + get + { + return _captureMouse; + } + set + { + _captureMouse = value; + } + } + + public int MouseX + { + get + { + return _mouseX; + } + } + + public int MouseY + { + get + { + return _mouseY; + } + } + + + public Anchor Anchor + { + get + { + return _anchor; + } + set + { + _anchor = value; + Invalidate(); + } + } + + public void Invalidate() + { + _invalidated = true; + foreach(var child in _children) + { + child.Invalidate(); + } + } + + public double Opacity + { + get + { + return _opacity; + } + set + { + _opacity = value; + Invalidate(); + } + } + + 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 + { + get + { + return _visible; + } + set + { + _visible = value; + Invalidate(); + } + } + + public void AddControl(Control ctrl) + { + if (!_children.Contains(ctrl)) + { + ctrl._parent = this; + _children.Add(ctrl); + Invalidate(); + } + } + + public bool MouseLeftDown + { + get + { + return _leftState; + } + } + + public bool MouseMiddleDown + { + get + { + return _middleState; + } + } + + public bool MouseRightDown + { + get + { + return _rightState; + } + } + + + + public int X + { + get + { + return _x; + } + set + { + _x = value; + Invalidate(); + } + } + + public int Y + { + get + { + return _y; + } + set + { + _y = value; + Invalidate(); + } + } + + public int Width + { + get + { + return _w; + } + set + { + _w = value; + Invalidate(); + } + } + + public int Height + { + get + { + return _h; + } + set + { + _h = value; + Invalidate(); + } + } + + public Control Parent + { + get + { + return _parent; + } + } + + public Control[] Children + { + get + { + return _children.ToArray(); + } + } + + public Point PointToParent(int x, int y) + { + return new Point(x + _x, y + _y); + } + + public Point PointToScreen(int x, int y) + { + var parentCoords = PointToParent(x, y); + Control parent = this._parent; + while(parent != null) + { + parentCoords = parent.PointToParent(parentCoords.X, parentCoords.Y); + parent = parent.Parent; + } + return parentCoords; + } + + public void ClearControls() + { + _children.Clear(); + Invalidate(); + } + + public Point PointToLocal(int x, int y) + { + return new GUI.Point(x - _x, y - _y); + } + + public virtual void MouseStateChanged() { } + + protected virtual void OnPaint(Graphics gfx) + { + + } + + public void InvalidateTopLevel() + { + var parent = this; + while (parent.Parent != null) + parent = parent.Parent; + parent.Invalidate(); + } + + public void Paint(System.Drawing.Graphics gfx) + { + if (_visible == true) + { + if (_invalidated) + { + _texCache = new Bitmap(Width, Height); + using (var cGfx = Graphics.FromImage(_texCache)) + { + OnPaint(cGfx); + } + _invalidated = false; + } + gfx.DrawImage(_texCache, 0, 0); + foreach (var child in _children) + { + if (child.Visible) + { + if (child._invalidated) + { + var cBmp = new Bitmap(child.Width, child.Height); + child.Paint(System.Drawing.Graphics.FromImage(cBmp)); + cBmp.SetOpacity((float)child.Opacity); + child._invalidated = false; + child._texCache = cBmp; + gfx.DrawImage(cBmp, new System.Drawing.Point(child.X, child.Y)); + + + + } + else + { + gfx.DrawImage(child._texCache, child.X, child.Y); + } + } + } + + } + } + + public void Layout() + { + //Dock style + if(_parent != null) + { + if(_anchor != 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. + if (_visible == false) + return false; + + + //Firstly, we get the mouse coordinates in the local space + var coords = PointToLocal(state.Position.X, state.Position.Y); + _mouseX = coords.X; + _mouseY = coords.Y; + //Now we check if the mouse is within the bounds of the control + if(coords.X >= 0 && coords.Y >= 0 && coords.X <= _w && coords.Y <= _h) + { + //We're in the local space. Let's fire the MouseMove event. + MouseMove?.Invoke(coords); + //Also, if the mouse hasn't been in the local space last time it moved, fire MouseEnter. + if(_wasMouseInControl == false) + { + _wasMouseInControl = true; + MouseEnter?.Invoke(); + Invalidate(); + } + + //Things are going to get a bit complicated. + //Firstly, we need to find out if we have any children. + bool _requiresMoreWork = true; + if(_children.Count > 0) + { + //We do. We're going to iterate through them all and process the mouse state. + foreach(var control in _children) + { + + //If the process method returns true, then we do not need to do anything else on our end. + + //We need to first create a new mousestate object with the new coordinates + + var nstate = new MouseState(coords.X, coords.Y, state.ScrollWheelValue, state.LeftButton, state.MiddleButton, state.RightButton, state.XButton1, state.XButton2); + //pass that state to the process method, and set the _requiresMoreWork value to the opposite of the return value + _requiresMoreWork = !control.ProcessMouseState(nstate); + //If it's false, break the loop. + if (_requiresMoreWork == false) + break; + } + } + + //If we need to do more work... + if(_requiresMoreWork == true) + { + bool fire = false; //so we know to fire a MouseStateChanged method + //Let's get the state values of each button + bool ld = state.LeftButton == ButtonState.Pressed; + bool md = state.MiddleButton == ButtonState.Pressed; + bool rd = state.RightButton == ButtonState.Pressed; + if(ld != _leftState || md != _middleState || rd != _rightState) + { + fire = true; + } + if (_leftState == true && ld == false) + { + Click?.Invoke(); + Invalidate(); + } + if (_leftState == false && ld == true) + { + var focused = UIManager.FocusedControl; + UIManager.FocusedControl = this; + focused?.InvalidateTopLevel(); + InvalidateTopLevel(); + } + _leftState = ld; + _middleState = md; + _rightState = rd; + if (fire) + MouseStateChanged(); + } + return true; + } + else + { + _leftState = false; + _rightState = false; + _middleState = false; + MouseStateChanged(); + //If the mouse was in local space before, fire MouseLeave + if (_wasMouseInControl == true) + { + if (CaptureMouse == true) + { + _wasMouseInControl = true; + int newX = MathHelper.Clamp(state.X, X, X + Width); + int newY = MathHelper.Clamp(state.Y, Y, Y + Height); + Mouse.SetPosition(newX, newY); + + } + else + { + _wasMouseInControl = false; + MouseLeave?.Invoke(); + Invalidate(); + } + } + } + if (CaptureMouse == true) + { + _mouseX = coords.X; + _mouseY = coords.Y; + Layout(); + _wasMouseInControl = true; + int newX = MathHelper.Clamp(state.X, X, X + Width); + int newY = MathHelper.Clamp(state.Y, Y, Y + Height); + Mouse.SetPosition(newX, newY); + return true; + } + + //Mouse is not in the local space, don't do anything. + 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 + { + public Point(int x, int y) + { + X = x; + Y = y; + } + + public int X { get; set; } + 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; + } + } + + [Flags] + public enum AnchorStyle + { + Top, + Left, + Bottom, + Right + } + + public class Anchor + { + public AnchorStyle Style { get; set; } + public int Distance { get; set; } + } +} 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..9a234d4 --- /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; + } + } + + protected override void OnPaint(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..e35dc27 --- /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; + } + } + + protected override void OnPaint(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 new file mode 100644 index 0000000..37b9ca7 --- /dev/null +++ b/ShiftOS.Frontend/GUI/TextControl.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShiftOS.Frontend.GUI +{ + public class TextControl : Control + { + private string _text = "Text Control"; + 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; } + set { _text = value; } + } + + public Font Font + { + get + { + return _font; + } + set + { + _font = value; + } + } + + public TextAlign TextAlign + { + get { return _textAlign; } + set { _textAlign = value; } + } + + protected override void OnPaint(Graphics gfx) + { + var sMeasure = gfx.MeasureString(_text, _font, Width); + PointF loc = new PointF(2, 2); + float centerH = (Width - sMeasure.Width) / 2; + float centerV = (Height - sMeasure.Height) / 2; + switch (_textAlign) + { + case TextAlign.TopCenter: + loc.X = centerH; + break; + case TextAlign.TopRight: + loc.X = Width - sMeasure.Width; + break; + case TextAlign.MiddleLeft: + loc.Y = centerV; + break; + case TextAlign.MiddleCenter: + loc.Y = centerV; + loc.X = centerH; + break; + case TextAlign.MiddleRight: + loc.Y = centerV; + loc.X = (Width - sMeasure.Width); + break; + case TextAlign.BottomLeft: + loc.Y = (Height - sMeasure.Height); + break; + case TextAlign.BottomCenter: + loc.Y = (Height - sMeasure.Height); + loc.X = centerH; + break; + case TextAlign.BottomRight: + loc.Y = (Height - sMeasure.Height); + loc.X = (Width - sMeasure.Width); + break; + + + } + + gfx.DrawString(_text, _font, new SolidBrush(Color.White), new RectangleF(loc.X, loc.Y, sMeasure.Width, sMeasure.Height)); + } + } + + public enum TextAlign + { + TopLeft, + TopCenter, + TopRight, + MiddleLeft, + MiddleCenter, + MiddleRight, + BottomLeft, + BottomCenter, + BottomRight + } +} diff --git a/ShiftOS.Frontend/GUI/TextInput.cs b/ShiftOS.Frontend/GUI/TextInput.cs new file mode 100644 index 0000000..7466cfd --- /dev/null +++ b/ShiftOS.Frontend/GUI/TextInput.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +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; + private Font _font = new Font("Tahoma", 9f); + + 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 = _text.Insert(_index, e.KeyChar.ToString()); + _index++; + } + CalculateVisibleText(); + Invalidate(); + base.OnKeyEvent(e); + } + + private int textInputOffset = 0; + private int maxCanFit = 5; + string visibleText = ""; + float caretPos = 2f; + + protected void CalculateVisibleText() + { + visibleText = ""; + caretPos = -1f; + using (var gfx = Graphics.FromImage(new Bitmap(1, 1))) + { + for (int i = textInputOffset; i < _text.Length; i++) + { + visibleText += _text[i]; + var measure = gfx.MeasureString(visibleText, _font); + if (measure.Width > Width) + { + maxCanFit = visibleText.Length; + if(_index < textInputOffset) + { + textInputOffset = MathHelper.Clamp(_index - (maxCanFit / 2), 0, _text.Length - 1); + + } + if(_index > textInputOffset + maxCanFit) + { + textInputOffset = MathHelper.Clamp(_index + (maxCanFit / 2), 0, _text.Length - 1) - maxCanFit; + } + break; + } + Height = (int)measure.Height + 4; + } + } + } + + + protected override void OnPaint(Graphics gfx) + { + gfx.Clear(LoadedSkin.ControlColor); + gfx.DrawString(visibleText, _font, new SolidBrush(LoadedSkin.ControlTextColor), 2, 2); + if (IsFocusedControl) + { + //Draw caret. + gfx.FillRectangle(new SolidBrush(LoadedSkin.ControlTextColor), new RectangleF(caretPos, 2, 2, Height - 4)); + } + gfx.DrawRectangle(new Pen(new SolidBrush(LoadedSkin.ControlTextColor), 1), new Rectangle(0, 0, Width - 1, Height - 1)); + + + } + } +} diff --git a/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs new file mode 100644 index 0000000..372c5a6 --- /dev/null +++ b/ShiftOS.Frontend/GraphicsSubsystem/UIManager.cs @@ -0,0 +1,353 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Xna.Framework; +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 +{ + public static class UIManager + { + 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.ToArray()) + { + using(var bmp = new System.Drawing.Bitmap(ctrl.Width, ctrl.Height)) + { + 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); + } + } + } + + public static void AddTopLevel(GUI.Control ctrl) + { + if (!topLevels.Contains(ctrl)) + topLevels.Add(ctrl); + ctrl.Layout(); + } + + public static void ProcessMouseState(MouseState state) + { + foreach(var ctrl in topLevels.ToArray()) + { + ctrl.ProcessMouseState(state); + } + } + + public static void ProcessKeyEvent(KeyEvent e) + { + FocusedControl?.ProcessKeyEvent(e); + } + + public static void DrawBackgroundLayer(GraphicsDevice graphics, SpriteBatch batch, int width, int height) + { + if (SkinEngine.LoadedSkin == null) + SkinEngine.Init(); + graphics.Clear(SkinEngine.LoadedSkin.DesktopColor.ToMonoColor()); + var desktopbg = SkinEngine.GetImage("desktopbackground"); + if(desktopbg != null) + { + var tex2 = new Texture2D(graphics, desktopbg.Width, desktopbg.Height); + tex2.SetData<byte>(SkinEngine.LoadedSkin.DesktopBackgroundImage); + batch.Draw(tex2, new Rectangle(0, 0, width, height), Color.White); + } + } + + public static Color ToMonoColor(this System.Drawing.Color color) + { + return new Color(color.R, color.G, color.B, color.A); + } + + internal static void StopHandling(GUI.Control ctrl) + { + if (topLevels.Contains(ctrl)) + topLevels.Remove(ctrl); + 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/Icon.bmp b/ShiftOS.Frontend/Icon.bmp Binary files differnew file mode 100644 index 0000000..2b48165 --- /dev/null +++ b/ShiftOS.Frontend/Icon.bmp diff --git a/ShiftOS.Frontend/Icon.ico b/ShiftOS.Frontend/Icon.ico Binary files differnew file mode 100644 index 0000000..7d9dec1 --- /dev/null +++ b/ShiftOS.Frontend/Icon.ico diff --git a/ShiftOS.Frontend/Infobox.cs b/ShiftOS.Frontend/Infobox.cs new file mode 100644 index 0000000..53b4857 --- /dev/null +++ b/ShiftOS.Frontend/Infobox.cs @@ -0,0 +1,189 @@ +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?.Invoke(); + AppearanceManager.Close(this); + }; + } + + public void ShowYesNo(Action<bool> callback) + { + AppearanceManager.SetupDialog(this); + flyesno.Visible = true; + txtinput.Visible = false; + btnok.Visible = false; + btnyes.Click += () => + { + callback?.Invoke(true); + AppearanceManager.Close(this); + }; + btnno.Click += () => + { + callback?.Invoke(false); + AppearanceManager.Close(this); + }; + } + + 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 = 213; + 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.X = 140; + this.btnok.Y = 140; + this.btnok.Text = Localization.Parse("{GEN_OK}"); + // + // pbicon + // + this.pbicon.X = 14; + this.pbicon.Y = 19; + this.pbicon.Width = 64; + this.pbicon.Height = 64; + this.pbicon.Image = Properties.Resources.justthes; + this.pbicon.ImageLayout = ImageLayout.Stretch; + // + // Dialog + // + this.Width = 341; + this.Height = 157; + 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/Program.cs b/ShiftOS.Frontend/Program.cs new file mode 100644 index 0000000..031b2ab --- /dev/null +++ b/ShiftOS.Frontend/Program.cs @@ -0,0 +1,20 @@ +using System; + +namespace ShiftOS.Frontend +{ + /// <summary> + /// The main class. + /// </summary> + public static class Program + { + /// <summary> + /// The main entry point for the application. + /// </summary> + [STAThread] + static void Main() + { + using (var game = new ShiftOS()) + game.Run(); + } + } +} diff --git a/ShiftOS.Frontend/Properties/AssemblyInfo.cs b/ShiftOS.Frontend/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f25b1d7 --- /dev/null +++ b/ShiftOS.Frontend/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ShiftOS.Frontend")] +[assembly: AssemblyProduct("ShiftOS.Frontend")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("13e2a4c8-a6cc-405b-a4ec-5d39531993c2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ShiftOS.Frontend/Properties/Resources.Designer.cs b/ShiftOS.Frontend/Properties/Resources.Designer.cs new file mode 100644 index 0000000..fc35525 --- /dev/null +++ b/ShiftOS.Frontend/Properties/Resources.Designer.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace ShiftOS.Frontend.Properties { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ShiftOS.Frontend.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// </summary> + internal static System.Drawing.Bitmap cursor_9x_pointer { + get { + object obj = ResourceManager.GetObject("cursor_9x_pointer", resourceCulture); + 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 new file mode 100644 index 0000000..e309997 --- /dev/null +++ b/ShiftOS.Frontend/Properties/Resources.resx @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <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/cursor_9x_pointer.png b/ShiftOS.Frontend/Resources/cursor_9x_pointer.png Binary files differnew file mode 100644 index 0000000..ff48150 --- /dev/null +++ b/ShiftOS.Frontend/Resources/cursor_9x_pointer.png diff --git a/ShiftOS.Frontend/Resources/justthes.png b/ShiftOS.Frontend/Resources/justthes.png Binary files differnew file mode 100644 index 0000000..a85ba27 --- /dev/null +++ b/ShiftOS.Frontend/Resources/justthes.png diff --git a/ShiftOS.Frontend/ShiftOS.Frontend.csproj b/ShiftOS.Frontend/ShiftOS.Frontend.csproj new file mode 100644 index 0000000..61ff0c6 --- /dev/null +++ b/ShiftOS.Frontend/ShiftOS.Frontend.csproj @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ShiftOS.Frontend</RootNamespace> + <AssemblyName>ShiftOS.Frontend</AssemblyName> + <FileAlignment>512</FileAlignment> + <MonoGamePlatform>DesktopGL</MonoGamePlatform> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath> + <DefineConstants>DEBUG;TRACE;LINUX</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <Prefer32Bit>false</Prefer32Bit> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> + <OutputPath>bin\$(MonoGamePlatform)\$(Platform)\$(Configuration)\</OutputPath> + <DefineConstants>TRACE;LINUX</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <Prefer32Bit>false</Prefer32Bit> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>Icon.ico</ApplicationIcon> + </PropertyGroup> + <PropertyGroup> + <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> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="ShiftOS.cs" /> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Window.cs" /> + </ItemGroup> + <ItemGroup> + <Reference Include="MonoGame.Framework"> + <HintPath>$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Icon.ico" /> + <EmbeddedResource Include="Icon.bmp" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <MonoGameContentReference Include="Content\Content.mgcb" /> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\SDL2.dll"> + <Link>x86\SDL2.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\SDL2.dll"> + <Link>x64\SDL2.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\soft_oal.dll"> + <Link>x86\soft_oal.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\soft_oal.dll"> + <Link>x64\soft_oal.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\libSDL2-2.0.so.0"> + <Link>x86\libSDL2-2.0.so.0</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\libSDL2-2.0.so.0"> + <Link>x64\libSDL2-2.0.so.0</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x86\libopenal.so.1"> + <Link>x86\libopenal.so.1</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\x64\libopenal.so.1"> + <Link>x64\libopenal.so.1</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\libSDL2-2.0.0.dylib"> + <Link>libSDL2-2.0.0.dylib</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\libopenal.1.dylib"> + <Link>libopenal.1.dylib</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="$(MonoGameInstallDirectory)\MonoGame\v3.0\Assemblies\DesktopGL\MonoGame.Framework.dll.config"> + <Link>MonoGame.Framework.dll.config</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + <None Include="app.manifest" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\ShiftOS.Objects\ShiftOS.Objects.csproj"> + <Project>{a069089a-8962-4607-b2b2-4cf4a371066e}</Project> + <Name>ShiftOS.Objects</Name> + </ProjectReference> + <ProjectReference Include="..\ShiftOS_TheReturn\ShiftOS.Engine.csproj"> + <Project>{7c979b07-0585-4033-a110-e5555b9d6651}</Project> + <Name>ShiftOS.Engine</Name> + </ProjectReference> + </ItemGroup> + <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. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/ShiftOS.Frontend/ShiftOS.cs b/ShiftOS.Frontend/ShiftOS.cs new file mode 100644 index 0000000..6bfa4dc --- /dev/null +++ b/ShiftOS.Frontend/ShiftOS.cs @@ -0,0 +1,240 @@ +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 +{ + /// <summary> + /// This is the main type for your game. + /// </summary> + public class ShiftOS : Game + { + GraphicsDeviceManager GraphicsDevice; + SpriteBatch spriteBatch; + + public ShiftOS() + { + GraphicsDevice = new GraphicsDeviceManager(this); + GraphicsDevice.PreferredBackBufferHeight = 1080; + GraphicsDevice.PreferredBackBufferWidth = 1920; + + Content.RootDirectory = "Content"; + + + //Make window borderless + Window.IsBorderless = false; + + //Set the title + Window.Title = "ShiftOS"; + + + + //Fullscreen + 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 + /// related content. Calling base.Initialize will enumerate through any components + /// and initialize them as well. + /// </summary> + protected override void Initialize() + { + //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 initiate the engine just for a ha. + + //We'll create a few UI elements when the save system loads + SaveSystem.GameReady += () => + { + var headerLabel = new GUI.TextControl(); + headerLabel.Font = SkinEngine.LoadedSkin.HeaderFont; + headerLabel.AutoSize = true; + headerLabel.Text = "ShiftOS engine startup stats"; + headerLabel.X = 30; + headerLabel.Y = 30; + UIManager.AddTopLevel(headerLabel); + + var statslabel = new GUI.TextControl(); + statslabel.AutoSize = true; + statslabel.X = 30; + statslabel.Y = headerLabel.Y + headerLabel.Height + 30; + UIManager.AddTopLevel(statslabel); + statslabel.Text = $@"Save System +======================= + +System name: {SaveSystem.CurrentSave.SystemName} +Users: {SaveSystem.CurrentSave.Users.Count} + +Current user: {SaveSystem.CurrentUser.Username} + +Sandbox mode: {SaveSystem.IsSandbox} +Installed upgrades: {SaveSystem.CurrentSave.CountUpgrades()} - may be inaccurate if in sandbox mode +Available upgrades: {Shiftorium.GetAvailable().Count()} +Total upgrades: {Shiftorium.GetDefaults().Count()} + +ShiftFS +============================ + +Mounted file systems: {Objects.ShiftFS.Utils.Mounts.Count} + +Reflection Manager +===================== + +Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime types that ShiftOS can reflect over. + + +"; + statslabel.Layout(); + }; + + //We'll use sandbox mode + SaveSystem.IsSandbox = true; + + SaveSystem.Begin(); + + var textinput = new GUI.TextInput(); + textinput.Width = 250; + textinput.Height = 20; + textinput.X = 0; + textinput.Y = 0; + UIManager.AddTopLevel(textinput); + + base.Initialize(); + + } + + /// <summary> + /// LoadContent will be called once per game and is the place to load + /// all of your content. + /// </summary> + protected override void LoadContent() + { + // Create a new SpriteBatch, which can be used to draw textures. + this.spriteBatch = new SpriteBatch(base.GraphicsDevice); + + // TODO: use this.Content to load your game content here + } + + /// <summary> + /// UnloadContent will be called once per game and is the place to unload + /// game-specific content. + /// </summary> + protected override void UnloadContent() + { + // TODO: Unload any non ContentManager content here + } + + /// <summary> + /// Allows the game to run logic such as updating the world, + /// checking for collisions, gathering input, and playing audio. + /// </summary> + /// <param name="gameTime">Provides a snapshot of timing values.</param> + protected override void Update(GameTime gameTime) + { + //Let's get the mouse state + var mouseState = Mouse.GetState(this.Window); + + //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); + } + + private GUI.TextControl framerate = new GUI.TextControl(); + + /// <summary> + /// This is called when the game should draw itself. + /// </summary> + /// <param name="gameTime">Provides a snapshot of timing values.</param> + protected override void Draw(GameTime gameTime) + { + this.spriteBatch.Begin(); + //Draw the desktop BG. + var graphics = GraphicsDevice.GraphicsDevice; + UIManager.DrawBackgroundLayer(graphics, spriteBatch, 640, 480); + + //The desktop is drawn, now we can draw the UI. + UIManager.DrawControls(graphics, spriteBatch); + + //Draw a mouse cursor + + + var bmp = Properties.Resources.cursor_9x_pointer; + 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); + var mousepos = Mouse.GetState(this.Window).Position; + var tex2 = new Texture2D(graphics, bmp.Width, bmp.Height); + tex2.SetData<byte>(rgb); + spriteBatch.Draw(tex2, new Rectangle(mousepos.X, mousepos.Y, bmp.Width, bmp.Height), Color.White); + + + + spriteBatch.End(); + base.Draw(gameTime); + } + } +} diff --git a/ShiftOS.Frontend/Window.cs b/ShiftOS.Frontend/Window.cs new file mode 100644 index 0000000..4fd08a5 --- /dev/null +++ b/ShiftOS.Frontend/Window.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ShiftOS.Engine; + +namespace ShiftOS.Frontend +{ + public abstract class Window : IShiftOSWindow + { + public void OnLoad() + { + throw new NotImplementedException(); + } + + public void OnSkinLoad() + { + throw new NotImplementedException(); + } + + public bool OnUnload() + { + throw new NotImplementedException(); + } + + public void OnUpgrade() + { + throw new NotImplementedException(); + } + } +} diff --git a/ShiftOS.Frontend/app.manifest b/ShiftOS.Frontend/app.manifest new file mode 100644 index 0000000..048d329 --- /dev/null +++ b/ShiftOS.Frontend/app.manifest @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> + <assemblyIdentity version="1.0.0.0" name="ShiftOS.Frontend"/> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> + </requestedPrivileges> + </security> + </trustInfo> + + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- A list of the Windows versions that this application has been tested on and is + is designed to work with. Uncomment the appropriate elements and Windows will + automatically selected the most compatible environment. --> + + <!-- Windows Vista --> + <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" /> + + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" /> + + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" /> + + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /> + + <!-- Windows 10 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> + + </application> + </compatibility> + + <application xmlns="urn:schemas-microsoft-com:asm.v3"> + <windowsSettings> + <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> + </windowsSettings> + </application> + +</assembly> diff --git a/ShiftOS.Objects/ShiftOS.Objects.csproj b/ShiftOS.Objects/ShiftOS.Objects.csproj index 9ed8c3b..4936c01 100644 --- a/ShiftOS.Objects/ShiftOS.Objects.csproj +++ b/ShiftOS.Objects/ShiftOS.Objects.csproj @@ -9,8 +9,9 @@ <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>ShiftOS.Objects</RootNamespace> <AssemblyName>ShiftOS.Objects</AssemblyName> - <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> + <TargetFrameworkProfile /> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/ShiftOS.WinForms/Program.cs b/ShiftOS.WinForms/Program.cs index c73f067..7b3acfa 100644 --- a/ShiftOS.WinForms/Program.cs +++ b/ShiftOS.WinForms/Program.cs @@ -50,7 +50,6 @@ namespace ShiftOS.WinForms Application.SetCompatibleTextRenderingDefault(false); //if ANYONE puts code before those two winforms config lines they will be declared a drunky. - Michael SkinEngine.SetPostProcessor(new DitheringSkinPostProcessor()); - LoginManager.Init(new GUILoginFrontend()); CrashHandler.SetGameMetadata(Assembly.GetExecutingAssembly()); SkinEngine.SetIconProber(new ShiftOSIconProvider()); TerminalBackend.TerminalRequested += () => diff --git a/ShiftOS/App.config b/ShiftOS/App.config new file mode 100644 index 0000000..88fa402 --- /dev/null +++ b/ShiftOS/App.config @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> + </startup> +</configuration>
\ No newline at end of file diff --git a/ShiftOS/Program.cs b/ShiftOS/Program.cs new file mode 100644 index 0000000..42ed8bc --- /dev/null +++ b/ShiftOS/Program.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShiftOS +{ + class Program + { + static void Main(string[] args) + { + } + } +} diff --git a/ShiftOS/Properties/AssemblyInfo.cs b/ShiftOS/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..dc8476a --- /dev/null +++ b/ShiftOS/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ShiftOS")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ShiftOS")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("518dae89-d558-4118-bd21-71246f356caf")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ShiftOS/ShiftOS.csproj b/ShiftOS/ShiftOS.csproj new file mode 100644 index 0000000..af6b643 --- /dev/null +++ b/ShiftOS/ShiftOS.csproj @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{518DAE89-D558-4118-BD21-71246F356CAF}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ShiftOS</RootNamespace> + <AssemblyName>ShiftOS</AssemblyName> + <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/ShiftOS/packages.config b/ShiftOS/packages.config new file mode 100644 index 0000000..5cd6937 --- /dev/null +++ b/ShiftOS/packages.config @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="MonoGame.Framework.WindowsDX" version="3.6.0.1625" targetFramework="net452" /> +</packages>
\ No newline at end of file diff --git a/ShiftOS_TheReturn.sln b/ShiftOS_TheReturn.sln index 04f0c5d..b14cb3f 100644 --- a/ShiftOS_TheReturn.sln +++ b/ShiftOS_TheReturn.sln @@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModLauncher", "ModLauncher\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShiftOS.Updater", "ShiftOS.Updater\ShiftOS.Updater.csproj", "{36BC512F-6FD4-4139-AED7-565FC8D5BCBC}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShiftOS.Frontend", "ShiftOS.Frontend\ShiftOS.Frontend.csproj", "{4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +65,10 @@ Global {36BC512F-6FD4-4139-AED7-565FC8D5BCBC}.Debug|Any CPU.Build.0 = Debug|Any CPU {36BC512F-6FD4-4139-AED7-565FC8D5BCBC}.Release|Any CPU.ActiveCfg = Release|Any CPU {36BC512F-6FD4-4139-AED7-565FC8D5BCBC}.Release|Any CPU.Build.0 = Release|Any CPU + {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DFC3088-1B08-4A0E-A9F5-483A7B9811FD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ShiftOS_TheReturn/App.config b/ShiftOS_TheReturn/App.config index b899c11..4765378 100644 --- a/ShiftOS_TheReturn/App.config +++ b/ShiftOS_TheReturn/App.config @@ -1,27 +1,27 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <configuration> <startup> - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> </startup> <runtime> - <loadFromRemoteSources enabled="true" /> + <loadFromRemoteSources enabled="true"/> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> - <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" /> + <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/> + <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/> </dependentAssembly> <dependentAssembly> - <assemblyIdentity name="System.Interactive.Async" publicKeyToken="94bc3704cddfc263" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-3.0.1000.0" newVersion="3.0.1000.0" /> + <assemblyIdentity name="System.Interactive.Async" publicKeyToken="94bc3704cddfc263" culture="neutral"/> + <bindingRedirect oldVersion="0.0.0.0-3.0.1000.0" newVersion="3.0.1000.0"/> </dependentAssembly> <dependentAssembly> - <assemblyIdentity name="Microsoft.Scripting" publicKeyToken="7f709c5b713576e1" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-1.1.2.22" newVersion="1.1.2.22" /> + <assemblyIdentity name="Microsoft.Scripting" publicKeyToken="7f709c5b713576e1" culture="neutral"/> + <bindingRedirect oldVersion="0.0.0.0-1.1.2.22" newVersion="1.1.2.22"/> </dependentAssembly> <dependentAssembly> - <assemblyIdentity name="IronPython" publicKeyToken="7f709c5b713576e1" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-2.7.7.0" newVersion="2.7.7.0" /> + <assemblyIdentity name="IronPython" publicKeyToken="7f709c5b713576e1" culture="neutral"/> + <bindingRedirect oldVersion="0.0.0.0-2.7.7.0" newVersion="2.7.7.0"/> </dependentAssembly> </assemblyBinding> </runtime> -</configuration>
\ No newline at end of file +</configuration> 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 diff --git a/ShiftOS_TheReturn/Properties/Resources.Designer.cs b/ShiftOS_TheReturn/Properties/Resources.Designer.cs index 85b350f..bfadf74 100644 --- a/ShiftOS_TheReturn/Properties/Resources.Designer.cs +++ b/ShiftOS_TheReturn/Properties/Resources.Designer.cs @@ -82,7 +82,17 @@ namespace ShiftOS.Engine.Properties { } /// <summary> - /// Looks up a localized string similar to . + /// Looks up a localized string similar to /* + /// * MIT License + /// * + /// * Copyright (c) 2017 Michael VanOverbeek and ShiftOS devs + /// * + /// * Permission is hereby granted, free of charge, to any person obtaining a copy + /// * of this software and associated documentation files (the "Software"), to deal + /// * in the Software without restriction, including without limitation the rights + /// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + /// * copies of the Software, and to permit persons to whom the Software is + /// * furnished to do so, sub [rest of string was truncated]";. /// </summary> internal static string pywintemplate { get { @@ -108,8 +118,7 @@ namespace ShiftOS.Engine.Properties { /// { /// Name: "WM 4 Windows", /// Cost: 150, - /// Description: "Display up to 4 simultaneous windows on-screen in a 2x2 grid.", - /// [rest of string was truncated]";. + /// Description: "Display up to 4 simultaneous windows on-screen i [rest of string was truncated]";. /// </summary> internal static string Shiftorium { get { @@ -138,8 +147,7 @@ namespace ShiftOS.Engine.Properties { ///Eine kurze Erklärung wie du das Terminal benutzt lautet wiefolgt. Du kannst das command 'sos.help' benutzen um eine Liste aller commands aufzurufen. Schreib es ///einfach in das Terminal und drücke <enter> um alle commands anzuzeigen. /// - ///Commands können mit argumenten versehen werden, indem du ein key-value Paar in einem {} Block hinter dem command angibst. Zum Beispiel: - /// [rest of string was truncated]";. + ///Commands können mit argumenten versehen werden, indem du ein key-value Paar in einem {} Block hinter dem command angibst. Zum Be [rest of string was truncated]";. /// </summary> internal static string strings_de { get { @@ -158,8 +166,7 @@ namespace ShiftOS.Engine.Properties { ///Commands can be sent arguments by specifying a key-value pair inside a {} block at the end of the command. For example: /// ///some.command{print:\"hello\"} - ///math.add{op1:1,op2:2} - /// [rest of string was truncated]";. + ///math.add{op1 [rest of string was truncated]";. /// </summary> internal static string strings_en { get { @@ -177,7 +184,7 @@ namespace ShiftOS.Engine.Properties { /// "Before you can begin with ShiftOS, you'll need to know a few things about it.", /// "One: Terminal command syntax.", /// "Inside ShiftOS, the bulk of your time is going to be spent within the Terminal.", - /// "The Terminal is an application that starts up when you turn on your computer. It allows you to execute system commands, open program [rest of string was truncated]";. + /// "The Terminal is an application that starts up when you turn on your computer. It allows you to execute system commands, ope [rest of string was truncated]";. /// </summary> internal static string sys_shiftoriumstory { get { diff --git a/ShiftOS_TheReturn/Properties/Settings.Designer.cs b/ShiftOS_TheReturn/Properties/Settings.Designer.cs index 3d7c7cd..a1e2e32 100644 --- a/ShiftOS_TheReturn/Properties/Settings.Designer.cs +++ b/ShiftOS_TheReturn/Properties/Settings.Designer.cs @@ -1,28 +1,4 @@ -/* - * MIT License - * - * Copyright (c) 2017 Michael VanOverbeek and ShiftOS devs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // Runtime Version:4.0.30319.42000 diff --git a/ShiftOS_TheReturn/ShiftOS.Engine.csproj b/ShiftOS_TheReturn/ShiftOS.Engine.csproj index f1946ad..02a5eeb 100644 --- a/ShiftOS_TheReturn/ShiftOS.Engine.csproj +++ b/ShiftOS_TheReturn/ShiftOS.Engine.csproj @@ -9,7 +9,7 @@ <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>ShiftOS.Engine</RootNamespace> <AssemblyName>ShiftOS.Engine</AssemblyName> - <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <PublishUrl>publish\</PublishUrl> @@ -27,6 +27,7 @@ <IsWebBootstrapper>false</IsWebBootstrapper> <UseApplicationTrust>false</UseApplicationTrust> <BootstrapperEnabled>true</BootstrapperEnabled> + <TargetFrameworkProfile /> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/ShiftOS_TheReturn/Shiftorium.cs b/ShiftOS_TheReturn/Shiftorium.cs index 0362566..e4c2a08 100644 --- a/ShiftOS_TheReturn/Shiftorium.cs +++ b/ShiftOS_TheReturn/Shiftorium.cs @@ -426,7 +426,7 @@ namespace ShiftOS.Engine try { if (SaveSystem.CurrentSave == null) - return false; + return true; if (SaveSystem.CurrentSave.StoriesExperienced == null) SaveSystem.CurrentSave.StoriesExperienced = new List<string>(); |
