-
-
Notifications
You must be signed in to change notification settings - Fork 591
Expand file tree
/
Copy pathHotkeyControl.xaml.cs
More file actions
336 lines (299 loc) · 12.6 KB
/
HotkeyControl.xaml.cs
File metadata and controls
336 lines (299 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
#nullable enable
namespace Flow.Launcher
{
public partial class HotkeyControl
{
public string WindowTitle {
get { return (string)GetValue(WindowTitleProperty); }
set { SetValue(WindowTitleProperty, value); }
}
public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register(
nameof(WindowTitle),
typeof(string),
typeof(HotkeyControl),
new PropertyMetadata(string.Empty)
);
/// <summary>
/// Designed for Preview Hotkey and KeyGesture.
/// </summary>
public static readonly DependencyProperty ValidateKeyGestureProperty = DependencyProperty.Register(
nameof(ValidateKeyGesture),
typeof(bool),
typeof(HotkeyControl),
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); }
}
private static void OnHotkeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not HotkeyControl hotkeyControl)
{
return;
}
hotkeyControl.RefreshHotkeyInterface(hotkeyControl.Hotkey);
}
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 TypeProperty = DependencyProperty.Register(
nameof(Type),
typeof(HotkeyType),
typeof(HotkeyControl),
new FrameworkPropertyMetadata(HotkeyType.None, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnHotkeyChanged)
);
public HotkeyType Type
{
get { return (HotkeyType)GetValue(TypeProperty); }
set { SetValue(TypeProperty, value); }
}
public enum HotkeyType
{
None,
// Custom query hotkeys
CustomQueryHotkey,
// Settings hotkeys
Hotkey,
PreviewHotkey,
OpenContextMenuHotkey,
SettingWindowHotkey,
OpenHistoryHotkey,
CycleHistoryUpHotkey,
CycleHistoryDownHotkey,
SelectPrevPageHotkey,
SelectNextPageHotkey,
AutoCompleteHotkey,
AutoCompleteHotkey2,
SelectPrevItemHotkey,
SelectPrevItemHotkey2,
SelectNextItemHotkey,
SelectNextItemHotkey2,
DialogJumpHotkey,
}
// We can initialize settings in static field because it has been constructed in App constuctor
// and it will not construct settings instances twice
private static readonly Settings _settings = Ioc.Default.GetRequiredService<Settings>();
private string hotkey = string.Empty;
public string Hotkey
{
get
{
return Type switch
{
// Custom query hotkeys
HotkeyType.CustomQueryHotkey => hotkey,
// Settings hotkeys
HotkeyType.Hotkey => _settings.Hotkey,
HotkeyType.PreviewHotkey => _settings.PreviewHotkey,
HotkeyType.OpenContextMenuHotkey => _settings.OpenContextMenuHotkey,
HotkeyType.SettingWindowHotkey => _settings.SettingWindowHotkey,
HotkeyType.OpenHistoryHotkey => _settings.OpenHistoryHotkey,
HotkeyType.CycleHistoryUpHotkey => _settings.CycleHistoryUpHotkey,
HotkeyType.CycleHistoryDownHotkey => _settings.CycleHistoryDownHotkey,
HotkeyType.SelectPrevPageHotkey => _settings.SelectPrevPageHotkey,
HotkeyType.SelectNextPageHotkey => _settings.SelectNextPageHotkey,
HotkeyType.AutoCompleteHotkey => _settings.AutoCompleteHotkey,
HotkeyType.AutoCompleteHotkey2 => _settings.AutoCompleteHotkey2,
HotkeyType.SelectPrevItemHotkey => _settings.SelectPrevItemHotkey,
HotkeyType.SelectPrevItemHotkey2 => _settings.SelectPrevItemHotkey2,
HotkeyType.SelectNextItemHotkey => _settings.SelectNextItemHotkey,
HotkeyType.SelectNextItemHotkey2 => _settings.SelectNextItemHotkey2,
HotkeyType.DialogJumpHotkey => _settings.DialogJumpHotkey,
_ => throw new System.NotImplementedException("Hotkey type not set")
};
}
set
{
switch (Type)
{
// Custom query hotkeys
case HotkeyType.CustomQueryHotkey:
// We just need to store it in a local field
// because we will save to settings in other place
hotkey = value;
break;
// Settings hotkeys
case HotkeyType.Hotkey:
_settings.Hotkey = value;
break;
case HotkeyType.PreviewHotkey:
_settings.PreviewHotkey = value;
break;
case HotkeyType.OpenContextMenuHotkey:
_settings.OpenContextMenuHotkey = value;
break;
case HotkeyType.SettingWindowHotkey:
_settings.SettingWindowHotkey = value;
break;
case HotkeyType.OpenHistoryHotkey:
_settings.OpenHistoryHotkey = value;
break;
case HotkeyType.CycleHistoryUpHotkey:
_settings.CycleHistoryUpHotkey = value;
break;
case HotkeyType.CycleHistoryDownHotkey:
_settings.CycleHistoryDownHotkey = value;
break;
case HotkeyType.SelectPrevPageHotkey:
_settings.SelectPrevPageHotkey = value;
break;
case HotkeyType.SelectNextPageHotkey:
_settings.SelectNextPageHotkey = value;
break;
case HotkeyType.AutoCompleteHotkey:
_settings.AutoCompleteHotkey = value;
break;
case HotkeyType.AutoCompleteHotkey2:
_settings.AutoCompleteHotkey2 = value;
break;
case HotkeyType.SelectPrevItemHotkey:
_settings.SelectPrevItemHotkey = value;
break;
case HotkeyType.SelectNextItemHotkey:
_settings.SelectNextItemHotkey = value;
break;
case HotkeyType.SelectPrevItemHotkey2:
_settings.SelectPrevItemHotkey2 = value;
break;
case HotkeyType.SelectNextItemHotkey2:
_settings.SelectNextItemHotkey2 = value;
break;
case HotkeyType.DialogJumpHotkey:
_settings.DialogJumpHotkey = value;
break;
default:
throw new System.NotImplementedException("Hotkey type not set");
}
// After setting the hotkey, we need to refresh the interface
RefreshHotkeyInterface(Hotkey);
}
}
public HotkeyControl()
{
InitializeComponent();
HotkeyList.ItemsSource = KeysToDisplay;
// We should not call RefreshHotkeyInterface here because DependencyProperty is not set yet
// And it will be called in OnHotkeyChanged event or Hotkey setter later
}
private void RefreshHotkeyInterface(string hotkey)
{
SetKeysToDisplay(new HotkeyModel(hotkey));
CurrentHotkey = new HotkeyModel(hotkey);
}
private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) =>
hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey);
public string EmptyHotkey => Localize.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)
{
_ = OpenHotkeyDialogAsync();
}
private async Task OpenHotkeyDialogAsync()
{
if (!string.IsNullOrEmpty(Hotkey))
{
HotKeyMapper.RemoveHotkey(Hotkey);
}
var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle)
{
Owner = Window.GetWindow(this)
};
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)
{
bool hotkeyAvailable;
// TODO: This is a temporary way to enforce changing only the open flow hotkey to Win, and will be removed by PR #3157
if (keyModel.ToString() == "LWin" || keyModel.ToString() == "RWin"
|| (Type == HotkeyType.Hotkey && keyModel.Win && keyModel.CharKey != Key.None))
{
hotkeyAvailable = keyModel.Validate(ValidateKeyGesture);
}
else
{
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);
}
}
}