mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Try implementing HotkeyControl, but with a modal window
This commit is contained in:
parent
15fe1cd643
commit
aaf770afa2
5 changed files with 456 additions and 2 deletions
77
Flow.Launcher/HotkeyControl2.xaml
Normal file
77
Flow.Launcher/HotkeyControl2.xaml
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<UserControl
|
||||
x:Class="Flow.Launcher.HotkeyControl2"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<Button
|
||||
Width="Auto"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Color01B}"
|
||||
Click="GetNewHotkey">
|
||||
<Button.Template>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
x:Name="ButtonBorder"
|
||||
Padding="5,0,5,0"
|
||||
Background="{DynamicResource ButtonBackgroundColor}"
|
||||
BorderBrush="{DynamicResource ButtonInsideBorder}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
<Condition Property="IsPressed" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ButtonMousePressed}" />
|
||||
<Setter TargetName="ButtonBorder" Property="BorderBrush"
|
||||
Value="{DynamicResource ButtonMousePressedInsideBorder}" />
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ButtonMouseOver}" />
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsPressed" Value="True" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ButtonMousePressed}" />
|
||||
<Setter TargetName="ButtonBorder" Property="BorderBrush"
|
||||
Value="{DynamicResource CustomContextHover}" />
|
||||
</MultiTrigger>
|
||||
</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>
|
||||
207
Flow.Launcher/HotkeyControl2.xaml.cs
Normal file
207
Flow.Launcher/HotkeyControl2.xaml.cs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
#nullable enable
|
||||
|
||||
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;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
public partial class HotkeyControl2
|
||||
{
|
||||
public string WindowTitle { get; set; } = string.Empty;
|
||||
|
||||
public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register(
|
||||
nameof(WindowTitle),
|
||||
typeof(string),
|
||||
typeof(HotkeyControl2),
|
||||
new PropertyMetadata(default(string))
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Designed for Preview Hotkey and KeyGesture.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ValidateKeyGestureProperty = DependencyProperty.Register(
|
||||
nameof(ValidateKeyGesture),
|
||||
typeof(bool),
|
||||
typeof(HotkeyControl2),
|
||||
new PropertyMetadata(default(bool))
|
||||
);
|
||||
|
||||
public bool ValidateKeyGesture
|
||||
{
|
||||
get { return (bool)GetValue(ValidateKeyGestureProperty); }
|
||||
set { SetValue(ValidateKeyGestureProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DefaultHotkeyProperty = DependencyProperty.Register(
|
||||
nameof(DefaultHotkey),
|
||||
typeof(string),
|
||||
typeof(HotkeyControl2),
|
||||
new PropertyMetadata(default(string))
|
||||
);
|
||||
|
||||
public string DefaultHotkey
|
||||
{
|
||||
get { return (string)GetValue(DefaultHotkeyProperty); }
|
||||
set { SetValue(DefaultHotkeyProperty, value); }
|
||||
}
|
||||
|
||||
private static void OnHotkeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is not HotkeyControl2 hotkeyControl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hotkeyControl.SetKeysToDisplay(new HotkeyModel(hotkeyControl.Hotkey));
|
||||
hotkeyControl.CurrentHotkey = new HotkeyModel(hotkeyControl.Hotkey);
|
||||
}
|
||||
|
||||
|
||||
public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register(
|
||||
nameof(ChangeHotkey),
|
||||
typeof(ICommand),
|
||||
typeof(HotkeyControl2),
|
||||
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(HotkeyControl2),
|
||||
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHotkeyChanged)
|
||||
);
|
||||
|
||||
public string Hotkey
|
||||
{
|
||||
get { return (string)GetValue(HotkeyProperty); }
|
||||
set { SetValue(HotkeyProperty, value); }
|
||||
}
|
||||
|
||||
public HotkeyControl2()
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Hotkey))
|
||||
{
|
||||
HotKeyMapper.RemoveHotkey(Hotkey);
|
||||
}
|
||||
|
||||
var owner = Window.GetWindow(this);
|
||||
var width = owner?.ActualWidth ?? 0;
|
||||
var height = owner?.ActualHeight ?? 0;
|
||||
var w = new HotkeyControl2Dialog
|
||||
{
|
||||
Title = WindowTitle,
|
||||
Owner = owner,
|
||||
Width = width,
|
||||
Height = height
|
||||
};
|
||||
w.ShowDialog();
|
||||
switch (w.ResultType)
|
||||
{
|
||||
case HotkeyControl2Dialog.EResultType.Cancel:
|
||||
return;
|
||||
case HotkeyControl2Dialog.EResultType.Save:
|
||||
SetHotkey(w.ResultValue);
|
||||
break;
|
||||
case HotkeyControl2Dialog.EResultType.Reset:
|
||||
ResetToDefault();
|
||||
break;
|
||||
case HotkeyControl2Dialog.EResultType.Delete:
|
||||
Delete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetToDefault()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Hotkey))
|
||||
HotKeyMapper.RemoveHotkey(Hotkey);
|
||||
Hotkey = DefaultHotkey;
|
||||
CurrentHotkey = new HotkeyModel(Hotkey);
|
||||
|
||||
SetKeysToDisplay(CurrentHotkey);
|
||||
|
||||
SetHotkey(CurrentHotkey);
|
||||
}
|
||||
|
||||
|
||||
private void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true)
|
||||
{
|
||||
if (triggerValidate)
|
||||
{
|
||||
bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture);
|
||||
|
||||
if (!hotkeyAvailable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Hotkey = keyModel.ToString();
|
||||
SetKeysToDisplay(CurrentHotkey);
|
||||
ChangeHotkey?.Execute(keyModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
Hotkey = keyModel.ToString();
|
||||
ChangeHotkey?.Execute(keyModel);
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Hotkey))
|
||||
HotKeyMapper.RemoveHotkey(Hotkey);
|
||||
Hotkey = "";
|
||||
SetKeysToDisplay(new HotkeyModel(false, false, false, false, Key.None));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetHotkey(string? keyStr, bool triggerValidate = true)
|
||||
{
|
||||
SetHotkey(new HotkeyModel(keyStr), triggerValidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Flow.Launcher/HotkeyControl2Dialog.xaml
Normal file
76
Flow.Launcher/HotkeyControl2Dialog.xaml
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<Window x:Class="Flow.Launcher.HotkeyControl2Dialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Width="400"
|
||||
Height="300"
|
||||
MinWidth="400"
|
||||
MinHeight="300"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
Icon="Images\app.ico"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Background="Transparent"
|
||||
AllowsTransparency="True"
|
||||
WindowStyle="None"
|
||||
PreviewKeyDown="OnPreviewKeyDown">
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome
|
||||
CaptionHeight="0"
|
||||
GlassFrameThickness="0" />
|
||||
</WindowChrome.WindowChrome>
|
||||
<Border Background="#AA000000" CornerRadius="8">
|
||||
<Border Background="DarkGray" Width="400" Height="300" HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
CornerRadius="8">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding Title}" />
|
||||
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center">
|
||||
<ItemsControl ItemsSource="{Binding KeysToDisplay}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="Red" CornerRadius="6" Padding="8" Margin="0 0 10 0">
|
||||
<TextBlock Text="{Binding}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="0" Grid.Column="1" Background="Gray" CornerRadius="0 8 0 0">
|
||||
<StackPanel>
|
||||
<Button Content="Reset" Click="Reset" />
|
||||
<Button Content="Delete" Click="Delete" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Background="Black" CornerRadius="0 0 8 8">
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal" Margin="10">
|
||||
|
||||
<Button Content="Save" Margin="0 0 10 0" Click="Save" />
|
||||
<Button Content="Cancel" Click="Cancel" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</Window>
|
||||
93
Flow.Launcher/HotkeyControl2Dialog.xaml.cs
Normal file
93
Flow.Launcher/HotkeyControl2Dialog.xaml.cs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Flow.Launcher.Core.Resource;
|
||||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Plugin;
|
||||
|
||||
namespace Flow.Launcher;
|
||||
|
||||
public partial class HotkeyControl2Dialog : Window
|
||||
{
|
||||
public string Hotkey { get; set; } = string.Empty;
|
||||
public HotkeyModel CurrentHotkey { get; set; } = new(false, false, false, false, Key.None);
|
||||
public ObservableCollection<string> KeysToDisplay { get; set; } = new();
|
||||
|
||||
public enum EResultType
|
||||
{
|
||||
Cancel,
|
||||
Save,
|
||||
Reset,
|
||||
Delete
|
||||
}
|
||||
|
||||
public EResultType ResultType { get; private set; } = EResultType.Cancel;
|
||||
public string ResultValue { get; private set; } = string.Empty;
|
||||
public string EmptyHotkey => InternationalizationManager.Instance.GetTranslation("none");
|
||||
public HotkeyControl2Dialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Reset(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
ResultType = EResultType.Reset;
|
||||
Close();
|
||||
}
|
||||
|
||||
public void Delete(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
ResultType = EResultType.Delete;
|
||||
Close();
|
||||
}
|
||||
|
||||
public void Cancel(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
ResultType = EResultType.Cancel;
|
||||
Close();
|
||||
}
|
||||
|
||||
public void Save(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
ResultType = EResultType.Save;
|
||||
ResultValue = string.Join("+", KeysToDisplay);
|
||||
Close();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2641,7 +2641,7 @@
|
|||
Title="{DynamicResource flowlauncherHotkey}"
|
||||
Icon=""
|
||||
Sub="{DynamicResource flowlauncherHotkeyToolTip}">
|
||||
<flowlauncher:HotkeyControl
|
||||
<flowlauncher:HotkeyControl2
|
||||
ChangeHotkey="{Binding SetTogglingHotkeyCommand}"
|
||||
DefaultHotkey="Alt+Space"
|
||||
Hotkey="{Binding Settings.Hotkey}"
|
||||
|
|
@ -2654,9 +2654,10 @@
|
|||
Title="{DynamicResource previewHotkey}"
|
||||
Icon=""
|
||||
Sub="{DynamicResource previewHotkeyToolTip}">
|
||||
<flowlauncher:HotkeyControl
|
||||
<flowlauncher:HotkeyControl2
|
||||
DefaultHotkey="F1"
|
||||
Hotkey="{Binding Settings.PreviewHotkey}"
|
||||
WindowTitle="Preview hotkey"
|
||||
ValidateKeyGesture="False" />
|
||||
</cc:Card>
|
||||
</StackPanel>
|
||||
|
|
|
|||
Loading…
Reference in a new issue