MeasureToolViewModel.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 using System; 6 using System.Collections.Generic; 7 using System.Globalization; 8 using System.Runtime.CompilerServices; 9 using System.Text.Json; 10 using global::PowerToys.GPOWrapper; 11 using Microsoft.PowerToys.Settings.UI.Helpers; 12 using Microsoft.PowerToys.Settings.UI.Library; 13 using Microsoft.PowerToys.Settings.UI.Library.Helpers; 14 using Microsoft.PowerToys.Settings.UI.Library.Interfaces; 15 using Microsoft.PowerToys.Settings.UI.SerializationContext; 16 17 namespace Microsoft.PowerToys.Settings.UI.ViewModels 18 { 19 public partial class MeasureToolViewModel : PageViewModelBase 20 { 21 protected override string ModuleName => MeasureToolSettings.ModuleName; 22 23 private SettingsUtils SettingsUtils { get; set; } 24 25 private GeneralSettings GeneralSettingsConfig { get; set; } 26 27 private GpoRuleConfigured _enabledGpoRuleConfiguration; 28 private bool _enabledStateIsGPOConfigured; 29 private bool _isEnabled; 30 31 private MeasureToolSettings Settings { get; set; } 32 33 public MeasureToolViewModel(SettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<MeasureToolSettings> measureToolSettingsRepository, Func<string, int> ipcMSGCallBackFunc) 34 { 35 SettingsUtils = settingsUtils; 36 37 ArgumentNullException.ThrowIfNull(settingsRepository); 38 39 GeneralSettingsConfig = settingsRepository.SettingsConfig; 40 41 InitializeEnabledValue(); 42 43 ArgumentNullException.ThrowIfNull(measureToolSettingsRepository); 44 45 Settings = measureToolSettingsRepository.SettingsConfig; 46 47 SendConfigMSG = ipcMSGCallBackFunc; 48 } 49 50 private void InitializeEnabledValue() 51 { 52 _enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredScreenRulerEnabledValue(); 53 if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled) 54 { 55 // Get the enabled state from GPO. 56 _enabledStateIsGPOConfigured = true; 57 _isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled; 58 } 59 else 60 { 61 _isEnabled = GeneralSettingsConfig.Enabled.MeasureTool; 62 } 63 } 64 65 public override Dictionary<string, HotkeySettings[]> GetAllHotkeySettings() 66 { 67 var hotkeysDict = new Dictionary<string, HotkeySettings[]> 68 { 69 [ModuleName] = [ActivationShortcut], 70 }; 71 72 return hotkeysDict; 73 } 74 75 public bool IsEnabled 76 { 77 get => _isEnabled; 78 set 79 { 80 if (_enabledStateIsGPOConfigured) 81 { 82 // If it's GPO configured, shouldn't be able to change this state. 83 return; 84 } 85 86 if (_isEnabled != value) 87 { 88 _isEnabled = value; 89 GeneralSettingsConfig.Enabled.MeasureTool = value; 90 OnPropertyChanged(nameof(IsEnabled)); 91 92 OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig); 93 SendConfigMSG(outgoing.ToString()); 94 95 NotifyPropertyChanged(); 96 NotifyPropertyChanged(nameof(ShowContinuousCaptureWarning)); 97 } 98 } 99 } 100 101 public bool IsEnabledGpoConfigured 102 { 103 get => _enabledStateIsGPOConfigured; 104 } 105 106 public bool ContinuousCapture 107 { 108 get 109 { 110 return Settings.Properties.ContinuousCapture; 111 } 112 113 set 114 { 115 if (Settings.Properties.ContinuousCapture != value) 116 { 117 Settings.Properties.ContinuousCapture = value; 118 NotifyPropertyChanged(); 119 NotifyPropertyChanged(nameof(ShowContinuousCaptureWarning)); 120 } 121 } 122 } 123 124 public bool DrawFeetOnCross 125 { 126 get 127 { 128 return Settings.Properties.DrawFeetOnCross; 129 } 130 131 set 132 { 133 if (Settings.Properties.DrawFeetOnCross != value) 134 { 135 Settings.Properties.DrawFeetOnCross = value; 136 NotifyPropertyChanged(); 137 } 138 } 139 } 140 141 public string CrossColor 142 { 143 get 144 { 145 return Settings.Properties.MeasureCrossColor.Value; 146 } 147 148 set 149 { 150 value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FF4500"; 151 if (!value.Equals(Settings.Properties.MeasureCrossColor.Value, StringComparison.OrdinalIgnoreCase)) 152 { 153 Settings.Properties.MeasureCrossColor.Value = value; 154 NotifyPropertyChanged(); 155 } 156 } 157 } 158 159 public bool PerColorChannelEdgeDetection 160 { 161 get 162 { 163 return Settings.Properties.PerColorChannelEdgeDetection; 164 } 165 166 set 167 { 168 if (Settings.Properties.PerColorChannelEdgeDetection != value) 169 { 170 Settings.Properties.PerColorChannelEdgeDetection = value; 171 NotifyPropertyChanged(); 172 } 173 } 174 } 175 176 public int UnitsOfMeasure 177 { 178 get 179 { 180 return Settings.Properties.UnitsOfMeasure.Value; 181 } 182 183 set 184 { 185 if (Settings.Properties.UnitsOfMeasure.Value != value) 186 { 187 Settings.Properties.UnitsOfMeasure.Value = value; 188 NotifyPropertyChanged(); 189 } 190 } 191 } 192 193 public int PixelTolerance 194 { 195 get 196 { 197 return Settings.Properties.PixelTolerance.Value; 198 } 199 200 set 201 { 202 if (Settings.Properties.PixelTolerance.Value != value) 203 { 204 Settings.Properties.PixelTolerance.Value = value; 205 NotifyPropertyChanged(); 206 } 207 } 208 } 209 210 public HotkeySettings ActivationShortcut 211 { 212 get 213 { 214 return Settings.Properties.ActivationShortcut; 215 } 216 217 set 218 { 219 if (Settings.Properties.ActivationShortcut != value) 220 { 221 Settings.Properties.ActivationShortcut = value ?? Settings.Properties.DefaultActivationShortcut; 222 223 NotifyPropertyChanged(); 224 225 SendConfigMSG( 226 string.Format( 227 CultureInfo.InvariantCulture, 228 "{{ \"powertoys\": {{ \"{0}\": {1} }} }}", 229 MeasureToolSettings.ModuleName, 230 JsonSerializer.Serialize(Settings, SourceGenerationContextContext.Default.MeasureToolSettings))); 231 } 232 } 233 } 234 235 public int DefaultMeasureStyle 236 { 237 get 238 { 239 return Settings.Properties.DefaultMeasureStyle.Value; 240 } 241 242 set 243 { 244 if (Settings.Properties.DefaultMeasureStyle.Value != value) 245 { 246 Settings.Properties.DefaultMeasureStyle.Value = value; 247 NotifyPropertyChanged(); 248 } 249 } 250 } 251 252 public void NotifyPropertyChanged([CallerMemberName] string propertyName = null) 253 { 254 OnPropertyChanged(propertyName); 255 if (propertyName == nameof(ShowContinuousCaptureWarning)) 256 { 257 // Don't trigger a settings update if the changed property is for visual notification. 258 return; 259 } 260 261 SettingsUtils.SaveSettings(Settings.ToJsonString(), MeasureToolSettings.ModuleName); 262 } 263 264 public void RefreshEnabledState() 265 { 266 InitializeEnabledValue(); 267 OnPropertyChanged(nameof(IsEnabled)); 268 OnPropertyChanged(nameof(ShowContinuousCaptureWarning)); 269 } 270 271 public bool ShowContinuousCaptureWarning 272 { 273 get => IsEnabled && ContinuousCapture; 274 } 275 276 private Func<string, int> SendConfigMSG { get; } 277 } 278 }