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); } } }