/ src / modules / EnvironmentVariables / EnvironmentVariablesUILib / EnvironmentVariablesMainPage.xaml.cs
EnvironmentVariablesMainPage.xaml.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.Linq;
  7  using System.Threading.Tasks;
  8  using System.Windows.Input;
  9  
 10  using CommunityToolkit.Mvvm.Input;
 11  using EnvironmentVariablesUILib.Models;
 12  using EnvironmentVariablesUILib.ViewModels;
 13  using Microsoft.UI.Xaml.Controls;
 14  
 15  namespace EnvironmentVariablesUILib
 16  {
 17      public sealed partial class EnvironmentVariablesMainPage : Page
 18      {
 19          private sealed class RelayCommandParameter
 20          {
 21              public RelayCommandParameter(Variable variable, VariablesSet set)
 22              {
 23                  Variable = variable;
 24                  this.Set = set;
 25              }
 26  
 27              public Variable Variable { get; set; }
 28  
 29              public VariablesSet Set { get; set; }
 30          }
 31  
 32          public MainViewModel ViewModel { get; private set; }
 33  
 34          public ICommand EditCommand => new RelayCommand<RelayCommandParameter>(EditVariable);
 35  
 36          public ICommand NewProfileCommand => new AsyncRelayCommand(AddProfileAsync);
 37  
 38          public ICommand AddProfileCommand => new RelayCommand(AddProfile);
 39  
 40          public ICommand UpdateProfileCommand => new RelayCommand(UpdateProfile);
 41  
 42          public ICommand AddVariableCommand => new RelayCommand(AddVariable);
 43  
 44          public ICommand CancelAddVariableCommand => new RelayCommand(CancelAddVariable);
 45  
 46          public ICommand AddDefaultVariableCommand => new RelayCommand<DefaultVariablesSet>(AddDefaultVariable);
 47  
 48          public EnvironmentVariablesMainPage(MainViewModel viewModel)
 49          {
 50              this.InitializeComponent();
 51              ViewModel = viewModel;
 52              DataContext = ViewModel;
 53  
 54              ViewModel.LoadEnvironmentVariables();
 55          }
 56  
 57          private async Task ShowEditDialogAsync(Variable variable, VariablesSet parentSet)
 58          {
 59              var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
 60  
 61              EditVariableDialog.Title = resourceLoader.GetString("EditVariableDialog_Title");
 62              EditVariableDialog.PrimaryButtonText = resourceLoader.GetString("SaveBtn");
 63              EditVariableDialog.SecondaryButtonText = resourceLoader.GetString("CancelBtn");
 64              EditVariableDialog.PrimaryButtonCommand = EditCommand;
 65              EditVariableDialog.PrimaryButtonCommandParameter = new RelayCommandParameter(variable, parentSet);
 66  
 67              var clone = variable.Clone();
 68              EditVariableDialog.DataContext = clone;
 69  
 70              await EditVariableDialog.ShowAsync();
 71          }
 72  
 73          private async void EditVariable_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
 74          {
 75              var btn = sender as MenuFlyoutItem;
 76              var variablesSet = btn.DataContext as VariablesSet;
 77              var variable = btn.CommandParameter as Variable;
 78  
 79              if (variable != null)
 80              {
 81                  await ShowEditDialogAsync(variable, variablesSet);
 82              }
 83          }
 84  
 85          private void EditVariable(RelayCommandParameter param)
 86          {
 87              var variableSet = param.Set as ProfileVariablesSet;
 88              var original = param.Variable;
 89              var edited = EditVariableDialog.DataContext as Variable;
 90              ViewModel.EditVariable(original, edited, variableSet);
 91          }
 92  
 93          private async Task AddProfileAsync()
 94          {
 95              SwitchViewsSegmentedView.SelectedIndex = 0;
 96  
 97              var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
 98              AddProfileDialog.Title = resourceLoader.GetString("AddNewProfileDialog_Title");
 99              AddProfileDialog.PrimaryButtonText = resourceLoader.GetString("AddBtn");
100              AddProfileDialog.SecondaryButtonText = resourceLoader.GetString("CancelBtn");
101              AddProfileDialog.PrimaryButtonCommand = AddProfileCommand;
102              AddProfileDialog.DataContext = new ProfileVariablesSet(Guid.NewGuid(), string.Empty);
103  
104              await AddProfileDialog.ShowAsync();
105          }
106  
107          private void AddProfile()
108          {
109              var profile = AddProfileDialog.DataContext as ProfileVariablesSet;
110              ViewModel.AddProfile(profile);
111          }
112  
113          private void UpdateProfile()
114          {
115              var updatedProfile = AddProfileDialog.DataContext as ProfileVariablesSet;
116              ViewModel.UpdateProfile(updatedProfile);
117          }
118  
119          private async void RemoveProfileBtn_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
120          {
121              var button = sender as MenuFlyoutItem;
122              var profile = button.CommandParameter as ProfileVariablesSet;
123  
124              if (profile != null)
125              {
126                  var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
127                  ContentDialog dialog = new ContentDialog();
128                  dialog.XamlRoot = RootPage.XamlRoot;
129                  dialog.Title = profile.Name;
130                  dialog.PrimaryButtonText = resourceLoader.GetString("Yes");
131                  dialog.CloseButtonText = resourceLoader.GetString("No");
132                  dialog.DefaultButton = ContentDialogButton.Primary;
133                  dialog.Content = new TextBlock() { Text = resourceLoader.GetString("Delete_Dialog_Description"), TextWrapping = Microsoft.UI.Xaml.TextWrapping.WrapWholeWords };
134                  dialog.PrimaryButtonClick += (s, args) =>
135                  {
136                      ViewModel.RemoveProfile(profile);
137                  };
138  
139                  var result = await dialog.ShowAsync();
140              }
141          }
142  
143          private void AddVariable()
144          {
145              var profile = AddProfileDialog.DataContext as ProfileVariablesSet;
146              if (profile != null)
147              {
148                  if (AddVariableSwitchPresenter.Value as string == "NewVariable")
149                  {
150                      profile.Variables.Add(new Variable(AddNewVariableName.Text, AddNewVariableValue.Text, VariablesSetType.Profile));
151                  }
152                  else
153                  {
154                      foreach (Variable variable in ExistingVariablesListView.SelectedItems)
155                      {
156                          if (!profile.Variables.Where(x => x.Name == variable.Name).Any())
157                          {
158                              var clone = variable.Clone(true);
159                              profile.Variables.Add(clone);
160                          }
161                      }
162                  }
163              }
164  
165              AddNewVariableName.Text = string.Empty;
166              AddNewVariableValue.Text = string.Empty;
167              ExistingVariablesListView.SelectionChanged -= ExistingVariablesListView_SelectionChanged;
168              ExistingVariablesListView.SelectedItems.Clear();
169              ExistingVariablesListView.SelectionChanged += ExistingVariablesListView_SelectionChanged;
170              AddVariableFlyout.Hide();
171          }
172  
173          private void CancelAddVariable()
174          {
175              AddNewVariableName.Text = string.Empty;
176              AddNewVariableValue.Text = string.Empty;
177  
178              ExistingVariablesListView.SelectionChanged -= ExistingVariablesListView_SelectionChanged;
179              ExistingVariablesListView.SelectedItems.Clear();
180              ExistingVariablesListView.SelectionChanged += ExistingVariablesListView_SelectionChanged;
181  
182              AddVariableFlyout.Hide();
183          }
184  
185          private void AddDefaultVariable(DefaultVariablesSet set)
186          {
187              var variable = AddDefaultVariableDialog.DataContext as Variable;
188              var type = set.Type;
189  
190              ViewModel.AddDefaultVariable(variable, type);
191          }
192  
193          private async void Delete_Variable_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
194          {
195              MenuFlyoutItem selectedItem = sender as MenuFlyoutItem;
196              var variableSet = selectedItem.DataContext as ProfileVariablesSet;
197              var variable = selectedItem.CommandParameter as Variable;
198  
199              if (variable != null)
200              {
201                  var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
202                  ContentDialog dialog = new ContentDialog();
203                  dialog.XamlRoot = RootPage.XamlRoot;
204                  dialog.Title = variable.Name;
205                  dialog.PrimaryButtonText = resourceLoader.GetString("Yes");
206                  dialog.CloseButtonText = resourceLoader.GetString("No");
207                  dialog.DefaultButton = ContentDialogButton.Primary;
208                  dialog.Content = new TextBlock() { Text = resourceLoader.GetString("Delete_Variable_Description"), TextWrapping = Microsoft.UI.Xaml.TextWrapping.WrapWholeWords };
209                  dialog.PrimaryButtonClick += (s, args) =>
210                  {
211                      ViewModel.DeleteVariable(variable, variableSet);
212                  };
213                  var result = await dialog.ShowAsync();
214              }
215          }
216  
217          private void AddNewVariableName_TextChanged(object sender, TextChangedEventArgs e)
218          {
219              TextBox nameTxtBox = sender as TextBox;
220              var profile = AddProfileDialog.DataContext as ProfileVariablesSet;
221  
222              if (nameTxtBox != null)
223              {
224                  if (nameTxtBox.Text.Length == 0 || nameTxtBox.Text.Length >= 255 || profile.Variables.Where(x => x.Name.Equals(nameTxtBox.Text, StringComparison.OrdinalIgnoreCase)).Any())
225                  {
226                      ConfirmAddVariableBtn.IsEnabled = false;
227                  }
228                  else
229                  {
230                      ConfirmAddVariableBtn.IsEnabled = true;
231                  }
232              }
233          }
234  
235          private void ReloadButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
236          {
237              ViewModel.LoadEnvironmentVariables();
238              ViewModel.EnvironmentState = EnvironmentState.Unchanged;
239          }
240  
241          private void ExistingVariablesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
242          {
243              var profile = AddProfileDialog.DataContext as ProfileVariablesSet;
244  
245              int toRemove = -1;
246  
247              if (e.AddedItems.Count > 0)
248              {
249                  var list = sender as ListView;
250                  var duplicates = list.SelectedItems.GroupBy(x => ((Variable)x).Name.ToLowerInvariant()).Where(g => g.Count() > 1).ToList();
251  
252                  foreach (var dup in duplicates)
253                  {
254                      ExistingVariablesListView.SelectionChanged -= ExistingVariablesListView_SelectionChanged;
255                      list.SelectedItems.Remove(dup.ElementAt(1));
256                      ExistingVariablesListView.SelectionChanged += ExistingVariablesListView_SelectionChanged;
257                  }
258              }
259  
260              if (e.RemovedItems.Count > 0)
261              {
262                  Variable removedVariable = e.RemovedItems[0] as Variable;
263                  for (int i = 0; i < profile.Variables.Count; i++)
264                  {
265                      if (profile.Variables[i].Name == removedVariable.Name && profile.Variables[i].Values == removedVariable.Values)
266                      {
267                          toRemove = i;
268                          break;
269                      }
270                  }
271  
272                  if (toRemove != -1)
273                  {
274                      profile.Variables.RemoveAt(toRemove);
275                  }
276              }
277  
278              ConfirmAddVariableBtn.IsEnabled = false;
279              foreach (Variable variable in ExistingVariablesListView.SelectedItems)
280              {
281                  if (variable != null)
282                  {
283                      if (!profile.Variables.Where(x => x.Name.Equals(variable.Name, StringComparison.Ordinal) && x.Values.Equals(variable.Values, StringComparison.Ordinal)).Any())
284                      {
285                          ConfirmAddVariableBtn.IsEnabled = true;
286                          break;
287                      }
288                  }
289              }
290          }
291  
292          private async void EditProfileBtn_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
293          {
294              SwitchViewsSegmentedView.SelectedIndex = 0;
295  
296              var button = sender as MenuFlyoutItem;
297              var profile = button.CommandParameter as ProfileVariablesSet;
298  
299              if (profile != null)
300              {
301                  var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
302                  AddProfileDialog.Title = resourceLoader.GetString("EditProfileDialog_Title");
303                  AddProfileDialog.PrimaryButtonText = resourceLoader.GetString("SaveBtn");
304                  AddProfileDialog.SecondaryButtonText = resourceLoader.GetString("CancelBtn");
305                  AddProfileDialog.PrimaryButtonCommand = UpdateProfileCommand;
306                  AddProfileDialog.DataContext = profile.Clone();
307                  await AddProfileDialog.ShowAsync();
308              }
309          }
310  
311          private void ExistingVariablesListView_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
312          {
313              var profile = AddProfileDialog.DataContext as ProfileVariablesSet;
314  
315              foreach (Variable item in ExistingVariablesListView.Items)
316              {
317                  if (item != null)
318                  {
319                      foreach (var profileItem in profile.Variables)
320                      {
321                          if (profileItem.Name == item.Name && profileItem.Values == item.Values)
322                          {
323                              if (ExistingVariablesListView.SelectedItems.Where(x => ((Variable)x).Name.Equals(profileItem.Name, StringComparison.OrdinalIgnoreCase)).Any())
324                              {
325                                  continue;
326                              }
327  
328                              ExistingVariablesListView.SelectionChanged -= ExistingVariablesListView_SelectionChanged;
329                              ExistingVariablesListView.SelectedItems.Add(item);
330                              ExistingVariablesListView.SelectionChanged += ExistingVariablesListView_SelectionChanged;
331                          }
332                      }
333                  }
334              }
335          }
336  
337          private async Task ShowAddDefaultVariableDialogAsync(DefaultVariablesSet set)
338          {
339              var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
340  
341              AddDefaultVariableDialog.Title = resourceLoader.GetString("AddVariable_Title");
342              AddDefaultVariableDialog.PrimaryButtonText = resourceLoader.GetString("SaveBtn");
343              AddDefaultVariableDialog.SecondaryButtonText = resourceLoader.GetString("CancelBtn");
344              AddDefaultVariableDialog.PrimaryButtonCommand = AddDefaultVariableCommand;
345              AddDefaultVariableDialog.PrimaryButtonCommandParameter = set;
346  
347              var variableType = set.Id == VariablesSet.SystemGuid ? VariablesSetType.System : VariablesSetType.User;
348              AddDefaultVariableDialog.DataContext = new Variable(string.Empty, string.Empty, variableType);
349  
350              await AddDefaultVariableDialog.ShowAsync();
351          }
352  
353          private async void AddDefaultVariableBtn_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
354          {
355              var button = sender as Button;
356              var defaultVariableSet = button.CommandParameter as DefaultVariablesSet;
357  
358              if (defaultVariableSet != null)
359              {
360                  await ShowAddDefaultVariableDialogAsync(defaultVariableSet);
361              }
362          }
363  
364          private void EditVariableDialogNameTxtBox_TextChanged(object sender, TextChangedEventArgs e)
365          {
366              var variable = EditVariableDialog.DataContext as Variable;
367              var param = EditVariableDialog.PrimaryButtonCommandParameter as RelayCommandParameter;
368              var variableSet = param.Set;
369  
370              if (variableSet == null)
371              {
372                  // default set
373                  variableSet = variable.ParentType == VariablesSetType.User ? ViewModel.UserDefaultSet : ViewModel.SystemDefaultSet;
374              }
375  
376              if (variableSet != null)
377              {
378                  if (variableSet.Variables.Where(x => x.Name.Equals(EditVariableDialogNameTxtBox.Text, StringComparison.OrdinalIgnoreCase)).Any() || !variable.Valid)
379                  {
380                      EditVariableDialog.IsPrimaryButtonEnabled = false;
381                  }
382                  else
383                  {
384                      EditVariableDialog.IsPrimaryButtonEnabled = true;
385                  }
386              }
387  
388              if (!variable.Validate())
389              {
390                  EditVariableDialog.IsPrimaryButtonEnabled = false;
391              }
392          }
393  
394          private void AddDefaultVariableNameTxtBox_TextChanged(object sender, TextChangedEventArgs e)
395          {
396              TextBox nameTxtBox = sender as TextBox;
397              var variable = AddDefaultVariableDialog.DataContext as Variable;
398              var defaultSet = variable.ParentType == VariablesSetType.User ? ViewModel.UserDefaultSet : ViewModel.SystemDefaultSet;
399  
400              if (nameTxtBox != null)
401              {
402                  if (nameTxtBox.Text.Length == 0 || defaultSet.Variables.Where(x => x.Name.Equals(nameTxtBox.Text, StringComparison.OrdinalIgnoreCase)).Any())
403                  {
404                      AddDefaultVariableDialog.IsPrimaryButtonEnabled = false;
405                  }
406                  else
407                  {
408                      AddDefaultVariableDialog.IsPrimaryButtonEnabled = true;
409                  }
410              }
411  
412              if (!variable.Validate())
413              {
414                  AddDefaultVariableDialog.IsPrimaryButtonEnabled = false;
415              }
416          }
417  
418          private void EditVariableDialogValueTxtBox_TextChanged(object sender, TextChangedEventArgs e)
419          {
420              var txtBox = sender as TextBox;
421              var variable = EditVariableDialog.DataContext as Variable;
422              EditVariableDialog.IsPrimaryButtonEnabled = true;
423  
424              variable.ValuesList = Variable.ValuesStringToValuesListItemCollection(txtBox.Text);
425          }
426  
427          private void ReorderButtonUp_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
428          {
429              var listItem = ((MenuFlyoutItem)sender).DataContext as Variable.ValuesListItem;
430              if (listItem == null)
431              {
432                  return;
433              }
434  
435              var variable = EditVariableDialog.DataContext as Variable;
436  
437              var index = variable.ValuesList.IndexOf(listItem);
438              if (index > 0)
439              {
440                  variable.ValuesList.Move(index, index - 1);
441              }
442  
443              var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
444              EditVariableDialogValueTxtBox.Text = newValues;
445          }
446  
447          private void ReorderButtonDown_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
448          {
449              var listItem = ((MenuFlyoutItem)sender).DataContext as Variable.ValuesListItem;
450              if (listItem == null)
451              {
452                  return;
453              }
454  
455              var variable = EditVariableDialog.DataContext as Variable;
456              var btn = EditVariableDialog.PrimaryButtonCommandParameter as Button;
457  
458              var index = variable.ValuesList.IndexOf(listItem);
459              if (index < variable.ValuesList.Count - 1)
460              {
461                  variable.ValuesList.Move(index, index + 1);
462              }
463  
464              var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
465              EditVariableDialogValueTxtBox.Text = newValues;
466          }
467  
468          private void RemoveListVariableButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
469          {
470              var listItem = ((MenuFlyoutItem)sender).DataContext as Variable.ValuesListItem;
471              if (listItem == null)
472              {
473                  return;
474              }
475  
476              var variable = EditVariableDialog.DataContext as Variable;
477              variable.ValuesList.Remove(listItem);
478  
479              var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
480              EditVariableDialogValueTxtBox.Text = newValues;
481          }
482  
483          private void InsertListEntryBeforeButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
484          {
485              var listItem = (sender as MenuFlyoutItem)?.DataContext as Variable.ValuesListItem;
486              if (listItem == null)
487              {
488                  return;
489              }
490  
491              var variable = EditVariableDialog.DataContext as Variable;
492              var index = variable.ValuesList.IndexOf(listItem);
493              variable.ValuesList.Insert(index, new Variable.ValuesListItem { Text = string.Empty });
494  
495              var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
496              EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
497              EditVariableDialogValueTxtBox.Text = newValues;
498              EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
499          }
500  
501          private void InsertListEntryAfterButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
502          {
503              var listItem = (sender as MenuFlyoutItem)?.DataContext as Variable.ValuesListItem;
504              if (listItem == null)
505              {
506                  return;
507              }
508  
509              var variable = EditVariableDialog.DataContext as Variable;
510              var index = variable.ValuesList.IndexOf(listItem);
511              variable.ValuesList.Insert(index + 1, new Variable.ValuesListItem { Text = string.Empty });
512  
513              var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
514              EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
515              EditVariableDialogValueTxtBox.Text = newValues;
516              EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
517          }
518  
519          private void EditVariableValuesListTextBox_LostFocus(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
520          {
521              var listItem = (sender as TextBox)?.DataContext as Variable.ValuesListItem;
522              if (listItem == null)
523              {
524                  return;
525              }
526  
527              if (listItem.Text == (sender as TextBox)?.Text)
528              {
529                  return;
530              }
531  
532              listItem.Text = (sender as TextBox)?.Text;
533              var variable = EditVariableDialog.DataContext as Variable;
534  
535              var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
536              EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
537              EditVariableDialogValueTxtBox.Text = newValues;
538              EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
539          }
540  
541          private void InvalidStateInfoBar_CloseButtonClick(InfoBar sender, object args)
542          {
543              ViewModel.EnvironmentState = EnvironmentState.Unchanged;
544          }
545  
546          private void AddVariableFlyout_Closed(object sender, object e)
547          {
548              CancelAddVariable();
549              ConfirmAddVariableBtn.IsEnabled = false;
550          }
551      }
552  }