Fix duplicate modifier and clean up code

This commit is contained in:
Hongtao Zhang 2024-04-17 23:10:31 -05:00
parent fd620f4ea8
commit 1d858d3357
2 changed files with 71 additions and 124 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

@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
@ -13,12 +11,13 @@ 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 Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel; using JetBrains.Annotations;
using NHotkey;
#nullable enable
namespace Flow.Launcher namespace Flow.Launcher
{ {
public partial class HotkeyControl : UserControl, INotifyPropertyChanged public partial class HotkeyControl : INotifyPropertyChanged
{ {
/// <summary> /// <summary>
/// Designed for Preview Hotkey and KeyGesture. /// Designed for Preview Hotkey and KeyGesture.
@ -42,29 +41,32 @@ namespace Flow.Launcher
set { SetValue(DefaultHotkeyProperty, value); } set { SetValue(DefaultHotkeyProperty, value); }
} }
public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register(
nameof(Hotkey), typeof(string), typeof(HotkeyControl),
new PropertyMetadata(default(string), OnHotkeyChanged));
private static void OnHotkeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnHotkeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {
if (d is HotkeyControl hotkeyControl) if (d is not HotkeyControl hotkeyControl)
{ {
hotkeyControl.SetKeysToDisplay(new HotkeyModel(hotkeyControl.Hotkey)); return;
hotkeyControl.CurrentHotkey = new HotkeyModel(hotkeyControl.Hotkey);
} }
hotkeyControl.SetKeysToDisplay(new HotkeyModel(hotkeyControl.Hotkey));
hotkeyControl.CurrentHotkey = new HotkeyModel(hotkeyControl.Hotkey);
} }
public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register( public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register(
nameof(ChangeHotkey), typeof(ICommand), typeof(HotkeyControl), new PropertyMetadata(default(ICommand))); nameof(ChangeHotkey), typeof(ICommand), typeof(HotkeyControl), new PropertyMetadata(default(ICommand)));
public ICommand ChangeHotkey public ICommand? ChangeHotkey
{ {
get { return (ICommand)GetValue(ChangeHotkeyProperty); } get { return (ICommand)GetValue(ChangeHotkeyProperty); }
set { SetValue(ChangeHotkeyProperty, value); } set { SetValue(ChangeHotkeyProperty, value); }
} }
public static readonly DependencyProperty HotkeyProperty = DependencyProperty.Register(
nameof(Hotkey), typeof(string), typeof(HotkeyControl),
new PropertyMetadata("", OnHotkeyChanged));
public string Hotkey public string Hotkey
{ {
get { return (string)GetValue(HotkeyProperty); } get { return (string)GetValue(HotkeyProperty); }
@ -122,19 +124,13 @@ namespace Flow.Launcher
tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B"); tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B");
} }
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
private void HotkeyBtn_OnLostFocus(object sender, RoutedEventArgs e)
{
HotkeyBtn.IsChecked = false;
RegisterHotkey();
}
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) =>
hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
@ -162,7 +158,7 @@ namespace Flow.Launcher
public ObservableCollection<string> KeysToDisplay { get; set; } = new ObservableCollection<string>(); public ObservableCollection<string> KeysToDisplay { get; set; } = new ObservableCollection<string>();
public HotkeyModel CurrentHotkey { get; private set; } public HotkeyModel CurrentHotkey { get; private set; } = new(false, false, false, false, Key.None);
public void StartRecording() public void StartRecording()
@ -186,7 +182,7 @@ namespace Flow.Launcher
try try
{ {
var converter = new KeyGestureConverter(); var converter = new KeyGestureConverter();
var key = (KeyGesture)converter.ConvertFromString(CurrentHotkey.ToString())!; _ = (KeyGesture)converter.ConvertFromString(CurrentHotkey.ToString())!;
} }
catch (Exception e) when (e is NotSupportedException or InvalidEnumArgumentException) catch (Exception e) when (e is NotSupportedException or InvalidEnumArgumentException)
{ {
@ -226,12 +222,14 @@ namespace Flow.Launcher
bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture); bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture);
SetMessage(hotkeyAvailable ? "success" : "hotkeyUnavailable", !hotkeyAvailable); SetMessage(hotkeyAvailable ? "success" : "hotkeyUnavailable", !hotkeyAvailable);
if (hotkeyAvailable) if (!hotkeyAvailable)
{ {
Hotkey = keyModel.ToString(); return;
SetKeysToDisplay(CurrentHotkey);
ChangeHotkey?.Execute(keyModel);
} }
Hotkey = keyModel.ToString();
SetKeysToDisplay(CurrentHotkey);
ChangeHotkey?.Execute(keyModel);
} }
else else
{ {
@ -245,62 +243,24 @@ namespace Flow.Launcher
if (!string.IsNullOrEmpty(Hotkey)) if (!string.IsNullOrEmpty(Hotkey))
HotKeyMapper.RemoveHotkey(Hotkey); HotKeyMapper.RemoveHotkey(Hotkey);
Hotkey = ""; Hotkey = "";
SetKeysToDisplay(KeysToDisplay, new List<string>()); SetKeysToDisplay(new HotkeyModel(false, false, false, false, Key.None));
HotkeyBtn.IsChecked = false; HotkeyBtn.IsChecked = false;
} }
private void SetKeysToDisplay(HotkeyModel hotkey) private void SetKeysToDisplay(HotkeyModel? hotkey)
{ {
KeysToDisplay.Clear(); KeysToDisplay.Clear();
if (hotkey.Alt)
{
KeysToDisplay.Add("Alt");
}
if (hotkey.Ctrl) if (hotkey == null || hotkey == default(HotkeyModel))
{
KeysToDisplay.Add("Ctrl");
}
if (hotkey.Shift)
{
KeysToDisplay.Add("Shift");
}
if (hotkey.Win)
{
KeysToDisplay.Add("Win");
}
if (hotkey.CharKey != Key.None)
{
KeysToDisplay.Add(hotkey.CharKey.ToString());
}
}
private void SetKeysToDisplay(ICollection<string> container, ICollection<string>? keys)
{
container.Clear();
if (keys == null)
{ {
KeysToDisplay.Add(EmptyHotkey);
return; return;
} }
foreach (var key in keys) foreach (var key in hotkey.Value.EnumerateDisplayKeys()!)
{ {
container.Add(key); KeysToDisplay.Add(key);
} }
if (!keys.Any())
{
container.Add(EmptyHotkey);
}
}
public void RegisterHotkey()
{
SetHotkey(Hotkey, true);
} }
public void SetHotkey(string? keyStr, bool triggerValidate = true) public void SetHotkey(string? keyStr, bool triggerValidate = true)
@ -309,29 +269,12 @@ namespace Flow.Launcher
} }
private void HotkeyBtn_OnChecked(object sender, RoutedEventArgs e) private void HotkeyBtn_OnChecked(object sender, RoutedEventArgs e) => StartRecording();
{
StartRecording();
}
private void HotkeyBtn_OnUnchecked(object sender, RoutedEventArgs e)
{
StopRecording();
}
private void ResetButton_OnClick(object sender, RoutedEventArgs e) private void ResetButton_OnClick(object sender, RoutedEventArgs e) => ResetToDefault();
{ private void DeleteBtn_OnClick(object sender, RoutedEventArgs e) => Delete();
ResetToDefault();
}
private void DeleteBtn_OnClick(object sender, RoutedEventArgs e) private void StopRecordingBtn_Click(object sender, RoutedEventArgs e) => StopRecording();
{
Delete();
}
public void StopRecordingBtn_Click(object sender, RoutedEventArgs e)
{
StopRecording();
}
} }
} }