mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 10:46:33 +02:00
Merge branch 'master' into users/niels9001/settings-incorrecttheminglabels
This commit is contained in:
@@ -70,24 +70,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
if (SettingsExists(powertoy, fileName))
|
||||
{
|
||||
// Given the file already exists, to deserialize the file and read it's content.
|
||||
T deserializedSettings = GetFile<T>(powertoy, fileName);
|
||||
|
||||
// IF the file needs to be modified, to save the new configurations accordingly.
|
||||
if (deserializedSettings.UpgradeSettingsConfiguration())
|
||||
try
|
||||
{
|
||||
SaveSettings(deserializedSettings.ToJsonString(), powertoy, fileName);
|
||||
// Given the file already exists, to deserialize the file and read it's content.
|
||||
T deserializedSettings = GetFile<T>(powertoy, fileName);
|
||||
|
||||
// If the file needs to be modified, to save the new configurations accordingly.
|
||||
if (deserializedSettings.UpgradeSettingsConfiguration())
|
||||
{
|
||||
SaveSettings(deserializedSettings.ToJsonString(), powertoy, fileName);
|
||||
}
|
||||
|
||||
return deserializedSettings;
|
||||
}
|
||||
|
||||
return deserializedSettings;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the settings file does not exist, to create a new object with default parameters and save it to a newly created settings file.
|
||||
T newSettingsItem = new T();
|
||||
SaveSettings(newSettingsItem.ToJsonString(), powertoy, fileName);
|
||||
return newSettingsItem;
|
||||
// Catch json deserialization exceptions when the file is corrupt and has an invalid json.
|
||||
// If there are any deserialization issues like in https://github.com/microsoft/PowerToys/issues/7500, log the error and create a new settings.json file.
|
||||
// This is different from the case where we have trailing zeros following a valid json file, which we have handled by trimming the trailing zeros.
|
||||
catch (JsonException ex)
|
||||
{
|
||||
Logger.LogError($"Exception encountered while loading {powertoy} settings.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// If the settings file does not exist or if the file is corrupt, to create a new object with default parameters and save it to a newly created settings file.
|
||||
T newSettingsItem = new T();
|
||||
SaveSettings(newSettingsItem.ToJsonString(), powertoy, fileName);
|
||||
return newSettingsItem;
|
||||
}
|
||||
|
||||
// Given the powerToy folder name and filename to be accessed, this function deserializes and returns the file.
|
||||
|
||||
@@ -32,6 +32,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
|
||||
Log(message, "INFO");
|
||||
}
|
||||
|
||||
public static void LogError(string message)
|
||||
{
|
||||
Log(message, "ERROR");
|
||||
#if DEBUG
|
||||
Debugger.Break();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void LogError(string message, Exception e)
|
||||
{
|
||||
Log(
|
||||
@@ -42,6 +50,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Utilities
|
||||
"Stack trace: " + Environment.NewLine +
|
||||
e?.StackTrace,
|
||||
"ERROR");
|
||||
#if DEBUG
|
||||
Debugger.Break();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void Log(string message, string type)
|
||||
|
||||
@@ -86,6 +86,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
private bool _keepDateModified;
|
||||
private int _encoderGuidId;
|
||||
|
||||
public bool IsListViewFocusRequested { get; set; }
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
@@ -257,6 +259,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
imageSizes.Add(newSize);
|
||||
_advancedSizes = imageSizes;
|
||||
SavesImageSizes(imageSizes);
|
||||
|
||||
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
|
||||
IsListViewFocusRequested = true;
|
||||
}
|
||||
|
||||
public void DeleteImageSize(int id)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerLauncher.Telemetry;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.Toolkit.Wpf.UI.XamlHost;
|
||||
@@ -67,16 +68,17 @@ namespace Microsoft.PowerToys.Settings.UI.Runner
|
||||
{
|
||||
if (ShellPage.ShellHandler.IPCResponseHandleList != null)
|
||||
{
|
||||
try
|
||||
var success = JsonObject.TryParse(msg, out JsonObject json);
|
||||
if (success)
|
||||
{
|
||||
JsonObject json = JsonObject.Parse(msg);
|
||||
foreach (Action<JsonObject> handle in ShellPage.ShellHandler.IPCResponseHandleList)
|
||||
{
|
||||
handle(json);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
else
|
||||
{
|
||||
Logger.LogError("Failed to parse JSON from IPC message.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,6 +69,11 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VCRTForwarders.140" Version="1.0.6" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
|
||||
<Version>3.3.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -13,7 +13,7 @@ using Windows.UI.Popups;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Runner
|
||||
{
|
||||
public class Program
|
||||
public static class Program
|
||||
{
|
||||
// Quantity of arguments
|
||||
private const int ArgumentsQty = 5;
|
||||
@@ -37,9 +37,9 @@ namespace Microsoft.PowerToys.Settings.UI.Runner
|
||||
App app = new App();
|
||||
app.InitializeComponent();
|
||||
|
||||
if (args.Length >= ArgumentsQty)
|
||||
if (args != null && args.Length >= ArgumentsQty)
|
||||
{
|
||||
int.TryParse(args[2], out int powerToysPID);
|
||||
_ = int.TryParse(args[2], out int powerToysPID);
|
||||
PowerToysPID = powerToysPID;
|
||||
|
||||
if (args[4] == "true")
|
||||
|
||||
@@ -6,36 +6,25 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
AutomationProperties.Name="{x:Bind Header, Mode=OneTime}"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBox x:Name="HotkeyTextBox"
|
||||
x:Uid="SettingsPage_SetShortcut"
|
||||
AutomationProperties.HelpText="{Binding ElementName=ShortcutWarningLabelText, Path=Text}"
|
||||
IsReadOnly="True">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Uid="ShortcutWarningLabel"/>
|
||||
<TextBlock Text="{x:Bind Keys, Mode=OneTime}" FontWeight="SemiBold"/>
|
||||
</StackPanel>
|
||||
</ToolTip>
|
||||
<TextBlock x:Name="ShortcutWarningLabelText">
|
||||
<Run x:Uid="ShortcutWarningLabel"/>
|
||||
<LineBreak/>
|
||||
<Run Text="{x:Bind Keys, Mode=OneTime}" FontWeight="SemiBold"/>
|
||||
</TextBlock>
|
||||
</ToolTipService.ToolTip>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Name="TitleText"
|
||||
Text="{x:Bind Header, Mode=OneTime}"
|
||||
Foreground="{Binding Path=IsEnabled, ElementName=HotkeyTextBox, Converter={StaticResource ModuleEnabledToForegroundConverter}}"
|
||||
/>
|
||||
|
||||
<TextBlock x:Uid="SettingsPage_SetShortcut_Glyph"
|
||||
x:Name="TitleGlyph" Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Margin="4,4,0,0"
|
||||
Foreground="{Binding Path=IsEnabled, ElementName=HotkeyTextBox, Converter={StaticResource ModuleEnabledToForegroundConverter}}"
|
||||
/>
|
||||
|
||||
</StackPanel>
|
||||
<TextBox x:Uid="SettingsPage_SetShortcut"
|
||||
x:Name="HotkeyTextBox"
|
||||
Margin="0,5,0,0"
|
||||
IsReadOnly="True"
|
||||
/>
|
||||
</StackPanel>
|
||||
<TextBox.Header>
|
||||
<TextBlock>
|
||||
<Run Text="{x:Bind Header, Mode=OneTime}"/>
|
||||
<Run Text="" FontFamily="Segoe MDL2 Assets"/>
|
||||
</TextBlock>
|
||||
</TextBox.Header>
|
||||
</TextBox>
|
||||
</UserControl>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -62,10 +62,10 @@
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=FancyZones_LaunchEditorButtonControl}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Viewbox Height="12" Width="12">
|
||||
<PathIcon Data="M896 0v896H0V0h896zM768 768V128H128v640h640zM0 1920v-896h1920v896H0zm128-768v640h1664v-640H128zM1024 0h896v896h-896V0zm768 768V128h-640v640h640z"/>
|
||||
<Viewbox Height="14" Width="14" Margin="-1,1,0,0">
|
||||
<PathIcon Data="M45,48H25.5V45H45V25.5H25.5v-3H45V3H25.5V0H48V48ZM22.5,48H3V45H22.5V3H3V0H25.5V48ZM0,48V0H3V48Z"/>
|
||||
</Viewbox>
|
||||
<TextBlock Margin="12,0,0,0"
|
||||
<TextBlock Margin="8,0,0,0"
|
||||
Name="FancyZones_LaunchEditorButtonControl"
|
||||
x:Uid="FancyZones_LaunchEditorButtonControl"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
SelectionMode="None"
|
||||
ScrollViewer.HorizontalScrollMode="Enabled"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Auto"
|
||||
ScrollViewer.IsHorizontalRailEnabled="True">
|
||||
ScrollViewer.IsHorizontalRailEnabled="True"
|
||||
ContainerContentChanging="ImagesSizesListView_ContainerContentChanging">
|
||||
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
@@ -277,7 +278,9 @@
|
||||
x:Uid="ImageResizer_FilenameFormatPlaceholder"
|
||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=ImageResizer_FilenameFormatHeader}">
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=ImageResizer_FilenameFormatHeader}"
|
||||
AutomationProperties.HelpText="{Binding ElementName=FileFormatTextBlock, Path=Text}"
|
||||
>
|
||||
<TextBox.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Name="ImageResizer_FilenameFormatHeader"
|
||||
@@ -290,44 +293,34 @@
|
||||
</StackPanel>
|
||||
</TextBox.Header>
|
||||
<ToolTipService.ToolTip>
|
||||
<StackPanel>
|
||||
<TextBlock x:Uid="ImageResizer_FileFormatDescription"/>
|
||||
<TextBlock Margin="{StaticResource SmallTopMargin}">
|
||||
<Run Text="%1" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Filename" />
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%2" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Sizename"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%3" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedWidth"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%4" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedHeight"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%5" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualWidth"/>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock>
|
||||
<Run Text="%6" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualHeight"/>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<TextBlock x:Name="FileFormatTextBlock">
|
||||
<Run x:Uid="ImageResizer_FileFormatDescription"/>
|
||||
<LineBreak/>
|
||||
<LineBreak/>
|
||||
<Run Text="%1" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Filename" />
|
||||
<LineBreak/>
|
||||
<Run Text="%2" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_Sizename"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%3" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedWidth"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%4" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_SelectedHeight"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%5" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualWidth"/>
|
||||
<LineBreak/>
|
||||
<Run Text="%6" FontWeight="Bold" />
|
||||
<Run Text=" - "/>
|
||||
<Run x:Uid="ImageResizer_Formatting_ActualHeight"/>
|
||||
</TextBlock>
|
||||
</ToolTipService.ToolTip>
|
||||
</TextBox>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
|
||||
@@ -45,5 +46,18 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void ImagesSizesListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
|
||||
{
|
||||
if (ViewModel.IsListViewFocusRequested)
|
||||
{
|
||||
// Set focus to the last item in the ListView
|
||||
int size = ImagesSizesListView.Items.Count;
|
||||
((ListViewItem)ImagesSizesListView.ContainerFromIndex(size - 1)).Focus(FocusState.Programmatic);
|
||||
|
||||
// Reset the focus requested flag
|
||||
ViewModel.IsListViewFocusRequested = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,10 +41,9 @@
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_FancyZones" helpers:NavHelper.NavigateTo="views:FancyZonesPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<PathIcon Data="M896 0v896H0V0h896zM768 768V128H128v640h640zM0 1920v-896h1920v896H0zm128-768v640h1664v-640H128zM1024 0h896v896h-896V0zm768 768V128h-640v640h640z"></PathIcon>
|
||||
<PathIcon Data="M45,48H25.5V45H45V25.5H25.5v-3H45V3H25.5V0H48V48ZM22.5,48H3V45H22.5V3H3V0H25.5V48ZM0,48V0H3V48Z"/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
@@ -54,35 +53,30 @@
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_ImageResizer" helpers:NavHelper.NavigateTo="views:ImageResizerPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<PathIcon Data="M0 768h1408v1152H0V768zm128 1024h870l-582-581-288 288v293zm1152 0v-102l-224-223-101 101 223 224h102zM128 896v421l288-287 448 447 192-191 224 224V896H128zm832 256q-26 0-45-19t-19-45q0-26 19-45t45-19q26 0 45 19t19 45q0 26-19 45t-45 19zm960-512V347l-339 338-90-90 338-339h-293V128h512v512h-128zm-768-512h256v128h-256V128zm-128 128H768V128h256v128zm-384 0H384V128h256v128zm-384 0H0V128h256v128zM128 640H0V384h128v256zm1920 128v256h-128V768h128zm-128 384h128v256h-128v-256zm0 384h128v256h-128v-256zm-384 256h256v128h-256v-128z"></PathIcon>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_KeyboardManager" helpers:NavHelper.NavigateTo="views:KeyboardManagerPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_PowerRename" helpers:NavHelper.NavigateTo="views:PowerRenamePage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_PowerLauncher" helpers:NavHelper.NavigateTo="views:PowerLauncherPage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
</winui:NavigationViewItem.Icon>
|
||||
</winui:NavigationViewItem>
|
||||
|
||||
<!-- TO DO: Update icon -->
|
||||
<winui:NavigationViewItem x:Uid="Shell_ShortcutGuide" helpers:NavHelper.NavigateTo="views:ShortcutGuidePage" AutomationProperties.HeadingLevel="Level1">
|
||||
<winui:NavigationViewItem.Icon>
|
||||
<FontIcon Glyph=""/>
|
||||
@@ -94,7 +88,6 @@
|
||||
DefaultHeader="{x:Bind ViewModel.Selected.Content, Mode=OneWay}">
|
||||
<behaviors:NavigationViewHeaderBehavior.DefaultHeaderTemplate>
|
||||
<DataTemplate>
|
||||
<!-- TODO: Style clean up-->
|
||||
<Grid Margin="0, -2, 0, 6">
|
||||
<TextBlock
|
||||
Text="{Binding}"
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace ColorPicker.Mouse
|
||||
private readonly IUserSettings _userSettings;
|
||||
private System.Windows.Point _previousMousePosition = new System.Windows.Point(-1, 1);
|
||||
private Color _previousColor = Color.Transparent;
|
||||
private bool _colorFormatChanged;
|
||||
|
||||
[ImportingConstructor]
|
||||
public MouseInfoProvider(AppStateHandler appStateMonitor, IUserSettings userSettings)
|
||||
@@ -40,6 +41,7 @@ namespace ColorPicker.Mouse
|
||||
|
||||
_mouseHook = new MouseHook();
|
||||
_userSettings = userSettings;
|
||||
_userSettings.CopiedColorRepresentation.PropertyChanged += CopiedColorRepresentation_PropertyChanged;
|
||||
}
|
||||
|
||||
public event EventHandler<Color> MouseColorChanged;
|
||||
@@ -73,9 +75,10 @@ namespace ColorPicker.Mouse
|
||||
}
|
||||
|
||||
var color = GetPixelColor(mousePosition);
|
||||
if (_previousColor != color)
|
||||
if (_previousColor != color || _colorFormatChanged)
|
||||
{
|
||||
_previousColor = color;
|
||||
_colorFormatChanged = false;
|
||||
MouseColorChanged?.Invoke(this, color);
|
||||
}
|
||||
}
|
||||
@@ -137,6 +140,11 @@ namespace ColorPicker.Mouse
|
||||
OnMouseDown?.Invoke(this, p);
|
||||
}
|
||||
|
||||
private void CopiedColorRepresentation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
_colorFormatChanged = true;
|
||||
}
|
||||
|
||||
private void DisposeHook()
|
||||
{
|
||||
if (_timer.IsEnabled)
|
||||
|
||||
@@ -404,15 +404,15 @@ namespace FancyZonesEditor
|
||||
_gridModel.ColumnPercents.Add(((_multiplier * (col + 1)) / cols) - ((_multiplier * col) / cols));
|
||||
}
|
||||
|
||||
int index = ZoneCount - 1;
|
||||
for (int col = cols - 1; col >= 0; col--)
|
||||
int index = 0;
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int row = rows - 1; row >= 0; row--)
|
||||
for (int col = 0; col < cols; col++)
|
||||
{
|
||||
_gridModel.CellChildMap[row, col] = index--;
|
||||
if (index < 0)
|
||||
_gridModel.CellChildMap[row, col] = index++;
|
||||
if (index == ZoneCount)
|
||||
{
|
||||
index = 0;
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ void FancyZones::ToggleEditor() noexcept
|
||||
winrt::com_ptr<IZoneWindow> zoneWindow;
|
||||
|
||||
std::shared_lock readLock(m_lock);
|
||||
|
||||
|
||||
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
||||
{
|
||||
zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, NULL);
|
||||
@@ -625,7 +625,7 @@ void FancyZones::ToggleEditor() noexcept
|
||||
{
|
||||
zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||
}
|
||||
|
||||
|
||||
if (!zoneWindow)
|
||||
{
|
||||
return;
|
||||
@@ -639,7 +639,8 @@ void FancyZones::ToggleEditor() noexcept
|
||||
|
||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
|
||||
allMonitors = FancyZonesUtils::GetAllMonitorRects<&MONITORINFOEX::rcWork>();
|
||||
} }).wait();
|
||||
} })
|
||||
.wait();
|
||||
|
||||
UINT currentDpi = 0;
|
||||
for (const auto& monitor : allMonitors)
|
||||
@@ -650,15 +651,15 @@ void FancyZones::ToggleEditor() noexcept
|
||||
{
|
||||
if (currentDpi == 0)
|
||||
{
|
||||
currentDpi = dpiX;
|
||||
continue;
|
||||
currentDpi = dpiX;
|
||||
continue;
|
||||
}
|
||||
if (currentDpi != dpiX)
|
||||
{
|
||||
MessageBoxW(NULL,
|
||||
GET_RESOURCE_STRING(IDS_SPAN_ACROSS_ZONES_WARNING).c_str(),
|
||||
GET_RESOURCE_STRING(IDS_POWERTOYS_FANCYZONES).c_str(),
|
||||
MB_OK | MB_ICONWARNING);
|
||||
GET_RESOURCE_STRING(IDS_SPAN_ACROSS_ZONES_WARNING).c_str(),
|
||||
GET_RESOURCE_STRING(IDS_POWERTOYS_FANCYZONES).c_str(),
|
||||
MB_OK | MB_ICONWARNING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -693,8 +694,9 @@ void FancyZones::ToggleEditor() noexcept
|
||||
mi.cbSize = sizeof(mi);
|
||||
|
||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
|
||||
GetMonitorInfo(monitor, &mi);
|
||||
} }).wait();
|
||||
GetMonitorInfo(monitor, &mi);
|
||||
} })
|
||||
.wait();
|
||||
|
||||
const auto x = mi.rcWork.left;
|
||||
const auto y = mi.rcWork.top;
|
||||
@@ -981,7 +983,7 @@ void FancyZones::UpdateZoneWindows() noexcept
|
||||
|
||||
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL {
|
||||
capture* params = reinterpret_cast<capture*>(data);
|
||||
MONITORINFOEX mi{ { .cbSize = sizeof(mi)} };
|
||||
MONITORINFOEX mi{ { .cbSize = sizeof(mi) } };
|
||||
if (GetMonitorInfoW(monitor, &mi))
|
||||
{
|
||||
auto& displayDeviceIdxMap = *(params->displayDeviceIdx);
|
||||
@@ -1006,8 +1008,8 @@ void FancyZones::UpdateZoneWindows() noexcept
|
||||
if (deviceId.empty())
|
||||
{
|
||||
deviceId = GetSystemMetrics(SM_REMOTESESSION) ?
|
||||
L"\\\\?\\DISPLAY#REMOTEDISPLAY#" :
|
||||
L"\\\\?\\DISPLAY#LOCALDISPLAY#";
|
||||
L"\\\\?\\DISPLAY#REMOTEDISPLAY#" :
|
||||
L"\\\\?\\DISPLAY#LOCALDISPLAY#";
|
||||
|
||||
fancyZones->AddZoneWindow(monitor, deviceId);
|
||||
}
|
||||
@@ -1180,22 +1182,24 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
||||
else
|
||||
{
|
||||
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
if (workArea)
|
||||
{
|
||||
auto zones = zoneSet->GetZones();
|
||||
for (size_t i = 0; i < zones.size(); i++)
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
{
|
||||
const auto& zone = zones[i];
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
const auto zones = zoneSet->GetZones();
|
||||
for (const auto& [zoneId, zone] : zones)
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
|
||||
zoneRect.left += monitorRect.left;
|
||||
zoneRect.right += monitorRect.left;
|
||||
zoneRect.top += monitorRect.top;
|
||||
zoneRect.bottom += monitorRect.top;
|
||||
zoneRect.left += monitorRect.left;
|
||||
zoneRect.right += monitorRect.left;
|
||||
zoneRect.top += monitorRect.top;
|
||||
zoneRect.bottom += monitorRect.top;
|
||||
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(i, workArea);
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(zoneId, workArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1225,22 +1229,24 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
||||
if (currentMonitorRect.top <= currentMonitorRect.bottom)
|
||||
{
|
||||
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, current);
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
if (workArea)
|
||||
{
|
||||
auto zones = zoneSet->GetZones();
|
||||
for (size_t i = 0; i < zones.size(); i++)
|
||||
auto zoneSet = workArea->ActiveZoneSet();
|
||||
if (zoneSet)
|
||||
{
|
||||
const auto& zone = zones[i];
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
const auto zones = zoneSet->GetZones();
|
||||
for (const auto& [zoneId, zone] : zones)
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
|
||||
zoneRect.left += currentMonitorRect.left;
|
||||
zoneRect.right += currentMonitorRect.left;
|
||||
zoneRect.top += currentMonitorRect.top;
|
||||
zoneRect.bottom += currentMonitorRect.top;
|
||||
zoneRect.left += currentMonitorRect.left;
|
||||
zoneRect.right += currentMonitorRect.left;
|
||||
zoneRect.top += currentMonitorRect.top;
|
||||
zoneRect.bottom += currentMonitorRect.top;
|
||||
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(i, workArea);
|
||||
zoneRects.emplace_back(zoneRect);
|
||||
zoneRectsInfo.emplace_back(zoneId, workArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1353,9 +1359,9 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
{
|
||||
monitor = MonitorFromWindow(GetForegroundWindow(), MONITOR_DEFAULTTONULL);
|
||||
}
|
||||
|
||||
|
||||
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||
if (zoneWindow->ActiveZoneSet() != nullptr)
|
||||
if (zoneWindow && zoneWindow->ActiveZoneSet() != nullptr)
|
||||
{
|
||||
if (vkCode == VK_UP || vkCode == VK_DOWN)
|
||||
{
|
||||
|
||||
@@ -135,7 +135,7 @@ RECT Zone::ComputeActualZoneRect(HWND window, HWND zoneWindow) const noexcept
|
||||
|
||||
winrt::com_ptr<IZone> MakeZone(const RECT& zoneRect, const size_t zoneId) noexcept
|
||||
{
|
||||
if (ValidateZoneRect(zoneRect) && zoneId > 0)
|
||||
if (ValidateZoneRect(zoneRect) && zoneId >= 0)
|
||||
{
|
||||
return winrt::make_self<Zone>(zoneRect, zoneId);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <common/dpi_aware.h>
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
using namespace FancyZonesUtils;
|
||||
@@ -113,7 +115,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ZoneSet(ZoneSetConfig const& config, std::vector<winrt::com_ptr<IZone>> zones) :
|
||||
ZoneSet(ZoneSetConfig const& config, ZonesMap zones) :
|
||||
m_config(config),
|
||||
m_zones(zones)
|
||||
{
|
||||
@@ -128,8 +130,8 @@ public:
|
||||
ZonesFromPoint(POINT pt) const noexcept;
|
||||
IFACEMETHODIMP_(std::vector<size_t>)
|
||||
GetZoneIndexSetFromWindow(HWND window) const noexcept;
|
||||
IFACEMETHODIMP_(std::vector<winrt::com_ptr<IZone>>)
|
||||
GetZones() const noexcept { return m_zones; }
|
||||
IFACEMETHODIMP_(ZonesMap)
|
||||
GetZones()const noexcept override { return m_zones; }
|
||||
IFACEMETHODIMP_(void)
|
||||
MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, size_t index) noexcept;
|
||||
IFACEMETHODIMP_(void)
|
||||
@@ -157,7 +159,7 @@ private:
|
||||
bool CalculateCustomLayout(Rect workArea, int spacing) noexcept;
|
||||
bool CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutInfo gridLayoutInfo, int spacing);
|
||||
|
||||
std::vector<winrt::com_ptr<IZone>> m_zones;
|
||||
ZonesMap m_zones;
|
||||
std::map<HWND, std::vector<size_t>> m_windowIndexSet;
|
||||
|
||||
// Needed for ExtendWindowByDirectionAndPosition
|
||||
@@ -170,7 +172,12 @@ private:
|
||||
|
||||
IFACEMETHODIMP ZoneSet::AddZone(winrt::com_ptr<IZone> zone) noexcept
|
||||
{
|
||||
m_zones.emplace_back(zone);
|
||||
auto zoneId = zone->Id();
|
||||
if (m_zones.contains(zoneId))
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
m_zones[zoneId] = zone;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -180,19 +187,19 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
|
||||
{
|
||||
std::vector<size_t> capturedZones;
|
||||
std::vector<size_t> strictlyCapturedZones;
|
||||
for (size_t i = 0; i < m_zones.size(); i++)
|
||||
for (const auto& [zoneId, zone] : m_zones)
|
||||
{
|
||||
const RECT& zoneRect = m_zones[i]->GetZoneRect();
|
||||
const RECT& zoneRect = zone->GetZoneRect();
|
||||
if (zoneRect.left - m_config.SensitivityRadius <= pt.x && pt.x <= zoneRect.right + m_config.SensitivityRadius &&
|
||||
zoneRect.top - m_config.SensitivityRadius <= pt.y && pt.y <= zoneRect.bottom + m_config.SensitivityRadius)
|
||||
{
|
||||
capturedZones.emplace_back(i);
|
||||
capturedZones.emplace_back(zoneId);
|
||||
}
|
||||
|
||||
if (zoneRect.left <= pt.x && pt.x < zoneRect.right &&
|
||||
zoneRect.top <= pt.y && pt.y < zoneRect.bottom)
|
||||
{
|
||||
strictlyCapturedZones.emplace_back(i);
|
||||
strictlyCapturedZones.emplace_back(zoneId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,8 +217,18 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
|
||||
{
|
||||
for (size_t j = i + 1; j < capturedZones.size(); ++j)
|
||||
{
|
||||
const auto& rectI = m_zones[capturedZones[i]]->GetZoneRect();
|
||||
const auto& rectJ = m_zones[capturedZones[j]]->GetZoneRect();
|
||||
RECT rectI;
|
||||
RECT rectJ;
|
||||
try
|
||||
{
|
||||
rectI = m_zones.at(capturedZones[i])->GetZoneRect();
|
||||
rectJ = m_zones.at(capturedZones[j])->GetZoneRect();
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (max(rectI.top, rectJ.top) + m_config.SensitivityRadius < min(rectI.bottom, rectJ.bottom) &&
|
||||
max(rectI.left, rectJ.left) + m_config.SensitivityRadius < min(rectI.right, rectJ.right))
|
||||
{
|
||||
@@ -230,8 +247,17 @@ ZoneSet::ZonesFromPoint(POINT pt) const noexcept
|
||||
size_t smallestIdx = 0;
|
||||
for (size_t i = 1; i < capturedZones.size(); ++i)
|
||||
{
|
||||
const auto& rectS = m_zones[capturedZones[smallestIdx]]->GetZoneRect();
|
||||
const auto& rectI = m_zones[capturedZones[i]]->GetZoneRect();
|
||||
RECT rectS;
|
||||
RECT rectI;
|
||||
try
|
||||
{
|
||||
rectS = m_zones.at(capturedZones[smallestIdx])->GetZoneRect();
|
||||
rectI = m_zones.at(capturedZones[i])->GetZoneRect();
|
||||
}
|
||||
catch (std::out_of_range)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
int smallestSize = (rectS.bottom - rectS.top) * (rectS.right - rectS.left);
|
||||
int iSize = (rectI.bottom - rectI.top) * (rectI.right - rectI.left);
|
||||
|
||||
@@ -267,7 +293,7 @@ ZoneSet::MoveWindowIntoZoneByIndex(HWND window, HWND workAreaWindow, size_t inde
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(void)
|
||||
ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const std::vector<size_t>& indexSet) noexcept
|
||||
ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const std::vector<size_t>& zoneIds) noexcept
|
||||
{
|
||||
if (m_zones.empty())
|
||||
{
|
||||
@@ -287,11 +313,12 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const st
|
||||
|
||||
m_windowIndexSet[window] = {};
|
||||
|
||||
for (size_t index : indexSet)
|
||||
for (size_t id : zoneIds)
|
||||
{
|
||||
if (index < m_zones.size())
|
||||
if (m_zones.contains(id))
|
||||
{
|
||||
RECT newSize = m_zones.at(index)->ComputeActualZoneRect(window, workAreaWindow);
|
||||
const auto& zone = m_zones.at(id);
|
||||
const RECT newSize = zone->ComputeActualZoneRect(window, workAreaWindow);
|
||||
if (!sizeEmpty)
|
||||
{
|
||||
size.left = min(size.left, newSize.left);
|
||||
@@ -305,12 +332,12 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const st
|
||||
sizeEmpty = false;
|
||||
}
|
||||
|
||||
m_windowIndexSet[window].push_back(index);
|
||||
m_windowIndexSet[window].push_back(id);
|
||||
}
|
||||
|
||||
if (index < std::numeric_limits<size_t>::digits)
|
||||
if (id < std::numeric_limits<size_t>::digits)
|
||||
{
|
||||
bitmask |= 1ull << index;
|
||||
bitmask |= 1ull << id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,14 +363,14 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow,
|
||||
// The window was not assigned to any zone here
|
||||
if (indexSet.size() == 0)
|
||||
{
|
||||
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { vkCode == VK_LEFT ? numZones - 1 : 0 });
|
||||
MoveWindowIntoZoneByIndex(window, workAreaWindow, vkCode == VK_LEFT ? numZones - 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t oldIndex = indexSet[0];
|
||||
size_t oldId = indexSet[0];
|
||||
|
||||
// We reached the edge
|
||||
if ((vkCode == VK_LEFT && oldIndex == 0) || (vkCode == VK_RIGHT && oldIndex == numZones - 1))
|
||||
if ((vkCode == VK_LEFT && oldId == 0) || (vkCode == VK_RIGHT && oldId == numZones - 1))
|
||||
{
|
||||
if (!cycle)
|
||||
{
|
||||
@@ -352,7 +379,7 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow,
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { vkCode == VK_LEFT ? numZones - 1 : 0 });
|
||||
MoveWindowIntoZoneByIndex(window, workAreaWindow, vkCode == VK_LEFT ? numZones - 1 : 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -360,11 +387,11 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndIndex(HWND window, HWND workAreaWindow,
|
||||
// We didn't reach the edge
|
||||
if (vkCode == VK_LEFT)
|
||||
{
|
||||
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { oldIndex - 1 });
|
||||
MoveWindowIntoZoneByIndex(window, workAreaWindow, oldId - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveWindowIntoZoneByIndexSet(window, workAreaWindow, { oldIndex + 1 });
|
||||
MoveWindowIntoZoneByIndex(window, workAreaWindow, oldId + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -378,20 +405,20 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND workAreaWind
|
||||
}
|
||||
|
||||
std::vector<bool> usedZoneIndices(m_zones.size(), false);
|
||||
for (size_t idx : GetZoneIndexSetFromWindow(window))
|
||||
for (size_t id : GetZoneIndexSetFromWindow(window))
|
||||
{
|
||||
usedZoneIndices[idx] = true;
|
||||
usedZoneIndices[id] = true;
|
||||
}
|
||||
|
||||
std::vector<RECT> zoneRects;
|
||||
std::vector<size_t> freeZoneIndices;
|
||||
|
||||
for (size_t i = 0; i < m_zones.size(); i++)
|
||||
for (const auto& [zoneId, zone] : m_zones)
|
||||
{
|
||||
if (!usedZoneIndices[i])
|
||||
if (!usedZoneIndices[zoneId])
|
||||
{
|
||||
zoneRects.emplace_back(m_zones[i]->GetZoneRect());
|
||||
freeZoneIndices.emplace_back(i);
|
||||
zoneRects.emplace_back(m_zones[zoneId]->GetZoneRect());
|
||||
freeZoneIndices.emplace_back(zoneId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +442,7 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND workAreaWind
|
||||
// Try again from the position off the screen in the opposite direction to vkCode
|
||||
// Consider all zones as available
|
||||
zoneRects.resize(m_zones.size());
|
||||
std::transform(m_zones.begin(), m_zones.end(), zoneRects.begin(), [](auto zone) { return zone->GetZoneRect(); });
|
||||
std::transform(m_zones.begin(), m_zones.end(), zoneRects.begin(), [](auto zone) { return zone.second->GetZoneRect(); });
|
||||
windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, windowZoneRect, vkCode);
|
||||
result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
|
||||
|
||||
@@ -588,7 +615,7 @@ bool ZoneSet::CalculateFocusLayout(Rect workArea, int zoneCount) noexcept
|
||||
|
||||
for (int i = 0; i < zoneCount; i++)
|
||||
{
|
||||
auto zone = MakeZone(focusZoneRect, m_zones.size() + 1);
|
||||
auto zone = MakeZone(focusZoneRect, m_zones.size());
|
||||
if (zone)
|
||||
{
|
||||
AddZone(zone);
|
||||
@@ -645,7 +672,7 @@ bool ZoneSet::CalculateColumnsAndRowsLayout(Rect workArea, FancyZonesDataTypes::
|
||||
}
|
||||
|
||||
|
||||
auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size() + 1);
|
||||
auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size());
|
||||
if (zone)
|
||||
{
|
||||
AddZone(zone);
|
||||
@@ -713,9 +740,9 @@ bool ZoneSet::CalculateGridLayout(Rect workArea, FancyZonesDataTypes::ZoneSetLay
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (int col = columns - 1; col >= 0; col--)
|
||||
for (int row = 0; row < rows; row++)
|
||||
{
|
||||
for (int row = rows - 1; row >= 0; row--)
|
||||
for (int col = 0; col < columns; col++)
|
||||
{
|
||||
gridLayoutInfo.cellChildMap()[row][col] = index++;
|
||||
if (index == zoneCount)
|
||||
@@ -765,7 +792,7 @@ bool ZoneSet::CalculateCustomLayout(Rect workArea, int spacing) noexcept
|
||||
DPIAware::Convert(m_config.Monitor, x, y);
|
||||
DPIAware::Convert(m_config.Monitor, width, height);
|
||||
|
||||
auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size() + 1);
|
||||
auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size());
|
||||
if (zone)
|
||||
{
|
||||
AddZone(zone);
|
||||
@@ -848,7 +875,7 @@ bool ZoneSet::CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutI
|
||||
long right = columnInfo[maxCol].End;
|
||||
long bottom = rowInfo[maxRow].End;
|
||||
|
||||
auto zone = MakeZone(RECT{ left, top, right, bottom }, m_zones.size() + 1);
|
||||
auto zone = MakeZone(RECT{ left, top, right, bottom }, i);
|
||||
if (zone)
|
||||
{
|
||||
AddZone(zone);
|
||||
@@ -873,30 +900,32 @@ std::vector<size_t> ZoneSet::GetCombinedZoneRange(const std::vector<size_t>& ini
|
||||
|
||||
RECT boundingRect;
|
||||
bool boundingRectEmpty = true;
|
||||
auto zones = GetZones();
|
||||
|
||||
for (size_t zoneId : combinedZones)
|
||||
{
|
||||
const RECT& rect = zones[zoneId]->GetZoneRect();
|
||||
if (boundingRectEmpty)
|
||||
if (m_zones.contains(zoneId))
|
||||
{
|
||||
boundingRect = rect;
|
||||
boundingRectEmpty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingRect.left = min(boundingRect.left, rect.left);
|
||||
boundingRect.top = min(boundingRect.top, rect.top);
|
||||
boundingRect.right = max(boundingRect.right, rect.right);
|
||||
boundingRect.bottom = max(boundingRect.bottom, rect.bottom);
|
||||
const RECT rect = m_zones.at(zoneId)->GetZoneRect();
|
||||
if (boundingRectEmpty)
|
||||
{
|
||||
boundingRect = rect;
|
||||
boundingRectEmpty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingRect.left = min(boundingRect.left, rect.left);
|
||||
boundingRect.top = min(boundingRect.top, rect.top);
|
||||
boundingRect.right = max(boundingRect.right, rect.right);
|
||||
boundingRect.bottom = max(boundingRect.bottom, rect.bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!boundingRectEmpty)
|
||||
{
|
||||
for (size_t zoneId = 0; zoneId < zones.size(); zoneId++)
|
||||
for (const auto& [zoneId, zone] : m_zones)
|
||||
{
|
||||
RECT rect = zones[zoneId]->GetZoneRect();
|
||||
const RECT rect = zone->GetZoneRect();
|
||||
if (boundingRect.left <= rect.left && rect.right <= boundingRect.right &&
|
||||
boundingRect.top <= rect.top && rect.bottom <= boundingRect.bottom)
|
||||
{
|
||||
|
||||
@@ -6,13 +6,15 @@ namespace FancyZonesDataTypes
|
||||
{
|
||||
enum class ZoneSetLayoutType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing single zone layout. ZoneSet is responsible for actual calculation of rectangle coordinates
|
||||
* (whether is grid or canvas layout) and moving windows through them.
|
||||
*/
|
||||
interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet : public IUnknown
|
||||
{
|
||||
// Mapping zone id to zone
|
||||
using ZonesMap = std::map<size_t, winrt::com_ptr<IZone>>;
|
||||
|
||||
/**
|
||||
* @returns Unique identifier of zone layout.
|
||||
*/
|
||||
@@ -45,7 +47,7 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
|
||||
/**
|
||||
* @returns Array of zone objects (defining coordinates of the zone) inside this zone layout.
|
||||
*/
|
||||
IFACEMETHOD_(std::vector<winrt::com_ptr<IZone>>, GetZones)() const = 0;
|
||||
IFACEMETHOD_(ZonesMap, GetZones) () const = 0;
|
||||
/**
|
||||
* Assign window to the zone based on zone index inside zone layout.
|
||||
*
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace ZoneWindowUtils
|
||||
COLORREF hostZoneBorderColor,
|
||||
COLORREF hostZoneHighlightColor,
|
||||
int hostZoneHighlightOpacity,
|
||||
std::vector<winrt::com_ptr<IZone>> zones,
|
||||
IZoneSet::ZonesMap zones,
|
||||
std::vector<size_t> highlightZone,
|
||||
bool flashMode)
|
||||
{
|
||||
@@ -621,7 +621,7 @@ void ZoneWindow::OnPaint(HDC hdc) noexcept
|
||||
COLORREF hostZoneBorderColor{};
|
||||
COLORREF hostZoneHighlightColor{};
|
||||
int hostZoneHighlightOpacity{};
|
||||
std::vector<winrt::com_ptr<IZone>> zones{};
|
||||
IZoneSet::ZonesMap zones;
|
||||
std::vector<size_t> highlightZone = m_highlightZone;
|
||||
bool flashMode = m_flashMode;
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "pch.h"
|
||||
#include "ZoneWindowDrawing.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace NonLocalizable
|
||||
{
|
||||
@@ -79,7 +82,7 @@ namespace
|
||||
g.DrawString(text.c_str(), -1, &font, gdiRect, &stringFormat, &solidBrush);
|
||||
}
|
||||
|
||||
void DrawZone(wil::unique_hdc& hdc, ZoneWindowDrawing::ColorSetting const& colorSetting, winrt::com_ptr<IZone> zone, const std::vector<winrt::com_ptr<IZone>>& zones, bool flashMode) noexcept
|
||||
void DrawZone(wil::unique_hdc& hdc, ZoneWindowDrawing::ColorSetting const& colorSetting, winrt::com_ptr<IZone> zone, bool flashMode)noexcept
|
||||
{
|
||||
RECT zoneRect = zone->GetZoneRect();
|
||||
|
||||
@@ -95,7 +98,7 @@ namespace
|
||||
|
||||
if (!flashMode)
|
||||
{
|
||||
DrawIndex(hdc, zoneRect, zone->Id());
|
||||
DrawIndex(hdc, zoneRect, zone->Id() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +115,7 @@ namespace ZoneWindowDrawing
|
||||
COLORREF zoneBorderColor,
|
||||
COLORREF highlightColor,
|
||||
int zoneOpacity,
|
||||
const std::vector<winrt::com_ptr<IZone>>& zones,
|
||||
const IZoneSet::ZonesMap& zones,
|
||||
const std::vector<size_t>& highlightZones,
|
||||
bool flashMode) noexcept
|
||||
{
|
||||
@@ -121,52 +124,41 @@ namespace ZoneWindowDrawing
|
||||
ColorSetting colorHighlight{ OpacitySettingToAlpha(zoneOpacity), 0, 255, 0, -2 };
|
||||
ColorSetting const colorFlash{ OpacitySettingToAlpha(zoneOpacity), RGB(81, 92, 107), 200, RGB(104, 118, 138), -2 };
|
||||
|
||||
std::vector<bool> isHighlighted(zones.size(), false);
|
||||
for (size_t x : highlightZones)
|
||||
{
|
||||
isHighlighted[x] = true;
|
||||
}
|
||||
|
||||
// First draw the inactive zones
|
||||
for (auto iter = zones.begin(); iter != zones.end(); iter++)
|
||||
{
|
||||
int zoneId = static_cast<int>(iter - zones.begin());
|
||||
winrt::com_ptr<IZone> zone = iter->try_as<IZone>();
|
||||
winrt::com_ptr<IZone> zone = iter->second;
|
||||
size_t zoneId = zone->Id();
|
||||
if (!zone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isHighlighted[zoneId])
|
||||
auto zoneIt = std::find(highlightZones.begin(), highlightZones.end(), zoneId);
|
||||
if (zoneIt == highlightZones.end())
|
||||
{
|
||||
if (flashMode)
|
||||
{
|
||||
DrawZone(hdc, colorFlash, zone, zones, flashMode);
|
||||
DrawZone(hdc, colorFlash, zone, flashMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
colorViewer.fill = zoneColor;
|
||||
colorViewer.border = zoneBorderColor;
|
||||
DrawZone(hdc, colorViewer, zone, zones, flashMode);
|
||||
DrawZone(hdc, colorViewer, zone, flashMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the active zones on top of the inactive zones
|
||||
for (auto iter = zones.begin(); iter != zones.end(); iter++)
|
||||
for (const auto& zoneId : highlightZones)
|
||||
{
|
||||
int zoneId = static_cast<int>(iter - zones.begin());
|
||||
winrt::com_ptr<IZone> zone = iter->try_as<IZone>();
|
||||
if (!zone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
colorHighlight.fill = highlightColor;
|
||||
colorHighlight.border = zoneBorderColor;
|
||||
|
||||
if (isHighlighted[zoneId])
|
||||
if (zones.contains(zoneId))
|
||||
{
|
||||
colorHighlight.fill = highlightColor;
|
||||
colorHighlight.border = zoneBorderColor;
|
||||
DrawZone(hdc, colorHighlight, zone, zones, flashMode);
|
||||
DrawZone(hdc, colorHighlight, zones.at(zoneId), flashMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <wil\resource.h>
|
||||
#include <winrt/base.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "Zone.h"
|
||||
#include "ZoneSet.h"
|
||||
|
||||
namespace ZoneWindowDrawing
|
||||
{
|
||||
@@ -24,7 +26,7 @@ namespace ZoneWindowDrawing
|
||||
COLORREF zoneBorderColor,
|
||||
COLORREF highlightColor,
|
||||
int zoneOpacity,
|
||||
const std::vector<winrt::com_ptr<IZone>>& zones,
|
||||
const IZoneSet::ZonesMap& zones,
|
||||
const std::vector<size_t>& highlightZones,
|
||||
bool flashMode) noexcept;
|
||||
}
|
||||
|
||||
@@ -85,28 +85,28 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD (AddOne)
|
||||
{
|
||||
constexpr size_t zoneId = 1;
|
||||
constexpr size_t zoneId = 0;
|
||||
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, zoneId);
|
||||
Assert::IsNotNull(zone.get());
|
||||
m_set->AddZone(zone);
|
||||
auto zones = m_set->GetZones();
|
||||
Assert::AreEqual((size_t)1, zones.size());
|
||||
compareZones(zone, zones[0]);
|
||||
Assert::AreEqual(zoneId, zones[0]->Id());
|
||||
compareZones(zone, zones[zoneId]);
|
||||
Assert::AreEqual(zoneId, zones[zoneId]->Id());
|
||||
}
|
||||
|
||||
TEST_METHOD (AddManyEqual)
|
||||
{
|
||||
for (size_t i = 0; i < 1024; i++)
|
||||
{
|
||||
size_t zoneId = i + 1;
|
||||
size_t zoneId = i;
|
||||
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, zoneId);
|
||||
Assert::IsNotNull(zone.get());
|
||||
m_set->AddZone(zone);
|
||||
auto zones = m_set->GetZones();
|
||||
Assert::AreEqual(i + 1, zones.size());
|
||||
compareZones(zone, zones[i]);
|
||||
Assert::AreEqual(zoneId, zones[i]->Id());
|
||||
compareZones(zone, zones[zoneId]);
|
||||
Assert::AreEqual(zoneId, zones[zoneId]->Id());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace FancyZonesUnitTests
|
||||
{
|
||||
for (size_t i = 0; i < 1024; i++)
|
||||
{
|
||||
size_t zoneId = i + 1;
|
||||
size_t zoneId = i;
|
||||
int left = rand() % 10;
|
||||
int top = rand() % 10;
|
||||
int right = left + 1 + rand() % 100;
|
||||
@@ -124,8 +124,8 @@ namespace FancyZonesUnitTests
|
||||
m_set->AddZone(zone);
|
||||
auto zones = m_set->GetZones();
|
||||
Assert::AreEqual(i + 1, zones.size());
|
||||
compareZones(zone, zones[i]);
|
||||
Assert::AreEqual(zoneId, zones[i]->Id());
|
||||
compareZones(zone, zones[zoneId]);
|
||||
Assert::AreEqual(zoneId, zones[zoneId]->Id());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,13 +135,6 @@ namespace FancyZonesUnitTests
|
||||
Assert::IsNotNull(zone.get());
|
||||
}
|
||||
|
||||
TEST_METHOD (MakeZoneWithInvalidId)
|
||||
{
|
||||
constexpr size_t invalidZoneId = 0;
|
||||
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 0, 0 }, invalidZoneId);
|
||||
Assert::IsNull(zone.get());
|
||||
}
|
||||
|
||||
TEST_METHOD (MakeZoneFromInvalidRectWidth)
|
||||
{
|
||||
winrt::com_ptr<IZone> zone = MakeZone({ 100, 100, 99, 101 }, 1);
|
||||
@@ -361,9 +354,9 @@ namespace FancyZonesUnitTests
|
||||
TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameWindow)
|
||||
{
|
||||
// Add a couple of zones.
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 2);
|
||||
winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 3);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 1);
|
||||
winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 2);
|
||||
m_set->AddZone(zone1);
|
||||
m_set->AddZone(zone2);
|
||||
m_set->AddZone(zone3);
|
||||
@@ -382,9 +375,9 @@ namespace FancyZonesUnitTests
|
||||
TEST_METHOD (MoveWindowIntoZoneByIndexSeveralTimesSameIndex)
|
||||
{
|
||||
// Add a couple of zones.
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 2);
|
||||
winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 3);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 1, 1, 101, 101 }, 1);
|
||||
winrt::com_ptr<IZone> zone3 = MakeZone({ 2, 2, 102, 102 }, 2);
|
||||
m_set->AddZone(zone1);
|
||||
m_set->AddZone(zone2);
|
||||
m_set->AddZone(zone3);
|
||||
@@ -414,7 +407,7 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD (MoveWindowIntoZoneByPointInnerPoint)
|
||||
{
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
m_set->AddZone(zone1);
|
||||
|
||||
auto window = Mocks::Window();
|
||||
@@ -425,8 +418,8 @@ namespace FancyZonesUnitTests
|
||||
|
||||
TEST_METHOD (MoveWindowIntoZoneByPointInnerPointOverlappingZones)
|
||||
{
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
|
||||
m_set->AddZone(zone1);
|
||||
m_set->AddZone(zone2);
|
||||
|
||||
@@ -441,8 +434,8 @@ namespace FancyZonesUnitTests
|
||||
const auto window = Mocks::Window();
|
||||
const auto zoneWindow = Mocks::Window();
|
||||
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
|
||||
|
||||
m_set->AddZone(zone1);
|
||||
m_set->AddZone(zone2);
|
||||
@@ -459,8 +452,8 @@ namespace FancyZonesUnitTests
|
||||
const auto window = Mocks::Window();
|
||||
const auto zoneWindow = Mocks::Window();
|
||||
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
|
||||
|
||||
m_set->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 1);
|
||||
|
||||
@@ -477,9 +470,9 @@ namespace FancyZonesUnitTests
|
||||
const auto window = Mocks::Window();
|
||||
const auto zoneWindow = Mocks::Window();
|
||||
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 2);
|
||||
winrt::com_ptr<IZone> zone3 = MakeZone({ 20, 20, 80, 80 }, 3);
|
||||
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
|
||||
winrt::com_ptr<IZone> zone3 = MakeZone({ 20, 20, 80, 80 }, 2);
|
||||
|
||||
m_set->AddZone(zone1);
|
||||
m_set->AddZone(zone2);
|
||||
@@ -507,9 +500,9 @@ namespace FancyZonesUnitTests
|
||||
m_set = MakeZoneSet(config);
|
||||
|
||||
// Add a couple of zones.
|
||||
m_zone1 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
m_zone2 = MakeZone({ 0, 0, 100, 100 }, 2);
|
||||
m_zone3 = MakeZone({ 0, 0, 100, 100 }, 3);
|
||||
m_zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
|
||||
m_zone2 = MakeZone({ 0, 0, 100, 100 }, 1);
|
||||
m_zone3 = MakeZone({ 0, 0, 100, 100 }, 2);
|
||||
m_set->AddZone(m_zone1);
|
||||
m_set->AddZone(m_zone2);
|
||||
m_set->AddZone(m_zone3);
|
||||
@@ -776,7 +769,7 @@ namespace FancyZonesUnitTests
|
||||
{
|
||||
Assert::IsTrue(set->IsZoneEmpty(zoneId));
|
||||
|
||||
const auto& zoneRect = zone->GetZoneRect();
|
||||
const auto& zoneRect = zone.second->GetZoneRect();
|
||||
Assert::IsTrue(zoneRect.left >= 0, L"left border is less than zero");
|
||||
Assert::IsTrue(zoneRect.top >= 0, L"top border is less than zero");
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 110 KiB |
@@ -21,12 +21,11 @@ namespace Microsoft.Plugin.Folder.Sources.Result
|
||||
|
||||
public Wox.Plugin.Result Create(IPublicAPI contextApi)
|
||||
{
|
||||
var result = new Wox.Plugin.Result
|
||||
var result = new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData)
|
||||
{
|
||||
Title = Title,
|
||||
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_file_result_subtitle, FilePath),
|
||||
IcoPath = FilePath,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData,
|
||||
Action = c => ShellAction.Execute(FilePath, contextApi),
|
||||
ContextData = new SearchResult { Type = ResultType.File, FullPath = FilePath },
|
||||
};
|
||||
|
||||
@@ -33,13 +33,12 @@ namespace Microsoft.Plugin.Folder.Sources.Result
|
||||
|
||||
public Wox.Plugin.Result Create(IPublicAPI contextApi)
|
||||
{
|
||||
return new Wox.Plugin.Result
|
||||
return new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Title).MatchData)
|
||||
{
|
||||
Title = Title,
|
||||
IcoPath = Path,
|
||||
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Subtitle),
|
||||
QueryTextDisplay = Path,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(Search, Title).MatchData,
|
||||
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path },
|
||||
Action = c => ShellAction.Execute(Path, contextApi),
|
||||
};
|
||||
|
||||
@@ -24,13 +24,12 @@ namespace Microsoft.Plugin.Folder
|
||||
|
||||
public Result Create(IPublicAPI contextApi)
|
||||
{
|
||||
return new Result
|
||||
return new Result(StringMatcher.FuzzySearch(Search, Title).MatchData)
|
||||
{
|
||||
Title = Title,
|
||||
IcoPath = Path,
|
||||
SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Subtitle),
|
||||
QueryTextDisplay = Path,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(Search, Title).MatchData,
|
||||
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path },
|
||||
Action = c => _shellAction.Execute(Path, contextApi),
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Plugin.Program.ProgramArgumentParser;
|
||||
using Mono.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Wox.Plugin;
|
||||
|
||||
@@ -34,7 +35,7 @@ namespace Microsoft.Plugin.Program.UnitTests.ProgramArgumentParser
|
||||
// basic version of the Quey parser which can be found at Wox.Core.Plugin.QueryBuilder but did not want to create a project reference
|
||||
var splittedSearchString = inputQuery?.Split(Query.TermSeparator, System.StringSplitOptions.RemoveEmptyEntries);
|
||||
var cleanQuery = string.Join(Query.TermSeparator, splittedSearchString);
|
||||
var query = new Query(cleanQuery, cleanQuery, splittedSearchString, string.Empty);
|
||||
var query = new Query(cleanQuery, cleanQuery, new ReadOnlyCollection<string>(splittedSearchString), string.Empty);
|
||||
|
||||
// Act
|
||||
string program = null, programArguments = null;
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Microsoft.Plugin.Program
|
||||
if (!string.IsNullOrEmpty(query?.Search))
|
||||
{
|
||||
// First Argument is always (part of) the program, 2nd term is possibly a Program Argument
|
||||
if (query.Terms.Length > 1)
|
||||
if (query.Terms.Count > 1)
|
||||
{
|
||||
for (var i = 1; i < query.Terms.Length; i++)
|
||||
for (var i = 1; i < query.Terms.Count; i++)
|
||||
{
|
||||
if (!string.Equals(query.Terms[i], DoubleDash, StringComparison.Ordinal))
|
||||
{
|
||||
|
||||
@@ -19,9 +19,9 @@ namespace Microsoft.Plugin.Program
|
||||
if (!string.IsNullOrEmpty(query?.Search))
|
||||
{
|
||||
// First Argument is always (part of) the program, 2nd term is possibly a Program Argument
|
||||
if (query.Terms.Length > 1)
|
||||
if (query.Terms.Count > 1)
|
||||
{
|
||||
for (var i = 1; i < query.Terms.Length; i++)
|
||||
for (var i = 1; i < query.Terms.Count; i++)
|
||||
{
|
||||
if (!ArgumentPrefixRegex.IsMatch(query.Terms[i]))
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
using Accessibility;
|
||||
using Microsoft.Plugin.Program.Logger;
|
||||
using Wox.Plugin.Logger;
|
||||
|
||||
namespace Microsoft.Plugin.Program.Programs
|
||||
{
|
||||
@@ -131,6 +132,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
public bool HasArguments { get; set; }
|
||||
|
||||
// Retrieve the target path using Shell Link
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "HRESULT E_FAIL is thrown while fetching description and E_FAIL does not relate to any specific exception.")]
|
||||
public string RetrieveTargetPath(string path)
|
||||
{
|
||||
var link = new ShellLink();
|
||||
@@ -160,8 +162,16 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
if (!string.IsNullOrEmpty(target))
|
||||
{
|
||||
buffer = new StringBuilder(MAX_PATH);
|
||||
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
|
||||
Description = buffer.ToString();
|
||||
try
|
||||
{
|
||||
((IShellLinkW)link).GetDescription(buffer, MAX_PATH);
|
||||
Description = buffer.ToString();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception($"|Failed to fetch description for {target}, {e.Message}", e, GetType());
|
||||
Description = string.Empty;
|
||||
}
|
||||
|
||||
StringBuilder argumentBuffer = new StringBuilder(MAX_PATH);
|
||||
((IShellLinkW)link).GetArguments(argumentBuffer, argumentBuffer.Capacity);
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
// To set the title to always be the displayname of the packaged application
|
||||
result.Title = DisplayName;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData;
|
||||
result.SetTitleHighlightData(StringMatcher.FuzzySearch(query, Name).MatchData);
|
||||
|
||||
var toolTipTitle = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_name, result.Title);
|
||||
var toolTipText = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_path, Package.Location);
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Microsoft.Plugin.Program.Programs
|
||||
|
||||
// To set the title for the result to always be the name of the application
|
||||
result.Title = Name;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData;
|
||||
result.SetTitleHighlightData(StringMatcher.FuzzySearch(query, Name).MatchData);
|
||||
|
||||
var toolTipTitle = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_name, result.Title);
|
||||
var toolTipText = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_path, FullPath);
|
||||
|
||||
@@ -32,5 +32,10 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
|
||||
<Version>3.3.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace Microsoft.Plugin.Uri.UnitTests.UriHelper
|
||||
[TestCase("[::]", true, "http://[::]/")]
|
||||
[TestCase("[2001:0DB8::1]", true, "http://[2001:db8::1]/")]
|
||||
[TestCase("[2001:0DB8::1]:80", true, "http://[2001:db8::1]/")]
|
||||
public void TryParse_CanParseHostName(string query, bool expectedSuccess, string expectedResult)
|
||||
public void TryParseCanParseHostName(string query, bool expectedSuccess, string expectedResult)
|
||||
{
|
||||
// Arrange
|
||||
var parser = new ExtendedUriParser();
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace Wox.Core.Plugin
|
||||
metadata.PluginDirectory = pluginDirectory;
|
||||
|
||||
// for plugins which doesn't has ActionKeywords key
|
||||
metadata.ActionKeywords = metadata.ActionKeywords ?? new List<string> { metadata.ActionKeyword };
|
||||
metadata.SetActionKeywords(metadata.GetActionKeywords() ?? new List<string> { metadata.ActionKeyword });
|
||||
|
||||
// for plugin still use old ActionKeyword
|
||||
metadata.ActionKeyword = metadata.ActionKeywords?[0];
|
||||
metadata.ActionKeyword = metadata.GetActionKeywords()?[0];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace Wox.Core.Plugin
|
||||
}
|
||||
|
||||
// Plugins may have multiple ActionKeywords, eg. WebSearch
|
||||
plugin.Metadata.ActionKeywords.Where(x => x != Query.GlobalPluginWildcardSign)
|
||||
plugin.Metadata.GetActionKeywords().Where(x => x != Query.GlobalPluginWildcardSign)
|
||||
.ToList()
|
||||
.ForEach(x => NonGlobalPlugins[x] = plugin);
|
||||
}
|
||||
@@ -244,7 +244,7 @@ namespace Wox.Core.Plugin
|
||||
|
||||
private static bool IsGlobalPlugin(PluginMetadata metadata)
|
||||
{
|
||||
return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign);
|
||||
return metadata.GetActionKeywords().Contains(Query.GlobalPluginWildcardSign);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -258,7 +258,6 @@ namespace Wox.Core.Plugin
|
||||
}
|
||||
|
||||
public static IEnumerable<PluginPair> GetPluginsForInterface<T>()
|
||||
where T : IFeatures
|
||||
{
|
||||
return AllPlugins.Where(p => p.Plugin is T);
|
||||
}
|
||||
@@ -320,7 +319,7 @@ namespace Wox.Core.Plugin
|
||||
NonGlobalPlugins[newActionKeyword] = plugin;
|
||||
}
|
||||
|
||||
plugin.Metadata.ActionKeywords.Add(newActionKeyword);
|
||||
plugin.Metadata.GetActionKeywords().Add(newActionKeyword);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -332,7 +331,7 @@ namespace Wox.Core.Plugin
|
||||
var plugin = GetPluginForId(id);
|
||||
if (oldActionkeyword == Query.GlobalPluginWildcardSign
|
||||
&& // Plugins may have multiple ActionKeywords that are global, eg. WebSearch
|
||||
plugin.Metadata.ActionKeywords
|
||||
plugin.Metadata.GetActionKeywords()
|
||||
.Where(x => x == Query.GlobalPluginWildcardSign)
|
||||
.ToList()
|
||||
.Count == 1)
|
||||
@@ -345,7 +344,7 @@ namespace Wox.Core.Plugin
|
||||
NonGlobalPlugins.Remove(oldActionkeyword);
|
||||
}
|
||||
|
||||
plugin.Metadata.ActionKeywords.Remove(oldActionkeyword);
|
||||
plugin.Metadata.GetActionKeywords().Remove(oldActionkeyword);
|
||||
}
|
||||
|
||||
public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Collections.Generic;
|
||||
using Wox.Plugin;
|
||||
|
||||
namespace Wox.Core.Plugin
|
||||
@@ -63,7 +64,7 @@ namespace Wox.Core.Plugin
|
||||
}
|
||||
|
||||
// A new query is constructed for each plugin as they have different action keywords
|
||||
var query = new Query(rawQuery, search, terms, pluginActionKeyword);
|
||||
var query = new Query(rawQuery, search, new ReadOnlyCollection<string>(terms), pluginActionKeyword);
|
||||
|
||||
pluginQueryPair.TryAdd(pluginPair, query);
|
||||
}
|
||||
@@ -80,7 +81,7 @@ namespace Wox.Core.Plugin
|
||||
{
|
||||
if (!pluginQueryPair.ContainsKey(globalPlugin))
|
||||
{
|
||||
var query = new Query(rawQuery, rawQuery, terms, string.Empty);
|
||||
var query = new Query(rawQuery, rawQuery, new ReadOnlyCollection<string>(terms), string.Empty);
|
||||
pluginQueryPair.Add(globalPlugin, query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Wox.Infrastructure.UserSettings
|
||||
var settings = Plugins[metadata.ID];
|
||||
if (settings.ActionKeywords?.Count > 0)
|
||||
{
|
||||
metadata.ActionKeywords = settings.ActionKeywords;
|
||||
metadata.SetActionKeywords(settings.ActionKeywords);
|
||||
metadata.ActionKeyword = settings.ActionKeywords[0];
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Wox.Infrastructure.UserSettings
|
||||
{
|
||||
ID = metadata.ID,
|
||||
Name = metadata.Name,
|
||||
ActionKeywords = metadata.ActionKeywords,
|
||||
ActionKeywords = metadata.GetActionKeywords(),
|
||||
Disabled = metadata.Disabled,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public static class AllowedLanguage
|
||||
@@ -18,8 +21,14 @@ namespace Wox.Plugin
|
||||
|
||||
public static bool IsAllowed(string language)
|
||||
{
|
||||
return language.ToUpper() == CSharp.ToUpper()
|
||||
|| language.ToUpper() == Executable.ToUpper();
|
||||
if (language == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(language));
|
||||
}
|
||||
|
||||
// Using InvariantCulture since this is a command line arg
|
||||
return language.ToUpper(CultureInfo.InvariantCulture) == CSharp.ToUpper(CultureInfo.InvariantCulture)
|
||||
|| language.ToUpper(CultureInfo.InvariantCulture) == Executable.ToUpper(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public interface IFeatures
|
||||
{
|
||||
}
|
||||
|
||||
public interface IContextMenu : IFeatures
|
||||
public interface IContextMenu
|
||||
{
|
||||
List<ContextMenuResult> LoadContextMenus(Result selectedResult);
|
||||
}
|
||||
@@ -18,14 +14,14 @@ namespace Wox.Plugin
|
||||
/// <summary>
|
||||
/// Represent plugins that support internationalization
|
||||
/// </summary>
|
||||
public interface IPluginI18n : IFeatures
|
||||
public interface IPluginI18n
|
||||
{
|
||||
string GetTranslatedPluginTitle();
|
||||
|
||||
string GetTranslatedPluginDescription();
|
||||
}
|
||||
|
||||
public interface IResultUpdated : IFeatures
|
||||
public interface IResultUpdated
|
||||
{
|
||||
event ResultUpdatedEventHandler ResultsUpdated;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public interface IDelayedExecutionPlugin : IFeatures
|
||||
public interface IDelayedExecutionPlugin
|
||||
{
|
||||
List<Result> Query(Query query, bool delayedExecution);
|
||||
}
|
||||
|
||||
14
src/modules/launcher/Wox.Plugin/LocProject.json
Normal file
14
src/modules/launcher/Wox.Plugin/LocProject.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"Projects": [
|
||||
{
|
||||
"LanguageSet": "Azure_Languages",
|
||||
"LocItems": [
|
||||
{
|
||||
"SourceFile": "src\\modules\\launcher\\Wox.Plugin\\Properties\\Resources.resx",
|
||||
"CopyOption": "LangIDOnName",
|
||||
"OutputPath": "src\\modules\\launcher\\Wox.Plugin\\Properties"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -14,6 +14,13 @@ namespace Wox.Plugin
|
||||
{
|
||||
private string _pluginDirectory;
|
||||
|
||||
private List<string> _actionKeywords;
|
||||
|
||||
public PluginMetadata(List<string> actionKeywords = null)
|
||||
{
|
||||
_actionKeywords = actionKeywords;
|
||||
}
|
||||
|
||||
public string ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
@@ -51,7 +58,15 @@ namespace Wox.Plugin
|
||||
|
||||
public string ActionKeyword { get; set; }
|
||||
|
||||
public List<string> ActionKeywords { get; set; }
|
||||
public List<string> GetActionKeywords()
|
||||
{
|
||||
return _actionKeywords;
|
||||
}
|
||||
|
||||
public void SetActionKeywords(List<string> value)
|
||||
{
|
||||
_actionKeywords = value;
|
||||
}
|
||||
|
||||
public string IcoPath { get; set; }
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
public class PluginPair
|
||||
@@ -19,7 +21,8 @@ namespace Wox.Plugin
|
||||
{
|
||||
if (obj is PluginPair r)
|
||||
{
|
||||
return string.Equals(r.Metadata.ID, Metadata.ID);
|
||||
// Using Ordinal since this is used internally
|
||||
return string.Equals(r.Metadata.ID, Metadata.ID, StringComparison.Ordinal);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -29,7 +32,8 @@ namespace Wox.Plugin
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashcode = Metadata.ID?.GetHashCode() ?? 0;
|
||||
// Using Ordinal since this is used internally
|
||||
var hashcode = Metadata.ID?.GetHashCode(StringComparison.Ordinal) ?? 0;
|
||||
return hashcode;
|
||||
}
|
||||
}
|
||||
|
||||
90
src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs
generated
Normal file
90
src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,90 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Wox.Plugin.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wox.Plugin.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copying path {0} has failed, it will now be deleted for consistency.
|
||||
/// </summary>
|
||||
public static string filesfolder_copy_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("filesfolder_copy_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not able to delete folder {0}, please go to the location and manually delete it.
|
||||
/// </summary>
|
||||
public static string filesfolder_removefolder_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("filesfolder_removefolder_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unable to verify folders and files between {0} and {1}.
|
||||
/// </summary>
|
||||
public static string filesfolder_verifybothfolderfilesequal_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("filesfolder_verifybothfolderfilesequal_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
132
src/modules/launcher/Wox.Plugin/Properties/Resources.resx
Normal file
132
src/modules/launcher/Wox.Plugin/Properties/Resources.resx
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="filesfolder_copy_failed" xml:space="preserve">
|
||||
<value>Copying path {0} has failed, it will now be deleted for consistency</value>
|
||||
<comment>parameter: targetPath</comment>
|
||||
</data>
|
||||
<data name="filesfolder_removefolder_failed" xml:space="preserve">
|
||||
<value>Not able to delete folder {0}, please go to the location and manually delete it</value>
|
||||
<comment>parameter: path</comment>
|
||||
</data>
|
||||
<data name="filesfolder_verifybothfolderfilesequal_failed" xml:space="preserve">
|
||||
<value>Unable to verify folders and files between {0} and {1}</value>
|
||||
<comment>paramaters: fromPath, toPath</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mono.Collections.Generic;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
@@ -18,7 +19,7 @@ namespace Wox.Plugin
|
||||
/// Initializes a new instance of the <see cref="Query"/> class.
|
||||
/// to allow unit tests for plug ins
|
||||
/// </summary>
|
||||
public Query(string rawQuery, string search, string[] terms, string actionKeyword = "")
|
||||
public Query(string rawQuery, string search, ReadOnlyCollection<string> terms, string actionKeyword = "")
|
||||
{
|
||||
Search = search;
|
||||
RawQuery = rawQuery;
|
||||
@@ -41,9 +42,9 @@ namespace Wox.Plugin
|
||||
public string Search { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the raw query splited into a string array.
|
||||
/// Gets the raw query splited into a string array.
|
||||
/// </summary>
|
||||
public string[] Terms { get; set; }
|
||||
public ReadOnlyCollection<string> Terms { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Query can be splited into multiple terms by whitespace
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
@@ -16,6 +17,7 @@ namespace Wox.Plugin
|
||||
private ToolTipData _toolTipData;
|
||||
private string _pluginDirectory;
|
||||
private string _icoPath;
|
||||
private IList<int> _titleHighlightData;
|
||||
|
||||
public string Title
|
||||
{
|
||||
@@ -26,7 +28,13 @@ namespace Wox.Plugin
|
||||
|
||||
set
|
||||
{
|
||||
_title = value.Replace("\n", " ");
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
// Using Ordinal since this is used internally
|
||||
_title = value.Replace("\n", " ", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,15 +98,32 @@ namespace Wox.Plugin
|
||||
|
||||
public int Score { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public IList<int> TitleHighlightData { get; set; }
|
||||
public Result(IList<int> titleHighlightData = null, IList<int> subTitleHighlightData = null)
|
||||
{
|
||||
_titleHighlightData = titleHighlightData;
|
||||
SubTitleHighlightData = subTitleHighlightData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of indexes for the characters to be highlighted in SubTitle
|
||||
/// Gets a list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public IList<int> SubTitleHighlightData { get; set; }
|
||||
public IList<int> GetTitleHighlightData()
|
||||
{
|
||||
return _titleHighlightData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public void SetTitleHighlightData(IList<int> value)
|
||||
{
|
||||
_titleHighlightData = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of indexes for the characters to be highlighted in SubTitle
|
||||
/// </summary>
|
||||
public IList<int> SubTitleHighlightData { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets only results that originQuery match with current query will be displayed in the panel
|
||||
@@ -129,10 +154,11 @@ namespace Wox.Plugin
|
||||
{
|
||||
var r = obj as Result;
|
||||
|
||||
var equality = string.Equals(r?.Title, Title) &&
|
||||
string.Equals(r?.SubTitle, SubTitle) &&
|
||||
string.Equals(r?.IcoPath, IcoPath) &&
|
||||
TitleHighlightData == r.TitleHighlightData &&
|
||||
// Using Ordinal since this is used internally
|
||||
var equality = string.Equals(r?.Title, Title, StringComparison.Ordinal) &&
|
||||
string.Equals(r?.SubTitle, SubTitle, StringComparison.Ordinal) &&
|
||||
string.Equals(r?.IcoPath, IcoPath, StringComparison.Ordinal) &&
|
||||
GetTitleHighlightData() == r.GetTitleHighlightData() &&
|
||||
SubTitleHighlightData == r.SubTitleHighlightData;
|
||||
|
||||
return equality;
|
||||
@@ -140,18 +166,16 @@ namespace Wox.Plugin
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashcode = (Title?.GetHashCode() ?? 0) ^
|
||||
(SubTitle?.GetHashCode() ?? 0);
|
||||
// Using Ordinal since this is used internally
|
||||
var hashcode = (Title?.GetHashCode(StringComparison.Ordinal) ?? 0) ^
|
||||
(SubTitle?.GetHashCode(StringComparison.Ordinal) ?? 0);
|
||||
return hashcode;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} : {1}", Title, SubTitle);
|
||||
}
|
||||
|
||||
public Result()
|
||||
{
|
||||
// Using CurrentCulture since this is user facing
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0} : {1}", Title, SubTitle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,7 +9,12 @@ namespace Wox.Plugin
|
||||
{
|
||||
public class ResultUpdatedEventArgs : EventArgs
|
||||
{
|
||||
public List<Result> Results { get; set; }
|
||||
public List<Result> Results { get; private set; }
|
||||
|
||||
public ResultUpdatedEventArgs(List<Result> results = null)
|
||||
{
|
||||
Results = results;
|
||||
}
|
||||
|
||||
public Query Query { get; set; }
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Wox.Plugin.Logger;
|
||||
using Wox.Plugin.Properties;
|
||||
|
||||
namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
@@ -56,9 +58,10 @@ namespace Wox.Plugin.SharedCommands
|
||||
string error = $"Copying path {targetPath} has failed";
|
||||
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#if DEBUG
|
||||
throw e;
|
||||
throw;
|
||||
#else
|
||||
System.Windows.MessageBox.Show(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath));
|
||||
// Using CurrentCulture since this is user facing
|
||||
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_copy_failed, targetPath));
|
||||
RemoveFolder(targetPath);
|
||||
#endif
|
||||
}
|
||||
@@ -91,9 +94,10 @@ namespace Wox.Plugin.SharedCommands
|
||||
string error = $"Unable to verify folders and files between {fromPath} and {toPath}";
|
||||
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#if DEBUG
|
||||
throw e;
|
||||
throw;
|
||||
#else
|
||||
System.Windows.MessageBox.Show(string.Format(error));
|
||||
// Using CurrentCulture since this is user facing
|
||||
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_verifybothfolderfilesequal_failed, fromPath, toPath));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -113,12 +117,13 @@ namespace Wox.Plugin.SharedCommands
|
||||
catch (Exception e)
|
||||
#pragma warning restore CS0168 // Variable is declared but never used
|
||||
{
|
||||
string error = $"Not able to delete folder {path}, please go to the location and manually delete it";
|
||||
string error = $"Not able to delete folder {path}";
|
||||
Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType);
|
||||
#if DEBUG
|
||||
throw e;
|
||||
throw;
|
||||
#else
|
||||
System.Windows.MessageBox.Show(string.Format(error));
|
||||
// Using CurrentCulture since this is user facing
|
||||
System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_removefolder_failed, path));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static Wox.Plugin.SharedCommands.ShellCommand;
|
||||
|
||||
namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetWindowTextLength(IntPtr hwnd);
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,13 @@ namespace Wox.Plugin.SharedCommands
|
||||
/// Opens search in a new browser. If no browser path is passed in then Chrome is used.
|
||||
/// Leave browser path blank to use Chrome.
|
||||
/// </summary>
|
||||
public static void NewBrowserWindow(this string url, string browserPath)
|
||||
public static void NewBrowserWindow(this Uri url, string browserPath)
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
}
|
||||
|
||||
var browserExecutableName = browserPath?
|
||||
.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None)
|
||||
.Last();
|
||||
@@ -24,7 +29,7 @@ namespace Wox.Plugin.SharedCommands
|
||||
var browser = string.IsNullOrEmpty(browserExecutableName) ? "chrome" : browserPath;
|
||||
|
||||
// Internet Explorer will open url in new browser window, and does not take the --new-window parameter
|
||||
var browserArguments = browserExecutableName == "iexplore.exe" ? url : "--new-window " + url;
|
||||
var browserArguments = browserExecutableName == "iexplore.exe" ? url.AbsoluteUri : "--new-window " + url.AbsoluteUri;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -34,7 +39,7 @@ namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = url,
|
||||
FileName = url.AbsoluteUri,
|
||||
UseShellExecute = true,
|
||||
};
|
||||
Process.Start(psi);
|
||||
@@ -44,24 +49,29 @@ namespace Wox.Plugin.SharedCommands
|
||||
/// <summary>
|
||||
/// Opens search as a tab in the default browser chosen in Windows settings.
|
||||
/// </summary>
|
||||
public static void NewTabInBrowser(this string url, string browserPath)
|
||||
public static void NewTabInBrowser(this Uri url, string browserPath)
|
||||
{
|
||||
if (url == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(url));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(browserPath))
|
||||
{
|
||||
Process.Start(browserPath, url);
|
||||
Process.Start(browserPath, url.AbsoluteUri);
|
||||
}
|
||||
else
|
||||
{
|
||||
Process.Start(url);
|
||||
Process.Start(url.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
|
||||
// This error may be thrown for Process.Start(browserPath, url)
|
||||
catch (System.ComponentModel.Win32Exception)
|
||||
{
|
||||
Process.Start(url);
|
||||
Process.Start(url.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
@@ -14,19 +13,15 @@ namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetWindowTextLength(IntPtr hwnd);
|
||||
|
||||
private static bool containsSecurityWindow;
|
||||
|
||||
public static Process RunAsDifferentUser(ProcessStartInfo processStartInfo)
|
||||
{
|
||||
if (processStartInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(processStartInfo));
|
||||
}
|
||||
|
||||
processStartInfo.Verb = "RunAsUser";
|
||||
var process = Process.Start(processStartInfo);
|
||||
|
||||
@@ -55,7 +50,7 @@ namespace Wox.Plugin.SharedCommands
|
||||
ProcessThreadCollection ptc = Process.GetCurrentProcess().Threads;
|
||||
for (int i = 0; i < ptc.Count; i++)
|
||||
{
|
||||
EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero);
|
||||
NativeMethods.EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +66,8 @@ namespace Wox.Plugin.SharedCommands
|
||||
|
||||
private static string GetWindowTitle(IntPtr hwnd)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(GetWindowTextLength(hwnd) + 1);
|
||||
GetWindowText(hwnd, sb, sb.Capacity);
|
||||
StringBuilder sb = new StringBuilder(NativeMethods.GetWindowTextLength(hwnd) + 1);
|
||||
_ = NativeMethods.GetWindowText(hwnd, sb, sb.Capacity);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Wox.Plugin
|
||||
private const string HighContrastWhiteTheme = "HighContrast.Accent5";
|
||||
|
||||
private Theme currentTheme;
|
||||
private bool _disposed = false;
|
||||
private bool _disposed;
|
||||
|
||||
public event ThemeChangedHandler ThemeChanged;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Wox.Plugin
|
||||
{
|
||||
if (string.IsNullOrEmpty(title))
|
||||
{
|
||||
throw new ArgumentException("title cannot be null or empty", "title");
|
||||
throw new ArgumentException("title cannot be null or empty", nameof(title));
|
||||
}
|
||||
|
||||
Title = title;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<Platforms>x64</Platforms>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -68,6 +69,10 @@
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.3.0" />
|
||||
<PackageReference Include="ControlzEx" Version="4.3.2" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.5" />
|
||||
@@ -96,4 +101,17 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Plugin;
|
||||
@@ -26,7 +27,7 @@ namespace Wox.Test
|
||||
// Arrange
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { ">" } } } },
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata(new List<string> { ">" } ) } },
|
||||
};
|
||||
string searchQuery = "> file.txt file2 file3";
|
||||
|
||||
@@ -43,7 +44,7 @@ namespace Wox.Test
|
||||
// Arrange
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { ">" }, Disabled = true } } },
|
||||
{ ">", new PluginPair { Metadata = new PluginMetadata(new List<string> { ">" }) { Disabled = true } } },
|
||||
};
|
||||
string searchQuery = "> file.txt file2 file3";
|
||||
|
||||
@@ -72,7 +73,7 @@ namespace Wox.Test
|
||||
{
|
||||
// Arrange
|
||||
string searchQuery = "> query";
|
||||
var firstPlugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { ">" } } };
|
||||
var firstPlugin = new PluginPair { Metadata = new PluginMetadata(new List<string> { ">" } ) };
|
||||
var secondPlugin = new PluginPair { Metadata = new PluginMetadata { ActionKeyword = ">" } };
|
||||
|
||||
var nonGlobalPluginWithActionKeywords = new Dictionary<string, PluginPair>
|
||||
@@ -85,7 +86,7 @@ namespace Wox.Test
|
||||
{ ">", secondPlugin },
|
||||
};
|
||||
string[] terms = { ">", "query" };
|
||||
Query expectedQuery = new Query("> query", "query", terms, ">");
|
||||
Query expectedQuery = new Query("> query", "query", new ReadOnlyCollection<string>(terms), ">");
|
||||
|
||||
// Act
|
||||
var queriesForPluginsWithActionKeywords = QueryBuilder.Build(ref searchQuery, nonGlobalPluginWithActionKeywords);
|
||||
@@ -103,7 +104,7 @@ namespace Wox.Test
|
||||
public void QueryBuilderShouldGenerateCorrectQueriesForPluginsWithMultipleActionKeywords()
|
||||
{
|
||||
// Arrange
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { "a", "b" } } };
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata(new List<string> { "a", "b" } ) };
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ "a", plugin },
|
||||
@@ -129,7 +130,7 @@ namespace Wox.Test
|
||||
public void QueryBuildShouldGenerateSameSearchQueryWithOrWithoutSpaceAfterActionKeyword()
|
||||
{
|
||||
// Arrange
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List<string> { "a" } } };
|
||||
var plugin = new PluginPair { Metadata = new PluginMetadata(new List<string> { "a" } ) };
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{ "a", plugin },
|
||||
@@ -198,8 +199,8 @@ namespace Wox.Test
|
||||
|
||||
// Assert
|
||||
// Using Ordinal since this is used internally
|
||||
Assert.IsTrue(firstQuery.Terms[0].Equals("cd", StringComparison.Ordinal) && firstQuery.Terms[1].Equals("efgh", StringComparison.Ordinal) && firstQuery.Terms.Length == 2);
|
||||
Assert.IsTrue(secondQuery.Terms[0].Equals("efgh", StringComparison.Ordinal) && secondQuery.Terms.Length == 1);
|
||||
Assert.IsTrue(firstQuery.Terms[0].Equals("cd", StringComparison.Ordinal) && firstQuery.Terms[1].Equals("efgh", StringComparison.Ordinal) && firstQuery.Terms.Count == 2);
|
||||
Assert.IsTrue(secondQuery.Terms[0].Equals("efgh", StringComparison.Ordinal) && secondQuery.Terms.Count == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user