2014-07-28 01:51:11 +00:00
using System ;
2014-09-29 04:47:21 +00:00
using System.IO ;
2014-07-28 01:51:11 +00:00
using System.Collections.Generic ;
using System.Windows.Forms ;
2014-07-28 01:55:20 +00:00
using System.Linq ;
2014-07-28 01:51:11 +00:00
2014-09-29 04:47:21 +00:00
using BizHawk.Common ;
2014-07-28 02:10:31 +00:00
using BizHawk.Emulation.Common ;
2014-07-28 01:51:11 +00:00
using BizHawk.Client.Common ;
2015-11-06 14:31:50 +00:00
//todo - add some more options for libretro types
2014-07-28 01:51:11 +00:00
namespace BizHawk.Client.EmuHawk.ToolExtensions
{
public static class ToolExtensions
{
2015-11-06 14:31:50 +00:00
public static ToolStripItem [ ] RecentMenu ( this RecentFiles recent , Action < string > loadFileCallback , bool autoload = false , bool romloading = false )
2014-07-28 01:51:11 +00:00
{
var items = new List < ToolStripItem > ( ) ;
if ( recent . Empty )
{
var none = new ToolStripMenuItem { Enabled = false , Text = "None" } ;
items . Add ( none ) ;
}
else
{
foreach ( var filename in recent )
{
2015-11-06 14:31:50 +00:00
string caption = filename ;
string path = filename ;
string physicalPath = filename ;
bool crazyStuff = true ;
//sentinel for newer format OpenAdvanced type code
if ( romloading )
{
if ( filename . StartsWith ( "*" ) )
{
var oa = OpenAdvancedSerializer . ParseWithLegacy ( filename ) ;
caption = oa . DisplayName ;
crazyStuff = false ;
if ( oa is OpenAdvanced_OpenRom )
{
crazyStuff = true ;
physicalPath = ( ( oa as OpenAdvanced_OpenRom ) . Path ) ;
}
}
}
2014-09-29 04:47:21 +00:00
//TODO - do TSMI and TSDD need disposing? yuck
2015-11-06 14:31:50 +00:00
var item = new ToolStripMenuItem { Text = caption } ;
2014-07-28 01:51:11 +00:00
items . Add ( item ) ;
2014-09-29 04:47:21 +00:00
item . Click + = ( o , ev ) = >
{
2015-11-06 14:31:50 +00:00
loadFileCallback ( path ) ;
2014-09-29 04:47:21 +00:00
} ;
var tsdd = new ToolStripDropDownMenu ( ) ;
2015-11-06 14:31:50 +00:00
if ( crazyStuff )
2014-09-29 04:47:21 +00:00
{
2015-11-06 14:31:50 +00:00
//TODO - use standard methods to split filename (hawkfile acquire?)
var hf = new HawkFile ( ) ;
hf . Parse ( physicalPath ) ;
bool canExplore = true ;
if ( ! File . Exists ( hf . FullPathWithoutMember ) )
canExplore = false ;
if ( canExplore )
2014-09-29 04:47:21 +00:00
{
2015-11-06 14:31:50 +00:00
//make a menuitem to show the last modified timestamp
var timestamp = File . GetLastWriteTime ( hf . FullPathWithoutMember ) ;
var tsmiTimestamp = new ToolStripLabel { Text = timestamp . ToString ( ) } ;
tsdd . Items . Add ( tsmiTimestamp ) ;
tsdd . Items . Add ( new ToolStripSeparator ( ) ) ;
if ( hf . IsArchive )
{
//make a menuitem to let you copy the path
var tsmiCopyCanonicalPath = new ToolStripMenuItem { Text = "&Copy Canonical Path" } ;
tsmiCopyCanonicalPath . Click + = ( o , ev ) = > { System . Windows . Forms . Clipboard . SetText ( physicalPath ) ; } ;
tsdd . Items . Add ( tsmiCopyCanonicalPath ) ;
var tsmiCopyArchivePath = new ToolStripMenuItem { Text = "Copy Archive Path" } ;
tsmiCopyArchivePath . Click + = ( o , ev ) = > { System . Windows . Forms . Clipboard . SetText ( hf . FullPathWithoutMember ) ; } ;
tsdd . Items . Add ( tsmiCopyArchivePath ) ;
var tsmiOpenArchive = new ToolStripMenuItem { Text = "Open &Archive" } ;
tsmiOpenArchive . Click + = ( o , ev ) = > { System . Diagnostics . Process . Start ( hf . FullPathWithoutMember ) ; } ;
tsdd . Items . Add ( tsmiOpenArchive ) ;
}
else
{
//make a menuitem to let you copy the path
var tsmiCopyPath = new ToolStripMenuItem { Text = "&Copy Path" } ;
tsmiCopyPath . Click + = ( o , ev ) = > { System . Windows . Forms . Clipboard . SetText ( physicalPath ) ; } ;
tsdd . Items . Add ( tsmiCopyPath ) ;
}
tsdd . Items . Add ( new ToolStripSeparator ( ) ) ;
//make a menuitem to let you explore to it
var tsmiExplore = new ToolStripMenuItem { Text = "&Explore" } ;
string explorePath = "\"" + hf . FullPathWithoutMember + "\"" ;
tsmiExplore . Click + = ( o , ev ) = > { System . Diagnostics . Process . Start ( "explorer.exe" , "/select, " + explorePath ) ; } ;
tsdd . Items . Add ( tsmiExplore ) ;
var tsmiCopyFile = new ToolStripMenuItem { Text = "Copy &File" } ;
var lame = new System . Collections . Specialized . StringCollection ( ) ;
lame . Add ( hf . FullPathWithoutMember ) ;
tsmiCopyFile . Click + = ( o , ev ) = > { System . Windows . Forms . Clipboard . SetFileDropList ( lame ) ; } ;
tsdd . Items . Add ( tsmiCopyFile ) ;
var tsmiTest = new ToolStripMenuItem { Text = "&Shell Context Menu" } ;
tsmiTest . Click + = ( o , ev ) = >
{
var si = new GongSolutions . Shell . ShellItem ( hf . FullPathWithoutMember ) ;
var scm = new GongSolutions . Shell . ShellContextMenu ( si ) ;
var tsddi = o as ToolStripDropDownItem ;
tsddi . Owner . Update ( ) ;
scm . ShowContextMenu ( tsddi . Owner , new System . Drawing . Point ( 0 , 0 ) ) ;
} ;
tsdd . Items . Add ( tsmiTest ) ;
tsdd . Items . Add ( new ToolStripSeparator ( ) ) ;
2014-09-30 08:51:48 +00:00
}
else
{
2015-11-06 14:31:50 +00:00
//make a menuitem to show the last modified timestamp
var tsmiMissingFile = new ToolStripLabel { Text = "-Missing-" } ;
tsdd . Items . Add ( tsmiMissingFile ) ;
tsdd . Items . Add ( new ToolStripSeparator ( ) ) ;
2014-09-29 04:47:21 +00:00
}
2015-11-06 14:31:50 +00:00
} //crazystuff
2014-09-29 04:47:21 +00:00
2015-11-06 14:31:50 +00:00
//in any case, make a menuitem to let you remove the item
var tsmiRemovePath = new ToolStripMenuItem { Text = "&Remove" } ;
2016-08-18 01:23:56 +00:00
tsmiRemovePath . Click + = ( o , ev ) = > {
recent . Remove ( path ) ;
} ;
2014-09-29 04:47:21 +00:00
tsdd . Items . Add ( tsmiRemovePath ) ;
////experiment of popping open a submenu. doesnt work well.
//item.MouseDown += (o, mev) =>
//{
// if (mev.Button != MouseButtons.Right) return;
// //location of the menu containing this item that was just rightclicked
// var pos = item.Owner.Bounds.Location;
// //the offset within that menu of this item
// var tsddi = item as ToolStripDropDownItem;
// pos.Offset(tsddi.Bounds.Location);
// //the offset of the click
// pos.Offset(mev.Location);
// //tsdd.OwnerItem = item; //has interesting promise, but breaks things otherwise
// tsdd.Show(pos);
//};
2015-11-06 14:31:50 +00:00
//just add it to the submenu for now. seems to work well enough, even though its a bit odd
2014-09-29 04:47:21 +00:00
item . MouseDown + = ( o , mev ) = >
{
if ( mev . Button ! = MouseButtons . Right ) return ;
if ( item . DropDown ! = null )
item . DropDown = tsdd ;
item . ShowDropDown ( ) ;
} ;
2014-07-28 01:51:11 +00:00
}
}
items . Add ( new ToolStripSeparator ( ) ) ;
2014-08-02 22:52:22 +00:00
var clearitem = new ToolStripMenuItem { Text = "&Clear" , Enabled = ! recent . Frozen } ;
2014-07-28 01:51:11 +00:00
clearitem . Click + = ( o , ev ) = > recent . Clear ( ) ;
items . Add ( clearitem ) ;
2014-08-02 22:49:27 +00:00
var freezeitem = new ToolStripMenuItem { Text = recent . Frozen ? "&Unfreeze" : "&Freeze" } ;
freezeitem . Click + = ( o , ev ) = > recent . Frozen ^ = true ;
items . Add ( freezeitem ) ;
2014-07-28 01:51:11 +00:00
if ( autoload )
{
var auto = new ToolStripMenuItem { Text = "&Autoload" , Checked = recent . AutoLoad } ;
auto . Click + = ( o , ev ) = > recent . ToggleAutoLoad ( ) ;
items . Add ( auto ) ;
}
2014-12-22 21:51:35 +00:00
var settingsitem = new ToolStripMenuItem { Text = "&Recent Settings..." } ;
settingsitem . Click + = ( o , ev ) = >
{
using ( var prompt = new InputPrompt
{
TextInputType = InputPrompt . InputType . Unsigned ,
Message = "Number of recent files to track" ,
InitialValue = recent . MAX_RECENT_FILES . ToString ( )
} )
{
var result = prompt . ShowDialog ( ) ;
if ( result = = DialogResult . OK )
{
int val = int . Parse ( prompt . PromptText ) ;
if ( val > 0 )
recent . MAX_RECENT_FILES = val ;
}
}
} ;
items . Add ( settingsitem ) ;
2014-07-28 01:51:11 +00:00
return items . ToArray ( ) ;
}
2016-08-18 01:23:56 +00:00
public static void HandleLoadError ( this RecentFiles recent , string path , string encodedPath = null )
2014-07-28 01:51:11 +00:00
{
GlobalWin . Sound . StopSound ( ) ;
2014-08-02 23:03:29 +00:00
if ( recent . Frozen )
2014-07-28 01:51:11 +00:00
{
2014-08-02 23:03:29 +00:00
var result = MessageBox . Show ( "Could not open " + path , "File not found" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
else
{
2016-08-29 16:38:36 +00:00
// ensure topmost, not to have to minimize everything to see and use our modal window, if it somehow got covered
var result = MessageBox . Show ( new Form ( ) { TopMost = true } , "Could not open " + path + "\nRemove from list?" , "File not found" , MessageBoxButtons . YesNo , MessageBoxIcon . Error ) ;
2014-08-02 23:03:29 +00:00
if ( result = = DialogResult . Yes )
{
2016-08-18 01:23:56 +00:00
if ( encodedPath ! = null )
recent . Remove ( encodedPath ) ;
else
recent . Remove ( path ) ;
2014-08-02 23:03:29 +00:00
}
2014-07-28 01:51:11 +00:00
}
GlobalWin . Sound . StartSound ( ) ;
}
2014-07-28 01:55:20 +00:00
public static void FreezeAll ( this IEnumerable < Watch > watches )
{
Global . CheatList . AddRange (
watches
. Where ( w = > ! w . IsSeparator )
2015-11-29 16:13:32 +00:00
. Select ( w = > new Cheat ( w , w . Value ) ) ) ;
2014-07-28 01:55:20 +00:00
}
public static void UnfreezeAll ( this IEnumerable < Watch > watches )
{
Global . CheatList . RemoveRange ( watches . Where ( watch = > ! watch . IsSeparator ) ) ;
}
2014-07-28 02:10:31 +00:00
2015-01-14 21:55:48 +00:00
public static IEnumerable < ToolStripItem > MenuItems ( this IMemoryDomains domains , Action < string > setCallback , string selected = "" , int? maxSize = null )
2014-07-28 02:10:31 +00:00
{
foreach ( var domain in domains )
{
var name = domain . Name ;
var item = new ToolStripMenuItem
{
Text = name ,
2015-01-18 16:00:20 +00:00
Enabled = ! ( maxSize . HasValue & & domain . Size > maxSize . Value ) ,
2014-07-28 02:10:31 +00:00
Checked = name = = selected
} ;
item . Click + = ( o , ev ) = > setCallback ( name ) ;
yield return item ;
}
}
2014-07-28 01:51:11 +00:00
}
}