diff options
Diffstat (limited to 'main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs')
-rw-r--r-- | main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs | 1200 |
1 files changed, 1200 insertions, 0 deletions
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs new file mode 100644 index 0000000000..2cf875404d --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs @@ -0,0 +1,1200 @@ +// +// ManagePackagesDialog.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Core; +using MonoDevelop.Ide; +using MonoDevelop.Projects; +using NuGet.Versioning; +using Xwt; +using Xwt.Drawing; +using PropertyChangedEventArgs = System.ComponentModel.PropertyChangedEventArgs; + +namespace MonoDevelop.PackageManagement +{ + internal partial class ManagePackagesDialog + { + IBackgroundPackageActionRunner backgroundActionRunner; + ManagePackagesViewModel viewModel; + List<SourceRepositoryViewModel> packageSources; + DataField<bool> packageHasBackgroundColorField = new DataField<bool> (); + DataField<ManagePackagesSearchResultViewModel> packageViewModelField = new DataField<ManagePackagesSearchResultViewModel> (); + DataField<Image> packageImageField = new DataField<Image> (); + DataField<double> packageCheckBoxAlphaField = new DataField<double> (); + const double packageCheckBoxSemiTransarentAlpha = 0.6; + ListStore packageStore; + ManagePackagesCellView packageCellView; + TimeSpan searchDelayTimeSpan = TimeSpan.FromMilliseconds (500); + IDisposable searchTimer; + SourceRepositoryViewModel dummyPackageSourceRepresentingConfigureSettingsItem = + new SourceRepositoryViewModel (GettextCatalog.GetString ("Configure Sources...")); + ImageLoader imageLoader = new ImageLoader (); + bool loadingMessageVisible; + bool ignorePackageVersionChanges; + const string IncludePrereleaseUserPreferenceName = "NuGet.AddPackagesDialog.IncludePrerelease"; + TimeSpan populatePackageVersionsDelayTimeSpan = TimeSpan.FromMilliseconds (500); + int packageVersionsAddedCount; + IDisposable populatePackageVersionsTimer; + const int MaxVersionsToPopulate = 100; + DataField<bool> projectCheckedField; + DataField<string> projectNameField; + DataField<string> packageVersionField; + DataField<ManageProjectViewModel> projectField; + CheckBoxCellView projectCheckBoxCellView; + ListStore projectStore; + + public ManagePackagesDialog (ManagePackagesViewModel viewModel, string initialSearch = null) + : this ( + viewModel, + initialSearch, + PackageManagementServices.BackgroundPackageActionRunner) + { + } + + public ManagePackagesDialog ( + ManagePackagesViewModel viewModel, + string initialSearch, + IBackgroundPackageActionRunner backgroundActionRunner) + { + this.viewModel = viewModel; + this.backgroundActionRunner = backgroundActionRunner; + + Build (); + + consolidateLabel.Visible = viewModel.IsManagingSolution; + UpdateDialogTitle (); + UpdatePackageSearchEntryWithInitialText (initialSearch); + UpdatePackageResultsPageLabels (); + + InitializeListView (); + UpdateAddPackagesButton (); + ShowLoadingMessage (); + LoadViewModel (initialSearch); + + closeButton.Clicked += CloseButtonClicked; + this.showPrereleaseCheckBox.Clicked += ShowPrereleaseCheckBoxClicked; + this.packageSourceComboBox.SelectionChanged += PackageSourceChanged; + this.addPackagesButton.Clicked += AddPackagesButtonClicked; + this.packageSearchEntry.Changed += PackageSearchEntryChanged; + this.packageSearchEntry.Activated += PackageSearchEntryActivated; + this.packageVersionComboBox.SelectionChanged += PackageVersionChanged; + imageLoader.Loaded += ImageLoaded; + + browseLabel.ButtonPressed += BrowseLabelButtonPressed; + installedLabel.ButtonPressed += InstalledLabelButtonPressed; + updatesLabel.ButtonPressed += UpdatesLabelButtonPressed; + consolidateLabel.ButtonPressed += ConsolidateLabelButtonPressed; + } + + public bool ShowPreferencesForPackageSources { get; private set; } + + protected override void Dispose (bool disposing) + { + closeButton.Clicked -= CloseButtonClicked; + currentPackageVersionLabel.BoundsChanged -= PackageVersionLabelBoundsChanged; + + imageLoader.Loaded -= ImageLoaded; + imageLoader.Dispose (); + + RemoveSelectedPackagePropertyChangedEventHandler (); + viewModel.PropertyChanged -= ViewModelPropertyChanged; + viewModel.Dispose (); + DisposeExistingTimer (); + DisposePopulatePackageVersionsTimer (); + packageStore.Clear (); + projectStore?.Clear (); + viewModel = null; + + base.Dispose (disposing); + } + + void UpdateDialogTitle () + { + if (viewModel.IsManagingSolution) + return; + + Title = GettextCatalog.GetString ("Manage NuGet Packages – {0}", viewModel.Project.Name); + } + + void UpdatePackageSearchEntryWithInitialText (string initialSearch) + { + packageSearchEntry.Text = initialSearch; + if (!String.IsNullOrEmpty (initialSearch)) { + packageSearchEntry.CursorPosition = initialSearch.Length; + } + } + + public string SearchText { + get { return packageSearchEntry.Text; } + } + + void InitializeListView () + { + packageStore = new ListStore (packageHasBackgroundColorField, packageCheckBoxAlphaField, packageImageField, packageViewModelField); + packagesListView.DataSource = packageStore; + + AddPackageCellViewToListView (); + + packagesListView.SelectionChanged += PackagesListViewSelectionChanged; + packagesListView.RowActivated += PackagesListRowActivated; + packagesListView.VerticalScrollControl.ValueChanged += PackagesListViewScrollValueChanged; + } + + void AddPackageCellViewToListView () + { + packageCellView = new ManagePackagesCellView { + PackageField = packageViewModelField, + HasBackgroundColorField = packageHasBackgroundColorField, + CheckBoxAlphaField = packageCheckBoxAlphaField, + ImageField = packageImageField, + CellWidth = 467 + }; + var textColumn = new ListViewColumn ("Package", packageCellView); + packagesListView.Columns.Add (textColumn); + + packageCellView.PackageChecked += PackageCellViewPackageChecked; + } + + void InitializeProjectsListView () + { + projectStore?.Clear (); + + // Recreate the list view each time. This is a workaround for the + // list view not displaying items on re-populating if it has been sorted. + if (projectsListView != null) { + projectsListViewVBox.Remove (projectsListView); + projectsListView.Dispose (); + } + + projectStore?.Dispose (); + + projectCheckedField = new DataField<bool> (); + projectNameField = new DataField<string> (); + packageVersionField = new DataField<string> (); + projectField = new DataField<ManageProjectViewModel> (); + projectStore = new ListStore (projectCheckedField, projectNameField, packageVersionField, projectField); + + projectsListView = new ListView (); + projectsListView.DataSource = projectStore; + + // Selected project check box column. + if (projectCheckBoxCellView != null) + projectCheckBoxCellView.Toggled -= ProjectCheckBoxCellViewToggled; + projectCheckBoxCellView = new CheckBoxCellView (); + projectCheckBoxCellView.ActiveField = projectCheckedField; + projectCheckBoxCellView.Editable = true; + projectCheckBoxCellView.Toggled += ProjectCheckBoxCellViewToggled; + var column = new ListViewColumn (string.Empty, projectCheckBoxCellView); + projectsListView.Columns.Add (column); + + // Project column. + var textCellView = new TextCellView (); + textCellView.TextField = projectNameField; + column = new ListViewColumn (GettextCatalog.GetString ("Project"), textCellView) { + CanResize = true, + SortDataField = projectNameField + }; + projectsListView.Columns.Add (column); + + // Package version column + textCellView = new TextCellView (); + textCellView.TextField = packageVersionField; + column = new ListViewColumn (GettextCatalog.GetString ("Version"), textCellView) { + CanResize = true, + SortDataField = packageVersionField + }; + projectsListView.Columns.Add (column); + + // Add list view to dialog. + projectsListViewVBox.PackStart (projectsListView, true, true); + } + + void ShowLoadingMessage () + { + UpdateSpinnerLabel (); + noPackagesFoundFrame.Visible = false; + packagesListView.Visible = false; + loadingSpinnerFrame.Visible = true; + loadingMessageVisible = true; + } + + void HideLoadingMessage () + { + loadingSpinnerFrame.Visible = false; + packagesListView.Visible = true; + noPackagesFoundFrame.Visible = false; + loadingMessageVisible = false; + } + + void UpdateSpinnerLabel () + { + if (String.IsNullOrWhiteSpace (packageSearchEntry.Text)) { + loadingSpinnerLabel.Text = GettextCatalog.GetString ("Loading package list..."); + } else { + loadingSpinnerLabel.Text = GettextCatalog.GetString ("Searching packages..."); + } + } + + void ShowNoPackagesFoundMessage () + { + if (!String.IsNullOrWhiteSpace (packageSearchEntry.Text)) { + packagesListView.Visible = false; + noPackagesFoundFrame.Visible = true; + } + } + + void CloseButtonClicked (object sender, EventArgs e) + { + Close (); + } + + void ShowPrereleaseCheckBoxClicked (object sender, EventArgs e) + { + viewModel.IncludePrerelease = !viewModel.IncludePrerelease; + + SaveIncludePrereleaseUserPreference (); + } + + void SaveIncludePrereleaseUserPreference () + { + Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution; + if (solution != null) { + if (viewModel.IncludePrerelease) { + solution.UserProperties.SetValue (IncludePrereleaseUserPreferenceName, viewModel.IncludePrerelease); + } else { + solution.UserProperties.RemoveValue (IncludePrereleaseUserPreferenceName); + } + solution.SaveUserProperties (); + } + } + + bool GetIncludePrereleaseUserPreference () + { + Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution; + if (solution != null) { + return solution.UserProperties.GetValue (IncludePrereleaseUserPreferenceName, false); + } + + return false; + } + + void LoadViewModel (string initialSearch) + { + viewModel.SearchTerms = initialSearch; + + viewModel.IncludePrerelease = GetIncludePrereleaseUserPreference (); + showPrereleaseCheckBox.Active = viewModel.IncludePrerelease; + + ClearSelectedPackageInformation (); + PopulatePackageSources (); + viewModel.PropertyChanged += ViewModelPropertyChanged; + + if (viewModel.SelectedPackageSource != null) { + viewModel.ReadPackages (); + } else { + HideLoadingMessage (); + } + } + + void ClearSelectedPackageInformation () + { + this.packageInfoVBox.Visible = false; + this.currentPackageVersionHBox.Visible = false; + this.packageVersionsHBox.Visible = false; + projectStore?.Clear (); + } + + void RemoveSelectedPackagePropertyChangedEventHandler () + { + if (viewModel.SelectedPackage != null) { + viewModel.SelectedPackage.PropertyChanged -= SelectedPackageViewModelChanged; + viewModel.SelectedPackage = null; + } + } + + List<SourceRepositoryViewModel> PackageSources { + get { + if (packageSources == null) { + packageSources = viewModel.PackageSources.ToList (); + } + return packageSources; + } + } + + void PopulatePackageSources () + { + foreach (SourceRepositoryViewModel packageSource in PackageSources) { + AddPackageSourceToComboBox (packageSource); + } + + AddPackageSourceToComboBox (dummyPackageSourceRepresentingConfigureSettingsItem); + + packageSourceComboBox.SelectedItem = viewModel.SelectedPackageSource; + } + + void AddPackageSourceToComboBox (SourceRepositoryViewModel packageSource) + { + packageSourceComboBox.Items.Add (packageSource, packageSource.Name); + } + + void PackageSourceChanged (object sender, EventArgs e) + { + var selectedPackageSource = (SourceRepositoryViewModel)packageSourceComboBox.SelectedItem; + if (selectedPackageSource == dummyPackageSourceRepresentingConfigureSettingsItem) { + ShowPreferencesForPackageSources = true; + Close (); + } else { + viewModel.SelectedPackageSource = selectedPackageSource; + } + } + + void PackagesListViewSelectionChanged (object sender, EventArgs e) + { + try { + ShowSelectedPackage (); + } catch (Exception ex) { + LoggingService.LogError ("Error showing selected package.", ex); + ShowErrorMessage (ex.Message); + } + } + + void ShowSelectedPackage () + { + RemoveSelectedPackagePropertyChangedEventHandler (); + + ManagePackagesSearchResultViewModel packageViewModel = GetSelectedPackageViewModel (); + viewModel.SelectedPackage = packageViewModel; + if (packageViewModel != null) { + ShowPackageInformation (packageViewModel); + } else { + ClearSelectedPackageInformation (); + } + UpdateAddPackagesButton (); + } + + ManagePackagesSearchResultViewModel GetSelectedPackageViewModel () + { + if (packagesListView.SelectedRow != -1) { + return packageStore.GetValue (packagesListView.SelectedRow, packageViewModelField); + } + return null; + } + + void ShowPackageInformation (ManagePackagesSearchResultViewModel packageViewModel) + { + bool consolidate = viewModel.IsConsolidatePageSelected; + + if (consolidate) { + projectsListViewLabel.Text = GettextCatalog.GetString ("Select projects and a version for a consolidation."); + } else { + // Use the package id and not the package title to prevent a pango crash if the title + // contains Chinese characters. + this.packageNameLabel.Markup = packageViewModel.GetIdMarkup (); + this.packageAuthor.Text = packageViewModel.Author; + this.packagePublishedDate.Text = packageViewModel.GetLastPublishedDisplayText (); + this.packageDownloads.Text = packageViewModel.GetDownloadCountDisplayText (); + this.packageDescription.Text = packageViewModel.Description; + this.packageId.Text = packageViewModel.Id; + this.packageId.Visible = packageViewModel.HasNoGalleryUrl; + ShowUri (this.packageIdLink, packageViewModel.GalleryUrl, packageViewModel.Id); + ShowUri (this.packageProjectPageLink, packageViewModel.ProjectUrl); + ShowUri (this.packageLicenseLink, packageViewModel.LicenseUrl); + + PopulatePackageDependencies (packageViewModel); + } + + if (viewModel.IsInstalledPageSelected) { + packageVersionsLabel.WidthRequest = -1; + currentPackageVersionHBox.Visible = false; + packageVersionsHBox.Visible = false; + } else if (viewModel.IsUpdatesPageSelected) { + PopulatePackageVersions (packageViewModel); + ShowCurrentPackageVersion (packageViewModel); + packageVersionsHBox.Visible = true; + } else { + packageVersionsLabel.WidthRequest = -1; + currentPackageVersionHBox.Visible = false; + PopulatePackageVersions (packageViewModel); + packageVersionsHBox.Visible = true; + } + + foreach (Widget child in packageInfoVBox.Children) { + child.Visible = !consolidate; + } + + if (consolidate) { + PopulateProjectList (); + } else { + projectStore?.Clear (); + } + + projectsListViewLabel.Visible = consolidate; + projectsListViewVBox.Visible = consolidate; + this.packageInfoVBox.Visible = true; + + packageViewModel.PropertyChanged += SelectedPackageViewModelChanged; + viewModel.LoadPackageMetadata (packageViewModel); + } + + void ShowCurrentPackageVersion (ManagePackagesSearchResultViewModel packageViewModel) + { + if (maxPackageVersionLabelWidth.HasValue) { + currentPackageVersionLabel.WidthRequest = maxPackageVersionLabelWidth.Value; + packageVersionsLabel.WidthRequest = maxPackageVersionLabelWidth.Value; + } + + currentPackageVersion.Text = packageViewModel.GetCurrentPackageVersionText (); + + currentPackageVersionInfoPopoverWidget.Message = packageViewModel.GetCurrentPackageVersionAdditionalText (); + currentPackageVersionInfoPopoverWidget.Visible = !string.IsNullOrEmpty (currentPackageVersionInfoPopoverWidget.Message); + + currentPackageVersionHBox.Visible = !string.IsNullOrEmpty (currentPackageVersion.Text); + } + + void ShowUri (LinkLabel linkLabel, Uri uri, string label) + { + linkLabel.Text = label; + ShowUri (linkLabel, uri); + } + + void ShowUri (LinkLabel linkLabel, Uri uri) + { + if (uri == null) { + linkLabel.Visible = false; + } else { + linkLabel.Visible = true; + linkLabel.Uri = uri; + } + } + + void ViewModelPropertyChanged (object sender, PropertyChangedEventArgs e) + { + try { + ShowPackages (); + } catch (Exception ex) { + LoggingService.LogError ("Error showing packages.", ex); + ShowErrorMessage (ex.Message); + } + } + + void ShowPackages () + { + if (viewModel.HasError) { + ShowErrorMessage (viewModel.ErrorMessage); + } else { + ClearErrorMessage (); + } + + if (viewModel.IsLoadingNextPage) { + // Show spinner? + } else if (viewModel.IsReadingPackages) { + ClearPackages (); + } else { + HideLoadingMessage (); + } + + if (!viewModel.IsLoadingNextPage) { + AppendPackagesToListView (); + } + + UpdateAddPackagesButton (); + } + + void ClearPackages () + { + packageStore.Clear (); + ResetPackagesListViewScroll (); + UpdatePackageListViewSelectionColor (); + ShowLoadingMessage (); + ShrinkImageCache (); + DisposePopulatePackageVersionsTimer (); + } + + void ResetPackagesListViewScroll () + { + packagesListView.VerticalScrollControl.Value = 0; + } + + void ShowErrorMessage (string message) + { + errorMessageLabel.Text = message; + errorMessageHBox.Visible = true; + } + + void ClearErrorMessage () + { + errorMessageHBox.Visible = false; + errorMessageLabel.Text = ""; + } + + void ShrinkImageCache () + { + imageLoader.ShrinkImageCache (); + } + + void AppendPackagesToListView () + { + bool packagesListViewWasEmpty = (packageStore.RowCount == 0); + + for (int row = packageStore.RowCount; row < viewModel.PackageViewModels.Count; ++row) { + ManagePackagesSearchResultViewModel packageViewModel = viewModel.PackageViewModels [row]; + AppendPackageToListView (packageViewModel); + LoadPackageImage (row, packageViewModel); + } + + if (packagesListViewWasEmpty && (packageStore.RowCount > 0)) { + packagesListView.SelectRow (0); + } + + if (!viewModel.IsReadingPackages && (packageStore.RowCount == 0)) { + ShowNoPackagesFoundMessage (); + } + } + + void AppendPackageToListView (ManagePackagesSearchResultViewModel packageViewModel) + { + int row = packageStore.AddRow (); + packageStore.SetValue (row, packageHasBackgroundColorField, IsOddRow (row)); + packageStore.SetValue (row, packageCheckBoxAlphaField, GetPackageCheckBoxAlpha ()); + packageStore.SetValue (row, packageViewModelField, packageViewModel); + } + + void LoadPackageImage (int row, ManagePackagesSearchResultViewModel packageViewModel) + { + if (packageViewModel.HasIconUrl) { + imageLoader.LoadFrom (packageViewModel.IconUrl, row); + } + } + + static bool IsOddRow (int row) + { + return (row % 2) == 0; + } + + double GetPackageCheckBoxAlpha () + { + if (PackagesCheckedCount == 0) { + return packageCheckBoxSemiTransarentAlpha; + } + return 1; + } + + void ImageLoaded (object sender, ImageLoadedEventArgs e) + { + if (!e.HasError) { + int row = (int)e.State; + if (IsValidRowAndUrl (row, e.Uri)) { + packageStore.SetValue (row, packageImageField, e.Image); + } + } + } + + bool IsValidRowAndUrl (int row, Uri uri) + { + if (row < packageStore.RowCount) { + ManagePackagesSearchResultViewModel packageViewModel = packageStore.GetValue (row, packageViewModelField); + if (packageViewModel != null) { + return uri == packageViewModel.IconUrl; + } + } + return false; + } + + void AddPackagesButtonClicked (object sender, EventArgs e) + { + try { + if (viewModel.IsConsolidatePageSelected) { + List<ManagePackagesSearchResultViewModel> packageViewModels = GetSelectedPackageViewModels (); + List<IPackageAction> packageActions = viewModel.CreateConsolidatePackageActions (packageViewModels); + RunPackageActions (packageActions); + } else { + var projects = SelectProjects ().ToList (); + if (projects.Any ()) { + List<IPackageAction> packageActions = CreatePackageActionsForSelectedPackages (projects); + RunPackageActions (packageActions); + } + } + } catch (Exception ex) { + LoggingService.LogError ("Adding packages failed.", ex); + ShowErrorMessage (ex.Message); + } + } + + IEnumerable<IDotNetProject> SelectProjects () + { + return SelectProjects (GetSelectedPackageViewModels ()); + } + + IEnumerable<IDotNetProject> SelectProjects (ManagePackagesSearchResultViewModel packageViewModel) + { + return SelectProjects (new [] { packageViewModel }); + } + + IEnumerable<IDotNetProject> SelectProjects (IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels) + { + if (!viewModel.IsManagingSolution) + return viewModel.DotNetProjects; + + var selectProjectsViewModel = new SelectProjectsViewModel ( + GetFilteredDotNetProjectsToSelect (packageViewModels), + GetPackagesCountForAddPackagesButtonLabel (), + viewModel.PageSelected); + + using (var dialog = new SelectProjectsDialog (selectProjectsViewModel)) { + Command result = dialog.ShowWithParent (); + if (result == Command.Ok) { + return dialog.GetSelectedProjects (); + } else { + return Enumerable.Empty<IDotNetProject> (); + } + } + } + + /// <summary> + /// Remove projects that do not make sense based on the currently selected filter. + /// If we are on the Installed page that do not include any projects that do not have + /// the selected NuGet package installed. + /// </summary> + IEnumerable<IDotNetProject> GetFilteredDotNetProjectsToSelect (IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels) + { + if (viewModel.PageSelected != ManagePackagesPage.Browse) { + var packageIds = packageViewModels.Select (pvm => pvm.Id).ToList (); + return viewModel.GetDotNetProjectsToSelect (packageIds); + } + + return viewModel.DotNetProjects; + } + + void RunPackageActions (List<IPackageAction> packageActions) + { + if (packageActions.Count > 0) { + ProgressMonitorStatusMessage progressMessage = GetProgressMonitorStatusMessages (packageActions); + backgroundActionRunner.Run (progressMessage, packageActions); + + if (viewModel.PageSelected == ManagePackagesPage.Browse) { + viewModel.OnInstallingSelectedPackages (); + } + Close (); + } + } + + List<IPackageAction> CreatePackageActionsForSelectedPackages (IEnumerable<IDotNetProject> selectedProjects) + { + List<ManagePackagesSearchResultViewModel> packageViewModels = GetSelectedPackageViewModels (); + if (packageViewModels.Count > 0) { + return viewModel.CreatePackageActions (packageViewModels, selectedProjects); + } + return new List<IPackageAction> (); + } + + ProgressMonitorStatusMessage GetProgressMonitorStatusMessages (List<IPackageAction> packageActions) + { + if (viewModel.PageSelected == ManagePackagesPage.Browse) { + return GetProgressMonitorInstallMessages (packageActions); + } else if (viewModel.PageSelected == ManagePackagesPage.Installed) { + return GetProgressMonitorUninstallMessages (packageActions); + } else if (viewModel.PageSelected == ManagePackagesPage.Updates) { + return GetProgressMonitorUpdateMessages (packageActions); + } else if (viewModel.PageSelected == ManagePackagesPage.Consolidate) { + return GetProgressMonitorConsolidateMessages (packageActions); + } + return null; + } + + ProgressMonitorStatusMessage GetProgressMonitorInstallMessages (List<IPackageAction> packageActions) + { + if (packageActions.Count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + if (OlderPackageInstalledThanPackageSelected ()) { + return ProgressMonitorStatusMessageFactory.CreateUpdatingSinglePackageMessage (packageId); + } + return ProgressMonitorStatusMessageFactory.CreateInstallingSinglePackageMessage (packageId); + } + return ProgressMonitorStatusMessageFactory.CreateInstallingMultiplePackagesMessage (packageActions.Count); + } + + static ProgressMonitorStatusMessage GetProgressMonitorUninstallMessages (List<IPackageAction> packageActions) + { + int count = packageActions.Count; + if (count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + return ProgressMonitorStatusMessageFactory.CreateRemoveSinglePackageMessage (packageId); + } + + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Removing {0} packages...", count), + GettextCatalog.GetString ("{0} packages successfully removed.", count), + GettextCatalog.GetString ("Could not remove packages."), + GettextCatalog.GetString ("{0} packages removed with warnings.", count) + ); + } + + static ProgressMonitorStatusMessage GetProgressMonitorUpdateMessages (List<IPackageAction> packageActions) + { + int count = packageActions.Count; + if (count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + return ProgressMonitorStatusMessageFactory.CreateUpdatingSinglePackageMessage (packageId); + } + + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Updating {0} packages...", count), + GettextCatalog.GetString ("{0} packages successfully updated.", count), + GettextCatalog.GetString ("Could not update packages."), + GettextCatalog.GetString ("{0} packages updated with warnings.", count) + ); + } + + static ProgressMonitorStatusMessage GetProgressMonitorConsolidateMessages (List<IPackageAction> packageActions) + { + int count = packageActions.Count; + if (count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Consolidating {0}...", packageId), + GettextCatalog.GetString ("{0} successfully consolidated.", packageId), + GettextCatalog.GetString ("Could not consolidate {0}.", packageId), + GettextCatalog.GetString ("{0} consolidated with warnings.", packageId) + ); + } + + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Consolidating {0} packages...", count), + GettextCatalog.GetString ("{0} packages successfully consolidated.", count), + GettextCatalog.GetString ("Could not consolidate packages."), + GettextCatalog.GetString ("{0} packages consolidated with warnings.", count) + ); + } + + List<ManagePackagesSearchResultViewModel> GetSelectedPackageViewModels () + { + List<ManagePackagesSearchResultViewModel> packageViewModels = viewModel.CheckedPackageViewModels.ToList (); + if (packageViewModels.Count > 0) { + return packageViewModels; + } + + ManagePackagesSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel (); + if (selectedPackageViewModel != null) { + packageViewModels.Add (selectedPackageViewModel); + } + return packageViewModels; + } + + void PackageSearchEntryChanged (object sender, EventArgs e) + { + ClearErrorMessage (); + ClearPackages (); + UpdateAddPackagesButton (); + SearchAfterDelay (); + } + + void SearchAfterDelay () + { + DisposeExistingTimer (); + searchTimer = Application.TimeoutInvoke (searchDelayTimeSpan, Search); + } + + void DisposeExistingTimer () + { + if (searchTimer != null) { + searchTimer.Dispose (); + } + } + + bool Search () + { + viewModel.SearchTerms = this.packageSearchEntry.Text; + viewModel.Search (); + + return false; + } + + void PackagesListRowActivated (object sender, ListViewRowEventArgs e) + { + if (PackagesCheckedCount > 0) { + AddPackagesButtonClicked (sender, e); + } else { + ManagePackagesSearchResultViewModel packageViewModel = packageStore.GetValue (e.RowIndex, packageViewModelField); + ManagePackage (packageViewModel); + } + } + + void ManagePackage (ManagePackagesSearchResultViewModel packageViewModel) + { + try { + if (packageViewModel != null) { + if (viewModel.IsConsolidatePageSelected) { + List<IPackageAction> packageActions = viewModel.CreateConsolidatePackageActions ( + new ManagePackagesSearchResultViewModel [] { packageViewModel } + ); + RunPackageActions (packageActions); + } else { + var projects = SelectProjects (packageViewModel).ToList (); + if (!projects.Any ()) + return; + + List<IPackageAction> packageActions = viewModel.CreatePackageActions ( + new ManagePackagesSearchResultViewModel [] { packageViewModel }, + projects); + RunPackageActions (packageActions); + } + } + } catch (Exception ex) { + LoggingService.LogInternalError ("ManagePackage failed.", ex); + ShowErrorMessage (ex.Message); + } + } + + void PackageSearchEntryActivated (object sender, EventArgs e) + { + if (loadingMessageVisible) + return; + + if (PackagesCheckedCount > 0) { + AddPackagesButtonClicked (sender, e); + } else { + ManagePackagesSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel (); + ManagePackage (selectedPackageViewModel); + } + } + + void PackagesListViewScrollValueChanged (object sender, EventArgs e) + { + if (viewModel.IsLoadingNextPage) { + return; + } + + if (IsScrollBarNearEnd (packagesListView.VerticalScrollControl)) { + if (viewModel.HasNextPage) { + viewModel.ShowNextPage (); + } + } + } + + bool IsScrollBarNearEnd (ScrollControl scrollControl) + { + double currentValue = scrollControl.Value; + double maxValue = scrollControl.UpperValue; + double pageSize = scrollControl.PageSize; + + return (currentValue / (maxValue - pageSize)) > 0.7; + } + + void PackageCellViewPackageChecked (object sender, ManagePackagesCellViewEventArgs e) + { + UpdateAddPackagesButton (); + UpdatePackageListViewSelectionColor (); + UpdatePackageListViewCheckBoxAlpha (); + } + + void UpdateAddPackagesButton () + { + addPackagesButton.Label = GetAddPackagesButtonLabel (); + addPackagesButton.Sensitive = IsAddPackagesButtonEnabled (); + } + + string GetAddPackagesButtonLabel () + { + int packagesSelectedCount = GetPackagesCountForAddPackagesButtonLabel (); + if (viewModel.PageSelected == ManagePackagesPage.Browse) { + string label = GettextCatalog.GetPluralString ("Add Package", "Add Packages", packagesSelectedCount); + if (PackagesCheckedCount <= 1 && OlderPackageInstalledThanPackageSelected ()) { + label = GettextCatalog.GetString ("Update Package"); + } + return label; + } else if (viewModel.PageSelected == ManagePackagesPage.Installed) { + return GettextCatalog.GetPluralString ("Uninstall Package", "Uninstall Packages", packagesSelectedCount); + } else if (viewModel.PageSelected == ManagePackagesPage.Updates) { + return GettextCatalog.GetPluralString ("Update Package", "Update Packages", packagesSelectedCount); + } else if (viewModel.PageSelected == ManagePackagesPage.Consolidate) { + return GettextCatalog.GetPluralString ("Consolidate Package", "Consolidate Packages", packagesSelectedCount); + } + + throw new NotImplementedException ("Unknown package results page"); + } + + int GetPackagesCountForAddPackagesButtonLabel () + { + if (PackagesCheckedCount > 1) + return PackagesCheckedCount; + + return 1; + } + + void UpdatePackageListViewSelectionColor () + { + packageCellView.UseStrongSelectionColor = (PackagesCheckedCount == 0); + } + + void UpdatePackageListViewCheckBoxAlpha () + { + if (PackagesCheckedCount > 1) + return; + + double alpha = GetPackageCheckBoxAlpha (); + for (int row = 0; row < packageStore.RowCount; ++row) { + packageStore.SetValue (row, packageCheckBoxAlphaField, alpha); + } + } + + bool OlderPackageInstalledThanPackageSelected () + { + if (PackagesCheckedCount != 0) { + return false; + } + + ManagePackagesSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel (); + if (selectedPackageViewModel != null) { + return selectedPackageViewModel.IsOlderPackageInstalled (); + } + return false; + } + + bool IsAddPackagesButtonEnabled () + { + if (loadingMessageVisible) + return false; + + if (!IsAtLeastOnePackageSelected ()) + return false; + + if (viewModel.IsConsolidatePageSelected) + return viewModel.CanConsolidate (); + + return true; + } + + bool IsAtLeastOnePackageSelected () + { + return (PackagesCheckedCount) >= 1 || (packagesListView.SelectedRow != -1); + } + + int PackagesCheckedCount { + get { return viewModel.CheckedPackageViewModels.Count; } + } + + void SelectedPackageViewModelChanged (object sender, PropertyChangedEventArgs e) + { + try { + if (e.PropertyName == "Versions") { + PopulatePackageVersions (viewModel.SelectedPackage); + } else { + if (!viewModel.IsConsolidatePageSelected) { + packagePublishedDate.Text = viewModel.SelectedPackage.GetLastPublishedDisplayText (); + PopulatePackageDependencies (viewModel.SelectedPackage); + } + } + } catch (Exception ex) { + LoggingService.LogError ("Error loading package versions.", ex); + } + } + + void PopulatePackageVersions (ManagePackagesSearchResultViewModel packageViewModel) + { + DisposePopulatePackageVersionsTimer (); + + ignorePackageVersionChanges = true; + try { + packageVersionComboBox.Items.Clear (); + if (packageViewModel.Versions.Any ()) { + NuGetVersion latestStableVersion = packageViewModel.Versions.FirstOrDefault (v => !v.IsPrerelease); + int count = 0; + foreach (NuGetVersion version in packageViewModel.Versions) { + count++; + if (count > MaxVersionsToPopulate) { + packageVersionsAddedCount = count - 1; + if (version >= packageViewModel.SelectedVersion) { + AddPackageVersionToComboBox (packageViewModel.SelectedVersion); + } + PopulatePackageVersionsAfterDelay (); + break; + } + AddPackageVersionToComboBox (version, latestStableVersion == version); + } + } else { + AddPackageVersionToComboBox (packageViewModel.Version); + } + packageVersionComboBox.SelectedItem = packageViewModel.SelectedVersion; + } finally { + ignorePackageVersionChanges = false; + } + } + + void AddPackageVersionToComboBox (NuGetVersion version, bool latestStable = false) + { + string versionLabel = version.ToString (); + if (latestStable) + versionLabel += " " + GettextCatalog.GetString ("(latest stable)"); + packageVersionComboBox.Items.Add (version, versionLabel); + } + + void PackageVersionChanged (object sender, EventArgs e) + { + if (ignorePackageVersionChanges || viewModel.SelectedPackage == null) + return; + + viewModel.SelectedPackage.SelectedVersion = (NuGetVersion)packageVersionComboBox.SelectedItem; + UpdateAddPackagesButton (); + } + + void PopulatePackageDependencies (ManagePackagesSearchResultViewModel packageViewModel) + { + if (packageViewModel.IsDependencyInformationAvailable) { + this.packageDependenciesHBox.Visible = true; + this.packageDependenciesListHBox.Visible = packageViewModel.HasDependencies; + this.packageDependenciesNoneLabel.Visible = !packageViewModel.HasDependencies; + this.packageDependenciesList.Text = packageViewModel.GetPackageDependenciesDisplayText (); + } else { + this.packageDependenciesHBox.Visible = false; + this.packageDependenciesListHBox.Visible = false; + this.packageDependenciesNoneLabel.Visible = false; + this.packageDependenciesList.Text = String.Empty; + } + } + + void PopulatePackageVersionsAfterDelay () + { + populatePackageVersionsTimer = Application.TimeoutInvoke (populatePackageVersionsDelayTimeSpan, PopulateMorePackageVersions); + } + + void DisposePopulatePackageVersionsTimer () + { + if (populatePackageVersionsTimer != null) { + populatePackageVersionsTimer.Dispose (); + populatePackageVersionsTimer = null; + } + } + + bool PopulateMorePackageVersions () + { + ManagePackagesSearchResultViewModel packageViewModel = viewModel?.SelectedPackage; + if (populatePackageVersionsTimer == null || packageViewModel == null) { + return false; + } + + int count = 0; + foreach (NuGetVersion version in packageViewModel.Versions.Skip (packageVersionsAddedCount)) { + count++; + + if (count > MaxVersionsToPopulate) { + packageVersionsAddedCount += count - 1; + return true; + } + + AddPackageVersionToComboBox (version); + } + + return false; + } + + void UpdatePackageResultsPageLabels () + { + UpdatePackageResultsLabel (ManagePackagesPage.Browse, browseLabel); + UpdatePackageResultsLabel (ManagePackagesPage.Installed, installedLabel); + UpdatePackageResultsLabel (ManagePackagesPage.Updates, updatesLabel); + UpdatePackageResultsLabel (ManagePackagesPage.Consolidate, consolidateLabel); + } + + void UpdatePackageResultsLabel (ManagePackagesPage page, Label label) + { + string text = (string)label.Tag; + if (page == viewModel.PageSelected) { + label.Markup = string.Format ("<b><u>{0}</u></b>", text); + } else { + label.Markup = text; + } + } + + void BrowseLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Browse; + OnPackageResultsPageSelected (); + } + + void InstalledLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Installed; + OnPackageResultsPageSelected (); + } + + void UpdatesLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Updates; + OnPackageResultsPageSelected (); + } + + void ConsolidateLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Consolidate; + OnPackageResultsPageSelected (); + } + + void OnPackageResultsPageSelected () + { + UpdatePackageResultsPageLabels (); + ClearErrorMessage (); + ClearPackages (); + UpdateAddPackagesButton (); + Search (); + } + + void PopulateProjectList () + { + InitializeProjectsListView (); + + foreach (ManageProjectViewModel project in viewModel.ProjectViewModels) { + int row = projectStore.AddRow (); + projectStore.SetValues ( + row, + projectCheckedField, + project.IsChecked, + projectNameField, + project.ProjectName, + packageVersionField, + project.PackageVersion, + projectField, + project); + } + } + + void ProjectCheckBoxCellViewToggled (object sender, WidgetEventArgs e) + { + int row = projectsListView.CurrentEventRow; + if (row == -1) + return; + + ManageProjectViewModel selectedProject = projectStore.GetValue (row, projectField); + if (selectedProject == null) + return; + + selectedProject.IsChecked = !selectedProject.IsChecked; + + UpdateAddPackagesButton (); + } + } +}
\ No newline at end of file |