PluginAdditionalOptionViewModel.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.Collections.Generic; 6 using System.ComponentModel; 7 using System.Globalization; 8 using System.Runtime.CompilerServices; 9 10 using Microsoft.PowerToys.Settings.UI.Library; 11 12 namespace Microsoft.PowerToys.Settings.UI.ViewModels 13 { 14 public partial class PluginAdditionalOptionViewModel : INotifyPropertyChanged 15 { 16 private PluginAdditionalOption _additionalOption; 17 18 internal PluginAdditionalOptionViewModel(PluginAdditionalOption additionalOption) 19 { 20 _additionalOption = additionalOption; 21 } 22 23 // Labels of single and first setting of combined types 24 public string DisplayLabel => _additionalOption.DisplayLabel; 25 26 public string DisplayDescription => _additionalOption.DisplayDescription; 27 28 // Labels of second setting of combined types 29 public string SecondDisplayLabel => _additionalOption.SecondDisplayLabel; 30 31 public string SecondDisplayDescription => _additionalOption.SecondDisplayDescription; 32 33 public PluginAdditionalOption.AdditionalOptionType Type => _additionalOption.PluginOptionType; 34 35 // Bool checkbox setting 36 public bool ShowCheckBox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.Checkbox; 37 38 public bool Value 39 { 40 get => _additionalOption.Value; 41 set 42 { 43 if (value != _additionalOption.Value) 44 { 45 _additionalOption.Value = value; 46 NotifyPropertyChanged(); 47 NotifyPropertyChanged(nameof(SecondSettingIsEnabled)); 48 } 49 } 50 } 51 52 // ComboBox setting 53 public bool ShowComboBox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.Combobox && 54 _additionalOption.ComboBoxItems != null && _additionalOption.ComboBoxItems.Count > 0; 55 56 public List<KeyValuePair<string, string>> ComboBoxItems => _additionalOption.ComboBoxItems; 57 58 public string ComboBoxValue 59 { 60 get => _additionalOption.ComboBoxValue.ToString(CultureInfo.InvariantCulture); 61 set 62 { 63 if (int.Parse(value, CultureInfo.InvariantCulture) != _additionalOption.ComboBoxValue) 64 { 65 _additionalOption.ComboBoxValue = int.Parse(value, CultureInfo.InvariantCulture); 66 NotifyPropertyChanged(); 67 } 68 } 69 } 70 71 // TextBox and MultilineTextBox setting 72 public bool ShowTextBox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.Textbox; 73 74 public bool ShowMultilineTextBox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.MultilineTextbox; 75 76 public int TextBoxMaxLength => (_additionalOption.TextBoxMaxLength == null) ? 0 : _additionalOption.TextBoxMaxLength.Value; // 0 is the default and means no limit. 77 78 public string PlaceholderText => _additionalOption.PlaceholderText; 79 80 public string TextValue 81 { 82 get => _additionalOption.TextValue; 83 set 84 { 85 if (value != _additionalOption.TextValue) 86 { 87 _additionalOption.TextValue = value; 88 NotifyPropertyChanged(); 89 } 90 } 91 } 92 93 // NumberBox setting 94 public bool ShowNumberBox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.Numberbox; 95 96 public double NumberBoxMin => (_additionalOption.NumberBoxMin == null) ? double.MinValue : _additionalOption.NumberBoxMin.Value; 97 98 public double NumberBoxMax => (_additionalOption.NumberBoxMax == null) ? double.MaxValue : _additionalOption.NumberBoxMax.Value; 99 100 public double NumberBoxSmallChange => (_additionalOption.NumberBoxSmallChange == null) ? 1 : _additionalOption.NumberBoxSmallChange.Value; 101 102 public double NumberBoxLargeChange => (_additionalOption.NumberBoxLargeChange == null) ? 10 : _additionalOption.NumberBoxLargeChange.Value; 103 104 public double NumberValue 105 { 106 get => _additionalOption.NumberValue; 107 set 108 { 109 if (double.IsNaN(value)) 110 { 111 // If the user clears the NumberBox and presses enter or moves focus away then `value` converted to double results in `double.NaN`. This crashes the settings app. (https://github.com/microsoft/PowerToys/issues/32738#issuecomment-2105983967) 112 // To prevent the crash and provide a nice user experience we reset the NumberBox to the last valid value. This happens by sending a `NotifyPropertyChanged()` command and let the NumberBox reload its value. 113 // (Yes we could use 0, but this needs additional code for checking 0 against min and max. 114 // And yes we could also use the min value of the NumberBox, but this is not user friendly as the minimum value of NumberBox can be `double.MinValue`.) 115 NotifyPropertyChanged(); 116 } 117 else if (value != _additionalOption.NumberValue) 118 { 119 _additionalOption.NumberValue = value; 120 NotifyPropertyChanged(); 121 } 122 } 123 } 124 125 // Show combined settings cards 126 public bool ShowCheckboxAndCombobox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.CheckboxAndCombobox; 127 128 public bool ShowCheckboxAndTextbox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.CheckboxAndTextbox; 129 130 public bool ShowCheckboxAndNumberbox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.CheckboxAndNumberbox; 131 132 public bool ShowCheckboxAndMultilineTextbox => _additionalOption.PluginOptionType == PluginAdditionalOption.AdditionalOptionType.CheckboxAndMultilineTextbox; 133 134 // Enabled state of ComboBox, TextBox, NumberBox (If combined with checkbox then checkbox value decides it.) 135 public bool SecondSettingIsEnabled => (int)_additionalOption.PluginOptionType > 10 ? _additionalOption.Value : true; 136 137 // Handle property changes 138 public event PropertyChangedEventHandler PropertyChanged; 139 140 private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") 141 { 142 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 143 } 144 } 145 }