using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Controls; using DS4Windows; namespace DS4WinWPF.DS4Forms.ViewModels { public class TrayIconViewModel { private string tooltipText = "DS4Windows"; private string iconSource = "/DS4Windows;component/Resources/DS4W.ico"; public const string ballonTitle = "DS4Windows"; public static string trayTitle = $"DS4Windows v{Global.exeversion}"; private ContextMenu contextMenu; public string TooltipText { get => tooltipText; set { string temp = value; if (value.Length > 63) temp = value.Substring(0, 63); if (tooltipText == temp) return; tooltipText = temp; TooltipTextChanged?.Invoke(this, EventArgs.Empty); } } public event EventHandler TooltipTextChanged; public string IconSource { get => iconSource; set { if (iconSource == value) return; iconSource = value; IconSourceChanged?.Invoke(this, EventArgs.Empty); } } public ContextMenu ContextMenu { get => contextMenu; } public event EventHandler IconSourceChanged; public event EventHandler RequestShutdown; public event EventHandler RequestOpen; public event EventHandler RequestMinimize; private List controllerList = new List(); private ProfileList profileListHolder; private ControlService controlService; public delegate void ProfileSelectedHandler(TrayIconViewModel sender, ControllerHolder item, string profile); public event ProfileSelectedHandler ProfileSelected; //public TrayIconViewModel(Tester tester) public TrayIconViewModel(ControlService service, ProfileList profileListHolder) { this.profileListHolder = profileListHolder; this.controlService = service; contextMenu = new ContextMenu(); PopulateControllerList(); PopulateToolText(); PopulateContextMenu(); SetupEvents(); profileListHolder.ProfileListCol.CollectionChanged += ProfileListCol_CollectionChanged; service.ServiceStarted += BuildControllerList; service.ServiceStarted += HookEvents; service.ServiceStarted += StartPopulateText; service.PreServiceStop += ClearToolText; service.PreServiceStop += UnhookEvents; service.PreServiceStop += ClearControllerList; service.HotplugController += Service_HotplugController; /*tester.StartControllers += HookBatteryUpdate; tester.StartControllers += StartPopulateText; tester.PreRemoveControllers += ClearToolText; tester.HotplugControllers += HookBatteryUpdate; tester.HotplugControllers += StartPopulateText; */ } private void ClearControllerList(object sender, EventArgs e) { controllerList.Clear(); } private void UnhookEvents(object sender, EventArgs e) { foreach (ControllerHolder holder in controllerList) { DS4Device currentDev = holder.Device; RemoveDeviceEvents(currentDev); } } private void Service_HotplugController(ControlService sender, DS4Device device, int index) { SetupDeviceEvents(device); controllerList.Add(new ControllerHolder(device, index)); } private void ProfileListCol_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { PopulateContextMenu(); } private void BuildControllerList(object sender, EventArgs e) { PopulateControllerList(); } public void PopulateContextMenu() { contextMenu.Items.Clear(); ItemCollection items = contextMenu.Items; MenuItem item; int idx = 0; foreach (ControllerHolder holder in controllerList) { DS4Device currentDev = holder.Device; item = new MenuItem() { Header = $"Controller {idx+1}" }; item.Tag = idx; //item.ContextMenu = new ContextMenu(); ItemCollection subitems = item.Items; string currentProfile = Global.ProfilePath[idx]; foreach (ProfileEntity entry in profileListHolder.ProfileListCol) { MenuItem temp = new MenuItem() { Header = entry.Name }; temp.Tag = idx; temp.Click += ProfileItem_Click; if (entry.Name == currentProfile) { temp.IsChecked = true; } subitems.Add(temp); } items.Add(item); idx++; } item = new MenuItem() { Header = "Disconnect Menu" }; idx = 0; foreach (ControllerHolder holder in controllerList) { DS4Device tempDev = holder.Device; if (tempDev.Synced && !tempDev.Charging) { MenuItem subitem = new MenuItem() { Header = $"Disconnect Controller {idx+1}" }; subitem.Click += DisconnectMenuItem_Click; subitem.Tag = idx; item.Items.Add(subitem); } idx++; } items.Add(item); items.Add(new Separator()); item = new MenuItem() { Header = "Open" }; item.Click += OpenMenuItem_Click; items.Add(item); item = new MenuItem() { Header = "Minimize" }; item.Click += MinimizeMenuItem_Click; items.Add(item); items.Add(new Separator()); item = new MenuItem() { Header = "Exit (Middle Mouse)" }; item.Click += ExitMenuItem_Click; items.Add(item); } private void OpenMenuItem_Click(object sender, System.Windows.RoutedEventArgs e) { RequestOpen?.Invoke(this, EventArgs.Empty); } private void MinimizeMenuItem_Click(object sender, System.Windows.RoutedEventArgs e) { RequestMinimize?.Invoke(this, EventArgs.Empty); } private void ProfileItem_Click(object sender, System.Windows.RoutedEventArgs e) { MenuItem item = sender as MenuItem; int idx = Convert.ToInt32(item.Tag); ControllerHolder holder = controllerList[idx]; ProfileSelected?.Invoke(this, holder, item.Header.ToString()); } private void DisconnectMenuItem_Click(object sender, System.Windows.RoutedEventArgs e) { MenuItem item = sender as MenuItem; int idx = Convert.ToInt32(item.Tag); ControllerHolder holder = controllerList[idx]; DS4Device tempDev = holder?.Device; if (tempDev != null && tempDev.Synced && !tempDev.Charging) { if (tempDev.ConnectionType == ConnectionType.BT) { tempDev.StopUpdate(); tempDev.DisconnectBT(); } else if (tempDev.ConnectionType == ConnectionType.SONYWA) { tempDev.DisconnectDongle(); } } //controllerList[idx] = null; } private void PopulateControllerList() { //IEnumerable devices = DS4Devices.getDS4Controllers(); int idx = 0; foreach (DS4Device currentDev in controlService.slotManager.ControllerColl) { controllerList.Add(new ControllerHolder(currentDev, idx)); idx++; } } private void StartPopulateText(object sender, EventArgs e) { PopulateToolText(); //PopulateContextMenu(); } private void PopulateToolText() { List items = new List(); items.Add(trayTitle); //IEnumerable devices = DS4Devices.getDS4Controllers(); int idx = 1; //foreach (DS4Device currentDev in devices) foreach (ControllerHolder holder in controllerList) { DS4Device currentDev = holder.Device; items.Add($"{idx}: {currentDev.ConnectionType} {currentDev.Battery}%{(currentDev.Charging ? "+" : "")}"); idx++; } TooltipText = string.Join("\n", items); } private void SetupEvents() { //IEnumerable devices = DS4Devices.getDS4Controllers(); //foreach (DS4Device currentDev in devices) foreach (ControllerHolder holder in controllerList) { DS4Device currentDev = holder.Device; SetupDeviceEvents(currentDev); } } private void SetupDeviceEvents(DS4Device device) { device.BatteryChanged += UpdateForBattery; device.ChargingChanged += UpdateForBattery; device.Removal += CurrentDev_Removal; } private void RemoveDeviceEvents(DS4Device device) { device.BatteryChanged -= UpdateForBattery; device.ChargingChanged -= UpdateForBattery; device.Removal -= CurrentDev_Removal; } private void CurrentDev_Removal(object sender, EventArgs e) { DS4Device currentDev = sender as DS4Device; ControllerHolder item = null; int idx = 0; foreach (ControllerHolder holder in controllerList) { if (currentDev == holder.Device) { item = holder; break; } idx++; } if (item != null) { controllerList.RemoveAt(idx); RemoveDeviceEvents(currentDev); PopulateToolText(); } } private void HookEvents(object sender, EventArgs e) { SetupEvents(); } private void UpdateForBattery(object sender, EventArgs e) { PopulateToolText(); } private void ClearToolText(object sender, EventArgs e) { TooltipText = "DS4Windows"; //contextMenu.Items.Clear(); } public void ClearContextMenu() { contextMenu.Items.Clear(); ItemCollection items = contextMenu.Items; MenuItem item = new MenuItem() { Header = "Open" }; item.Click += OpenMenuItem_Click; items.Add(item); item = new MenuItem() { Header = "Minimize" }; item.Click += MinimizeMenuItem_Click; items.Add(item); items.Add(new Separator()); item = new MenuItem() { Header = "Exit (Middle Mouse)" }; item.Click += ExitMenuItem_Click; items.Add(item); } private void ExitMenuItem_Click(object sender, System.Windows.RoutedEventArgs e) { RequestShutdown?.Invoke(this, EventArgs.Empty); } } public class ControllerHolder { private DS4Device device; private int index; public DS4Device Device { get => device; } public int Index { get => index; } public ControllerHolder(DS4Device device, int index) { this.device = device; this.index = index; } } }