mirror of
https://git.alee14.me/shiftos-archive/ShiftOS_TheReturn.git
synced 2025-01-22 18:02:16 +00:00
434 lines
15 KiB
C#
434 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using ShiftOS.Engine;
|
|
using ShiftOS.Frontend.GraphicsSubsystem;
|
|
using ShiftOS.Frontend.GUI;
|
|
using static ShiftOS.Objects.ShiftFS.Utils;
|
|
|
|
namespace ShiftOS.Frontend.Apps
|
|
{
|
|
[WinOpen("fileskimmer")]
|
|
[Launcher("File Skimmer", false, null, "System")]
|
|
[DefaultTitle("File Skimmer")]
|
|
public class FileSkimmer : GUI.Control, IShiftOSWindow
|
|
{
|
|
private string _currentdirectory = "0:";
|
|
private const string SD_SYSTEM = "__system";
|
|
private GUI.ListView _fList = null;
|
|
private GUI.TextControl _currentdirtext = null;
|
|
private GUI.Button _openFile = null;
|
|
private GUI.TextControl _fileFilter = null;
|
|
private GUI.TextControl _filePrompt = null;
|
|
private GUI.TextInput _fileBox = null;
|
|
|
|
|
|
public bool IsDialog = false;
|
|
public Action<string> DialogCallback = null;
|
|
public string[] FileFilters = new string[] { "" };
|
|
public FileOpenerStyle DialogMode = FileOpenerStyle.Open;
|
|
|
|
public int SelectedFilter = 0;
|
|
|
|
public FileSkimmer()
|
|
{
|
|
_fileBox = new GUI.TextInput();
|
|
_filePrompt = new TextControl();
|
|
_fileFilter = new TextControl();
|
|
_openFile = new Button();
|
|
|
|
AddControl(_openFile);
|
|
AddControl(_fileBox);
|
|
AddControl(_filePrompt);
|
|
AddControl(_fileFilter);
|
|
|
|
_openFile.AutoSize = true;
|
|
_fileFilter.AutoSize = true;
|
|
_filePrompt.AutoSize = true;
|
|
|
|
Width = 720;
|
|
Height = 480;
|
|
_fList = new GUI.ListView();
|
|
//TODO: keyboard support in listviews
|
|
/*
|
|
_fList.KeyEvent += (e) =>
|
|
{
|
|
if(e.Key == Microsoft.Xna.Framework.Input.Keys.Enter)
|
|
{
|
|
Navigate(_fList.SelectedItem.ToString());
|
|
}
|
|
};*/
|
|
_fList.DoubleClick += () =>
|
|
{
|
|
try
|
|
{
|
|
Navigate(_fList.SelectedItem.Tag);
|
|
}
|
|
catch { }
|
|
};
|
|
AddControl(_fList);
|
|
_currentdirtext = new GUI.TextControl();
|
|
_currentdirtext.AutoSize = true;
|
|
AddControl(_currentdirtext);
|
|
ResetList();
|
|
|
|
}
|
|
|
|
public void OnLoad()
|
|
{
|
|
|
|
if (Hacking.CurrentHackable != null)
|
|
{
|
|
if (Hacking.CurrentHackable.VectorsUnlocked.Contains(Objects.SystemType.FileServer))
|
|
{
|
|
if (Mounts.Count > 2)
|
|
{
|
|
Mounts.RemoveAt(2);
|
|
}
|
|
var dir = new Objects.ShiftFS.Directory();
|
|
dir.Name = $"{Hacking.CurrentHackable.Data.SystemName} (ftp)";
|
|
Mounts.Add(dir);
|
|
foreach (var loot in Hacking.CurrentHackable.ServerFTPLoot)
|
|
{
|
|
if(!FileExists("2:/" + loot.LootName))
|
|
{
|
|
var bytes = Hacking.GetLootBytes(loot.PointTo);
|
|
WriteAllBytes($"2:/{loot.LootName}", bytes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Width = 720;
|
|
Height = 480;
|
|
_fList = new GUI.ListView();
|
|
//TODO: keyboard support in listviews
|
|
/*
|
|
_fList.KeyEvent += (e) =>
|
|
{
|
|
if(e.Key == Microsoft.Xna.Framework.Input.Keys.Enter)
|
|
{
|
|
Navigate(_fList.SelectedItem.ToString());
|
|
}
|
|
};*/
|
|
_fList.Click += () =>
|
|
{
|
|
if(_fList.SelectedItem != null)
|
|
{
|
|
if(_fList.SelectedItem.Tag != "__up")
|
|
{
|
|
if(FileExists(_fList.SelectedItem.Tag))
|
|
{
|
|
_fileBox.Text = _fList.SelectedItem.Text;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
_fList.DoubleClick += () =>
|
|
{
|
|
try
|
|
{
|
|
Navigate(_fList.SelectedItem.Tag);
|
|
}
|
|
catch { }
|
|
};
|
|
_fileBox.KeyEvent += (key) =>
|
|
{
|
|
if (key.Key == Microsoft.Xna.Framework.Input.Keys.Enter)
|
|
{
|
|
HandleFileSelect();
|
|
}
|
|
};
|
|
_openFile.Click += () =>
|
|
{
|
|
HandleFileSelect();
|
|
};
|
|
AddControl(_fList);
|
|
_currentdirtext = new GUI.TextControl();
|
|
_currentdirtext.AutoSize = true;
|
|
AddControl(_currentdirtext);
|
|
ResetList();
|
|
}
|
|
|
|
public void HandleFileSelect(bool quiet = false)
|
|
{
|
|
string fname = _fileBox.Text;
|
|
string filter = FileFilters[SelectedFilter];
|
|
if (filter != "Directory")
|
|
if (!fname.EndsWith(filter))
|
|
fname += filter;
|
|
string path = _currentdirectory + "/" + fname;
|
|
bool exists = false;
|
|
if (filter == "Directory")
|
|
exists = DirectoryExists(path);
|
|
else
|
|
exists = FileExists(path);
|
|
if (exists)
|
|
{
|
|
if (DialogMode == FileOpenerStyle.Open || quiet)
|
|
{
|
|
DialogCallback?.Invoke(path);
|
|
AppearanceManager.Close(this);
|
|
}
|
|
else
|
|
{
|
|
Engine.Infobox.PromptYesNo("Overwrite file?", "The file you chose already exists on disk. Would you like to overwrite it?", (answer) =>
|
|
{
|
|
if (answer)
|
|
{
|
|
DialogCallback?.Invoke(path);
|
|
AppearanceManager.Close(this);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (DialogMode == FileOpenerStyle.Open)
|
|
{
|
|
if (quiet == false)
|
|
Engine.Infobox.Show("File not found.", "The requested file path could not be found on disk.");
|
|
}
|
|
else
|
|
{
|
|
DialogCallback?.Invoke(path);
|
|
AppearanceManager.Close(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Navigate(string path)
|
|
{
|
|
if(path == "__up")
|
|
{
|
|
if (_currentdirectory == SD_SYSTEM)
|
|
throw new NaughtyDeveloperException("Someone tried to make it so you can go \"up one directory\" in the mounts list.");
|
|
if (_currentdirectory.EndsWith(":"))
|
|
{
|
|
_currentdirectory = SD_SYSTEM;
|
|
ResetList();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
int slashlast = _currentdirectory.LastIndexOf("/");
|
|
int len = _currentdirectory.Length - slashlast;
|
|
_currentdirectory = _currentdirectory.Remove(slashlast, len);
|
|
ResetList();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (DirectoryExists(path))
|
|
{
|
|
_currentdirectory = path;
|
|
ResetList();
|
|
}
|
|
else if (FileExists(path))
|
|
{
|
|
if (IsDialog)
|
|
{
|
|
bool quiet = DialogMode == FileOpenerStyle.Open;
|
|
this.HandleFileSelect(quiet);
|
|
}
|
|
else
|
|
{
|
|
if (!FileSkimmerBackend.OpenFile(path))
|
|
{
|
|
Engine.Infobox.Show("File Skimmer can't open this file!", "File Skimmer couldn't find a program that can open a file of this type. Please install a program that can handle this file and try again.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Texture2D ToTexture2D(System.Drawing.Image img)
|
|
{
|
|
if (img == null)
|
|
return null;
|
|
using(var bmp = new System.Drawing.Bitmap(img))
|
|
{
|
|
var lck = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
|
var arr = new byte[Math.Abs(lck.Stride) * lck.Height];
|
|
Marshal.Copy(lck.Scan0, arr, 0, arr.Length);
|
|
for(int i = 0; i < arr.Length; i += 4)
|
|
{
|
|
byte r = arr[i];
|
|
byte b = arr[i + 2];
|
|
arr[i] = b;
|
|
arr[i + 2] = r;
|
|
}
|
|
var tex2 = new Texture2D(UIManager.GraphicsDevice, bmp.Width, bmp.Height);
|
|
tex2.SetData<byte>(arr);
|
|
bmp.UnlockBits(lck);
|
|
return tex2;
|
|
}
|
|
}
|
|
|
|
public void OnSkinLoad()
|
|
{
|
|
foreach(var name in Enum.GetNames(typeof(FileType)))
|
|
{
|
|
FileType ftype = (FileType)Enum.Parse(typeof(FileType), name);
|
|
var img = ToTexture2D(GetImage(ftype));
|
|
_fList.SetImage(name, img);
|
|
}
|
|
|
|
|
|
_currentdirtext.Font = SkinEngine.LoadedSkin.Header3Font;
|
|
}
|
|
|
|
public System.Drawing.Image GetImage(FileType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case FileType.UpOne:
|
|
return Properties.Resources.fileicon5;
|
|
case FileType.Mount:
|
|
case FileType.Directory:
|
|
return Properties.Resources.fileicon0;
|
|
case FileType.Executable:
|
|
case FileType.Lua:
|
|
case FileType.Python:
|
|
return Properties.Resources.fileiconsaa;
|
|
case FileType.Image:
|
|
return Properties.Resources.fileicon3;
|
|
case FileType.Skin:
|
|
return Properties.Resources.fileicon10;
|
|
case FileType.TextFile:
|
|
return Properties.Resources.fileicon2;
|
|
case FileType.CommandFormat:
|
|
return Properties.Resources.fileiconcf;
|
|
default:
|
|
return Properties.Resources.fileicon1;
|
|
}
|
|
}
|
|
|
|
public bool OnUnload()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public void OnUpgrade()
|
|
{
|
|
}
|
|
|
|
public void ResetList()
|
|
{
|
|
if (_currentdirectory == SD_SYSTEM)
|
|
_currentdirtext.Text = "My storage drives";
|
|
else
|
|
_currentdirtext.Text = _currentdirectory;
|
|
|
|
_fList.ClearItems();
|
|
if (_currentdirectory != SD_SYSTEM)
|
|
_fList.AddItem(new GUI.ListViewItem
|
|
{
|
|
Text = "Up one...",
|
|
Tag = "__up",
|
|
ImageKey = FileType.UpOne.ToString()
|
|
});
|
|
|
|
if(_currentdirectory == SD_SYSTEM)
|
|
{
|
|
foreach(var mount in Mounts)
|
|
{
|
|
string mountpath = $"{Mounts.IndexOf(mount)}:";
|
|
string name = $"{mount.Name} ({mountpath})";
|
|
_fList.AddItem(new ListViewItem
|
|
{
|
|
Text = name,
|
|
Tag = mountpath,
|
|
ImageKey = FileType.Mount.ToString()
|
|
});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach(var dir in GetDirectories(_currentdirectory))
|
|
{
|
|
var dinf = GetDirectoryInfo(dir);
|
|
_fList.AddItem(new ListViewItem
|
|
{
|
|
Text = dinf.Name,
|
|
Tag = dir,
|
|
ImageKey = FileType.Directory.ToString()
|
|
});
|
|
}
|
|
foreach (var dir in GetFiles(_currentdirectory))
|
|
{
|
|
var dinf = GetFileInfo(dir);
|
|
if (dinf.Name.EndsWith(FileFilters[SelectedFilter]))
|
|
{
|
|
var ext = FileSkimmerBackend.GetFileType(dir);
|
|
|
|
|
|
_fList.AddItem(new ListViewItem
|
|
{
|
|
Text = dinf.Name,
|
|
Tag = dir,
|
|
ImageKey = ext.ToString()
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
InvalidateTopLevel();
|
|
}
|
|
|
|
|
|
private const int _fileselectboxheight = 50;
|
|
|
|
protected override void OnLayout(GameTime gameTime)
|
|
{
|
|
int listbottom = Height - _currentdirtext.Height;
|
|
if (IsDialog)
|
|
listbottom -= _fileselectboxheight;
|
|
|
|
_currentdirtext.Layout(gameTime);
|
|
_fList.X = 0;
|
|
_fList.Y = 0;
|
|
_fList.Width = Width;
|
|
_fList.Height = listbottom;
|
|
_currentdirtext.X = (Width - _currentdirtext.Width) / 2;
|
|
_currentdirtext.Y = _fList.Height;
|
|
|
|
if (IsDialog)
|
|
{
|
|
int _fileselectstart = Height - _fileselectboxheight;
|
|
_openFile.Text = DialogMode.ToString();
|
|
_openFile.Visible = true;
|
|
_openFile.X = (Width - _openFile.Width) - 10;
|
|
_openFile.Y = _fileselectstart + ((_fileselectboxheight - _openFile.Height) / 2);
|
|
|
|
_filePrompt.AutoSize = true;
|
|
_filePrompt.Text = $"{DialogMode} file: ";
|
|
_filePrompt.Font = SkinEngine.LoadedSkin.MainFont;
|
|
_filePrompt.Layout(gameTime);
|
|
|
|
_filePrompt.X = 10;
|
|
_filePrompt.Y = _fileselectstart + ((_fileselectboxheight - _filePrompt.Height) / 2);
|
|
_filePrompt.Visible = true;
|
|
|
|
_fileFilter.AutoSize = true;
|
|
_fileFilter.Visible = true;
|
|
_fileFilter.Text = FileFilters[SelectedFilter];
|
|
_fileFilter.Font = SkinEngine.LoadedSkin.MainFont;
|
|
_fileFilter.Layout(gameTime);
|
|
_fileFilter.X = _openFile.X - _fileFilter.Width - 10;
|
|
_fileFilter.Y = _fileselectstart + ((_fileselectboxheight - _fileFilter.Height) / 2);
|
|
|
|
_fileBox.X = _filePrompt.X + _filePrompt.Width + 10;
|
|
_fileBox.Width = _fileFilter.X - _fileBox.X;
|
|
_fileBox.Height = 24;
|
|
_fileBox.Y = _fileselectstart + ((_fileselectboxheight - _fileBox.Height) / 2);
|
|
_fileBox.Visible = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|