Merge pull request #2648 from Yusyuriv/new-hotkey-control

Improve Hotkey System
This commit is contained in:
Jeremy Wu 2024-04-25 00:09:51 +10:00 committed by GitHub
commit 4ce591fa20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 2407 additions and 950 deletions

View file

@ -6,7 +6,7 @@ using System.Windows.Input;
namespace Flow.Launcher.Infrastructure.Hotkey namespace Flow.Launcher.Infrastructure.Hotkey
{ {
public class HotkeyModel public record struct HotkeyModel
{ {
public bool Alt { get; set; } public bool Alt { get; set; }
public bool Shift { get; set; } public bool Shift { get; set; }
@ -17,8 +17,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey
private static readonly Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string> private static readonly Dictionary<Key, string> specialSymbolDictionary = new Dictionary<Key, string>
{ {
{Key.Space, "Space"}, { Key.Space, "Space" }, { Key.Oem3, "~" }
{Key.Oem3, "~"}
}; };
public ModifierKeys ModifierKeys public ModifierKeys ModifierKeys
@ -30,18 +29,22 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{ {
modifierKeys |= ModifierKeys.Alt; modifierKeys |= ModifierKeys.Alt;
} }
if (Shift) if (Shift)
{ {
modifierKeys |= ModifierKeys.Shift; modifierKeys |= ModifierKeys.Shift;
} }
if (Win) if (Win)
{ {
modifierKeys |= ModifierKeys.Windows; modifierKeys |= ModifierKeys.Windows;
} }
if (Ctrl) if (Ctrl)
{ {
modifierKeys |= ModifierKeys.Control; modifierKeys |= ModifierKeys.Control;
} }
return modifierKeys; return modifierKeys;
} }
} }
@ -66,31 +69,37 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{ {
return; return;
} }
List<string> keys = hotkeyString.Replace(" ", "").Split('+').ToList(); List<string> keys = hotkeyString.Replace(" ", "").Split('+').ToList();
if (keys.Contains("Alt")) if (keys.Contains("Alt"))
{ {
Alt = true; Alt = true;
keys.Remove("Alt"); keys.Remove("Alt");
} }
if (keys.Contains("Shift")) if (keys.Contains("Shift"))
{ {
Shift = true; Shift = true;
keys.Remove("Shift"); keys.Remove("Shift");
} }
if (keys.Contains("Win")) if (keys.Contains("Win"))
{ {
Win = true; Win = true;
keys.Remove("Win"); keys.Remove("Win");
} }
if (keys.Contains("Ctrl")) if (keys.Contains("Ctrl"))
{ {
Ctrl = true; Ctrl = true;
keys.Remove("Ctrl"); keys.Remove("Ctrl");
} }
if (keys.Count == 1) if (keys.Count == 1)
{ {
string charKey = keys[0]; string charKey = keys[0];
KeyValuePair<Key, string>? specialSymbolPair = specialSymbolDictionary.FirstOrDefault(pair => pair.Value == charKey); KeyValuePair<Key, string>? specialSymbolPair =
specialSymbolDictionary.FirstOrDefault(pair => pair.Value == charKey);
if (specialSymbolPair.Value.Value != null) if (specialSymbolPair.Value.Value != null)
{ {
CharKey = specialSymbolPair.Value.Key; CharKey = specialSymbolPair.Value.Key;
@ -103,7 +112,6 @@ namespace Flow.Launcher.Infrastructure.Hotkey
} }
catch (ArgumentException) catch (ArgumentException)
{ {
} }
} }
} }
@ -111,33 +119,39 @@ namespace Flow.Launcher.Infrastructure.Hotkey
public override string ToString() public override string ToString()
{ {
List<string> keys = new List<string>(); return string.Join(" + ", EnumerateDisplayKeys());
if (Ctrl) }
public IEnumerable<string> EnumerateDisplayKeys()
{
if (Ctrl && CharKey is not (Key.LeftCtrl or Key.RightCtrl))
{ {
keys.Add("Ctrl"); yield return "Ctrl";
} }
if (Alt)
if (Alt && CharKey is not (Key.LeftAlt or Key.RightAlt))
{ {
keys.Add("Alt"); yield return "Alt";
} }
if (Shift)
if (Shift && CharKey is not (Key.LeftShift or Key.RightShift))
{ {
keys.Add("Shift"); yield return "Shift";
} }
if (Win)
if (Win && CharKey is not (Key.LWin or Key.RWin))
{ {
keys.Add("Win"); yield return "Win";
} }
if (CharKey != Key.None) if (CharKey != Key.None)
{ {
keys.Add(specialSymbolDictionary.ContainsKey(CharKey) yield return specialSymbolDictionary.TryGetValue(CharKey, out var value)
? specialSymbolDictionary[CharKey] ? value
: CharKey.ToString()); : CharKey.ToString();
} }
return string.Join(" + ", keys);
} }
/// <summary> /// <summary>
/// Validate hotkey /// Validate hotkey
/// </summary> /// </summary>
@ -164,11 +178,13 @@ namespace Flow.Launcher.Infrastructure.Hotkey
{ {
KeyGesture keyGesture = new KeyGesture(CharKey, ModifierKeys); KeyGesture keyGesture = new KeyGesture(CharKey, ModifierKeys);
} }
catch (System.Exception e) when (e is NotSupportedException || e is InvalidEnumArgumentException) catch (System.Exception e) when
(e is NotSupportedException || e is InvalidEnumArgumentException)
{ {
return false; return false;
} }
} }
if (ModifierKeys == ModifierKeys.None) if (ModifierKeys == ModifierKeys.None)
{ {
return !IsPrintableCharacter(CharKey); return !IsPrintableCharacter(CharKey);
@ -206,18 +222,6 @@ namespace Flow.Launcher.Infrastructure.Hotkey
key == Key.Decimal; key == Key.Decimal;
} }
public override bool Equals(object obj)
{
if (obj is HotkeyModel other)
{
return ModifierKeys == other.ModifierKeys && CharKey == other.CharKey;
}
else
{
return false;
}
}
public override int GetHashCode() public override int GetHashCode()
{ {
return HashCode.Combine(ModifierKeys, CharKey); return HashCode.Combine(ModifierKeys, CharKey);

View file

@ -20,6 +20,16 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool ShowOpenResultHotkey { get; set; } = true; public bool ShowOpenResultHotkey { get; set; } = true;
public double WindowSize { get; set; } = 580; public double WindowSize { get; set; } = 580;
public string PreviewHotkey { get; set; } = $"F1"; public string PreviewHotkey { get; set; } = $"F1";
public string AutoCompleteHotkey { get; set; } = $"{KeyConstant.Ctrl} + Tab";
public string AutoCompleteHotkey2 { get; set; } = $"";
public string SelectNextItemHotkey { get; set; } = $"Tab";
public string SelectNextItemHotkey2 { get; set; } = $"";
public string SelectPrevItemHotkey { get; set; } = $"Shift + Tab";
public string SelectPrevItemHotkey2 { get; set; } = $"";
public string SelectNextPageHotkey { get; set; } = $"";
public string SelectPrevPageHotkey { get; set; } = $"";
public string OpenContextMenuHotkey { get; set; } = $"Ctrl+O";
public string SettingWindowHotkey { get; set; } = $"Ctrl+I";
public string Language public string Language
{ {

View file

@ -2,10 +2,12 @@
x:Class="Flow.Launcher.CustomQueryHotkeySetting" x:Class="Flow.Launcher.CustomQueryHotkeySetting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flowlauncher="clr-namespace:Flow.Launcher" xmlns:flowlauncher="clr-namespace:Flow.Launcher"
Title="{DynamicResource customeQueryHotkeyTitle}" Title="{DynamicResource customeQueryHotkeyTitle}"
Width="530" Width="530"
Background="{DynamicResource PopuBGColor}" Background="{DynamicResource PopuBGColor}"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Foreground="{DynamicResource PopupTextColor}" Foreground="{DynamicResource PopupTextColor}"
Icon="Images\app.png" Icon="Images\app.png"
MouseDown="window_MouseDown" MouseDown="window_MouseDown"
@ -60,94 +62,75 @@
</Grid> </Grid>
</StackPanel> </StackPanel>
<StackPanel Margin="26,0,26,0"> <StackPanel Margin="26,0,26,0">
<StackPanel Grid.Row="0" Margin="0,0,0,12"> <TextBlock
<TextBlock Margin="0,0,0,12"
Grid.Column="0" FontSize="20"
Margin="0,0,0,0" FontWeight="SemiBold"
FontSize="20" Text="{DynamicResource customeQueryHotkeyTitle}"
FontWeight="SemiBold" TextAlignment="Left" />
Text="{DynamicResource customeQueryHotkeyTitle}" <TextBlock
TextAlignment="Left" /> FontSize="14"
</StackPanel> Text="{DynamicResource customeQueryHotkeyTips}"
<StackPanel> TextAlignment="Left"
<TextBlock TextWrapping="WrapWithOverflow" />
FontSize="14" <Image
Text="{DynamicResource customeQueryHotkeyTips}" Width="478"
TextAlignment="Left" Margin="0,20,0,0"
TextWrapping="WrapWithOverflow" /> Source="/Images/illustration_01.png" />
<Image
Width="478"
Margin="0,20,0,0"
Source="/Images/illustration_01.png" />
</StackPanel>
<StackPanel Margin="0,20,0,0" Orientation="Horizontal"> <Grid Width="478" Margin="0,20,0,0">
<Grid Width="478"> <Grid.RowDefinitions>
<Grid.RowDefinitions> <RowDefinition />
<RowDefinition /> <RowDefinition />
<RowDefinition /> </Grid.RowDefinitions>
</Grid.RowDefinitions> <Grid.ColumnDefinitions>
<Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0" <TextBlock
Grid.Column="0" Grid.Row="0"
Margin="10" Grid.Column="0"
HorizontalAlignment="Left" Margin="10"
VerticalAlignment="Center" HorizontalAlignment="Left"
FontSize="14" VerticalAlignment="Center"
Text="{DynamicResource hotkey}" /> FontSize="14"
<StackPanel Text="{DynamicResource hotkey}" />
Grid.Row="0" <flowlauncher:HotkeyControl
Grid.Column="1" x:Name="HotkeyControl"
Orientation="Horizontal"> Grid.Row="0"
<flowlauncher:HotkeyControl Grid.Column="1"
x:Name="ctlHotkey" Grid.ColumnSpan="2"
Grid.Column="1" Margin="10,0,10,0"
Width="200" HorizontalAlignment="Left"
Height="36" VerticalAlignment="Center"
Margin="10,0,10,0" HorizontalContentAlignment="Left"
HorizontalAlignment="Left" DefaultHotkey="" />
VerticalAlignment="Center" <TextBlock
HorizontalContentAlignment="Left" /> Grid.Row="1"
<TextBlock Grid.Column="0"
Grid.Row="1" Margin="10"
Grid.Column="0" HorizontalAlignment="Left"
Margin="10" VerticalAlignment="Center"
HorizontalAlignment="Left" FontSize="14"
VerticalAlignment="Center" Text="{DynamicResource customQuery}" />
FontSize="14" <TextBox
Text="{DynamicResource actionKeyword}" /> x:Name="tbAction"
</StackPanel> Grid.Row="1"
<TextBlock Grid.Column="1"
Grid.Row="1" Margin="10"
Grid.Column="0" HorizontalAlignment="Stretch"
Margin="10" VerticalAlignment="Center" />
HorizontalAlignment="Left" <Button
VerticalAlignment="Center" x:Name="btnTestActionKeyword"
FontSize="14" Grid.Row="1"
Text="{DynamicResource customQuery}" /> Grid.Column="2"
<DockPanel Margin="0,0,10,0"
Grid.Row="1" Padding="10,5,10,5"
Grid.Column="1" Click="BtnTestActionKeyword_OnClick"
LastChildFill="True"> Content="{DynamicResource preview}" />
<Button </Grid>
x:Name="btnTestActionKeyword"
Margin="0,0,10,0"
Padding="10,5,10,5"
Click="BtnTestActionKeyword_OnClick"
Content="{DynamicResource preview}"
DockPanel.Dock="Right" />
<TextBox
x:Name="tbAction"
Margin="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Center" />
</DockPanel>
</Grid>
</StackPanel>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<Border <Border
@ -174,4 +157,4 @@
</StackPanel> </StackPanel>
</Border> </Border>
</Grid> </Grid>
</Window> </Window>

View file

@ -6,6 +6,7 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Controls; using System.Windows.Controls;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -32,21 +33,11 @@ namespace Flow.Launcher
{ {
if (!update) if (!update)
{ {
if (!ctlHotkey.CurrentHotkeyAvailable) _settings.CustomPluginHotkeys ??= new ObservableCollection<CustomPluginHotkey>();
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("hotkeyIsNotUnavailable"));
return;
}
if (_settings.CustomPluginHotkeys == null)
{
_settings.CustomPluginHotkeys = new ObservableCollection<CustomPluginHotkey>();
}
var pluginHotkey = new CustomPluginHotkey var pluginHotkey = new CustomPluginHotkey
{ {
Hotkey = ctlHotkey.CurrentHotkey.ToString(), Hotkey = HotkeyControl.CurrentHotkey.ToString(), ActionKeyword = tbAction.Text
ActionKeyword = tbAction.Text
}; };
_settings.CustomPluginHotkeys.Add(pluginHotkey); _settings.CustomPluginHotkeys.Add(pluginHotkey);
@ -54,14 +45,9 @@ namespace Flow.Launcher
} }
else else
{ {
if (updateCustomHotkey.Hotkey != ctlHotkey.CurrentHotkey.ToString() && !ctlHotkey.CurrentHotkeyAvailable)
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("hotkeyIsNotUnavailable"));
return;
}
var oldHotkey = updateCustomHotkey.Hotkey; var oldHotkey = updateCustomHotkey.Hotkey;
updateCustomHotkey.ActionKeyword = tbAction.Text; updateCustomHotkey.ActionKeyword = tbAction.Text;
updateCustomHotkey.Hotkey = ctlHotkey.CurrentHotkey.ToString(); updateCustomHotkey.Hotkey = HotkeyControl.CurrentHotkey.ToString();
//remove origin hotkey //remove origin hotkey
HotKeyMapper.RemoveHotkey(oldHotkey); HotKeyMapper.RemoveHotkey(oldHotkey);
HotKeyMapper.SetCustomQueryHotkey(updateCustomHotkey); HotKeyMapper.SetCustomQueryHotkey(updateCustomHotkey);
@ -70,9 +56,11 @@ namespace Flow.Launcher
Close(); Close();
} }
public void UpdateItem(CustomPluginHotkey item) public void UpdateItem(CustomPluginHotkey item)
{ {
updateCustomHotkey = _settings.CustomPluginHotkeys.FirstOrDefault(o => o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); updateCustomHotkey = _settings.CustomPluginHotkeys.FirstOrDefault(o =>
o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey);
if (updateCustomHotkey == null) if (updateCustomHotkey == null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey"));
@ -81,7 +69,7 @@ namespace Flow.Launcher
} }
tbAction.Text = updateCustomHotkey.ActionKeyword; tbAction.Text = updateCustomHotkey.ActionKeyword;
_ = ctlHotkey.SetHotkeyAsync(updateCustomHotkey.Hotkey, false); HotkeyControl.SetHotkey(updateCustomHotkey.Hotkey, false);
update = true; update = true;
lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update"); lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update");
} }
@ -101,12 +89,10 @@ namespace Flow.Launcher
private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */
{ {
TextBox textBox = Keyboard.FocusedElement as TextBox; if (Keyboard.FocusedElement is not TextBox textBox) return;
if (textBox != null)
{ TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next);
TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next); textBox.MoveFocus(tRequest);
textBox.MoveFocus(tRequest);
}
} }
} }
} }

View file

@ -3,54 +3,75 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="24"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid> <Button
<Grid.ColumnDefinitions> Width="Auto"
<ColumnDefinition Width="200" /> FontSize="13"
</Grid.ColumnDefinitions> FontWeight="Bold"
<Popup Foreground="{DynamicResource Color01B}"
x:Name="popup" Click="GetNewHotkey">
AllowDrop="True" <Button.Template>
AllowsTransparency="True" <ControlTemplate TargetType="Button">
IsOpen="{Binding IsKeyboardFocused, ElementName=tbHotkey, Mode=OneWay}" <Border
Placement="Top" x:Name="ButtonBorder"
PlacementTarget="{Binding ElementName=tbHotkey}" Padding="5,0,5,0"
PopupAnimation="Fade" Background="{DynamicResource ButtonBackgroundColor}"
StaysOpen="True" BorderBrush="{DynamicResource ButtonInsideBorder}"
VerticalOffset="-5"> BorderThickness="1"
<Border CornerRadius="5">
Width="140" <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
Height="30" </Border>
Background="{DynamicResource Color01B}" <ControlTemplate.Triggers>
BorderBrush="{DynamicResource Color21B}" <MultiTrigger>
BorderThickness="1" <MultiTrigger.Conditions>
CornerRadius="4"> <Condition Property="IsMouseOver" Value="True" />
<TextBlock <Condition Property="IsPressed" Value="True" />
x:Name="tbMsg" </MultiTrigger.Conditions>
Margin="0,0,0,0" <Setter TargetName="ButtonBorder" Property="Background"
HorizontalAlignment="Center" Value="{DynamicResource ButtonMousePressed}" />
VerticalAlignment="Center" <Setter TargetName="ButtonBorder" Property="BorderBrush"
FontSize="13" Value="{DynamicResource ButtonMousePressedInsideBorder}" />
FontWeight="SemiBold" </MultiTrigger>
Foreground="{DynamicResource Color05B}" <MultiTrigger>
Text="{DynamicResource flowlauncherPressHotkey}" <MultiTrigger.Conditions>
Visibility="Visible" /> <Condition Property="IsMouseOver" Value="True" />
</Border> </MultiTrigger.Conditions>
</Popup> <Setter TargetName="ButtonBorder" Property="Background"
Value="{DynamicResource ButtonMouseOver}" />
<TextBox </MultiTrigger>
x:Name="tbHotkey" <MultiTrigger>
Margin="0,0,18,0" <MultiTrigger.Conditions>
VerticalContentAlignment="Center" <Condition Property="IsPressed" Value="True" />
input:InputMethod.IsInputMethodEnabled="False" </MultiTrigger.Conditions>
GotFocus="tbHotkey_GotFocus" <Setter TargetName="ButtonBorder" Property="Background"
LostFocus="tbHotkey_LostFocus" Value="{DynamicResource ButtonMousePressed}" />
PreviewKeyDown="TbHotkey_OnPreviewKeyDown" <Setter TargetName="ButtonBorder" Property="BorderBrush"
TabIndex="100" /> Value="{DynamicResource CustomContextHover}" />
</Grid> </MultiTrigger>
</UserControl> </ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
<Button.Content>
<ItemsControl x:Name="HotkeyList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
Margin="2,5,2,5"
Padding="10,5,10,5"
Background="{DynamicResource AccentButtonBackground}"
BorderThickness="1"
CornerRadius="5">
<TextBlock Text="{Binding}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Button.Content>
</Button>
</UserControl>

View file

@ -1,141 +1,193 @@
using System; #nullable enable
using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper; using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using System.Threading;
namespace Flow.Launcher namespace Flow.Launcher
{ {
public partial class HotkeyControl : UserControl public partial class HotkeyControl
{ {
public HotkeyModel CurrentHotkey { get; private set; } public string WindowTitle {
public bool CurrentHotkeyAvailable { get; private set; } get { return (string)GetValue(WindowTitleProperty); }
set { SetValue(WindowTitleProperty, value); }
}
public event EventHandler HotkeyChanged; public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register(
nameof(WindowTitle),
typeof(string),
typeof(HotkeyControl),
new PropertyMetadata(string.Empty)
);
/// <summary> /// <summary>
/// Designed for Preview Hotkey and KeyGesture. /// Designed for Preview Hotkey and KeyGesture.
/// </summary> /// </summary>
public bool ValidateKeyGesture { get; set; } = false; public static readonly DependencyProperty ValidateKeyGestureProperty = DependencyProperty.Register(
nameof(ValidateKeyGesture),
typeof(bool),
typeof(HotkeyControl),
new PropertyMetadata(default(bool))
);
protected virtual void OnHotkeyChanged() => HotkeyChanged?.Invoke(this, EventArgs.Empty); public bool ValidateKeyGesture
public HotkeyControl()
{ {
InitializeComponent(); get { return (bool)GetValue(ValidateKeyGestureProperty); }
set { SetValue(ValidateKeyGestureProperty, value); }
} }
private CancellationTokenSource hotkeyUpdateSource; public static readonly DependencyProperty DefaultHotkeyProperty = DependencyProperty.Register(
nameof(DefaultHotkey),
typeof(string),
typeof(HotkeyControl),
new PropertyMetadata(default(string))
);
private void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e) public string DefaultHotkey
{ {
hotkeyUpdateSource?.Cancel(); get { return (string)GetValue(DefaultHotkeyProperty); }
hotkeyUpdateSource?.Dispose(); set { SetValue(DefaultHotkeyProperty, value); }
hotkeyUpdateSource = new(); }
var token = hotkeyUpdateSource.Token;
e.Handled = true;
//when alt is pressed, the real key should be e.SystemKey private static void OnHotkeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
Key key = e.Key == Key.System ? e.SystemKey : e.Key; {
if (d is not HotkeyControl hotkeyControl)
SpecialKeyState specialKeyState = GlobalHotkey.CheckModifiers();
var hotkeyModel = new HotkeyModel(
specialKeyState.AltPressed,
specialKeyState.ShiftPressed,
specialKeyState.WinPressed,
specialKeyState.CtrlPressed,
key);
if (hotkeyModel.Equals(CurrentHotkey))
{ {
return; return;
} }
_ = Dispatcher.InvokeAsync(async () => hotkeyControl.SetKeysToDisplay(new HotkeyModel(hotkeyControl.Hotkey));
{ hotkeyControl.CurrentHotkey = new HotkeyModel(hotkeyControl.Hotkey);
await Task.Delay(500, token);
if (!token.IsCancellationRequested)
await SetHotkeyAsync(hotkeyModel);
});
} }
public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true)
{
tbHotkey.Text = keyModel.ToString();
tbHotkey.Select(tbHotkey.Text.Length, 0);
public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register(
nameof(ChangeHotkey),
typeof(ICommand),
typeof(HotkeyControl),
new PropertyMetadata(default(ICommand))
);
public ICommand? ChangeHotkey
{
get { return (ICommand)GetValue(ChangeHotkeyProperty); }
set { SetValue(ChangeHotkeyProperty, value); }
}
public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register(
nameof(Hotkey),
typeof(string),
typeof(HotkeyControl),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHotkeyChanged)
);
public string Hotkey
{
get { return (string)GetValue(HotkeyProperty); }
set { SetValue(HotkeyProperty, value); }
}
public HotkeyControl()
{
InitializeComponent();
HotkeyList.ItemsSource = KeysToDisplay;
SetKeysToDisplay(CurrentHotkey);
}
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) =>
hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
public string EmptyHotkey => InternationalizationManager.Instance.GetTranslation("none");
public ObservableCollection<string> KeysToDisplay { get; set; } = new();
public HotkeyModel CurrentHotkey { get; private set; } = new(false, false, false, false, Key.None);
public void GetNewHotkey(object sender, RoutedEventArgs e)
{
OpenHotkeyDialog();
}
private async Task OpenHotkeyDialog()
{
if (!string.IsNullOrEmpty(Hotkey))
{
HotKeyMapper.RemoveHotkey(Hotkey);
}
var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle);
await dialog.ShowAsync();
switch (dialog.ResultType)
{
case HotkeyControlDialog.EResultType.Cancel:
SetHotkey(Hotkey);
return;
case HotkeyControlDialog.EResultType.Save:
SetHotkey(dialog.ResultValue);
break;
case HotkeyControlDialog.EResultType.Delete:
Delete();
break;
}
}
private void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true)
{
if (triggerValidate) if (triggerValidate)
{ {
bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture); bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture);
CurrentHotkeyAvailable = hotkeyAvailable;
SetMessage(hotkeyAvailable);
OnHotkeyChanged();
var token = hotkeyUpdateSource.Token; if (!hotkeyAvailable)
await Task.Delay(500, token);
if (token.IsCancellationRequested)
return;
if (CurrentHotkeyAvailable)
{ {
CurrentHotkey = keyModel; return;
// To trigger LostFocus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null);
Keyboard.ClearFocus();
} }
Hotkey = keyModel.ToString();
SetKeysToDisplay(CurrentHotkey);
ChangeHotkey?.Execute(keyModel);
} }
else else
{ {
CurrentHotkey = keyModel; Hotkey = keyModel.ToString();
ChangeHotkey?.Execute(keyModel);
} }
} }
public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true) public void Delete()
{ {
return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate); if (!string.IsNullOrEmpty(Hotkey))
HotKeyMapper.RemoveHotkey(Hotkey);
Hotkey = "";
SetKeysToDisplay(new HotkeyModel(false, false, false, false, Key.None));
} }
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); private void SetKeysToDisplay(HotkeyModel? hotkey)
public new bool IsFocused => tbHotkey.IsFocused;
private void tbHotkey_LostFocus(object sender, RoutedEventArgs e)
{ {
tbHotkey.Text = CurrentHotkey?.ToString() ?? ""; KeysToDisplay.Clear();
tbHotkey.Select(tbHotkey.Text.Length, 0);
}
private void tbHotkey_GotFocus(object sender, RoutedEventArgs e) if (hotkey == null || hotkey == default(HotkeyModel))
{
ResetMessage();
}
private void ResetMessage()
{
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("flowlauncherPressHotkey");
tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B");
}
private void SetMessage(bool hotkeyAvailable)
{
if (!hotkeyAvailable)
{ {
tbMsg.Foreground = new SolidColorBrush(Colors.Red); KeysToDisplay.Add(EmptyHotkey);
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable"); return;
} }
else
foreach (var key in hotkey.Value.EnumerateDisplayKeys()!)
{ {
tbMsg.Foreground = new SolidColorBrush(Colors.Green); KeysToDisplay.Add(key);
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("success");
} }
tbMsg.Visibility = Visibility.Visible; }
public void SetHotkey(string? keyStr, bool triggerValidate = true)
{
SetHotkey(new HotkeyModel(keyStr), triggerValidate);
} }
} }
} }

View file

@ -0,0 +1,153 @@
<ui:ContentDialog
x:Class="Flow.Launcher.HotkeyControlDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.modernwpf.com/2019"
Background="{DynamicResource PopuBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0"
CornerRadius="8"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Foreground="{DynamicResource PopupTextColor}"
PreviewKeyDown="OnPreviewKeyDown"
Style="{DynamicResource ContentDialog}">
<ui:ContentDialog.Resources>
<Thickness x:Key="ContentDialogPadding">0</Thickness>
<Thickness x:Key="ContentDialogTitleMargin">0</Thickness>
</ui:ContentDialog.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<!-- Window title and the keys in the hotkey -->
<Grid Grid.Row="0" Margin="26,12,26,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel>
<TextBlock
Margin="0,0,0,0"
FontSize="20"
FontWeight="SemiBold"
Text="{Binding WindowTitle}"
TextAlignment="Left" />
<TextBlock FontSize="14" Text="{DynamicResource hotkeyRegGuide}" />
</StackPanel>
<Border
Grid.Row="1"
Width="450"
Height="100"
Margin="0,100,0,0"
Padding="26,12,26,0">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<ItemsControl ItemsSource="{Binding KeysToDisplay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
MinWidth="50"
MinHeight="50"
Margin="5,0,5,0"
Padding="8"
Background="{DynamicResource AccentButtonBackground}"
CornerRadius="6">
<TextBlock
Margin="5,0,5,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="{DynamicResource Color01B}"
Text="{Binding}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
<!-- Warning message for when something went wrong with the new hotkey. -->
<Border Grid.Row="1">
<Border
x:Name="Alert"
Width="420"
Height="50"
HorizontalAlignment="Center"
Background="{DynamicResource InfoBarWarningBG}"
BorderBrush="{DynamicResource InfoBarBD}"
BorderThickness="1"
CornerRadius="5"
Visibility="Collapsed">
<Grid VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<ui:FontIcon
Margin="20,0,14,0"
VerticalAlignment="Center"
FontSize="15"
Foreground="{DynamicResource InfoBarWarningIcon}"
Glyph="&#xf167;" />
<TextBlock
x:Name="tbMsg"
Margin="0,0,0,2"
HorizontalAlignment="Left"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}" />
</StackPanel>
</Grid>
</Border>
</Border>
<!-- Action buttons at the bottom of the dialog -->
<Border
Grid.Row="2"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0"
CornerRadius="0 0 8 8">
<StackPanel
Margin="10"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
x:Name="SaveBtn"
Height="30"
MinWidth="100"
Margin="0,0,4,0"
Click="Save"
Content="{DynamicResource commonSave}"
Style="{StaticResource AccentButtonStyle}" />
<Button
Height="30"
MinWidth="100"
Margin="4,0,4,0"
Click="Reset"
Content="{DynamicResource commonReset}" />
<Button
Height="30"
MinWidth="100"
Margin="4,0,4,0"
Click="Delete"
Content="{DynamicResource commonDelete}" />
<Button
Height="30"
MinWidth="100"
Margin="4,0,0,0"
Click="Cancel"
Content="{DynamicResource commonCancel}" />
</StackPanel>
</Border>
</Grid>
</ui:ContentDialog>

View file

@ -0,0 +1,127 @@
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using ModernWpf.Controls;
namespace Flow.Launcher;
public partial class HotkeyControlDialog : ContentDialog
{
private string DefaultHotkey { get; }
public string WindowTitle { get; }
public HotkeyModel CurrentHotkey { get; private set; }
public ObservableCollection<string> KeysToDisplay { get; } = new();
public enum EResultType
{
Cancel,
Save,
Delete
}
public EResultType ResultType { get; private set; } = EResultType.Cancel;
public string ResultValue { get; private set; } = string.Empty;
public static string EmptyHotkey => InternationalizationManager.Instance.GetTranslation("none");
public HotkeyControlDialog(string hotkey, string defaultHotkey, string windowTitle = "")
{
WindowTitle = windowTitle switch
{
"" or null => InternationalizationManager.Instance.GetTranslation("hotkeyRegTitle"),
_ => windowTitle
};
DefaultHotkey = defaultHotkey;
CurrentHotkey = new HotkeyModel(hotkey);
SetKeysToDisplay(CurrentHotkey);
InitializeComponent();
}
private void Reset(object sender, RoutedEventArgs routedEventArgs)
{
SetKeysToDisplay(new HotkeyModel(DefaultHotkey));
}
private void Delete(object sender, RoutedEventArgs routedEventArgs)
{
KeysToDisplay.Clear();
KeysToDisplay.Add(EmptyHotkey);
}
private void Cancel(object sender, RoutedEventArgs routedEventArgs)
{
ResultType = EResultType.Cancel;
Hide();
}
private void Save(object sender, RoutedEventArgs routedEventArgs)
{
if (KeysToDisplay.Count == 1 && KeysToDisplay[0] == EmptyHotkey)
{
ResultType = EResultType.Delete;
Hide();
return;
}
ResultType = EResultType.Save;
ResultValue = string.Join("+", KeysToDisplay);
Hide();
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
//when alt is pressed, the real key should be e.SystemKey
Key key = e.Key == Key.System ? e.SystemKey : e.Key;
SpecialKeyState specialKeyState = GlobalHotkey.CheckModifiers();
var hotkeyModel = new HotkeyModel(
specialKeyState.AltPressed,
specialKeyState.ShiftPressed,
specialKeyState.WinPressed,
specialKeyState.CtrlPressed,
key);
CurrentHotkey = hotkeyModel;
SetKeysToDisplay(CurrentHotkey);
}
private void SetKeysToDisplay(HotkeyModel? hotkey)
{
KeysToDisplay.Clear();
if (hotkey == null || hotkey == default(HotkeyModel))
{
KeysToDisplay.Add(EmptyHotkey);
return;
}
foreach (var key in hotkey.Value.EnumerateDisplayKeys()!)
{
KeysToDisplay.Add(key);
}
if (tbMsg == null)
return;
if (!CheckHotkeyAvailability(hotkey.Value, true))
{
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable");
Alert.Visibility = Visibility.Visible;
SaveBtn.IsEnabled = false;
}
else
{
Alert.Visibility = Visibility.Collapsed;
SaveBtn.IsEnabled = true;
}
}
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) =>
hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
}

View file

@ -172,14 +172,34 @@
<!-- Setting Hotkey --> <!-- Setting Hotkey -->
<system:String x:Key="hotkey">Hotkey</system:String> <system:String x:Key="hotkey">Hotkey</system:String>
<system:String x:Key="hotkeys">Hotkeys</system:String> <system:String x:Key="hotkeys">Hotkeys</system:String>
<system:String x:Key="flowlauncherHotkey">Flow Launcher Hotkey</system:String> <system:String x:Key="flowlauncherHotkey">Open Flow Launcher</system:String>
<system:String x:Key="flowlauncherHotkeyToolTip">Enter shortcut to show/hide Flow Launcher.</system:String> <system:String x:Key="flowlauncherHotkeyToolTip">Enter shortcut to show/hide Flow Launcher.</system:String>
<system:String x:Key="previewHotkey">Preview Hotkey</system:String> <system:String x:Key="previewHotkey">Toggle Preview</system:String>
<system:String x:Key="previewHotkeyToolTip">Enter shortcut to show/hide preview in search window.</system:String> <system:String x:Key="previewHotkeyToolTip">Enter shortcut to show/hide preview in search window.</system:String>
<system:String x:Key="hotkeyPresets">Hotkey Presets</system:String>
<system:String x:Key="hotkeyPresetsToolTip">List of currently registered hotkeys</system:String>
<system:String x:Key="openResultModifiers">Open Result Modifier Key</system:String> <system:String x:Key="openResultModifiers">Open Result Modifier Key</system:String>
<system:String x:Key="openResultModifiersToolTip">Select a modifier key to open selected result via keyboard.</system:String> <system:String x:Key="openResultModifiersToolTip">Select a modifier key to open selected result via keyboard.</system:String>
<system:String x:Key="showOpenResultHotkey">Show Hotkey</system:String> <system:String x:Key="showOpenResultHotkey">Show Hotkey</system:String>
<system:String x:Key="showOpenResultHotkeyToolTip">Show result selection hotkey with results.</system:String> <system:String x:Key="showOpenResultHotkeyToolTip">Show result selection hotkey with results.</system:String>
<system:String x:Key="autoCompleteHotkey">Auto Complete</system:String>
<system:String x:Key="autoCompleteHotkeyToolTip">Runs autocomplete for the selected items.</system:String>
<system:String x:Key="SelectNextItemHotkey">Select Next Item</system:String>
<system:String x:Key="SelectPrevItemHotkey">Select Prev Item</system:String>
<system:String x:Key="SelectNextPageHotkey">Next Page</system:String>
<system:String x:Key="SelectPrevPageHotkey">Prev Page</system:String>
<system:String x:Key="OpenContextMenuHotkey">Open Context Menu</system:String>
<system:String x:Key="SettingWindowHotkey">Open Setting Window</system:String>
<system:String x:Key="CopyFilePathHotkey">Copy File Path</system:String>
<system:String x:Key="ToggleGameModeHotkey">Toggle Game Mode</system:String>
<system:String x:Key="ToggleHistoryHotkey">Toggle History</system:String>
<system:String x:Key="OpenContainFolderHotkey">Open Containing Folder</system:String>
<system:String x:Key="RunAsAdminHotkey">Run As Admin</system:String>
<system:String x:Key="ReloadPluginHotkey">Reload Plugins Data</system:String>
<system:String x:Key="QuickWidthHotkey">Quick Adjust Window Width Size</system:String>
<system:String x:Key="QuickHeightHotkey">Quick Adjust Window Height Size</system:String>
<system:String x:Key="ReloadPluginHotkeyToolTip">Use when require plugins to reload and update their existing data.</system:String>
<system:String x:Key="AdditionalHotkeyToolTip">You can add one more hotkey for this function.</system:String>
<system:String x:Key="customQueryHotkey">Custom Query Hotkeys</system:String> <system:String x:Key="customQueryHotkey">Custom Query Hotkeys</system:String>
<system:String x:Key="customQueryShortcut">Custom Query Shortcuts</system:String> <system:String x:Key="customQueryShortcut">Custom Query Shortcuts</system:String>
<system:String x:Key="builtinShortcuts">Built-in Shortcuts</system:String> <system:String x:Key="builtinShortcuts">Built-in Shortcuts</system:String>
@ -190,6 +210,7 @@
<system:String x:Key="delete">Delete</system:String> <system:String x:Key="delete">Delete</system:String>
<system:String x:Key="edit">Edit</system:String> <system:String x:Key="edit">Edit</system:String>
<system:String x:Key="add">Add</system:String> <system:String x:Key="add">Add</system:String>
<system:String x:Key="none">None</system:String>
<system:String x:Key="pleaseSelectAnItem">Please select an item</system:String> <system:String x:Key="pleaseSelectAnItem">Please select an item</system:String>
<system:String x:Key="deleteCustomHotkeyWarning">Are you sure you want to delete {0} plugin hotkey?</system:String> <system:String x:Key="deleteCustomHotkeyWarning">Are you sure you want to delete {0} plugin hotkey?</system:String>
<system:String x:Key="deleteCustomShortcutWarning">Are you sure you want to delete shortcut: {0} with expansion {1}?</system:String> <system:String x:Key="deleteCustomShortcutWarning">Are you sure you want to delete shortcut: {0} with expansion {1}?</system:String>
@ -288,6 +309,9 @@
<system:String x:Key="hotkeyIsNotUnavailable">Hotkey is unavailable, please select a new hotkey</system:String> <system:String x:Key="hotkeyIsNotUnavailable">Hotkey is unavailable, please select a new hotkey</system:String>
<system:String x:Key="invalidPluginHotkey">Invalid plugin hotkey</system:String> <system:String x:Key="invalidPluginHotkey">Invalid plugin hotkey</system:String>
<system:String x:Key="update">Update</system:String> <system:String x:Key="update">Update</system:String>
<system:String x:Key="hotkeyRegTitle">Binding Hotkey</system:String>
<system:String x:Key="hotkeyUnavailable">Current hotkey is unavailable.</system:String>
<system:String x:Key="hotkeyRegGuide">Press the keys you want to use for this function.</system:String>
<!-- Custom Query Shortcut Dialog --> <!-- Custom Query Shortcut Dialog -->
<system:String x:Key="customeQueryShortcutTitle">Custom Query Shortcut</system:String> <system:String x:Key="customeQueryShortcutTitle">Custom Query Shortcut</system:String>
@ -297,8 +321,11 @@
<system:String x:Key="duplicateShortcut">Shortcut already exists, please enter a new Shortcut or edit the existing one.</system:String> <system:String x:Key="duplicateShortcut">Shortcut already exists, please enter a new Shortcut or edit the existing one.</system:String>
<system:String x:Key="emptyShortcut">Shortcut and/or its expansion is empty.</system:String> <system:String x:Key="emptyShortcut">Shortcut and/or its expansion is empty.</system:String>
<!-- Hotkey Control --> <!-- Common Action -->
<system:String x:Key="hotkeyUnavailable">Hotkey Unavailable</system:String> <system:String x:Key="commonSave">Save</system:String>
<system:String x:Key="commonCancel">Cancel</system:String>
<system:String x:Key="commonReset">Reset</system:String>
<system:String x:Key="commonDelete">Delete</system:String>
<!-- Crash Reporter --> <!-- Crash Reporter -->
<system:String x:Key="reportWindow_version">Version</system:String> <system:String x:Key="reportWindow_version">Version</system:String>

View file

@ -46,47 +46,14 @@
<Window.InputBindings> <Window.InputBindings>
<KeyBinding Key="Escape" Command="{Binding EscCommand}" /> <KeyBinding Key="Escape" Command="{Binding EscCommand}" />
<KeyBinding Key="F5" Command="{Binding ReloadPluginDataCommand}" /> <KeyBinding Key="F5" Command="{Binding ReloadPluginDataCommand}" />
<KeyBinding Key="Tab" Command="{Binding AutocompleteQueryCommand}" />
<KeyBinding
Key="Tab"
Command="{Binding AutocompleteQueryCommand}"
Modifiers="Shift" />
<KeyBinding
Key="I"
Command="{Binding OpenSettingCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="N"
Command="{Binding SelectNextItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="J"
Command="{Binding SelectNextItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="D"
Command="{Binding SelectNextPageCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="P"
Command="{Binding SelectPrevItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="K"
Command="{Binding SelectPrevItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="U"
Command="{Binding SelectPrevPageCommand}"
Modifiers="Ctrl" />
<KeyBinding <KeyBinding
Key="Home" Key="Home"
Command="{Binding SelectFirstResultCommand}" Command="{Binding SelectFirstResultCommand}"
Modifiers="Alt" /> Modifiers="Alt" />
<KeyBinding <KeyBinding
Key="O" Key="End"
Command="{Binding LoadContextMenuCommand}" Command="{Binding SelectLastResultCommand}"
Modifiers="Ctrl" /> Modifiers="Alt" />
<KeyBinding <KeyBinding
Key="R" Key="R"
Command="{Binding ReQueryCommand}" Command="{Binding ReQueryCommand}"
@ -111,10 +78,6 @@
Key="OemMinus" Key="OemMinus"
Command="{Binding DecreaseMaxResultCommand}" Command="{Binding DecreaseMaxResultCommand}"
Modifiers="Control" /> Modifiers="Control" />
<KeyBinding
Key="H"
Command="{Binding LoadHistoryCommand}"
Modifiers="Ctrl" />
<KeyBinding <KeyBinding
Key="Enter" Key="Enter"
Command="{Binding OpenResultCommand}" Command="{Binding OpenResultCommand}"
@ -194,6 +157,46 @@
Key="{Binding PreviewHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}" Key="{Binding PreviewHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding TogglePreviewCommand}" Command="{Binding TogglePreviewCommand}"
Modifiers="{Binding PreviewHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" /> Modifiers="{Binding PreviewHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding AutoCompleteHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding AutocompleteQueryCommand}"
Modifiers="{Binding AutoCompleteHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding AutoCompleteHotkey2, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding AutocompleteQueryCommand}"
Modifiers="{Binding AutoCompleteHotkey2, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SelectNextItemHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding SelectNextItemCommand}"
Modifiers="{Binding SelectNextItemHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SelectPrevItemHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding SelectPrevItemCommand}"
Modifiers="{Binding SelectPrevItemHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SelectNextItemHotkey2, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding SelectNextItemCommand}"
Modifiers="{Binding SelectNextItemHotkey2, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SelectPrevItemHotkey2, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding SelectPrevItemCommand}"
Modifiers="{Binding SelectPrevItemHotkey2, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SettingWindowHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding OpenSettingCommand}"
Modifiers="{Binding SettingWindowHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding OpenContextMenuHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding LoadContextMenuCommand}"
Modifiers="{Binding OpenContextMenuHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SelectNextPageHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding SelectNextPageCommand}"
Modifiers="{Binding SelectNextPageHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
<KeyBinding
Key="{Binding SelectPrevPageHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
Command="{Binding SelectPrevPageCommand}"
Modifiers="{Binding SelectPrevPageHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='modifiers'}" />
</Window.InputBindings> </Window.InputBindings>
<Grid> <Grid>
<Border MouseDown="OnMouseDown" Style="{DynamicResource WindowBorderStyle}"> <Border MouseDown="OnMouseDown" Style="{DynamicResource WindowBorderStyle}">

View file

@ -0,0 +1,117 @@
<UserControl
x:Class="Flow.Launcher.Resources.Controls.Card"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ui="http://schemas.modernwpf.com/2019"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<Border x:Name="BD" HorizontalAlignment="Stretch">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="{DynamicResource Color00B}" />
<Setter Property="BorderBrush" Value="{DynamicResource Color03B}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="MinHeight" Value="68" />
<Setter Property="Margin" Value="0,4,0,0" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType=local:Card}}" Value="Inside">
<Setter Property="BorderThickness" Value="0,1,0,0" />
<Setter Property="CornerRadius" Value="0" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="Background" Value="Transparent" />
</DataTrigger>
<DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType=local:Card}}" Value="InsideFit">
<Setter Property="BorderThickness" Value="0,1,0,0" />
<Setter Property="CornerRadius" Value="0" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="Padding" Value="38,0,26,0" />
<Setter Property="Background" Value="Transparent" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="auto"
MinWidth="20"
MaxWidth="60" />
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="Auto" MinWidth="30" />
</Grid.ColumnDefinitions>
<ContentControl
Grid.Row="0"
Grid.Column="2"
Margin="0,0,16,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
<StackPanel>
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Grid.Column" Value="1" />
<Setter Property="Width" Value="Auto" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
</StackPanel.Style>
<TextBlock x:Name="ItemTitle" Text="{Binding Title, RelativeSource={RelativeSource AncestorType=local:Card}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock x:Name="SubTitle" Text="{Binding Sub, RelativeSource={RelativeSource AncestorType=local:Card}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SubTitle, Path=Text}" Value="{x:Static sys:String.Empty}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Foreground" Value="{DynamicResource Color04B}" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="Padding" Value="0,0,24,0" />
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
<TextBlock x:Name="ItemIcon" Text="{Binding Icon, RelativeSource={RelativeSource AncestorType=local:Card}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ItemIcon, Path=Text}" Value="{x:Static sys:String.Empty}">
<Setter Property="Margin" Value="24,0,0,0" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Margin" Value="24,0,16,0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontSize" Value="20" />
<Setter Property="FontFamily" Value="/Resources/#Segoe Fluent Icons" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
</ControlTemplate>
</UserControl.Template>
</UserControl>

View file

@ -0,0 +1,63 @@
using System.Windows;
using UserControl = System.Windows.Controls.UserControl;
namespace Flow.Launcher.Resources.Controls
{
public partial class Card : UserControl
{
public enum CardType
{
Default,
Inside,
InsideFit
}
public Card()
{
InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register(nameof(Title), typeof(string), typeof(Card), new PropertyMetadata(string.Empty));
public string Sub
{
get { return (string)GetValue(SubProperty); }
set { SetValue(SubProperty, value); }
}
public static readonly DependencyProperty SubProperty =
DependencyProperty.Register(nameof(Sub), typeof(string), typeof(Card), new PropertyMetadata(string.Empty));
public string Icon
{
get { return (string)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register(nameof(Icon), typeof(string), typeof(Card), new PropertyMetadata(string.Empty));
/// <summary>
/// Gets or sets additional content for the UserControl
/// </summary>
public object AdditionalContent
{
get { return (object)GetValue(AdditionalContentProperty); }
set { SetValue(AdditionalContentProperty, value); }
}
public static readonly DependencyProperty AdditionalContentProperty =
DependencyProperty.Register(nameof(AdditionalContent), typeof(object), typeof(Card),
new PropertyMetadata(null));
public CardType Type
{
get { return (CardType)GetValue(TypeProperty); }
set { SetValue(TypeProperty, value); }
}
public static readonly DependencyProperty TypeProperty =
DependencyProperty.Register(nameof(Type), typeof(CardType), typeof(Card),
new PropertyMetadata(CardType.Default));
}
}

View file

@ -0,0 +1,313 @@
<UserControl
x:Class="Flow.Launcher.Resources.Controls.ExCard"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ui="http://schemas.modernwpf.com/2019"
mc:Ignorable="d">
<UserControl.Template>
<ControlTemplate TargetType="UserControl">
<Expander
x:Name="expanderHeader"
Padding="0"
BorderThickness="1"
IsExpanded="{Binding Mode=TwoWay, Path=IsExpanded}"
SnapsToDevicePixels="False">
<Expander.Style>
<Style TargetType="{x:Type Expander}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource Color00B}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="BorderBrush" Value="{DynamicResource Color03B}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border
x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5"
SnapsToDevicePixels="true">
<DockPanel>
<ToggleButton
x:Name="HeaderSite"
MinWidth="0"
MinHeight="68"
Margin="0,0,0,0"
Padding="0,0,0,0"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
DockPanel.Dock="Top"
FocusVisualStyle="{DynamicResource ExpanderHeaderFocusVisual}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontStretch="{TemplateBinding FontStretch}"
FontStyle="{TemplateBinding FontStyle}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border
x:Name="ToggleBtn"
Padding="{TemplateBinding Padding}"
Background="{DynamicResource Color00B}"
ClipToBounds="True"
CornerRadius="5">
<Grid SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<ContentPresenter
Grid.Column="0"
Margin="0,0,0,0"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
RecognizesAccessKey="True"
SnapsToDevicePixels="True" />
<Grid
x:Name="ChevronGrid"
Grid.Column="2"
Margin="0,0,18,0"
VerticalAlignment="Center"
Background="Transparent"
RenderTransformOrigin="0.5, 0.5">
<Grid.RenderTransform>
<RotateTransform Angle="0" />
</Grid.RenderTransform>
<Ellipse
x:Name="circle"
Width="19"
Height="19"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stroke="Transparent" />
<Path
x:Name="arrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 1,1.5 L 4.5,5 L 8,1.5"
SnapsToDevicePixels="false"
Stroke="#666"
StrokeThickness="1" />
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="arrow" Property="Data" Value="M 1,4.5 L 4.5,1 L 8,4.5" />
<Setter TargetName="ToggleBtn" Property="CornerRadius" Value="5 5 0 0" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="circle" Property="Stroke" Value="Transparent" />
<Setter TargetName="arrow" Property="Stroke" Value="{DynamicResource Color05B}" />
<Setter TargetName="ToggleBtn" Property="Background" Value="{DynamicResource CustomExpanderHover}" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="circle" Property="Stroke" Value="Transparent" />
<Setter TargetName="circle" Property="StrokeThickness" Value="1.5" />
<Setter TargetName="arrow" Property="Stroke" Value="{DynamicResource Color17B}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<Border x:Name="ContentPresenterBorder" BorderThickness="0">
<ContentPresenter
x:Name="ExpandSite"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
DockPanel.Dock="Bottom"
Focusable="false" />
<Border.LayoutTransform>
<ScaleTransform ScaleY="0" />
</Border.LayoutTransform>
</Border>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter TargetName="ExpandSite" Property="Visibility" Value="Visible" />
<Setter TargetName="ContentPresenterBorder" Property="BorderThickness" Value="0,0,0,0" />
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ContentPresenterBorder"
Storyboard.TargetProperty="(Border.LayoutTransform).(ScaleTransform.ScaleY)"
From="0.0"
To="1.0"
Duration="00:00:00.00" />
<DoubleAnimation
Storyboard.TargetName="ContentPresenterBorder"
Storyboard.TargetProperty="(Border.Opacity)"
From="0.0"
To="1.0"
Duration="00:00:00.00" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="ContentPresenterBorder"
Storyboard.TargetProperty="(Border.LayoutTransform).(ScaleTransform.ScaleY)"
From="1.0"
To="0"
Duration="00:00:00.00" />
<!-- Animation 00:00:00.167 -->
<DoubleAnimation
Storyboard.TargetName="ContentPresenterBorder"
Storyboard.TargetProperty="(Border.Opacity)"
From="1.0"
To="0.0"
Duration="00:00:00.00" />
<!-- Animation 00:00:00.167 -->
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="ExpandDirection" Value="Right">
<Setter TargetName="ExpandSite" Property="DockPanel.Dock" Value="Right" />
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Left" />
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource ExpanderRightHeaderStyle}" />
</Trigger>
<Trigger Property="ExpandDirection" Value="Up">
<Setter TargetName="ExpandSite" Property="DockPanel.Dock" Value="Top" />
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Bottom" />
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource ExpanderUpHeaderStyle}" />
</Trigger>
<Trigger Property="ExpandDirection" Value="Left">
<Setter TargetName="ExpandSite" Property="DockPanel.Dock" Value="Left" />
<Setter TargetName="HeaderSite" Property="DockPanel.Dock" Value="Right" />
<Setter TargetName="HeaderSite" Property="Style" Value="{StaticResource ExpanderLeftHeaderStyle}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Expander.Style>
<Expander.Header>
<Border Margin="0" Padding="0,12,0,12">
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Expander}}, Path=ActualWidth}" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="auto"
MinWidth="20"
MaxWidth="60" />
<ColumnDefinition Width="7*" />
<ColumnDefinition Width="Auto" MinWidth="30" />
<ColumnDefinition Width="Auto" MinWidth="30" />
</Grid.ColumnDefinitions>
<ContentControl
x:Name="firstContentPresenter"
Grid.Column="2"
Margin="0,0,14,0"
HorizontalAlignment="Right"
Content="{Binding SideContent, RelativeSource={RelativeSource AncestorType=local:ExCard}}" />
<TextBlock
x:Name="ItemIcon"
Grid.Column="0"
VerticalAlignment="Center"
Text="{Binding Icon, RelativeSource={RelativeSource AncestorType=local:ExCard}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ItemIcon, Path=Text}" Value="{x:Static sys:String.Empty}">
<Setter Property="Margin" Value="24,0,0,0" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Grid.Column" Value="0" />
<Setter Property="Margin" Value="24,0,16,0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontSize" Value="20" />
<Setter Property="FontFamily" Value="/Resources/#Segoe Fluent Icons" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
</TextBlock.Style>
</TextBlock>
<StackPanel Grid.Column="1" Margin="0,0,14,0">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="Grid.Column" Value="1" />
<Setter Property="Width" Value="Auto" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
</StackPanel.Style>
<TextBlock x:Name="ItemTitle" Text="{Binding Title, RelativeSource={RelativeSource AncestorType=local:ExCard}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock x:Name="SubTitle" Text="{Binding Sub, RelativeSource={RelativeSource AncestorType=local:ExCard}}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SubTitle, Path=Text}" Value="{x:Static sys:String.Empty}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Foreground" Value="{DynamicResource Color04B}" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Margin" Value="0,0,0,0" />
<Setter Property="Padding" Value="0,0,24,0" />
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</Grid>
</Border>
</Expander.Header>
<Grid
Grid.Column="0"
Grid.ColumnSpan="4"
HorizontalAlignment="Stretch"
FlowDirection="LeftToRight">
<StackPanel Margin="0,0,0,0" Orientation="Vertical">
<ContentControl
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="0,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
</StackPanel>
</Grid>
</Expander>
</ControlTemplate>
</UserControl.Template>
</UserControl>

View file

@ -0,0 +1,57 @@
using System.Windows;
using System.Windows.Controls;
namespace Flow.Launcher.Resources.Controls
{
public partial class ExCard : UserControl
{
public ExCard()
{
InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register(nameof(Title), typeof(string), typeof(ExCard), new PropertyMetadata(string.Empty));
public string Sub
{
get { return (string)GetValue(SubProperty); }
set { SetValue(SubProperty, value); }
}
public static readonly DependencyProperty SubProperty =
DependencyProperty.Register(nameof(Sub), typeof(string), typeof(ExCard), new PropertyMetadata(string.Empty));
public string Icon
{
get { return (string)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register(nameof(Icon), typeof(string), typeof(ExCard), new PropertyMetadata(string.Empty));
/// <summary>
/// Gets or sets additional content for the UserControl
/// </summary>
public object AdditionalContent
{
get { return (object)GetValue(AdditionalContentProperty); }
set { SetValue(AdditionalContentProperty, value); }
}
public static readonly DependencyProperty AdditionalContentProperty =
DependencyProperty.Register(nameof(AdditionalContent), typeof(object), typeof(ExCard),
new PropertyMetadata(null));
public object SideContent
{
get { return (object)GetValue(SideContentProperty); }
set { SetValue(SideContentProperty, value); }
}
public static readonly DependencyProperty SideContentProperty =
DependencyProperty.Register(nameof(SideContent), typeof(object), typeof(ExCard),
new PropertyMetadata(null));
}
}

View file

@ -0,0 +1,74 @@
<UserControl
x:Class="Flow.Launcher.Resources.Controls.HotkeyDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<Button
Width="Auto"
FontSize="13"
FontWeight="Bold"
Foreground="{DynamicResource Color01B}">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border
x:Name="ButtonBorder"
BorderBrush="{DynamicResource ButtonInsideBorder}"
CornerRadius="5">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="{DynamicResource Color12B}" />
<Setter Property="Padding" Value="5,0,5,0" />
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType=local:HotkeyDisplay}}" Value="Small">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="BorderThickness" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Button.Template>
<Button.Content>
<ItemsControl x:Name="KeysControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" CornerRadius="5">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundBaseLowBrush}" />
<Setter Property="Padding" Value="10,5,10,5" />
<Setter Property="Margin" Value="2,5,2,5" />
<Setter Property="BorderThickness" Value="1" />
<Style.Triggers>
<DataTrigger Binding="{Binding Type, RelativeSource={RelativeSource AncestorType=local:HotkeyDisplay}}" Value="Small">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" />
<Setter Property="Padding" Value="10,5,10,5" />
<Setter Property="Margin" Value="2,0,2,0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Foreground="{DynamicResource AccentButtonForegroundPointerOver}" Text="{Binding}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Button.Content>
</Button>
</Grid>
</UserControl>

View file

@ -0,0 +1,63 @@
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
namespace Flow.Launcher.Resources.Controls
{
public partial class HotkeyDisplay : UserControl
{
public enum DisplayType
{
Default,
Small
}
public HotkeyDisplay()
{
InitializeComponent();
//List<string> stringList =e.NewValue.Split('+').ToList();
Values = new ObservableCollection<string>();
KeysControl.ItemsSource = Values;
}
public string Keys
{
get { return (string)GetValue(KeysProperty); }
set { SetValue(KeysProperty, value); }
}
public static readonly DependencyProperty KeysProperty =
DependencyProperty.Register(nameof(Keys), typeof(string), typeof(HotkeyDisplay),
new PropertyMetadata(string.Empty, keyChanged));
public DisplayType Type
{
get { return (DisplayType)GetValue(TypeProperty); }
set { SetValue(TypeProperty, value); }
}
public static readonly DependencyProperty TypeProperty =
DependencyProperty.Register(nameof(Type), typeof(DisplayType), typeof(HotkeyDisplay),
new PropertyMetadata(DisplayType.Default));
private static void keyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as UserControl;
if (null == control) return; // This should not be possible
var newValue = e.NewValue as string;
if (null == newValue) return;
if (d is not HotkeyDisplay hotkeyDisplay)
return;
hotkeyDisplay.Values.Clear();
foreach (var key in newValue.Split('+'))
{
hotkeyDisplay.Values.Add(key);
}
}
public ObservableCollection<string> Values { get; set; }
}
}

View file

@ -3283,5 +3283,416 @@
</Style.Triggers> </Style.Triggers>
</Style> </Style>
<!-- Content Dialog -->
<Style x:Key="ContentDialog" TargetType="ui:ContentDialog">
<Setter Property="Foreground" Value="{DynamicResource ContentDialogForeground}" />
<Setter Property="Background" Value="{DynamicResource ContentDialogBackground}" />
<Setter Property="BorderThickness" Value="{DynamicResource ContentDialogBorderWidth}" />
<Setter Property="BorderBrush" Value="{DynamicResource ContentDialogBorderBrush}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="CornerRadius" Value="{DynamicResource OverlayCornerRadius}" />
<Setter Property="PrimaryButtonStyle" Value="{DynamicResource DefaultButtonStyle}" />
<Setter Property="SecondaryButtonStyle" Value="{DynamicResource DefaultButtonStyle}" />
<Setter Property="CloseButtonStyle" Value="{DynamicResource DefaultButtonStyle}" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="IsShadowEnabled" Value="{DynamicResource {x:Static SystemParameters.DropShadowKey}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ui:ContentDialog">
<Border x:Name="Container">
<VisualStateManager.CustomVisualStateManager>
<ui:SimpleVisualStateManager />
</VisualStateManager.CustomVisualStateManager>
<Grid
x:Name="LayoutRoot"
Background="{DynamicResource ContentDialogOverlayBG}"
SnapsToDevicePixels="True"
Visibility="Collapsed">
<Grid
x:Name="BackgroundElement"
MinWidth="{DynamicResource ContentDialogMinWidth}"
MinHeight="{DynamicResource ContentDialogMinHeight}"
MaxWidth="{DynamicResource ContentDialogMaxWidth}"
MaxHeight="{DynamicResource ContentDialogMaxHeight}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FlowDirection="{TemplateBinding FlowDirection}"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<ScaleTransform x:Name="ScaleTransform" />
</Grid.RenderTransform>
<ui:ThemeShadowChrome
x:Name="Shdw"
Margin="{DynamicResource ContentDialogBorderWidth}"
CornerRadius="{TemplateBinding CornerRadius}"
IsShadowEnabled="{TemplateBinding IsShadowEnabled}" />
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Border x:Name="DialogSpace" Padding="{DynamicResource ContentDialogPadding}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer
x:Name="ContentScrollViewer"
Margin="{DynamicResource ContentDialogContentScrollViewerMargin}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
IsTabStop="False"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl
x:Name="Title"
Margin="{DynamicResource ContentDialogTitleMargin}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="{TemplateBinding Title}"
ContentTemplate="{TemplateBinding TitleTemplate}"
FontFamily="{DynamicResource {x:Static SystemFonts.MessageFontFamilyKey}}"
FontSize="20"
FontWeight="Normal"
Foreground="{TemplateBinding Foreground}"
IsTabStop="False"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<ui:ContentPresenterEx
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
TextWrapping="Wrap" />
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
<ui:ContentPresenterEx
x:Name="Content"
Grid.Row="1"
Margin="{DynamicResource ContentDialogContentMargin}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
TextElement.FontFamily="{DynamicResource ContentControlThemeFontFamily}"
TextElement.FontSize="{DynamicResource ControlContentThemeFontSize}"
TextElement.Foreground="{TemplateBinding Foreground}"
TextWrapping="Wrap" />
</Grid>
</ScrollViewer>
<Grid
x:Name="CommandSpace"
Grid.Row="1"
Margin="{DynamicResource ContentDialogCommandSpaceMargin}"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
KeyboardNavigation.DirectionalNavigation="Contained">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="PrimaryButton"
Grid.Column="0"
Margin="0,0,2,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding PrimaryButtonText}"
IsEnabled="{TemplateBinding IsPrimaryButtonEnabled}"
Style="{TemplateBinding PrimaryButtonStyle}" />
<Button
x:Name="SecondaryButton"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="2,0,2,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding SecondaryButtonText}"
IsEnabled="{TemplateBinding IsSecondaryButtonEnabled}"
Style="{TemplateBinding SecondaryButtonStyle}" />
<Button
x:Name="CloseButton"
Grid.Column="3"
Margin="2,0,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding CloseButtonText}"
Style="{TemplateBinding CloseButtonStyle}" />
</Grid>
</Grid>
</Border>
</Border>
</Grid>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DialogShowingStates">
<VisualStateGroup.Transitions>
<VisualTransition To="DialogHidden">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="SnapsToDevicePixels">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
</BooleanAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
</BooleanAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleX">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0" />
<SplineDoubleKeyFrame
KeySpline="0.1,0.9 0.2,1.0"
KeyTime="0:0:0.5"
Value="1.05" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleY">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0" />
<SplineDoubleKeyFrame
KeySpline="0.1,0.9 0.2,1.0"
KeyTime="0:0:0.5"
Value="1.05" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0" />
<LinearDoubleKeyFrame KeyTime="0:0:0.083" Value="0.0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition To="DialogShowing">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="SnapsToDevicePixels">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
</BooleanAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleX">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.05" />
<SplineDoubleKeyFrame
KeySpline="0.1,0.9 0.2,1.0"
KeyTime="0:0:0.5"
Value="1.0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleY">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.05" />
<SplineDoubleKeyFrame
KeySpline="0.1,0.9 0.2,1.0"
KeyTime="0:0:0.5"
Value="1.0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity">
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0" />
<LinearDoubleKeyFrame KeyTime="0:0:0.167" Value="1.0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="DialogHidden" />
<VisualState x:Name="DialogShowing">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="(KeyboardNavigation.TabNavigation)">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static KeyboardNavigationMode.Cycle}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="DialogShowingWithoutSmokeLayer">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Null}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DialogSizingStates">
<VisualState x:Name="DefaultDialogSizing" />
<VisualState x:Name="FullDialogSizing">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="VerticalAlignment">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static VerticalAlignment.Stretch}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonsVisibilityStates">
<VisualState x:Name="AllVisible" />
<VisualState x:Name="NoneVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CommandSpace" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PrimaryVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SecondaryVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CloseVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PrimaryAndSecondaryVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PrimaryAndCloseVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SecondaryAndCloseVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="0" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="0,0,2,0" />
</ThicknessAnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DefaultButtonStates">
<VisualState x:Name="NoDefaultButton" />
<VisualState x:Name="PrimaryAsDefaultButton" />
<VisualState x:Name="SecondaryAsDefaultButton" />
<VisualState x:Name="CloseAsDefaultButton" />
</VisualStateGroup>
<VisualStateGroup x:Name="DialogBorderStates">
<VisualState x:Name="NoBorder" />
<VisualState x:Name="AccentColorBorder">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{DynamicResource SystemControlForegroundAccentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsShadowEnabled" Value="False">
<Setter TargetName="Shdw" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="DefaultButton" Value="Primary">
<Setter TargetName="PrimaryButton" Property="Style" Value="{DynamicResource AccentButtonStyle}" />
</Trigger>
<Trigger Property="DefaultButton" Value="Secondary">
<Setter TargetName="SecondaryButton" Property="Style" Value="{DynamicResource AccentButtonStyle}" />
</Trigger>
<Trigger Property="DefaultButton" Value="Close">
<Setter TargetName="CloseButton" Property="Style" Value="{DynamicResource AccentButtonStyle}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary> </ResourceDictionary>

View file

@ -104,6 +104,16 @@
<Color x:Key="NumberBoxColor26">#ffffff</Color> <Color x:Key="NumberBoxColor26">#ffffff</Color>
<Color x:Key="HoverStoreGrid">#272727</Color> <Color x:Key="HoverStoreGrid">#272727</Color>
<!-- Resources for HotkeyControl -->
<SolidColorBrush x:Key="CustomHotkeyHover" Color="#323232" />
<!-- Resources for Expander -->
<SolidColorBrush x:Key="CustomExpanderHover" Color="#323232" />
<!-- Resource for ContentDialog -->
<SolidColorBrush x:Key="ContentDialogOverlayBG" Color="#4D000000" />
<!-- Infobar Warning -->
<SolidColorBrush x:Key="InfoBarWarningIcon" Color="#FCE100" />
<SolidColorBrush x:Key="InfoBarWarningBG" Color="#433519" />
<SolidColorBrush x:Key="InfoBarBD" Color="#19000000" />
<SolidColorBrush x:Key="ButtonOutBorder" Color="Transparent" /> <SolidColorBrush x:Key="ButtonOutBorder" Color="Transparent" />
<SolidColorBrush x:Key="ButtonInsideBorder" Color="#3f3f3f" /> <SolidColorBrush x:Key="ButtonInsideBorder" Color="#3f3f3f" />
@ -772,7 +782,7 @@
<m:StaticResource x:Key="ContentDialogForeground" ResourceKey="SystemControlPageTextBaseHighBrush" /> <m:StaticResource x:Key="ContentDialogForeground" ResourceKey="SystemControlPageTextBaseHighBrush" />
<m:StaticResource x:Key="ContentDialogBackground" ResourceKey="SystemControlPageBackgroundAltHighBrush" /> <m:StaticResource x:Key="ContentDialogBackground" ResourceKey="SystemControlPageBackgroundAltHighBrush" />
<m:StaticResource x:Key="ContentDialogBorderBrush" ResourceKey="SystemControlBackgroundBaseLowBrush" /> <m:StaticResource x:Key="ContentDialogBorderBrush" ResourceKey="SystemControlBackgroundBaseLowBrush" />
<m:StaticResource x:Key="ContentDialogLightDismissOverlayBackground" ResourceKey="SystemControlPageBackgroundMediumAltMediumBrush" /> <m:StaticResource x:Key="ContentDialogLightDismissOverlayBackground" ResourceKey="ContentDialogOverlayBG" />
<!-- Resources for DataGrid --> <!-- Resources for DataGrid -->
<sys:Double x:Key="ListAccentLowOpacity">0.6</sys:Double> <sys:Double x:Key="ListAccentLowOpacity">0.6</sys:Double>

View file

@ -95,6 +95,17 @@
<Color x:Key="NumberBoxColor26">#1b1b1b</Color> <Color x:Key="NumberBoxColor26">#1b1b1b</Color>
<Color x:Key="HoverStoreGrid">#f6f6f6</Color> <Color x:Key="HoverStoreGrid">#f6f6f6</Color>
<!-- Resources for HotkeyControl -->
<SolidColorBrush x:Key="CustomHotkeyHover" Color="#f6f6f6" />
<!-- Resources for Expander -->
<SolidColorBrush x:Key="CustomExpanderHover" Color="#f6f6f6" />
<!-- Resource for ContentDialog -->
<SolidColorBrush x:Key="ContentDialogOverlayBG" Color="#4D000000" />
<!-- Infobar Warning -->
<SolidColorBrush x:Key="InfoBarWarningIcon" Color="#9D5D00" />
<SolidColorBrush x:Key="InfoBarWarningBG" Color="#FFF4CE" />
<SolidColorBrush x:Key="InfoBarBD" Color="#0F000000" />
<SolidColorBrush x:Key="ButtonOutBorder" Color="#e5e5e5" /> <SolidColorBrush x:Key="ButtonOutBorder" Color="#e5e5e5" />
<SolidColorBrush x:Key="ButtonInsideBorder" Color="#d3d3d3" /> <SolidColorBrush x:Key="ButtonInsideBorder" Color="#d3d3d3" />

View file

@ -9,6 +9,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:ui="http://schemas.modernwpf.com/2019"
Title="WelcomePage2" Title="WelcomePage2"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"> mc:Ignorable="d">
<Page.Resources> <Page.Resources>
<converters:BorderClipConverter x:Key="BorderClipConverter" /> <converters:BorderClipConverter x:Key="BorderClipConverter" />
@ -110,12 +111,12 @@
FontWeight="SemiBold" FontWeight="SemiBold"
Text="{DynamicResource flowlauncherHotkey}" /> Text="{DynamicResource flowlauncherHotkey}" />
<flowlauncher:HotkeyControl <flowlauncher:HotkeyControl
x:Name="HotkeyControl" Margin="0,8,0,0"
Width="300" ChangeHotkey="{Binding SetTogglingHotkeyCommand}"
Height="35" DefaultHotkey="Alt+Space"
Margin="-206,10,0,0" Hotkey="{Binding Settings.Hotkey}"
GotFocus="HotkeyControl_OnGotFocus" ValidateKeyGesture="True"
LostFocus="HotkeyControl_OnLostFocus"/> WindowTitle="{DynamicResource flowlauncherHotkey}" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View file

@ -5,16 +5,14 @@ using System;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Navigation; using System.Windows.Navigation;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher.Resources.Pages namespace Flow.Launcher.Resources.Pages
{ {
public partial class WelcomePage2 public partial class WelcomePage2
{ {
private Settings Settings { get; set; } public Settings Settings { get; set; }
private Brush tbMsgForegroundColorOriginal;
private string tbMsgTextOriginal;
protected override void OnNavigatedTo(NavigationEventArgs e) protected override void OnNavigatedTo(NavigationEventArgs e)
{ {
@ -22,31 +20,14 @@ namespace Flow.Launcher.Resources.Pages
Settings = settings; Settings = settings;
else else
throw new ArgumentException("Unexpected Parameter setting."); throw new ArgumentException("Unexpected Parameter setting.");
InitializeComponent(); InitializeComponent();
tbMsgTextOriginal = HotkeyControl.tbMsg.Text;
tbMsgForegroundColorOriginal = HotkeyControl.tbMsg.Foreground;
HotkeyControl.SetHotkeyAsync(Settings.Hotkey, false);
} }
private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args)
{
HotKeyMapper.RemoveHotkey(Settings.Hotkey);
}
private void HotkeyControl_OnLostFocus(object sender, RoutedEventArgs args)
{
if (HotkeyControl.CurrentHotkeyAvailable)
{
HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
Settings.Hotkey = HotkeyControl.CurrentHotkey.ToString();
}
else
{
HotKeyMapper.SetHotkey(new HotkeyModel(Settings.Hotkey), HotKeyMapper.OnToggleHotkey);
}
HotkeyControl.tbMsg.Text = tbMsgTextOriginal; [RelayCommand]
HotkeyControl.tbMsg.Foreground = tbMsgForegroundColorOriginal; private static void SetTogglingHotkey(HotkeyModel hotkey)
{
HotKeyMapper.SetHotkey(hotkey, HotKeyMapper.OnToggleHotkey);
} }
} }
} }

View file

@ -2,11 +2,13 @@
x:Class="Flow.Launcher.Resources.Pages.WelcomePage3" x:Class="Flow.Launcher.Resources.Pages.WelcomePage3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages" xmlns:local="clr-namespace:Flow.Launcher.Resources.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:ui="http://schemas.modernwpf.com/2019"
Title="WelcomePage3" Title="WelcomePage3"
VerticalAlignment="Stretch"
mc:Ignorable="d"> mc:Ignorable="d">
<Page.Resources> <Page.Resources>
<Style x:Key="KbdLine" TargetType="Border"> <Style x:Key="KbdLine" TargetType="Border">
@ -27,301 +29,86 @@
<Setter Property="Foreground" Value="{DynamicResource Color05B}" /> <Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style> </Style>
</Page.Resources> </Page.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <Grid>
<Grid> <Grid.RowDefinitions>
<Grid.RowDefinitions> <RowDefinition Height="Auto" />
<RowDefinition Height="0" /> <RowDefinition Height="*" />
<RowDefinition /> </Grid.RowDefinitions>
</Grid.RowDefinitions> <TextBlock
Grid.Row="0"
<Border Grid.Row="0" HorizontalAlignment="Stretch"> Margin="24,20,24,14"
<Border.Background> FontSize="20"
<LinearGradientBrush StartPoint="0 0" EndPoint="1 1"> FontWeight="SemiBold"
<LinearGradientBrush.GradientStops> Text="{DynamicResource Welcome_Page3_Title}" />
<GradientStop Offset="0.0" Color="#16af7b" /> <ScrollViewer
<GradientStop Offset="1.0" Color="#34c191" /> Grid.Row="1"
</LinearGradientBrush.GradientStops> Height="478"
</LinearGradientBrush> Margin="0,0,0,0"
</Border.Background> HorizontalAlignment="Stretch"
FontSize="13">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal"> <StackPanel Margin="24,0,24,0">
<Image <Border
Width="300" BorderBrush="{DynamicResource Color03B}"
Height="100" BorderThickness="0"
Margin="0,0,0,0" CornerRadius="5">
Source="../../images/page_img02.png" <StackPanel>
Style="{DynamicResource StyleImageFadeIn}" /> <cc:Card
</StackPanel> Title="{DynamicResource HotkeyUpDownDesc}"
</Border> BorderThickness="0,0,0,0"
Type="Inside">
<ScrollViewer
Grid.Row="1"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid>
<StackPanel Margin="24,20,24,20">
<StackPanel Margin="0,0,0,10">
<TextBlock
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource Welcome_Page3_Title}" />
</StackPanel>
<Border Style="{DynamicResource KbdLine}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel <cc:HotkeyDisplay Keys="←+→" Type="Small" />
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">←</TextBlock>
</Border>
<TextBlock VerticalAlignment="Center">,</TextBlock>
<Border Margin="5,0,0,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">→</TextBlock>
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyUpDownDesc}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </cc:Card>
<cc:Card
<Border Style="{DynamicResource KbdLine}"> Title="{DynamicResource HotkeyLeftRightDesc}"
BorderThickness="0,0,0,0"
Type="Inside">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel <cc:HotkeyDisplay Keys="↑+↓" Type="Small" />
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">↑</TextBlock>
</Border>
<TextBlock VerticalAlignment="Center">,</TextBlock>
<Border Margin="5,0,0,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">↓</TextBlock>
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyLeftRightDesc}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </cc:Card>
<cc:Card
<Border Style="{DynamicResource KbdLine}"> Title="{DynamicResource HotkeyESCDesc}"
BorderThickness="0,0,0,0"
Type="Inside">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel <cc:HotkeyDisplay Keys="ESC" Type="Small" />
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}">Enter</TextBlock>
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyRunDesc}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </cc:Card>
<cc:Card
<Border Style="{DynamicResource KbdLine}"> Title="{DynamicResource HotkeyRunDesc}"
BorderThickness="0,0,0,0"
Type="Inside">
<cc:HotkeyDisplay Keys="ENTER" Type="Small" />
</cc:Card>
<cc:Card
Title="{DynamicResource HotkeyShiftEnterDesc}"
BorderThickness="0,0,0,0"
Type="Inside">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel <cc:HotkeyDisplay Keys="SHIFT+ENTER" Type="Small" />
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ESC" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyESCDesc}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </cc:Card>
<cc:Card
<Border Style="{DynamicResource KbdLine}"> Title="{DynamicResource HotkeyCtrlEnterDesc}"
BorderThickness="0,0,0,0"
Type="Inside">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel <cc:HotkeyDisplay Keys="CTRL+ENTER" Type="Small" />
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Tab" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyTabDesc}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </cc:Card>
<cc:Card
<Border Style="{DynamicResource KbdLine}"> Title="{DynamicResource HotkeyCtrlShiftEnterDesc}"
BorderThickness="0,0,0,0"
Type="Inside">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel <cc:HotkeyDisplay Keys="CTRL+SHIFT+ENTER" Type="Small" />
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Shift" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ENTER" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyShiftEnterDesc}" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </cc:Card>
<Border Style="{DynamicResource KbdLine}">
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ENTER" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyCtrlEnterDesc}" />
</StackPanel>
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Shift" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="ENTER" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyCtrlShiftEnterDesc}" />
</StackPanel>
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="H" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyCtrlHDesc}" />
</StackPanel>
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="Ctrl" />
</Border>
<TextBlock VerticalAlignment="Center">+</TextBlock>
<Border Margin="5,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="I" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyCtrlIDesc}" />
</StackPanel>
</StackPanel>
</Border>
<Border Style="{DynamicResource KbdLine}">
<StackPanel Orientation="Horizontal">
<StackPanel
Width="210"
Margin="20,5,4,5"
VerticalAlignment="Center"
Orientation="Horizontal">
<Border Margin="0,0,5,0" Style="{DynamicResource Kbd}">
<TextBlock Style="{DynamicResource KbdText}" Text="F5" />
</Border>
</StackPanel>
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
FontSize="13"
Text="{DynamicResource HotkeyF5Desc}" />
</StackPanel>
</StackPanel>
</Border>
</StackPanel> </StackPanel>
</Grid> </Border>
</ScrollViewer> </StackPanel>
</ScrollViewer>
</Grid> </Grid>
</ScrollViewer>
</ui:Page> </ui:Page>

View file

@ -2,6 +2,7 @@
x:Class="Flow.Launcher.SettingWindow" x:Class="Flow.Launcher.SettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:core="clr-namespace:Flow.Launcher.Core.Resource;assembly=Flow.Launcher.Core" xmlns:core="clr-namespace:Flow.Launcher.Core.Resource;assembly=Flow.Launcher.Core"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@ -2647,63 +2648,37 @@
<StackPanel Margin="5,18,18,10"> <StackPanel Margin="5,18,18,10">
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
Margin="0,5,0,2" Margin="0,5,0,6"
FontSize="30" FontSize="30"
Style="{StaticResource PageTitle}" Style="{StaticResource PageTitle}"
Text="{DynamicResource hotkeys}" Text="{DynamicResource hotkeys}"
TextAlignment="left" /> TextAlignment="left" />
<StackPanel Grid.Row="1"> <StackPanel Grid.Row="1">
<Border Margin="0,8,0,0" Style="{DynamicResource SettingGroupBox}"> <cc:Card
<ItemsControl Style="{StaticResource SettingGrid}"> Title="{DynamicResource flowlauncherHotkey}"
<StackPanel Style="{StaticResource TextPanel}"> Icon="&#xeda7;"
<TextBlock Style="{DynamicResource SettingTitleLabel}" Text="{DynamicResource flowlauncherHotkey}" /> Sub="{DynamicResource flowlauncherHotkeyToolTip}">
<TextBlock Style="{DynamicResource SettingSubTitleLabel}" Text="{DynamicResource flowlauncherHotkeyToolTip}" /> <flowlauncher:HotkeyControl
</StackPanel> ChangeHotkey="{Binding SetTogglingHotkeyCommand}"
<flowlauncher:HotkeyControl DefaultHotkey="Alt+Space"
x:Name="HotkeyControl" Hotkey="{Binding Settings.Hotkey}"
Grid.Row="0" ValidateKeyGesture="True"
Grid.Column="2" WindowTitle="{DynamicResource flowlauncherHotkey}" />
Width="300" </cc:Card>
Height="35"
Margin="0,0,0,0"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
GotFocus="OnHotkeyControlFocused"
Loaded="OnHotkeyControlLoaded"
LostFocus="OnHotkeyControlFocusLost" />
<TextBlock Style="{StaticResource Glyph}">
&#xeda7;
</TextBlock>
</ItemsControl>
</Border>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="2"> <StackPanel Grid.Row="2">
<Border Margin="0,8,0,0" Style="{DynamicResource SettingGroupBox}"> <cc:Card
<ItemsControl Style="{StaticResource SettingGrid}"> Title="{DynamicResource previewHotkey}"
<StackPanel Style="{StaticResource TextPanel}"> Icon="&#xe8a1;"
<TextBlock Style="{DynamicResource SettingTitleLabel}" Text="{DynamicResource previewHotkey}" /> Sub="{DynamicResource previewHotkeyToolTip}">
<TextBlock Style="{DynamicResource SettingSubTitleLabel}" Text="{DynamicResource previewHotkeyToolTip}" /> <flowlauncher:HotkeyControl
</StackPanel> DefaultHotkey="F1"
<flowlauncher:HotkeyControl Hotkey="{Binding Settings.PreviewHotkey}"
x:Name="PreviewHotkeyControl" ValidateKeyGesture="False"
Grid.Row="0" WindowTitle="{DynamicResource previewHotkey}" />
Grid.Column="2" </cc:Card>
Width="300"
Height="35"
Margin="0,0,0,0"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
Loaded="OnPreviewHotkeyControlLoaded"
LostFocus="OnPreviewHotkeyControlFocusLost"
ValidateKeyGesture="True" />
<TextBlock Style="{StaticResource Glyph}">
&#xe8a1;
</TextBlock>
</ItemsControl>
</Border>
</StackPanel> </StackPanel>
<Border <Border
@ -2763,163 +2738,359 @@
</StackPanel> </StackPanel>
</Border> </Border>
<TextBlock <StackPanel Grid.Row="2">
Grid.Row="4" <cc:ExCard
Margin="0,10,12,10" Title="{DynamicResource hotkeyPresets}"
Padding="0,12,0,0" Margin="0,14,0,0"
VerticalAlignment="Center" Icon="&#xf0e2;"
FontSize="14" Sub="{DynamicResource hotkeyPresetsToolTip}">
Foreground="{DynamicResource Color05B}" <StackPanel>
Text="{DynamicResource customQueryHotkey}" /> <cc:Card
<ListView Title="{DynamicResource OpenContainFolderHotkey}"
Grid.Row="5" Icon="&#xe8b7;"
MinHeight="160" Type="Inside">
Margin="0,0,0,0" <cc:HotkeyDisplay Keys="Ctrl+Enter" />
Background="{DynamicResource Color02B}" </cc:Card>
BorderBrush="DarkGray" <cc:Card
BorderThickness="1" Title="{DynamicResource RunAsAdminHotkey}"
ItemsSource="{Binding Settings.CustomPluginHotkeys}" Icon="&#xe7ef;"
SelectedItem="{Binding SelectedCustomPluginHotkey}" Type="Inside">
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}"> <cc:HotkeyDisplay Keys="Ctrl+Shift+Enter" />
<ListView.View> </cc:Card>
<GridView> <cc:Card
<GridViewColumn Width="180" Header="{DynamicResource hotkey}"> Title="{DynamicResource ToggleHistoryHotkey}"
<GridViewColumn.CellTemplate> Icon="&#xf738;"
<DataTemplate DataType="userSettings:CustomPluginHotkey"> Type="Inside">
<TextBlock Text="{Binding Hotkey}" /> <cc:HotkeyDisplay Keys="Ctrl+H" />
</DataTemplate> </cc:Card>
</GridViewColumn.CellTemplate> <cc:Card
</GridViewColumn> Title="{DynamicResource CopyFilePathHotkey}"
<GridViewColumn Width="430" Header="{DynamicResource customQuery}"> Icon="&#xe8c8;"
<GridViewColumn.CellTemplate> Type="Inside">
<DataTemplate DataType="userSettings:CustomPluginHotkey"> <cc:HotkeyDisplay Keys="Ctrl+Shift+C" />
<TextBlock Text="{Binding ActionKeyword}" /> </cc:Card>
</DataTemplate> <cc:Card
</GridViewColumn.CellTemplate> Title="{DynamicResource OpenContextMenuHotkey}"
</GridViewColumn> Icon="&#xede3;"
</GridView> Type="Inside">
</ListView.View> <flowlauncher:HotkeyControl
</ListView> DefaultHotkey="Ctrl+I"
<StackPanel Hotkey="{Binding Settings.OpenContextMenuHotkey}"
Grid.Row="6" ValidateKeyGesture="False" />
Margin="0" </cc:Card>
HorizontalAlignment="Right" <cc:Card
VerticalAlignment="Top" Title="{DynamicResource OpenContextMenuHotkey}"
Orientation="Horizontal"> Icon="&#xede3;"
<Button Type="Inside">
MinWidth="100" <cc:HotkeyDisplay Keys="Shift+Enter" />
Margin="10" </cc:Card>
Click="OnDeleteCustomHotkeyClick"
Content="{DynamicResource delete}" /> <cc:Card
<Button Title="{DynamicResource SettingWindowHotkey}"
MinWidth="100" Icon="&#xe713;"
Margin="10" Type="Inside">
Click="OnEditCustomHotkeyClick" <flowlauncher:HotkeyControl
Content="{DynamicResource edit}" /> DefaultHotkey="Ctrl+I"
<Button Hotkey="{Binding Settings.SettingWindowHotkey}"
MinWidth="100" ValidateKeyGesture="False" />
Margin="10,10,0,10" </cc:Card>
Click="OnAddCustomHotkeyClick" <cc:Card
Content="{DynamicResource add}" /> Title="{DynamicResource ToggleGameModeHotkey}"
Icon="&#xe7fc;"
Type="Inside">
<cc:HotkeyDisplay Keys="Ctrl+Shift+C" />
</cc:Card>
<cc:Card
Title="{DynamicResource ReloadPluginHotkey}"
Icon="&#xe72c;"
Sub="{DynamicResource ReloadPluginHotkeyToolTip}"
Type="Inside">
<cc:HotkeyDisplay Keys="F5" />
</cc:Card>
<cc:Card
Title="{DynamicResource SelectNextPageHotkey}"
Icon="&#xf0ad;"
Type="Inside">
<flowlauncher:HotkeyControl
DefaultHotkey=""
Hotkey="{Binding Settings.SelectNextPageHotkey}"
ValidateKeyGesture="False" />
</cc:Card>
<cc:Card
Title="{DynamicResource SelectPrevPageHotkey}"
Icon="&#xf0ae;"
Type="Inside">
<flowlauncher:HotkeyControl
DefaultHotkey=""
Hotkey="{Binding Settings.SelectPrevPageHotkey}"
ValidateKeyGesture="False" />
</cc:Card>
<cc:Card
Title="{DynamicResource QuickWidthHotkey}"
Icon="&#xe7ea;"
Type="Inside">
<StackPanel Orientation="Horizontal">
<cc:HotkeyDisplay Keys="Ctrl+[" />
<cc:HotkeyDisplay Margin="4,0,0,0" Keys="Ctrl+]" />
</StackPanel>
</cc:Card>
<cc:Card
Title="{DynamicResource QuickHeightHotkey}"
Icon="&#xe7eb;"
Type="Inside">
<StackPanel Orientation="Horizontal">
<cc:HotkeyDisplay Keys="Ctrl+Plus" />
<cc:HotkeyDisplay Margin="4,0,0,0" Keys="Ctrl+Minus" />
</StackPanel>
</cc:Card>
</StackPanel>
</cc:ExCard>
<cc:ExCard
Title="{DynamicResource autoCompleteHotkey}"
Margin="0,14,0,0"
Icon="&#xe893;"
Sub="{DynamicResource autoCompleteHotkeyToolTip}">
<cc:ExCard.SideContent>
<flowlauncher:HotkeyControl
DefaultHotkey="Ctrl+Tab"
Hotkey="{Binding Settings.AutoCompleteHotkey}"
ValidateKeyGesture="False" />
</cc:ExCard.SideContent>
<cc:Card
Title="{DynamicResource autoCompleteHotkey}"
Sub="{DynamicResource AdditionalHotkeyToolTip}"
Type="InsideFit">
<flowlauncher:HotkeyControl
DefaultHotkey=""
Hotkey="{Binding Settings.AutoCompleteHotkey2}"
ValidateKeyGesture="False" />
</cc:Card>
</cc:ExCard>
<cc:ExCard
Title="{DynamicResource SelectNextItemHotkey}"
Margin="0,4,0,0"
Icon="&#xe74b;">
<cc:ExCard.SideContent>
<flowlauncher:HotkeyControl
DefaultHotkey="Tab"
Hotkey="{Binding Settings.SelectNextItemHotkey}"
ValidateKeyGesture="False" />
</cc:ExCard.SideContent>
<cc:Card
Title="{DynamicResource SelectNextItemHotkey}"
Sub="{DynamicResource AdditionalHotkeyToolTip}"
Type="InsideFit">
<flowlauncher:HotkeyControl
DefaultHotkey=""
Hotkey="{Binding Settings.SelectNextItemHotkey2}"
ValidateKeyGesture="False" />
</cc:Card>
</cc:ExCard>
<cc:ExCard
Title="{DynamicResource SelectPrevItemHotkey}"
Margin="0,4,0,0"
Icon="&#xe74a;">
<cc:ExCard.SideContent>
<flowlauncher:HotkeyControl
DefaultHotkey="Shift+Tab"
Hotkey="{Binding Settings.SelectPrevItemHotkey}"
ValidateKeyGesture="False" />
</cc:ExCard.SideContent>
<cc:Card
Title="{DynamicResource SelectPrevItemHotkey}"
Sub="{DynamicResource AdditionalHotkeyToolTip}"
Type="InsideFit">
<flowlauncher:HotkeyControl
DefaultHotkey=""
Hotkey="{Binding Settings.SelectPrevItemHotkey2}"
ValidateKeyGesture="False" />
</cc:Card>
</cc:ExCard>
<cc:ExCard
Title="{DynamicResource customQueryHotkey}"
Margin="0,20,0,0"
Icon="&#xf26c;">
<StackPanel Margin="0,0,0,0">
<Separator
Width="Auto"
Margin="0"
BorderThickness="1"
Style="{StaticResource SettingSeparatorStyle}" />
<StackPanel Margin="18,18,18,0">
<ListView
Grid.Row="5"
MinHeight="160"
Margin="0,0,0,0"
Background="{DynamicResource Color02B}"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding Settings.CustomPluginHotkeys}"
SelectedItem="{Binding SelectedCustomPluginHotkey}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Width="180" Header="{DynamicResource hotkey}">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="userSettings:CustomPluginHotkey">
<TextBlock Text="{Binding Hotkey}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="430" Header="{DynamicResource customQuery}">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="userSettings:CustomPluginHotkey">
<TextBlock Text="{Binding ActionKeyword}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel
Grid.Row="6"
Margin="0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button
MinWidth="100"
Margin="10"
Click="OnDeleteCustomHotkeyClick"
Content="{DynamicResource delete}" />
<Button
MinWidth="100"
Margin="10"
Click="OnEditCustomHotkeyClick"
Content="{DynamicResource edit}" />
<Button
MinWidth="100"
Margin="10,10,0,10"
Click="OnAddCustomHotkeyClick"
Content="{DynamicResource add}" />
</StackPanel>
</StackPanel>
</StackPanel>
</cc:ExCard>
<cc:ExCard
Title="{DynamicResource customQueryShortcut}"
Margin="0,4,0,0"
Icon="&#xf26b;">
<StackPanel>
<Separator
Width="Auto"
Margin="0"
BorderThickness="1"
Style="{StaticResource SettingSeparatorStyle}" />
<StackPanel Margin="18,12,18,0">
<ListView
Grid.Row="8"
MinHeight="160"
Margin="0,6,0,0"
Background="{DynamicResource Color02B}"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding CustomShortcuts}"
SelectedItem="{Binding SelectedCustomShortcut}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Width="180" Header="{DynamicResource customShortcut}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="430" Header="{DynamicResource customShortcutExpansion}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel
Grid.Row="9"
Margin="0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button
MinWidth="100"
Margin="10"
Click="OnDeleteCustomShortCutClick"
Content="{DynamicResource delete}" />
<Button
MinWidth="100"
Margin="10"
Click="OnEditCustomShortCutClick"
Content="{DynamicResource edit}" />
<Button
MinWidth="100"
Margin="10,10,0,10"
Click="OnAddCustomShortCutClick"
Content="{DynamicResource add}" />
</StackPanel>
</StackPanel>
</StackPanel>
</cc:ExCard>
<cc:ExCard
Title="{DynamicResource builtinShortcuts}"
Margin="0,4,0,14"
Icon="&#xf158;">
<StackPanel>
<Separator
Width="Auto"
Margin="0"
BorderThickness="1"
Style="{StaticResource SettingSeparatorStyle}" />
<StackPanel Margin="16,8,16,0">
<ListView
Grid.Row="11"
MinHeight="160"
Margin="0,6,0,16"
Background="{DynamicResource Color02B}"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding BuiltinShortcuts}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Width="180" Header="{DynamicResource customShortcut}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="430" Header="{DynamicResource builtinShortcutDescription}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description, Converter={StaticResource TranslationConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</StackPanel>
</cc:ExCard>
</StackPanel> </StackPanel>
<TextBlock
Grid.Row="7"
Margin="0,0,12,2"
Padding="0,12,0,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource Color05B}"
Text="{DynamicResource customQueryShortcut}" />
<ListView
Name="customShortcutView"
Grid.Row="8"
MinHeight="160"
Margin="0,6,0,0"
Background="{DynamicResource Color02B}"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding CustomShortcuts}"
SelectedItem="{Binding SelectedCustomShortcut}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Width="180" Header="{DynamicResource customShortcut}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="430" Header="{DynamicResource customShortcutExpansion}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel
Grid.Row="9"
Margin="0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button
MinWidth="100"
Margin="10"
Click="OnDeleteCustomShortCutClick"
Content="{DynamicResource delete}" />
<Button
MinWidth="100"
Margin="10"
Click="OnEditCustomShortCutClick"
Content="{DynamicResource edit}" />
<Button
MinWidth="100"
Margin="10,10,0,10"
Click="OnAddCustomShortCutClick"
Content="{DynamicResource add}" />
</StackPanel>
<TextBlock
Grid.Row="10"
Margin="0,0,12,2"
Padding="0,12,0,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource Color05B}"
Text="{DynamicResource builtinShortcuts}" />
<ListView
Grid.Row="11"
MinHeight="160"
Margin="0,6,0,20"
Background="{DynamicResource Color02B}"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding BuiltinShortcuts}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Width="180" Header="{DynamicResource customShortcut}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="430" Header="{DynamicResource builtinShortcutDescription}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description, Converter={StaticResource TranslationConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>

View file

@ -17,6 +17,7 @@ using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop; using System.Windows.Interop;
using System.Windows.Navigation; using System.Windows.Navigation;
using NHotkey;
using Button = System.Windows.Controls.Button; using Button = System.Windows.Controls.Button;
using Control = System.Windows.Controls.Control; using Control = System.Windows.Controls.Control;
using KeyEventArgs = System.Windows.Input.KeyEventArgs; using KeyEventArgs = System.Windows.Input.KeyEventArgs;
@ -110,41 +111,9 @@ namespace Flow.Launcher
#region Hotkey #region Hotkey
private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e) private void OnToggleHotkey(object sender, HotkeyEventArgs e)
{ {
_ = HotkeyControl.SetHotkeyAsync(viewModel.Settings.Hotkey, false); HotKeyMapper.OnToggleHotkey(sender, e);
}
private void OnHotkeyControlFocused(object sender, RoutedEventArgs e)
{
HotKeyMapper.RemoveHotkey(settings.Hotkey);
}
private void OnHotkeyControlFocusLost(object sender, RoutedEventArgs e)
{
if (HotkeyControl.CurrentHotkeyAvailable)
{
HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
HotKeyMapper.RemoveHotkey(settings.Hotkey);
settings.Hotkey = HotkeyControl.CurrentHotkey.ToString();
}
else
{
HotKeyMapper.SetHotkey(new HotkeyModel(settings.Hotkey), HotKeyMapper.OnToggleHotkey);
}
}
private void OnPreviewHotkeyControlLoaded(object sender, RoutedEventArgs e)
{
_ = PreviewHotkeyControl.SetHotkeyAsync(settings.PreviewHotkey, false);
}
private void OnPreviewHotkeyControlFocusLost(object sender, RoutedEventArgs e)
{
if (PreviewHotkeyControl.CurrentHotkeyAvailable)
{
settings.PreviewHotkey = PreviewHotkeyControl.CurrentHotkey.ToString();
}
} }
private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e) private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e)
@ -391,7 +360,7 @@ namespace Flow.Launcher
{ {
if (viewModel.EditSelectedCustomShortcut()) if (viewModel.EditSelectedCustomShortcut())
{ {
customShortcutView.Items.Refresh(); //customShortcutView.Items.Refresh(); Should Fix
} }
} }

View file

@ -80,6 +80,36 @@ namespace Flow.Launcher.ViewModel
case nameof(Settings.PreviewHotkey): case nameof(Settings.PreviewHotkey):
OnPropertyChanged(nameof(PreviewHotkey)); OnPropertyChanged(nameof(PreviewHotkey));
break; break;
case nameof(Settings.AutoCompleteHotkey):
OnPropertyChanged(nameof(AutoCompleteHotkey));
break;
case nameof(Settings.AutoCompleteHotkey2):
OnPropertyChanged(nameof(AutoCompleteHotkey2));
break;
case nameof(Settings.SelectNextItemHotkey):
OnPropertyChanged(nameof(SelectNextItemHotkey));
break;
case nameof(Settings.SelectNextItemHotkey2):
OnPropertyChanged(nameof(SelectNextItemHotkey2));
break;
case nameof(Settings.SelectPrevItemHotkey):
OnPropertyChanged(nameof(SelectPrevItemHotkey));
break;
case nameof(Settings.SelectPrevItemHotkey2):
OnPropertyChanged(nameof(SelectPrevItemHotkey2));
break;
case nameof(Settings.SelectNextPageHotkey):
OnPropertyChanged(nameof(SelectNextPageHotkey));
break;
case nameof(Settings.SelectPrevPageHotkey):
OnPropertyChanged(nameof(SelectPrevPageHotkey));
break;
case nameof(Settings.OpenContextMenuHotkey):
OnPropertyChanged(nameof(OpenContextMenuHotkey));
break;
case nameof(Settings.SettingWindowHotkey):
OnPropertyChanged(nameof(SettingWindowHotkey));
break;
} }
}; };
@ -342,6 +372,13 @@ namespace Flow.Launcher.ViewModel
SelectedResults.SelectFirstResult(); SelectedResults.SelectFirstResult();
} }
[RelayCommand]
private void SelectLastResult()
{
SelectedResults.SelectLastResult();
}
[RelayCommand] [RelayCommand]
private void SelectPrevPage() private void SelectPrevPage()
{ {
@ -627,25 +664,33 @@ namespace Flow.Launcher.ViewModel
public string OpenResultCommandModifiers => Settings.OpenResultModifiers; public string OpenResultCommandModifiers => Settings.OpenResultModifiers;
public string PreviewHotkey public string VerifyOrSetDefaultHotkey(string hotkey, string defaultHotkey)
{ {
get try
{ {
// TODO try to patch issue #1755 var converter = new KeyGestureConverter();
// Added in v1.14.0, remove after v1.16.0. var key = (KeyGesture)converter.ConvertFromString(hotkey);
try
{
var converter = new KeyGestureConverter();
var key = (KeyGesture)converter.ConvertFromString(Settings.PreviewHotkey);
}
catch (Exception e) when (e is NotSupportedException || e is InvalidEnumArgumentException)
{
Settings.PreviewHotkey = "F1";
}
return Settings.PreviewHotkey;
} }
catch (Exception e) when (e is NotSupportedException || e is InvalidEnumArgumentException)
{
return defaultHotkey;
}
return hotkey;
} }
public string PreviewHotkey => VerifyOrSetDefaultHotkey(Settings.PreviewHotkey, "F1");
public string AutoCompleteHotkey => VerifyOrSetDefaultHotkey(Settings.AutoCompleteHotkey, "Ctrl+Tab");
public string AutoCompleteHotkey2 => VerifyOrSetDefaultHotkey(Settings.AutoCompleteHotkey2, "");
public string SelectNextItemHotkey => VerifyOrSetDefaultHotkey(Settings.SelectNextItemHotkey, "Tab");
public string SelectNextItemHotkey2 => VerifyOrSetDefaultHotkey(Settings.SelectNextItemHotkey2, "");
public string SelectPrevItemHotkey => VerifyOrSetDefaultHotkey(Settings.SelectPrevItemHotkey, "Shift+Tab");
public string SelectPrevItemHotkey2 => VerifyOrSetDefaultHotkey(Settings.SelectPrevItemHotkey2, "");
public string SelectNextPageHotkey => VerifyOrSetDefaultHotkey(Settings.SelectNextPageHotkey, "");
public string SelectPrevPageHotkey => VerifyOrSetDefaultHotkey(Settings.SelectPrevPageHotkey, "");
public string OpenContextMenuHotkey => VerifyOrSetDefaultHotkey(Settings.OpenContextMenuHotkey, "Ctrl+O");
public string SettingWindowHotkey => VerifyOrSetDefaultHotkey(Settings.SettingWindowHotkey, "Ctrl+I");
public string Image => Constant.QueryTextBoxIconImagePath; public string Image => Constant.QueryTextBoxIconImagePath;

View file

@ -117,6 +117,11 @@ namespace Flow.Launcher.ViewModel
SelectedIndex = NewIndex(0); SelectedIndex = NewIndex(0);
} }
public void SelectLastResult()
{
SelectedIndex = NewIndex(Results.Count - 1);
}
public void Clear() public void Clear()
{ {
lock (_collectionLock) lock (_collectionLock)

View file

@ -22,6 +22,8 @@ using Flow.Launcher.Plugin.SharedModels;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using System.Globalization; using System.Globalization;
using System.Runtime.CompilerServices;
using Flow.Launcher.Infrastructure.Hotkey;
namespace Flow.Launcher.ViewModel namespace Flow.Launcher.ViewModel
{ {
@ -68,7 +70,12 @@ namespace Flow.Launcher.ViewModel
break; break;
} }
}; };
}
[RelayCommand]
public void SetTogglingHotkey(HotkeyModel hotkey)
{
HotKeyMapper.SetHotkey(hotkey, HotKeyMapper.OnToggleHotkey);
} }
public Settings Settings { get; set; } public Settings Settings { get; set; }
@ -110,13 +117,15 @@ namespace Flow.Launcher.ViewModel
} }
catch (Exception e) catch (Exception e)
{ {
Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), e.Message); Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"),
e.Message);
} }
} }
} }
// This is only required to set at startup. When portable mode enabled/disabled a restart is always required // This is only required to set at startup. When portable mode enabled/disabled a restart is always required
private bool _portableMode = DataLocation.PortableDataLocationInUse(); private bool _portableMode = DataLocation.PortableDataLocationInUse();
public bool PortableMode public bool PortableMode
{ {
get => _portableMode; get => _portableMode;
@ -185,6 +194,7 @@ namespace Flow.Launcher.ViewModel
} }
private List<LastQueryMode> _lastQueryModes = new List<LastQueryMode>(); private List<LastQueryMode> _lastQueryModes = new List<LastQueryMode>();
public List<LastQueryMode> LastQueryModes public List<LastQueryMode> LastQueryModes
{ {
get get
@ -193,6 +203,7 @@ namespace Flow.Launcher.ViewModel
{ {
_lastQueryModes = InitLastQueryModes(); _lastQueryModes = InitLastQueryModes();
} }
return _lastQueryModes; return _lastQueryModes;
} }
} }
@ -200,17 +211,16 @@ namespace Flow.Launcher.ViewModel
private List<LastQueryMode> InitLastQueryModes() private List<LastQueryMode> InitLastQueryModes()
{ {
var modes = new List<LastQueryMode>(); var modes = new List<LastQueryMode>();
var enums = (Infrastructure.UserSettings.LastQueryMode[])Enum.GetValues(typeof(Infrastructure.UserSettings.LastQueryMode)); var enums = (Infrastructure.UserSettings.LastQueryMode[])Enum.GetValues(
typeof(Infrastructure.UserSettings.LastQueryMode));
foreach (var e in enums) foreach (var e in enums)
{ {
var key = $"LastQuery{e}"; var key = $"LastQuery{e}";
var display = _translater.GetTranslation(key); var display = _translater.GetTranslation(key);
var m = new LastQueryMode var m = new LastQueryMode { Display = display, Value = e, };
{
Display = display, Value = e,
};
modes.Add(m); modes.Add(m);
} }
return modes; return modes;
} }
@ -267,15 +277,15 @@ namespace Flow.Launcher.ViewModel
public List<string> OpenResultModifiersList => new List<string> public List<string> OpenResultModifiersList => new List<string>
{ {
KeyConstant.Alt, KeyConstant.Alt, KeyConstant.Ctrl, $"{KeyConstant.Ctrl}+{KeyConstant.Alt}"
KeyConstant.Ctrl,
$"{KeyConstant.Ctrl}+{KeyConstant.Alt}"
}; };
private Internationalization _translater => InternationalizationManager.Instance; private Internationalization _translater => InternationalizationManager.Instance;
public List<Language> Languages => _translater.LoadAvailableLanguages(); public List<Language> Languages => _translater.LoadAvailableLanguages();
public IEnumerable<int> MaxResultsRange => Enumerable.Range(2, 16); public IEnumerable<int> MaxResultsRange => Enumerable.Range(2, 16);
public string AlwaysPreviewToolTip => string.Format(_translater.GetTranslation("AlwaysPreviewToolTip"), Settings.PreviewHotkey); public string AlwaysPreviewToolTip =>
string.Format(_translater.GetTranslation("AlwaysPreviewToolTip"), Settings.PreviewHotkey);
public string TestProxy() public string TestProxy()
{ {
@ -285,6 +295,7 @@ namespace Flow.Launcher.ViewModel
{ {
return InternationalizationManager.Instance.GetTranslation("serverCantBeEmpty"); return InternationalizationManager.Instance.GetTranslation("serverCantBeEmpty");
} }
if (Settings.Proxy.Port <= 0) if (Settings.Proxy.Port <= 0)
{ {
return InternationalizationManager.Instance.GetTranslation("portCantBeEmpty"); return InternationalizationManager.Instance.GetTranslation("portCantBeEmpty");
@ -303,6 +314,7 @@ namespace Flow.Launcher.ViewModel
Credentials = new NetworkCredential(proxyUserName, Settings.Proxy.Password) Credentials = new NetworkCredential(proxyUserName, Settings.Proxy.Password)
}; };
} }
try try
{ {
var response = (HttpWebResponse)request.GetResponse(); var response = (HttpWebResponse)request.GetResponse();
@ -333,10 +345,7 @@ namespace Flow.Launcher.ViewModel
get => PluginManager.AllPlugins get => PluginManager.AllPlugins
.OrderBy(x => x.Metadata.Disabled) .OrderBy(x => x.Metadata.Disabled)
.ThenBy(y => y.Metadata.Name) .ThenBy(y => y.Metadata.Name)
.Select(p => new PluginViewModel .Select(p => new PluginViewModel { PluginPair = p })
{
PluginPair = p
})
.ToList(); .ToList();
} }
@ -383,8 +392,7 @@ namespace Flow.Launcher.ViewModel
await PluginsManifest.UpdateManifestAsync(); await PluginsManifest.UpdateManifestAsync();
OnPropertyChanged(nameof(ExternalPlugins)); OnPropertyChanged(nameof(ExternalPlugins));
} }
internal void DisplayPluginQuery(string queryToDisplay, PluginPair plugin, int actionKeywordPosition = 0) internal void DisplayPluginQuery(string queryToDisplay, PluginPair plugin, int actionKeywordPosition = 0)
{ {
@ -458,12 +466,10 @@ namespace Flow.Launcher.ViewModel
{ {
var key = $"ColorScheme{e}"; var key = $"ColorScheme{e}";
var display = _translater.GetTranslation(key); var display = _translater.GetTranslation(key);
var m = new ColorScheme var m = new ColorScheme { Display = display, Value = e, };
{
Display = display, Value = e,
};
modes.Add(m); modes.Add(m);
} }
return modes; return modes;
} }
} }
@ -484,13 +490,10 @@ namespace Flow.Launcher.ViewModel
{ {
var key = $"SearchWindowScreen{e}"; var key = $"SearchWindowScreen{e}";
var display = _translater.GetTranslation(key); var display = _translater.GetTranslation(key);
var m = new SearchWindowScreen var m = new SearchWindowScreen { Display = display, Value = e, };
{
Display = display,
Value = e,
};
modes.Add(m); modes.Add(m);
} }
return modes; return modes;
} }
} }
@ -511,12 +514,10 @@ namespace Flow.Launcher.ViewModel
{ {
var key = $"SearchWindowAlign{e}"; var key = $"SearchWindowAlign{e}";
var display = _translater.GetTranslation(key); var display = _translater.GetTranslation(key);
var m = new SearchWindowAlign var m = new SearchWindowAlign { Display = display, Value = e, };
{
Display = display, Value = e,
};
modes.Add(m); modes.Add(m);
} }
return modes; return modes;
} }
} }
@ -531,6 +532,7 @@ namespace Flow.Launcher.ViewModel
{ {
screenNumbers.Add(i); screenNumbers.Add(i);
} }
return screenNumbers; return screenNumbers;
} }
} }
@ -617,13 +619,10 @@ namespace Flow.Launcher.ViewModel
{ {
var key = $"AnimationSpeed{e}"; var key = $"AnimationSpeed{e}";
var display = _translater.GetTranslation(key); var display = _translater.GetTranslation(key);
var m = new AnimationSpeed var m = new AnimationSpeed { Display = display, Value = e, };
{
Display = display,
Value = e,
};
speeds.Add(m); speeds.Add(m);
} }
return speeds; return speeds;
} }
} }
@ -690,10 +689,7 @@ namespace Flow.Launcher.ViewModel
bitmap.DecodePixelWidth = 800; bitmap.DecodePixelWidth = 800;
bitmap.DecodePixelHeight = 600; bitmap.DecodePixelHeight = 600;
bitmap.EndInit(); bitmap.EndInit();
var brush = new ImageBrush(bitmap) var brush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill };
{
Stretch = Stretch.UniformToFill
};
return brush; return brush;
} }
else else
@ -714,26 +710,36 @@ namespace Flow.Launcher.ViewModel
new Result new Result
{ {
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleExplorer"), Title = InternationalizationManager.Instance.GetTranslation("SampleTitleExplorer"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleExplorer"), SubTitle =
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png") InternationalizationManager.Instance.GetTranslation("SampleSubTitleExplorer"),
IcoPath =
Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png")
}, },
new Result new Result
{ {
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleWebSearch"), Title = InternationalizationManager.Instance.GetTranslation("SampleTitleWebSearch"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleWebSearch"), SubTitle =
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png") InternationalizationManager.Instance.GetTranslation("SampleSubTitleWebSearch"),
IcoPath =
Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png")
}, },
new Result new Result
{ {
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProgram"), Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProgram"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProgram"), SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProgram"),
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.Program\Images\program.png") IcoPath =
Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.Program\Images\program.png")
}, },
new Result new Result
{ {
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProcessKiller"), Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProcessKiller"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProcessKiller"), SubTitle =
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png") InternationalizationManager.Instance.GetTranslation("SampleSubTitleProcessKiller"),
IcoPath = Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png")
} }
}; };
var vm = new ResultsViewModel(Settings); var vm = new ResultsViewModel(Settings);
@ -889,6 +895,7 @@ namespace Flow.Launcher.ViewModel
SelectedCustomShortcut = item; SelectedCustomShortcut = item;
return true; return true;
} }
return false; return false;
} }
@ -917,6 +924,7 @@ namespace Flow.Launcher.ViewModel
public string Documentation => Constant.Documentation; public string Documentation => Constant.Documentation;
public string Docs => Constant.Docs; public string Docs => Constant.Docs;
public string Github => Constant.GitHub; public string Github => Constant.GitHub;
public string Version public string Version
{ {
get get
@ -931,7 +939,9 @@ namespace Flow.Launcher.ViewModel
} }
} }
} }
public string ActivatedTimes => string.Format(_translater.GetTranslation("about_activate_times"), Settings.ActivateTimes);
public string ActivatedTimes =>
string.Format(_translater.GetTranslation("about_activate_times"), Settings.ActivateTimes);
public string CheckLogFolder public string CheckLogFolder
{ {
@ -939,7 +949,8 @@ namespace Flow.Launcher.ViewModel
{ {
var logFiles = GetLogFiles(); var logFiles = GetLogFiles();
long size = logFiles.Sum(file => file.Length); long size = logFiles.Sum(file => file.Length);
return string.Format("{0} ({1})", _translater.GetTranslation("clearlogfolder"), BytesToReadableString(size)); return string.Format("{0} ({1})", _translater.GetTranslation("clearlogfolder"),
BytesToReadableString(size));
} }
} }
@ -976,10 +987,7 @@ namespace Flow.Launcher.ViewModel
internal static string BytesToReadableString(long bytes) internal static string BytesToReadableString(long bytes)
{ {
const int scale = 1024; const int scale = 1024;
string[] orders = new string[] string[] orders = new string[] { "GB", "MB", "KB", "B" };
{
"GB", "MB", "KB", "B"
};
long max = (long)Math.Pow(scale, orders.Length - 1); long max = (long)Math.Pow(scale, orders.Length - 1);
foreach (string order in orders) foreach (string order in orders)
@ -989,6 +997,7 @@ namespace Flow.Launcher.ViewModel
max /= scale; max /= scale;
} }
return "0 B"; return "0 B";
} }

View file

@ -10,6 +10,10 @@
Title="{DynamicResource Welcome_Page1_Title}" Title="{DynamicResource Welcome_Page1_Title}"
Width="550" Width="550"
Height="650" Height="650"
MinWidth="550"
MinHeight="650"
MaxWidth="550"
MaxHeight="650"
Activated="OnActivated" Activated="OnActivated"
Background="{DynamicResource Color00B}" Background="{DynamicResource Color00B}"
Foreground="{DynamicResource PopupTextColor}" Foreground="{DynamicResource PopupTextColor}"