//----------------------------------------------------------------------- // // Copyright © Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------- namespace Microsoft.PowerShell.Commands.ShowCommandInternal { using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Management.Automation; using System.Windows; using Microsoft.Management.UI.Internal; using Microsoft.PowerShell.Commands.ShowCommandExtension; /// /// Contains all Commands, Parameters, ParameterSet and Common Parameter. /// public class AllModulesViewModel : INotifyPropertyChanged { #region Private Fields /// /// Flag indicating a wait message is being displayed /// private bool waitMessageDisplayed; /// /// True if this ViewModel is not supposed to show common parameters /// private bool noCommonParameter; /// /// the filterName of command /// private string commandNameFilter; /// /// Field used for the Modules property. /// private List modules; /// /// true if a command can be run /// private bool canRun; /// /// true if a command can be copied /// private bool canCopy; /// /// the selected module being displayed in the GUI /// private ModuleViewModel selectedModule; /// /// the visibility of the refresh button /// private Visibility refreshVisibility = Visibility.Collapsed; /// /// Provides an extra viewModel object that allows callers to control certain aspects of the GUI /// private object extraViewModel; /// /// private property for ZoomLevel /// private double zoomLevel = 1.0; #endregion #region Construction and Destructor /// /// Initializes a new instance of the AllModulesViewModel class /// /// the loaded modules /// commands to show public AllModulesViewModel(Dictionary importedModules, IEnumerable commands) { if (commands == null || !commands.GetEnumerator().MoveNext()) { throw new ArgumentNullException("commands"); } this.Initialization(importedModules, commands, true); } /// /// Initializes a new instance of the AllModulesViewModel class /// /// the loaded modules /// All PowerShell commands /// true not to show common parameters public AllModulesViewModel(Dictionary importedModules, IEnumerable commands, bool noCommonParameter) { if (commands == null) { throw new ArgumentNullException("commands"); } this.Initialization(importedModules, commands, noCommonParameter); } #endregion #region INotifyPropertyChanged Members /// /// PropertyChanged Event /// public event PropertyChangedEventHandler PropertyChanged; #endregion /// /// Indicates the selected command in the selected module needs to display the help for a command /// public event EventHandler SelectedCommandInSelectedModuleNeedsHelp; /// /// Indicates the selected command in the selected module needs to import a module for a command /// public event EventHandler SelectedCommandInSelectedModuleNeedsImportModule; /// /// Indicates the selected command in the selected module should be run /// public event EventHandler RunSelectedCommandInSelectedModule; /// /// Indicates we want to refresh the viewModel /// public event EventHandler Refresh; #region Public Properties /// /// Get or Sets Zoom level /// public double ZoomLevel { get { return this.zoomLevel; } set { if (value > 0) { this.zoomLevel = value / 100.0; this.OnNotifyPropertyChanged("ZoomLevel"); } } } /// /// Gets the tooltip for the refresh button /// public static string RefreshTooltip { get { return String.Format(CultureInfo.CurrentUICulture, ShowCommandResources.RefreshShowCommandTooltipFormat, "import-module"); } } /// /// Gets or sets the visibility of the refresh button /// public Visibility RefreshVisibility { get { return this.refreshVisibility; } set { if (this.refreshVisibility == value) { return; } this.refreshVisibility = value; this.OnNotifyPropertyChanged("RefreshVisibility"); } } /// /// Gets a value indicating whether common parameters are displayed /// public bool NoCommonParameter { get { return this.noCommonParameter; } } /// /// Gets or sets the filterName of command /// public string CommandNameFilter { get { return this.commandNameFilter; } set { if (this.CommandNameFilter == value) { return; } this.commandNameFilter = value; if (this.selectedModule != null) { this.selectedModule.RefreshFilteredCommands(this.CommandNameFilter); this.selectedModule.SelectedCommand = null; } this.OnNotifyPropertyChanged("CommandNameFilter"); } } /// /// Gets or sets the selected module being displayed in the GUI /// public ModuleViewModel SelectedModule { get { return this.selectedModule; } set { if (this.selectedModule == value) { return; } if (this.selectedModule != null) { this.selectedModule.SelectedCommandNeedsImportModule -= new EventHandler(this.SelectedModule_SelectedCommandNeedsImportModule); this.selectedModule.SelectedCommandNeedsHelp -= new EventHandler(this.SelectedModule_SelectedCommandNeedsHelp); this.selectedModule.RunSelectedCommand -= new EventHandler(this.SelectedModule_RunSelectedCommand); this.selectedModule.PropertyChanged -= new PropertyChangedEventHandler(this.SelectedModule_PropertyChanged); } this.selectedModule = value; this.SetCanRun(); this.SetCanCopy(); if (this.selectedModule != null) { this.selectedModule.RefreshFilteredCommands(this.CommandNameFilter); this.selectedModule.SelectedCommandNeedsImportModule += new EventHandler(this.SelectedModule_SelectedCommandNeedsImportModule); this.selectedModule.SelectedCommandNeedsHelp += new EventHandler(this.SelectedModule_SelectedCommandNeedsHelp); this.selectedModule.RunSelectedCommand += new EventHandler(this.SelectedModule_RunSelectedCommand); this.selectedModule.PropertyChanged += new PropertyChangedEventHandler(this.SelectedModule_PropertyChanged); this.selectedModule.SelectedCommand = null; } this.OnNotifyPropertyChanged("SelectedModule"); } } /// /// Gets a value indicating whether we can run a command /// public bool CanRun { get { return this.canRun; } } /// /// Gets a value indicating whether we can copy a command /// public bool CanCopy { get { return this.canCopy; } } /// /// Gets the Modules parameter. /// public List Modules { get { return this.modules; } } /// /// Gets the visibility of the wait message /// public Visibility WaitMessageVisibility { get { return this.waitMessageDisplayed ? Visibility.Visible : Visibility.Hidden; } } /// /// Gets the visibility of the main grid /// public Visibility MainGridVisibility { get { return this.waitMessageDisplayed ? Visibility.Hidden : Visibility.Visible; } } /// /// Gets a value indicating whether the main grid is displayed /// public bool MainGridDisplayed { get { return !this.waitMessageDisplayed; } } /// /// Gets or sets a value indicating whether the wait message is displayed /// public bool WaitMessageDisplayed { get { return this.waitMessageDisplayed; } set { if (this.waitMessageDisplayed == value) { return; } this.waitMessageDisplayed = value; this.SetCanCopy(); this.SetCanRun(); this.OnNotifyPropertyChanged("WaitMessageDisplayed"); this.OnNotifyPropertyChanged("WaitMessageVisibility"); this.OnNotifyPropertyChanged("MainGridDisplayed"); this.OnNotifyPropertyChanged("MainGridVisibility"); } } /// /// Gets or sets an extra viewModel object that allows callers to control certain aspects of the GUI /// public object ExtraViewModel { get { return this.extraViewModel; } set { if (this.extraViewModel == value) { return; } this.extraViewModel = value; this.OnNotifyPropertyChanged("ExtraViewModel"); } } #endregion /// /// Returns the selected script /// /// the selected script public string GetScript() { if (this.SelectedModule == null) { return null; } if (this.SelectedModule.SelectedCommand == null) { return null; } return this.SelectedModule.SelectedCommand.GetScript(); } /// /// Triggers Refresh /// internal void OnRefresh() { EventHandler handler = this.Refresh; if (handler != null) { handler(this, new EventArgs()); } } #region Private Methods /// /// If current modules name is ALL, then return true. /// /// The modules name /// Return true is the module name is ALLModulesViewModel. private static bool IsAll(string name) { return name.Equals(ShowCommandResources.All, StringComparison.Ordinal); } /// /// Monitors property changes in the selected module to call: /// SetCanRun for IsThereASelectedImportedCommandWhereAllMandatoryParametersHaveValues /// SetCanCopy for SetCanCopy /// /// event sender /// event arguments private void SelectedModule_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "IsThereASelectedImportedCommandWhereAllMandatoryParametersHaveValues") { this.SetCanRun(); } else if (e.PropertyName == "IsThereASelectedCommand") { this.SetCanCopy(); } } /// /// Called to set this.CanRun when: /// The SelectedModule changes, since there will be no selected command in the new module, and CanRun should be false /// WaitMessageDisplayedMessage changes since this being true will cause this.MainGridDisplayed to be false and CanRun should be false /// IsThereASelectedImportedCommandWhereAllMandatoryParametersHaveValues changes in the selected module /// private void SetCanRun() { bool newValue = this.selectedModule != null && this.MainGridDisplayed && this.selectedModule.IsThereASelectedImportedCommandWhereAllMandatoryParametersHaveValues; if (this.canRun == newValue) { return; } this.canRun = newValue; this.OnNotifyPropertyChanged("CanRun"); } /// /// Called to set this.CanCopy when: /// The SelectedModule changes, since there will be no selected command in the new module, and CanCopy should be false /// WaitMessageDisplayedMessage changes since this being true will cause this.MainGridDisplayed to be false and CanCopy should be false /// IsThereASelectedCommand changes in the selected module /// private void SetCanCopy() { bool newValue = this.selectedModule != null && this.MainGridDisplayed && this.selectedModule.IsThereASelectedCommand; if (this.canCopy == newValue) { return; } this.canCopy = newValue; this.OnNotifyPropertyChanged("CanCopy"); } /// /// Initialize AllModulesViewModel. /// /// All loaded modules /// List of commands in all modules /// Whether showing common parameter private void Initialization(Dictionary importedModules, IEnumerable commands, bool noCommonParameterInModel) { if (commands == null) { return; } Dictionary rawModuleViewModels = new Dictionary(); this.noCommonParameter = noCommonParameterInModel; // separates commands in their Modules foreach (ShowCommandCommandInfo command in commands) { ModuleViewModel moduleViewModel; if (!rawModuleViewModels.TryGetValue(command.ModuleName, out moduleViewModel)) { moduleViewModel = new ModuleViewModel(command.ModuleName, importedModules); rawModuleViewModels.Add(command.ModuleName, moduleViewModel); } CommandViewModel commandViewModel; try { commandViewModel = CommandViewModel.GetCommandViewModel(moduleViewModel, command, noCommonParameterInModel); } catch (RuntimeException) { continue; } moduleViewModel.Commands.Add(commandViewModel); moduleViewModel.SetAllModules(this); } // populates this.modules this.modules = new List(); // if there is just one module then use only it if (rawModuleViewModels.Values.Count == 1) { this.modules.Add(rawModuleViewModels.Values.First()); this.modules[0].SortCommands(false); this.SelectedModule = this.modules[0]; return; } // If there are more modules, create an additional module to aggregate all commands ModuleViewModel allCommandsModule = new ModuleViewModel(ShowCommandResources.All, null); this.modules.Add(allCommandsModule); allCommandsModule.SetAllModules(this); if (rawModuleViewModels.Values.Count > 0) { foreach (ModuleViewModel module in rawModuleViewModels.Values) { module.SortCommands(false); this.modules.Add(module); allCommandsModule.Commands.AddRange(module.Commands); } } allCommandsModule.SortCommands(true); this.modules.Sort(this.Compare); this.SelectedModule = this.modules.Count == 0 ? null : this.modules[0]; } /// /// Compare two ModuleViewModel target and source. /// /// The source ModuleViewModel /// The target ModuleViewModel /// Compare result private int Compare(ModuleViewModel source, ModuleViewModel target) { if (AllModulesViewModel.IsAll(source.Name) && !AllModulesViewModel.IsAll(target.Name)) { return -1; } if (!AllModulesViewModel.IsAll(source.Name) && AllModulesViewModel.IsAll(target.Name)) { return 1; } return String.Compare(source.Name, target.Name, StringComparison.OrdinalIgnoreCase); } /// /// Called when the SelectedCommandNeedsHelp event is triggered in the Selected Module /// /// event sender /// event arguments private void SelectedModule_SelectedCommandNeedsHelp(object sender, HelpNeededEventArgs e) { this.OnSelectedCommandInSelectedModuleNeedsHelp(e); } /// /// Called when the SelectedCommandNeedsImportModule event is triggered in the Selected Module /// /// event sender /// event arguments private void SelectedModule_SelectedCommandNeedsImportModule(object sender, ImportModuleEventArgs e) { this.OnSelectedCommandInSelectedModuleNeedsImportModule(e); } /// /// Triggers SelectedCommandInSelectedModuleNeedsHelp /// /// event arguments private void OnSelectedCommandInSelectedModuleNeedsHelp(HelpNeededEventArgs e) { EventHandler handler = this.SelectedCommandInSelectedModuleNeedsHelp; if (handler != null) { handler(this, e); } } /// /// Triggers SelectedCommandInSelectedModuleNeedsImportModule /// /// event arguments private void OnSelectedCommandInSelectedModuleNeedsImportModule(ImportModuleEventArgs e) { EventHandler handler = this.SelectedCommandInSelectedModuleNeedsImportModule; if (handler != null) { handler(this, e); } } /// /// Called when the RunSelectedCommand is triggered in the selected module /// /// event sender /// event arguments private void SelectedModule_RunSelectedCommand(object sender, CommandEventArgs e) { this.OnRunSelectedCommandInSelectedModule(e); } /// /// Triggers RunSelectedCommandInSelectedModule /// /// event arguments private void OnRunSelectedCommandInSelectedModule(CommandEventArgs e) { EventHandler handler = this.RunSelectedCommandInSelectedModule; if (handler != null) { handler(this, e); } } /// /// If property changed will be notify /// /// The changed property private void OnNotifyPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { handler (this, new PropertyChangedEventArgs(propertyName)); } } #endregion } }