cemu-DS4Windows/DS4Windows/DS4Forms/ViewModels/TrayIconViewModel.cs

415 lines
14 KiB
C#
Raw Normal View History

2019-12-18 22:33:23 +01:00
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows;
2019-12-18 22:33:23 +01:00
using System.Windows.Controls;
using DS4Windows;
namespace DS4WinWPF.DS4Forms.ViewModels
{
public class TrayIconViewModel
{
private string tooltipText = "DS4Windows";
public const string ICON_COLOR = "/DS4Windows;component/Resources/DS4W.ico";
public const string ICON_WHITE = "/DS4Windows;component/Resources/DS4W - White.ico";
private string iconSource = ICON_COLOR;
2019-12-18 22:33:23 +01:00
public const string ballonTitle = "DS4Windows";
public static string trayTitle = $"DS4Windows v{Global.exeversion}";
private ContextMenu contextMenu;
private MenuItem changeServiceItem;
private MenuItem openItem;
private MenuItem minimizeItem;
private MenuItem openProgramItem;
private MenuItem closeItem;
2019-12-18 22:33:23 +01:00
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;
public event EventHandler RequestServiceChange;
2019-12-18 22:33:23 +01:00
private ReaderWriterLockSlim _colLocker = new ReaderWriterLockSlim();
2019-12-18 22:33:23 +01:00
private List<ControllerHolder> controllerList = new List<ControllerHolder>();
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();
iconSource = Global.UseWhiteIcon ? ICON_WHITE : ICON_COLOR;
changeServiceItem = new MenuItem() { Header = "Start" };
changeServiceItem.Click += ChangeControlServiceItem_Click;
changeServiceItem.IsEnabled = false;
openItem = new MenuItem() { Header = "Open",
FontWeight = FontWeights.Bold };
openItem.Click += OpenMenuItem_Click;
minimizeItem = new MenuItem() { Header = "Minimize" };
minimizeItem.Click += MinimizeMenuItem_Click;
openProgramItem = new MenuItem() { Header = "Open Program Folder" };
openProgramItem.Click += OpenProgramFolderItem_Click;
closeItem = new MenuItem() { Header = "Exit (Middle Mouse)" }; ;
closeItem.Click += ExitMenuItem_Click;
2019-12-18 22:33:23 +01:00
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.RunningChanged += Service_RunningChanged;
2019-12-18 22:33:23 +01:00
service.HotplugController += Service_HotplugController;
/*tester.StartControllers += HookBatteryUpdate;
tester.StartControllers += StartPopulateText;
tester.PreRemoveControllers += ClearToolText;
tester.HotplugControllers += HookBatteryUpdate;
tester.HotplugControllers += StartPopulateText;
*/
}
private void Service_RunningChanged(object sender, EventArgs e)
{
string temp = controlService.running ? "Stop" : "Start";
App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
changeServiceItem.Header = temp;
changeServiceItem.IsEnabled = true;
}));
}
2019-12-18 22:33:23 +01:00
private void ClearControllerList(object sender, EventArgs e)
{
_colLocker.EnterWriteLock();
2019-12-18 22:33:23 +01:00
controllerList.Clear();
_colLocker.ExitWriteLock();
2019-12-18 22:33:23 +01:00
}
private void UnhookEvents(object sender, EventArgs e)
{
_colLocker.EnterReadLock();
2019-12-18 22:33:23 +01:00
foreach (ControllerHolder holder in controllerList)
{
DS4Device currentDev = holder.Device;
RemoveDeviceEvents(currentDev);
}
_colLocker.ExitReadLock();
2019-12-18 22:33:23 +01:00
}
private void Service_HotplugController(ControlService sender, DS4Device device, int index)
{
SetupDeviceEvents(device);
_colLocker.EnterWriteLock();
2019-12-18 22:33:23 +01:00
controllerList.Add(new ControllerHolder(device, index));
_colLocker.ExitWriteLock();
2019-12-18 22:33:23 +01:00
}
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;
_colLocker.EnterReadLock();
2019-12-18 22:33:23 +01:00
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++;
}
if (idx == 0)
{
item.IsEnabled = false;
}
_colLocker.ExitReadLock();
2019-12-18 22:33:23 +01:00
items.Add(item);
items.Add(new Separator());
PopulateStaticItems();
2019-12-18 22:33:23 +01:00
}
private void ChangeControlServiceItem_Click(object sender, System.Windows.RoutedEventArgs e)
{
changeServiceItem.IsEnabled = false;
RequestServiceChange?.Invoke(this, EventArgs.Empty);
}
private void OpenProgramFolderItem_Click(object sender, System.Windows.RoutedEventArgs e)
{
Process.Start(Global.exedirpath);
}
2019-12-18 22:33:23 +01:00
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)
2019-12-18 22:33:23 +01:00
{
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();
2019-12-18 22:33:23 +01:00
tempDev.DisconnectBT();
}
else if (tempDev.ConnectionType == ConnectionType.SONYWA)
{
tempDev.DisconnectDongle();
}
}
//controllerList[idx] = null;
}
private void PopulateControllerList()
{
//IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers();
int idx = 0;
_colLocker.EnterWriteLock();
2019-12-18 22:33:23 +01:00
foreach (DS4Device currentDev in controlService.slotManager.ControllerColl)
{
controllerList.Add(new ControllerHolder(currentDev, idx));
idx++;
}
_colLocker.ExitWriteLock();
2019-12-18 22:33:23 +01:00
}
private void StartPopulateText(object sender, EventArgs e)
{
PopulateToolText();
//PopulateContextMenu();
}
private void PopulateToolText()
{
List<string> items = new List<string>();
items.Add(trayTitle);
//IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers();
int idx = 1;
//foreach (DS4Device currentDev in devices)
_colLocker.EnterReadLock();
2019-12-18 22:33:23 +01:00
foreach (ControllerHolder holder in controllerList)
{
DS4Device currentDev = holder.Device;
items.Add($"{idx}: {currentDev.ConnectionType} {currentDev.Battery}%{(currentDev.Charging ? "+" : "")}");
idx++;
}
_colLocker.ExitReadLock();
2019-12-18 22:33:23 +01:00
TooltipText = string.Join("\n", items);
}
private void SetupEvents()
{
//IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers();
//foreach (DS4Device currentDev in devices)
_colLocker.EnterReadLock();
2019-12-18 22:33:23 +01:00
foreach (ControllerHolder holder in controllerList)
{
DS4Device currentDev = holder.Device;
SetupDeviceEvents(currentDev);
}
_colLocker.ExitReadLock();
2019-12-18 22:33:23 +01:00
}
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;
_colLocker.EnterWriteLock();
2019-12-18 22:33:23 +01:00
foreach (ControllerHolder holder in controllerList)
{
if (currentDev == holder.Device)
{
item = holder;
break;
}
idx++;
}
if (item != null)
{
controllerList.RemoveAt(idx);
RemoveDeviceEvents(currentDev);
}
_colLocker.ExitWriteLock();
PopulateToolText();
2019-12-18 22:33:23 +01:00
}
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();
}
private void PopulateStaticItems()
2019-12-18 22:33:23 +01:00
{
ItemCollection items = contextMenu.Items;
items.Add(changeServiceItem);
items.Add(openItem);
items.Add(minimizeItem);
items.Add(openProgramItem);
2019-12-18 22:33:23 +01:00
items.Add(new Separator());
items.Add(closeItem);
}
public void ClearContextMenu()
{
contextMenu.Items.Clear();
PopulateStaticItems();
2019-12-18 22:33:23 +01:00
}
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;
}
}
}