WingMan – Rev 6
?pathlinks?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using WingMan.Communication;
using WingMan.MouseKey;
using WingMan.Properties;
namespace WingMan
{
public partial class WingManForm : Form
{
public WingManForm()
{
InitializeComponent();
FormTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
MQTTCommunication = new MQTTCommunication(FormTaskScheduler);
MouseKeyBindings = new MouseKeyBindings(new List<MouseKeyBinding>());
HelmBindingSource = new BindingSource
{
DataSource = MouseKeyBindings.Bindings
};
HelmBindingsListBox.DisplayMember = "DisplayName";
HelmBindingsListBox.ValueMember = "Keys";
HelmBindingsListBox.DataSource = HelmBindingSource;
MouseKeyBindingsExchange = new MouseKeyBindingsExchange();
WingBindingSource = new BindingSource
{
DataSource = MouseKeyBindingsExchange.ExchangeBindings
};
WingBindingsComboBox.DisplayMember = "Nick";
WingBindingsComboBox.ValueMember = "Names";
WingBindingsComboBox.DataSource = WingBindingSource;
// Start lobby message synchronizer.
LobbyMessageSynchronizer = new LobbyMessageSynchronizer(MQTTCommunication);
LobbyMessageSynchronizer.OnLobbyMessageReceived += OnLobbyMessageReceived;
// Start mouse key bindings synchronizer.
MouseKeyBindingsSynchronizer = new MouseKeyBindingsSynchronizer(MouseKeyBindings, MQTTCommunication);
MouseKeyBindingsSynchronizer.OnMouseKeyBindingsSynchronized += OnMouseKeyBindingsSynchronized;
}
private void OnMouseKeyBindingsSynchronized(object sender, MouseKeyBindingsSynchronizedEventArgs e)
{
foreach (var binding in e.ExchangeBindings)
{
ActivityTextBox.AppendText(
$"{Strings.Synchronized_bindings_with_client} : {binding.Nick} : {binding.Names.Count}{Environment.NewLine}");
var exchangeBindings = MouseKeyBindingsExchange.ExchangeBindings.FirstOrDefault(exchangeBinding =>
string.Equals(exchangeBinding.Nick, binding.Nick, StringComparison.Ordinal));
// If the nick has not been registered add it.
if (exchangeBindings == null)
{
MouseKeyBindingsExchange.ExchangeBindings.Add(binding);
continue;
}
// If the nick has been added, then update the binding names.
exchangeBindings.Names = binding.Names;
// Update wing list box.
var selectedExchangeBinding = (MouseKeyBindingExchange) WingBindingsComboBox.SelectedItem;
if (selectedExchangeBinding == null || !string.Equals(selectedExchangeBinding.Nick, binding.Nick))
continue;
WingBindingsListBox.Items.Clear();
WingBindingsListBox.DisplayMember = "Name";
WingBindingsListBox.ValueMember = "Name";
WingBindingsListBox.Items.AddRange(exchangeBindings.Names.Select(name => (object) name).ToArray());
}
WingBindingSource.ResetBindings(false);
}
private static TaskScheduler FormTaskScheduler { get; set; }
private static IKeyboardMouseEvents MouseKeyApplicationHook { get; set; }
private List<string> MouseKeyCombo { get; set; }
private MouseKeyBindings MouseKeyBindings { get; }
private BindingSource HelmBindingSource { get; }
private BindingSource WingBindingSource { get; set; }
private MouseKeyBindingsExchange MouseKeyBindingsExchange { get; set; }
public MQTTCommunication MQTTCommunication { get; set; }
public LobbyMessageSynchronizer LobbyMessageSynchronizer { get; set; }
public MouseKeyBindingsSynchronizer MouseKeyBindingsSynchronizer { get; set; }
private void OnLobbyMessageReceived(object sender, LobbyMessageReceivedEventArgs e)
{
LobbyTextBox.Invoke((MethodInvoker) delegate
{
LobbyTextBox.AppendText($"{e.Nick} : {e.Message}{Environment.NewLine}");
});
}
private void AddressTextBoxClick(object sender, EventArgs e)
{
Address.BackColor = Color.Empty;
}
private void PortTextBoxClick(object sender, EventArgs e)
{
Port.BackColor = Color.Empty;
}
private async void HostButtonClickAsync(object sender, EventArgs e)
{
// Stop the MQTT server if it is running.
if (MQTTCommunication.Running)
{
await MQTTCommunication.Stop().ConfigureAwait(false);
toolStripStatusLabel.Text = Strings.Server_stopped;
HostButton.BackColor = Color.Empty;
// Enable controls.
ConnectButton.Enabled = true;
Address.Enabled = true;
Port.Enabled = true;
Nick.Enabled = true;
return;
}
if (!ValidateAddressPort(out var ipAddress, out var port, out var nick))
return;
// Start the MQTT server.
await MQTTCommunication.Start(MQTTCommunicationType.Server, ipAddress, port, nick).ConfigureAwait(false);
toolStripStatusLabel.Text = Strings.Server_started;
HostButton.BackColor = Color.Aquamarine;
// Disable controls
ConnectButton.Enabled = false;
Address.Enabled = false;
Port.Enabled = false;
Nick.Enabled = false;
}
private bool ValidateAddressPort(out IPAddress address, out int port, out string nick)
{
address = IPAddress.Any;
port = 0;
nick = string.Empty;
if (string.IsNullOrEmpty(Address.Text) &&
string.IsNullOrEmpty(Port.Text) &&
string.IsNullOrEmpty(Nick.Text))
{
Address.BackColor = Color.LightPink;
Port.BackColor = Color.LightPink;
Nick.BackColor = Color.LightPink;
return false;
}
if (!IPAddress.TryParse(Address.Text, out address))
{
Address.BackColor = Color.LightPink;
return false;
}
if (!uint.TryParse(Port.Text, out var uPort))
{
Port.BackColor = Color.LightPink;
return false;
}
port = (int) uPort;
if (string.IsNullOrEmpty(Nick.Text))
{
Nick.BackColor = Color.LightPink;
return false;
}
nick = Nick.Text;
Address.BackColor = Color.Empty;
Port.BackColor = Color.Empty;
Nick.BackColor = Color.Empty;
return true;
}
private async void ConnectButtonClickAsync(object sender, EventArgs e)
{
if (MQTTCommunication.Running)
{
await MQTTCommunication.Stop().ConfigureAwait(false);
ConnectButton.Text = Strings.Connect;
ConnectButton.BackColor = Color.Empty;
Address.Enabled = true;
Port.Enabled = true;
Nick.Enabled = true;
HostButton.Enabled = true;
return;
}
if (!ValidateAddressPort(out var ipAddress, out var port, out var nick))
return;
await MQTTCommunication.Start(MQTTCommunicationType.Client, ipAddress, port, nick).ConfigureAwait(false);
toolStripStatusLabel.Text = Strings.Client_started;
ConnectButton.Text = Strings.Disconnect;
ConnectButton.BackColor = Color.Aquamarine;
HostButton.Enabled = false;
Address.Enabled = false;
Port.Enabled = false;
Nick.Enabled = false;
}
private async void LobbySayTextBoxKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode != Keys.Enter)
return;
await LobbyMessageSynchronizer.Broadcast(LobbySayTextBox.Text).ConfigureAwait(false);
LobbySayTextBox.Text = string.Empty;
}
private void HelmAddButtonClick(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(HelmNameTextBox.Text))
{
HelmNameTextBox.BackColor = Color.LightPink;
return;
}
HelmAddButton.Enabled = false;
MouseKeyCombo = new List<string>();
MouseKeyApplicationHook = Hook.AppEvents();
MouseKeyApplicationHook.MouseDown += MouseKeyHookOnMouseDown;
MouseKeyApplicationHook.KeyUp += MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.KeyDown += MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.MouseUp += MouseKeyHookOnMouseUp;
}
private void MouseKeyHookOnKeyUp(object sender, KeyEventArgs e)
{
MouseKeyBindings.Bindings.Add(new MouseKeyBinding(HelmNameTextBox.Text, MouseKeyCombo));
HelmBindingSource.ResetBindings(false);
MouseKeyApplicationHook.KeyDown -= MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.KeyUp -= MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.KeyDown -= MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.KeyUp -= MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.Dispose();
HelmNameTextBox.Text = string.Empty;
HelmAddButton.Enabled = true;
}
private void MouseKeyHookOnMouseUp(object sender, MouseEventArgs e)
{
MouseKeyBindings.Bindings.Add(new MouseKeyBinding(HelmNameTextBox.Text, MouseKeyCombo));
HelmBindingSource.ResetBindings(false);
MouseKeyApplicationHook.KeyDown -= MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.KeyUp -= MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.KeyDown -= MouseKeyHookOnKeyDown;
MouseKeyApplicationHook.KeyUp -= MouseKeyHookOnKeyUp;
MouseKeyApplicationHook.Dispose();
HelmNameTextBox.Text = string.Empty;
HelmAddButton.Enabled = true;
}
private void MouseKeyHookOnMouseDown(object sender, MouseEventArgs e)
{
MouseKeyCombo.Add(e.Button.ToDisplayName());
}
private void MouseKeyHookOnKeyDown(object sender, KeyEventArgs e)
{
e.SuppressKeyPress = true;
MouseKeyCombo.Add(e.KeyCode.ToDisplayName());
}
private void HelmNameTextBoxClick(object sender, EventArgs e)
{
HelmNameTextBox.BackColor = Color.Empty;
}
private void HelmRemoveButtonClick(object sender, EventArgs e)
{
var helmBinding = (MouseKeyBinding) HelmBindingsListBox.SelectedItem;
if (helmBinding == null)
return;
MouseKeyBindings.Bindings.Remove(helmBinding);
HelmBindingSource.ResetBindings(false);
}
private async void LobbySayButtonClick(object sender, EventArgs e)
{
await LobbyMessageSynchronizer.Broadcast(LobbySayTextBox.Text).ConfigureAwait(false);
LobbySayTextBox.Text = string.Empty;
}
private void WingBindingsComboBoxSelectionChangeCompleted(object sender, EventArgs e)
{
var exchangeBinding = (MouseKeyBindingExchange)WingBindingsComboBox.SelectedItem;
if (exchangeBinding == null)
return;
WingBindingsListBox.Items.Clear();
WingBindingsListBox.DisplayMember = "Name";
WingBindingsListBox.ValueMember = "Name";
WingBindingsListBox.Items.AddRange(exchangeBinding.Names.Select(name => (object)name).ToArray());
}
}
}