diff options
author | Karsten Heimrich <karsten.heimrich@qt.io> | 2022-03-11 15:41:34 +0100 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@qt.io> | 2022-04-05 11:18:57 +0000 |
commit | 724ed366ec292f875e17d8e0f1e994461e099c6d (patch) | |
tree | af0418d93750e93dddad4be31f50ddf3425416ef | |
parent | b11f42de79c296b4c56d971929c2b25a57f5a267 (diff) |
Rework help link chooser and translation page search
* Introduce new classes to use VS provided search facility
and update implementations using these new classes.
* Minor using statement cleanup
Change-Id: Idc299665c3712cd0b7a1b1b7e5e1bc270831b9df
Reviewed-by: Miguel Costa <miguel.costa@qt.io>
-rw-r--r-- | QtVsTools.Core/QtVsTools.Core.csproj | 2 | ||||
-rw-r--r-- | QtVsTools.Core/VisualStudio/VsSearch.cs | 146 | ||||
-rw-r--r-- | QtVsTools.Package/Package/QtHelp.cs | 6 | ||||
-rw-r--r-- | QtVsTools.Package/Package/QtHelpLinkChooser.xaml | 18 | ||||
-rw-r--r-- | QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs | 23 | ||||
-rw-r--r-- | QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml | 28 | ||||
-rw-r--r-- | QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs | 18 |
7 files changed, 191 insertions, 50 deletions
diff --git a/QtVsTools.Core/QtVsTools.Core.csproj b/QtVsTools.Core/QtVsTools.Core.csproj index fbc2cc9c..b6d7aa75 100644 --- a/QtVsTools.Core/QtVsTools.Core.csproj +++ b/QtVsTools.Core/QtVsTools.Core.csproj @@ -69,6 +69,7 @@ // --> <ItemGroup> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> + <Reference Include="PresentationFramework" /> <Reference Include="System" /> <Reference Include="System.Drawing" /> <Reference Include="System.Xml" /> @@ -182,6 +183,7 @@ <Compile Include="SR.cs" /> <Compile Include="VersionInformation.cs" /> <Compile Include="VisualStudio\IProjectTracker.cs" /> + <Compile Include="VisualStudio\VsSearch.cs" /> <Compile Include="VisualStudio\VsServiceProvider.cs" /> <Compile Include="WaitDialog.cs" /> <EmbeddedResource Include="ExportProjectDialog.resx"> diff --git a/QtVsTools.Core/VisualStudio/VsSearch.cs b/QtVsTools.Core/VisualStudio/VsSearch.cs new file mode 100644 index 00000000..5951b0b7 --- /dev/null +++ b/QtVsTools.Core/VisualStudio/VsSearch.cs @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt VS Tools. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Controls; +using System.Windows.Data; +using Microsoft.Internal.VisualStudio.PlatformUI; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace QtVsTools.VisualStudio +{ + public class SearchTask : VsSearchTask + { + private readonly Action _clearCallback = null; + private readonly Func<IEnumerable<string>, uint> _searchCallBack = null; + + public SearchTask(uint cookie, IVsSearchQuery query, IVsSearchCallback callback, + Action clearCallback, Func<IEnumerable<string>, uint> searchCallBack) + : base(cookie, query, callback) + { + _clearCallback = clearCallback; + _searchCallBack = searchCallBack; + } + + protected override void OnStartSearch() + { + ErrorCode = VSConstants.S_OK; + try { + _ = ThreadHelper.JoinableTaskFactory.RunAsync(async () => + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (TaskStatus != VSConstants.VsSearchTaskStatus.Stopped) { + SearchResults = _searchCallBack( + SearchUtilities.ExtractSearchTokens(SearchQuery).Select(token => + { + ThreadHelper.ThrowIfNotOnUIThread(); + return token.ParsedTokenText; + }) + ); + } else if (TaskStatus == VSConstants.VsSearchTaskStatus.Stopped) { + _clearCallback(); + } + }); + } catch { + ErrorCode = VSConstants.E_FAIL; + } + base.OnStartSearch(); + } + + protected override void OnStopSearch() + { + SearchResults = 0; + } + } + + public abstract class VsWindowSearch : IVsWindowSearch + { + public abstract IVsSearchTask CreateSearch(uint cookie, IVsSearchQuery query, + IVsSearchCallback callback); + + public virtual void ClearSearch() + {} + + public virtual void ProvideSearchSettings(IVsUIDataSource settings) + { + Utilities.SetValue(settings, SearchSettingsDataSource.PropertyNames.ControlMaxWidth, + (uint)10000); + Utilities.SetValue(settings, SearchSettingsDataSource.PropertyNames.SearchStartType, + (uint)VSSEARCHSTARTTYPE.SST_INSTANT); + } + + public virtual bool OnNavigationKeyDown(uint dwNavigationKey, uint dwModifiers) => false; + + public virtual bool SearchEnabled => true; + + public virtual Guid Category => Guid.Empty; + + public virtual IVsEnumWindowSearchFilters SearchFiltersEnum => null; + + public virtual IVsEnumWindowSearchOptions SearchOptionsEnum => null; + } + + public class ListBoxSearch : VsWindowSearch + { + private readonly ListBox _listBox = null; + private Action<string> _setSearchText = null; + + public ListBoxSearch(ListBox listBox, Action<string> action) + { + _listBox = listBox; + _setSearchText = action; + } + + public override IVsSearchTask CreateSearch(uint cookie, IVsSearchQuery query, + IVsSearchCallback callback) + { + return new SearchTask(cookie, query, callback, ClearSearch, + searchCallBack: (IEnumerable<string> tokens) => + { + _setSearchText(string.Join(" ", tokens)); + var view = CollectionViewSource.GetDefaultView(_listBox.ItemsSource); + + view.Refresh(); + if (_listBox.Items.Count == 1 || _listBox.SelectedItem == null) + _listBox.SelectedIndex = 0; + return (uint)view.Cast<object>().Count(); + }); + } + + public override void ClearSearch() + { + _setSearchText(string.Empty); + CollectionViewSource.GetDefaultView(_listBox.ItemsSource).Refresh(); + } + } +} diff --git a/QtVsTools.Package/Package/QtHelp.cs b/QtVsTools.Package/Package/QtHelp.cs index e3e86b30..84b121d1 100644 --- a/QtVsTools.Package/Package/QtHelp.cs +++ b/QtVsTools.Package/Package/QtHelp.cs @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt VS Tools. @@ -33,11 +33,9 @@ using System.Data.Common; using System.Data.SQLite; using System.IO; using System.Linq; +using EnvDTE; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; -using EnvDTE; - -using Task = System.Threading.Tasks.Task; namespace QtVsTools { diff --git a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml index d9d6a1d6..0494ddef 100644 --- a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml +++ b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml @@ -46,15 +46,13 @@ ResizeMode="CanResizeWithGrip" WindowStartupLocation="CenterOwner"> <vsui:DialogWindow.Resources> - <BooleanToVisibilityConverter x:Key="b2v" /> <Style x:Key="ListBoxDoubleClickStyle" TargetType="ListBoxItem"> <EventSetter Event="MouseDoubleClick" Handler="OnListBoxItem_DoubleClick" /> </Style> </vsui:DialogWindow.Resources> - <Grid Margin="10" - FocusManager.FocusedElement="{Binding ElementName=searchBox}"> + <Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> @@ -68,18 +66,8 @@ Text="{Binding Path=Keyword}" /> <Run Text=":" /> </TextBlock> - <Grid Grid.Row="1" - MinHeight="22" - Background="White"> - <TextBlock Text=" Filter..." - Foreground="LightSteelBlue" - VerticalAlignment="Center" - Visibility="{Binding ElementName=searchBox, - Path=Text.IsEmpty, Converter={StaticResource b2v}}" /> - <TextBox Name="searchBox" - Background="Transparent" - TextChanged="OnSearchBox_TextChanged" - VerticalContentAlignment="Center" /> + <Grid Grid.Row="1"> + <Grid Name="searchControlHost" /> </Grid> <ListBox Grid.Row="2" Margin="0,10,0,0" diff --git a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs index 32b46387..655954ad 100644 --- a/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs +++ b/QtVsTools.Package/Package/QtHelpLinkChooser.xaml.cs @@ -33,6 +33,9 @@ using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using Microsoft.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using QtVsTools.VisualStudio; namespace QtVsTools { @@ -47,28 +50,32 @@ namespace QtVsTools } public string Link { get; set; } + public string SearchText { get; set; } + public string Keyword { private get; set; } public Dictionary<string, string> Links { private get; set; } private void OnLoaded(object sender, RoutedEventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var view = CollectionViewSource.GetDefaultView(linkListBox.ItemsSource); view.Filter = obj => { - if (string.IsNullOrEmpty(searchBox.Text)) + if (string.IsNullOrEmpty(SearchText)) return true; var item = (KeyValuePair<string, string>)obj; - return item.Key.IndexOf(searchBox.Text, StringComparison.OrdinalIgnoreCase) >= 0; + return item.Key.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; }; linkListBox.SelectedIndex = 0; - } - private void OnSearchBox_TextChanged(object sender, TextChangedEventArgs e) - { - CollectionViewSource.GetDefaultView(linkListBox.ItemsSource).Refresh(); - if (linkListBox.Items.Count == 1 || linkListBox.SelectedItem == null) - linkListBox.SelectedIndex = 0; + var factory = VsServiceProvider + .GetService<SVsWindowSearchHostFactory, IVsWindowSearchHostFactory>(); + var host = factory.CreateWindowSearchHost(searchControlHost); + + host.SetupSearch(new ListBoxSearch(linkListBox, value => SearchText = value)); + host.Activate(); // set focus } private void OnListBoxItem_DoubleClick(object sender, MouseButtonEventArgs e) diff --git a/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml index b87402d9..f025643c 100644 --- a/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml +++ b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml @@ -30,7 +30,6 @@ <common:WizardPage x:Class="QtVsTools.Wizards.ItemWizard.TranslationPage" xmlns:common="clr-namespace:QtVsTools.Wizards.Common" - xmlns:util="clr-namespace:QtVsTools.Wizards.Util" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" @@ -38,12 +37,8 @@ KeepAlive="True" mc:Ignorable="d" d:DesignHeight="445" - d:DesignWidth="585" - FocusManager.FocusedElement="{Binding ElementName=LanguageListBox}"> - <common:WizardPage.Resources> - <BooleanToVisibilityConverter x:Key="b2v" /> - </common:WizardPage.Resources> - <Grid> + d:DesignWidth="585" > + <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="*" /> @@ -92,19 +87,8 @@ <TextBlock Grid.Row="0" Margin="0,0,0,5" Text="Select a Language:" /> - <Grid Grid.Row="1" - MinHeight="22" - Background="White"> - <TextBlock Text=" Filter..." - Foreground="LightSteelBlue" - VerticalAlignment="Center" - Visibility="{Binding ElementName=searchBox, - Path=Text.IsEmpty, - Converter={StaticResource b2v}}" /> - <TextBox Name="searchBox" - Background="Transparent" - TextChanged="OnSearchBoxTextChanged" - VerticalContentAlignment="Center" /> + <Grid Grid.Row="1"> + <Grid Name="searchControlHost" /> </Grid> <ListBox Grid.Row="2" Margin="0,10,0,8" @@ -115,6 +99,7 @@ SelectedValue="{Binding Path=Data.CultureInfoName}" SelectionChanged="OnLanguageBoxSelectionChanged" /> <TextBlock Grid.Row="3" + Margin="0,0,0,5" Text="Save as:"/> <Grid Grid.Row="4"> <Grid.ColumnDefinitions> @@ -123,7 +108,8 @@ </Grid.ColumnDefinitions> <TextBox Text="{Binding Path=Data.TsFile}"/> <TextBlock Grid.Column="1" - Margin="5,0,0,0"> + Margin="5,0,0,0" + VerticalAlignment="Center"> <Run FontWeight="Bold" Text="{Binding Path=Data.CultureInfoName}" /> <Run Text=".ts" /> diff --git a/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs index 59dbb5b7..7a25c517 100644 --- a/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs +++ b/QtVsTools.Wizards/ItemWizard/Translation/TranslationPage.xaml.cs @@ -31,13 +31,18 @@ using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; namespace QtVsTools.Wizards.ItemWizard { + using QtVsTools.VisualStudio; using Wizards.Common; public partial class TranslationPage : WizardPage { + private string SearchText { get; set; } + public TranslationPage() { InitializeComponent(); @@ -47,16 +52,25 @@ namespace QtVsTools.Wizards.ItemWizard private void OnTranslationPageLoaded(object sender, RoutedEventArgs e) { + ThreadHelper.ThrowIfNotOnUIThread(); + var view = CollectionViewSource.GetDefaultView(LanguageListBox.ItemsSource); view.Filter = obj => { - if (string.IsNullOrEmpty(searchBox.Text)) + if (string.IsNullOrEmpty(SearchText)) return true; var item = (KeyValuePair<string, string>)obj; - return item.Value.IndexOf(searchBox.Text, StringComparison.OrdinalIgnoreCase) >= 0; + return item.Value.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0; }; LanguageListBox.SelectedIndex = 0; + + var factory = VsServiceProvider + .GetService<SVsWindowSearchHostFactory, IVsWindowSearchHostFactory>(); + var host = factory.CreateWindowSearchHost(searchControlHost); + + host.SetupSearch(new ListBoxSearch(LanguageListBox, value => SearchText = value)); + host.Activate(); // set focus } private void OnSearchBoxTextChanged(object sender, TextChangedEventArgs e) |