Add port config, quick-switch toolbar, and dark mode styling
- Add Config button to each monitor for hiding ports, custom labels, and quick-switch selection - Add quick-switch toolbar at top of popup for one-click input switching - Add dark mode styling for all controls (buttons, combobox, dropdown items) - Add loading spinner animation - Add Exit button in header - Fix dropdown selection to correctly show current input 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
125
Library/Config/MonitorConfigManager.cs
Normal file
125
Library/Config/MonitorConfigManager.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using CMM.Library.Helpers;
|
||||
using CMM.Library.ViewModel;
|
||||
using System.IO;
|
||||
|
||||
namespace CMM.Library.Config;
|
||||
|
||||
public static class MonitorConfigManager
|
||||
{
|
||||
private static readonly string ConfigFolder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
"MonitorControl");
|
||||
|
||||
private static readonly string ConfigFile = Path.Combine(ConfigFolder, "config.json");
|
||||
|
||||
private static AppConfig? _cachedConfig;
|
||||
|
||||
public static AppConfig Load()
|
||||
{
|
||||
if (_cachedConfig != null)
|
||||
return _cachedConfig;
|
||||
|
||||
if (!File.Exists(ConfigFile))
|
||||
{
|
||||
_cachedConfig = new AppConfig();
|
||||
return _cachedConfig;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_cachedConfig = ConfigFile.JsonFormFile<AppConfig>() ?? new AppConfig();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_cachedConfig = new AppConfig();
|
||||
}
|
||||
|
||||
return _cachedConfig;
|
||||
}
|
||||
|
||||
public static void Save(AppConfig config)
|
||||
{
|
||||
_cachedConfig = config;
|
||||
config.FileToJson(ConfigFile);
|
||||
}
|
||||
|
||||
public static MonitorConfig GetMonitorConfig(string serialNumber)
|
||||
{
|
||||
var config = Load();
|
||||
return config.Monitors.FirstOrDefault(m => m.SerialNumber == serialNumber)
|
||||
?? new MonitorConfig { SerialNumber = serialNumber };
|
||||
}
|
||||
|
||||
public static void SaveMonitorConfig(MonitorConfig monitorConfig)
|
||||
{
|
||||
var config = Load();
|
||||
var existing = config.Monitors.FirstOrDefault(m => m.SerialNumber == monitorConfig.SerialNumber);
|
||||
|
||||
if (existing != null)
|
||||
config.Monitors.Remove(existing);
|
||||
|
||||
config.Monitors.Add(monitorConfig);
|
||||
Save(config);
|
||||
}
|
||||
|
||||
public static List<QuickSwitchItem> GetQuickSwitchItems()
|
||||
{
|
||||
var config = Load();
|
||||
var items = new List<QuickSwitchItem>();
|
||||
|
||||
foreach (var monitor in config.Monitors)
|
||||
{
|
||||
foreach (var port in monitor.Ports.Where(p => p.ShowInQuickSwitch && !p.IsHidden))
|
||||
{
|
||||
items.Add(new QuickSwitchItem
|
||||
{
|
||||
MonitorSerialNumber = monitor.SerialNumber,
|
||||
MonitorName = monitor.MonitorName,
|
||||
PortVcpValue = port.VcpValue,
|
||||
PortLabel = port.DisplayName
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public static List<InputSourceOption> ApplyConfigToOptions(
|
||||
string serialNumber,
|
||||
List<InputSourceOption> options)
|
||||
{
|
||||
var monitorConfig = GetMonitorConfig(serialNumber);
|
||||
|
||||
if (monitorConfig.Ports.Count == 0)
|
||||
return options;
|
||||
|
||||
var result = new List<InputSourceOption>();
|
||||
|
||||
foreach (var option in options)
|
||||
{
|
||||
var portConfig = monitorConfig.Ports.FirstOrDefault(p => p.VcpValue == option.Value);
|
||||
|
||||
if (portConfig != null)
|
||||
{
|
||||
// Respect hidden setting - don't show hidden ports
|
||||
if (portConfig.IsHidden)
|
||||
continue;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(portConfig.CustomLabel))
|
||||
{
|
||||
result.Add(new InputSourceOption(option.Value, portConfig.CustomLabel));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.Add(option);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void ClearCache()
|
||||
{
|
||||
_cachedConfig = null;
|
||||
}
|
||||
}
|
||||
44
Library/ViewModel/MonitorConfig.cs
Normal file
44
Library/ViewModel/MonitorConfig.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace CMM.Library.ViewModel;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for a single monitor's ports
|
||||
/// </summary>
|
||||
public class MonitorConfig
|
||||
{
|
||||
public string SerialNumber { get; set; } = string.Empty;
|
||||
public string MonitorName { get; set; } = string.Empty;
|
||||
public List<PortConfig> Ports { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for a single input port
|
||||
/// </summary>
|
||||
public class PortConfig
|
||||
{
|
||||
public int VcpValue { get; set; }
|
||||
public string DefaultName { get; set; } = string.Empty;
|
||||
public string CustomLabel { get; set; } = string.Empty;
|
||||
public bool IsHidden { get; set; }
|
||||
public bool ShowInQuickSwitch { get; set; }
|
||||
|
||||
public string DisplayName => string.IsNullOrWhiteSpace(CustomLabel) ? DefaultName : CustomLabel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quick switch item shown in toolbar
|
||||
/// </summary>
|
||||
public class QuickSwitchItem
|
||||
{
|
||||
public string MonitorSerialNumber { get; set; } = string.Empty;
|
||||
public string MonitorName { get; set; } = string.Empty;
|
||||
public int PortVcpValue { get; set; }
|
||||
public string PortLabel { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Root configuration object
|
||||
/// </summary>
|
||||
public class AppConfig
|
||||
{
|
||||
public List<MonitorConfig> Monitors { get; set; } = new();
|
||||
}
|
||||
Reference in New Issue
Block a user