From 5c952e786115f602b12e8de59fbc917d0eeeec90 Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Sun, 1 Mar 2026 21:34:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0CodeStudio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BuildTime.txt | 2 +- GitCommit.txt | 2 +- Gui/AppManager.cs | 1 + Gui/Apps/CodeStudio/CodeStudio.cs | 47 +++++ Gui/Apps/CodeStudio/Ide.cs | 322 ++++++++++++++++++++++++++++++ 5 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 Gui/Apps/CodeStudio/CodeStudio.cs create mode 100644 Gui/Apps/CodeStudio/Ide.cs diff --git a/BuildTime.txt b/BuildTime.txt index 4788991..bc27331 100644 --- a/BuildTime.txt +++ b/BuildTime.txt @@ -1 +1 @@ -2026-03-01 19:30:39 \ No newline at end of file +2026-03-01 21:19:06 \ No newline at end of file diff --git a/GitCommit.txt b/GitCommit.txt index 36fb5c3..bcef3a3 100644 --- a/GitCommit.txt +++ b/GitCommit.txt @@ -1 +1 @@ -1f385ac \ No newline at end of file +6a9d39a \ No newline at end of file diff --git a/Gui/AppManager.cs b/Gui/AppManager.cs index d120e97..f4e9f00 100644 --- a/Gui/AppManager.cs +++ b/Gui/AppManager.cs @@ -120,6 +120,7 @@ namespace CMLeonOS.Gui RegisterApp(new AppMetadata("Stopwatch", () => { return new Stopwatch(); }, Icons.Icon_Stopwatch, Color.FromArgb(168, 55, 47))); RegisterApp(new AppMetadata("Paint", () => { return new Apps.Paint.Paint(); }, Icons.Icon_Paint, Color.FromArgb(0, 115, 186))); RegisterApp(new AppMetadata("Memory Statistics", () => { return new Apps.MemoryStatistics(); }, Icons.Icon_MemoryStatistics, Color.FromArgb(25, 25, 25))); + RegisterApp(new AppMetadata("CodeStudio", () => { return new Apps.CodeStudio.CodeStudio(); }, Icons.Icon_CodeStudio, Color.FromArgb(14, 59, 76))); Logger.Logger.Instance.Info("AppManager", $"{AppMetadatas.Count} apps were registered."); diff --git a/Gui/Apps/CodeStudio/CodeStudio.cs b/Gui/Apps/CodeStudio/CodeStudio.cs new file mode 100644 index 0000000..2fba252 --- /dev/null +++ b/Gui/Apps/CodeStudio/CodeStudio.cs @@ -0,0 +1,47 @@ +using CMLeonOS; +using CMLeonOS.Gui.UILib; +using System.Drawing; +using Cosmos.System.Graphics; + +namespace CMLeonOS.Gui.Apps.CodeStudio +{ + internal class CodeStudio : Process + { + internal CodeStudio() : base("CodeStudio", ProcessType.Application) { } + + Window splash; + + WindowManager wm = ProcessManager.GetProcess(); + + [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.CodeStudio.Splash.bmp")] + private static byte[] _splashBytes; + private static Bitmap splashBitmap = new Bitmap(_splashBytes); + + private Ide ide; + + private bool ideCreated = false; + + public override void Start() + { + base.Start(); + splash = new Window(this, 372, 250, 535, 300); + wm.AddWindow(splash); + + splash.DrawImage(splashBitmap, 0, 0); + //splash.DrawString("Starting...", Color.White, 20, splash.Height - 16 - 20); + + wm.Update(splash); + } + + public override void Run() + { + if (!ideCreated) + { + ide = new Ide(this, wm); + ide.Start(); + wm.RemoveWindow(splash); + ideCreated = true; + } + } + } +} diff --git a/Gui/Apps/CodeStudio/Ide.cs b/Gui/Apps/CodeStudio/Ide.cs new file mode 100644 index 0000000..fb69dbb --- /dev/null +++ b/Gui/Apps/CodeStudio/Ide.cs @@ -0,0 +1,322 @@ +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); + } + } +}