2017-07-17 14:34:59 -04:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2017-08-05 15:44:09 -04:00
using System.Runtime.InteropServices ;
2017-07-17 14:34:59 -04:00
using System.Text ;
using System.Threading.Tasks ;
2017-07-19 16:08:33 -04:00
using Microsoft.Xna.Framework ;
2017-08-05 15:44:09 -04:00
using Microsoft.Xna.Framework.Graphics ;
2017-07-17 14:34:59 -04:00
using ShiftOS.Engine ;
2017-08-05 15:44:09 -04:00
using ShiftOS.Frontend.GraphicsSubsystem ;
using ShiftOS.Frontend.GUI ;
2017-07-17 14:34:59 -04:00
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" ;
2017-08-05 15:44:09 -04:00
private GUI . ListView _fList = null ;
2017-07-17 14:34:59 -04:00
private GUI . TextControl _currentdirtext = null ;
2017-08-05 17:01:15 -04:00
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 ( ) ;
}
2017-07-17 14:34:59 -04:00
public void OnLoad ( )
{
2017-08-02 10:23:13 -04:00
if ( Hacking . CurrentHackable ! = null )
2017-08-02 09:30:39 -04:00
{
if ( Hacking . CurrentHackable . VectorsUnlocked . Contains ( Objects . SystemType . FileServer ) )
{
2017-08-02 10:23:13 -04:00
if ( Mounts . Count > 2 )
2017-08-02 09:30:39 -04:00
{
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 ) )
{
2017-08-02 11:14:29 -04:00
var bytes = Hacking . GetLootBytes ( loot . PointTo ) ;
2017-08-02 10:23:13 -04:00
WriteAllBytes ( $"2:/{loot.LootName}" , bytes ) ;
2017-08-02 09:30:39 -04:00
}
}
}
}
2017-07-17 14:34:59 -04:00
Width = 720 ;
Height = 480 ;
2017-08-05 15:44:09 -04:00
_fList = new GUI . ListView ( ) ;
//TODO: keyboard support in listviews
/ *
2017-07-17 14:34:59 -04:00
_fList . KeyEvent + = ( e ) = >
{
if ( e . Key = = Microsoft . Xna . Framework . Input . Keys . Enter )
{
Navigate ( _fList . SelectedItem . ToString ( ) ) ;
}
2017-08-05 15:44:09 -04:00
} ; * /
2017-08-05 17:01:15 -04:00
_fList . Click + = ( ) = >
{
if ( _fList . SelectedItem ! = null )
{
if ( _fList . SelectedItem . Tag ! = "__up" )
{
if ( FileExists ( _fList . SelectedItem . Tag ) )
{
_fileBox . Text = _fList . SelectedItem . Text ;
}
}
}
} ;
2017-07-17 14:34:59 -04:00
_fList . DoubleClick + = ( ) = >
{
try
{
2017-08-05 15:44:09 -04:00
Navigate ( _fList . SelectedItem . Tag ) ;
2017-07-17 14:34:59 -04:00
}
catch { }
} ;
2017-08-05 17:01:15 -04:00
_fileBox . KeyEvent + = ( key ) = >
{
if ( key . Key = = Microsoft . Xna . Framework . Input . Keys . Enter )
{
HandleFileSelect ( ) ;
}
} ;
_openFile . Click + = ( ) = >
{
HandleFileSelect ( ) ;
} ;
2017-07-17 14:34:59 -04:00
AddControl ( _fList ) ;
_currentdirtext = new GUI . TextControl ( ) ;
_currentdirtext . AutoSize = true ;
AddControl ( _currentdirtext ) ;
ResetList ( ) ;
}
2017-08-05 17:01:15 -04:00
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 ) ;
}
}
}
2017-08-05 15:44:09 -04:00
public void Navigate ( string path )
2017-07-17 14:34:59 -04:00
{
2017-08-05 15:44:09 -04:00
if ( path = = "__up" )
2017-07-17 14:34:59 -04:00
{
2017-08-05 15:44:09 -04:00
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 ( ":" ) )
2017-07-17 14:34:59 -04:00
{
2017-08-05 15:44:09 -04:00
_currentdirectory = SD_SYSTEM ;
2017-07-17 14:34:59 -04:00
ResetList ( ) ;
2017-08-05 15:44:09 -04:00
return ;
2017-07-17 14:34:59 -04:00
}
else
{
2017-08-05 15:44:09 -04:00
int slashlast = _currentdirectory . LastIndexOf ( "/" ) ;
int len = _currentdirectory . Length - slashlast ;
_currentdirectory = _currentdirectory . Remove ( slashlast , len ) ;
2017-07-17 14:34:59 -04:00
ResetList ( ) ;
2017-08-05 15:44:09 -04:00
return ;
2017-07-17 14:34:59 -04:00
}
}
if ( DirectoryExists ( path ) )
{
_currentdirectory = path ;
ResetList ( ) ;
}
else if ( FileExists ( path ) )
{
2017-08-05 17:01:15 -04:00
if ( IsDialog )
{
bool quiet = DialogMode = = FileOpenerStyle . Open ;
this . HandleFileSelect ( quiet ) ;
}
else
2017-07-17 14:34:59 -04:00
{
2017-08-05 17:01:15 -04:00
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." ) ;
}
2017-08-05 15:44:09 -04:00
}
}
}
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 ;
2017-07-17 14:34:59 -04:00
}
2017-08-05 15:44:09 -04:00
var tex2 = new Texture2D ( UIManager . GraphicsDevice , bmp . Width , bmp . Height ) ;
tex2 . SetData < byte > ( arr ) ;
bmp . UnlockBits ( lck ) ;
return tex2 ;
2017-07-17 14:34:59 -04:00
}
}
public void OnSkinLoad ( )
{
2017-08-05 15:44:09 -04:00
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 ) ;
}
2017-07-17 14:34:59 -04:00
_currentdirtext . Font = SkinEngine . LoadedSkin . Header3Font ;
}
2017-08-05 15:44:09 -04:00
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 ;
}
}
2017-07-17 14:34:59 -04:00
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 )
2017-08-05 15:44:09 -04:00
_fList . AddItem ( new GUI . ListViewItem
{
Text = "Up one..." ,
Tag = "__up" ,
ImageKey = FileType . UpOne . ToString ( )
} ) ;
2017-07-17 14:34:59 -04:00
if ( _currentdirectory = = SD_SYSTEM )
{
foreach ( var mount in Mounts )
{
2017-08-05 15:44:09 -04:00
string mountpath = $"{Mounts.IndexOf(mount)}:" ;
string name = $"{mount.Name} ({mountpath})" ;
_fList . AddItem ( new ListViewItem
{
Text = name ,
Tag = mountpath ,
ImageKey = FileType . Mount . ToString ( )
} ) ;
2017-07-17 14:34:59 -04:00
}
}
else
{
foreach ( var dir in GetDirectories ( _currentdirectory ) )
{
var dinf = GetDirectoryInfo ( dir ) ;
2017-08-05 15:44:09 -04:00
_fList . AddItem ( new ListViewItem
{
Text = dinf . Name ,
Tag = dir ,
ImageKey = FileType . Directory . ToString ( )
} ) ;
2017-07-17 14:34:59 -04:00
}
foreach ( var dir in GetFiles ( _currentdirectory ) )
{
var dinf = GetFileInfo ( dir ) ;
2017-08-05 17:01:15 -04:00
if ( dinf . Name . EndsWith ( FileFilters [ SelectedFilter ] ) )
{
var ext = FileSkimmerBackend . GetFileType ( dir ) ;
2017-08-05 15:44:09 -04:00
2017-08-05 17:01:15 -04:00
_fList . AddItem ( new ListViewItem
{
Text = dinf . Name ,
Tag = dir ,
ImageKey = ext . ToString ( )
} ) ;
}
2017-07-17 14:34:59 -04:00
}
}
InvalidateTopLevel ( ) ;
}
2017-08-05 17:01:15 -04:00
private const int _fileselectboxheight = 50 ;
2017-07-19 16:08:33 -04:00
protected override void OnLayout ( GameTime gameTime )
2017-07-17 14:34:59 -04:00
{
2017-08-05 17:01:15 -04:00
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 )
2017-07-17 14:34:59 -04:00
{
2017-08-05 17:01:15 -04:00
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 ;
2017-07-17 14:34:59 -04:00
}
2017-08-05 17:01:15 -04:00
2017-07-17 14:34:59 -04:00
}
}
}