WingMan – Blame information for rev 25
?pathlinks?
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 | { |
||
25 | office | 306 | notifyIcon1.BalloonTipTitle = Properties.Strings.Lobby_message; |
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 | { |
||
700 | if (WindowState == FormWindowState.Minimized) |
||
701 | { |
||
702 | Hide(); |
||
703 | } |
||
704 | } |
||
705 | |||
706 | private void NotifyIconDoubleClick(object sender, EventArgs e) |
||
707 | { |
||
708 | Show(); |
||
709 | WindowState = FormWindowState.Normal; |
||
710 | } |
||
711 | |||
24 | office | 712 | private async void LocalBindingsCheckedListBoxItemCheck(object sender, ItemCheckEventArgs e) |
713 | { |
||
714 | var helmBinding = (KeyBinding) LocalBindingsCheckedListBox.Items[e.Index]; |
||
715 | if (helmBinding == null) |
||
716 | return; |
||
717 | |||
718 | switch (e.NewValue) |
||
719 | { |
||
720 | case CheckState.Checked: |
||
721 | helmBinding.Enabled = true; |
||
722 | break; |
||
723 | case CheckState.Unchecked: |
||
724 | helmBinding.Enabled = false; |
||
725 | break; |
||
726 | } |
||
727 | |||
728 | await SaveLocalMouseKeyBindings(); |
||
729 | } |
||
730 | |||
10 | office | 731 | #region Saving and loading |
732 | |||
733 | private async Task SaveLocalMouseKeyBindings() |
||
734 | { |
||
735 | try |
||
736 | { |
||
737 | using (var memoryStream = new MemoryStream()) |
||
738 | { |
||
739 | LocalKeyBindings.XmlSerializer.Serialize(memoryStream, LocalKeyBindings); |
||
740 | |||
741 | memoryStream.Position = 0L; |
||
742 | |||
743 | using (var fileStream = new FileStream("LocalKeyBindings.xml", FileMode.Create)) |
||
744 | { |
||
745 | await memoryStream.CopyToAsync(fileStream); |
||
746 | } |
||
747 | } |
||
748 | } |
||
749 | catch (Exception) |
||
750 | { |
||
751 | ActivityTextBox.AppendText( |
||
752 | $"{Strings.Failed_saving_local_bindings}{Environment.NewLine}"); |
||
753 | } |
||
9 | office | 754 | } |
755 | |||
10 | office | 756 | private async Task LoadLocalMouseKeyBindings() |
757 | { |
||
758 | try |
||
759 | { |
||
760 | using (var fileStream = new FileStream("LocalKeyBindings.xml", FileMode.Open)) |
||
761 | { |
||
762 | using (var memoryStream = new MemoryStream()) |
||
763 | { |
||
764 | await fileStream.CopyToAsync(memoryStream); |
||
765 | |||
766 | memoryStream.Position = 0L; |
||
767 | |||
768 | var loadedBindings = |
||
769 | (LocalKeyBindings) LocalKeyBindings.XmlSerializer.Deserialize(memoryStream); |
||
770 | |||
21 | office | 771 | foreach (var binding in loadedBindings.Bindings) |
772 | LocalKeyBindings.Bindings.Add(binding); |
||
10 | office | 773 | |
24 | office | 774 | |
775 | LocalCheckedListBoxBindingSource.ResetBindings(false); |
||
10 | office | 776 | } |
777 | } |
||
778 | } |
||
779 | catch (Exception) |
||
780 | { |
||
781 | ActivityTextBox.AppendText( |
||
782 | $"{Strings.Failed_loading_local_bindings}{Environment.NewLine}"); |
||
783 | } |
||
784 | } |
||
785 | |||
9 | office | 786 | private async Task SaveRemoteMouseKeyBindings() |
787 | { |
||
788 | try |
||
789 | { |
||
790 | using (var memoryStream = new MemoryStream()) |
||
791 | { |
||
10 | office | 792 | RemoteKeyBindings.XmlSerializer.Serialize(memoryStream, RemoteKeyBindings); |
9 | office | 793 | |
794 | memoryStream.Position = 0L; |
||
795 | |||
10 | office | 796 | using (var fileStream = new FileStream("RemoteKeyBindings.xml", FileMode.Create)) |
9 | office | 797 | { |
10 | office | 798 | await memoryStream.CopyToAsync(fileStream); |
9 | office | 799 | } |
800 | } |
||
801 | } |
||
802 | catch (Exception) |
||
803 | { |
||
804 | ActivityTextBox.AppendText( |
||
805 | $"{Strings.Failed_saving_remote_bindings}{Environment.NewLine}"); |
||
806 | } |
||
807 | } |
||
808 | |||
809 | private async Task LoadRemoteMouseKeyBindings() |
||
810 | { |
||
811 | try |
||
812 | { |
||
10 | office | 813 | using (var fileStream = new FileStream("RemoteKeyBindings.xml", FileMode.Open)) |
9 | office | 814 | { |
815 | using (var memoryStream = new MemoryStream()) |
||
816 | { |
||
10 | office | 817 | await fileStream.CopyToAsync(memoryStream); |
9 | office | 818 | |
819 | memoryStream.Position = 0L; |
||
820 | |||
821 | var loadedBindings = |
||
10 | office | 822 | (RemoteKeyBindings) RemoteKeyBindings.XmlSerializer.Deserialize(memoryStream); |
9 | office | 823 | |
21 | office | 824 | foreach (var binding in loadedBindings.Bindings) |
825 | RemoteKeyBindings.Bindings.Add(binding); |
||
9 | office | 826 | } |
827 | } |
||
828 | } |
||
829 | catch (Exception) |
||
830 | { |
||
831 | ActivityTextBox.AppendText( |
||
832 | $"{Strings.Failed_loading_remote_bindings}{Environment.NewLine}"); |
||
833 | } |
||
834 | } |
||
10 | office | 835 | |
836 | #endregion |
||
1 | office | 837 | } |
838 | } |