mirror of
https://github.com/Leonmmcoset/CMLeonOS.git
synced 2026-03-03 15:30:27 +00:00
314 lines
10 KiB
C#
314 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;
|
||
|
|
|
||
|
|
namespace CMLeonOS.Gui.UILib
|
||
|
|
{
|
||
|
|
internal class FileBrowser
|
||
|
|
{
|
||
|
|
private Process process;
|
||
|
|
private WindowManager wm;
|
||
|
|
private Window window;
|
||
|
|
private Table fileTable;
|
||
|
|
private TextBox pathBox;
|
||
|
|
private TextBox fileNameBox;
|
||
|
|
private Button upButton;
|
||
|
|
private Button selectButton;
|
||
|
|
private Button cancelButton;
|
||
|
|
|
||
|
|
private string currentPath = @"0:\";
|
||
|
|
private string selectedPath = null;
|
||
|
|
private Action<string> onFileSelected;
|
||
|
|
private bool selectDirectoryOnly = false;
|
||
|
|
|
||
|
|
private const int headerHeight = 32;
|
||
|
|
private const int buttonHeight = 28;
|
||
|
|
private const int buttonWidth = 80;
|
||
|
|
private const int fileNameBoxHeight = 24;
|
||
|
|
|
||
|
|
internal FileBrowser(Process process, WindowManager wm, Action<string> onFileSelected, bool selectDirectoryOnly = false)
|
||
|
|
{
|
||
|
|
this.process = process;
|
||
|
|
this.wm = wm;
|
||
|
|
this.onFileSelected = onFileSelected;
|
||
|
|
this.selectDirectoryOnly = selectDirectoryOnly;
|
||
|
|
}
|
||
|
|
|
||
|
|
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_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.Up.bmp")]
|
||
|
|
private static byte[] _iconBytes_Up;
|
||
|
|
internal static Bitmap Icon_Up = new Bitmap(_iconBytes_Up);
|
||
|
|
}
|
||
|
|
|
||
|
|
private Bitmap GetFileIcon(string path)
|
||
|
|
{
|
||
|
|
string extension = Path.GetExtension(path).ToLower();
|
||
|
|
|
||
|
|
return extension switch
|
||
|
|
{
|
||
|
|
".txt" or ".md" or ".log" or ".lua" or ".rs" => Icons.Icon_File_Text,
|
||
|
|
_ => Icons.Icon_File
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PopulateFileTable()
|
||
|
|
{
|
||
|
|
fileTable.Cells.Clear();
|
||
|
|
fileTable.SelectedCellIndex = -1;
|
||
|
|
|
||
|
|
bool empty = true;
|
||
|
|
|
||
|
|
foreach (string path in Directory.GetDirectories(currentPath))
|
||
|
|
{
|
||
|
|
fileTable.Cells.Add(new TableCell(Icons.Icon_Directory, Path.GetFileName(path), tag: "Directory"));
|
||
|
|
empty = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (string path in Directory.GetFiles(currentPath))
|
||
|
|
{
|
||
|
|
fileTable.Cells.Add(new TableCell(GetFileIcon(path), Path.GetFileName(path), tag: "File"));
|
||
|
|
empty = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (empty)
|
||
|
|
{
|
||
|
|
fileTable.Clear(fileTable.Background);
|
||
|
|
fileTable.DrawString("This folder is empty.", Color.Black, (fileTable.Width / 2) - 80, 12);
|
||
|
|
wm.Update(fileTable);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
fileTable.Render();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PathBoxChanged()
|
||
|
|
{
|
||
|
|
string inputPath = pathBox.Text;
|
||
|
|
|
||
|
|
if (string.IsNullOrWhiteSpace(inputPath))
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!inputPath.Contains(':'))
|
||
|
|
{
|
||
|
|
inputPath = $@"0:\{inputPath}";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (Directory.Exists(inputPath))
|
||
|
|
{
|
||
|
|
currentPath = inputPath;
|
||
|
|
PopulateFileTable();
|
||
|
|
}
|
||
|
|
else if (File.Exists(inputPath))
|
||
|
|
{
|
||
|
|
currentPath = Path.GetDirectoryName(inputPath);
|
||
|
|
PopulateFileTable();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void PathBoxSubmitted()
|
||
|
|
{
|
||
|
|
string inputPath = pathBox.Text;
|
||
|
|
|
||
|
|
if (string.IsNullOrWhiteSpace(inputPath))
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!inputPath.Contains(':'))
|
||
|
|
{
|
||
|
|
inputPath = $@"0:\{inputPath}";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (File.Exists(inputPath) || (selectDirectoryOnly && Directory.Exists(inputPath)))
|
||
|
|
{
|
||
|
|
selectedPath = inputPath;
|
||
|
|
onFileSelected?.Invoke(selectedPath);
|
||
|
|
Close();
|
||
|
|
}
|
||
|
|
else if (Directory.Exists(inputPath))
|
||
|
|
{
|
||
|
|
currentPath = inputPath;
|
||
|
|
PopulateFileTable();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void UpClicked(int x, int y)
|
||
|
|
{
|
||
|
|
if (currentPath.Length > 3)
|
||
|
|
{
|
||
|
|
string parentPath = Path.GetDirectoryName(currentPath);
|
||
|
|
if (!string.IsNullOrEmpty(parentPath))
|
||
|
|
{
|
||
|
|
currentPath = @"0:\";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
currentPath = parentPath;
|
||
|
|
}
|
||
|
|
PopulateFileTable();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SelectClicked(int x, int y)
|
||
|
|
{
|
||
|
|
if (fileTable.SelectedCellIndex >= 0)
|
||
|
|
{
|
||
|
|
TableCell selectedCell = fileTable.Cells[fileTable.SelectedCellIndex];
|
||
|
|
string selectedName = selectedCell.Text;
|
||
|
|
string fullPath = Path.Combine(currentPath, selectedName);
|
||
|
|
|
||
|
|
string tag = selectedCell.Tag as string;
|
||
|
|
if (tag == "Directory")
|
||
|
|
{
|
||
|
|
currentPath = fullPath;
|
||
|
|
PopulateFileTable();
|
||
|
|
}
|
||
|
|
else if (tag == "File")
|
||
|
|
{
|
||
|
|
if (selectDirectoryOnly)
|
||
|
|
{
|
||
|
|
string fileName = fileNameBox.Text;
|
||
|
|
if (string.IsNullOrWhiteSpace(fileName))
|
||
|
|
{
|
||
|
|
fileName = selectedName;
|
||
|
|
}
|
||
|
|
selectedPath = Path.Combine(currentPath, fileName);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
selectedPath = fullPath;
|
||
|
|
}
|
||
|
|
onFileSelected?.Invoke(selectedPath);
|
||
|
|
Close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (selectDirectoryOnly)
|
||
|
|
{
|
||
|
|
string fileName = fileNameBox.Text;
|
||
|
|
if (!string.IsNullOrWhiteSpace(fileName))
|
||
|
|
{
|
||
|
|
selectedPath = Path.Combine(currentPath, fileName);
|
||
|
|
onFileSelected?.Invoke(selectedPath);
|
||
|
|
Close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FileTableSelected(int index)
|
||
|
|
{
|
||
|
|
SelectClicked(0, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void CancelClicked(int x, int y)
|
||
|
|
{
|
||
|
|
selectedPath = null;
|
||
|
|
onFileSelected?.Invoke(null);
|
||
|
|
Close();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FileTableDoubleClicked(int index)
|
||
|
|
{
|
||
|
|
SelectClicked(0, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal void Show()
|
||
|
|
{
|
||
|
|
window = new Window(process, 100, 100, 500, 400);
|
||
|
|
wm.AddWindow(window);
|
||
|
|
|
||
|
|
window.DrawString(selectDirectoryOnly ? "Save As" : "Open File", Color.DarkBlue, 12, 12);
|
||
|
|
|
||
|
|
pathBox = new TextBox(window, 8, 40, window.Width - 16, 24)
|
||
|
|
{
|
||
|
|
Background = Color.White,
|
||
|
|
Foreground = Color.Black,
|
||
|
|
Text = currentPath,
|
||
|
|
ReadOnly = false
|
||
|
|
};
|
||
|
|
pathBox.Changed = PathBoxChanged;
|
||
|
|
pathBox.Submitted = PathBoxSubmitted;
|
||
|
|
wm.AddWindow(pathBox);
|
||
|
|
|
||
|
|
if (selectDirectoryOnly)
|
||
|
|
{
|
||
|
|
window.DrawString("File name:", Color.Black, 8, 72);
|
||
|
|
|
||
|
|
fileNameBox = new TextBox(window, 8, 96, window.Width - 16, fileNameBoxHeight)
|
||
|
|
{
|
||
|
|
Background = Color.White,
|
||
|
|
Foreground = Color.Black,
|
||
|
|
Text = "",
|
||
|
|
ReadOnly = false
|
||
|
|
};
|
||
|
|
wm.AddWindow(fileNameBox);
|
||
|
|
}
|
||
|
|
|
||
|
|
upButton = new Button(window, 8, selectDirectoryOnly ? 128 : 72, 60, buttonHeight)
|
||
|
|
{
|
||
|
|
Text = "Up",
|
||
|
|
Image = Icons.Icon_Up,
|
||
|
|
ImageLocation = Button.ButtonImageLocation.Left
|
||
|
|
};
|
||
|
|
upButton.OnClick = UpClicked;
|
||
|
|
wm.AddWindow(upButton);
|
||
|
|
|
||
|
|
int tableY = selectDirectoryOnly ? 128 + buttonHeight + 8 : 72 + buttonHeight + 8;
|
||
|
|
int tableHeight = window.Height - tableY - buttonHeight - 8 - buttonHeight - 16;
|
||
|
|
|
||
|
|
fileTable = new Table(window, 8, tableY, window.Width - 16, tableHeight)
|
||
|
|
{
|
||
|
|
AllowDeselection = false
|
||
|
|
};
|
||
|
|
fileTable.TableCellSelected = FileTableSelected;
|
||
|
|
PopulateFileTable();
|
||
|
|
wm.AddWindow(fileTable);
|
||
|
|
|
||
|
|
int buttonY = window.Height - buttonHeight - 8;
|
||
|
|
selectButton = new Button(window, window.Width - buttonWidth - 8, buttonY, buttonWidth, buttonHeight)
|
||
|
|
{
|
||
|
|
Text = selectDirectoryOnly ? "Save" : "Open"
|
||
|
|
};
|
||
|
|
selectButton.OnClick = SelectClicked;
|
||
|
|
wm.AddWindow(selectButton);
|
||
|
|
|
||
|
|
cancelButton = new Button(window, window.Width - buttonWidth * 2 - 16, buttonY, buttonWidth, buttonHeight)
|
||
|
|
{
|
||
|
|
Text = "Cancel"
|
||
|
|
};
|
||
|
|
cancelButton.OnClick = CancelClicked;
|
||
|
|
wm.AddWindow(cancelButton);
|
||
|
|
|
||
|
|
wm.Update(window);
|
||
|
|
}
|
||
|
|
|
||
|
|
internal void Close()
|
||
|
|
{
|
||
|
|
if (window != null)
|
||
|
|
{
|
||
|
|
wm.RemoveWindow(window);
|
||
|
|
window = null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|