ProfileEditorViewModel.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 #nullable enable 6 7 using System.Collections.ObjectModel; 8 using System.ComponentModel; 9 using System.Linq; 10 using System.Runtime.CompilerServices; 11 using Microsoft.PowerToys.Settings.UI.Library; 12 using PowerDisplay.Common.Models; 13 14 namespace Microsoft.PowerToys.Settings.UI.ViewModels 15 { 16 /// <summary> 17 /// ViewModel for Profile Editor Dialog 18 /// </summary> 19 public class ProfileEditorViewModel : INotifyPropertyChanged 20 { 21 private string _profileName = string.Empty; 22 private ObservableCollection<MonitorSelectionItem> _monitors; 23 24 public ProfileEditorViewModel(ObservableCollection<MonitorInfo> availableMonitors, string defaultName = "") 25 { 26 _profileName = defaultName; 27 _monitors = new ObservableCollection<MonitorSelectionItem>(); 28 29 // Set TotalMonitorCount for DisplayName to show monitor numbers when multiple monitors exist 30 int totalCount = availableMonitors.Count; 31 foreach (var monitor in availableMonitors) 32 { 33 monitor.TotalMonitorCount = totalCount; 34 } 35 36 // Initialize monitor selection items 37 foreach (var monitor in availableMonitors) 38 { 39 var item = new MonitorSelectionItem 40 { 41 SuppressAutoSelection = true, 42 Monitor = monitor, 43 IsSelected = false, 44 Brightness = monitor.CurrentBrightness, 45 Contrast = 50, // Default value (MonitorInfo doesn't store contrast) 46 Volume = 50, // Default value (MonitorInfo doesn't store volume) 47 ColorTemperature = monitor.ColorTemperatureVcp, 48 }; 49 50 item.SuppressAutoSelection = false; 51 52 // Subscribe to selection and checkbox changes 53 item.PropertyChanged += OnMonitorItemPropertyChanged; 54 55 _monitors.Add(item); 56 } 57 } 58 59 public string ProfileName 60 { 61 get => _profileName; 62 set 63 { 64 if (_profileName != value) 65 { 66 _profileName = value; 67 OnPropertyChanged(); 68 OnPropertyChanged(nameof(CanSave)); 69 } 70 } 71 } 72 73 public ObservableCollection<MonitorSelectionItem> Monitors 74 { 75 get => _monitors; 76 set 77 { 78 if (_monitors != value) 79 { 80 _monitors = value; 81 OnPropertyChanged(); 82 } 83 } 84 } 85 86 public bool HasSelectedMonitors => _monitors?.Any(m => m.IsSelected) ?? false; 87 88 public bool HasValidSettings => _monitors != null && 89 _monitors.Any(m => m.IsSelected) && 90 _monitors.Where(m => m.IsSelected).All(m => m.IncludeBrightness || m.IncludeContrast || m.IncludeVolume || m.IncludeColorTemperature); 91 92 public bool CanSave => !string.IsNullOrWhiteSpace(_profileName) && HasSelectedMonitors && HasValidSettings; 93 94 public PowerDisplayProfile CreateProfile() 95 { 96 var settings = _monitors 97 .Where(m => m.IsSelected) 98 .Select(m => new ProfileMonitorSetting( 99 m.Monitor.Id, // Monitor Id (unique identifier) 100 m.IncludeBrightness ? (int?)m.Brightness : null, 101 m.IncludeColorTemperature && m.SupportsColorTemperature ? (int?)m.ColorTemperature : null, 102 m.IncludeContrast && m.SupportsContrast ? (int?)m.Contrast : null, 103 m.IncludeVolume && m.SupportsVolume ? (int?)m.Volume : null)) 104 .ToList(); 105 106 return new PowerDisplayProfile(_profileName, settings); 107 } 108 109 public event PropertyChangedEventHandler? PropertyChanged; 110 111 protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) 112 { 113 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 114 } 115 116 /// <summary> 117 /// Handle property changes from monitor selection items. 118 /// Centralizes validation state updates to avoid duplication. 119 /// </summary> 120 private void OnMonitorItemPropertyChanged(object? sender, PropertyChangedEventArgs e) 121 { 122 // Update selection-dependent properties 123 if (e.PropertyName == nameof(MonitorSelectionItem.IsSelected)) 124 { 125 OnPropertyChanged(nameof(HasSelectedMonitors)); 126 } 127 128 // Update validation state for relevant property changes 129 if (e.PropertyName == nameof(MonitorSelectionItem.IsSelected) || 130 e.PropertyName == nameof(MonitorSelectionItem.IncludeBrightness) || 131 e.PropertyName == nameof(MonitorSelectionItem.IncludeContrast) || 132 e.PropertyName == nameof(MonitorSelectionItem.IncludeVolume) || 133 e.PropertyName == nameof(MonitorSelectionItem.IncludeColorTemperature)) 134 { 135 OnPropertyChanged(nameof(CanSave)); 136 OnPropertyChanged(nameof(HasValidSettings)); 137 } 138 } 139 } 140 }