Files
CMLeonOS/Gui/Apps/CodeStudio/Ide.cs
2026-03-01 21:34:43 +08:00

323 lines
10 KiB
C#

using CMLeonOS;
using CMLeonOS.Gui.UILib;
using Cosmos.System.Graphics;
using System.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using UniLua;
namespace CMLeonOS.Gui.Apps.CodeStudio
{
internal class Ide
{
internal Ide(Process process, WindowManager wm)
{
this.process = process;
this.wm = wm;
}
[IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.CodeStudio.Run.bmp")]
private static byte[] _runBytes;
private static Bitmap runBitmap = new Bitmap(_runBytes);
Process process;
WindowManager wm;
AppWindow mainWindow;
Button runButton;
TextBox editor;
TextBox problems;
TextBox output;
private const int headersHeight = 24;
private const int problemsHeight = 128;
private const int outputHeight = 128;
private string? path = null;
private bool modified = false;
private void TextChanged()
{
modified = true;
UpdateTitle();
}
private static class Theme
{
internal static Color Background = Color.FromArgb(68, 76, 84);
internal static Color CodeBackground = Color.FromArgb(41, 46, 51);
}
private void UpdateTitle()
{
if (path == null)
{
mainWindow.Title = "Untitled - Lua CodeStudio";
return;
}
if (modified)
{
mainWindow.Title = $"{Path.GetFileName(path)}* - Lua CodeStudio";
}
else
{
mainWindow.Title = $"{Path.GetFileName(path)} - Lua CodeStudio";
}
}
internal void Open(string newPath, bool readFile = true)
{
if (newPath == null) return;
if (readFile && !File.Exists(newPath))
{
MessageBox messageBox = new MessageBox(process, "Lua CodeStudio", $"No such file '{Path.GetFileName(newPath)}'.");
messageBox.Show();
}
path = newPath;
if (readFile)
{
editor.Text = File.ReadAllText(path);
editor.MarkAllLines();
editor.Render();
modified = false;
}
UpdateTitle();
}
private void OpenFilePrompt()
{
PromptBox prompt = new PromptBox(process, "Open File", "Enter the path to open.", "Path", (string newPath) =>
{
if (!newPath.Contains(':'))
{
newPath = $@"0:\{newPath}";
}
Open(newPath);
});
prompt.Show();
}
private void SaveAsPrompt()
{
PromptBox prompt = new PromptBox(process, "Save As", "Enter the path to save to.", "Path", (string newPath) =>
{
if (!newPath.Contains(':'))
{
newPath = $@"0:\{newPath}";
}
Open(newPath, readFile: false);
// Check if open succeeded.
if (path != null)
{
Save();
}
});
prompt.Show();
}
private void Save()
{
if (path == null)
{
SaveAsPrompt();
return;
}
File.WriteAllText(path, editor.Text);
modified = false;
UpdateTitle();
}
private void RunClicked(int x, int y)
{
try
{
output.Text = "";
ILuaState lua = LuaAPI.NewState();
lua.L_OpenLibs();
lua.PushCSharpFunction(L =>
{
int n = L.GetTop();
string result = "";
for (int i = 1; i <= n; i++)
{
if (i > 1) result += "\t";
LuaType type = L.Type(i);
if (type == LuaType.LUA_TSTRING)
{
result += L.ToString(i);
}
else if (type == LuaType.LUA_TBOOLEAN)
{
result += L.ToBoolean(i) ? "true" : "false";
}
else if (type == LuaType.LUA_TNUMBER)
{
result += L.ToNumber(i).ToString();
}
else if (type == LuaType.LUA_TNIL)
{
result += "nil";
}
}
output.Text += result + "\n";
return 0;
});
lua.SetGlobal("print");
UniLua.ThreadStatus loadResult = lua.L_LoadString(editor.Text);
if (loadResult == UniLua.ThreadStatus.LUA_OK)
{
UniLua.ThreadStatus callResult = lua.PCall(0, 0, 0);
if (callResult == UniLua.ThreadStatus.LUA_OK)
{
problems.Foreground = Color.LimeGreen;
problems.Text = "Execution successful";
}
else
{
string errorMsg = lua.ToString(-1);
problems.Foreground = Color.Pink;
problems.Text = $"Script execution error: {errorMsg}";
}
}
else
{
string errorMsg = lua.ToString(-1);
problems.Foreground = Color.Pink;
problems.Text = $"Script load error: {errorMsg}";
}
}
catch (Exception e)
{
problems.Foreground = Color.Pink;
problems.Text = e.Message;
}
}
private void Evaluate()
{
try
{
ILuaState lua = LuaAPI.NewState();
lua.L_OpenLibs();
UniLua.ThreadStatus loadResult = lua.L_LoadString(editor.Text);
if (loadResult == UniLua.ThreadStatus.LUA_OK)
{
problems.Foreground = Color.LimeGreen;
problems.Text = "No syntax errors";
}
else
{
string errorMsg = lua.ToString(-1);
if (string.IsNullOrWhiteSpace(errorMsg))
{
problems.Foreground = Color.Pink;
problems.Text = "Script load error: Unknown error";
}
else
{
problems.Foreground = Color.Pink;
problems.Text = $"Script load error: {errorMsg}";
}
}
}
catch (Exception e)
{
problems.Foreground = Color.Pink;
problems.Text = e.Message;
}
}
internal void Start()
{
mainWindow = new AppWindow(process, 96, 96, 800, 600);
mainWindow.Clear(Theme.Background);
mainWindow.Closing = process.TryStop;
UpdateTitle();
wm.AddWindow(mainWindow);
runButton = new Button(mainWindow, 0, 0, 60, headersHeight);
runButton.Background = Theme.Background;
runButton.Border = Theme.Background;
runButton.Foreground = Color.White;
runButton.Text = "Run";
runButton.Image = runBitmap;
runButton.ImageLocation = Button.ButtonImageLocation.Left;
runButton.OnClick = RunClicked;
wm.AddWindow(runButton);
editor = new TextBox(mainWindow, 0, headersHeight, mainWindow.Width, mainWindow.Height - headersHeight - problemsHeight - outputHeight - (headersHeight * 3))
{
Background = Theme.CodeBackground,
Foreground = Color.White,
Text = "print(\"Hello World!\")",
Changed = TextChanged,
MultiLine = true
};
wm.AddWindow(editor);
problems = new TextBox(mainWindow, 0, headersHeight + editor.Height + headersHeight, mainWindow.Width, problemsHeight + (headersHeight * 2))
{
Background = Theme.CodeBackground,
Foreground = Color.Gray,
Text = "Click Evaluate to check your program for syntax errors.",
ReadOnly = true,
MultiLine = true
};
wm.AddWindow(problems);
mainWindow.DrawString("Problems", Color.White, 0, headersHeight + editor.Height);
output = new TextBox(mainWindow, 0, headersHeight + editor.Height + problemsHeight + (headersHeight * 2), mainWindow.Width, outputHeight + (headersHeight * 2))
{
Background = Theme.CodeBackground,
Foreground = Color.White,
Text = "Output will appear here...",
ReadOnly = true,
MultiLine = true
};
wm.AddWindow(output);
mainWindow.DrawString("Output", Color.White, 0, headersHeight + editor.Height + problemsHeight + headersHeight);
var shortcutBar = new ShortcutBar(mainWindow, runButton.Width, 0, mainWindow.Width - runButton.Width, headersHeight)
{
Background = Theme.Background,
Foreground = Color.White
};
shortcutBar.Cells.Add(new ShortcutBarCell("Open", OpenFilePrompt));
shortcutBar.Cells.Add(new ShortcutBarCell("Save", Save));
shortcutBar.Cells.Add(new ShortcutBarCell("Save As", SaveAsPrompt));
shortcutBar.Cells.Add(new ShortcutBarCell("Evaluate", Evaluate));
shortcutBar.Render();
wm.AddWindow(shortcutBar);
wm.Update(mainWindow);
}
}
}