WingMan – Blame information for rev 27

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