/ src / settings-ui / Settings.UI / ViewModels / PluginAdditionalOptionViewModel.cs
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  }