WIP: new HotkeyControl

This commit is contained in:
Yusyuriv 2024-04-12 17:13:45 +06:00
parent da630039d1
commit 914f400956
No known key found for this signature in database
GPG key ID: A91C52E6F73148E0
4 changed files with 132 additions and 64 deletions

View file

@ -5,14 +5,10 @@
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"
Height="24"
d:DesignHeight="300"
d:DesignHeight="45"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Popup
x:Name="popup"
AllowDrop="True"
@ -43,14 +39,50 @@
</Border>
</Popup>
<TextBox
x:Name="tbHotkey"
Margin="0,0,18,0"
VerticalContentAlignment="Center"
input:InputMethod.IsInputMethodEnabled="False"
GotFocus="tbHotkey_GotFocus"
LostFocus="tbHotkey_LostFocus"
PreviewKeyDown="TbHotkey_OnPreviewKeyDown"
TabIndex="100" />
<Button FontSize="13" FontWeight="Bold" Foreground="{DynamicResource Color01B}" Click="OnButtonClicked">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border
x:Name="ButtonBorder"
Background="{DynamicResource Color12B}"
BorderBrush="{DynamicResource ButtonInsideBorder}"
BorderThickness="1"
CornerRadius="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonBorder" Property="Background" Value="{DynamicResource CustomContextHover}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ButtonBorder" Property="Background" Value="{DynamicResource ButtonMousePressed}" />
<Setter TargetName="ButtonBorder" Property="BorderBrush" Value="{DynamicResource ButtonMousePressedInsideBorder}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
<Button.Content>
<ItemsControl ItemsSource="{Binding Path=KeysToDisplay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
Margin="6"
Padding="10,5,10,5"
Background="{DynamicResource SystemAccentColorLight2Brush}"
BorderThickness="1"
CornerRadius="5"
Height="30">
<TextBlock Text="{Binding}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Button.Content>
</Button>
</Grid>
</UserControl>
</UserControl>

View file

@ -1,4 +1,6 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@ -9,14 +11,37 @@ using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using System.Threading;
using NHotkey;
namespace Flow.Launcher
{
public partial class HotkeyControl : UserControl
public partial class HotkeyControl : UserControl, IDisposable, INotifyPropertyChanged
{
public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register(
nameof(Hotkey),
typeof(string),
typeof(HotkeyControl),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
);
public HotkeyModel CurrentHotkey { get; private set; }
public bool CurrentHotkeyAvailable { get; private set; }
public string Hotkey
{
get => (string)GetValue(HotkeyProperty);
set
{
SetValue(HotkeyProperty, value);
OnPropertyChanged(nameof(KeysToDisplay));
}
}
public string[] KeysToDisplay => Hotkey.Split(" + ");
#nullable enable
public EventHandler<HotkeyEventArgs>? Action { get; set; }
#nullable restore
public event EventHandler HotkeyChanged;
/// <summary>
@ -29,6 +54,28 @@ namespace Flow.Launcher
public HotkeyControl()
{
InitializeComponent();
Loaded += HotkeyControl_Loaded;
}
private void HotkeyControl_LostFocus(object o, RoutedEventArgs routedEventArgs)
{
HotKeyMapper.SetHotkey(CurrentHotkey, Action);
}
private void HotkeyControl_GotFocus(object o, RoutedEventArgs routedEventArgs)
{
HotKeyMapper.RemoveHotkey(Hotkey);
}
private void HotkeyControl_Loaded(object sender, RoutedEventArgs e)
{
_ = SetHotkeyAsync(Hotkey, false);
if (Action is not null)
{
GotFocus += HotkeyControl_GotFocus;
LostFocus += HotkeyControl_LostFocus;
}
}
private CancellationTokenSource hotkeyUpdateSource;
@ -68,8 +115,8 @@ namespace Flow.Launcher
public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true)
{
tbHotkey.Text = keyModel.ToString();
tbHotkey.Select(tbHotkey.Text.Length, 0);
// tbHotkey.Text = keyModel.ToString();
// tbHotkey.Select(tbHotkey.Text.Length, 0);
if (triggerValidate)
{
@ -86,6 +133,7 @@ namespace Flow.Launcher
if (CurrentHotkeyAvailable)
{
CurrentHotkey = keyModel;
Hotkey = keyModel.ToString();
// To trigger LostFocus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null);
Keyboard.ClearFocus();
@ -94,9 +142,10 @@ namespace Flow.Launcher
else
{
CurrentHotkey = keyModel;
Hotkey = keyModel.ToString();
}
}
public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true)
{
return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate);
@ -104,12 +153,12 @@ namespace Flow.Launcher
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
public new bool IsFocused => tbHotkey.IsFocused;
// public new bool IsFocused => tbHotkey.IsFocused;
private void tbHotkey_LostFocus(object sender, RoutedEventArgs e)
{
tbHotkey.Text = CurrentHotkey?.ToString() ?? "";
tbHotkey.Select(tbHotkey.Text.Length, 0);
// tbHotkey.Text = CurrentHotkey?.ToString() ?? "";
// tbHotkey.Select(tbHotkey.Text.Length, 0);
}
private void tbHotkey_GotFocus(object sender, RoutedEventArgs e)
@ -137,5 +186,25 @@ namespace Flow.Launcher
}
tbMsg.Visibility = Visibility.Visible;
}
public void Dispose()
{
hotkeyUpdateSource?.Dispose();
Loaded -= HotkeyControl_Loaded;
GotFocus -= HotkeyControl_GotFocus;
LostFocus -= HotkeyControl_LostFocus;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void OnButtonClicked(object sender, RoutedEventArgs e)
{
// TODO
}
}
}

View file

@ -693,7 +693,7 @@
</ItemsControl>
</Border>
<Border
<Border
Margin="0,30,0,0"
Padding="0"
Style="{DynamicResource SettingGroupBox}">
@ -720,7 +720,7 @@
<ComboBox
x:Name="SelectScreen"
MinWidth="160"
Margin="0,0,18,0"
Margin="0,0,18,0"
VerticalAlignment="Center"
FontSize="14"
ItemsSource="{Binding ScreenNumbers}"
@ -2543,7 +2543,7 @@
TickFrequency="1"
Value="{Binding SoundEffectVolume, Mode=TwoWay}" />
</StackPanel>
<TextBlock Style="{StaticResource Glyph}">
<TextBlock Style="{StaticResource Glyph}">
&#xe994;
</TextBlock>
</ItemsControl>
@ -2657,9 +2657,8 @@
Margin="0,0,0,0"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
GotFocus="OnHotkeyControlFocused"
Loaded="OnHotkeyControlLoaded"
LostFocus="OnHotkeyControlFocusLost" />
Hotkey="{Binding Settings.Hotkey}"
Action="OnToggleHotkey" />
<TextBlock Style="{StaticResource Glyph}">
&#xeda7;
@ -2684,8 +2683,7 @@
Margin="0,0,0,0"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
Loaded="OnPreviewHotkeyControlLoaded"
LostFocus="OnPreviewHotkeyControlFocusLost"
Hotkey="{Binding Settings.PreviewHotkey}"
ValidateKeyGesture="True" />
<TextBlock Style="{StaticResource Glyph}">
&#xe8a1;

View file

@ -17,6 +17,7 @@ using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Navigation;
using NHotkey;
using Button = System.Windows.Controls.Button;
using Control = System.Windows.Controls.Control;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
@ -110,41 +111,9 @@ namespace Flow.Launcher
#region Hotkey
private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e)
private void OnToggleHotkey(object sender, HotkeyEventArgs e)
{
_ = HotkeyControl.SetHotkeyAsync(viewModel.Settings.Hotkey, false);
}
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();
}
HotKeyMapper.OnToggleHotkey(sender, e);
}
private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e)