Revise Hotkey Structure

- Put all logic to HotkeyControlViewModel.cs
- Remove logic about GetFocus/LostFocus
- RegisterCallBack (Delegate)
This commit is contained in:
Hongtao Zhang 2024-04-12 11:10:25 -05:00
parent 6e34218f8e
commit 453f767188
9 changed files with 354 additions and 266 deletions

View file

@ -2,6 +2,7 @@
x:Class="Flow.Launcher.CustomQueryHotkeySetting"
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:flowlauncher="clr-namespace:Flow.Launcher"
Title="{DynamicResource customeQueryHotkeyTitle}"
Width="530"
@ -11,7 +12,8 @@
MouseDown="window_MouseDown"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen">
WindowStartupLocation="CenterScreen"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
@ -104,7 +106,7 @@
Grid.Column="1"
Orientation="Horizontal">
<flowlauncher:HotkeyControl
x:Name="ctlHotkey"
DataContext="{Binding HotkeyControlViewModel}"
Grid.Column="1"
Width="200"
Height="36"

View file

@ -6,6 +6,7 @@ using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher
{
@ -32,7 +33,7 @@ namespace Flow.Launcher
{
if (!update)
{
if (!ctlHotkey.CurrentHotkeyAvailable)
if (!HotkeyControlViewModel.CurrentHotkeyAvailable)
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("hotkeyIsNotUnavailable"));
return;
@ -45,8 +46,7 @@ namespace Flow.Launcher
var pluginHotkey = new CustomPluginHotkey
{
Hotkey = ctlHotkey.CurrentHotkey.ToString(),
ActionKeyword = tbAction.Text
Hotkey = HotkeyControlViewModel.CurrentHotkey.ToString(), ActionKeyword = tbAction.Text
};
_settings.CustomPluginHotkeys.Add(pluginHotkey);
@ -54,14 +54,16 @@ namespace Flow.Launcher
}
else
{
if (updateCustomHotkey.Hotkey != ctlHotkey.CurrentHotkey.ToString() && !ctlHotkey.CurrentHotkeyAvailable)
if (updateCustomHotkey.Hotkey != HotkeyControlViewModel.CurrentHotkey.ToString() &&
!HotkeyControlViewModel.CurrentHotkeyAvailable)
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("hotkeyIsNotUnavailable"));
return;
}
var oldHotkey = updateCustomHotkey.Hotkey;
updateCustomHotkey.ActionKeyword = tbAction.Text;
updateCustomHotkey.Hotkey = ctlHotkey.CurrentHotkey.ToString();
updateCustomHotkey.Hotkey = HotkeyControlViewModel.CurrentHotkey.ToString();
//remove origin hotkey
HotKeyMapper.RemoveHotkey(oldHotkey);
HotKeyMapper.SetCustomQueryHotkey(updateCustomHotkey);
@ -70,9 +72,12 @@ namespace Flow.Launcher
Close();
}
public HotkeyControlViewModel HotkeyControlViewModel { get; set; } = new HotkeyControlViewModel();
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)
{
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey"));
@ -81,7 +86,7 @@ namespace Flow.Launcher
}
tbAction.Text = updateCustomHotkey.ActionKeyword;
_ = ctlHotkey.SetHotkeyAsync(updateCustomHotkey.Hotkey, false);
_ = HotkeyControlViewModel.SetHotkeyAsync(updateCustomHotkey.Hotkey, false);
update = true;
lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update");
}

View file

@ -5,8 +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"
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
d:DesignWidth="300"
mc:Ignorable="d">
mc:Ignorable="d"
d:DataContext="{d:DesignInstance vm:HotkeyControlViewModel}">
<Grid>
<Popup
x:Name="popup"
@ -43,9 +45,10 @@
FontSize="13"
FontWeight="Bold"
Foreground="{DynamicResource Color01B}"
Click="OnStartRecordingClicked"
Command="{Binding StartRecordingCommand}"
PreviewKeyDown="OnPreviewKeyDown"
KeyboardNavigation.TabNavigation="Continue">
KeyboardNavigation.TabNavigation="Continue"
IsChecked="{Binding Recording}">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Grid>
@ -62,9 +65,9 @@
BorderThickness="1"
CornerRadius="5">
<StackPanel Orientation="Horizontal">
<Button Content="Reset" Click="OnResetToDefaultClicked" />
<Button Content="Delete" Click="OnDeleteClicked" />
<Button Content="Stop Rec" Click="OnStopRecordingClicked" />
<Button Content="Reset" Command="{Binding ResetToDefaultCommand}" />
<Button Content="Delete" Command="{Binding DeleteCommand}" />
<Button Content="Stop Rec" Command="{Binding StopRecordingCommand}" />
</StackPanel>
</Border>
@ -100,7 +103,8 @@
</ControlTemplate>
</ToggleButton.Template>
<ToggleButton.Content>
<ItemsControl ItemsSource="{Binding Path=KeysToDisplay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
<ItemsControl
ItemsSource="{Binding Path=KeysToDisplay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
@ -122,4 +126,4 @@
</ToggleButton.Content>
</ToggleButton>
</Grid>
</UserControl>
</UserControl>

View file

@ -10,141 +10,42 @@ using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel;
using NHotkey;
namespace Flow.Launcher
{
public partial class HotkeyControl : UserControl, IDisposable, INotifyPropertyChanged
public partial class HotkeyControl : UserControl, 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 DefaultHotkey { get; set; }
private const string EmptyKeyValue = "<empty>";
private const string KeySeparator = " + ";
private string[] _keysToDisplay = { EmptyKeyValue };
public string[] KeysToDisplay
{
get => _keysToDisplay;
set
{
_keysToDisplay = value;
OnPropertyChanged();
}
}
#nullable enable
public EventHandler<HotkeyEventArgs>? Action { get; set; }
#nullable restore
public event EventHandler HotkeyChanged;
/// <summary>
/// Designed for Preview Hotkey and KeyGesture.
/// </summary>
public bool ValidateKeyGesture { get; set; } = false;
protected virtual void OnHotkeyChanged() => HotkeyChanged?.Invoke(this, EventArgs.Empty);
// /// <summary>
// /// Designed for Preview Hotkey and KeyGesture.
// /// </summary>
// public static readonly DependencyProperty ValidateKeyGestureProperty = DependencyProperty.Register(
// nameof(ValidateKeyGesture), typeof(bool), typeof(HotkeyControlViewModel),
// 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(HotkeyControl), new PropertyMetadata(default(string)));
//
// public string DefaultHotkey
// {
// get { return (string)GetValue(DefaultHotkeyProperty); }
// set { SetValue(DefaultHotkeyProperty, value); }
// }
public HotkeyControl()
{
InitializeComponent();
Loaded += HotkeyControl_Loaded;
}
/*------------------ New Logic Structure Part ------------------------*/
private void OnStartRecordingClicked(object sender, RoutedEventArgs e)
{
if (HotkeyBtn.IsChecked == true)
{
if (!string.IsNullOrEmpty(Hotkey))
{
HotKeyMapper.RemoveHotkey(Hotkey);
}
/* 1. Key Recording Start */
/* 2. Key Display area clear
* 3. Key Display when typing*/
}
}
private void OnStopRecordingClicked(object sender, RoutedEventArgs e)
{
HotkeyBtn.IsChecked = false;
if (KeysToDisplay.Length == 0 || (KeysToDisplay.Length == 1 && KeysToDisplay[0] == EmptyKeyValue))
{
return;
}
_ = SetHotkeyAsync(string.Join(KeySeparator, KeysToDisplay));
}
private void OnResetToDefaultClicked(object sender, RoutedEventArgs e)
{
HotkeyBtn.IsChecked = false;
if (!string.IsNullOrEmpty(Hotkey))
HotKeyMapper.RemoveHotkey(Hotkey);
Hotkey = DefaultHotkey;
KeysToDisplay = Hotkey.Split(KeySeparator);
_ = SetHotkeyAsync(Hotkey);
}
private void OnDeleteClicked(object sender, RoutedEventArgs e)
{
HotkeyBtn.IsChecked = false;
if (!string.IsNullOrEmpty(Hotkey))
HotKeyMapper.RemoveHotkey(Hotkey);
Hotkey = "";
KeysToDisplay = new []{ EmptyKeyValue };
}
/*------------------ New Logic Structure Part------------------------*/
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);
KeysToDisplay = Hotkey switch
{
null or "" => new[] { EmptyKeyValue },
_ => Hotkey.Split(KeySeparator)
};
if (Action is not null)
{
GotFocus += HotkeyControl_GotFocus;
LostFocus += HotkeyControl_LostFocus;
}
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (HotkeyBtn.IsChecked != true)
@ -163,49 +64,9 @@ namespace Flow.Launcher
specialKeyState.CtrlPressed,
key);
if (hotkeyModel.Equals(CurrentHotkey))
{
return;
}
KeysToDisplay = hotkeyModel.ToString().Split(KeySeparator);
((HotkeyControlViewModel)this.DataContext).KeyDown(hotkeyModel);
}
public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true)
{
// tbHotkey.Text = keyModel.ToString();
// tbHotkey.Select(tbHotkey.Text.Length, 0);
if (triggerValidate)
{
bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture);
CurrentHotkeyAvailable = hotkeyAvailable;
SetMessage(hotkeyAvailable);
OnHotkeyChanged();
if (CurrentHotkeyAvailable)
{
CurrentHotkey = keyModel;
Hotkey = keyModel.ToString();
KeysToDisplay = Hotkey.Split(KeySeparator);
// To trigger LostFocus
FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null);
Keyboard.ClearFocus();
}
}
else
{
CurrentHotkey = keyModel;
Hotkey = keyModel.ToString();
}
}
public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true)
{
return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate);
}
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
// public new bool IsFocused => tbHotkey.IsFocused;
@ -226,28 +87,6 @@ namespace Flow.Launcher
tbMsg.SetResourceReference(TextBox.ForegroundProperty, "Color05B");
}
private void SetMessage(bool hotkeyAvailable)
{
if (!hotkeyAvailable)
{
tbMsg.Foreground = new SolidColorBrush(Colors.Red);
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable");
}
else
{
tbMsg.Foreground = new SolidColorBrush(Colors.Green);
tbMsg.Text = InternationalizationManager.Instance.GetTranslation("success");
}
tbMsg.Visibility = Visibility.Visible;
}
public void Dispose()
{
Loaded -= HotkeyControl_Loaded;
GotFocus -= HotkeyControl_GotFocus;
LostFocus -= HotkeyControl_LostFocus;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)

View file

@ -9,7 +9,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="WelcomePage2"
mc:Ignorable="d">
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Page.Resources>
<converters:BorderClipConverter x:Key="BorderClipConverter" />
<Style x:Key="StyleImageFadeIn" TargetType="{x:Type Image}">
@ -111,6 +112,7 @@
Text="{DynamicResource flowlauncherHotkey}" />
<flowlauncher:HotkeyControl
x:Name="HotkeyControl"
DataContext="{Binding Path=HotkeyControlViewModel}"
Width="300"
Height="35"
Margin="-206,10,0,0"

View file

@ -5,6 +5,7 @@ using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Navigation;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher.Resources.Pages
{
@ -16,6 +17,11 @@ namespace Flow.Launcher.Resources.Pages
private string tbMsgTextOriginal;
public HotkeyControlViewModel HotkeyControlViewModel { get; set; }= new HotkeyControlViewModel()
{
ValidateKeyGesture = true
};
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.ExtraData is Settings settings)
@ -24,10 +30,11 @@ namespace Flow.Launcher.Resources.Pages
throw new ArgumentException("Unexpected Parameter setting.");
InitializeComponent();
tbMsgTextOriginal = HotkeyControl.tbMsg.Text;
tbMsgForegroundColorOriginal = HotkeyControl.tbMsg.Foreground;
HotkeyControl.SetHotkeyAsync(Settings.Hotkey, false);
_ = HotkeyControlViewModel.SetHotkeyAsync(Settings.Hotkey, false);
}
private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args)
{
@ -35,10 +42,10 @@ namespace Flow.Launcher.Resources.Pages
}
private void HotkeyControl_OnLostFocus(object sender, RoutedEventArgs args)
{
if (HotkeyControl.CurrentHotkeyAvailable)
if (HotkeyControlViewModel.CurrentHotkeyAvailable)
{
HotKeyMapper.SetHotkey(HotkeyControl.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
Settings.Hotkey = HotkeyControl.CurrentHotkey.ToString();
HotKeyMapper.SetHotkey(HotkeyControlViewModel.CurrentHotkey, HotKeyMapper.OnToggleHotkey);
Settings.Hotkey = HotkeyControlViewModel.CurrentHotkey.ToString();
}
else
{

View file

@ -2643,15 +2643,12 @@
<TextBlock Style="{DynamicResource SettingSubTitleLabel}" Text="{DynamicResource flowlauncherHotkeyToolTip}" />
</StackPanel>
<flowlauncher:HotkeyControl
x:Name="HotkeyControl"
Grid.Row="0"
Grid.Column="2"
Margin="0,0,16,0"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
DefaultHotkey="Alt + Space"
Action="OnToggleHotkey"
Hotkey="{Binding Settings.Hotkey}" />
DataContext="{Binding ToggleHotkeyViewModel}"/>
<TextBlock Style="{StaticResource Glyph}">
&#xeda7;
@ -2673,10 +2670,7 @@
Grid.Column="2"
Margin="0,0,16,0"
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
DefaultHotkey="F1"
Hotkey="{Binding Settings.PreviewHotkey}"
ValidateKeyGesture="True" />
HorizontalContentAlignment="Right" />
<TextBlock Style="{StaticResource Glyph}">
&#xe8a1;
</TextBlock>

View file

@ -0,0 +1,224 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin;
using JetBrains.Annotations;
#nullable enable
namespace Flow.Launcher.ViewModel
{
public partial class HotkeyControlViewModel : BaseModel
{
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) =>
hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
public string? Message { get; set; }
public bool MessageVisibility { get; set; }
public SolidColorBrush? MessageColor { get; set; }
public bool CurrentHotkeyAvailable { get; private set; }
public string DefaultHotkey { get; init; }
private void SetMessage(bool hotkeyAvailable)
{
Message = hotkeyAvailable
? InternationalizationManager.Instance.GetTranslation("success")
: InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable");
MessageColor = hotkeyAvailable ? new SolidColorBrush(Colors.Green) : new SolidColorBrush(Colors.Red);
MessageVisibility = true;
}
public HotkeyControlViewModel(string hotkey = "",
string defaultHotkey = "",
bool validateKeyGesture = true,
Action<HotkeyModel>? hotkeyDelegate = null)
{
Hotkey = hotkey;
DefaultHotkey = defaultHotkey;
ValidateKeyGesture = validateKeyGesture;
HotkeyDelegate = hotkeyDelegate;
if (string.IsNullOrEmpty(Hotkey))
{
Hotkey = DefaultHotkey;
}
SetKeysToDisplay(Hotkey?.Split(KeySeparator));
}
private const string EmptyKeyValue = "<empty>";
private const string KeySeparator = " + ";
public ObservableCollection<string> KeysToDisplay { get; } = new() { EmptyKeyValue };
public HotkeyModel CurrentHotkey { get; private set; }
public string Hotkey { get; set; }
public bool Recording { get; set; }
[RelayCommand]
public async Task StartRecordingAsync()
{
if (!Recording)
{
return;
}
if (!string.IsNullOrEmpty(Hotkey))
{
HotKeyMapper.RemoveHotkey(Hotkey);
}
/* 1. Key Recording Start */
/* 2. Key Display area clear
* 3. Key Display when typing*/
}
[RelayCommand]
private async Task StopRecordingAsync()
{
Recording = false;
if (KeysToDisplay.Count == 0 || (KeysToDisplay.Count == 1 && KeysToDisplay[0] == EmptyKeyValue))
{
return;
}
await SetHotkeyAsync(CurrentHotkey, true);
}
[RelayCommand]
private async Task ResetToDefaultAsync()
{
Recording = false;
if (!string.IsNullOrEmpty(Hotkey))
HotKeyMapper.RemoveHotkey(Hotkey);
Hotkey = DefaultHotkey;
KeysToDisplay.Clear();
foreach (var key in Hotkey.Split(KeySeparator))
{
KeysToDisplay.Add(key);
}
await SetHotkeyAsync(Hotkey);
}
public bool ValidateKeyGesture { get; set; }
public Action<HotkeyModel> HotkeyDelegate { get; set; }
private async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true)
{
// tbHotkey.Text = keyModel.ToString();
// tbHotkey.Select(tbHotkey.Text.Length, 0);
if (triggerValidate)
{
bool hotkeyAvailable = CheckHotkeyAvailability(keyModel, ValidateKeyGesture);
CurrentHotkeyAvailable = hotkeyAvailable;
SetMessage(hotkeyAvailable);
HotkeyDelegate?.Invoke(keyModel);
if (CurrentHotkeyAvailable)
{
CurrentHotkey = keyModel;
Hotkey = keyModel.ToString();
SetKeysToDisplay(Hotkey.Split(KeySeparator));
}
}
else
{
CurrentHotkey = keyModel;
Hotkey = keyModel.ToString();
}
}
[RelayCommand]
public async Task DeleteAsync()
{
Recording = false;
if (!string.IsNullOrEmpty(Hotkey))
HotKeyMapper.RemoveHotkey(Hotkey);
Hotkey = "";
SetKeysToDisplay(new List<string>());
}
private void SetKeysToDisplay(HotkeyModel hotkey)
{
KeysToDisplay.Clear();
if (hotkey.Alt)
{
KeysToDisplay.Add("Alt");
}
if (hotkey.Ctrl)
{
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>? keys)
{
KeysToDisplay.Clear();
if (keys == null)
{
return;
}
foreach (var key in keys)
{
KeysToDisplay.Add(key);
}
if (!keys.Any())
{
KeysToDisplay.Add(EmptyKeyValue);
}
}
public Task SetHotkeyAsync(string? keyStr, bool triggerValidate = true)
{
return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate);
}
public void KeyDown(HotkeyModel hotkeyModel)
{
CurrentHotkey = hotkeyModel;
SetKeysToDisplay(hotkeyModel.ToString().Split(KeySeparator));
}
}
}

View file

@ -22,6 +22,7 @@ using Flow.Launcher.Plugin.SharedModels;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.Input;
using System.Globalization;
using System.Runtime.CompilerServices;
namespace Flow.Launcher.ViewModel
{
@ -69,6 +70,12 @@ namespace Flow.Launcher.ViewModel
}
};
ToggleHotkeyViewModel =
new HotkeyControlViewModel(Settings.Hotkey, "Alt + Space", true, hotkey =>
{
Settings.Hotkey = hotkey.ToString();
HotKeyMapper.SetHotkey(hotkey, HotKeyMapper.OnToggleHotkey);
});
}
public Settings Settings { get; set; }
@ -110,13 +117,15 @@ namespace Flow.Launcher.ViewModel
}
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
private bool _portableMode = DataLocation.PortableDataLocationInUse();
public bool PortableMode
{
get => _portableMode;
@ -185,6 +194,7 @@ namespace Flow.Launcher.ViewModel
}
private List<LastQueryMode> _lastQueryModes = new List<LastQueryMode>();
public List<LastQueryMode> LastQueryModes
{
get
@ -193,6 +203,7 @@ namespace Flow.Launcher.ViewModel
{
_lastQueryModes = InitLastQueryModes();
}
return _lastQueryModes;
}
}
@ -200,17 +211,16 @@ namespace Flow.Launcher.ViewModel
private List<LastQueryMode> InitLastQueryModes()
{
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)
{
var key = $"LastQuery{e}";
var display = _translater.GetTranslation(key);
var m = new LastQueryMode
{
Display = display, Value = e,
};
var m = new LastQueryMode { Display = display, Value = e, };
modes.Add(m);
}
return modes;
}
@ -267,15 +277,15 @@ namespace Flow.Launcher.ViewModel
public List<string> OpenResultModifiersList => new List<string>
{
KeyConstant.Alt,
KeyConstant.Ctrl,
$"{KeyConstant.Ctrl}+{KeyConstant.Alt}"
KeyConstant.Alt, KeyConstant.Ctrl, $"{KeyConstant.Ctrl}+{KeyConstant.Alt}"
};
private Internationalization _translater => InternationalizationManager.Instance;
public List<Language> Languages => _translater.LoadAvailableLanguages();
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()
{
@ -285,6 +295,7 @@ namespace Flow.Launcher.ViewModel
{
return InternationalizationManager.Instance.GetTranslation("serverCantBeEmpty");
}
if (Settings.Proxy.Port <= 0)
{
return InternationalizationManager.Instance.GetTranslation("portCantBeEmpty");
@ -303,6 +314,7 @@ namespace Flow.Launcher.ViewModel
Credentials = new NetworkCredential(proxyUserName, Settings.Proxy.Password)
};
}
try
{
var response = (HttpWebResponse)request.GetResponse();
@ -333,10 +345,7 @@ namespace Flow.Launcher.ViewModel
get => PluginManager.AllPlugins
.OrderBy(x => x.Metadata.Disabled)
.ThenBy(y => y.Metadata.Name)
.Select(p => new PluginViewModel
{
PluginPair = p
})
.Select(p => new PluginViewModel { PluginPair = p })
.ToList();
}
@ -383,8 +392,7 @@ namespace Flow.Launcher.ViewModel
await PluginsManifest.UpdateManifestAsync();
OnPropertyChanged(nameof(ExternalPlugins));
}
internal void DisplayPluginQuery(string queryToDisplay, PluginPair plugin, int actionKeywordPosition = 0)
{
@ -458,12 +466,10 @@ namespace Flow.Launcher.ViewModel
{
var key = $"ColorScheme{e}";
var display = _translater.GetTranslation(key);
var m = new ColorScheme
{
Display = display, Value = e,
};
var m = new ColorScheme { Display = display, Value = e, };
modes.Add(m);
}
return modes;
}
}
@ -484,13 +490,10 @@ namespace Flow.Launcher.ViewModel
{
var key = $"SearchWindowScreen{e}";
var display = _translater.GetTranslation(key);
var m = new SearchWindowScreen
{
Display = display,
Value = e,
};
var m = new SearchWindowScreen { Display = display, Value = e, };
modes.Add(m);
}
return modes;
}
}
@ -511,12 +514,10 @@ namespace Flow.Launcher.ViewModel
{
var key = $"SearchWindowAlign{e}";
var display = _translater.GetTranslation(key);
var m = new SearchWindowAlign
{
Display = display, Value = e,
};
var m = new SearchWindowAlign { Display = display, Value = e, };
modes.Add(m);
}
return modes;
}
}
@ -531,6 +532,7 @@ namespace Flow.Launcher.ViewModel
{
screenNumbers.Add(i);
}
return screenNumbers;
}
}
@ -617,13 +619,10 @@ namespace Flow.Launcher.ViewModel
{
var key = $"AnimationSpeed{e}";
var display = _translater.GetTranslation(key);
var m = new AnimationSpeed
{
Display = display,
Value = e,
};
var m = new AnimationSpeed { Display = display, Value = e, };
speeds.Add(m);
}
return speeds;
}
}
@ -690,10 +689,7 @@ namespace Flow.Launcher.ViewModel
bitmap.DecodePixelWidth = 800;
bitmap.DecodePixelHeight = 600;
bitmap.EndInit();
var brush = new ImageBrush(bitmap)
{
Stretch = Stretch.UniformToFill
};
var brush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill };
return brush;
}
else
@ -714,26 +710,36 @@ namespace Flow.Launcher.ViewModel
new Result
{
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleExplorer"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleExplorer"),
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png")
SubTitle =
InternationalizationManager.Instance.GetTranslation("SampleSubTitleExplorer"),
IcoPath =
Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png")
},
new Result
{
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleWebSearch"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleWebSearch"),
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png")
SubTitle =
InternationalizationManager.Instance.GetTranslation("SampleSubTitleWebSearch"),
IcoPath =
Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png")
},
new Result
{
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProgram"),
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
{
Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProcessKiller"),
SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProcessKiller"),
IcoPath = Path.Combine(Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png")
SubTitle =
InternationalizationManager.Instance.GetTranslation("SampleSubTitleProcessKiller"),
IcoPath = Path.Combine(Constant.ProgramDirectory,
@"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png")
}
};
var vm = new ResultsViewModel(Settings);
@ -889,6 +895,7 @@ namespace Flow.Launcher.ViewModel
SelectedCustomShortcut = item;
return true;
}
return false;
}
@ -917,6 +924,7 @@ namespace Flow.Launcher.ViewModel
public string Documentation => Constant.Documentation;
public string Docs => Constant.Docs;
public string Github => Constant.GitHub;
public string Version
{
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
{
@ -939,10 +949,13 @@ namespace Flow.Launcher.ViewModel
{
var logFiles = GetLogFiles();
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));
}
}
public HotkeyControlViewModel ToggleHotkeyViewModel { get; set; }
private static DirectoryInfo GetLogDir(string version = "")
{
return new DirectoryInfo(Path.Combine(DataLocation.DataDirectory(), Constant.Logs, version));
@ -976,10 +989,7 @@ namespace Flow.Launcher.ViewModel
internal static string BytesToReadableString(long bytes)
{
const int scale = 1024;
string[] orders = new string[]
{
"GB", "MB", "KB", "B"
};
string[] orders = new string[] { "GB", "MB", "KB", "B" };
long max = (long)Math.Pow(scale, orders.Length - 1);
foreach (string order in orders)
@ -989,6 +999,7 @@ namespace Flow.Launcher.ViewModel
max /= scale;
}
return "0 B";
}