Browse Source

Refactor SearchPane so only the view model is exposed.

pull/3266/head
tom-englert 9 months ago committed by Siegfried Pammer
parent
commit
dde581adc8
  1. 4
      ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs
  2. 13
      ILSpy/Commands/ScopeSearchToAssembly.cs
  3. 14
      ILSpy/Commands/ScopeSearchToNamespace.cs
  4. 8
      ILSpy/Controls/CultureSelectionConverter.cs
  5. 46
      ILSpy/Controls/TreeView/Converters.cs
  6. 5
      ILSpy/Controls/TreeView/SharpTreeView.xaml
  7. 6
      ILSpy/DecompilationOptions.cs
  8. 11
      ILSpy/Docking/DockWorkspace.cs
  9. 66
      ILSpy/MainWindow.xaml
  10. 30
      ILSpy/MainWindow.xaml.cs
  11. 6
      ILSpy/Options/DisplaySettings.cs
  12. 2
      ILSpy/Options/DisplaySettingsPanel.xaml
  13. 8
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  14. 20
      ILSpy/Search/SearchPane.xaml
  15. 161
      ILSpy/Search/SearchPane.xaml.cs
  16. 41
      ILSpy/Search/SearchPaneModel.cs
  17. 4
      ILSpy/TextView/DecompilerTextView.cs
  18. 2
      ILSpy/Themes/WindowStyleManagerBehavior.cs
  19. 2
      ILSpy/Util/SettingsService.cs
  20. 97
      ILSpy/ViewModels/PaneModel.cs

4
ICSharpCode.ILSpyX/Search/AbstractSearchStrategy.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.ILSpyX.Search
public AssemblySearchKind AssemblySearchKind; public AssemblySearchKind AssemblySearchKind;
public MemberSearchKind MemberSearchKind; public MemberSearchKind MemberSearchKind;
public string[] Keywords; public string[] Keywords;
public Regex RegEx; public Regex? RegEx;
public bool FullNameSearch; public bool FullNameSearch;
public bool OmitGenerics; public bool OmitGenerics;
public string InNamespace; public string InNamespace;
@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpyX.Search
public abstract class AbstractSearchStrategy public abstract class AbstractSearchStrategy
{ {
protected readonly string[] searchTerm; protected readonly string[] searchTerm;
protected readonly Regex regex; protected readonly Regex? regex;
protected readonly bool fullNameSearch; protected readonly bool fullNameSearch;
protected readonly bool omitGenerics; protected readonly bool omitGenerics;
protected readonly SearchRequest searchRequest; protected readonly SearchRequest searchRequest;

13
ILSpy/Commands/ScopeSearchToAssembly.cs

@ -23,6 +23,7 @@ using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -31,11 +32,19 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.Shared)]
public class ScopeSearchToAssembly : IContextMenuEntry public class ScopeSearchToAssembly : IContextMenuEntry
{ {
private readonly SearchPaneModel searchPane;
[ImportingConstructor]
public ScopeSearchToAssembly(SearchPaneModel searchPane)
{
this.searchPane = searchPane;
}
public void Execute(TextViewContext context) public void Execute(TextViewContext context)
{ {
// asmName cannot be null here, because Execute is only called if IsEnabled/IsVisible return true. // asmName cannot be null here, because Execute is only called if IsEnabled/IsVisible return true.
string asmName = GetAssembly(context)!; string asmName = GetAssembly(context)!;
string searchTerm = MainWindow.Instance.SearchPane.SearchTerm; string searchTerm = searchPane.SearchTerm;
string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm); string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
bool replaced = false; bool replaced = false;
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
@ -55,7 +64,7 @@ namespace ICSharpCode.ILSpy
{ {
searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args); searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
} }
MainWindow.Instance.SearchPane.SearchTerm = searchTerm; searchPane.SearchTerm = searchTerm;
} }
public bool IsEnabled(TextViewContext context) public bool IsEnabled(TextViewContext context)

14
ILSpy/Commands/ScopeSearchToNamespace.cs

@ -21,6 +21,7 @@ using System.ComponentModel.Composition;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
@ -29,10 +30,18 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.Shared)]
public class ScopeSearchToNamespace : IContextMenuEntry public class ScopeSearchToNamespace : IContextMenuEntry
{ {
private readonly SearchPaneModel searchPane;
[ImportingConstructor]
public ScopeSearchToNamespace(SearchPaneModel searchPane)
{
this.searchPane = searchPane;
}
public void Execute(TextViewContext context) public void Execute(TextViewContext context)
{ {
string ns = GetNamespace(context); string ns = GetNamespace(context);
string searchTerm = MainWindow.Instance.SearchPane.SearchTerm; string searchTerm = searchPane.SearchTerm;
string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm); string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
bool replaced = false; bool replaced = false;
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
@ -52,7 +61,8 @@ namespace ICSharpCode.ILSpy
{ {
searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args); searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
} }
MainWindow.Instance.SearchPane.SearchTerm = searchTerm;
searchPane.SearchTerm = searchTerm;
} }
public bool IsEnabled(TextViewContext context) public bool IsEnabled(TextViewContext context)

8
ILSpy/Controls/CultureSelectionConverter.cs

@ -19,10 +19,11 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy.Controls namespace ICSharpCode.ILSpy.Controls
{ {
public class CultureSelectionConverter : IValueConverter public class CultureSelectionConverter : MarkupExtension, IValueConverter
{ {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
@ -37,5 +38,10 @@ namespace ICSharpCode.ILSpy.Controls
return parameter; return parameter;
return Binding.DoNothing; return Binding.DoNothing;
} }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
} }
} }

46
ILSpy/Controls/TreeView/Converters.cs

@ -1,46 +0,0 @@
// Copyright (c) 2020 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.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy.Controls.TreeView
{
public class CollapsedWhenFalse : MarkupExtension, IValueConverter
{
public static CollapsedWhenFalse Instance = new CollapsedWhenFalse();
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Instance;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

5
ILSpy/Controls/TreeView/SharpTreeView.xaml

@ -1,7 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Default="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView" xmlns:Default="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:styles="urn:TomsToolbox.Wpf.Styles"> xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:toms="urn:TomsToolbox">
<Style x:Key="ExpandCollapseToggleStyle" <Style x:Key="ExpandCollapseToggleStyle"
TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}"> TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
@ -227,7 +228,7 @@
<Grid> <Grid>
<Default:LinesRenderer x:Name="linesRenderer" <Default:LinesRenderer x:Name="linesRenderer"
ClipToBounds="True" ClipToBounds="True"
Visibility="{Binding ShowLines, RelativeSource={RelativeSource AncestorType={x:Type Default:SharpTreeView}}, Converter={Default:CollapsedWhenFalse}}" /> Visibility="{Binding ShowLines, RelativeSource={RelativeSource AncestorType={x:Type Default:SharpTreeView}}, Converter={toms:BooleanToVisibilityConverter}}" />
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<FrameworkElement Name="spacer" /> <FrameworkElement Name="spacer" />
<ToggleButton Name="expander" <ToggleButton Name="expander"

6
ILSpy/DecompilationOptions.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Gets the settings for the decompiler. /// Gets the settings for the decompiler.
/// </summary> /// </summary>
public Decompiler.DecompilerSettings DecompilerSettings { get; private set; } public DecompilerSettings DecompilerSettings { get; private set; }
/// <summary> /// <summary>
/// Gets/sets an optional state of a decompiler text view. /// Gets/sets an optional state of a decompiler text view.
@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy
internal int StepLimit = int.MaxValue; internal int StepLimit = int.MaxValue;
internal bool IsDebug = false; internal bool IsDebug = false;
public DecompilationOptions(LanguageVersion version, Decompiler.DecompilerSettings settings, DisplaySettingsViewModel displaySettings) public DecompilationOptions(LanguageVersion version, DecompilerSettings settings, DisplaySettings displaySettings)
{ {
if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion)) if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion))
languageVersion = Decompiler.CSharp.LanguageVersion.Latest; languageVersion = Decompiler.CSharp.LanguageVersion.Latest;
@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy
newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings); newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings);
} }
private string GetIndentationString(DisplaySettingsViewModel displaySettings) private string GetIndentationString(DisplaySettings displaySettings)
{ {
if (displaySettings.IndentationUseTabs) if (displaySettings.IndentationUseTabs)
{ {

11
ILSpy/Docking/DockWorkspace.cs

@ -17,17 +17,12 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Navigation;
using System.Windows.Threading; using System.Windows.Threading;
using AvalonDock; using AvalonDock;
@ -36,6 +31,7 @@ using AvalonDock.Layout.Serialization;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
@ -219,7 +215,7 @@ namespace ICSharpCode.ILSpy.Docking
} }
CloseAllTabs(); CloseAllTabs();
SessionSettings.DockLayout.Reset(); SessionSettings.DockLayout.Reset();
InitializeLayout(MainWindow.Instance.DockManager); InitializeLayout(MainWindow.Instance.dockManager);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView); MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView);
} }
@ -268,5 +264,8 @@ namespace ICSharpCode.ILSpy.Docking
public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown) public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown)
{ {
} }
// Dummy property to make the XAML designer happy, the model is provided by the AvalonDock PaneStyleSelectors, not by the DockWorkspace, but the designer assumes the data context in the PaneStyleSelectors is the DockWorkspace.
public PaneModel Model { get; } = null;
} }
} }

66
ILSpy/MainWindow.xaml

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Window <Window
x:Class="ICSharpCode.ILSpy.MainWindow" x:Class="ICSharpCode.ILSpy.MainWindow"
x:ClassModifier="public"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView" xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:local="clr-namespace:ICSharpCode.ILSpy" xmlns:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:search="clr-namespace:ICSharpCode.ILSpy.Search"
xmlns:avalondock="https://github.com/Dirkster99/AvalonDock" xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking" xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking"
@ -22,8 +21,9 @@
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes" xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:toms="urn:TomsToolbox" xmlns:toms="urn:TomsToolbox"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels" xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}" xmlns:treeNodes="clr-namespace:ICSharpCode.ILSpy.TreeNodes"
> xmlns:util="clr-namespace:ICSharpCode.ILSpy.Util"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
<Window.Resources> <Window.Resources>
<tv:SharpTreeView x:Key="AssemblyTreeView" <tv:SharpTreeView x:Key="AssemblyTreeView"
AutomationProperties.Name="Assemblies and Classes" AutomationProperties.Name="Assemblies and Classes"
@ -36,7 +36,7 @@
<Style TargetType="tv:SharpTreeViewItem"> <Style TargetType="tv:SharpTreeViewItem">
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type tv:SharpTreeViewItem}"> <ControlTemplate TargetType="{x:Type tv:SharpTreeViewItem}" d:DataContext="{d:DesignInstance treeNodes:ILSpyTreeNode}">
<Border Background="Transparent"> <Border Background="Transparent">
<Border Background="{TemplateBinding Background}"> <Border Background="{TemplateBinding Background}">
<tv:SharpTreeNodeView x:Name="nodeView" HorizontalAlignment="Left" /> <tv:SharpTreeNodeView x:Name="nodeView" HorizontalAlignment="Left" />
@ -76,8 +76,6 @@
<ContentPresenter Content="{Binding Content}" /> <ContentPresenter Content="{Binding Content}" />
</DataTemplate> </DataTemplate>
<controls:CultureSelectionConverter x:Key="cultureSelectionConverter" />
<toms:BindingRelay x:Key="WindowBinding" DataContext="{Binding}" /> <toms:BindingRelay x:Key="WindowBinding" DataContext="{Binding}" />
</Window.Resources> </Window.Resources>
@ -133,7 +131,8 @@
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}"> <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Command" Value="{x:Static local:ILSpyCommands.SetTheme}" /> <Setter Property="Command" Value="{x:Static local:ILSpyCommands.SetTheme}" />
<Setter Property="CommandParameter" Value="{Binding}" /> <Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="IsCheckable" Value="True" /><!-- Required by AvalonDock's MenuItem style to show the checkmark --> <Setter Property="IsCheckable" Value="True" />
<!-- Required by AvalonDock's MenuItem style to show the checkmark -->
<Setter Property="IsChecked"> <Setter Property="IsChecked">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{x:Static toms:BinaryOperationConverter.Equality}" Mode="OneWay"> <MultiBinding Converter="{x:Static toms:BinaryOperationConverter.Equality}" Mode="OneWay">
@ -146,9 +145,9 @@
</MenuItem.ItemContainerStyle> </MenuItem.ItemContainerStyle>
</MenuItem> </MenuItem>
<MenuItem Header="{x:Static properties:Resources.UILanguage}"> <MenuItem Header="{x:Static properties:Resources.UILanguage}">
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter={x:Null}}" /> <MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter={x:Null}}" />
<MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter=en-US}" /> <MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=en-US}" />
<MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={StaticResource cultureSelectionConverter}, ConverterParameter=zh-Hans}" /> <MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=zh-Hans}" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" /> <MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" />
@ -184,27 +183,38 @@
<!-- 'Open' toolbar category is inserted here --> <!-- 'Open' toolbar category is inserted here -->
<Separator /> <Separator />
<ComboBox Name="assemblyListComboBox" Width="100" MaxDropDownHeight="Auto" <ComboBox Name="assemblyListComboBox" Width="100" MaxDropDownHeight="Auto"
ItemsSource="{Binding AssemblyListManager.AssemblyLists}" ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}" ItemsSource="{Binding AssemblyListManager.AssemblyLists}"
ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}"
SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" /> SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" />
<Button Command="{x:Static local:ILSpyCommands.ManageAssemblyListsCommand}" ToolTip="{x:Static properties:Resources.ManageAssemblyLists}"> <Button Command="{x:Static local:ILSpyCommands.ManageAssemblyListsCommand}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ManageAssemblyLists}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</Button> </Button>
<Separator /> <Separator />
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}"> <CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}"> <CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox> </CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}"> <CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}"
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}" Style="{StaticResource DarkModeAwareImageStyle}"/> ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}"
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox> </CheckBox>
<Separator /> <Separator />
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto" <ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}" IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}" ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}" ItemsSource="{x:Static local:Languages.AllLanguages}"
ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" /> SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" />
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto" ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}" <ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto"
ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}" Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}" IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
@ -215,8 +225,10 @@
<DockPanel KeyboardNavigation.TabNavigation="Contained"> <DockPanel KeyboardNavigation.TabNavigation="Contained">
<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button> <Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center" Text="{x:Static properties:Resources.ILSpyVersionAvailable}" /> <TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center"
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick" Content="{x:Static properties:Resources.Download}"/> Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick"
Content="{x:Static properties:Resources.Download}" />
</StackPanel> </StackPanel>
</DockPanel> </DockPanel>
</Border> </Border>
@ -225,13 +237,13 @@
<StatusBarItem DockPanel.Dock="Right"> <StatusBarItem DockPanel.Dock="Right">
<TextBlock VerticalAlignment="Center" <TextBlock VerticalAlignment="Center"
HorizontalAlignment="Right" HorizontalAlignment="Right"
x:Name="StatusLabel" x:Name="statusLabel"
ToolTip="{x:Static properties:Resources.Status}" ToolTip="{x:Static properties:Resources.Status}"
Text="{x:Static properties:Resources.StandBy}" /> Text="{x:Static properties:Resources.StandBy}" />
</StatusBarItem> </StatusBarItem>
</StatusBar> </StatusBar>
<avalondock:DockingManager x:Name="DockManager" <avalondock:DockingManager x:Name="dockManager"
DataContext="{Binding Workspace}" DataContext="{Binding Workspace}"
AnchorablesSource="{Binding ToolPanes}" AnchorablesSource="{Binding ToolPanes}"
DocumentsSource="{Binding TabPages}" DocumentsSource="{Binding TabPages}"
@ -239,7 +251,7 @@
AllowMixedOrientation="True"> AllowMixedOrientation="True">
<avalondock:DockingManager.DocumentHeaderTemplate> <avalondock:DockingManager.DocumentHeaderTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type viewModels:PaneModel}">
<TextBlock x:Name="headerText" Text="{Binding Title}" /> <TextBlock x:Name="headerText" Text="{Binding Title}" />
<DataTemplate.Triggers> <DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True"> <DataTrigger Binding="{Binding IsActive}" Value="True">

30
ILSpy/MainWindow.xaml.cs

@ -89,12 +89,6 @@ namespace ICSharpCode.ILSpy
} }
} }
public SearchPane SearchPane {
get {
return App.ExportProvider.GetExportedValue<SearchPane>();
}
}
public DecompilationOptions CreateDecompilationOptions() public DecompilationOptions CreateDecompilationOptions()
{ {
var decompilerView = DockWorkspace.Instance.ActiveTabPage.Content as IProgress<DecompilationProgress>; var decompilerView = DockWorkspace.Instance.ActiveTabPage.Content as IProgress<DecompilationProgress>;
@ -123,10 +117,10 @@ namespace ICSharpCode.ILSpy
} }
InitializeComponent(); InitializeComponent();
InitToolPanes(); InitToolPanes();
DockWorkspace.Instance.InitializeLayout(DockManager); DockWorkspace.Instance.InitializeLayout(dockManager);
MessageBus<SessionSettingsChangedEventArgs>.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e); MessageBus<SessionSettingsChangedEventArgs>.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e);
MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => filterSettings_PropertyChanged(sender, e); MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => LanguageSettings_PropertyChanged(sender, e);
MessageBus<DockWorkspaceActiveTabPageChangedEventArgs>.Subscribers += DockWorkspace_ActiveTabPageChanged; MessageBus<DockWorkspaceActiveTabPageChangedEventArgs>.Subscribers += DockWorkspace_ActiveTabPageChanged;
InitMainMenu(); InitMainMenu();
@ -647,8 +641,10 @@ namespace ICSharpCode.ILSpy
NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies); NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies);
if (args.Search != null) if (args.Search != null)
{ {
SearchPane.SearchTerm = args.Search; var searchPane = App.ExportProvider.GetExportedValue<SearchPaneModel>();
SearchPane.Show();
searchPane.SearchTerm = args.Search;
searchPane.Show();
} }
} }
@ -1004,20 +1000,14 @@ namespace ICSharpCode.ILSpy
assemblyList.OpenAssembly(asm.Location); assemblyList.OpenAssembly(asm.Location);
} }
void filterSettings_PropertyChanged(object sender, PropertyChangedEventArgs e) void LanguageSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
RefreshTreeViewFilter();
if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion") if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion")
{ {
DecompileSelectedNodes(recordHistory: false); DecompileSelectedNodes(recordHistory: false);
} }
} }
public void RefreshTreeViewFilter()
{
SearchPane.UpdateFilter();
}
internal AssemblyListTreeNode AssemblyListTreeNode { internal AssemblyListTreeNode AssemblyListTreeNode {
get { return assemblyListTreeNode; } get { return assemblyListTreeNode; }
} }
@ -1592,7 +1582,7 @@ namespace ICSharpCode.ILSpy
sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
sessionSettings.WindowBounds = this.RestoreBounds; sessionSettings.WindowBounds = this.RestoreBounds;
sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(DockManager)); sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(dockManager));
sessionSettings.Save(); sessionSettings.Save();
} }
@ -1622,8 +1612,8 @@ namespace ICSharpCode.ILSpy
{ {
if (this.statusBar.Visibility == Visibility.Collapsed) if (this.statusBar.Visibility == Visibility.Collapsed)
this.statusBar.Visibility = Visibility.Visible; this.statusBar.Visibility = Visibility.Visible;
this.StatusLabel.Foreground = foreground; this.statusLabel.Foreground = foreground;
this.StatusLabel.Text = status; this.statusLabel.Text = status;
} }
public ItemCollection GetMainMenuItems() public ItemCollection GetMainMenuItems()

6
ILSpy/Options/DisplaySettingsViewModel.cs → ILSpy/Options/DisplaySettings.cs

@ -27,9 +27,9 @@ namespace ICSharpCode.ILSpy.Options
/// <summary> /// <summary>
/// Description of DisplaySettings. /// Description of DisplaySettings.
/// </summary> /// </summary>
public class DisplaySettingsViewModel : INotifyPropertyChanged public class DisplaySettings : INotifyPropertyChanged
{ {
public DisplaySettingsViewModel() public DisplaySettings()
{ {
this.theme = ThemeManager.Current.DefaultTheme; this.theme = ThemeManager.Current.DefaultTheme;
this.selectedFont = new FontFamily("Consolas"); this.selectedFont = new FontFamily("Consolas");
@ -328,7 +328,7 @@ namespace ICSharpCode.ILSpy.Options
} }
} }
public void CopyValues(DisplaySettingsViewModel s) public void CopyValues(DisplaySettings s)
{ {
this.Theme = s.Theme; this.Theme = s.Theme;
this.SelectedFont = s.selectedFont; this.SelectedFont = s.selectedFont;

2
ILSpy/Options/DisplaySettingsPanel.xaml

@ -7,7 +7,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes" xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
d:DataContext="{d:DesignInstance local:DisplaySettingsViewModel}"> d:DataContext="{d:DesignInstance local:DisplaySettings}">
<UserControl.Resources> <UserControl.Resources>
<local:FontSizeConverter x:Key="fontSizeConv" /> <local:FontSizeConverter x:Key="fontSizeConv" />
</UserControl.Resources> </UserControl.Resources>

8
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -99,10 +99,10 @@ namespace ICSharpCode.ILSpy.Options
select ff).ToArray(); select ff).ToArray();
} }
public static DisplaySettingsViewModel LoadDisplaySettings(ILSpySettings settings, SessionSettings sessionSettings = null) public static DisplaySettings LoadDisplaySettings(ILSpySettings settings, SessionSettings sessionSettings = null)
{ {
XElement e = settings["DisplaySettings"]; XElement e = settings["DisplaySettings"];
var s = new DisplaySettingsViewModel(); var s = new DisplaySettings();
s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas"); s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas");
s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3; s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3;
s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false; s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false;
@ -131,7 +131,7 @@ namespace ICSharpCode.ILSpy.Options
public void Save(XElement root) public void Save(XElement root)
{ {
var s = (DisplaySettingsViewModel)this.DataContext; var s = (DisplaySettings)this.DataContext;
var section = new XElement("DisplaySettings"); var section = new XElement("DisplaySettings");
section.SetAttributeValue("Font", s.SelectedFont.Source); section.SetAttributeValue("Font", s.SelectedFont.Source);
@ -190,7 +190,7 @@ namespace ICSharpCode.ILSpy.Options
public void LoadDefaults() public void LoadDefaults()
{ {
SettingsService.Instance.DisplaySettings.CopyValues(new DisplaySettingsViewModel()); SettingsService.Instance.DisplaySettings.CopyValues(new DisplaySettings());
this.DataContext = SettingsService.Instance.DisplaySettings; this.DataContext = SettingsService.Instance.DisplaySettings;
} }
} }

20
ILSpy/Search/SearchPane.xaml

@ -5,7 +5,11 @@
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties" xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="self" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="self" mc:Ignorable="d"
xmlns:toms="urn:TomsToolbox" xmlns:toms="urn:TomsToolbox"
d:DesignHeight="300" d:DesignWidth="300"> xmlns:search="clr-namespace:ICSharpCode.ILSpy.Search"
xmlns:spyX="clr-namespace:ICSharpCode.ILSpyX.Search;assembly=ICSharpCode.ILSpyX"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance search:SearchPaneModel}"
viewModels:Pane.IsActive="{Binding IsActive}">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
@ -20,15 +24,19 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<controls:SearchBox x:Name="searchBox" DockPanel.Dock="Top" Grid.Column="0" Grid.Row="0" Margin="1" <controls:SearchBox x:Name="searchBox" DockPanel.Dock="Top" Grid.Column="0" Grid.Row="0" Margin="1"
PreviewKeyDown="SearchBox_PreviewKeyDown" PreviewKeyDown="SearchBox_PreviewKeyDown"
Text="{Binding SearchTerm, ElementName=self}" ToolTip="{x:Static properties:Resources.SearchPane_Search}" UpdateDelay="0:0:0.1" Text="{Binding SearchTerm, UpdateSourceTrigger=PropertyChanged}" ToolTip="{x:Static properties:Resources.SearchPane_Search}" UpdateDelay="0:0:0.1"
TextChanged="SearchBox_TextChanged"
WatermarkColor="Gray" WatermarkText="{x:Static properties:Resources.WatermarkText}" /> WatermarkColor="Gray" WatermarkText="{x:Static properties:Resources.WatermarkText}" />
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal"> <StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<Label Margin="0,-1" Target="searchModeComboBox" Content="{x:Static properties:Resources._SearchFor}"/> <Label Margin="0,-1" Target="searchModeComboBox" Content="{x:Static properties:Resources._SearchFor}"/>
<ComboBox Width="100" Name="searchModeComboBox" Margin="1" <ComboBox Width="100" Name="searchModeComboBox" Margin="1"
TextSearch.TextPath="Name" TextSearch.TextPath="Name"
ItemsSource="{Binding SearchModes}"
SelectedValuePath="Mode"
SelectedValue="{Binding SessionSettings.SelectedSearchMode, Mode=TwoWay}"
SelectionChanged="SearchModeComboBox_SelectionChanged"> SelectionChanged="SearchModeComboBox_SelectionChanged">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type search:SearchModeModel}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" /> <Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" />
<TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Name}" />
@ -49,7 +57,7 @@
<GridView AllowsColumnReorder="False"> <GridView AllowsColumnReorder="False">
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Name}" SortBy="Name"> <controls:SortableGridViewColumn Header="{x:Static properties:Resources.Name}" SortBy="Name">
<controls:SortableGridViewColumn.CellTemplate> <controls:SortableGridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type spyX:SearchResult}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" /> <Image Height="16" Margin="0,0,4,0" Width="16" Source="{Binding Image}" />
<TextBlock Text="{Binding Name}" ToolTip="{Binding ToolTip}" TextTrimming="CharacterEllipsis" /> <TextBlock Text="{Binding Name}" ToolTip="{Binding ToolTip}" TextTrimming="CharacterEllipsis" />
@ -59,7 +67,7 @@
</controls:SortableGridViewColumn> </controls:SortableGridViewColumn>
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Location}" SortBy="Location"> <controls:SortableGridViewColumn Header="{x:Static properties:Resources.Location}" SortBy="Location">
<controls:SortableGridViewColumn.CellTemplate> <controls:SortableGridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type spyX:SearchResult}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding LocationImage}" /> <Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding LocationImage}" />
<TextBlock Text="{Binding Location}" ToolTip="{Binding Location}" TextTrimming="CharacterEllipsis" /> <TextBlock Text="{Binding Location}" ToolTip="{Binding Location}" TextTrimming="CharacterEllipsis" />
@ -69,7 +77,7 @@
</controls:SortableGridViewColumn> </controls:SortableGridViewColumn>
<controls:SortableGridViewColumn Header="{x:Static properties:Resources.Assembly}" SortBy="Assembly"> <controls:SortableGridViewColumn Header="{x:Static properties:Resources.Assembly}" SortBy="Assembly">
<controls:SortableGridViewColumn.CellTemplate> <controls:SortableGridViewColumn.CellTemplate>
<DataTemplate> <DataTemplate DataType="{x:Type spyX:SearchResult}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding AssemblyImage}" /> <Image Height="16" Margin="4,0,4,0" Width="16" Source="{Binding AssemblyImage}" />
<TextBlock Text="{Binding Assembly}" ToolTip="{Binding Assembly}" TextTrimming="CharacterEllipsis" /> <TextBlock Text="{Binding Assembly}" ToolTip="{Binding Assembly}" TextTrimming="CharacterEllipsis" />

161
ILSpy/Search/SearchPane.cs → ILSpy/Search/SearchPane.xaml.cs

@ -20,10 +20,8 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -34,13 +32,14 @@ using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.ILSpy.AppEnv; using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Util; using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Extensions; using ICSharpCode.ILSpyX.Extensions;
using ICSharpCode.ILSpyX.Search; using ICSharpCode.ILSpyX.Search;
using TomsToolbox.Essentials;
using TomsToolbox.Wpf;
using TomsToolbox.Wpf.Composition.Mef; using TomsToolbox.Wpf.Composition.Mef;
namespace ICSharpCode.ILSpy.Search namespace ICSharpCode.ILSpy.Search
@ -49,48 +48,31 @@ namespace ICSharpCode.ILSpy.Search
/// Search pane /// Search pane
/// </summary> /// </summary>
[DataTemplate(typeof(SearchPaneModel))] [DataTemplate(typeof(SearchPaneModel))]
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.NonShared)]
[Export] public partial class SearchPane
public partial class SearchPane : UserControl
{ {
const int MAX_RESULTS = 1000; const int MAX_RESULTS = 1000;
const int MAX_REFRESH_TIME_MS = 10; // More means quicker forward of data, less means better responsibility const int MAX_REFRESH_TIME_MS = 10; // More means quicker forward of data, fewer means better responsibility
RunningSearch currentSearch; RunningSearch currentSearch;
bool runSearchOnNextShow; bool runSearchOnNextShow;
IComparer<SearchResult> resultsComparer; IComparer<SearchResult> resultsComparer;
public static readonly DependencyProperty ResultsProperty = public ObservableCollection<SearchResult> Results { get; } = [];
DependencyProperty.Register("Results", typeof(ObservableCollection<SearchResult>), typeof(SearchPane),
new PropertyMetadata(new ObservableCollection<SearchResult>())); string SearchTerm => searchBox.Text;
public ObservableCollection<SearchResult> Results {
get { return (ObservableCollection<SearchResult>)GetValue(ResultsProperty); }
}
public SearchPane() public SearchPane()
{ {
InitializeComponent(); InitializeComponent();
searchModeComboBox.Items.Add(new { Image = Images.Library, Name = "Types and Members" });
searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" });
searchModeComboBox.Items.Add(new { Image = Images.Method, Name = "Method" });
searchModeComboBox.Items.Add(new { Image = Images.Field, Name = "Field" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Property" });
searchModeComboBox.Items.Add(new { Image = Images.Event, Name = "Event" });
searchModeComboBox.Items.Add(new { Image = Images.Literal, Name = "Constant" });
searchModeComboBox.Items.Add(new { Image = Images.Library, Name = "Metadata Token" });
searchModeComboBox.Items.Add(new { Image = Images.Resource, Name = "Resource" });
searchModeComboBox.Items.Add(new { Image = Images.Assembly, Name = "Assembly" });
searchModeComboBox.Items.Add(new { Image = Images.Namespace, Name = "Namespace" });
ContextMenuProvider.Add(listBox); ContextMenuProvider.Add(listBox);
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => MainWindow_Instance_CurrentAssemblyListChanged(sender, e); MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed();
CompositionTarget.Rendering += UpdateResults; MessageBus<LanguageSettingsChangedEventArgs>.Subscribers += (sender, e) => LanguageSettings_PropertyChanged();
// This starts empty search right away, so do at the end (we're still in ctor) CompositionTarget.Rendering += UpdateResults;
searchModeComboBox.SelectedIndex = (int)SettingsService.Instance.SessionSettings.SelectedSearchMode;
} }
void MainWindow_Instance_CurrentAssemblyListChanged(object sender, NotifyCollectionChangedEventArgs e) void CurrentAssemblyList_Changed()
{ {
if (IsVisible) if (IsVisible)
{ {
@ -103,7 +85,12 @@ namespace ICSharpCode.ILSpy.Search
} }
} }
internal void UpdateFilter() void LanguageSettings_PropertyChanged()
{
UpdateFilter();
}
void UpdateFilter()
{ {
if (IsVisible) if (IsVisible)
{ {
@ -116,43 +103,48 @@ namespace ICSharpCode.ILSpy.Search
} }
} }
public void Show() protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
if (!IsVisible)
{ {
DockWorkspace.Instance.ToolPanes.Single(p => p.ContentId == SearchPaneModel.PaneContentId).IsVisible = true; base.OnPropertyChanged(e);
if (runSearchOnNextShow)
if (e.Property == IsVisibleProperty)
{ {
if (e.NewValue as bool? != true)
return;
if (!runSearchOnNextShow)
return;
runSearchOnNextShow = false; runSearchOnNextShow = false;
StartSearch(this.SearchTerm); StartSearch(this.SearchTerm);
} }
else if (e.Property == Pane.IsActiveProperty)
{
if (e.NewValue as bool? != true)
return;
if (IsMouseOver && Mouse.LeftButton == MouseButtonState.Pressed && !SearchTerm.IsNullOrEmpty())
return;
FocusSearchBox();
} }
Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(
delegate {
searchBox.Focus();
searchBox.SelectAll();
}));
} }
public static readonly DependencyProperty SearchTermProperty = void FocusSearchBox()
DependencyProperty.Register("SearchTerm", typeof(string), typeof(SearchPane), {
new FrameworkPropertyMetadata(string.Empty, OnSearchTermChanged)); this.BeginInvoke(DispatcherPriority.Background, () => {
searchBox.Focus();
public string SearchTerm { searchBox.SelectAll();
get { return (string)GetValue(SearchTermProperty); } });
set { SetValue(SearchTermProperty, value); }
} }
static void OnSearchTermChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
{ {
((SearchPane)o).StartSearch((string)e.NewValue); StartSearch(searchBox.Text);
} }
void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) void SearchModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
SettingsService.Instance.SessionSettings.SelectedSearchMode = (SearchMode)searchModeComboBox.SelectedIndex;
StartSearch(this.SearchTerm); StartSearch(this.SearchTerm);
} }
@ -180,32 +172,36 @@ namespace ICSharpCode.ILSpy.Search
protected override void OnKeyDown(KeyEventArgs e) protected override void OnKeyDown(KeyEventArgs e)
{ {
base.OnKeyDown(e); base.OnKeyDown(e);
if (e.Key == Key.T && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
if (e.KeyboardDevice.Modifiers != ModifierKeys.Control)
return;
switch (e.Key)
{ {
searchModeComboBox.SelectedIndex = (int)SearchMode.Type; case Key.T:
searchModeComboBox.SelectedValue = SearchMode.Type;
e.Handled = true; e.Handled = true;
} break;
else if (e.Key == Key.M && e.KeyboardDevice.Modifiers == ModifierKeys.Control) case Key.M:
{ searchModeComboBox.SelectedValue = SearchMode.Member;
searchModeComboBox.SelectedIndex = (int)SearchMode.Member;
e.Handled = true; e.Handled = true;
} break;
else if (e.Key == Key.S && e.KeyboardDevice.Modifiers == ModifierKeys.Control) case Key.S:
{ searchModeComboBox.SelectedValue = SearchMode.Literal;
searchModeComboBox.SelectedIndex = (int)SearchMode.Literal;
e.Handled = true; e.Handled = true;
break;
} }
} }
void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e) void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e)
{ {
if (e.Key == Key.Down && listBox.HasItems) if (e.Key != Key.Down || !listBox.HasItems)
{ return;
e.Handled = true; e.Handled = true;
listBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); listBox.MoveFocus(new(FocusNavigationDirection.First));
listBox.SelectedIndex = 0; listBox.SelectedIndex = 0;
} }
}
void UpdateResults(object sender, EventArgs e) void UpdateResults(object sender, EventArgs e)
{ {
@ -220,9 +216,10 @@ namespace ICSharpCode.ILSpy.Search
++resultsAdded; ++resultsAdded;
} }
if (resultsAdded > 0 && Results.Count == MAX_RESULTS) if (resultsAdded <= 0 || Results.Count != MAX_RESULTS)
{ return;
Results.Add(new SearchResult {
Results.Add(new() {
Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound, Name = Properties.Resources.SearchAbortedMoreThan1000ResultsFound,
Location = null!, Location = null!,
Assembly = null!, Assembly = null!,
@ -230,9 +227,9 @@ namespace ICSharpCode.ILSpy.Search
LocationImage = null!, LocationImage = null!,
AssemblyImage = null!, AssemblyImage = null!,
}); });
currentSearch.Cancel(); currentSearch.Cancel();
} }
}
async void StartSearch(string searchTerm) async void StartSearch(string searchTerm)
{ {
@ -253,7 +250,7 @@ namespace ICSharpCode.ILSpy.Search
{ {
searchProgressBar.IsIndeterminate = true; searchProgressBar.IsIndeterminate = true;
startedSearch = new RunningSearch(await mainWindow.CurrentAssemblyList.GetAllAssemblies(), searchTerm, startedSearch = new(await mainWindow.CurrentAssemblyList.GetAllAssemblies(), searchTerm,
(SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage, (SearchMode)searchModeComboBox.SelectedIndex, mainWindow.CurrentLanguage,
SettingsService.Instance.SessionSettings.LanguageSettings.ShowApiLevel); SettingsService.Instance.SessionSettings.LanguageSettings.ShowApiLevel);
currentSearch = startedSearch; currentSearch = startedSearch;
@ -262,7 +259,8 @@ namespace ICSharpCode.ILSpy.Search
} }
if (currentSearch == startedSearch) if (currentSearch == startedSearch)
{ //are we still running the same search {
//are we still running the same search
searchProgressBar.IsIndeterminate = false; searchProgressBar.IsIndeterminate = false;
} }
} }
@ -277,7 +275,7 @@ namespace ICSharpCode.ILSpy.Search
sealed class RunningSearch sealed class RunningSearch
{ {
readonly CancellationTokenSource cts = new CancellationTokenSource(); readonly CancellationTokenSource cts = new();
readonly IList<LoadedAssembly> assemblies; readonly IList<LoadedAssembly> assemblies;
readonly SearchRequest searchRequest; readonly SearchRequest searchRequest;
readonly SearchMode searchMode; readonly SearchMode searchMode;
@ -299,8 +297,8 @@ namespace ICSharpCode.ILSpy.Search
{ {
string[] parts = CommandLineTools.CommandLineToArgumentArray(input); string[] parts = CommandLineTools.CommandLineToArgumentArray(input);
SearchRequest request = new SearchRequest(); SearchRequest request = new();
List<string> keywords = new List<string>(); List<string> keywords = new();
Regex regex = null; Regex regex = null;
request.Mode = searchMode; request.Mode = searchMode;
@ -350,7 +348,6 @@ namespace ICSharpCode.ILSpy.Search
// then we do not interpret it as prefix, but as searchTerm. // then we do not interpret it as prefix, but as searchTerm.
searchTerm = part; searchTerm = part;
prefix = null; prefix = null;
prefixLength = -1;
} }
if (prefix == null || prefix.Length <= 2) if (prefix == null || prefix.Length <= 2)
@ -442,7 +439,7 @@ namespace ICSharpCode.ILSpy.Search
{ {
try try
{ {
return new Regex(s, RegexOptions.Compiled); return new(s, RegexOptions.Compiled);
} }
catch (ArgumentException) catch (ArgumentException)
{ {
@ -540,9 +537,11 @@ namespace ICSharpCode.ILSpy.Search
public ShowSearchCommand() public ShowSearchCommand()
: base(NavigationCommands.Search) : base(NavigationCommands.Search)
{ {
NavigationCommands.Search.InputGestures.Clear(); var gestures = NavigationCommands.Search.InputGestures;
NavigationCommands.Search.InputGestures.Add(new KeyGesture(Key.F, ModifierKeys.Control | ModifierKeys.Shift));
NavigationCommands.Search.InputGestures.Add(new KeyGesture(Key.E, ModifierKeys.Control)); gestures.Clear();
gestures.Add(new KeyGesture(Key.F, ModifierKeys.Control | ModifierKeys.Shift));
gestures.Add(new KeyGesture(Key.E, ModifierKeys.Control));
} }
} }
} }

41
ILSpy/ViewModels/SearchPaneModel.cs → ILSpy/Search/SearchPaneModel.cs

@ -17,15 +17,28 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition; using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
namespace ICSharpCode.ILSpy.ViewModels using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX.Search;
namespace ICSharpCode.ILSpy.Search
{
public class SearchModeModel
{ {
public SearchMode Mode { get; init; }
public string Name { get; init; }
public ImageSource Image { get; init; }
}
[ExportToolPane] [ExportToolPane]
[PartCreationPolicy(CreationPolicy.Shared)] [PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public class SearchPaneModel : ToolPaneModel public class SearchPaneModel : ToolPaneModel
{ {
private string searchTerm;
public const string PaneContentId = "searchPane"; public const string PaneContentId = "searchPane";
public SearchPaneModel() public SearchPaneModel()
@ -37,10 +50,26 @@ namespace ICSharpCode.ILSpy.ViewModels
IsCloseable = true; IsCloseable = true;
} }
public override void Show() public SearchModeModel[] SearchModes { get; } = [
{ new() { Mode = SearchMode.TypeAndMember, Image = Images.Library, Name = "Types and Members" },
base.Show(); new() { Mode = SearchMode.Type, Image = Images.Class, Name = "Type" },
MainWindow.Instance.SearchPane.Show(); new() { Mode = SearchMode.Member, Image = Images.Property, Name = "Member" },
new() { Mode = SearchMode.Method, Image = Images.Method, Name = "Method" },
new() { Mode = SearchMode.Field, Image = Images.Field, Name = "Field" },
new() { Mode = SearchMode.Property, Image = Images.Property, Name = "Property" },
new() { Mode = SearchMode.Event, Image = Images.Event, Name = "Event" },
new() { Mode = SearchMode.Literal, Image = Images.Literal, Name = "Constant" },
new() { Mode = SearchMode.Token, Image = Images.Library, Name = "Metadata Token" },
new() { Mode = SearchMode.Resource, Image = Images.Resource, Name = "Resource" },
new() { Mode = SearchMode.Assembly, Image = Images.Assembly, Name = "Assembly" },
new() { Mode = SearchMode.Namespace, Image = Images.Namespace, Name = "Namespace" }
];
public SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
public string SearchTerm {
get => searchTerm;
set => SetProperty(ref searchTerm, value);
} }
} }
} }

4
ILSpy/TextView/DecompilerTextView.cs

@ -181,11 +181,11 @@ namespace ICSharpCode.ILSpy.TextView
void CurrentDisplaySettings_PropertyChanged(object? sender, PropertyChangedEventArgs e) void CurrentDisplaySettings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(DisplaySettingsViewModel.ShowLineNumbers)) if (e.PropertyName == nameof(DisplaySettings.ShowLineNumbers))
{ {
ShowLineMargin(); ShowLineMargin();
} }
else if (e.PropertyName == nameof(DisplaySettingsViewModel.HighlightCurrentLine)) else if (e.PropertyName == nameof(DisplaySettings.HighlightCurrentLine))
{ {
SetHighlightCurrentLine(); SetHighlightCurrentLine();
} }

2
ILSpy/Themes/WindowStyleManagerBehavior.cs

@ -85,7 +85,7 @@ namespace ICSharpCode.ILSpy.Themes
private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e) private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(DisplaySettingsViewModel.StyleWindowTitleBar)) if (e.PropertyName == nameof(DisplaySettings.StyleWindowTitleBar))
{ {
if (!SettingsService.Instance.DisplaySettings.StyleWindowTitleBar) if (!SettingsService.Instance.DisplaySettings.StyleWindowTitleBar)
{ {

2
ILSpy/Util/SettingsService.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.Util
public DecompilerSettings DecompilerSettings { get; set; } public DecompilerSettings DecompilerSettings { get; set; }
public DisplaySettingsViewModel DisplaySettings { get; } public DisplaySettings DisplaySettings { get; }
public AssemblyListManager AssemblyListManager { get; } public AssemblyListManager AssemblyListManager { get; }
} }

97
ILSpy/ViewModels/PaneModel.cs

@ -18,8 +18,11 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.ILSpy.Docking;
using TomsToolbox.Wpf; using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.ViewModels namespace ICSharpCode.ILSpy.ViewModels
@ -57,93 +60,81 @@ namespace ICSharpCode.ILSpy.ViewModels
} }
} }
public PaneModel() private bool isSelected;
{
this.closeCommand = new CloseCommandImpl(this);
}
private bool isSelected = false;
public bool IsSelected { public bool IsSelected {
get => isSelected; get => isSelected;
set { set => SetProperty(ref isSelected, value);
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
} }
private bool isActive = false; private bool isActive;
public bool IsActive { public bool IsActive {
get => isActive; get => isActive;
set { set => SetProperty(ref isActive, value);
if (isActive != value)
{
isActive = value;
OnPropertyChanged(nameof(IsActive));
}
}
} }
private bool isVisible; private bool isVisible;
public bool IsVisible { public bool IsVisible {
get { return isVisible; } get { return isVisible; }
set { set {
if (isVisible != value) if (SetProperty(ref isVisible, value) && !value)
{ {
isVisible = value; // When the pane is hidden, it should no longer be marked as active, else it won't raise an event when it is activated again.
OnPropertyChanged(nameof(IsVisible)); IsActive = false;
} }
} }
} }
private bool isCloseable = true; private bool isCloseable = true;
public bool IsCloseable { public bool IsCloseable {
get { return isCloseable; } get => isCloseable;
set { set => SetProperty(ref isCloseable, value);
if (isCloseable != value)
{
isCloseable = value;
OnPropertyChanged(nameof(IsCloseable));
}
}
} }
private ICommand closeCommand; public ICommand CloseCommand => new CloseCommandImpl(this);
public ICommand CloseCommand {
get { return closeCommand; }
set {
if (closeCommand != value)
{
closeCommand = value;
OnPropertyChanged(nameof(CloseCommand));
}
}
}
private string contentId; private string contentId;
public string ContentId { public string ContentId {
get => contentId; get => contentId;
set { set => SetProperty(ref contentId, value);
if (contentId != value)
{
contentId = value;
OnPropertyChanged(nameof(ContentId));
}
}
} }
private string title; private string title;
public string Title { public string Title {
get => title; get => title;
set { set => SetProperty(ref title, value);
if (title != value) }
}
public static class Pane
{
// Helper properties to enable binding state properties from the model to the view.
public static readonly DependencyProperty IsActiveProperty = DependencyProperty.RegisterAttached(
"IsActive", typeof(bool), typeof(Pane), new FrameworkPropertyMetadata(default(bool)));
public static void SetIsActive(DependencyObject element, bool value)
{ {
title = value; element.SetValue(IsActiveProperty, value);
OnPropertyChanged(nameof(Title));
} }
public static bool GetIsActive(DependencyObject element)
{
return (bool)element.GetValue(IsActiveProperty);
} }
public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.RegisterAttached(
"IsVisible", typeof(bool), typeof(Pane), new FrameworkPropertyMetadata(default(bool)));
public static void SetIsVisible(DependencyObject element, bool value)
{
element.SetValue(IsVisibleProperty, value);
}
public static bool GetIsVisible(DependencyObject element)
{
return (bool)element.GetValue(IsVisibleProperty);
} }
} }
} }

Loading…
Cancel
Save