diff --git a/ILSpy/Analyzers/AnalyzerTreeView.cs b/ILSpy/Analyzers/AnalyzerTreeView.cs index 132f7c1db..945d62fcc 100644 --- a/ILSpy/Analyzers/AnalyzerTreeView.cs +++ b/ILSpy/Analyzers/AnalyzerTreeView.cs @@ -44,29 +44,22 @@ namespace ICSharpCode.ILSpy.Analyzers [Export] public class AnalyzerTreeView : SharpTreeView { - FilterSettings filterSettings; - public AnalyzerTreeView() { this.ShowRoot = false; this.BorderThickness = new Thickness(0); ContextMenuProvider.Add(this); - MessageBus.Subscribers += (sender, e) => MainWindow_Instance_CurrentAssemblyListChanged(sender, e); + MessageBus.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e); MessageBus.Subscribers += DockWorkspace_ActiveTabPageChanged; - filterSettings = MainWindow.Instance.SessionSettings.FilterSettings; - filterSettings.PropertyChanged += FilterSettings_PropertyChanged; + MessageBus.Subscribers += (sender, e) => LanguageSettings_PropertyChanged(sender, e); } private void DockWorkspace_ActiveTabPageChanged(object sender, EventArgs e) { this.Root ??= new AnalyzerRootNode { Language = MainWindow.Instance.CurrentLanguage }; - - filterSettings.PropertyChanged -= FilterSettings_PropertyChanged; - filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings; - filterSettings.PropertyChanged += FilterSettings_PropertyChanged; } - private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + private void LanguageSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { switch (e.PropertyName) { @@ -77,7 +70,7 @@ namespace ICSharpCode.ILSpy.Analyzers } } - void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) + void CurrentAssemblyList_Changed(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action == NotifyCollectionChangedAction.Reset) { diff --git a/ILSpy/Commands/SetThemeCommand.cs b/ILSpy/Commands/SetThemeCommand.cs index 9083300ab..2d1a0b32a 100644 --- a/ILSpy/Commands/SetThemeCommand.cs +++ b/ILSpy/Commands/SetThemeCommand.cs @@ -1,11 +1,13 @@ -namespace ICSharpCode.ILSpy.Commands +using ICSharpCode.ILSpy.Util; + +namespace ICSharpCode.ILSpy.Commands { public class SetThemeCommand : SimpleCommand { public override void Execute(object parameter) { if (parameter is string theme) - MainWindow.Instance.SessionSettings.Theme = theme; + SettingsService.Instance.SessionSettings.Theme = theme; } } } diff --git a/ILSpy/FilterSettings.cs b/ILSpy/LanguageSettings.cs similarity index 80% rename from ILSpy/FilterSettings.cs rename to ILSpy/LanguageSettings.cs index 6adb3200d..a9a00fade 100644 --- a/ILSpy/FilterSettings.cs +++ b/ILSpy/LanguageSettings.cs @@ -23,6 +23,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Xml.Linq; +using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy @@ -30,12 +31,7 @@ namespace ICSharpCode.ILSpy /// /// Represents the filters applied to the tree view. /// - /// - /// This class is mutable; but the ILSpyTreeNode filtering assumes that filter settings are immutable. - /// Thus, the main window will use one mutable instance (for data-binding), and will assign a new - /// clone to the ILSpyTreeNodes whenever the main mutable instance changes. - /// - public class FilterSettings : INotifyPropertyChanged + public class LanguageSettings : INotifyPropertyChanged { /// /// This dictionary is necessary to remember language versions across language changes. For example, @@ -44,13 +40,12 @@ namespace ICSharpCode.ILSpy /// private readonly Dictionary languageVersionHistory = new Dictionary(); - public FilterSettings(XElement element) + public LanguageSettings(XElement element) { this.ShowApiLevel = (ApiVisibility?)(int?)element.Element("ShowAPILevel") ?? ApiVisibility.PublicAndInternal; this.Language = Languages.GetLanguage((string)element.Element("Language")); - this.LanguageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == (string)element.Element("LanguageVersion")); - if (this.LanguageVersion == default(LanguageVersion)) - this.LanguageVersion = language.LanguageVersions.LastOrDefault(); + this.LanguageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == (string)element.Element("LanguageVersion")) + ?? Language.LanguageVersions.LastOrDefault(); } public XElement SaveAsXml() @@ -63,33 +58,6 @@ namespace ICSharpCode.ILSpy ); } - string searchTerm; - - /// - /// Gets/Sets the search term. - /// Only tree nodes containing the search term will be shown. - /// - public string SearchTerm { - get { return searchTerm; } - set { - if (searchTerm != value) - { - searchTerm = value; - OnPropertyChanged(nameof(SearchTerm)); - } - } - } - - /// - /// Gets whether a node with the specified text is matched by the current search term. - /// - public virtual bool SearchTermMatches(string text) - { - if (string.IsNullOrEmpty(searchTerm)) - return true; - return text.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0; - } - ApiVisibility showApiLevel; /// @@ -211,15 +179,23 @@ namespace ICSharpCode.ILSpy { if (PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + var args = new PropertyChangedEventArgs(propertyName); + + PropertyChanged(this, args); + MessageBus.Send(this, new LanguageSettingsChangedEventArgs(args)); } } - public FilterSettings Clone() + + // This class has been initially called FilterSettings, but then has been Hijacked to store language settings as well. + // While the filter settings were some sort of local, the language settings are global. This is a bit of a mess. + // There has been a lot of workarounds cloning the FilterSettings to pass them down to the tree nodes, without messing up the global language settings. + // Finally, this filtering was not used at all, so this SearchTerm is just a placeholder to make the filtering code compile, in case someone wants to reactivate filtering in the future. + public string SearchTerm => string.Empty; + + public bool SearchTermMatches(string value) { - FilterSettings f = (FilterSettings)MemberwiseClone(); - f.PropertyChanged = null; - return f; + return true; } } } diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index 411ff87b0..32d7981eb 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -123,9 +123,9 @@ - - - + + + @@ -189,25 +189,25 @@ - + - + - + + SelectedItem="{Binding SessionSettings.LanguageSettings.Language}"/> + SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/> diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index b40d950a7..0f6a4953d 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -73,9 +73,7 @@ namespace ICSharpCode.ILSpy { bool refreshInProgress, changingActiveTab; readonly NavigationHistory history = new NavigationHistory(); - ILSpySettings spySettingsForMainWindow_Loaded; - SessionSettings sessionSettings; - FilterSettings filterSettings; + AssemblyList assemblyList; AssemblyListTreeNode assemblyListTreeNode; @@ -85,10 +83,6 @@ namespace ICSharpCode.ILSpy get { return instance; } } - public SessionSettings SessionSettings { - get { return sessionSettings; } - } - internal AssemblyListManager AssemblyListManager { get; } public SharpTreeView AssemblyTreeView { @@ -116,9 +110,10 @@ namespace ICSharpCode.ILSpy public MainWindow() { instance = this; - var spySettings = ILSpySettings.Load(); - this.spySettingsForMainWindow_Loaded = spySettings; - this.sessionSettings = new SessionSettings(spySettings); + + var spySettings = SettingsService.Instance.SpySettings; + var sessionSettings = SettingsService.Instance.SessionSettings; + this.CurrentDecompilerSettings = DecompilerSettingsPanel.LoadDecompilerSettings(spySettings); this.CurrentDisplaySettings = DisplaySettingsPanel.LoadDisplaySettings(spySettings); this.AssemblyListManager = new AssemblyListManager(spySettings) { @@ -144,10 +139,11 @@ namespace ICSharpCode.ILSpy InitializeComponent(); InitToolPanes(); DockWorkspace.Instance.InitializeLayout(DockManager); - sessionSettings.PropertyChanged += SessionSettings_PropertyChanged; - filterSettings = sessionSettings.FilterSettings; - filterSettings.PropertyChanged += filterSettings_PropertyChanged; + + MessageBus.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e); + MessageBus.Subscribers += (sender, e) => filterSettings_PropertyChanged(sender, e); MessageBus.Subscribers += DockWorkspace_ActiveTabPageChanged; + InitMainMenu(); InitWindowMenu(); InitToolbar(); @@ -160,9 +156,6 @@ namespace ICSharpCode.ILSpy private void DockWorkspace_ActiveTabPageChanged(object sender, EventArgs e) { DockWorkspace dock = DockWorkspace.Instance; - filterSettings.PropertyChanged -= filterSettings_PropertyChanged; - filterSettings = dock.ActiveTabPage.FilterSettings; - filterSettings.PropertyChanged += filterSettings_PropertyChanged; var windowMenuItem = mainMenu.Items.OfType().First(m => (string)m.Tag == nameof(Properties.Resources._Window)); foreach (MenuItem menuItem in windowMenuItem.Items.OfType()) @@ -176,6 +169,8 @@ namespace ICSharpCode.ILSpy private void SessionSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) { + var sessionSettings = SettingsService.Instance.SessionSettings; + switch (e.PropertyName) { case nameof(SessionSettings.ActiveAssemblyList): @@ -580,6 +575,8 @@ namespace ICSharpCode.ILSpy base.OnSourceInitialized(e); PresentationSource source = PresentationSource.FromVisual(this); + var sessionSettings = SettingsService.Instance.SessionSettings; + // Validate and Set Window Bounds Rect bounds = Rect.Transform(sessionSettings.WindowBounds, source.CompositionTarget.TransformToDevice); var boundsRect = new System.Drawing.Rectangle((int)bounds.Left, (int)bounds.Top, (int)bounds.Width, (int)bounds.Height); @@ -648,7 +645,7 @@ namespace ICSharpCode.ILSpy { LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false); if (args.Language != null) - filterSettings.Language = Languages.GetLanguage(args.Language); + SettingsService.Instance.SessionSettings.LanguageSettings.Language = Languages.GetLanguage(args.Language); return true; } @@ -658,6 +655,8 @@ namespace ICSharpCode.ILSpy /// void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings spySettings = null) { + var sessionSettings = SettingsService.Instance.SessionSettings; + var relevantAssemblies = commandLineLoadedAssemblies.ToList(); commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies); @@ -832,15 +831,13 @@ namespace ICSharpCode.ILSpy void MainWindow_Loaded(object sender, RoutedEventArgs e) { - DockWorkspace.Instance.TabPages.Add(new TabPageModel() { - FilterSettings = filterSettings.Clone() - }); + DockWorkspace.Instance.TabPages.Add(new() { }); DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.First(); - ILSpySettings spySettings = this.spySettingsForMainWindow_Loaded; - this.spySettingsForMainWindow_Loaded = null; var loadPreviousAssemblies = Options.MiscSettingsPanel.CurrentMiscSettings.LoadPreviousAssemblies; + var sessionSettings = SettingsService.Instance.SessionSettings; + if (loadPreviousAssemblies) { // Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff. @@ -870,7 +867,7 @@ namespace ICSharpCode.ILSpy this.assemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true); } - Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => OpenAssemblies(spySettings))); + Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => OpenAssemblies(SettingsService.Instance.SpySettings))); } void OpenAssemblies(ILSpySettings spySettings) @@ -1000,7 +997,6 @@ namespace ICSharpCode.ILSpy assemblyList.CollectionChanged += assemblyList_Assemblies_CollectionChanged; assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); - assemblyListTreeNode.FilterSettings = filterSettings.Clone(); assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false); AssemblyTreeView.Root = assemblyListTreeNode; @@ -1064,13 +1060,7 @@ namespace ICSharpCode.ILSpy public void RefreshTreeViewFilter() { - // filterSettings is mutable; but the ILSpyTreeNode filtering assumes that filter settings are immutable. - // Thus, the main window will use one mutable instance (for data-binding), and assign a new clone to the ILSpyTreeNodes whenever the main - // mutable instance changes. - FilterSettings filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings.Clone(); - if (assemblyListTreeNode != null) - assemblyListTreeNode.FilterSettings = filterSettings; - SearchPane.UpdateFilter(filterSettings); + SearchPane.UpdateFilter(); } internal AssemblyListTreeNode AssemblyListTreeNode { @@ -1097,10 +1087,7 @@ namespace ICSharpCode.ILSpy { if (inNewTabPage) { - DockWorkspace.Instance.TabPages.Add( - new TabPageModel() { - FilterSettings = filterSettings.Clone() - }); + DockWorkspace.Instance.TabPages.Add(new TabPageModel() { }); DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); AssemblyTreeView.SelectedItem = null; } @@ -1143,10 +1130,7 @@ namespace ICSharpCode.ILSpy { if (inNewTabPage) { - DockWorkspace.Instance.TabPages.Add( - new TabPageModel() { - FilterSettings = filterSettings.Clone() - }); + DockWorkspace.Instance.TabPages.Add(new TabPageModel() { }); DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); } @@ -1519,8 +1503,9 @@ namespace ICSharpCode.ILSpy } } - public Language CurrentLanguage => DockWorkspace.Instance.ActiveTabPage.FilterSettings.Language; - public LanguageVersion CurrentLanguageVersion => DockWorkspace.Instance.ActiveTabPage.FilterSettings.LanguageVersion; + public Language CurrentLanguage => SettingsService.Instance.SessionSettings.LanguageSettings.Language; + + public LanguageVersion CurrentLanguageVersion => SettingsService.Instance.SessionSettings.LanguageSettings.LanguageVersion; public event SelectionChangedEventHandler SelectionChanged; @@ -1590,10 +1575,7 @@ namespace ICSharpCode.ILSpy { if (inNewTabPage) { - DockWorkspace.Instance.TabPages.Add( - new TabPageModel() { - FilterSettings = filterSettings.Clone() - }); + DockWorkspace.Instance.TabPages.Add(new() { }); DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); } @@ -1646,18 +1628,19 @@ namespace ICSharpCode.ILSpy base.OnStateChanged(e); // store window state in settings only if it's not minimized if (this.WindowState != System.Windows.WindowState.Minimized) - sessionSettings.WindowState = this.WindowState; + SettingsService.Instance.SessionSettings.WindowState = this.WindowState; } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); + var sessionSettings = SettingsService.Instance.SessionSettings; + sessionSettings.ActiveAssemblyList = assemblyList.ListName; sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode); sessionSettings.WindowBounds = this.RestoreBounds; sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(DockManager)); - sessionSettings.FilterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings.Clone(); sessionSettings.Save(); } diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml.cs b/ILSpy/Options/DisplaySettingsPanel.xaml.cs index 0319b327d..3e81eb7fe 100644 --- a/ILSpy/Options/DisplaySettingsPanel.xaml.cs +++ b/ILSpy/Options/DisplaySettingsPanel.xaml.cs @@ -27,6 +27,7 @@ using System.Windows.Media; using System.Windows.Threading; using System.Xml.Linq; +using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpyX.Settings; namespace ICSharpCode.ILSpy.Options @@ -123,7 +124,7 @@ namespace ICSharpCode.ILSpy.Options s.ShowRawOffsetsAndBytesBeforeInstruction = (bool?)e.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false; s.StyleWindowTitleBar = (bool?)e.Attribute("StyleWindowTitleBar") ?? false; - s.Theme = MainWindow.Instance.SessionSettings.Theme; + s.Theme = SettingsService.Instance.SessionSettings.Theme; return s; } @@ -154,8 +155,8 @@ namespace ICSharpCode.ILSpy.Options section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", s.ShowRawOffsetsAndBytesBeforeInstruction); section.SetAttributeValue("StyleWindowTitleBar", s.StyleWindowTitleBar); - MainWindow.Instance.SessionSettings.Theme = s.Theme; - var sessionSettings = MainWindow.Instance.SessionSettings.ToXml(); + SettingsService.Instance.SessionSettings.Theme = s.Theme; + var sessionSettings = SettingsService.Instance.SessionSettings.ToXml(); MainWindow.Instance.CurrentDisplaySettings.CopyValues(s); diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs index e35a4da73..f3bd6a550 100644 --- a/ILSpy/Search/SearchPane.cs +++ b/ILSpy/Search/SearchPane.cs @@ -50,6 +50,7 @@ namespace ICSharpCode.ILSpy.Search /// [DataTemplate(typeof(SearchPaneModel))] [PartCreationPolicy(CreationPolicy.Shared)] + [Export] public partial class SearchPane : UserControl { const int MAX_RESULTS = 1000; @@ -57,7 +58,6 @@ namespace ICSharpCode.ILSpy.Search RunningSearch currentSearch; bool runSearchOnNextShow; IComparer resultsComparer; - FilterSettings filterSettings; public static readonly DependencyProperty ResultsProperty = DependencyProperty.Register("Results", typeof(ObservableCollection), typeof(SearchPane), @@ -84,11 +84,10 @@ namespace ICSharpCode.ILSpy.Search ContextMenuProvider.Add(listBox); MessageBus.Subscribers += (sender, e) => MainWindow_Instance_CurrentAssemblyListChanged(sender, e); - filterSettings = MainWindow.Instance.SessionSettings.FilterSettings; CompositionTarget.Rendering += UpdateResults; // This starts empty search right away, so do at the end (we're still in ctor) - searchModeComboBox.SelectedIndex = (int)MainWindow.Instance.SessionSettings.SelectedSearchMode; + searchModeComboBox.SelectedIndex = (int)SettingsService.Instance.SessionSettings.SelectedSearchMode; } void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) @@ -104,10 +103,8 @@ namespace ICSharpCode.ILSpy.Search } } - internal void UpdateFilter(FilterSettings settings) + internal void UpdateFilter() { - this.filterSettings = settings; - if (IsVisible) { StartSearch(this.SearchTerm); @@ -155,7 +152,7 @@ namespace ICSharpCode.ILSpy.Search void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { - MainWindow.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex; + SettingsService.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex; StartSearch(this.SearchTerm); } @@ -258,7 +255,7 @@ namespace ICSharpCode.ILSpy.Search searchProgressBar.IsIndeterminate = true; startedSearch = new RunningSearch(await mainWindow.CurrentAssemblyList.GetAllAssemblies(), searchTerm, (SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage, - filterSettings.ShowApiLevel); + SettingsService.Instance.SessionSettings.LanguageSettings.ShowApiLevel); currentSearch = startedSearch; await startedSearch.Run(); diff --git a/ILSpy/SessionSettings.cs b/ILSpy/SessionSettings.cs index 4004513c5..ad58d121f 100644 --- a/ILSpy/SessionSettings.cs +++ b/ILSpy/SessionSettings.cs @@ -28,6 +28,7 @@ using System.Xml.Linq; using ICSharpCode.ILSpy.Docking; using ICSharpCode.ILSpy.Themes; +using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpyX.Search; using ICSharpCode.ILSpyX.Settings; @@ -47,7 +48,7 @@ namespace ICSharpCode.ILSpy if (filterSettings == null) filterSettings = new XElement("FilterSettings"); - this.FilterSettings = new FilterSettings(filterSettings); + this.LanguageSettings = new LanguageSettings(filterSettings); this.ActiveAssemblyList = (string)doc.Element("ActiveAssemblyList"); @@ -72,10 +73,15 @@ namespace ICSharpCode.ILSpy void OnPropertyChanged([CallerMemberName] string propertyName = null) { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + var args = new PropertyChangedEventArgs(propertyName); + + PropertyChanged?.Invoke(this, args); + + MessageBus.Send(this, new SessionSettingsChangedEventArgs(args)); } - public FilterSettings FilterSettings { get; internal set; } + public LanguageSettings LanguageSettings { get; } + public SearchMode SelectedSearchMode { get; set; } public string Theme { @@ -113,16 +119,16 @@ namespace ICSharpCode.ILSpy } } - public WindowState WindowState = WindowState.Normal; + public WindowState WindowState; public Rect WindowBounds; internal static Rect DefaultWindowBounds = new Rect(10, 10, 750, 550); - public DockLayoutSettings DockLayout { get; private set; } + public DockLayoutSettings DockLayout { get; } public XElement ToXml() { XElement doc = new XElement("SessionSettings"); - doc.Add(this.FilterSettings.SaveAsXml()); + doc.Add(this.LanguageSettings.SaveAsXml()); if (this.ActiveAssemblyList != null) { doc.Add(new XElement("ActiveAssemblyList", this.ActiveAssemblyList)); diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index a92a98362..b28c0809f 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -449,7 +449,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return dataObject; } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.SearchTermMatches(LoadedAssembly.ShortName)) return FilterResult.Match; diff --git a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs index 525bb8aa3..caea0a521 100644 --- a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public override object Icon => TypeTreeNode.GetIcon(type); - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs index 0499f5dff..30cd704f8 100644 --- a/ILSpy/TreeNodes/EventTreeNode.cs +++ b/ILSpy/TreeNodes/EventTreeNode.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return Images.GetIcon(MemberIcon.Event, MethodTreeNode.GetOverlayIcon(@event.Accessibility), @event.IsStatic); } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs index 4df85b89f..4509f2ca6 100644 --- a/ILSpy/TreeNodes/FieldTreeNode.cs +++ b/ILSpy/TreeNodes/FieldTreeNode.cs @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return Images.GetIcon(MemberIcon.Field, MethodTreeNode.GetOverlayIcon(field.Accessibility), field.IsStatic); } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs index 56c055308..f5c2aa2cd 100644 --- a/ILSpy/TreeNodes/ILSpyTreeNode.cs +++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs @@ -27,6 +27,7 @@ using System.Windows.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpyX.Abstractions; using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions; using ICSharpCode.ILSpyX.TreeView; @@ -38,25 +39,20 @@ namespace ICSharpCode.ILSpy.TreeNodes /// public abstract class ILSpyTreeNode : SharpTreeNode, ITreeNode { - FilterSettings filterSettings; bool childrenNeedFiltering; - public FilterSettings FilterSettings { - get { return filterSettings; } - set { - if (filterSettings != value) - { - filterSettings = value; - OnFilterSettingsChanged(); - } - } + public ILSpyTreeNode() + { + MessageBus.Subscribers += LanguageSettings_Changed; } + LanguageSettings LanguageSettings => SettingsService.Instance.SessionSettings.LanguageSettings; + public Language Language { - get { return filterSettings != null ? filterSettings.Language : Languages.AllLanguages[0]; } + get { return LanguageSettings.Language ?? Languages.AllLanguages[0]; } } - public virtual FilterResult Filter(FilterSettings settings) + public virtual FilterResult Filter(LanguageSettings settings) { if (string.IsNullOrEmpty(settings.SearchTerm)) return FilterResult.Match; @@ -92,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes return false; } - internal protected override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) + protected internal override void OnChildrenChanged(NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { @@ -111,27 +107,21 @@ namespace ICSharpCode.ILSpy.TreeNodes void ApplyFilterToChild(ILSpyTreeNode child) { - FilterResult r; - if (this.FilterSettings == null) - r = FilterResult.Match; - else - r = child.Filter(this.FilterSettings); + FilterResult r = child.Filter(this.LanguageSettings); + switch (r) { case FilterResult.Hidden: child.IsHidden = true; break; case FilterResult.Match: - child.FilterSettings = StripSearchTerm(this.FilterSettings); child.IsHidden = false; break; case FilterResult.Recurse: - child.FilterSettings = this.FilterSettings; child.EnsureChildrenFiltered(); child.IsHidden = child.Children.All(c => c.IsHidden); break; case FilterResult.MatchAndRecurse: - child.FilterSettings = StripSearchTerm(this.FilterSettings); child.EnsureChildrenFiltered(); child.IsHidden = child.Children.All(c => c.IsHidden); break; @@ -140,19 +130,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } - static FilterSettings StripSearchTerm(FilterSettings filterSettings) - { - if (filterSettings == null) - return null; - if (!string.IsNullOrEmpty(filterSettings.SearchTerm)) - { - filterSettings = filterSettings.Clone(); - filterSettings.SearchTerm = null; - } - return filterSettings; - } - - protected virtual void OnFilterSettingsChanged() + protected virtual void LanguageSettings_Changed(object sender, EventArgs e) { RaisePropertyChanged(nameof(Text)); if (IsVisible) @@ -166,11 +144,6 @@ namespace ICSharpCode.ILSpy.TreeNodes } } - /*protected override void OnIsVisibleChanged() - { - base.OnIsVisibleChanged(); - EnsureChildrenFiltered(); - }*/ internal void EnsureChildrenFiltered() { diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index c805d5a83..090055123 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.TreeNodes language.DecompileMethod(MethodDefinition, output, options); } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; diff --git a/ILSpy/TreeNodes/NamespaceTreeNode.cs b/ILSpy/TreeNodes/NamespaceTreeNode.cs index 19982834f..c3c759c70 100644 --- a/ILSpy/TreeNodes/NamespaceTreeNode.cs +++ b/ILSpy/TreeNodes/NamespaceTreeNode.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.isPublicAPI = value; } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.SearchTermMatches(name)) return FilterResult.MatchAndRecurse; diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs index ab437f8d4..8374d094f 100644 --- a/ILSpy/TreeNodes/PropertyTreeNode.cs +++ b/ILSpy/TreeNodes/PropertyTreeNode.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes MethodTreeNode.GetOverlayIcon(property.Accessibility), property.IsStatic); } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; diff --git a/ILSpy/TreeNodes/ResourceListTreeNode.cs b/ILSpy/TreeNodes/ResourceListTreeNode.cs index d812b7966..5f143db9a 100644 --- a/ILSpy/TreeNodes/ResourceListTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceListTreeNode.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.Children.Add(ResourceTreeNode.Create(r)); } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (string.IsNullOrEmpty(settings.SearchTerm)) return FilterResult.MatchAndRecurse; diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs index bb306aa9a..69502149f 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs @@ -55,7 +55,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public override object Icon => Images.Resource; - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && (Resource.Attributes & ManifestResourceAttributes.VisibilityMask) == ManifestResourceAttributes.Private) return FilterResult.Hidden; diff --git a/ILSpy/TreeNodes/ThreadingSupport.cs b/ILSpy/TreeNodes/ThreadingSupport.cs index 7f99b3afb..ce1d87515 100644 --- a/ILSpy/TreeNodes/ThreadingSupport.cs +++ b/ILSpy/TreeNodes/ThreadingSupport.cs @@ -138,7 +138,7 @@ namespace ICSharpCode.ILSpy.TreeNodes get { return Resources.Loading; } } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { return FilterResult.Match; } @@ -161,7 +161,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.text = text; } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { return FilterResult.Match; } diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 5917f35e0..91f7e11c3 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } } - public override FilterResult Filter(FilterSettings settings) + public override FilterResult Filter(LanguageSettings settings) { if (settings.ShowApiLevel == ApiVisibility.PublicOnly && !IsPublicAPI) return FilterResult.Hidden; diff --git a/ILSpy/Util/MessageBus.cs b/ILSpy/Util/MessageBus.cs index 288f97227..7573cb33c 100644 --- a/ILSpy/Util/MessageBus.cs +++ b/ILSpy/Util/MessageBus.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Specialized; +using System.ComponentModel; using TomsToolbox.Essentials; @@ -51,5 +52,9 @@ namespace ICSharpCode.ILSpy.Util public class CurrentAssemblyListChangedEventArgs(NotifyCollectionChangedEventArgs e) : WrappedEventArgs(e); + public class LanguageSettingsChangedEventArgs(PropertyChangedEventArgs e) : WrappedEventArgs(e); + + public class SessionSettingsChangedEventArgs(PropertyChangedEventArgs e) : WrappedEventArgs(e); + public class DockWorkspaceActiveTabPageChangedEventArgs : EventArgs; } \ No newline at end of file diff --git a/ILSpy/Util/SettingsService.cs b/ILSpy/Util/SettingsService.cs new file mode 100644 index 000000000..0f7a07e6a --- /dev/null +++ b/ILSpy/Util/SettingsService.cs @@ -0,0 +1,20 @@ +using ICSharpCode.ILSpyX.Settings; + +namespace ICSharpCode.ILSpy.Util +{ + internal class SettingsService + { + public static readonly SettingsService Instance = new SettingsService(); + + private SettingsService() + { + this.SpySettings = ILSpySettings.Load(); + + SessionSettings = new(this.SpySettings); + } + + public ILSpySettings SpySettings { get; } + + public SessionSettings SessionSettings { get; } + } +} diff --git a/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs b/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs index 57f6edb96..23959c2c3 100644 --- a/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs +++ b/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs @@ -27,6 +27,7 @@ using System.Windows.Input; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Commands; using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.ViewModels @@ -174,7 +175,7 @@ namespace ICSharpCode.ILSpy.ViewModels return; manager.ClearAll(); manager.CreateDefaultAssemblyLists(); - MainWindow.Instance.SessionSettings.ActiveAssemblyList = manager.AssemblyLists[0]; + SettingsService.Instance.SessionSettings.ActiveAssemblyList = manager.AssemblyLists[0]; } private void ExecuteDelete() @@ -189,9 +190,9 @@ namespace ICSharpCode.ILSpy.ViewModels if (manager.AssemblyLists.Count > 0) { SelectedAssemblyList = manager.AssemblyLists[Math.Max(0, index - 1)]; - if (MainWindow.Instance.SessionSettings.ActiveAssemblyList == assemblyList) + if (SettingsService.Instance.SessionSettings.ActiveAssemblyList == assemblyList) { - MainWindow.Instance.SessionSettings.ActiveAssemblyList = SelectedAssemblyList; + SettingsService.Instance.SessionSettings.ActiveAssemblyList = SelectedAssemblyList; } } } @@ -232,9 +233,9 @@ namespace ICSharpCode.ILSpy.ViewModels string assemblyList = SelectedAssemblyList; SelectedAssemblyList = dlg.ListName; manager.RenameList(assemblyList, dlg.ListName); - if (MainWindow.Instance.SessionSettings.ActiveAssemblyList == assemblyList) + if (SettingsService.Instance.SessionSettings.ActiveAssemblyList == assemblyList) { - MainWindow.Instance.SessionSettings.ActiveAssemblyList = manager.AssemblyLists[manager.AssemblyLists.Count - 1]; + SettingsService.Instance.SessionSettings.ActiveAssemblyList = manager.AssemblyLists[manager.AssemblyLists.Count - 1]; } } } @@ -272,7 +273,7 @@ namespace ICSharpCode.ILSpy.ViewModels private void ExecuteSelectAssemblyList() { - MainWindow.Instance.SessionSettings.ActiveAssemblyList = SelectedAssemblyList; + SettingsService.Instance.SessionSettings.ActiveAssemblyList = SelectedAssemblyList; this.parent.Close(); } } diff --git a/ILSpy/ViewModels/TabPageModel.cs b/ILSpy/ViewModels/TabPageModel.cs index 836560c2c..71063243e 100644 --- a/ILSpy/ViewModels/TabPageModel.cs +++ b/ILSpy/ViewModels/TabPageModel.cs @@ -17,11 +17,10 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.ViewModels @@ -33,29 +32,6 @@ namespace ICSharpCode.ILSpy.ViewModels this.Title = Properties.Resources.NewTab; } - private FilterSettings filterSettings; - - public FilterSettings FilterSettings { - get => filterSettings; - set { - if (filterSettings != value) - { - filterSettings = value; - RaisePropertyChanged(nameof(FilterSettings)); - } - } - } - - public Language Language { - get => filterSettings.Language; - set => filterSettings.Language = value; - } - - public LanguageVersion LanguageVersion { - get => filterSettings.LanguageVersion; - set => filterSettings.LanguageVersion = value; - } - private bool supportsLanguageSwitching = true; public bool SupportsLanguageSwitching { diff --git a/ILSpy/Views/DebugSteps.xaml.cs b/ILSpy/Views/DebugSteps.xaml.cs index 3b59c383f..29aa4261b 100644 --- a/ILSpy/Views/DebugSteps.xaml.cs +++ b/ILSpy/Views/DebugSteps.xaml.cs @@ -29,16 +29,13 @@ namespace ICSharpCode.ILSpy #if DEBUG ILAstLanguage language; #endif - FilterSettings filterSettings; - public DebugSteps() { InitializeComponent(); #if DEBUG - MessageBus.Subscribers += DockWorkspace_ActiveTabPageChanged; - filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings; - filterSettings.PropertyChanged += FilterSettings_PropertyChanged; + MessageBus.Subscribers += (sender, e) => LanguageSettings_PropertyChanged(sender, e); + MainWindow.Instance.SelectionChanged += SelectionChanged; writingOptions.PropertyChanged += WritingOptions_PropertyChanged; @@ -51,13 +48,6 @@ namespace ICSharpCode.ILSpy #endif } - private void DockWorkspace_ActiveTabPageChanged(object sender, EventArgs e) - { - filterSettings.PropertyChanged -= FilterSettings_PropertyChanged; - filterSettings = DockWorkspace.Instance.ActiveTabPage.FilterSettings; - filterSettings.PropertyChanged += FilterSettings_PropertyChanged; - } - private void WritingOptions_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { DecompileAsync(lastSelectedStep); @@ -71,7 +61,7 @@ namespace ICSharpCode.ILSpy }); } - private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + private void LanguageSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { #if DEBUG if (e.PropertyName == "Language")