diff --git a/ILSpy/Assets/Icons/Literal.svg b/ILSpy/Assets/Icons/Literal.svg new file mode 100644 index 000000000..45c0171e7 --- /dev/null +++ b/ILSpy/Assets/Icons/Literal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ILSpy/Images.cs b/ILSpy/Images.cs index 4a5d7439d..d9969966f 100644 --- a/ILSpy/Images.cs +++ b/ILSpy/Images.cs @@ -107,6 +107,7 @@ namespace ILSpy.Images public static readonly IImage Field = LoadSvg(nameof(Field)); public static readonly IImage Property = LoadSvg(nameof(Property)); public static readonly IImage Event = LoadSvg(nameof(Event)); + public static readonly IImage Literal = LoadSvg(nameof(Literal)); // Reference overlays (small badge layered onto a base icon for TypeRef/MemberRef nodes). internal static readonly IImage ReferenceOverlay = LoadSvg(nameof(ReferenceOverlay)); diff --git a/ILSpy/Search/SearchPane.axaml b/ILSpy/Search/SearchPane.axaml index 08af2edeb..2ebb4bca9 100644 --- a/ILSpy/Search/SearchPane.axaml +++ b/ILSpy/Search/SearchPane.axaml @@ -9,15 +9,39 @@ + PlaceholderText="Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/..." + ToolTip.Tip="Search" + Text="{Binding SearchTerm, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"> + + + + + + MinWidth="180"> - + + + + + diff --git a/ILSpy/Search/SearchPane.axaml.cs b/ILSpy/Search/SearchPane.axaml.cs index 08e48bcb2..6b2dbba83 100644 --- a/ILSpy/Search/SearchPane.axaml.cs +++ b/ILSpy/Search/SearchPane.axaml.cs @@ -20,6 +20,7 @@ using System; using Avalonia.Controls; using Avalonia.Input; +using Avalonia.Interactivity; using Avalonia.Threading; using ICSharpCode.ILSpyX.Search; @@ -37,6 +38,17 @@ namespace ILSpy.Search SearchResults.KeyDown += OnResultKeyDown; } + void OnClearSearchClicked(object? sender, RoutedEventArgs e) + { + // Empty the query and return focus to the input so the user can start typing + // straight away. Setting SearchTerm = "" triggers the same cancel-and-restart + // path as deleting the text by hand. + if (DataContext is SearchPaneModel vm) + vm.SearchTerm = string.Empty; + SearchInput.Focus(); + e.Handled = true; + } + protected override void OnDataContextChanged(EventArgs e) { base.OnDataContextChanged(e); diff --git a/ILSpy/Search/SearchPaneModel.cs b/ILSpy/Search/SearchPaneModel.cs index 82d16c624..8eed545f5 100644 --- a/ILSpy/Search/SearchPaneModel.cs +++ b/ILSpy/Search/SearchPaneModel.cs @@ -20,6 +20,8 @@ using System; using System.Collections.ObjectModel; using System.Composition; +using Avalonia.Media; + using CommunityToolkit.Mvvm.ComponentModel; using ICSharpCode.ILSpyX; @@ -36,12 +38,14 @@ namespace ILSpy.Search /// /// One entry in the search-mode picker. The determines which /// ICSharpCode.ILSpyX.Search strategy runs when the user types a query; - /// is the label rendered in the ComboBox. + /// is the label rendered in the ComboBox and + /// is the icon shown alongside it (both in the dropdown and in the closed selector). /// public sealed class SearchModeEntry { public required SearchMode Mode { get; init; } public required string Name { get; init; } + public required IImage Image { get; init; } } [Export] @@ -71,18 +75,18 @@ namespace ILSpy.Search /// strings so users moving between builds see the same labels. /// public SearchModeEntry[] SearchModes { get; } = new[] { - new SearchModeEntry { Mode = SearchMode.TypeAndMember, Name = "Types and Members" }, - new SearchModeEntry { Mode = SearchMode.Type, Name = "Type" }, - new SearchModeEntry { Mode = SearchMode.Member, Name = "Member" }, - new SearchModeEntry { Mode = SearchMode.Method, Name = "Method" }, - new SearchModeEntry { Mode = SearchMode.Field, Name = "Field" }, - new SearchModeEntry { Mode = SearchMode.Property, Name = "Property" }, - new SearchModeEntry { Mode = SearchMode.Event, Name = "Event" }, - new SearchModeEntry { Mode = SearchMode.Literal, Name = "Constant" }, - new SearchModeEntry { Mode = SearchMode.Token, Name = "Metadata Token" }, - new SearchModeEntry { Mode = SearchMode.Resource, Name = "Resource" }, - new SearchModeEntry { Mode = SearchMode.Assembly, Name = "Assembly" }, - new SearchModeEntry { Mode = SearchMode.Namespace, Name = "Namespace" }, + new SearchModeEntry { Mode = SearchMode.TypeAndMember, Name = "Types and Members", Image = Images.Images.Library }, + new SearchModeEntry { Mode = SearchMode.Type, Name = "Type", Image = Images.Images.Class }, + new SearchModeEntry { Mode = SearchMode.Member, Name = "Member", Image = Images.Images.Property }, + new SearchModeEntry { Mode = SearchMode.Method, Name = "Method", Image = Images.Images.Method }, + new SearchModeEntry { Mode = SearchMode.Field, Name = "Field", Image = Images.Images.Field }, + new SearchModeEntry { Mode = SearchMode.Property, Name = "Property", Image = Images.Images.Property }, + new SearchModeEntry { Mode = SearchMode.Event, Name = "Event", Image = Images.Images.Event }, + new SearchModeEntry { Mode = SearchMode.Literal, Name = "Constant", Image = Images.Images.Literal }, + new SearchModeEntry { Mode = SearchMode.Token, Name = "Metadata Token", Image = Images.Images.Library }, + new SearchModeEntry { Mode = SearchMode.Resource, Name = "Resource", Image = Images.Images.Resource }, + new SearchModeEntry { Mode = SearchMode.Assembly, Name = "Assembly", Image = Images.Images.Assembly }, + new SearchModeEntry { Mode = SearchMode.Namespace, Name = "Namespace", Image = Images.Images.Namespace }, }; ///