// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Threading;
using AvalonDock.Layout.Serialization;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.TreeView;
using Microsoft.Win32;
namespace ICSharpCode.ILSpy
{
class MainWindowDataContext
{
public DockWorkspace Workspace { get; set; }
public SessionSettings SessionSettings { get; set; }
public AssemblyListManager AssemblyListManager { get; set; }
}
///
/// The main window of the application.
///
partial class MainWindow : Window
{
bool refreshInProgress, changingActiveTab;
readonly NavigationHistory history = new NavigationHistory();
ILSpySettings spySettingsForMainWindow_Loaded;
internal SessionSettings sessionSettings;
AssemblyList assemblyList;
AssemblyListTreeNode assemblyListTreeNode;
static MainWindow instance;
public static MainWindow Instance {
get { return instance; }
}
public SessionSettings SessionSettings {
get { return sessionSettings; }
}
internal AssemblyListManager AssemblyListManager { get; }
public SharpTreeView AssemblyTreeView {
get {
return FindResource("AssemblyTreeView") as SharpTreeView;
}
}
public AnalyzerTreeView AnalyzerTreeView {
get {
return FindResource("AnalyzerTreeView") as AnalyzerTreeView;
}
}
public SearchPane SearchPane {
get {
return FindResource("SearchPane") as SearchPane;
}
}
public MainWindow()
{
instance = this;
var spySettings = ILSpySettings.Load();
this.spySettingsForMainWindow_Loaded = spySettings;
this.sessionSettings = new SessionSettings(spySettings);
this.AssemblyListManager = new AssemblyListManager(spySettings);
// Make sure Images are initialized on the UI thread.
this.Icon = Images.ILSpyIcon;
this.DataContext = new MainWindowDataContext {
Workspace = DockWorkspace.Instance,
SessionSettings = sessionSettings,
AssemblyListManager = AssemblyListManager
};
AssemblyListManager.CreateDefaultAssemblyLists();
if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(sessionSettings.CurrentCulture);
}
DockWorkspace.Instance.LoadSettings(sessionSettings);
InitializeComponent();
InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager);
sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged;
sessionSettings.PropertyChanged += SessionSettings_PropertyChanged;
InitMainMenu();
InitToolbar();
ContextMenuProvider.Add(AssemblyTreeView);
this.Loaded += MainWindow_Loaded;
}
private void SessionSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(SessionSettings.ActiveAssemblyList):
ShowAssemblyList(sessionSettings.ActiveAssemblyList);
break;
case nameof(SessionSettings.IsDarkMode):
// update syntax highlighting and force reload (AvalonEdit does not automatically refresh on highlighting change)
DecompilerTextView.RegisterHighlighting();
DecompileSelectedNodes(DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState);
break;
case nameof(SessionSettings.CurrentCulture):
MessageBox.Show(Properties.Resources.SettingsChangeRestartRequired, "ILSpy");
break;
}
}
void SetWindowBounds(Rect bounds)
{
this.Left = bounds.Left;
this.Top = bounds.Top;
this.Width = bounds.Width;
this.Height = bounds.Height;
}
#region Toolbar extensibility
void InitToolbar()
{
int navigationPos = 0;
int openPos = 1;
var toolbarCommands = App.ExportProvider.GetExports("ToolbarCommand");
foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.ToolbarOrder).GroupBy(c => Properties.Resources.ResourceManager.GetString(c.Metadata.ToolbarCategory)))
{
if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Navigation"))
{
foreach (var command in commandGroup)
{
toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command));
openPos++;
}
}
else if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Open"))
{
foreach (var command in commandGroup)
{
toolBar.Items.Insert(openPos++, MakeToolbarItem(command));
}
}
else
{
toolBar.Items.Add(new Separator());
foreach (var command in commandGroup)
{
toolBar.Items.Add(MakeToolbarItem(command));
}
}
}
}
Button MakeToolbarItem(Lazy command)
{
return new Button {
Style = ThemeManager.Current.CreateToolBarButtonStyle(),
Command = CommandWrapper.Unwrap(command.Value),
ToolTip = Properties.Resources.ResourceManager.GetString(command.Metadata.ToolTip),
Tag = command.Metadata.Tag,
Content = new Image {
Width = 16,
Height = 16,
Source = Images.Load(command.Value, command.Metadata.ToolbarIcon)
}
};
}
#endregion
#region Main Menu extensibility
void InitMainMenu()
{
var mainMenuCommands = App.ExportProvider.GetExports("MainMenuCommand");
foreach (var topLevelMenu in mainMenuCommands.OrderBy(c => c.Metadata.MenuOrder).GroupBy(c => GetResourceString(c.Metadata.Menu)))
{
var topLevelMenuItem = mainMenu.Items.OfType