Port over the Terminal
This commit is contained in:
parent
d23c5cc29d
commit
3e65bf26fd
6 changed files with 204 additions and 99 deletions
|
@ -1,9 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using ShiftOS.Engine;
|
||||
using ShiftOS.Frontend.GraphicsSubsystem;
|
||||
using static ShiftOS.Engine.SkinEngine;
|
||||
|
@ -58,11 +61,17 @@ namespace ShiftOS.Frontend.Apps
|
|||
|
||||
public class TerminalControl : GUI.TextInput, ITerminalWidget
|
||||
{
|
||||
public TerminalControl()
|
||||
{
|
||||
Dock = GUI.DockStyle.Fill;
|
||||
|
||||
}
|
||||
|
||||
public string[] Lines
|
||||
{
|
||||
get
|
||||
{
|
||||
return Text.Split(new[] { "\n" }, StringSplitOptions.None);
|
||||
return Text.Split(new[] { "\r\n" }, StringSplitOptions.None);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +96,8 @@ namespace ShiftOS.Frontend.Apps
|
|||
{
|
||||
Engine.Desktop.InvokeOnWorkerThread(() =>
|
||||
{
|
||||
Text += text;
|
||||
SelectBottom();
|
||||
Text = Text.Insert(Index, text);
|
||||
Index += text.Length;
|
||||
RecalculateLayout();
|
||||
InvalidateTopLevel();
|
||||
|
@ -126,66 +135,168 @@ namespace ShiftOS.Frontend.Apps
|
|||
{
|
||||
var cursorpos = GetPointAtIndex(gfx);
|
||||
var caretSize = gfx.SmartMeasureString(Text.ToString(), LoadedSkin.TerminalFont, Width - 4);
|
||||
float initial = ((caretSize.Height) - cursorpos.Y) - _vertOffset;
|
||||
float initial = (((float)Math.Floor(caretSize.Height)) + cursorpos.Y) - _vertOffset;
|
||||
if (initial < 0)
|
||||
{
|
||||
float difference = initial - Height;
|
||||
_vertOffset += initial + difference;
|
||||
_vertOffset = initial + difference;
|
||||
}
|
||||
if (initial > Height)
|
||||
{
|
||||
float difference = initial - Height;
|
||||
_vertOffset -= initial - difference;
|
||||
_vertOffset = initial - difference;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLayout()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the X and Y coordinates (in pixels) of the caret.
|
||||
/// </summary>
|
||||
/// <param name="gfx">A <see cref="System.Drawing.Graphics"/> object used for font measurements</param>
|
||||
/// <returns>An absolute fucking mess. Seriously, can someone fix this method so it uhh WORKS PROPERLY?</returns>
|
||||
public PointF GetPointAtIndex(Graphics gfx)
|
||||
public Point GetPointAtIndex(Graphics gfx)
|
||||
{
|
||||
float vertMeasure = 2.0f;
|
||||
float horizMeasure = 2.0f;
|
||||
int lineindexes = 0;
|
||||
for (int l = 0; l <= GetCurrentLine(); l++)
|
||||
{
|
||||
var measure = gfx.SmartMeasureString(Lines[l], LoadedSkin.TerminalFont, Width - 4);
|
||||
vertMeasure += measure.Width;
|
||||
if(l == GetCurrentLine())
|
||||
int vertMeasure = 2;
|
||||
int horizMeasure = 2;
|
||||
var textSize = gfx.SmartMeasureString(Text, LoadedSkin.TerminalFont, Width - 4);
|
||||
for(int i = 0; i <= Index && i < Text.Length; i++)
|
||||
{
|
||||
var size = gfx.SmartMeasureString((Text[i] == '\n') ? " " : Text[i].ToString(), LoadedSkin.TerminalFont);
|
||||
if (Text[i] == '\n' || horizMeasure > Width - 4)
|
||||
{
|
||||
string _linetext = Text.Substring(lineindexes, Index - lineindexes);
|
||||
var lMeasure = gfx.SmartMeasureString(_linetext, LoadedSkin.TerminalFont);
|
||||
horizMeasure = lMeasure.Width;
|
||||
if (horizMeasure > Width - 4)
|
||||
horizMeasure -= (Width-4);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineindexes += Lines[l].Length;
|
||||
horizMeasure = 2;
|
||||
vertMeasure += (int)Math.Ceiling(size.Height);
|
||||
continue;
|
||||
}
|
||||
|
||||
horizMeasure += (int)Math.Floor(size.Width);
|
||||
}
|
||||
return new PointF(horizMeasure, vertMeasure);
|
||||
return new Point(horizMeasure, vertMeasure);
|
||||
}
|
||||
|
||||
protected override void OnKeyEvent(KeyEvent e)
|
||||
protected override void OnKeyEvent(KeyEvent a)
|
||||
{
|
||||
if (e.Key == Microsoft.Xna.Framework.Input.Keys.Enter)
|
||||
if (a.Key == Keys.Enter)
|
||||
{
|
||||
Text = Text.Insert(Index, "\r\n");
|
||||
Index++;
|
||||
try
|
||||
{
|
||||
if (!TerminalBackend.PrefixEnabled)
|
||||
{
|
||||
string textraw = Lines[Lines.Length - 1];
|
||||
TerminalBackend.SendText(textraw);
|
||||
return;
|
||||
}
|
||||
var text = Lines;
|
||||
var text2 = text[text.Length - 1];
|
||||
var text3 = "";
|
||||
var text4 = Regex.Replace(text2, @"\t|\n|\r", "");
|
||||
|
||||
{
|
||||
if (TerminalBackend.PrefixEnabled)
|
||||
{
|
||||
text3 = text4.Remove(0, $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ".Length);
|
||||
}
|
||||
TerminalBackend.LastCommand = text3;
|
||||
TerminalBackend.SendText(text4);
|
||||
if (TerminalBackend.InStory == false)
|
||||
{
|
||||
{
|
||||
var result = SkinEngine.LoadedSkin.CurrentParser.ParseCommand(text3);
|
||||
|
||||
if (result.Equals(default(KeyValuePair<string, Dictionary<string, string>>)))
|
||||
{
|
||||
Console.WriteLine("{ERR_SYNTAXERROR}");
|
||||
}
|
||||
else
|
||||
{
|
||||
TerminalBackend.InvokeCommand(result.Key, result.Value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (TerminalBackend.PrefixEnabled)
|
||||
{
|
||||
TerminalBackend.PrintPrompt();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
else if (a.Key == Keys.Back)
|
||||
{
|
||||
try
|
||||
{
|
||||
var tostring3 = Lines[Lines.Length - 1];
|
||||
var tostringlen = tostring3.Length + 1;
|
||||
var workaround = $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ";
|
||||
var derp = workaround.Length + 1;
|
||||
if (tostringlen != derp)
|
||||
{
|
||||
AppearanceManager.CurrentPosition--;
|
||||
base.OnKeyEvent(a);
|
||||
RecalculateLayout();
|
||||
InvalidateTopLevel();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.WriteLine("Drunky alert in terminal.");
|
||||
}
|
||||
}
|
||||
else if (a.Key == Keys.Left)
|
||||
{
|
||||
if (SaveSystem.CurrentSave != null)
|
||||
{
|
||||
var getstring = Lines[Lines.Length - 1];
|
||||
var stringlen = getstring.Length + 1;
|
||||
var header = $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ";
|
||||
var headerlen = header.Length + 1;
|
||||
var selstart = Index;
|
||||
var remstrlen = Text.Length - stringlen;
|
||||
var finalnum = selstart - remstrlen;
|
||||
|
||||
if (finalnum != headerlen)
|
||||
{
|
||||
AppearanceManager.CurrentPosition--;
|
||||
base.OnKeyEvent(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (a.Key == Keys.Up)
|
||||
{
|
||||
var tostring3 = Lines[Lines.Length - 1];
|
||||
if (tostring3 == $"{SaveSystem.CurrentUser.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ")
|
||||
Console.Write(TerminalBackend.LastCommand);
|
||||
ConsoleEx.OnFlush?.Invoke();
|
||||
return;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TerminalBackend.InStory)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (a.KeyChar != '\0')
|
||||
{
|
||||
base.OnKeyEvent(a);
|
||||
AppearanceManager.CurrentPosition++;
|
||||
RecalculateLayout();
|
||||
InvalidateTopLevel();
|
||||
}
|
||||
}
|
||||
base.OnKeyEvent(e);
|
||||
RecalculateLayout();
|
||||
InvalidateTopLevel();
|
||||
}
|
||||
|
||||
protected override void OnPaint(Graphics gfx)
|
||||
{
|
||||
RecalculateLayout();
|
||||
{
|
||||
gfx.Clear(LoadedSkin.TerminalBackColorCC.ToColor());
|
||||
if (!string.IsNullOrEmpty(Text))
|
||||
{
|
||||
|
@ -257,7 +368,8 @@ namespace ShiftOS.Frontend.Apps
|
|||
var textformat = new StringFormat(StringFormat.GenericTypographic);
|
||||
textformat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
|
||||
textformat.Trimming = StringTrimming.None;
|
||||
return gfx.MeasureString(s, font, width, textformat);
|
||||
var measure = gfx.MeasureString(s, font, width, textformat);
|
||||
return new SizeF((float)Math.Floor(measure.Width), (float)Math.Floor(measure.Height));
|
||||
}
|
||||
|
||||
public static SizeF SmartMeasureString(this Graphics gfx, string s, Font font)
|
||||
|
@ -267,7 +379,8 @@ namespace ShiftOS.Frontend.Apps
|
|||
var textformat = new StringFormat(StringFormat.GenericTypographic);
|
||||
textformat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
|
||||
textformat.Trimming = StringTrimming.None;
|
||||
return gfx.MeasureString(s, font, int.MaxValue, textformat);
|
||||
var measure = gfx.MeasureString(s, font, int.MaxValue, textformat);
|
||||
return new SizeF((float)Math.Floor(measure.Width), (float)Math.Floor(measure.Height));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,6 +60,20 @@ namespace ShiftOS.Frontend.Desktop
|
|||
win.OnSkinLoad();
|
||||
}
|
||||
|
||||
private int MaxCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Shiftorium.UpgradeInstalled("wm_unlimited_windows"))
|
||||
return int.MaxValue;
|
||||
if (Shiftorium.UpgradeInstalled("wm_4_windows"))
|
||||
return 4;
|
||||
if (Shiftorium.UpgradeInstalled("wm_2_windows"))
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetupWindow(IShiftOSWindow win)
|
||||
{
|
||||
if (!Shiftorium.UpgradeAttributesUnlocked(win.GetType()))
|
||||
|
@ -67,6 +81,11 @@ namespace ShiftOS.Frontend.Desktop
|
|||
Console.WriteLine("Application not found on system.");
|
||||
return;
|
||||
}
|
||||
while(AppearanceManager.OpenForms.Count > MaxCount)
|
||||
{
|
||||
AppearanceManager.OpenForms[0].Close();
|
||||
AppearanceManager.OpenForms.RemoveAt(0);
|
||||
}
|
||||
var wb = new WindowBorder();
|
||||
wb.Width = (win as GUI.Control).Width + LoadedSkin.LeftBorderWidth + LoadedSkin.RightBorderWidth;
|
||||
wb.Height = (win as GUI.Control).Height + LoadedSkin.TitlebarHeight + LoadedSkin.BottomBorderWidth;
|
||||
|
@ -78,7 +97,23 @@ namespace ShiftOS.Frontend.Desktop
|
|||
win.OnLoad();
|
||||
win.OnUpgrade();
|
||||
win.OnSkinLoad();
|
||||
if (!Shiftorium.UpgradeInstalled("wm_free_placement"))
|
||||
{
|
||||
TileWindows();
|
||||
}
|
||||
}
|
||||
|
||||
public void TileWindows()
|
||||
{
|
||||
if (AppearanceManager.OpenForms.Count == 0)
|
||||
return;
|
||||
else if(AppearanceManager.OpenForms.Count == 1)
|
||||
{
|
||||
var wb = (WindowBorder)AppearanceManager.OpenForms[0];
|
||||
wb.X = 0;
|
||||
wb.Y = 0;
|
||||
wb.ResizeWindow(UIManager.Viewport.Width, UIManager.Viewport.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +122,19 @@ namespace ShiftOS.Frontend.Desktop
|
|||
private string _text = "ShiftOS window";
|
||||
private GUI.Control _hostedwindow = null;
|
||||
|
||||
public void ResizeWindow(int width, int height)
|
||||
{
|
||||
int titleheight = Shiftorium.UpgradeInstalled("wm_titlebar") ? LoadedSkin.TitlebarHeight : 0;
|
||||
int leftwidth = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.LeftBorderWidth : 0;
|
||||
int bottomheight = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.BottomBorderWidth : 0;
|
||||
int rightwidth = Shiftorium.UpgradeInstalled("window_borders") ? LoadedSkin.RightBorderWidth : 0;
|
||||
_hostedwindow.Width = width - leftwidth - rightwidth;
|
||||
_hostedwindow.Height = width - bottomheight - titleheight;
|
||||
Width = width;
|
||||
Height = height;
|
||||
|
||||
}
|
||||
|
||||
public WindowBorder()
|
||||
{
|
||||
X = 720;
|
||||
|
|
|
@ -32,9 +32,7 @@ namespace ShiftOS.Frontend.GUI
|
|||
_index = 0;
|
||||
return;
|
||||
}
|
||||
_index = MathHelper.Clamp(value, 0, _text.Length - 1);
|
||||
if (_text[_index] == '\n')
|
||||
_index++;
|
||||
_index = MathHelper.Clamp(value, 0, _text.Length);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace ShiftOS.Frontend.GraphicsSubsystem
|
|||
public static class UIManager
|
||||
{
|
||||
private static List<GUI.Control> topLevels = new List<GUI.Control>();
|
||||
|
||||
public static System.Drawing.Size Viewport { get; set; }
|
||||
public static GUI.Control FocusedControl = null;
|
||||
|
||||
public static void LayoutUpdate()
|
||||
|
|
|
@ -22,6 +22,10 @@ namespace ShiftOS.Frontend
|
|||
GraphicsDevice = new GraphicsDeviceManager(this);
|
||||
GraphicsDevice.PreferredBackBufferHeight = 1080;
|
||||
GraphicsDevice.PreferredBackBufferWidth = 1920;
|
||||
UIManager.Viewport = new System.Drawing.Size(
|
||||
GraphicsDevice.PreferredBackBufferWidth,
|
||||
GraphicsDevice.PreferredBackBufferHeight
|
||||
);
|
||||
|
||||
Content.RootDirectory = "Content";
|
||||
|
||||
|
@ -64,55 +68,8 @@ namespace ShiftOS.Frontend
|
|||
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();
|
||||
};
|
||||
|
||||
|
||||
TerminalBackend.TerminalRequested += () =>
|
||||
{
|
||||
AppearanceManager.SetupWindow(new Apps.Terminal());
|
||||
|
@ -123,17 +80,6 @@ Reflection manager found {ReflectMan.Types.Count()} Common Language Runtime type
|
|||
|
||||
SaveSystem.Begin(true);
|
||||
|
||||
var textinput = new GUI.TextInput();
|
||||
textinput.Width = 250;
|
||||
textinput.Height = 20;
|
||||
textinput.X = 0;
|
||||
textinput.Y = 0;
|
||||
UIManager.AddTopLevel(textinput);
|
||||
|
||||
framerate.Width = GraphicsDevice.PreferredBackBufferWidth;
|
||||
framerate.Height = GraphicsDevice.PreferredBackBufferHeight;
|
||||
framerate.TextAlign = GUI.TextAlign.BottomRight;
|
||||
|
||||
base.Initialize();
|
||||
|
||||
}
|
||||
|
|
|
@ -426,7 +426,7 @@ namespace ShiftOS.Engine
|
|||
try
|
||||
{
|
||||
if (SaveSystem.CurrentSave == null)
|
||||
return true;
|
||||
return false;
|
||||
|
||||
if (SaveSystem.CurrentSave.StoriesExperienced == null)
|
||||
SaveSystem.CurrentSave.StoriesExperienced = new List<string>();
|
||||
|
|
Reference in a new issue