using Cosmos.System.Graphics; using CMLeonOS; using CMLeonOS.Gui.UILib; using CMLeonOS.Logger; using CMLeonOS.Utils; using System; using System.Drawing; using System.IO; namespace CMLeonOS.Gui.Apps { internal class Files : Process { internal Files() : base("Files", ProcessType.Application) { } AppWindow window; Table entryTable; Table shortcutsTable; ImageBlock up; TextBox pathBox; Window header; WindowManager wm = ProcessManager.GetProcess(); private static class Icons { [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.Directory.bmp")] private static byte[] _iconBytes_Directory; internal static Bitmap Icon_Directory = new Bitmap(_iconBytes_Directory); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.File.bmp")] private static byte[] _iconBytes_File; internal static Bitmap Icon_File = new Bitmap(_iconBytes_File); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.File_Config.bmp")] private static byte[] _iconBytes_File_Config; internal static Bitmap Icon_File_Config = new Bitmap(_iconBytes_File_Config); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.File_Rs.bmp")] private static byte[] _iconBytes_File_Rs; internal static Bitmap Icon_File_Rs = new Bitmap(_iconBytes_File_Rs); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.File_Text.bmp")] private static byte[] _iconBytes_File_Text; internal static Bitmap Icon_File_Text = new Bitmap(_iconBytes_File_Text); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.Drive.bmp")] private static byte[] _iconBytes_Drive; internal static Bitmap Icon_Drive = new Bitmap(_iconBytes_Drive); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.Home.bmp")] private static byte[] _iconBytes_Home; internal static Bitmap Icon_Home = new Bitmap(_iconBytes_Home); [IL2CPU.API.Attribs.ManifestResourceStream(ResourceName = "CMLeonOS.Gui.Resources.Files.Up.bmp")] private static byte[] _iconBytes_Up; internal static Bitmap Icon_Up = new Bitmap(_iconBytes_Up); } private string currentDir = @"0:\"; private const int pathBoxMargin = 4; private const int pathBoxHeight = 24; private const int shortcutsWidth = 128; private const int headerHeight = 32; private const string dirEmptyMessage = "This folder is empty."; private readonly (string Name, string Path)[] shortcuts = new (string, string)[] { ("CMLeonOS (0:)", @"0:\"), ("My Home", @$"0:\user\{UserSystem.CurrentLoggedInUser.Username}"), ("Users", @"0:\user"), }; private Bitmap GetFileIcon(string path) { string extension = Path.GetExtension(path).ToLower(); return extension switch { ".txt" or ".md" or ".log" => Icons.Icon_File_Text, ".rs" => Icons.Icon_File_Rs, ".ini" or ".cfg" => Icons.Icon_File_Config, _ => Icons.Icon_File }; } private Bitmap GetDirectoryIcon(string path) { if (Path.TrimEndingDirectorySeparator(path).StartsWith(@"0:\user\")) { return Icons.Icon_Home; } switch (path) { case @"0:\": return Icons.Icon_Drive; default: return Icons.Icon_Directory; } } private void PopulateEntryTable() { entryTable.Cells.Clear(); entryTable.SelectedCellIndex = -1; bool empty = true; foreach (string path in Directory.GetDirectories(currentDir)) { entryTable.Cells.Add(new TableCell(GetDirectoryIcon(path), Path.GetFileName(path), tag: "Directory")); empty = false; } foreach (string path in Directory.GetFiles(currentDir)) { entryTable.Cells.Add(new TableCell(GetFileIcon(path), Path.GetFileName(path), tag: "File")); empty = false; } if (empty) { entryTable.Clear(entryTable.Background); entryTable.DrawString(dirEmptyMessage, Color.Black, (entryTable.Width / 2) - ((dirEmptyMessage.Length * 8) / 2), 12); wm.Update(entryTable); } else { entryTable.Render(); } } private void PopulateShortcutTable() { shortcutsTable.Cells.Clear(); foreach ((string Name, string Path) item in shortcuts) { shortcutsTable.Cells.Add(new TableCell(GetDirectoryIcon(item.Path), item.Name, tag: item.Path)); } shortcutsTable.Render(); } private bool NavigateTo(string path) { string sanitised = PathUtil.Sanitize(path); if (!Directory.Exists(sanitised)) { MessageBox messageBox = new MessageBox(this, "Files", $"CMLeonOS can't find that folder.\nCheck the spelling and try again."); messageBox.Show(); return false; } currentDir = sanitised; pathBox.Text = sanitised; PopulateEntryTable(); UpdateSelectedShortcut(); RenderHeader(); if (sanitised == @"0:\") { window.Title = "Files"; } else { window.Title = Path.GetDirectoryName(sanitised); } return true; } private void UpdateSelectedShortcut() { for (int i = 0; i < shortcuts.Length; i++) { if (shortcuts[i].Path == currentDir) { shortcutsTable.SelectedCellIndex = i; return; } } shortcutsTable.SelectedCellIndex = -1; } private void EntryTableDoubleClicked(int x, int y) { if (entryTable.SelectedCellIndex != -1) { TableCell cell = entryTable.Cells[entryTable.SelectedCellIndex]; string path = PathUtil.Combine(currentDir, cell.Text); if ((string)cell.Tag == "Directory") { NavigateTo(path); } else if ((string)cell.Tag == "File") { try { string extension = Path.GetExtension(path).ToLower(); if (extension == ".txt" || extension == ".md") { var notepad = new Notepad(path); var metadata = AppManager.GetAppMetadata("Notepad"); metadata.Start(); } else { Logger.Logger.Instance.Warning("Files", $"Cannot open file: {path}"); } } catch (Exception ex) { Logger.Logger.Instance.Error("Files", $"Error opening file: {ex.Message}"); } } } } private void ShortcutsTableCellSelected(int index) { if (index != -1) { bool success = NavigateTo(shortcuts[index].Path); if (!success) { UpdateSelectedShortcut(); } } } private void PathBoxSubmitted() { bool success = NavigateTo(pathBox.Text); if (!success) { pathBox.Text = currentDir; } } private void UpClicked() { DirectoryInfo parent = Directory.GetParent(currentDir); if (parent != null) { NavigateTo(parent.FullName); } } private void RenderHeader(bool updateWindow = true) { header.Clear(Color.DarkBlue); header.DrawImageAlpha(GetDirectoryIcon(currentDir), 8, 8); DirectoryInfo info = new DirectoryInfo(currentDir); string currentDirFriendlyName = Path.GetFileName(currentDir); if (currentDir == $@"0:\user\{UserSystem.CurrentLoggedInUser.Username}") { currentDirFriendlyName = "My Home"; } header.DrawString(info.Parent == null ? currentDir : currentDirFriendlyName, Color.White, 32, 8); if (updateWindow) { wm.Update(header); } } private void WindowClicked(int x, int y) { if (x < pathBoxHeight && y < pathBoxHeight) { UpClicked(); } } public override void Start() { base.Start(); window = new AppWindow(this, 288, 240, 512, 304); wm.AddWindow(window); window.Title = "Files"; window.Icon = AppManager.GetAppMetadata("Files").Icon; window.OnClick = WindowClicked; window.Closing = TryStop; window.Clear(Color.DarkGray); window.DrawImageAlpha(Icons.Icon_Up, 0, 0); pathBox = new TextBox(window, (pathBoxMargin / 2) + pathBoxHeight, pathBoxMargin / 2, window.Width - pathBoxMargin - pathBoxHeight, 24 - pathBoxMargin); pathBox.Text = currentDir; pathBox.Submitted = PathBoxSubmitted; wm.AddWindow(pathBox); entryTable = new Table(window, shortcutsWidth, pathBoxHeight + headerHeight, window.Width - shortcutsWidth, window.Height - pathBoxHeight - headerHeight); entryTable.OnDoubleClick = EntryTableDoubleClicked; PopulateEntryTable(); wm.AddWindow(entryTable); header = new Window(this, window, shortcutsWidth, pathBoxHeight, window.Width - shortcutsWidth, headerHeight); wm.AddWindow(header); RenderHeader(updateWindow: false); shortcutsTable = new Table(window, 0, pathBoxHeight, shortcutsWidth, window.Height - pathBoxHeight); shortcutsTable.AllowDeselection = false; shortcutsTable.Background = Color.DarkGray; shortcutsTable.Foreground = Color.White; PopulateShortcutTable(); shortcutsTable.SelectedCellIndex = 0; shortcutsTable.TableCellSelected = ShortcutsTableCellSelected; wm.AddWindow(shortcutsTable); wm.Update(window); } public override void Run() { } } }