WingMan – Blame information for rev 32

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Collections.Generic;
14 office 3 using System.Collections.ObjectModel;
24 office 4 using System.ComponentModel;
1 office 5 using System.Drawing;
9 office 6 using System.IO;
1 office 7 using System.Linq;
8 using System.Net;
7 office 9 using System.Threading;
6 office 10 using System.Threading.Tasks;
1 office 11 using System.Windows.Forms;
4 office 12 using Gma.System.MouseKeyHook;
9 office 13 using MQTTnet.Extensions.ManagedClient;
14 using MQTTnet.Server;
23 office 15 using WingMan.AutoCompletion;
14 office 16 using WingMan.Bindings;
1 office 17 using WingMan.Communication;
32 office 18 using WingMan.Discovery;
7 office 19 using WingMan.Lobby;
5 office 20 using WingMan.Properties;
8 office 21 using WingMan.Utilities;
1 office 22  
23 namespace WingMan
24 {
2 office 25 public partial class WingManForm : Form
1 office 26 {
5 office 27 public WingManForm()
28 {
29 InitializeComponent();
1 office 30  
6 office 31 FormTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
7 office 32 FormCancellationTokenSource = new CancellationTokenSource();
1 office 33  
32 office 34 // Set up discovery.
35 Discovery = new Discovery.Discovery(FormCancellationTokenSource, FormTaskScheduler);
36 Discovery.OnPortMapFailed += OnDiscoveryPortMapFailed;
37  
23 office 38 // Set up autocompletion.
39 AutoCompletion = new AutoCompletion.AutoCompletion(FormTaskScheduler, FormCancellationTokenSource.Token);
40 AutoCompletion.OnSaveFailed += AutoCompletionOnSaveFailed;
41 AutoCompletion.OnLoadFailed += AutoCompletionOnLoadFailed;
42  
43 Task.Run(() => AutoCompletion.Load(Address.Name, Address.AutoCompleteCustomSource));
44 Task.Run(() => AutoCompletion.Load(Port.Name, Address.AutoCompleteCustomSource));
45 Task.Run(() => AutoCompletion.Load(Nick.Name, Nick.AutoCompleteCustomSource));
46  
9 office 47 MqttCommunication = new MqttCommunication(FormTaskScheduler, FormCancellationTokenSource.Token);
48 MqttCommunication.OnClientAuthenticationFailed += OnMqttClientAuthenticationFailed;
49 MqttCommunication.OnClientConnectionFailed += OnMqttClientConnectionFailed;
50 MqttCommunication.OnClientDisconnected += OnMqttClientDisconnected;
51 MqttCommunication.OnClientConnected += OnMqttClientConnected;
52 MqttCommunication.OnServerAuthenticationFailed += OnMqttServerAuthenticationFailed;
53 MqttCommunication.OnServerStopped += OnMqttServerStopped;
54 MqttCommunication.OnServerStarted += OnMqttServerStarted;
55 MqttCommunication.OnServerClientConnected += OnMqttServerClientConnected;
56 MqttCommunication.OnServerClientDisconnected += OnMqttServerClientDisconnected;
6 office 57  
10 office 58 LocalKeyBindings = new LocalKeyBindings(new List<KeyBinding>());
14 office 59 RemoteKeyBindings = new RemoteKeyBindings(new ObservableCollection<RemoteKeyBinding>());
1 office 60  
24 office 61 LocalCheckedListBoxBindingSource = new BindingSource
5 office 62 {
10 office 63 DataSource = LocalKeyBindings.Bindings
5 office 64 };
24 office 65 LocalCheckedListBoxBindingSource.ListChanged += LocalCheckedListBoxBindingSourceOnListChanged;
66 LocalBindingsCheckedListBox.DisplayMember = "DisplayName";
67 LocalBindingsCheckedListBox.ValueMember = "Keys";
68 LocalBindingsCheckedListBox.DataSource = LocalCheckedListBoxBindingSource;
1 office 69  
10 office 70 KeyBindingsExchange = new KeyBindingsExchange
5 office 71 {
10 office 72 ExchangeBindings = new List<KeyBindingExchange>()
7 office 73 };
74  
9 office 75 RemoteBindingsComboBoxSource = new BindingSource
7 office 76 {
10 office 77 DataSource = KeyBindingsExchange.ExchangeBindings
5 office 78 };
9 office 79 RemoteBindingsComboBox.DisplayMember = "Nick";
10 office 80 RemoteBindingsComboBox.ValueMember = "KeyBindings";
9 office 81 RemoteBindingsComboBox.DataSource = RemoteBindingsComboBoxSource;
4 office 82  
5 office 83 // Start lobby message synchronizer.
9 office 84 LobbyMessageSynchronizer = new LobbyMessageSynchronizer(MqttCommunication, FormTaskScheduler,
7 office 85 FormCancellationTokenSource.Token);
5 office 86 LobbyMessageSynchronizer.OnLobbyMessageReceived += OnLobbyMessageReceived;
4 office 87  
5 office 88 // Start mouse key bindings synchronizer.
10 office 89 KeyBindingsSynchronizer = new KeyBindingsSynchronizer(LocalKeyBindings, MqttCommunication,
7 office 90 FormTaskScheduler, FormCancellationTokenSource.Token);
10 office 91 KeyBindingsSynchronizer.OnMouseKeyBindingsSynchronized += OnMouseKeyBindingsSynchronized;
9 office 92  
10 office 93 // Start mouse key interceptor.
94 KeyInterceptor = new KeyInterceptor(RemoteKeyBindings, MqttCommunication, FormTaskScheduler,
95 FormCancellationTokenSource.Token);
96 KeyInterceptor.OnMouseKeyBindingMatched += OnMouseKeyBindingMatched;
97  
98 // Start mouse key simulator.
99 KeySimulator = new KeySimulator(LocalKeyBindings, MqttCommunication, FormTaskScheduler,
100 FormCancellationTokenSource.Token);
101 KeySimulator.OnMouseKeyBindingExecuting += OnMouseKeyBindingExecuting;
5 office 102 }
4 office 103  
32 office 104 private static Discovery.Discovery Discovery { get; set; }
23 office 105 private static AutoCompletion.AutoCompletion AutoCompletion { get; set; }
7 office 106 private static CancellationTokenSource FormCancellationTokenSource { get; set; }
4 office 107  
7 office 108 private static TaskScheduler FormTaskScheduler { get; set; }
4 office 109  
7 office 110 private static IKeyboardMouseEvents MouseKeyApplicationHook { get; set; }
4 office 111  
7 office 112 private List<string> MouseKeyCombo { get; set; }
2 office 113  
10 office 114 private LocalKeyBindings LocalKeyBindings { get; }
4 office 115  
10 office 116 private RemoteKeyBindings RemoteKeyBindings { get; }
4 office 117  
24 office 118 private BindingSource LocalCheckedListBoxBindingSource { get; }
4 office 119  
9 office 120 private BindingSource RemoteBindingsComboBoxSource { get; }
121  
10 office 122 private KeyBindingsExchange KeyBindingsExchange { get; }
7 office 123  
9 office 124 public MqttCommunication MqttCommunication { get; set; }
7 office 125  
126 public LobbyMessageSynchronizer LobbyMessageSynchronizer { get; set; }
127  
10 office 128 public KeyBindingsSynchronizer KeyBindingsSynchronizer { get; set; }
7 office 129  
10 office 130 public KeyInterceptor KeyInterceptor { get; set; }
131  
132 public KeySimulator KeySimulator { get; set; }
133  
32 office 134 public void OnDiscoveryPortMapFailed(object sender, DiscoveryFailedEventArgs args)
135 {
136 switch (args.Type)
137 {
138 case DiscoveryType.UPnP:
139 ActivityTextBox.AppendText(
140 $"{Strings.Failed_to_create_UPnP_port_mapping}{Environment.NewLine}");
141 break;
142 case DiscoveryType.PMP:
143 ActivityTextBox.AppendText(
144 $"{Strings.Failed_to_create_PMP_port_mapping}{Environment.NewLine}");
145 break;
146 }
147 }
148  
24 office 149 private void LocalCheckedListBoxBindingSourceOnListChanged(object sender, ListChangedEventArgs e)
150 {
151 // Check items
152 LocalBindingsCheckedListBox.ItemCheck -= LocalBindingsCheckedListBoxItemCheck;
153  
154 for (var i = 0; i < LocalKeyBindings.Bindings.Count; ++i)
155 switch (LocalKeyBindings.Bindings[i].Enabled)
156 {
157 case true:
158 LocalBindingsCheckedListBox.SetItemCheckState(i, CheckState.Checked);
159 break;
160 default:
161 LocalBindingsCheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
162 break;
163 }
164  
165 LocalBindingsCheckedListBox.ItemCheck += LocalBindingsCheckedListBoxItemCheck;
166 }
167  
23 office 168 private void AutoCompletionOnLoadFailed(object sender, AutoCompletionFailedEventArgs args)
169 {
170 ActivityTextBox.AppendText(
171 $"{Strings.Failed_loading_autocomplete_source} : {args.Name} : {args.Exception.Message}{Environment.NewLine}");
172 }
173  
174 private void AutoCompletionOnSaveFailed(object sender, AutoCompletionFailedEventArgs args)
175 {
176 ActivityTextBox.AppendText(
177 $"{Strings.Failed_saving_autocomplete_source} : {args.Name} : {args.Exception.Message}{Environment.NewLine}");
178 }
179  
21 office 180 /// <inheritdoc />
10 office 181 /// <summary>
182 /// Clean up any resources being used.
183 /// </summary>
184 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
185 protected override void Dispose(bool disposing)
8 office 186 {
10 office 187 FormCancellationTokenSource?.Dispose();
188 FormCancellationTokenSource = null;
9 office 189  
10 office 190 if (disposing && components != null)
9 office 191 {
10 office 192 components.Dispose();
193 components = null;
9 office 194 }
10 office 195  
196 base.Dispose(disposing);
9 office 197 }
198  
10 office 199 private void OnMouseKeyBindingExecuting(object sender, KeyBindingExecutingEventArgs args)
200 {
201 ActivityTextBox.AppendText(
202 $"{Strings.Executing_binding_from_remote_client} : {args.Nick} : {args.Name}{Environment.NewLine}");
203 }
204  
205 private void OnMouseKeyBindingMatched(object sender, KeyBindingMatchedEventArgs args)
206 {
207 ActivityTextBox.AppendText(
208 $"{Strings.Matched_remote_key_binding} : {args.Nick} : {args.Name} : {string.Join(" + ", args.KeyCombo)}{Environment.NewLine}");
209 }
210  
9 office 211 private void OnMqttServerClientDisconnected(object sender, MqttClientDisconnectedEventArgs e)
212 {
8 office 213 ActivityTextBox.AppendText(
9 office 214 $"{Strings.Client_disconnected}{Environment.NewLine}");
215 }
216  
217 private void OnMqttServerClientConnected(object sender, MqttClientConnectedEventArgs e)
218 {
219 ActivityTextBox.AppendText(
220 $"{Strings.Client_connected}{Environment.NewLine}");
221 }
222  
223 private void OnMqttServerStarted(object sender, EventArgs e)
224 {
225 ActivityTextBox.AppendText(
226 $"{Strings.Server_started}{Environment.NewLine}");
227 }
228  
229 private void OnMqttServerStopped(object sender, EventArgs e)
230 {
231 ActivityTextBox.AppendText(
232 $"{Strings.Server_stopped}{Environment.NewLine}");
233 }
234  
235 private void OnMqttClientConnected(object sender, MQTTnet.Client.MqttClientConnectedEventArgs e)
236 {
237 ActivityTextBox.AppendText(
238 $"{Strings.Client_connected}{Environment.NewLine}");
239 }
240  
241 private void OnMqttClientDisconnected(object sender, MQTTnet.Client.MqttClientDisconnectedEventArgs e)
242 {
243 ActivityTextBox.AppendText(
244 $"{Strings.Client_disconnected}{Environment.NewLine}");
245 }
246  
247 private void OnMqttClientConnectionFailed(object sender, MqttManagedProcessFailedEventArgs e)
248 {
249 ActivityTextBox.AppendText(
250 $"{Strings.Client_connection_failed}{Environment.NewLine}");
251 }
252  
10 office 253 private void OnMqttServerAuthenticationFailed(object sender, MqttAuthenticationFailureEventArgs e)
9 office 254 {
255 ActivityTextBox.AppendText(
10 office 256 $"{Strings.Failed_to_authenticate_client} : {e.Exception}{Environment.NewLine}");
8 office 257 }
258  
10 office 259 private void OnMqttClientAuthenticationFailed(object sender, MqttAuthenticationFailureEventArgs e)
8 office 260 {
261 ActivityTextBox.AppendText(
10 office 262 $"{Strings.Failed_to_authenticate_with_server} : {e.Exception}{Environment.NewLine}");
8 office 263 }
264  
10 office 265 private void OnMouseKeyBindingsSynchronized(object sender, KeyBindingsSynchronizerEventArgs e)
7 office 266 {
267 ActivityTextBox.AppendText(
10 office 268 $"{Strings.Synchronized_bindings_with_client} : {e.Bindings.Nick} : {e.Bindings.KeyBindings.Count}{Environment.NewLine}");
6 office 269  
10 office 270 var exchangeBindings = KeyBindingsExchange.ExchangeBindings.FirstOrDefault(exchangeBinding =>
7 office 271 string.Equals(exchangeBinding.Nick, e.Bindings.Nick, StringComparison.Ordinal));
5 office 272  
7 office 273 // If the nick does not exist then add it.
274 if (exchangeBindings == null)
275 {
10 office 276 KeyBindingsExchange.ExchangeBindings.Add(e.Bindings);
9 office 277 RemoteBindingsComboBoxSource.ResetBindings(false);
10 office 278 UpdateRemoteItems();
7 office 279 return;
280 }
5 office 281  
7 office 282 // If the bindings for the nick have not changed then do not update.
10 office 283 if (exchangeBindings.KeyBindings.SequenceEqual(e.Bindings.KeyBindings))
7 office 284 {
9 office 285 RemoteBindingsComboBoxSource.ResetBindings(false);
10 office 286 UpdateRemoteItems();
7 office 287 return;
288 }
5 office 289  
7 office 290 // Update the bindings.
10 office 291 exchangeBindings.KeyBindings = e.Bindings.KeyBindings;
9 office 292 RemoteBindingsComboBoxSource.ResetBindings(false);
10 office 293 UpdateRemoteItems();
7 office 294 }
5 office 295  
10 office 296 private void UpdateRemoteItems()
7 office 297 {
10 office 298 var exchangeBindings = (List<KeyBinding>) RemoteBindingsComboBox.SelectedValue;
299 if (exchangeBindings == null)
7 office 300 return;
5 office 301  
14 office 302 var replaceMouseBindings = new ObservableCollection<RemoteKeyBinding>();
10 office 303 foreach (var remoteBinding in RemoteKeyBindings.Bindings)
304 {
305 if (!exchangeBindings.Any(binding =>
306 string.Equals(binding.Name, remoteBinding.Name, StringComparison.Ordinal)))
307 continue;
308  
309 replaceMouseBindings.Add(remoteBinding);
310 }
311  
21 office 312 RemoteKeyBindings.Bindings.Clear();
313 foreach (var binding in replaceMouseBindings) RemoteKeyBindings.Bindings.Add(binding);
10 office 314  
9 office 315 RemoteBindingsListBox.Items.Clear();
316 RemoteBindingsListBox.DisplayMember = "Name";
317 RemoteBindingsListBox.ValueMember = "Name";
10 office 318 var bindings = exchangeBindings.Select(binding => (object) binding.Name).ToArray();
319 if (bindings.Length == 0)
7 office 320 return;
5 office 321  
10 office 322 RemoteBindingsListBox.Items.AddRange(bindings);
7 office 323 }
5 office 324  
325 private void OnLobbyMessageReceived(object sender, LobbyMessageReceivedEventArgs e)
326 {
27 office 327 notifyIcon1.BalloonTipTitle = Strings.Lobby_message;
25 office 328 notifyIcon1.BalloonTipText = $"{e.Nick} : {e.Message}{Environment.NewLine}";
329 notifyIcon1.ShowBalloonTip(1000);
330  
9 office 331 LobbyTextBox.AppendText($"{e.Nick} : {e.Message}{Environment.NewLine}");
5 office 332 }
333  
1 office 334 private void AddressTextBoxClick(object sender, EventArgs e)
335 {
336 Address.BackColor = Color.Empty;
337 }
338  
339 private void PortTextBoxClick(object sender, EventArgs e)
340 {
341 Port.BackColor = Color.Empty;
342 }
343  
344 private async void HostButtonClickAsync(object sender, EventArgs e)
345 {
346 // Stop the MQTT server if it is running.
9 office 347 if (MqttCommunication.Running)
1 office 348 {
10 office 349 await MqttCommunication.Stop();
1 office 350 HostButton.BackColor = Color.Empty;
351  
3 office 352 // Enable controls.
1 office 353 ConnectButton.Enabled = true;
5 office 354 Address.Enabled = true;
355 Port.Enabled = true;
356 Nick.Enabled = true;
10 office 357 Password.Enabled = true;
1 office 358 return;
359 }
360  
21 office 361 if (!ValidateConnectionParameters(out var ipAddress, out var port, out var nick, out var password))
1 office 362 return;
363  
23 office 364 StoreConnectionAutocomplete();
365  
32 office 366 // Try to reserve port: try UPnP followed by PMP.
367 if (!await Discovery.CreateMapping(DiscoveryType.UPnP, port) &&
368 !await Discovery.CreateMapping(DiscoveryType.PMP, port))
369 ActivityTextBox.AppendText(
370 $"{Strings.Failed_creating_automatic_port_mapping_please_make_sure_the_port_is_routed_properly}{Environment.NewLine}");
371  
1 office 372 // Start the MQTT server.
10 office 373 if (!await MqttCommunication
374 .Start(MqttCommunicationType.Server, ipAddress, port, nick, password))
9 office 375 {
376 ActivityTextBox.AppendText(
377 $"{Strings.Failed_starting_server}{Environment.NewLine}");
378 return;
379 }
380  
1 office 381 HostButton.BackColor = Color.Aquamarine;
382  
3 office 383 // Disable controls
1 office 384 ConnectButton.Enabled = false;
3 office 385 Address.Enabled = false;
386 Port.Enabled = false;
387 Nick.Enabled = false;
10 office 388 Password.Enabled = false;
3 office 389 }
390  
23 office 391 private async void StoreConnectionAutocomplete()
392 {
393 Address.AutoCompleteCustomSource.Add(Address.Text);
394  
395 await AutoCompletion.Save(Address.Name, Address.AutoCompleteCustomSource);
396  
397 Port.AutoCompleteCustomSource.Add(Port.Text);
398  
399 await AutoCompletion.Save(Port.Name, Port.AutoCompleteCustomSource);
400  
401 Nick.AutoCompleteCustomSource.Add(Nick.Text);
402  
403 await AutoCompletion.Save(Nick.Name, Nick.AutoCompleteCustomSource);
404 }
405  
21 office 406 private bool ValidateConnectionParameters(
407 out IPAddress address,
408 out int port,
409 out string nick,
410 out string password)
1 office 411 {
412 address = IPAddress.Any;
413 port = 0;
2 office 414 nick = string.Empty;
8 office 415 password = string.Empty;
1 office 416  
417 if (string.IsNullOrEmpty(Address.Text) &&
2 office 418 string.IsNullOrEmpty(Port.Text) &&
8 office 419 string.IsNullOrEmpty(Nick.Text) &&
420 string.IsNullOrEmpty(Password.Text))
1 office 421 {
422 Address.BackColor = Color.LightPink;
423 Port.BackColor = Color.LightPink;
2 office 424 Nick.BackColor = Color.LightPink;
8 office 425 Password.BackColor = Color.LightPink;
1 office 426 return false;
427 }
428  
429 if (!IPAddress.TryParse(Address.Text, out address))
21 office 430 try
431 {
432 address = Dns.GetHostAddresses(Address.Text).FirstOrDefault();
433 }
434 catch (Exception ex)
435 {
436 ActivityTextBox.AppendText(
437 $"{Strings.Could_not_resolve_hostname} : {ex.Message}{Environment.NewLine}");
1 office 438  
21 office 439 Address.BackColor = Color.LightPink;
440 return false;
441 }
442  
1 office 443 if (!uint.TryParse(Port.Text, out var uPort))
444 {
445 Port.BackColor = Color.LightPink;
446 return false;
447 }
448  
449 port = (int) uPort;
450  
2 office 451 if (string.IsNullOrEmpty(Nick.Text))
452 {
453 Nick.BackColor = Color.LightPink;
454 return false;
455 }
456  
457 nick = Nick.Text;
458  
8 office 459 if (string.IsNullOrEmpty(Password.Text))
460 {
461 Password.BackColor = Color.LightPink;
462 return false;
463 }
464  
10 office 465 password = AES.ExpandKey(Password.Text);
8 office 466  
1 office 467 Address.BackColor = Color.Empty;
468 Port.BackColor = Color.Empty;
2 office 469 Nick.BackColor = Color.Empty;
8 office 470 Password.BackColor = Color.Empty;
1 office 471  
472 return true;
473 }
474  
475 private async void ConnectButtonClickAsync(object sender, EventArgs e)
476 {
9 office 477 if (MqttCommunication.Running)
1 office 478 {
10 office 479 await MqttCommunication.Stop();
5 office 480 ConnectButton.Text = Strings.Connect;
1 office 481 ConnectButton.BackColor = Color.Empty;
482  
5 office 483 Address.Enabled = true;
484 Port.Enabled = true;
485 Nick.Enabled = true;
10 office 486 Password.Enabled = true;
1 office 487 HostButton.Enabled = true;
488 return;
489 }
490  
21 office 491 if (!ValidateConnectionParameters(out var ipAddress, out var port, out var nick, out var password))
1 office 492 return;
493  
23 office 494 StoreConnectionAutocomplete();
495  
10 office 496 if (!await MqttCommunication
497 .Start(MqttCommunicationType.Client, ipAddress, port, nick, password))
9 office 498 {
499 ActivityTextBox.AppendText(
500 $"{Strings.Failed_starting_client}{Environment.NewLine}");
501 return;
502 }
1 office 503  
5 office 504 ConnectButton.Text = Strings.Disconnect;
1 office 505 ConnectButton.BackColor = Color.Aquamarine;
506  
507 HostButton.Enabled = false;
5 office 508 Address.Enabled = false;
509 Port.Enabled = false;
510 Nick.Enabled = false;
10 office 511 Password.Enabled = false;
1 office 512 }
513  
2 office 514 private async void LobbySayTextBoxKeyDown(object sender, KeyEventArgs e)
515 {
25 office 516 // Do not send messages if the communication is not running.
517 if (!MqttCommunication.Running)
518 return;
519  
2 office 520 if (e.KeyCode != Keys.Enter)
521 return;
522  
10 office 523 await LobbyMessageSynchronizer.Broadcast(LobbySayTextBox.Text);
2 office 524  
5 office 525 LobbySayTextBox.Text = string.Empty;
2 office 526 }
4 office 527  
10 office 528 private void LocalAddBindingButtonClick(object sender, EventArgs e)
4 office 529 {
9 office 530 if (string.IsNullOrEmpty(LocalNameTextBox.Text))
4 office 531 {
9 office 532 LocalNameTextBox.BackColor = Color.LightPink;
4 office 533 return;
534 }
535  
10 office 536 // Only unique names allowed.
537 if (LocalKeyBindings.Bindings.Any(binding =>
538 string.Equals(binding.Name, LocalNameTextBox.Text, StringComparison.Ordinal)))
539 {
540 LocalNameTextBox.BackColor = Color.LightPink;
24 office 541 LocalBindingsCheckedListBox.BackColor = Color.LightPink;
10 office 542 return;
543 }
544  
545 LocalNameTextBox.BackColor = Color.Empty;
24 office 546 LocalBindingsCheckedListBox.BackColor = Color.Empty;
10 office 547  
8 office 548 ShowOverlayPanel();
4 office 549  
550 MouseKeyCombo = new List<string>();
551  
10 office 552 MouseKeyApplicationHook = Hook.GlobalEvents();
9 office 553 MouseKeyApplicationHook.KeyUp += LocalMouseKeyHookOnKeyUp;
554 MouseKeyApplicationHook.KeyDown += LocalMouseKeyHookOnKeyDown;
4 office 555 }
556  
8 office 557 private void ShowOverlayPanel()
558 {
559 OverlayPanel.BringToFront();
560 OverlayPanel.Visible = true;
561 OverlayPanel.Invalidate();
562 }
563  
14 office 564 private async void LocalMouseKeyHookOnKeyUp(object sender, KeyEventArgs e)
4 office 565 {
10 office 566 LocalKeyBindings.Bindings.Add(new KeyBinding(LocalNameTextBox.Text, MouseKeyCombo));
4 office 567  
24 office 568 LocalCheckedListBoxBindingSource.ResetBindings(false);
4 office 569  
9 office 570 MouseKeyApplicationHook.KeyDown -= LocalMouseKeyHookOnKeyDown;
571 MouseKeyApplicationHook.KeyUp -= LocalMouseKeyHookOnKeyUp;
4 office 572  
573 MouseKeyApplicationHook.Dispose();
574  
9 office 575 LocalNameTextBox.Text = string.Empty;
8 office 576 HideOverlayPanel();
9 office 577  
14 office 578 await SaveLocalMouseKeyBindings();
4 office 579 }
580  
8 office 581 private void HideOverlayPanel()
582 {
583 OverlayPanel.SendToBack();
584 OverlayPanel.Visible = false;
585 OverlayPanel.Invalidate();
586 }
587  
9 office 588 private void LocalMouseKeyHookOnKeyDown(object sender, KeyEventArgs e)
4 office 589 {
590 e.SuppressKeyPress = true;
591  
10 office 592 KeyConversion.KeysToString.TryGetValue((byte) e.KeyCode, out var key);
593  
594 MouseKeyCombo.Add(key);
4 office 595 }
596  
10 office 597 private void LocalNameTextBoxClick(object sender, EventArgs e)
4 office 598 {
9 office 599 LocalNameTextBox.BackColor = Color.Empty;
4 office 600 }
601  
14 office 602 private async void LocalBindingsRemoveButtonClick(object sender, EventArgs e)
4 office 603 {
24 office 604 var helmBinding = (KeyBinding) LocalBindingsCheckedListBox.SelectedItem;
5 office 605 if (helmBinding == null)
606 return;
4 office 607  
10 office 608 LocalKeyBindings.Bindings.Remove(helmBinding);
24 office 609 LocalCheckedListBoxBindingSource.ResetBindings(false);
9 office 610  
14 office 611 await SaveLocalMouseKeyBindings();
4 office 612 }
613  
5 office 614 private async void LobbySayButtonClick(object sender, EventArgs e)
4 office 615 {
25 office 616 // Do not send messages if the communication is not running.
617 if (!MqttCommunication.Running)
618 return;
619  
10 office 620 await LobbyMessageSynchronizer.Broadcast(LobbySayTextBox.Text);
4 office 621  
5 office 622 LobbySayTextBox.Text = string.Empty;
4 office 623 }
624  
9 office 625 private void RemoteBindingsComboBoxSelectionChangeCompleted(object sender, EventArgs e)
4 office 626 {
10 office 627 UpdateRemoteItems();
4 office 628 }
8 office 629  
14 office 630 private async void WingManFormOnLoad(object sender, EventArgs e)
8 office 631 {
14 office 632 await LoadLocalMouseKeyBindings();
10 office 633  
14 office 634 await LoadRemoteMouseKeyBindings();
8 office 635 }
9 office 636  
10 office 637 private void RemoteBindingsBindButtonClicked(object sender, EventArgs e)
9 office 638 {
10 office 639 if (string.IsNullOrEmpty((string) RemoteBindingsListBox.SelectedItem))
9 office 640 {
10 office 641 RemoteBindingsListBox.BackColor = Color.LightPink;
642 return;
643 }
9 office 644  
10 office 645 RemoteBindingsListBox.BackColor = Color.Empty;
9 office 646  
10 office 647 ShowOverlayPanel();
9 office 648  
10 office 649 MouseKeyCombo = new List<string>();
9 office 650  
10 office 651 MouseKeyApplicationHook = Hook.GlobalEvents();
21 office 652 MouseKeyApplicationHook.KeyUp += RemoteKeyHookOnKeyUp;
653 MouseKeyApplicationHook.KeyDown += RemoteKeyHookOnKeyDown;
9 office 654 }
655  
10 office 656 private void RemoteBindingsUnbindButtonClicked(object sender, EventArgs e)
9 office 657 {
10 office 658 var item = (string) RemoteBindingsListBox.SelectedItem;
659 if (string.IsNullOrEmpty(item))
660 {
661 RemoteBindingsListBox.BackColor = Color.LightPink;
662 return;
663 }
9 office 664  
10 office 665 RemoteBindingsListBox.BackColor = Color.Empty;
9 office 666  
10 office 667 var remoteKeyBinding = RemoteKeyBindings.Bindings.FirstOrDefault(binding =>
668 string.Equals(binding.Name, item, StringComparison.Ordinal));
669  
670 if (remoteKeyBinding == null)
671 return;
672  
673 RemoteKeyBindings.Bindings.Remove(remoteKeyBinding);
674 RemoteBindingsBindToBox.Text = string.Empty;
9 office 675 }
676  
21 office 677 private void RemoteKeyHookOnKeyDown(object sender, KeyEventArgs e)
9 office 678 {
679 e.SuppressKeyPress = true;
680  
21 office 681 if (!KeyConversion.KeysToString.TryGetValue((byte) e.KeyCode, out var key))
682 return;
9 office 683  
10 office 684 MouseKeyCombo.Add(key);
9 office 685 }
686  
21 office 687 private async void RemoteKeyHookOnKeyUp(object sender, KeyEventArgs e)
9 office 688 {
10 office 689 RemoteKeyBindings.Bindings.Add(new RemoteKeyBinding(RemoteBindingsComboBox.Text,
9 office 690 (string) RemoteBindingsListBox.SelectedItem, MouseKeyCombo));
691  
21 office 692 MouseKeyApplicationHook.KeyDown -= RemoteKeyHookOnKeyDown;
693 MouseKeyApplicationHook.KeyUp -= RemoteKeyHookOnKeyUp;
9 office 694  
695 MouseKeyApplicationHook.Dispose();
696  
697 RemoteBindingsBindToBox.Text = string.Join(" + ", MouseKeyCombo);
698 HideOverlayPanel();
699  
14 office 700 await SaveRemoteMouseKeyBindings();
9 office 701 }
702  
10 office 703 private void RemoteBindingsListBoxSelectedValueChanged(object sender, EventArgs e)
9 office 704 {
10 office 705 RemoteBindingsBindToBox.Text = "";
9 office 706  
10 office 707 var name = (string) RemoteBindingsListBox.SelectedItem;
708 if (string.IsNullOrEmpty(name))
709 return;
9 office 710  
14 office 711 var nick = RemoteBindingsComboBox.Text;
712 if (string.IsNullOrEmpty(nick))
713 return;
714  
10 office 715 foreach (var binding in RemoteKeyBindings.Bindings)
716 {
14 office 717 if (!string.Equals(binding.Nick, nick) || !string.Equals(binding.Name, name))
10 office 718 continue;
9 office 719  
10 office 720 RemoteBindingsBindToBox.Text = string.Join(" + ", binding.Keys);
721 break;
722 }
723 }
9 office 724  
23 office 725 private void WingManFormResized(object sender, EventArgs e)
726 {
27 office 727 if (WindowState == FormWindowState.Minimized) Hide();
23 office 728 }
729  
730 private void NotifyIconDoubleClick(object sender, EventArgs e)
731 {
732 Show();
733 WindowState = FormWindowState.Normal;
734 }
735  
24 office 736 private async void LocalBindingsCheckedListBoxItemCheck(object sender, ItemCheckEventArgs e)
737 {
738 var helmBinding = (KeyBinding) LocalBindingsCheckedListBox.Items[e.Index];
739 if (helmBinding == null)
740 return;
741  
742 switch (e.NewValue)
743 {
744 case CheckState.Checked:
745 helmBinding.Enabled = true;
746 break;
747 case CheckState.Unchecked:
748 helmBinding.Enabled = false;
749 break;
750 }
751  
752 await SaveLocalMouseKeyBindings();
753 }
754  
10 office 755 #region Saving and loading
756  
757 private async Task SaveLocalMouseKeyBindings()
758 {
759 try
760 {
761 using (var memoryStream = new MemoryStream())
762 {
763 LocalKeyBindings.XmlSerializer.Serialize(memoryStream, LocalKeyBindings);
764  
765 memoryStream.Position = 0L;
766  
767 using (var fileStream = new FileStream("LocalKeyBindings.xml", FileMode.Create))
768 {
769 await memoryStream.CopyToAsync(fileStream);
770 }
771 }
772 }
773 catch (Exception)
774 {
775 ActivityTextBox.AppendText(
776 $"{Strings.Failed_saving_local_bindings}{Environment.NewLine}");
777 }
9 office 778 }
779  
10 office 780 private async Task LoadLocalMouseKeyBindings()
781 {
782 try
783 {
784 using (var fileStream = new FileStream("LocalKeyBindings.xml", FileMode.Open))
785 {
786 using (var memoryStream = new MemoryStream())
787 {
788 await fileStream.CopyToAsync(memoryStream);
789  
790 memoryStream.Position = 0L;
791  
792 var loadedBindings =
793 (LocalKeyBindings) LocalKeyBindings.XmlSerializer.Deserialize(memoryStream);
794  
21 office 795 foreach (var binding in loadedBindings.Bindings)
796 LocalKeyBindings.Bindings.Add(binding);
10 office 797  
24 office 798  
799 LocalCheckedListBoxBindingSource.ResetBindings(false);
10 office 800 }
801 }
802 }
803 catch (Exception)
804 {
805 ActivityTextBox.AppendText(
806 $"{Strings.Failed_loading_local_bindings}{Environment.NewLine}");
807 }
808 }
809  
9 office 810 private async Task SaveRemoteMouseKeyBindings()
811 {
812 try
813 {
814 using (var memoryStream = new MemoryStream())
815 {
10 office 816 RemoteKeyBindings.XmlSerializer.Serialize(memoryStream, RemoteKeyBindings);
9 office 817  
818 memoryStream.Position = 0L;
819  
10 office 820 using (var fileStream = new FileStream("RemoteKeyBindings.xml", FileMode.Create))
9 office 821 {
10 office 822 await memoryStream.CopyToAsync(fileStream);
9 office 823 }
824 }
825 }
826 catch (Exception)
827 {
828 ActivityTextBox.AppendText(
829 $"{Strings.Failed_saving_remote_bindings}{Environment.NewLine}");
830 }
831 }
832  
833 private async Task LoadRemoteMouseKeyBindings()
834 {
835 try
836 {
10 office 837 using (var fileStream = new FileStream("RemoteKeyBindings.xml", FileMode.Open))
9 office 838 {
839 using (var memoryStream = new MemoryStream())
840 {
10 office 841 await fileStream.CopyToAsync(memoryStream);
9 office 842  
843 memoryStream.Position = 0L;
844  
845 var loadedBindings =
10 office 846 (RemoteKeyBindings) RemoteKeyBindings.XmlSerializer.Deserialize(memoryStream);
9 office 847  
21 office 848 foreach (var binding in loadedBindings.Bindings)
849 RemoteKeyBindings.Bindings.Add(binding);
9 office 850 }
851 }
852 }
853 catch (Exception)
854 {
855 ActivityTextBox.AppendText(
856 $"{Strings.Failed_loading_remote_bindings}{Environment.NewLine}");
857 }
858 }
10 office 859  
860 #endregion
1 office 861 }
862 }