@ -53,26 +53,27 @@ namespace ICSharpCode.ILSpy
@@ -53,26 +53,27 @@ namespace ICSharpCode.ILSpy
partial class MainWindow : Window
{
bool refreshInProgress ;
bool handlingNugetPackageSelection ;
readonly NavigationHistory < NavigationState > history = new NavigationHistory < NavigationState > ( ) ;
ILSpySettings spySettingsForMainWindow_Loaded ;
internal SessionSettings sessionSettings ;
internal AssemblyListManager assemblyListManager ;
AssemblyList assemblyList ;
AssemblyListTreeNode assemblyListTreeNode ;
readonly DecompilerTextView decompilerTextView ;
static MainWindow instance ;
public static MainWindow Instance {
get { return instance ; }
}
public SessionSettings SessionSettings {
get { return sessionSettings ; }
}
public MainWindow ( )
{
instance = this ;
@ -80,28 +81,28 @@ namespace ICSharpCode.ILSpy
@@ -80,28 +81,28 @@ namespace ICSharpCode.ILSpy
this . spySettingsForMainWindow_Loaded = spySettings ;
this . sessionSettings = new SessionSettings ( spySettings ) ;
this . assemblyListManager = new AssemblyListManager ( spySettings ) ;
this . Icon = new BitmapImage ( new Uri ( "pack://application:,,,/ILSpy;component/images/ILSpy.ico" ) ) ;
this . DataContext = sessionSettings ;
InitializeComponent ( ) ;
decompilerTextView = App . ExportProvider . GetExportedValue < DecompilerTextView > ( ) ;
mainPane . Content = decompilerTextView ;
if ( sessionSettings . SplitterPosition > 0 & & sessionSettings . SplitterPosition < 1 ) {
leftColumn . Width = new GridLength ( sessionSettings . SplitterPosition , GridUnitType . Star ) ;
rightColumn . Width = new GridLength ( 1 - sessionSettings . SplitterPosition , GridUnitType . Star ) ;
}
sessionSettings . FilterSettings . PropertyChanged + = filterSettings_PropertyChanged ;
InitMainMenu ( ) ;
InitToolbar ( ) ;
ContextMenuProvider . Add ( treeView , decompilerTextView ) ;
this . Loaded + = MainWindow_Loaded ;
}
void SetWindowBounds ( Rect bounds )
{
this . Left = bounds . Left ;
@ -109,9 +110,9 @@ namespace ICSharpCode.ILSpy
@@ -109,9 +110,9 @@ namespace ICSharpCode.ILSpy
this . Width = bounds . Width ;
this . Height = bounds . Height ;
}
#region Toolbar extensibility
void InitToolbar ( )
{
int navigationPos = 0 ;
@ -134,9 +135,9 @@ namespace ICSharpCode.ILSpy
@@ -134,9 +135,9 @@ namespace ICSharpCode.ILSpy
}
}
}
}
Button MakeToolbarItem ( Lazy < ICommand , IToolbarCommandMetadata > command )
{
object image = Images . Load ( command . Value , command . Metadata . ToolbarIcon ) ;
@ -155,9 +156,9 @@ namespace ICSharpCode.ILSpy
@@ -155,9 +156,9 @@ namespace ICSharpCode.ILSpy
} ;
}
#endregion
#region Main Menu extensibility
void InitMainMenu ( )
{
var mainMenuCommands = App . ExportProvider . GetExports < ICommand , IMainMenuCommandMetadata > ( "MainMenuCommand" ) ;
@ -198,8 +199,8 @@ namespace ICSharpCode.ILSpy
@@ -198,8 +199,8 @@ namespace ICSharpCode.ILSpy
internal static string GetResourceString ( string key )
{
var str = ! string . IsNullOrEmpty ( key ) ? Properties . Resources . ResourceManager . GetString ( key ) : null ;
return string . IsNullOrEmpty ( key ) | | string . IsNullOrEmpty ( str ) ? key : str ;
var str = ! string . IsNullOrEmpty ( key ) ? Properties . Resources . ResourceManager . GetString ( key ) : null ;
return string . IsNullOrEmpty ( key ) | | string . IsNullOrEmpty ( str ) ? key : str ;
}
#endregion
@ -225,16 +226,18 @@ namespace ICSharpCode.ILSpy
@@ -225,16 +226,18 @@ namespace ICSharpCode.ILSpy
SetWindowBounds ( sessionSettings . WindowBounds ) ;
else
SetWindowBounds ( SessionSettings . DefaultWindowBounds ) ;
this . WindowState = sessionSettings . WindowState ;
}
unsafe IntPtr WndProc ( IntPtr hwnd , int msg , IntPtr wParam , IntPtr lParam , ref bool handled )
{
if ( msg = = NativeMethods . WM_COPYDATA ) {
CopyDataStruct * copyData = ( CopyDataStruct * ) lParam ;
string data = new string ( ( char * ) copyData - > Buffer , 0 , copyData - > Size / sizeof ( char ) ) ;
if ( data . StartsWith ( "ILSpy:\r\n" , StringComparison . Ordinal ) ) {
if ( handlingNugetPackageSelection )
return ( IntPtr ) 1 ;
data = data . Substring ( 8 ) ;
List < string > lines = new List < string > ( ) ;
using ( StringReader r = new StringReader ( data ) ) {
@ -255,17 +258,17 @@ namespace ICSharpCode.ILSpy
@@ -255,17 +258,17 @@ namespace ICSharpCode.ILSpy
return IntPtr . Zero ;
}
#endregion
public AssemblyList CurrentAssemblyList {
get { return assemblyList ; }
}
public event NotifyCollectionChangedEventHandler CurrentAssemblyListChanged ;
List < LoadedAssembly > commandLineLoadedAssemblies = new List < LoadedAssembly > ( ) ;
List < string > nugetPackagesToLoad = new List < string > ( ) ;
bool HandleCommandLineArguments ( CommandLineArguments args )
{
int i = 0 ;
@ -278,12 +281,12 @@ namespace ICSharpCode.ILSpy
@@ -278,12 +281,12 @@ namespace ICSharpCode.ILSpy
i + + ;
}
}
LoadAssemblies ( args . AssembliesToLoad , commandLineLoadedAssemblies , false ) ;
LoadAssemblies ( args . AssembliesToLoad , commandLineLoadedAssemblies , focusNode : false ) ;
if ( args . Language ! = null )
sessionSettings . FilterSettings . Language = Languages . GetLanguage ( args . Language ) ;
return true ;
}
/// <summary>
/// Called on startup or when passed arguments via WndProc from a second instance.
/// In the format case, spySettings is non-null; in the latter it is null.
@ -291,14 +294,15 @@ namespace ICSharpCode.ILSpy
@@ -291,14 +294,15 @@ namespace ICSharpCode.ILSpy
void HandleCommandLineArgumentsAfterShowList ( CommandLineArguments args , ILSpySettings spySettings = null )
{
if ( nugetPackagesToLoad . Count > 0 ) {
LoadAssemblies ( nugetPackagesToLoad , commandLineLoadedAssemblies , focusNode : false ) ;
var relevantPackages = nugetPackagesToLoad . ToArray ( ) ;
nugetPackagesToLoad . Clear ( ) ;
// Show the nuget package open dialog after the command line/window message was processed.
Dispatcher . BeginInvoke ( new Action ( ( ) = > LoadAssemblies ( relevantPackages , commandLineLoadedAssemblies , focusNode : false ) ) , DispatcherPriority . Normal ) ;
}
var relevantAssemblies = commandLineLoadedAssemblies . ToList ( ) ;
commandLineLoadedAssemblies . Clear ( ) ; // clear references once we don't need them anymore
NavigateOnLaunch ( args . NavigateTo , sessionSettings . ActiveTreeViewPath , spySettings , relevantAssemblies ) ;
if ( args . Search ! = null )
{
if ( args . Search ! = null ) {
SearchPane . Instance . SearchTerm = args . Search ;
SearchPane . Instance . Show ( ) ;
}
@ -456,12 +460,12 @@ namespace ICSharpCode.ILSpy
@@ -456,12 +460,12 @@ namespace ICSharpCode.ILSpy
void OpenAssemblies ( ILSpySettings spySettings )
{
HandleCommandLineArgumentsAfterShowList ( App . CommandLineArguments , spySettings ) ;
AvalonEditTextOutput output = new AvalonEditTextOutput ( ) ;
if ( FormatExceptions ( App . StartupExceptions . ToArray ( ) , output ) )
decompilerTextView . ShowText ( output ) ;
}
bool FormatExceptions ( App . ExceptionData [ ] exceptions , ITextOutput output )
{
var stringBuilder = new StringBuilder ( ) ;
@ -476,7 +480,7 @@ namespace ICSharpCode.ILSpy
@@ -476,7 +480,7 @@ namespace ICSharpCode.ILSpy
{
if ( exceptions . Length = = 0 ) return false ;
bool first = true ;
foreach ( var item in exceptions ) {
if ( first )
first = false ;
@ -492,17 +496,17 @@ namespace ICSharpCode.ILSpy
@@ -492,17 +496,17 @@ namespace ICSharpCode.ILSpy
} else
output . AppendLine ( item . Exception . ToString ( ) ) ;
}
return true ;
}
#region Update Check
string updateAvailableDownloadUrl ;
public void ShowMessageIfUpdatesAvailableAsync ( ILSpySettings spySettings , bool forceCheck = false )
{
// Don't check for updates if we're in an MSIX since they work differently
if ( WindowsVersionHelper . HasPackageIdentity ) {
if ( WindowsVersionHelper . HasPackageIdentity ) {
return ;
}
@ -514,12 +518,12 @@ namespace ICSharpCode.ILSpy
@@ -514,12 +518,12 @@ namespace ICSharpCode.ILSpy
}
result . ContinueWith ( task = > AdjustUpdateUIAfterCheck ( task , forceCheck ) , TaskScheduler . FromCurrentSynchronizationContext ( ) ) ;
}
void updatePanelCloseButtonClick ( object sender , RoutedEventArgs e )
{
updatePanel . Visibility = Visibility . Collapsed ;
}
void downloadOrCheckUpdateButtonClick ( object sender , RoutedEventArgs e )
{
if ( updateAvailableDownloadUrl ! = null ) {
@ -544,30 +548,29 @@ namespace ICSharpCode.ILSpy
@@ -544,30 +548,29 @@ namespace ICSharpCode.ILSpy
}
}
#endregion
public void ShowAssemblyList ( string name )
{
ILSpySettings settings = ILSpySettings . Load ( ) ;
AssemblyList list = this . assemblyListManager . LoadList ( settings , name ) ;
//Only load a new list when it is a different one
if ( list . ListName ! = CurrentAssemblyList . ListName )
{
if ( list . ListName ! = CurrentAssemblyList . ListName ) {
ShowAssemblyList ( list ) ;
}
}
void ShowAssemblyList ( AssemblyList assemblyList )
{
history . Clear ( ) ;
this . assemblyList = assemblyList ;
assemblyList . assemblies . CollectionChanged + = assemblyList_Assemblies_CollectionChanged ;
assemblyListTreeNode = new AssemblyListTreeNode ( assemblyList ) ;
assemblyListTreeNode . FilterSettings = sessionSettings . FilterSettings . Clone ( ) ;
assemblyListTreeNode . Select = SelectNode ;
treeView . Root = assemblyListTreeNode ;
if ( assemblyList . ListName = = AssemblyListManager . DefaultListName )
#if DEBUG
this . Title = $"ILSpy {RevisionClass.FullVersion}" ;
@ -596,7 +599,7 @@ namespace ICSharpCode.ILSpy
@@ -596,7 +599,7 @@ namespace ICSharpCode.ILSpy
if ( CurrentAssemblyListChanged ! = null )
CurrentAssemblyListChanged ( this , e ) ;
}
void LoadInitialAssemblies ( )
{
// Called when loading an empty assembly list; so that
@ -614,7 +617,7 @@ namespace ICSharpCode.ILSpy
@@ -614,7 +617,7 @@ namespace ICSharpCode.ILSpy
foreach ( System . Reflection . Assembly asm in initialAssemblies )
assemblyList . OpenAssembly ( asm . Location ) ;
}
void filterSettings_PropertyChanged ( object sender , PropertyChangedEventArgs e )
{
RefreshTreeViewFilter ( ) ;
@ -622,7 +625,7 @@ namespace ICSharpCode.ILSpy
@@ -622,7 +625,7 @@ namespace ICSharpCode.ILSpy
DecompileSelectedNodes ( recordHistory : false ) ;
}
}
public void RefreshTreeViewFilter ( )
{
// filterSettings is mutable; but the ILSpyTreeNode filtering assumes that filter settings are immutable.
@ -631,11 +634,11 @@ namespace ICSharpCode.ILSpy
@@ -631,11 +634,11 @@ namespace ICSharpCode.ILSpy
if ( assemblyListTreeNode ! = null )
assemblyListTreeNode . FilterSettings = sessionSettings . FilterSettings . Clone ( ) ;
}
internal AssemblyListTreeNode AssemblyListTreeNode {
get { return assemblyListTreeNode ; }
}
#region Node Selection
public void SelectNode ( SharpTreeNode obj )
@ -661,7 +664,7 @@ namespace ICSharpCode.ILSpy
@@ -661,7 +664,7 @@ namespace ICSharpCode.ILSpy
treeView . SetSelectedNodes ( nodes ) ;
}
}
/// <summary>
/// Retrieves a node using the .ToString() representations of its ancestors.
/// </summary>
@ -686,7 +689,7 @@ namespace ICSharpCode.ILSpy
@@ -686,7 +689,7 @@ namespace ICSharpCode.ILSpy
else
return node ;
}
/// <summary>
/// Gets the .ToString() representation of the node's ancestors.
/// </summary>
@ -702,7 +705,7 @@ namespace ICSharpCode.ILSpy
@@ -702,7 +705,7 @@ namespace ICSharpCode.ILSpy
path . Reverse ( ) ;
return path . ToArray ( ) ;
}
public ILSpyTreeNode FindTreeNode ( object reference )
{
switch ( reference ) {
@ -724,12 +727,12 @@ namespace ICSharpCode.ILSpy
@@ -724,12 +727,12 @@ namespace ICSharpCode.ILSpy
return null ;
}
}
public void JumpToReference ( object reference )
{
JumpToReferenceAsync ( reference ) . HandleExceptions ( ) ;
}
/// <summary>
/// Jumps to the specified reference.
/// </summary>
@ -800,7 +803,7 @@ namespace ICSharpCode.ILSpy
@@ -800,7 +803,7 @@ namespace ICSharpCode.ILSpy
{
if ( fileNames = = null )
throw new ArgumentNullException ( nameof ( fileNames ) ) ;
if ( focusNode )
treeView . UnselectAll ( ) ;
@ -813,24 +816,29 @@ namespace ICSharpCode.ILSpy
@@ -813,24 +816,29 @@ namespace ICSharpCode.ILSpy
foreach ( string file in fileNames ) {
switch ( Path . GetExtension ( file ) ) {
case ".nupkg" :
LoadedNugetPackage package = new LoadedNugetPackage ( file ) ;
var selectionDialog = new NugetPackageBrowserDialog ( package ) ;
selectionDialog . Owner = this ;
if ( selectionDialog . ShowDialog ( ) ! = true )
break ;
foreach ( var entry in selectionDialog . SelectedItems ) {
var nugetAsm = assemblyList . OpenAssembly ( "nupkg://" + file + ";" + entry . Name , entry . Stream , true ) ;
if ( nugetAsm ! = null ) {
if ( loadedAssemblies ! = null )
loadedAssemblies . Add ( nugetAsm ) ;
else {
var node = assemblyListTreeNode . FindAssemblyNode ( nugetAsm ) ;
if ( node ! = null & & focusNode ) {
treeView . SelectedItems . Add ( node ) ;
lastNode = node ;
this . handlingNugetPackageSelection = true ;
try {
LoadedNugetPackage package = new LoadedNugetPackage ( file ) ;
var selectionDialog = new NugetPackageBrowserDialog ( package ) ;
selectionDialog . Owner = this ;
if ( selectionDialog . ShowDialog ( ) ! = true )
break ;
foreach ( var entry in selectionDialog . SelectedItems ) {
var nugetAsm = assemblyList . OpenAssembly ( "nupkg://" + file + ";" + entry . Name , entry . Stream , true ) ;
if ( nugetAsm ! = null ) {
if ( loadedAssemblies ! = null )
loadedAssemblies . Add ( nugetAsm ) ;
else {
var node = assemblyListTreeNode . FindAssemblyNode ( nugetAsm ) ;
if ( node ! = null & & focusNode ) {
treeView . SelectedItems . Add ( node ) ;
lastNode = node ;
}
}
}
}
} finally {
this . handlingNugetPackageSelection = false ;
}
break ;
default :
@ -853,7 +861,7 @@ namespace ICSharpCode.ILSpy
@@ -853,7 +861,7 @@ namespace ICSharpCode.ILSpy
treeView . FocusNode ( lastNode ) ;
}
}
void RefreshCommandExecuted ( object sender , ExecutedRoutedEventArgs e )
{
try {
@ -865,13 +873,13 @@ namespace ICSharpCode.ILSpy
@@ -865,13 +873,13 @@ namespace ICSharpCode.ILSpy
refreshInProgress = false ;
}
}
void SearchCommandExecuted ( object sender , ExecutedRoutedEventArgs e )
{
SearchPane . Instance . Show ( ) ;
}
#endregion
#region Decompile (TreeView_SelectionChanged)
void TreeView_SelectionChanged ( object sender , SelectionChangedEventArgs e )
{
@ -880,10 +888,10 @@ namespace ICSharpCode.ILSpy
@@ -880,10 +888,10 @@ namespace ICSharpCode.ILSpy
if ( SelectionChanged ! = null )
SelectionChanged ( sender , e ) ;
}
Task decompilationTask ;
bool ignoreDecompilationRequests ;
void DecompileSelectedNodes ( DecompilerTextViewState state = null , bool recordHistory = true )
{
if ( ignoreDecompilationRequests )
@ -891,14 +899,14 @@ namespace ICSharpCode.ILSpy
@@ -891,14 +899,14 @@ namespace ICSharpCode.ILSpy
if ( treeView . SelectedItems . Count = = 0 & & refreshInProgress )
return ;
if ( recordHistory ) {
var dtState = decompilerTextView . GetState ( ) ;
if ( dtState ! = null )
if ( dtState ! = null )
history . UpdateCurrent ( new NavigationState ( dtState ) ) ;
history . Record ( new NavigationState ( treeView . SelectedItems . OfType < SharpTreeNode > ( ) ) ) ;
}
if ( treeView . SelectedItems . Count = = 1 ) {
ILSpyTreeNode node = treeView . SelectedItem as ILSpyTreeNode ;
if ( node ! = null & & node . View ( decompilerTextView ) )
@ -927,7 +935,7 @@ namespace ICSharpCode.ILSpy
@@ -927,7 +935,7 @@ namespace ICSharpCode.ILSpy
refreshInProgress = false ;
}
}
public DecompilerTextView TextView {
get { return decompilerTextView ; }
}
@ -950,7 +958,7 @@ namespace ICSharpCode.ILSpy
@@ -950,7 +958,7 @@ namespace ICSharpCode.ILSpy
e . Handled = true ;
e . CanExecute = history . CanNavigateBack ;
}
void BackCommandExecuted ( object sender , ExecutedRoutedEventArgs e )
{
if ( history . CanNavigateBack ) {
@ -958,13 +966,13 @@ namespace ICSharpCode.ILSpy
@@ -958,13 +966,13 @@ namespace ICSharpCode.ILSpy
NavigateHistory ( false ) ;
}
}
void ForwardCommandCanExecute ( object sender , CanExecuteRoutedEventArgs e )
{
e . Handled = true ;
e . CanExecute = history . CanNavigateForward ;
}
void ForwardCommandExecuted ( object sender , ExecutedRoutedEventArgs e )
{
if ( history . CanNavigateForward ) {
@ -972,18 +980,17 @@ namespace ICSharpCode.ILSpy
@@ -972,18 +980,17 @@ namespace ICSharpCode.ILSpy
NavigateHistory ( true ) ;
}
}
void NavigateHistory ( bool forward )
{
var dtState = decompilerTextView . GetState ( ) ;
if ( dtState ! = null )
if ( dtState ! = null )
history . UpdateCurrent ( new NavigationState ( dtState ) ) ;
var newState = forward ? history . GoForward ( ) : history . GoBack ( ) ;
ignoreDecompilationRequests = true ;
treeView . SelectedItems . Clear ( ) ;
foreach ( var node in newState . TreeNodes )
{
foreach ( var node in newState . TreeNodes ) {
treeView . SelectedItems . Add ( node ) ;
}
if ( newState . TreeNodes . Any ( ) )
@ -991,9 +998,9 @@ namespace ICSharpCode.ILSpy
@@ -991,9 +998,9 @@ namespace ICSharpCode.ILSpy
ignoreDecompilationRequests = false ;
DecompileSelectedNodes ( newState . ViewState , false ) ;
}
#endregion
protected override void OnStateChanged ( EventArgs e )
{
base . OnStateChanged ( e ) ;
@ -1001,7 +1008,7 @@ namespace ICSharpCode.ILSpy
@@ -1001,7 +1008,7 @@ namespace ICSharpCode.ILSpy
if ( this . WindowState ! = System . Windows . WindowState . Minimized )
sessionSettings . WindowState = this . WindowState ;
}
protected override void OnClosing ( CancelEventArgs e )
{
base . OnClosing ( e ) ;
@ -1032,7 +1039,7 @@ namespace ICSharpCode.ILSpy
@@ -1032,7 +1039,7 @@ namespace ICSharpCode.ILSpy
return loadedAssy . FileName ;
}
#region Top/Bottom Pane management
/// <summary>
@ -1046,14 +1053,12 @@ namespace ICSharpCode.ILSpy
@@ -1046,14 +1053,12 @@ namespace ICSharpCode.ILSpy
var pane2Height = pane2Row . Height ;
//only star height values are normalized.
if ( ! pane1Height . IsStar | | ! pane2Height . IsStar )
{
if ( ! pane1Height . IsStar | | ! pane2Height . IsStar ) {
return ;
}
var totalHeight = pane1Height . Value + pane2Height . Value ;
if ( totalHeight = = 0 )
{
if ( totalHeight = = 0 ) {
return ;
}
@ -1080,20 +1085,20 @@ namespace ICSharpCode.ILSpy
@@ -1080,20 +1085,20 @@ namespace ICSharpCode.ILSpy
}
topPane . Visibility = Visibility . Visible ;
}
void TopPane_CloseButtonClicked ( object sender , EventArgs e )
{
sessionSettings . TopPaneSplitterPosition = topPaneRow . Height . Value / ( topPaneRow . Height . Value + textViewRow . Height . Value ) ;
topPaneRow . MinHeight = 0 ;
topPaneRow . Height = new GridLength ( 0 ) ;
topPane . Visibility = Visibility . Collapsed ;
IPane pane = topPane . Content as IPane ;
topPane . Content = null ;
if ( pane ! = null )
pane . Closed ( ) ;
}
public void ShowInBottomPane ( string title , object content )
{
bottomPaneRow . MinHeight = 1 0 0 ;
@ -1113,26 +1118,26 @@ namespace ICSharpCode.ILSpy
@@ -1113,26 +1118,26 @@ namespace ICSharpCode.ILSpy
}
bottomPane . Visibility = Visibility . Visible ;
}
void BottomPane_CloseButtonClicked ( object sender , EventArgs e )
{
sessionSettings . BottomPaneSplitterPosition = bottomPaneRow . Height . Value / ( bottomPaneRow . Height . Value + textViewRow . Height . Value ) ;
bottomPaneRow . MinHeight = 0 ;
bottomPaneRow . Height = new GridLength ( 0 ) ;
bottomPane . Visibility = Visibility . Collapsed ;
IPane pane = bottomPane . Content as IPane ;
bottomPane . Content = null ;
if ( pane ! = null )
pane . Closed ( ) ;
}
#endregion
public void UnselectAll ( )
{
treeView . UnselectAll ( ) ;
}
public void SetStatus ( string status , Brush foreground )
{
if ( this . statusBar . Visibility = = Visibility . Collapsed )
@ -1140,12 +1145,12 @@ namespace ICSharpCode.ILSpy
@@ -1140,12 +1145,12 @@ namespace ICSharpCode.ILSpy
this . StatusLabel . Foreground = foreground ;
this . StatusLabel . Text = status ;
}
public ItemCollection GetMainMenuItems ( )
{
return mainMenu . Items ;
}
public ItemCollection GetToolBarItems ( )
{
return toolBar . Items ;