Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/Directory.Build.props2
-rw-r--r--main/build/MacOSX/monostub.mm2
m---------main/external/debugger-libs0
-rw-r--r--main/external/fsharpbinding/MonoDevelop.FSharpBinding/Services/RoslynHelpers.fs1
m---------main/external/vs-editor-api0
m---------main/external/xwt0
-rw-r--r--main/msbuild/RoslynVersion.props5
-rw-r--r--main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs51
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs86
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj1
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs12
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs51
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs123
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs51
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs2
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs27
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs41
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs5
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs5
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs36
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs273
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj1
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs1
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml6
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs6
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs48
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs44
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs6
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellView.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs)678
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewCheckBox.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewCheckBox.cs)58
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewEventArgs.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewEventArgs.cs)81
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.UI.cs)849
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs)2020
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs)163
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs117
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs107
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs4
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesSearchResultViewModel.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageSearchResultViewModel.cs)14
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesViewModel.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs)47
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj10
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesSearchResultViewModelTests.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageSearchResultViewModelTests.cs)66
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesViewModelTests.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs)419
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentManagedNuGetPackagesRepositoryTests.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentNuGetPackagesRepositoryTests.cs)18
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml36
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj42
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs608
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs4
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs36
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs60
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesSearchResultViewModel.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs)891
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs1019
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs61
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagedPackagesSearchResultViewModelComparer.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModelComparer.cs)12
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentManagedNuGetPackagesRepository.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentNuGetPackagesRepository.cs)14
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs4
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs101
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs48
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs111
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs119
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs107
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs119
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs10
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs17
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs36
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs121
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs14
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs3
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs20
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs29
-rw-r--r--main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml4
-rw-r--r--main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml2
-rw-r--r--main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml2
-rw-r--r--main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml2
-rw-r--r--main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs4
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs5
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs121
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetFrameworkMoniker.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs31
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs6
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs6
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs293
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildFileFormat.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs32
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/ProjectEvaluationException.cs8
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/SlnFileFormat.cs40
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs8
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MSBuildSerializationExtension.cs28
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs6
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectExtension.cs70
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs12
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs6
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectReader.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceSerializationExtension.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml19
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml2
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/ActionCommand.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs33
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebookTab.cs18
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs83
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs21
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs26
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs29
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Mac/NSViewExtensions.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Shared/GtkWorkarounds.cs65
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs102
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs21
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchMemento.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-pinned-9.pngbin0 -> 138 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-pinned-9@2x.pngbin0 -> 209 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark.pngbin0 -> 137 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark@2x.pngbin0 -> 201 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9.pngbin0 -> 143 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9@2x.pngbin0 -> 188 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark.pngbin0 -> 140 bytes
-rw-r--r--main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark@2x.pngbin0 -> 178 bytes
-rw-r--r--main/src/tools/mdtool/mdtool.csproj3
-rw-r--r--main/src/tools/mdtool/src/mdtool.cs59
-rw-r--r--main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/FilePathTests.cs66
-rw-r--r--main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/MSBuildProjectTests.cs14
-rw-r--r--main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/ProjectWithWildcardsTests.cs29
-rwxr-xr-xmain/tests/test-projects/console-project-with-wildcards/ConsoleProject-with-question-wildcard.csproj51
-rw-r--r--main/tests/test-projects/console-project-with-wildcards/maybe.js0
-rw-r--r--main/tests/test-projects/console-project-with-wildcards/maybe1.js0
-rwxr-xr-xmain/tests/test-projects/msbuild-tests/functions.csproj28
-rw-r--r--version-checks2
139 files changed, 6975 insertions, 3658 deletions
diff --git a/main/Directory.Build.props b/main/Directory.Build.props
index 1108f347a8..a63e497e15 100644
--- a/main/Directory.Build.props
+++ b/main/Directory.Build.props
@@ -1,4 +1,5 @@
<Project>
+ <Import Project="$(MSBuildThisFileDirectory)msbuild\RoslynVersion.props"/>
<PropertyGroup>
<RootDirectory>$(MSBuildThisFileDirectory)</RootDirectory>
@@ -19,7 +20,6 @@
<NuGetVersionNuGet>5.2.0-rtm.6067</NuGetVersionNuGet>
<NuGetVersionNUnit2>2.7.0</NuGetVersionNUnit2>
<NuGetVersionNUnit3>3.9.0</NuGetVersionNUnit3>
- <NuGetVersionRoslyn>3.3.0-beta1-19360-03</NuGetVersionRoslyn>
<NuGetVersionVSCodeDebugProtocol>15.8.20719.1</NuGetVersionVSCodeDebugProtocol>
<NuGetVersionVSComposition>15.8.112</NuGetVersionVSComposition>
<NuGetVersionVSEditor>16.1.28-g2ad4df7366</NuGetVersionVSEditor>
diff --git a/main/build/MacOSX/monostub.mm b/main/build/MacOSX/monostub.mm
index 36aca3a6ef..daec2cb615 100644
--- a/main/build/MacOSX/monostub.mm
+++ b/main/build/MacOSX/monostub.mm
@@ -260,7 +260,7 @@ main (int argc, char **argv)
}
// can be overridden with plist string MonoMinVersion
- NSString *req_mono_version = @"6.0.0.296";
+ NSString *req_mono_version = @"6.4.0.94";
NSDictionary *plist = [mainBundle infoDictionary];
if (plist) {
diff --git a/main/external/debugger-libs b/main/external/debugger-libs
-Subproject 694e1afd1f525e183cc60156d1bd929321bf87c
+Subproject 15f8803077ae5f921c7e350c09df0ea2d221df6
diff --git a/main/external/fsharpbinding/MonoDevelop.FSharpBinding/Services/RoslynHelpers.fs b/main/external/fsharpbinding/MonoDevelop.FSharpBinding/Services/RoslynHelpers.fs
index 7df93b10ee..11215f1ea8 100644
--- a/main/external/fsharpbinding/MonoDevelop.FSharpBinding/Services/RoslynHelpers.fs
+++ b/main/external/fsharpbinding/MonoDevelop.FSharpBinding/Services/RoslynHelpers.fs
@@ -40,4 +40,5 @@ module RoslynHelpers =
member x.ToMinimalDisplayString (_semanticModel, _position, _format) = symbolUse.Symbol.DisplayName //TODO format?
member x.ToMinimalDisplayParts (_semanticModel, _position, _format) = ImmutableArray.Empty //TODO
member x.HasUnsupportedMetadata = false //TODO
+ member x.Equals (other:Microsoft.CodeAnalysis.ISymbol, equalityComparer:Microsoft.CodeAnalysis.SymbolEqualityComparer) = equalityComparer.Equals(x, other)
member x.Equals (other:Microsoft.CodeAnalysis.ISymbol) = x.Equals(other)
diff --git a/main/external/vs-editor-api b/main/external/vs-editor-api
-Subproject 5f7f209e67b239bf8a05a63cfd1d90ac2bbd65c
+Subproject bf08f61283c38940a96fab59bfaa6e74f255207
diff --git a/main/external/xwt b/main/external/xwt
-Subproject dfd9f3b4ccc103c8463332a67985a1363678811
+Subproject 8379063a5c0beee41ad795593a09f132486194d
diff --git a/main/msbuild/RoslynVersion.props b/main/msbuild/RoslynVersion.props
new file mode 100644
index 0000000000..cc1f50e536
--- /dev/null
+++ b/main/msbuild/RoslynVersion.props
@@ -0,0 +1,5 @@
+<Project>
+ <PropertyGroup>
+ <NuGetVersionRoslyn>3.3.0-beta2-19401-05</NuGetVersionRoslyn>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs
index a4b6937b34..b34a637c1f 100644
--- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs
+++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs
@@ -917,31 +917,36 @@ namespace MonoDevelop.AssemblyBrowser
internal void Open (string url, AssemblyLoader currentAssembly = null, bool expandNode = true)
{
- Task.WhenAll (this.definitions.Select (d => d.LoadingTask)).ContinueWith (d => {
- // At least one of them failed.
- if (d.IsFaulted) {
- LoggingService.LogError ("Failed to load assemblies", d.Exception);
-
- // It's possible the assembly in which the type we're looking for exists
- // so try probing for it regardless.
- }
+ try {
+ Task.WhenAll (this.definitions.Select (d => d.LoadingTask)).ContinueWith (d => {
+ // At least one of them failed.
+ if (d.IsFaulted) {
+ LoggingService.LogError ("Failed to load assemblies", d.Exception);
+
+ // It's possible the assembly in which the type we're looking for exists
+ // so try probing for it regardless.
+ }
- suspendNavigation = false;
- ITreeNavigator nav = SearchMember (url, expandNode);
- if (definitions.Count == 0) // we've been disposed
- return;
- if (nav != null)
- return;
- try {
- if (currentAssembly != null) {
- OpenFromAssembly (url, currentAssembly);
- } else {
- OpenFromAssemblyNames (url);
+ suspendNavigation = false;
+ ITreeNavigator nav = SearchMember (url, expandNode);
+ if (definitions.Count == 0) // we've been disposed
+ return;
+ if (nav != null)
+ return;
+ try {
+ if (currentAssembly != null) {
+ OpenFromAssembly (url, currentAssembly);
+ } else {
+ OpenFromAssemblyNames (url);
+ }
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e);
}
- } catch (Exception e) {
- LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e);
- }
- }, Runtime.MainTaskScheduler).Ignore ();
+ }, Runtime.MainTaskScheduler).Ignore ();
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while opening assembly :" + url);
+ MessageService.ShowError (GettextCatalog.GetString ("Error while opening assembly {0}.", url), e);
+ }
}
void OpenFromAssembly (string url, AssemblyLoader currentAssembly, bool expandNode = true)
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs
new file mode 100644
index 0000000000..8966cc23c5
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs
@@ -0,0 +1,86 @@
+//
+// BreakpointStoreTests.cs
+//
+// Author:
+// Greg Munn <gregm@microsoft.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 NUnit.Framework;
+using Mono.Debugging.Client;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Mono.Debugging.Tests
+{
+ [TestFixture]
+ public class BreakpointStoreTests
+ {
+
+ [Test]
+ public async Task WhenStoreModifiedExternallyThenIteratingOverBreakpointsShouldNotThrow ()
+ {
+ var store = new BreakpointStore ();
+
+ Action<int> threadAddAction = (x) => {
+ store.Add (new Breakpoint ($"fileName{x}.cs", 10));
+ };
+
+ Action threadEnumerateAction = () => {
+ foreach (var bk in store.GetBreakpointsAtFile ("fileName1.cs")) {
+ }
+ };
+
+ List<Task> tasks = new List<Task> ();
+
+ for (int i = 0; i < 10; i++) {
+ tasks.Add (Task.Run (() => {
+ threadAddAction (i);
+ }));
+
+ tasks.Add (Task.Run (() => {
+ threadEnumerateAction ();
+ }));
+ }
+
+ foreach (var task in tasks) {
+ await task;
+ }
+ }
+
+ [Test]
+ public void GetBreakpointsAtFileReturnsCorrectFiles ()
+ {
+ var store = new BreakpointStore ();
+
+ store.Add (new Breakpoint ("fileName1.cs", 10));
+ store.Add (new Breakpoint ("fileName1.cs", 20));
+ store.Add (new Breakpoint ("fileName2.cs", 10));
+ store.Add (new Breakpoint ("fileName3.cs", 15));
+
+ int count = 0;
+ foreach (var bk in store.GetBreakpointsAtFile ("fileName1.cs")) {
+ count++;
+ Assert.AreEqual ("fileName1.cs", bk.FileName);
+ }
+
+ Assert.AreEqual (2, count);
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj
index 75a26167f2..6007317a64 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj
@@ -22,6 +22,7 @@
<Compile Include="DebugTests.MonoDevelop.cs" />
<Compile Include="TextFile.cs" />
<Compile Include="VsCodeStackFrameTests.cs" />
+ <Compile Include="BreakpointsAndSteppingTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MonoDevelop.Debugger.csproj">
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs
index 9e7aff8e03..4b307559c2 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs
@@ -68,13 +68,11 @@ namespace MonoDevelop.Debugger
var bps = new List<Breakpoint> ();
var needsUpdate = false;
- lock (breakpointStore) {
- foreach (var breakpoint in breakpointStore.GetBreakpointsAtFile (textDocument.FilePath)) {
- if (breakpoint.Line > snapshot.LineCount)
- continue;
+ foreach (var breakpoint in breakpointStore.GetBreakpointsAtFile (textDocument.FilePath)) {
+ if (breakpoint.Line > snapshot.LineCount)
+ continue;
- bps.Add (breakpoint);
- }
+ bps.Add (breakpoint);
}
foreach (var breakpoint in bps) {
@@ -82,7 +80,7 @@ namespace MonoDevelop.Debugger
needsUpdate = true;
var line = snapshot.GetLineFromLineNumber (breakpoint.Line - 1);
- var position = line.Start.Position + breakpoint.Column;
+ var position = line.Start.Position + breakpoint.Column - 1;
var span = await DebuggingService.GetBreakpointSpanAsync (textDocument, position);
if (breakpoints.TryGetValue (breakpoint, out var existingBreakpoint)) {
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs
index 40b79833c5..121c4f12fd 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs
@@ -292,8 +292,7 @@ namespace MonoDevelop.Debugger
continue;
var bp = (BreakEvent) store.GetValue (iter, (int) Columns.Breakpoint);
- lock (breakpoints)
- breakpoints.Remove (bp);
+ breakpoints.Remove (bp);
deleted = true;
}
} finally {
@@ -421,32 +420,30 @@ namespace MonoDevelop.Debugger
store.Clear ();
if (breakpoints != null) {
- lock (breakpoints) {
- foreach (BreakEvent be in breakpoints) {
- if (be.NonUserBreakpoint)
- continue;
-
- string hitCount = be.HitCountMode != HitCountMode.None ? be.CurrentHitCount.ToString () : "";
- string traceExp = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.TraceExpression : "";
- string traceVal = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.LastTraceValue : "";
- string name, condition = null;
-
- if (be is FunctionBreakpoint fb) {
- if (fb.ParamTypes != null)
- name = fb.FunctionName + "(" + string.Join (", ", fb.ParamTypes) + ")";
- else
- name = fb.FunctionName;
- } else if (be is Breakpoint bp) {
- name = string.Format ("{0}:{1},{2}", bp.FileName, bp.Line, bp.Column);
- condition = bp.ConditionExpression;
- } else if (be is Catchpoint cp) {
- name = cp.ExceptionName;
- } else {
- name = "";
- }
-
- store.AppendValues (GetIconId (be), be.Enabled, name, be, condition, traceExp, hitCount, traceVal);
+ foreach (BreakEvent be in breakpoints) {
+ if (be.NonUserBreakpoint)
+ continue;
+
+ string hitCount = be.HitCountMode != HitCountMode.None ? be.CurrentHitCount.ToString () : "";
+ string traceExp = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.TraceExpression : "";
+ string traceVal = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.LastTraceValue : "";
+ string name, condition = null;
+
+ if (be is FunctionBreakpoint fb) {
+ if (fb.ParamTypes != null)
+ name = fb.FunctionName + "(" + string.Join (", ", fb.ParamTypes) + ")";
+ else
+ name = fb.FunctionName;
+ } else if (be is Breakpoint bp) {
+ name = string.Format ("{0}:{1},{2}", bp.FileName, bp.Line, bp.Column);
+ condition = bp.ConditionExpression;
+ } else if (be is Catchpoint cp) {
+ name = cp.ExceptionName;
+ } else {
+ name = "";
}
+
+ store.AppendValues (GetIconId (be), be.Enabled, name, be, condition, traceExp, hitCount, traceVal);
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs
index 4b0b795f29..8f519906e9 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs
@@ -322,22 +322,20 @@ namespace MonoDevelop.Debugger
{
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints) {
- if (!breakpoints.IsReadOnly) {
- foreach (var be in breakpoints) {
- if (be is Breakpoint bp) {
- if (!bp.NonUserBreakpoint) {
- info.Enabled = true;
- break;
- }
- } else {
+ if (!breakpoints.IsReadOnly) {
+ foreach (var be in breakpoints) {
+ if (be is Breakpoint bp) {
+ if (!bp.NonUserBreakpoint) {
info.Enabled = true;
break;
}
+ } else {
+ info.Enabled = true;
+ break;
}
- } else {
- info.Enabled = false;
}
+ } else {
+ info.Enabled = false;
}
info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints);
@@ -355,8 +353,7 @@ namespace MonoDevelop.Debugger
var (caretLine, caretColumn) = textView.MDCaretLineAndColumn ();
var point = textView.Caret.Position.BufferPosition;
- lock (breakpoints)
- bp = breakpoints.Toggle (IdeApp.Workbench.ActiveDocument.FileName, caretLine, caretColumn);
+ bp = breakpoints.Toggle (IdeApp.Workbench.ActiveDocument.FileName, caretLine, caretColumn);
// If the breakpoint could not be inserted in the caret location, move the caret
// to the real line of the breakpoint, so that if the Toggle command is run again,
@@ -381,10 +378,8 @@ namespace MonoDevelop.Debugger
{
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints) {
- foreach (var bp in breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()))
- bp.Enabled = !bp.Enabled;
- }
+ foreach (var bp in breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()))
+ bp.Enabled = !bp.Enabled;
}
protected override void Update (CommandInfo info)
@@ -396,15 +391,13 @@ namespace MonoDevelop.Debugger
IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true) != null &&
IdeApp.Workbench.ActiveDocument.FileName != FilePath.Null &&
!breakpoints.IsReadOnly) {
- lock (breakpoints) {
- var bpInLine = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine());
- info.Enabled = bpInLine.Count > 0;
- info.Text = GettextCatalog.GetString ("Disable Breakpoint");
- foreach (var bp in bpInLine) {
- if (!bp.Enabled)
- info.Text = GettextCatalog.GetString ("Enable Breakpoint");
- break;
- }
+ var bpInLine = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine());
+ info.Enabled = bpInLine.Count > 0;
+ info.Text = GettextCatalog.GetString ("Disable Breakpoint");
+ foreach (var bp in bpInLine) {
+ if (!bp.Enabled)
+ info.Text = GettextCatalog.GetString ("Enable Breakpoint");
+ break;
}
} else {
info.Enabled = false;
@@ -416,20 +409,18 @@ namespace MonoDevelop.Debugger
{
protected override void Run ()
{
- var breakpoints = DebuggingService.Breakpoints;
+ var breakpoints = DebuggingService.Breakpoints.ToList();
bool enable = false;
- lock (breakpoints) {
- foreach (BreakEvent bp in breakpoints) {
- if (!bp.Enabled) {
- enable = true;
- break;
- }
+ foreach (BreakEvent bp in breakpoints) {
+ if (!bp.Enabled) {
+ enable = true;
+ break;
}
+ }
- foreach (BreakEvent bp in breakpoints) {
- bp.Enabled = enable;
- }
+ foreach (BreakEvent bp in breakpoints) {
+ bp.Enabled = enable;
}
}
@@ -437,20 +428,19 @@ namespace MonoDevelop.Debugger
{
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints) {
- info.Enabled = !breakpoints.IsReadOnly && breakpoints.Count > 0;
- bool enable = false;
- foreach (BreakEvent bp in breakpoints) {
- if (!bp.Enabled) {
- enable = true;
- break;
- }
+ info.Enabled = !breakpoints.IsReadOnly && breakpoints.Count > 0;
+ bool enable = false;
+ foreach (BreakEvent bp in breakpoints) {
+ if (!bp.Enabled) {
+ enable = true;
+ break;
}
- if (enable)
- info.Text = GettextCatalog.GetString ("Enable All Breakpoints");
- else
- info.Text = GettextCatalog.GetString ("Disable All Breakpoints");
}
+ if (enable)
+ info.Text = GettextCatalog.GetString ("Enable All Breakpoints");
+ else
+ info.Text = GettextCatalog.GetString ("Disable All Breakpoints");
+
info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints);
}
}
@@ -475,15 +465,13 @@ namespace MonoDevelop.Debugger
{
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints) {
- IEnumerable<Breakpoint> brs = breakpoints.GetBreakpointsAtFileLine (
- IdeApp.Workbench.ActiveDocument.FileName,
- IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ());
+ IEnumerable<Breakpoint> brs = breakpoints.GetBreakpointsAtFileLine (
+ IdeApp.Workbench.ActiveDocument.FileName,
+ IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ());
- List<Breakpoint> list = new List<Breakpoint> (brs);
- foreach (Breakpoint bp in list)
- breakpoints.Remove (bp);
- }
+ List<Breakpoint> list = new List<Breakpoint> (brs);
+ foreach (Breakpoint bp in list)
+ breakpoints.Remove (bp);
}
protected override void Update (CommandInfo info)
@@ -495,8 +483,7 @@ namespace MonoDevelop.Debugger
IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true) != null &&
IdeApp.Workbench.ActiveDocument.FileName != FilePath.Null &&
!breakpoints.IsReadOnly) {
- lock (breakpoints)
- info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0;
+ info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0;
} else {
info.Enabled = false;
}
@@ -511,8 +498,7 @@ namespace MonoDevelop.Debugger
if (DebuggingService.ShowBreakpointProperties (ref bp)) {
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints)
- breakpoints.Add (bp);
+ breakpoints.Add (bp);
}
}
@@ -531,8 +517,7 @@ namespace MonoDevelop.Debugger
if (DebuggingService.ShowBreakpointProperties (ref bp, BreakpointType.Function)) {
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints)
- breakpoints.Add (bp);
+ breakpoints.Add (bp);
}
}
@@ -551,8 +536,7 @@ namespace MonoDevelop.Debugger
if (DebuggingService.ShowBreakpointProperties (ref bp, BreakpointType.Catchpoint)) {
var breakpoints = DebuggingService.Breakpoints;
- lock (breakpoints)
- breakpoints.Add (bp);
+ breakpoints.Add (bp);
}
}
@@ -632,11 +616,9 @@ namespace MonoDevelop.Debugger
var breakpoints = DebuggingService.Breakpoints;
IList<Breakpoint> brs;
- lock (breakpoints) {
- brs = breakpoints.GetBreakpointsAtFileLine (
- IdeApp.Workbench.ActiveDocument.FileName,
- IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ());
- }
+ brs = breakpoints.GetBreakpointsAtFileLine (
+ IdeApp.Workbench.ActiveDocument.FileName,
+ IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ());
if (brs.Count > 0) {
BreakEvent be = brs [0];
@@ -653,8 +635,7 @@ namespace MonoDevelop.Debugger
IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true) != null &&
IdeApp.Workbench.ActiveDocument.FileName != FilePath.Null &&
!breakpoints.IsReadOnly) {
- lock (breakpoints)
- info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0;
+ info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0;
} else {
info.Enabled = false;
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
index 5ed2950d2e..e9139d5fa0 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
@@ -186,12 +186,10 @@ namespace MonoDevelop.Debugger
if (liveUpdate) {
var bp = pinnedWatches.CreateLiveUpdateBreakpoint (watch);
pinnedWatches.Bind (watch, bp);
- lock (breakpoints)
- breakpoints.Add(bp);
+ breakpoints.Add(bp);
} else {
pinnedWatches.Bind (watch, null);
- lock (breakpoints)
- breakpoints.Remove (watch.BoundTracer);
+ breakpoints.Remove (watch.BoundTracer);
}
}
@@ -1347,26 +1345,24 @@ namespace MonoDevelop.Debugger
static void OnLineCountChanged (object ob, LineCountEventArgs a)
{
- lock (breakpoints) {
- foreach (var bp in breakpoints.GetBreakpoints ()) {
- if (bp.FileName == a.TextFile.Name) {
- if (bp.Line > a.LineNumber) {
- var startIndex = a.TextFile.GetPositionFromLineColumn (bp.Line, bp.Column);
- var endIndex = a.TextFile.GetPositionFromLineColumn (bp.Line + 1, 0) - 1;
+ foreach (var bp in breakpoints.GetBreakpoints ()) {
+ if (bp.FileName == a.TextFile.Name) {
+ if (bp.Line > a.LineNumber) {
+ var startIndex = a.TextFile.GetPositionFromLineColumn (bp.Line, bp.Column);
+ var endIndex = a.TextFile.GetPositionFromLineColumn (bp.Line + 1, 0) - 1;
- if (endIndex < startIndex)
- endIndex = startIndex;
+ if (endIndex < startIndex)
+ endIndex = startIndex;
- var text = a.TextFile.GetText (startIndex, endIndex);
+ var text = a.TextFile.GetText (startIndex, endIndex);
- // If the line that has the breakpoint is deleted, delete the breakpoint, otherwise update the line #.
- if (bp.Line + a.LineCount >= a.LineNumber && !string.IsNullOrWhiteSpace (text))
- breakpoints.UpdateBreakpointLine (bp, bp.Line + a.LineCount);
- else
- breakpoints.Remove (bp);
- } else if (bp.Line == a.LineNumber && a.LineCount < 0)
+ // If the line that has the breakpoint is deleted, delete the breakpoint, otherwise update the line #.
+ if (bp.Line + a.LineCount >= a.LineNumber && !string.IsNullOrWhiteSpace (text))
+ breakpoints.UpdateBreakpointLine (bp, bp.Line + a.LineCount);
+ else
breakpoints.Remove (bp);
- }
+ } else if (bp.Line == a.LineNumber && a.LineCount < 0)
+ breakpoints.Remove (bp);
}
}
}
@@ -1374,8 +1370,7 @@ namespace MonoDevelop.Debugger
static void OnStoreUserPrefs (object s, UserPreferencesEventArgs args)
{
var baseDir = (args.Item as Solution)?.BaseDirectory;
- lock (breakpoints)
- args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.Breakpoints", breakpoints.Save (baseDir));
+ args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.Breakpoints", breakpoints.Save (baseDir));
args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.PinnedWatches", pinnedWatches);
}
@@ -1385,27 +1380,23 @@ namespace MonoDevelop.Debugger
if (elem != null) {
var baseDir = (args.Item as Solution)?.BaseDirectory;
- lock (breakpoints)
- breakpoints.Load (elem, baseDir);
+ breakpoints.Load (elem, baseDir);
}
PinnedWatchStore wstore = args.Properties.GetValue<PinnedWatchStore> ("MonoDevelop.Ide.DebuggingService.PinnedWatches");
if (wstore != null)
pinnedWatches.LoadFrom (wstore);
- lock (breakpoints)
- pinnedWatches.BindAll (breakpoints);
+ pinnedWatches.BindAll (breakpoints);
- lock (breakpoints)
- pinnedWatches.SetAllLiveUpdateBreakpoints (breakpoints);
+ pinnedWatches.SetAllLiveUpdateBreakpoints (breakpoints);
return Task.FromResult (true);
}
static void OnSolutionClosed (object s, EventArgs args)
{
- lock (breakpoints)
- breakpoints.Clear ();
+ breakpoints.Clear ();
}
static Microsoft.CodeAnalysis.ISymbol GetLanguageItem (MonoDevelop.Ide.Gui.Document document, SourceLocation sourceLocation, string identifier)
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs
index e65c855147..8389942e4c 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs
@@ -100,7 +100,7 @@ namespace MonoDevelop.Debugger
// Shared
ObjectValueTreeSelectedTextColor = Ide.Gui.Styles.BaseSelectionTextColor.ToHexString (false);
- ObjectValueTreeForegroundTextColor = Ide.Gui.Styles.BaseSelectionTextColor.ToHexString (false);
+ ObjectValueTreeForegroundTextColor = Ide.Gui.Styles.BaseForegroundColor.ToHexString (false);
ObjectValueTreeExternalCodeForegroundTextColor = ExceptionCaughtDialog.ExternalCodeTextColor.ToHexString (false);
ObjectValueTreeValueErrorText = Ide.Gui.Styles.WarningForegroundColor;
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs
index 0435aeb74c..fac52ab751 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs
@@ -159,18 +159,21 @@ namespace MonoDevelop.Debugger
if (process != null) { //User right-clicked on thread and not process
context_menu.Items.Add (new SeparatorContextMenuItem ());
var session = store.GetValue (selected, (int)Columns.Session) as DebuggerSession;
- var continueExecution = new ContextMenuItem (GettextCatalog.GetString ("Resume"));
- continueExecution.Sensitive = !session.IsRunning;
- continueExecution.Clicked += delegate {
- session.Continue ();
- };
- context_menu.Items.Add (continueExecution);
- var pauseExecution = new ContextMenuItem (GettextCatalog.GetString ("Pause"));
- pauseExecution.Sensitive = session.IsRunning;
- pauseExecution.Clicked += delegate {
- session.Stop ();
- };
- context_menu.Items.Add (pauseExecution);
+
+ if (session != null) {
+ var continueExecution = new ContextMenuItem (GettextCatalog.GetString ("Resume"));
+ continueExecution.Sensitive = !session.IsRunning;
+ continueExecution.Clicked += delegate {
+ session.Continue ();
+ };
+ context_menu.Items.Add (continueExecution);
+ var pauseExecution = new ContextMenuItem (GettextCatalog.GetString ("Pause"));
+ pauseExecution.Sensitive = session.IsRunning;
+ pauseExecution.Clicked += delegate {
+ session.Stop ();
+ };
+ context_menu.Items.Add (pauseExecution);
+ }
}
context_menu.Show (this, evt);
}
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs
new file mode 100644
index 0000000000..b473f188cb
--- /dev/null
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs
@@ -0,0 +1,41 @@
+//
+// DependenciesNodeCommandHandler.cs
+//
+// Author:
+// Matt Ward <matt.ward@microsoft.com>
+//
+// Copyright (c) 2019 Microsoft
+//
+// 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 MonoDevelop.Ide;
+using MonoDevelop.Ide.Gui.Components;
+using MonoDevelop.PackageManagement;
+
+namespace MonoDevelop.DotNetCore.Commands
+{
+ class DependenciesNodeCommandHandler : NodeCommandHandler
+ {
+ public override void ActivateItem ()
+ {
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject);
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs
index 78ee767357..cf2b31370a 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs
@@ -24,6 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.PackageManagement;
@@ -33,8 +34,8 @@ namespace MonoDevelop.DotNetCore.Commands
{
public override void ActivateItem ()
{
- var runner = new AddPackagesDialogRunner ();
- runner.Run ();
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject);
}
}
}
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs
index 8c00cd2380..107c754e6b 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs
@@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
+using MonoDevelop.DotNetCore.Commands;
using MonoDevelop.Ide.Gui.Components;
namespace MonoDevelop.DotNetCore.NodeBuilders
@@ -40,6 +41,10 @@ namespace MonoDevelop.DotNetCore.NodeBuilders
return DependenciesNode.NodeName;
}
+ public override Type CommandHandlerType {
+ get { return typeof (DependenciesNodeCommandHandler); }
+ }
+
public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo)
{
var node = (DependenciesNode)dataObject;
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs
index e3c1a79ef9..df44c28c89 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs
@@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
+using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -140,16 +141,32 @@ namespace MonoDevelop.DotNetCore.Templating
return null;
string templatesDirectory = Path.Combine (
- DotNetCoreSdk.SdkRootPath,
- dotNetCoreSdk.OriginalString,
- "Templates"
- );
+ DotNetCoreSdk.SdkRootPath,
+ dotNetCoreSdk.OriginalString,
+ "Templates"
+ );
- if (DirectoryExists (templatesDirectory)) {
- return templatesDirectory;
+ if (!DirectoryExists (templatesDirectory)) {
+ // .NET Core 3.0 Preview 8 and higher place templates in the root dir
+ // and versioned by runtime, not SDK
+ var baseTemplatesDir = Path.Combine (Directory.GetParent (DotNetCoreSdk.SdkRootPath).FullName, "templates");
+ if (DirectoryExists (baseTemplatesDir)) {
+ var availableTemplates = new Dictionary<DotNetCoreVersion, string> ();
+ foreach (var dir in EnumerateDirectories (baseTemplatesDir)) {
+ if (DotNetCoreVersion.TryParse (Path.GetFileName (dir), out var version)) {
+ availableTemplates [version] = dir;
+ }
+ }
+
+ templatesDirectory = availableTemplates.Keys
+ .Where (v => v.Major < dotNetCoreSdk.Major || (v.Major == dotNetCoreSdk.Major && v.Minor <= dotNetCoreSdk.Minor))
+ .OrderByDescending (v => v)
+ .Select (v => availableTemplates [v])
+ .FirstOrDefault ();
+ }
}
- return string.Empty;
+ return DirectoryExists (templatesDirectory) ? templatesDirectory : string.Empty;
}
DotNetCoreVersion GetDotNetCoreSdkVersion (DotNetCoreVersion version)
@@ -172,5 +189,10 @@ namespace MonoDevelop.DotNetCore.Templating
/// Used by unit tests.
/// </summary>
internal Func<string, IEnumerable<string>> EnumerateFiles = Directory.EnumerateFiles;
+
+ /// <summary>
+ /// Used by unit tests.
+ /// </summary>
+ internal Func<string, IEnumerable<string>> EnumerateDirectories = Directory.EnumerateDirectories;
}
}
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs
index a9720ac747..4053f3f526 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs
@@ -24,9 +24,10 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using MonoDevelop.DotNetCore.Templating;
using NUnit.Framework;
@@ -52,6 +53,7 @@ namespace MonoDevelop.DotNetCore.Tests
provider = new DotNetCoreProjectTemplateStringTagProvider ();
provider.DirectoryExists = DirectoryExists;
provider.EnumerateFiles = EnumerateFiles;
+ provider.EnumerateDirectories = EnumerateDirectories;
}
bool DirectoryExists (string directory)
@@ -64,6 +66,11 @@ namespace MonoDevelop.DotNetCore.Tests
return templateFiles;
}
+ IEnumerable<string> EnumerateDirectories (string directory)
+ {
+ return directories.Where (dir => Directory.GetParent (dir).FullName == directory);
+ }
+
static string ToNativePath (string filePath)
{
if (Path.DirectorySeparatorChar == '\\')
@@ -77,6 +84,34 @@ namespace MonoDevelop.DotNetCore.Tests
return filePath.Replace ('\\', Path.DirectorySeparatorChar);
}
+ protected void DotNetCoreSdksInstalled (string sdkVersion, string templatesVersion, bool globalTemplates)
+ {
+ DotNetCoreSdksInstalled (sdkVersion);
+ if (globalTemplates) {
+ AddGlobalProjectTemplateFile (
+ templatesVersion,
+ $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.nupkg",
+ $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.nupkg",
+ $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.nupkg",
+ $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.nupkg");
+ } else {
+ AddProjectTemplateFile (
+ sdkVersion,
+ $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.nupkg",
+ $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.nupkg",
+ $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.nupkg",
+ $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.aaa",
+ $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.nupkg");
+ }
+ }
+
string GetTagValue (string tag)
{
return provider.GetTagValue (null, tag) as string;
@@ -102,6 +137,35 @@ namespace MonoDevelop.DotNetCore.Tests
return GetTagValue ($"DotNetCoreSdk.{version}.Templates.Web.Spa.ProjectTemplates.nupkg");
}
+ string GetExpectedTemplateTagValue (string sdkVersion, string templatesVersion, string filePrefix, bool globalTemplates)
+ {
+ if (globalTemplates) {
+ return Path.Combine (
+ Directory.GetParent (sdkRootPath).FullName,
+ "templates",
+ templatesVersion,
+ $"{filePrefix}.{templatesVersion}.nupkg");
+ } else {
+ return Path.Combine (
+ sdkRootPath,
+ sdkVersion,
+ "Templates",
+ $"{filePrefix}.{templatesVersion}.nupkg");
+ }
+ }
+
+ void AddGlobalProjectTemplateFile (string sdkVersion, params string [] fileNames)
+ {
+ string directory = Path.Combine (Directory.GetParent (sdkRootPath).FullName, "templates");
+ directories.Add (directory);
+ directory = Path.Combine (directory, sdkVersion);
+ directories.Add (directory);
+ foreach (string fileName in fileNames) {
+ string fullPath = Path.Combine (directory, fileName);
+ templateFiles.Add (fullPath);
+ }
+ }
+
void AddProjectTemplateFile (string sdkVersion, params string[] fileNames)
{
foreach (string fileName in fileNames) {
@@ -129,6 +193,7 @@ namespace MonoDevelop.DotNetCore.Tests
Assert.AreEqual (string.Empty, GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.1"));
Assert.AreEqual (string.Empty, GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.2"));
+ Assert.AreEqual (string.Empty, GetDotNetCoreSdkCommonProjectTemplatesTagValue ("3.0"));
}
[TestCase ("2.1", "2.1.300-preview1-008174")]
@@ -142,182 +207,56 @@ namespace MonoDevelop.DotNetCore.Tests
Assert.AreEqual (string.Empty, result);
}
- [Test]
- public void NetCore22Installed_CommonProjectTemplates ()
+ [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)]
+ [TestCase ("3.0.100-preview7-012821", "3.0.2.0.0-preview7.19365.3", false)]
+ [TestCase ("2.2.100-preview2-009404", "2.2.1.0.2-beta4-20180904-2003790", false)]
+ [TestCase ("2.1.701", "2.1.1.0.2-beta3", false)]
+ [TestCase ("2.1.300-preview1-008174", "2.1.1.0.1-beta3-20180215-1392068", false)]
+ public void NetCoreInstalled_CommonProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates)
{
- DotNetCoreSdksInstalled ("2.2.100-preview2-009404");
- AddProjectTemplateFile (
- "2.2.100-preview2-009404",
- "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg",
- "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.2.100-preview2-009404",
- "Templates",
- "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg");
-
- string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.2");
-
- Assert.AreEqual (expectedResult, result);
+ DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates);
+ Assert.AreEqual (
+ GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.common.projecttemplates", globalTemplates),
+ GetDotNetCoreSdkCommonProjectTemplatesTagValue (sdkVersion.Substring (0, 3)));
}
- [Test]
- public void NetCore22Installed_TestProjectTemplates ()
+ [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)]
+ [TestCase ("3.0.100-preview7-012821", "3.0.1.0.2-beta4.19155.2", false)]
+ [TestCase ("2.2.100-preview2-009404", "2.2.1.0.2-beta4-20180904-2003790", false)]
+ [TestCase ("2.1.701", "2.1.1.0.2-beta4-20181009-2100240", false)]
+ [TestCase ("2.1.300-preview1-008174", "2.1.1.0.1-beta3-20180215-1392068", false)]
+ public void NetCoreInstalled_TestProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates)
{
- DotNetCoreSdksInstalled ("2.2.100-preview2-009404");
- AddProjectTemplateFile (
- "2.2.100-preview2-009404",
- "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg",
- "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.2.100-preview2-009404",
- "Templates",
- "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg");
-
- string result = GetDotNetCoreSdkTestProjectTemplatesTagValue ("2.2");
-
- Assert.AreEqual (expectedResult, result);
- }
-
- [Test]
- public void NetCore22Installed_WebProjectTemplates ()
- {
- DotNetCoreSdksInstalled ("2.2.100-preview2-009404");
- AddProjectTemplateFile (
- "2.2.100-preview2-009404",
- "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg",
- "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.2.100-preview2-009404",
- "Templates",
- "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg");
-
- string result = GetDotNetCoreSdkWebProjectTemplatesTagValue ("2.2");
-
- Assert.AreEqual (expectedResult, result);
+ DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates);
+ Assert.AreEqual (
+ GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.test.projecttemplates", globalTemplates),
+ GetDotNetCoreSdkTestProjectTemplatesTagValue (sdkVersion.Substring (0, 3)));
}
- [Test]
- public void NetCore22Installed_MatchingFileWithDifferentExtension_CommonProjectTemplates ()
+ [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)]
+ [TestCase ("3.0.100-preview7-012821", "3.0.0-preview7.19365.7", false)]
+ [TestCase ("2.2.100-preview2-009404", "2.2.2.2.0-preview2-35157", false)]
+ [TestCase ("2.1.701", "2.1.2.1.12", false)]
+ [TestCase ("2.1.300-preview1-008174", "2.1.2.1.0-preview1-final", false)]
+ public void NetCoreInstalled_WebProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates)
{
- DotNetCoreSdksInstalled ("2.2.100-preview2-009404");
- AddProjectTemplateFile (
- "2.2.100-preview2-009404",
- "microsoft.dotnet.common.projecttemplates.2.0.1.0.0-beta3-20171110-312.aaa",
- "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.2.100-preview2-009404",
- "Templates",
- "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg");
-
- string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.2");
-
- Assert.AreEqual (expectedResult, result);
+ DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates);
+ Assert.AreEqual (
+ GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.web.projecttemplates", globalTemplates),
+ GetDotNetCoreSdkWebProjectTemplatesTagValue (sdkVersion.Substring (0, 3)));
}
- [Test]
- public void NetCore21Installed_CommonProjectTemplates ()
+ [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)]
+ [TestCase ("3.0.100-preview7-012821", "3.0.0-preview7.19365.7", false)]
+ [TestCase ("2.2.100-preview2-009404", "2.2.2.2.0-preview2-35157", false)]
+ [TestCase ("2.1.701", "2.1.12", false)]
+ [TestCase ("2.1.300-preview1-008174", "2.1.2.1.0-preview1-final", false)]
+ public void NetCoreInstalled_SpaWebProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates)
{
- DotNetCoreSdksInstalled ("2.1.300-preview1-008174");
- AddProjectTemplateFile (
- "2.1.300-preview1-008174",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.1.300-preview1-008174",
- "Templates",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg");
-
- string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.1");
-
- Assert.AreEqual (expectedResult, result);
- }
-
- [Test]
- public void NetCore21Installed_TestProjectTemplates ()
- {
- DotNetCoreSdksInstalled ("2.1.300-preview1-008174");
- AddProjectTemplateFile (
- "2.1.300-preview1-008174",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.1.300-preview1-008174",
- "Templates",
- "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg");
-
- string result = GetDotNetCoreSdkTestProjectTemplatesTagValue ("2.1");
-
- Assert.AreEqual (expectedResult, result);
- }
-
- [Test]
- public void NetCore21Installed_WebProjectTemplates ()
- {
- DotNetCoreSdksInstalled ("2.1.300-preview1-008174");
- AddProjectTemplateFile (
- "2.1.300-preview1-008174",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.1.300-preview1-008174",
- "Templates",
- "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg");
-
- string result = GetDotNetCoreSdkWebProjectTemplatesTagValue ("2.1");
-
- Assert.AreEqual (expectedResult, result);
- }
-
- [Test]
- public void NetCore21Installed_SpaWebProjectTemplates ()
- {
- DotNetCoreSdksInstalled ("2.1.300-preview1-008174");
- AddProjectTemplateFile (
- "2.1.300-preview1-008174",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg",
- "microsoft.dotnet.web.spa.projecttemplates.2.1.2.1.0-preview1-final.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.1.300-preview1-008174",
- "Templates",
- "microsoft.dotnet.web.spa.projecttemplates.2.1.2.1.0-preview1-final.nupkg");
-
- string result = GetDotNetCoreSdkSpaWebProjectTemplatesTagValue ("2.1");
-
- Assert.AreEqual (expectedResult, result);
- }
-
- [Test]
- public void NetCore21Installed_MatchingFileWithDifferentExtension_CommonProjectTemplates ()
- {
- DotNetCoreSdksInstalled ("2.1.300-preview1-008174");
- AddProjectTemplateFile (
- "2.1.300-preview1-008174",
- "microsoft.dotnet.common.projecttemplates.2.0.1.0.0-beta3-20171110-312.aaa",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg");
- string expectedResult = Path.Combine (
- sdkRootPath,
- "2.1.300-preview1-008174",
- "Templates",
- "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg");
-
- string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.1");
-
- Assert.AreEqual (expectedResult, result);
+ DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates);
+ Assert.AreEqual (
+ GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.web.spa.projecttemplates", globalTemplates),
+ GetDotNetCoreSdkSpaWebProjectTemplatesTagValue (sdkVersion.Substring (0, 3)));
}
[TestCase ("DotNetCoreSdk.2.1.Templates.Common.ProjectTemplates.txt")]
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj
index bb1c502dc0..a79bd177e0 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj
@@ -91,6 +91,7 @@
<Compile Include="MonoDevelop.DotNetCore\FrameworkReference.cs" />
<Compile Include="MonoDevelop.DotNetCore.NodeBuilders\PackageDependencyNodePropertyProvider.cs" />
<Compile Include="MonoDevelop.DotNetCore.NodeBuilders\PackageDependencyNodeDescriptor.cs" />
+ <Compile Include="MonoDevelop.DotNetCore.Commands\DependenciesNodeCommandHandler.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj">
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs
index 4b8f3463ce..24a9ff0849 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs
@@ -26,6 +26,7 @@
using System;
using System.IO;
+using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Core;
diff --git a/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml b/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml
index 8e8459640d..32c246959b 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml
+++ b/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml
@@ -1214,7 +1214,7 @@
<SeparatorItem
id="DependenciesEditReferenceSeparator" />
<CommandItem
- id="MonoDevelop.PackageManagement.Commands.AddPackages" _label = "Add _Packages..." />
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInProject" />
<CommandItem
@@ -1222,7 +1222,7 @@
</Condition>
<Condition id="ItemType" value="MonoDevelop.DotNetCore.NodeBuilders.PackageDependenciesNode">
<CommandItem
- id="MonoDevelop.PackageManagement.Commands.AddPackages" _label = "Add _Packages..." />
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInProject" />
<CommandItem
@@ -1233,7 +1233,7 @@
value="MonoDevelop.DotNetCore.NodeBuilders.AssemblyDependenciesNode|MonoDevelop.DotNetCore.NodeBuilders.ProjectDependenciesNode">
<CommandItem
id="MonoDevelop.Ide.Commands.ProjectCommands.AddReference"
- insertbefore="MonoDevelop.PackageManagement.Commands.AddPackages" />
+ insertbefore="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" />
</Condition>
<Condition id="ItemType" value="UnknownProject|Solution">
<CommandItem
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs
index c16dc31352..1a08dcbb5f 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs
@@ -24,16 +24,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
-
namespace MonoDevelop.PackageManagement.Commands
{
internal class AddPackagesHandler : PackagesCommandHandler
{
protected override void Run ()
{
- var runner = new AddPackagesDialogRunner ();
- runner.Run ();
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (GetSelectedDotNetProject ());
}
protected override bool IsEnabled ()
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs
new file mode 100644
index 0000000000..91c593b4eb
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs
@@ -0,0 +1,48 @@
+//
+// ManagePackagesHandler.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.Linq;
+using MonoDevelop.PackageManagement.Commands;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal class ManagePackagesHandler : PackagesCommandHandler
+ {
+ protected override void Run ()
+ {
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run ();
+ }
+
+ protected override bool IsEnabled ()
+ {
+ var solution = GetSelectedSolution ();
+ return (solution != null) &&
+ solution.GetAllDotNetProjects ().Any ();
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs
new file mode 100644
index 0000000000..583c401cf9
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs
@@ -0,0 +1,44 @@
+//
+// ManagePackagesInProjectHandler.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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 MonoDevelop.PackageManagement.Commands;
+
+namespace MonoDevelop.PackageManagement
+{
+ class ManagePackagesInProjectHandler : PackagesCommandHandler
+ {
+ protected override bool IsEnabled ()
+ {
+ return IsDotNetProjectSelected ();
+ }
+
+ protected override void Run ()
+ {
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (GetSelectedDotNetProject ());
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs
index b0b0a7b585..a07b239fd0 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs
@@ -28,9 +28,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Components.Commands;
+using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.PackageManagement.NodeBuilders;
-using NuGet.ProjectManagement;
namespace MonoDevelop.PackageManagement.Commands
{
@@ -38,8 +38,8 @@ namespace MonoDevelop.PackageManagement.Commands
{
public override void ActivateItem ()
{
- var runner = new AddPackagesDialogRunner ();
- runner.Run ();
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject);
}
[CommandUpdateHandler (PackagesFolderNodeCommands.ReinstallAllPackagesInProject)]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellView.cs
index aa6b3111d4..09611a1daa 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellView.cs
@@ -1,340 +1,340 @@
-//
-// PackageCellView.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 MonoDevelop.Core;
-using Xwt;
-using Xwt.Drawing;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class PackageCellView : CanvasCellView
- {
- int packageIdFontSize;
- int packageDescriptionFontSize;
-
- public PackageCellView ()
- {
- CellWidth = 260;
-
- BackgroundColor = Styles.CellBackgroundColor;
- StrongSelectionColor = Styles.CellStrongSelectionColor;
- SelectionColor = Styles.CellSelectionColor;
-
- UseStrongSelectionColor = true;
-
- if (Platform.IsWindows) {
- packageIdFontSize = 10;
- packageDescriptionFontSize = 9;
- } else {
- packageIdFontSize = 12;
- packageDescriptionFontSize = 11;
- }
- }
-
- public IDataField<PackageSearchResultViewModel> PackageField { get; set; }
- public IDataField<Image> ImageField { get; set; }
- public IDataField<bool> HasBackgroundColorField { get; set; }
- public IDataField<double> CheckBoxAlphaField { get; set; }
-
- public double CellWidth { get; set; }
-
- public Color BackgroundColor { get; set; }
- public Color StrongSelectionColor { get; set; }
- public Color SelectionColor { get; set; }
-
- public bool UseStrongSelectionColor { get; set; }
-
- public event EventHandler<PackageCellViewEventArgs> PackageChecked;
-
- protected override void OnDraw (Context ctx, Rectangle cellArea)
- {
- PackageSearchResultViewModel packageViewModel = GetValue (PackageField);
- if (packageViewModel == null) {
- return;
- }
-
- FillCellBackground (ctx);
- UpdateTextColor (ctx);
-
- DrawCheckBox (ctx, packageViewModel, cellArea);
- DrawPackageImage (ctx, cellArea);
-
- double packageIdWidth = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
-
- // Package download count.
- if (packageViewModel.HasDownloadCount) {
- var downloadCountTextLayout = new TextLayout ();
- downloadCountTextLayout.Text = packageViewModel.GetDownloadCountOrVersionDisplayText ();
- Size size = downloadCountTextLayout.GetSize ();
- Point location = new Point (cellArea.Right - packageDescriptionPadding.Right, cellArea.Top + packageDescriptionPadding.Top);
- Point downloadLocation = location.Offset (-size.Width, 0);
- ctx.DrawTextLayout (downloadCountTextLayout, downloadLocation);
-
- packageIdWidth = downloadLocation.X - cellArea.Left - packageIdRightHandPaddingWidth - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
- }
-
- // Package Id.
- // Use the package id and not the package title to prevent a pango crash if the title
- // contains Chinese characters.
- var packageIdTextLayout = new TextLayout ();
- packageIdTextLayout.Font = packageIdTextLayout.Font.WithSize (packageIdFontSize);
- packageIdTextLayout.Markup = packageViewModel.GetIdMarkup ();
- packageIdTextLayout.Trimming = TextTrimming.WordElipsis;
- Size packageIdTextSize = packageIdTextLayout.GetSize ();
- packageIdTextLayout.Width = packageIdWidth;
- ctx.DrawTextLayout (
- packageIdTextLayout,
- cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset,
- cellArea.Top + packageDescriptionPadding.Top);
-
- // Package description.
- var descriptionTextLayout = new TextLayout ();
- descriptionTextLayout.Font = descriptionTextLayout.Font.WithSize (packageDescriptionFontSize);
- descriptionTextLayout.Width = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
- descriptionTextLayout.Height = cellArea.Height - packageIdTextSize.Height - packageDescriptionPadding.VerticalSpacing;
- descriptionTextLayout.Text = packageViewModel.Summary;
- descriptionTextLayout.Trimming = TextTrimming.Word;
-
- ctx.DrawTextLayout (
- descriptionTextLayout,
- cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset,
- cellArea.Top + packageIdTextSize.Height + packageDescriptionPaddingHeight + packageDescriptionPadding.Top);
- }
-
- void UpdateTextColor (Context ctx)
- {
- if (UseStrongSelectionColor && Selected) {
- ctx.SetColor (Styles.CellTextSelectionColor);
- } else {
- ctx.SetColor (Styles.CellTextColor);
- }
- }
-
- void FillCellBackground (Context ctx)
- {
- if (Selected) {
- FillCellBackground (ctx, GetSelectedColor ());
- } else if (IsBackgroundColorFieldSet ()) {
- FillCellBackground (ctx, BackgroundColor);
- }
- }
-
- Color GetSelectedColor ()
- {
- if (UseStrongSelectionColor) {
- return StrongSelectionColor;
- }
- return SelectionColor;
- }
-
- bool IsBackgroundColorFieldSet ()
- {
- return GetValue (HasBackgroundColorField, false);
- }
-
- void FillCellBackground (Context ctx, Color color)
- {
- ctx.Rectangle (BackgroundBounds);
- ctx.SetColor (color);
- ctx.Fill ();
- }
-
- void DrawCheckBox (Context ctx, PackageSearchResultViewModel packageViewModel, Rectangle cellArea)
- {
- CreateCheckboxImages ();
-
- Image image = GetCheckBoxImage (packageViewModel.IsChecked);
- double alpha = GetCheckBoxImageAlpha ();
- ctx.DrawImage (
- image,
- cellArea.Left + checkBoxPadding.Left,
- cellArea.Top + ((cellArea.Height - checkBoxImageSize.Height - 2) / 2),
- alpha);
- }
-
- void CreateCheckboxImages ()
- {
- if (whiteCheckedCheckBoxImage != null)
- return;
-
- var widget = Toolkit.CurrentEngine.GetNativeWidget (ParentWidget);
- var checkbox = new PackageCellViewCheckBox (ParentWidget.ParentWindow.Screen.ScaleFactor);
- checkbox.Container = (Gtk.Widget)widget;
- checkbox.Size = (int)checkBoxImageSize.Width + 1;
-
- // White checkbox.
- whiteUncheckedCheckBoxImage = checkbox.CreateImage ();
- checkbox.Active = true;
- whiteCheckedCheckBoxImage = checkbox.CreateImage ();
-
- // Odd numbered checkbox.
- checkbox.BackgroundColor = BackgroundColor;
- checkedCheckBoxWithBackgroundColorImage = checkbox.CreateImage ();
- checkbox.Active = false;
- uncheckedCheckBoxWithBackgroundColorImage = checkbox.CreateImage ();
-
- // Grey check box.
- checkbox.BackgroundColor = SelectionColor;
- greyUncheckedCheckBoxImage = checkbox.CreateImage ();
- checkbox.Active = true;
- greyCheckedCheckBoxImage = checkbox.CreateImage ();
-
- // Blue check box.
- checkbox.BackgroundColor = StrongSelectionColor;
- blueCheckedCheckBoxImage = checkbox.CreateImage ();
- checkbox.Active = false;
- blueUncheckedCheckBoxImage = checkbox.CreateImage ();
- }
-
- double GetCheckBoxImageAlpha ()
- {
- return GetValue (CheckBoxAlphaField, 1);
- }
-
- Image GetCheckBoxImage (bool checkBoxActive)
- {
- if (Selected && UseStrongSelectionColor && checkBoxActive) {
- return blueCheckedCheckBoxImage;
- } else if (Selected && checkBoxActive) {
- return greyCheckedCheckBoxImage;
- } else if (Selected && UseStrongSelectionColor) {
- return blueUncheckedCheckBoxImage;
- } else if (Selected) {
- return greyUncheckedCheckBoxImage;
- } else if (checkBoxActive && IsBackgroundColorFieldSet ()) {
- return checkedCheckBoxWithBackgroundColorImage;
- } else if (checkBoxActive) {
- return whiteCheckedCheckBoxImage;
- } else if (IsBackgroundColorFieldSet ()) {
- return uncheckedCheckBoxWithBackgroundColorImage;
- } else {
- return whiteUncheckedCheckBoxImage;
- }
- }
-
- void DrawPackageImage (Context ctx, Rectangle cellArea)
- {
- Image image = GetValue (ImageField);
-
- if (image == null) {
- image = defaultPackageImage;
- }
-
- if (Selected)
- image = image.WithStyles ("sel");
-
- if (PackageImageNeedsResizing (image)) {
- Point imageLocation = GetPackageImageLocation (maxPackageImageSize, cellArea);
- ctx.DrawImage (
- image,
- cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X,
- Math.Round( cellArea.Top + packageImagePadding.Top + imageLocation.Y),
- maxPackageImageSize.Width,
- maxPackageImageSize.Height);
- } else {
- Point imageLocation = GetPackageImageLocation (image.Size, cellArea);
- ctx.DrawImage (
- image,
- cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X,
- Math.Round (cellArea.Top + packageImagePadding.Top + imageLocation.Y));
- }
- }
-
- bool PackageImageNeedsResizing (Image image)
- {
- return (image.Width > maxPackageImageSize.Width) || (image.Height > maxPackageImageSize.Height);
- }
-
- Point GetPackageImageLocation (Size imageSize, Rectangle cellArea)
- {
- double width = (packageImageAreaWidth - imageSize.Width) / 2;
- double height = (cellArea.Height - imageSize.Height - packageImagePadding.Bottom) / 2;
- return new Point (width, height);
- }
-
+//
+// PackageCellView.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 MonoDevelop.Core;
+using Xwt;
+using Xwt.Drawing;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal class ManagePackagesCellView : CanvasCellView
+ {
+ int packageIdFontSize;
+ int packageDescriptionFontSize;
+
+ public ManagePackagesCellView ()
+ {
+ CellWidth = 260;
+
+ BackgroundColor = Styles.CellBackgroundColor;
+ StrongSelectionColor = Styles.CellStrongSelectionColor;
+ SelectionColor = Styles.CellSelectionColor;
+
+ UseStrongSelectionColor = true;
+
+ if (Platform.IsWindows) {
+ packageIdFontSize = 10;
+ packageDescriptionFontSize = 9;
+ } else {
+ packageIdFontSize = 12;
+ packageDescriptionFontSize = 11;
+ }
+ }
+
+ public IDataField<ManagePackagesSearchResultViewModel> PackageField { get; set; }
+ public IDataField<Image> ImageField { get; set; }
+ public IDataField<bool> HasBackgroundColorField { get; set; }
+ public IDataField<double> CheckBoxAlphaField { get; set; }
+
+ public double CellWidth { get; set; }
+
+ public Color BackgroundColor { get; set; }
+ public Color StrongSelectionColor { get; set; }
+ public Color SelectionColor { get; set; }
+
+ public bool UseStrongSelectionColor { get; set; }
+
+ public event EventHandler<ManagePackagesCellViewEventArgs> PackageChecked;
+
+ protected override void OnDraw (Context ctx, Rectangle cellArea)
+ {
+ ManagePackagesSearchResultViewModel packageViewModel = GetValue (PackageField);
+ if (packageViewModel == null) {
+ return;
+ }
+
+ FillCellBackground (ctx);
+ UpdateTextColor (ctx);
+
+ DrawCheckBox (ctx, packageViewModel, cellArea);
+ DrawPackageImage (ctx, cellArea);
+
+ double packageIdWidth = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
+
+ // Package download count.
+ if (packageViewModel.HasDownloadCount) {
+ var downloadCountTextLayout = new TextLayout ();
+ downloadCountTextLayout.Text = packageViewModel.GetDownloadCountOrVersionDisplayText ();
+ Size size = downloadCountTextLayout.GetSize ();
+ Point location = new Point (cellArea.Right - packageDescriptionPadding.Right, cellArea.Top + packageDescriptionPadding.Top);
+ Point downloadLocation = location.Offset (-size.Width, 0);
+ ctx.DrawTextLayout (downloadCountTextLayout, downloadLocation);
+
+ packageIdWidth = downloadLocation.X - cellArea.Left - packageIdRightHandPaddingWidth - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
+ }
+
+ // Package Id.
+ // Use the package id and not the package title to prevent a pango crash if the title
+ // contains Chinese characters.
+ var packageIdTextLayout = new TextLayout ();
+ packageIdTextLayout.Font = packageIdTextLayout.Font.WithSize (packageIdFontSize);
+ packageIdTextLayout.Markup = packageViewModel.GetIdMarkup ();
+ packageIdTextLayout.Trimming = TextTrimming.WordElipsis;
+ Size packageIdTextSize = packageIdTextLayout.GetSize ();
+ packageIdTextLayout.Width = packageIdWidth;
+ ctx.DrawTextLayout (
+ packageIdTextLayout,
+ cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset,
+ cellArea.Top + packageDescriptionPadding.Top);
+
+ // Package description.
+ var descriptionTextLayout = new TextLayout ();
+ descriptionTextLayout.Font = descriptionTextLayout.Font.WithSize (packageDescriptionFontSize);
+ descriptionTextLayout.Width = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
+ descriptionTextLayout.Height = cellArea.Height - packageIdTextSize.Height - packageDescriptionPadding.VerticalSpacing;
+ descriptionTextLayout.Text = packageViewModel.Summary;
+ descriptionTextLayout.Trimming = TextTrimming.Word;
+
+ ctx.DrawTextLayout (
+ descriptionTextLayout,
+ cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset,
+ cellArea.Top + packageIdTextSize.Height + packageDescriptionPaddingHeight + packageDescriptionPadding.Top);
+ }
+
+ void UpdateTextColor (Context ctx)
+ {
+ if (Selected) {
+ ctx.SetColor (Styles.CellTextSelectionColor);
+ } else {
+ ctx.SetColor (Styles.CellTextColor);
+ }
+ }
+
+ void FillCellBackground (Context ctx)
+ {
+ if (Selected) {
+ FillCellBackground (ctx, GetSelectedColor ());
+ } else if (IsBackgroundColorFieldSet ()) {
+ FillCellBackground (ctx, BackgroundColor);
+ }
+ }
+
+ Color GetSelectedColor ()
+ {
+ if (UseStrongSelectionColor) {
+ return StrongSelectionColor;
+ }
+ return SelectionColor;
+ }
+
+ bool IsBackgroundColorFieldSet ()
+ {
+ return GetValue (HasBackgroundColorField, false);
+ }
+
+ void FillCellBackground (Context ctx, Color color)
+ {
+ ctx.Rectangle (BackgroundBounds);
+ ctx.SetColor (color);
+ ctx.Fill ();
+ }
+
+ void DrawCheckBox (Context ctx, ManagePackagesSearchResultViewModel packageViewModel, Rectangle cellArea)
+ {
+ CreateCheckboxImages ();
+
+ Image image = GetCheckBoxImage (packageViewModel.IsChecked);
+ double alpha = GetCheckBoxImageAlpha ();
+ ctx.DrawImage (
+ image,
+ cellArea.Left + checkBoxPadding.Left,
+ cellArea.Top + ((cellArea.Height - checkBoxImageSize.Height - 2) / 2),
+ alpha);
+ }
+
+ void CreateCheckboxImages ()
+ {
+ if (whiteCheckedCheckBoxImage != null)
+ return;
+
+ var widget = Toolkit.CurrentEngine.GetNativeWidget (ParentWidget);
+ var checkbox = new ManagePackagesCellViewCheckBox (ParentWidget.ParentWindow.Screen.ScaleFactor);
+ checkbox.Container = (Gtk.Widget)widget;
+ checkbox.Size = (int)checkBoxImageSize.Width + 1;
+
+ // White checkbox.
+ whiteUncheckedCheckBoxImage = checkbox.CreateImage ();
+ checkbox.Active = true;
+ whiteCheckedCheckBoxImage = checkbox.CreateImage ();
+
+ // Odd numbered checkbox.
+ checkbox.BackgroundColor = BackgroundColor;
+ checkedCheckBoxWithBackgroundColorImage = checkbox.CreateImage ();
+ checkbox.Active = false;
+ uncheckedCheckBoxWithBackgroundColorImage = checkbox.CreateImage ();
+
+ // Grey check box.
+ checkbox.BackgroundColor = SelectionColor;
+ greyUncheckedCheckBoxImage = checkbox.CreateImage ();
+ checkbox.Active = true;
+ greyCheckedCheckBoxImage = checkbox.CreateImage ();
+
+ // Blue check box.
+ checkbox.BackgroundColor = StrongSelectionColor;
+ blueCheckedCheckBoxImage = checkbox.CreateImage ();
+ checkbox.Active = false;
+ blueUncheckedCheckBoxImage = checkbox.CreateImage ();
+ }
+
+ double GetCheckBoxImageAlpha ()
+ {
+ return GetValue (CheckBoxAlphaField, 1);
+ }
+
+ Image GetCheckBoxImage (bool checkBoxActive)
+ {
+ if (Selected && UseStrongSelectionColor && checkBoxActive) {
+ return blueCheckedCheckBoxImage;
+ } else if (Selected && checkBoxActive) {
+ return greyCheckedCheckBoxImage;
+ } else if (Selected && UseStrongSelectionColor) {
+ return blueUncheckedCheckBoxImage;
+ } else if (Selected) {
+ return greyUncheckedCheckBoxImage;
+ } else if (checkBoxActive && IsBackgroundColorFieldSet ()) {
+ return checkedCheckBoxWithBackgroundColorImage;
+ } else if (checkBoxActive) {
+ return whiteCheckedCheckBoxImage;
+ } else if (IsBackgroundColorFieldSet ()) {
+ return uncheckedCheckBoxWithBackgroundColorImage;
+ } else {
+ return whiteUncheckedCheckBoxImage;
+ }
+ }
+
+ void DrawPackageImage (Context ctx, Rectangle cellArea)
+ {
+ Image image = GetValue (ImageField);
+
+ if (image == null) {
+ image = defaultPackageImage;
+ }
+
+ if (Selected)
+ image = image.WithStyles ("sel");
+
+ if (PackageImageNeedsResizing (image)) {
+ Point imageLocation = GetPackageImageLocation (maxPackageImageSize, cellArea);
+ ctx.DrawImage (
+ image,
+ cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X,
+ Math.Round( cellArea.Top + packageImagePadding.Top + imageLocation.Y),
+ maxPackageImageSize.Width,
+ maxPackageImageSize.Height);
+ } else {
+ Point imageLocation = GetPackageImageLocation (image.Size, cellArea);
+ ctx.DrawImage (
+ image,
+ cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X,
+ Math.Round (cellArea.Top + packageImagePadding.Top + imageLocation.Y));
+ }
+ }
+
+ bool PackageImageNeedsResizing (Image image)
+ {
+ return (image.Width > maxPackageImageSize.Width) || (image.Height > maxPackageImageSize.Height);
+ }
+
+ Point GetPackageImageLocation (Size imageSize, Rectangle cellArea)
+ {
+ double width = (packageImageAreaWidth - imageSize.Width) / 2;
+ double height = (cellArea.Height - imageSize.Height - packageImagePadding.Bottom) / 2;
+ return new Point (width, height);
+ }
+
protected override Size OnGetRequiredSize (SizeConstraint widthConstraint)
- {
- var layout = new TextLayout ();
- layout.Text = "W";
- layout.Font = layout.Font.WithSize (packageDescriptionFontSize);
- Size size = layout.GetSize ();
- return new Size (CellWidth, size.Height * linesDisplayedCount + packageDescriptionPaddingHeight + packageDescriptionPadding.VerticalSpacing);
- }
-
- protected override void OnButtonPressed (ButtonEventArgs args)
- {
- PackageSearchResultViewModel packageViewModel = GetValue (PackageField);
- if (packageViewModel == null) {
- base.OnButtonPressed (args);
- return;
- }
-
- double x = args.X - Bounds.X;
- double y = args.Y - Bounds.Y;
-
- if (checkBoxImageClickableRectangle.Contains (x, y)) {
- packageViewModel.IsChecked = !packageViewModel.IsChecked;
- OnPackageChecked (packageViewModel);
- }
- }
-
- void OnPackageChecked (PackageSearchResultViewModel packageViewModel)
- {
- if (PackageChecked != null) {
- PackageChecked (this, new PackageCellViewEventArgs (packageViewModel));
- }
- }
-
- const int packageDescriptionPaddingHeight = 5;
- const int packageIdRightHandPaddingWidth = 5;
- const int linesDisplayedCount = 4;
-
- const int checkBoxAreaWidth = 36;
- const int packageImageAreaWidth = 54;
- const int packageDescriptionLeftOffset = checkBoxAreaWidth + packageImageAreaWidth + 8;
-
- WidgetSpacing packageDescriptionPadding = new WidgetSpacing (5, 5, 5, 10);
- WidgetSpacing packageImagePadding = new WidgetSpacing (0, 0, 0, 5);
- WidgetSpacing checkBoxPadding = new WidgetSpacing (10, 0, 0, 10);
-
- Size maxPackageImageSize = new Size (48, 48);
- Size checkBoxImageSize = new Size (16, 16);
- Rectangle checkBoxImageClickableRectangle = new Rectangle (0, 10, 40, 50);
-
- Image whiteCheckedCheckBoxImage;
- Image whiteUncheckedCheckBoxImage;
- Image greyCheckedCheckBoxImage;
- Image greyUncheckedCheckBoxImage;
- Image blueCheckedCheckBoxImage;
- Image blueUncheckedCheckBoxImage;
- Image checkedCheckBoxWithBackgroundColorImage;
- Image uncheckedCheckBoxWithBackgroundColorImage;
-
- static readonly Image defaultPackageImage = Image.FromResource (typeof(PackageCellView), "package-48.png");
- }
-}
-
+ {
+ var layout = new TextLayout ();
+ layout.Text = "W";
+ layout.Font = layout.Font.WithSize (packageDescriptionFontSize);
+ Size size = layout.GetSize ();
+ return new Size (CellWidth, size.Height * linesDisplayedCount + packageDescriptionPaddingHeight + packageDescriptionPadding.VerticalSpacing);
+ }
+
+ protected override void OnButtonPressed (ButtonEventArgs args)
+ {
+ ManagePackagesSearchResultViewModel packageViewModel = GetValue (PackageField);
+ if (packageViewModel == null) {
+ base.OnButtonPressed (args);
+ return;
+ }
+
+ double x = args.X - Bounds.X;
+ double y = args.Y - Bounds.Y;
+
+ if (checkBoxImageClickableRectangle.Contains (x, y)) {
+ packageViewModel.IsChecked = !packageViewModel.IsChecked;
+ OnPackageChecked (packageViewModel);
+ }
+ }
+
+ void OnPackageChecked (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ if (PackageChecked != null) {
+ PackageChecked (this, new ManagePackagesCellViewEventArgs (packageViewModel));
+ }
+ }
+
+ const int packageDescriptionPaddingHeight = 5;
+ const int packageIdRightHandPaddingWidth = 5;
+ const int linesDisplayedCount = 4;
+
+ const int checkBoxAreaWidth = 36;
+ const int packageImageAreaWidth = 54;
+ const int packageDescriptionLeftOffset = checkBoxAreaWidth + packageImageAreaWidth + 8;
+
+ WidgetSpacing packageDescriptionPadding = new WidgetSpacing (5, 5, 5, 10);
+ WidgetSpacing packageImagePadding = new WidgetSpacing (0, 0, 0, 5);
+ WidgetSpacing checkBoxPadding = new WidgetSpacing (10, 0, 0, 10);
+
+ Size maxPackageImageSize = new Size (48, 48);
+ Size checkBoxImageSize = new Size (16, 16);
+ Rectangle checkBoxImageClickableRectangle = new Rectangle (0, 10, 40, 50);
+
+ Image whiteCheckedCheckBoxImage;
+ Image whiteUncheckedCheckBoxImage;
+ Image greyCheckedCheckBoxImage;
+ Image greyUncheckedCheckBoxImage;
+ Image blueCheckedCheckBoxImage;
+ Image blueUncheckedCheckBoxImage;
+ Image checkedCheckBoxWithBackgroundColorImage;
+ Image uncheckedCheckBoxWithBackgroundColorImage;
+
+ static readonly Image defaultPackageImage = Image.FromResource (typeof(ManagePackagesCellView), "package-48.png");
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewCheckBox.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewCheckBox.cs
index 5e0277c98d..c137669b79 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewCheckBox.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewCheckBox.cs
@@ -1,49 +1,49 @@
-//
-// PackageCellViewCheckBox.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.
-
+//
+// ManagePackagesCellViewCheckBox.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 MonoDevelop.Components;
using Gtk;
namespace MonoDevelop.PackageManagement
{
- internal class PackageCellViewCheckBox
+ internal class ManagePackagesCellViewCheckBox
{
static int indicatorSize;
static int indicatorSpacing;
double scaleFactor;
- static PackageCellViewCheckBox ()
+ static ManagePackagesCellViewCheckBox ()
{
var cb = new Gtk.CheckButton ();
indicatorSize = (int) cb.StyleGetProperty ("indicator-size");
indicatorSpacing = (int) cb.StyleGetProperty ("indicator-spacing");
}
- public PackageCellViewCheckBox (double scaleFactor)
+ public ManagePackagesCellViewCheckBox (double scaleFactor)
{
this.scaleFactor = scaleFactor;
Size = indicatorSize;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewEventArgs.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewEventArgs.cs
index 20e7920ec9..ae50585266 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewEventArgs.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewEventArgs.cs
@@ -1,41 +1,40 @@
-//
-// PackageCellViewEventArgs.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;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class PackageCellViewEventArgs : EventArgs
- {
- public PackageCellViewEventArgs (PackageSearchResultViewModel packageViewModel)
- {
- PackageViewModel = packageViewModel;
- }
-
- public PackageSearchResultViewModel PackageViewModel { get; private set; }
- }
-}
-
+//
+// PackageCellViewEventArgs.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;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal class ManagePackagesCellViewEventArgs : EventArgs
+ {
+ public ManagePackagesCellViewEventArgs (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ PackageViewModel = packageViewModel;
+ }
+
+ public ManagePackagesSearchResultViewModel PackageViewModel { get; }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.UI.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs
index eda980a15c..c47a39aaf4 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.UI.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs
@@ -1,377 +1,476 @@
-//
-// AddPackagesDialog.UI.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 ExtendedTitleBarDialog = MonoDevelop.Components.ExtendedTitleBarDialog;
-using Mono.Unix;
-using MonoDevelop.Core;
-using MonoDevelop.Ide;
-using Xwt;
-using Xwt.Drawing;
-
-namespace MonoDevelop.PackageManagement
-{
- internal partial class AddPackagesDialog : ExtendedTitleBarDialog
- {
- ComboBox packageSourceComboBox;
- SearchTextEntry packageSearchEntry;
- ListView packagesListView;
- VBox packageInfoVBox;
- Label packageNameLabel;
- LinkLabel packageIdLink;
- Label packageDescription;
- Label packageAuthor;
- Label packagePublishedDate;
- Label packageDownloads;
- LinkLabel packageLicenseLink;
- LinkLabel packageProjectPageLink;
- Label packageDependenciesList;
- HBox packageDependenciesHBox;
- HBox packageDependenciesListHBox;
- Label packageDependenciesNoneLabel;
- CheckBox showPrereleaseCheckBox;
- Label packageId;
- Button addPackagesButton;
- FrameBox loadingSpinnerFrame;
- HBox errorMessageHBox;
- Label errorMessageLabel;
- Label loadingSpinnerLabel;
- FrameBox noPackagesFoundFrame;
- ComboBox packageVersionComboBox;
- HBox packageVersionsHBox;
- int packageInfoFontSize = 11;
-
- void Build ()
- {
- Title = Catalog.GetString ("Add Packages");
- Width = 820;
- Height = 520;
- Padding = new WidgetSpacing ();
-
- if (Platform.IsWindows) {
- packageInfoFontSize = 9;
- }
-
- // Top part of dialog:
- // Package sources and search.
- var topHBox = new HBox ();
- topHBox.Margin = new WidgetSpacing (8, 5, 6, 5);
-
- packageSourceComboBox = new ComboBox ();
- packageSourceComboBox.Name = "packageSourceComboBox";
- packageSourceComboBox.MinWidth = 200;
- topHBox.PackStart (packageSourceComboBox);
-
- packageSearchEntry = new SearchTextEntry ();
- packageSearchEntry.Name = "addPackagesDialogSearchEntry";
- packageSearchEntry.WidthRequest = 187;
- topHBox.PackEnd (packageSearchEntry);
-
- this.HeaderContent = topHBox;
-
- // Middle of dialog:
- // Packages and package information.
- var mainVBox = new VBox ();
- Content = mainVBox;
-
- var middleHBox = new HBox ();
- middleHBox.Spacing = 0;
- var middleFrame = new FrameBox ();
- middleFrame.Content = middleHBox;
- middleFrame.BorderWidth = new WidgetSpacing (0, 0, 0, 1);
- middleFrame.BorderColor = Styles.LineBorderColor;
- mainVBox.PackStart (middleFrame, true, true);
-
- // Error information.
- var packagesListVBox = new VBox ();
- packagesListVBox.Spacing = 0;
- errorMessageHBox = new HBox ();
- errorMessageHBox.Margin = new WidgetSpacing ();
- errorMessageHBox.BackgroundColor = Styles.ErrorBackgroundColor;
- errorMessageHBox.Visible = false;
- var errorImage = new ImageView ();
- errorImage.Margin = new WidgetSpacing (10, 0, 0, 0);
- errorImage.Image = ImageService.GetIcon (MonoDevelop.Ide.Gui.Stock.Warning, Gtk.IconSize.Menu);
- errorImage.HorizontalPlacement = WidgetPlacement.End;
- errorMessageHBox.PackStart (errorImage);
- errorMessageLabel = new Label ();
- errorMessageLabel.TextColor = Styles.ErrorForegroundColor;
- errorMessageLabel.Margin = new WidgetSpacing (5, 5, 5, 5);
- errorMessageLabel.Wrap = WrapMode.Word;
- errorMessageHBox.PackStart (errorMessageLabel, true);
- packagesListVBox.PackStart (errorMessageHBox);
-
- // Packages list.
- middleHBox.PackStart (packagesListVBox, true, true);
- packagesListView = new ListView ();
- packagesListView.BorderVisible = false;
- packagesListView.HeadersVisible = false;
- packagesListVBox.PackStart (packagesListView, true, true);
-
- // Loading spinner.
- var loadingSpinnerHBox = new HBox ();
- loadingSpinnerHBox.HorizontalPlacement = WidgetPlacement.Center;
- var loadingSpinner = new Spinner ();
- loadingSpinner.Animate = true;
- loadingSpinner.MinWidth = 20;
- loadingSpinnerHBox.PackStart (loadingSpinner);
-
- loadingSpinnerLabel = new Label ();
- loadingSpinnerLabel.Text = Catalog.GetString ("Loading package list...");
- loadingSpinnerHBox.PackEnd (loadingSpinnerLabel);
-
- loadingSpinnerFrame = new FrameBox ();
- loadingSpinnerFrame.Visible = false;
- loadingSpinnerFrame.BackgroundColor = Styles.BackgroundColor;
- loadingSpinnerFrame.Content = loadingSpinnerHBox;
- loadingSpinnerFrame.BorderWidth = new WidgetSpacing ();
- packagesListVBox.PackStart (loadingSpinnerFrame, true, true);
-
- // No packages found label.
- var noPackagesFoundHBox = new HBox ();
- noPackagesFoundHBox.HorizontalPlacement = WidgetPlacement.Center;
-
- var noPackagesFoundLabel = new Label ();
- noPackagesFoundLabel.Text = Catalog.GetString ("No matching packages found.");
- noPackagesFoundHBox.PackEnd (noPackagesFoundLabel);
-
- noPackagesFoundFrame = new FrameBox ();
- noPackagesFoundFrame.Visible = false;
- noPackagesFoundFrame.BackgroundColor = Styles.BackgroundColor;
- noPackagesFoundFrame.Content = noPackagesFoundHBox;
- noPackagesFoundFrame.BorderWidth = new WidgetSpacing ();
- packagesListVBox.PackStart (noPackagesFoundFrame, true, true);
-
- // Package information
- packageInfoVBox = new VBox ();
- var packageInfoFrame = new FrameBox ();
- packageInfoFrame.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoFrame.BorderWidth = new WidgetSpacing ();
- packageInfoFrame.Content = packageInfoVBox;
- packageInfoVBox.Margin = new WidgetSpacing (15, 12, 15, 12);
- var packageInfoContainerVBox = new VBox ();
- packageInfoContainerVBox.WidthRequest = 240;
- packageInfoContainerVBox.PackStart (packageInfoFrame, true, true);
-
- var packageInfoScrollView = new ScrollView ();
- packageInfoScrollView.BorderVisible = false;
- packageInfoScrollView.HorizontalScrollPolicy = ScrollPolicy.Never;
- packageInfoScrollView.Content = packageInfoContainerVBox;
- packageInfoScrollView.BackgroundColor = Styles.PackageInfoBackgroundColor;
- var packageInfoScrollViewFrame = new FrameBox ();
- packageInfoScrollViewFrame.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoScrollViewFrame.BorderWidth = new WidgetSpacing (1, 0, 0, 0);
- packageInfoScrollViewFrame.BorderColor = Styles.LineBorderColor;
- packageInfoScrollViewFrame.Content = packageInfoScrollView;
-
- // Package name and version.
- var packageNameHBox = new HBox ();
- packageInfoVBox.PackStart (packageNameHBox);
-
- packageNameLabel = new Label ();
- packageNameLabel.Ellipsize = EllipsizeMode.End;
- Font packageInfoSmallFont = packageNameLabel.Font.WithSize (packageInfoFontSize);
- Font packageInfoBoldFont = packageInfoSmallFont.WithWeight (FontWeight.Bold);
- packageNameLabel.Font = packageInfoSmallFont;
- packageNameHBox.PackStart (packageNameLabel, true);
-
- // Package description.
- packageDescription = new Label ();
- packageDescription.Wrap = WrapMode.Word;
- packageDescription.Font = packageNameLabel.Font.WithSize (packageInfoFontSize);
- packageDescription.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoVBox.PackStart (packageDescription);
-
- // Package id.
- var packageIdHBox = new HBox ();
- packageIdHBox.MarginTop = 7;
- packageInfoVBox.PackStart (packageIdHBox);
-
- var packageIdLabel = new Label ();
+//
+// ManagePackagesDialog.UI.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 ExtendedTitleBarDialog = MonoDevelop.Components.ExtendedTitleBarDialog;
+using InformationPopoverWidget = MonoDevelop.Components.InformationPopoverWidget;
+using System;
+using MonoDevelop.Core;
+using MonoDevelop.Ide;
+using Xwt;
+using Xwt.Drawing;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal partial class ManagePackagesDialog : ExtendedTitleBarDialog
+ {
+ ComboBox packageSourceComboBox;
+ SearchTextEntry packageSearchEntry;
+ ListView packagesListView;
+ VBox packageInfoVBox;
+ HBox packageNameHBox;
+ Label packageNameLabel;
+ LinkLabel packageIdLink;
+ Label packageDescription;
+ Label packageAuthor;
+ Label packagePublishedDate;
+ Label packageDownloads;
+ LinkLabel packageLicenseLink;
+ LinkLabel packageProjectPageLink;
+ Label packageDependenciesList;
+ HBox packageDependenciesHBox;
+ HBox packageDependenciesListHBox;
+ Label packageDependenciesNoneLabel;
+ CheckBox showPrereleaseCheckBox;
+ Label packageId;
+ Button addPackagesButton;
+ FrameBox loadingSpinnerFrame;
+ HBox errorMessageHBox;
+ Label errorMessageLabel;
+ Label loadingSpinnerLabel;
+ FrameBox noPackagesFoundFrame;
+ ComboBox packageVersionComboBox;
+ HBox packageVersionsHBox;
+ Label packageVersionsLabel;
+ Label browseLabel;
+ Label installedLabel;
+ Label updatesLabel;
+ Label consolidateLabel;
+ VBox projectsListViewVBox;
+ Label projectsListViewLabel;
+ ListView projectsListView;
+ HBox currentPackageVersionHBox;
+ Label currentPackageVersionLabel;
+ Label currentPackageVersion;
+ InformationPopoverWidget currentPackageVersionInfoPopoverWidget;
+ Button closeButton;
+ int packageInfoFontSize = 11;
+
+ void Build ()
+ {
+ Title = GettextCatalog.GetString ("Manage NuGet Packages – Solution");
+ Width = 840;
+ Height = 528;
+ Padding = new WidgetSpacing ();
+
+ if (Platform.IsWindows) {
+ packageInfoFontSize = 9;
+ }
+
+ // Top part of dialog:
+ // Package sources and search.
+ var topHBox = new HBox ();
+ topHBox.Margin = new WidgetSpacing (8, 5, 6, 5);
+
+ packageSourceComboBox = new ComboBox ();
+ packageSourceComboBox.Name = "packageSourceComboBox";
+ packageSourceComboBox.MinWidth = 200;
+ topHBox.PackStart (packageSourceComboBox);
+
+ int tabLabelMinWidth = 60;
+ browseLabel = new Label ();
+ browseLabel.Text = GettextCatalog.GetString ("Browse");
+ browseLabel.Tag = browseLabel.Text;
+ browseLabel.MinWidth = tabLabelMinWidth;
+ browseLabel.MarginLeft = 10;
+ topHBox.PackStart (browseLabel);
+
+ installedLabel = new Label ();
+ installedLabel.Text = GettextCatalog.GetString ("Installed");
+ installedLabel.Tag = installedLabel.Text;
+ installedLabel.MinWidth = tabLabelMinWidth;
+ topHBox.PackStart (installedLabel);
+
+ updatesLabel = new Label ();
+ updatesLabel.Text = GettextCatalog.GetString ("Updates");
+ updatesLabel.Tag = updatesLabel.Text;
+ updatesLabel.MinWidth = tabLabelMinWidth;
+ topHBox.PackStart (updatesLabel);
+
+ consolidateLabel = new Label ();
+ consolidateLabel.Text = GettextCatalog.GetString ("Consolidate");
+ consolidateLabel.Tag = consolidateLabel.Text;
+ consolidateLabel.MinWidth = tabLabelMinWidth;
+ topHBox.PackStart (consolidateLabel);
+
+ packageSearchEntry = new SearchTextEntry ();
+ packageSearchEntry.Name = "managePackagesDialogSearchEntry";
+ packageSearchEntry.WidthRequest = 187;
+ topHBox.PackEnd (packageSearchEntry);
+
+ this.HeaderContent = topHBox;
+
+ // Middle of dialog:
+ // Packages and package information.
+ var mainVBox = new VBox ();
+ Content = mainVBox;
+
+ var middleHBox = new HBox ();
+ middleHBox.Spacing = 0;
+ var middleFrame = new FrameBox ();
+ middleFrame.Content = middleHBox;
+ middleFrame.BorderWidth = new WidgetSpacing (0, 0, 0, 1);
+ middleFrame.BorderColor = Styles.LineBorderColor;
+ mainVBox.PackStart (middleFrame, true, true);
+
+ // Error information.
+ var packagesListVBox = new VBox ();
+ packagesListVBox.Spacing = 0;
+ errorMessageHBox = new HBox ();
+ errorMessageHBox.Margin = new WidgetSpacing ();
+ errorMessageHBox.BackgroundColor = Styles.ErrorBackgroundColor;
+ errorMessageHBox.Visible = false;
+ var errorImage = new ImageView ();
+ errorImage.Margin = new WidgetSpacing (10, 0, 0, 0);
+ errorImage.Image = ImageService.GetIcon (MonoDevelop.Ide.Gui.Stock.Warning, Gtk.IconSize.Menu);
+ errorImage.HorizontalPlacement = WidgetPlacement.End;
+ errorMessageHBox.PackStart (errorImage);
+ errorMessageLabel = new Label ();
+ errorMessageLabel.TextColor = Styles.ErrorForegroundColor;
+ errorMessageLabel.Margin = new WidgetSpacing (5, 5, 5, 5);
+ errorMessageLabel.Wrap = WrapMode.Word;
+ errorMessageHBox.PackStart (errorMessageLabel, true);
+ packagesListVBox.PackStart (errorMessageHBox);
+
+ // Packages list.
+ middleHBox.PackStart (packagesListVBox, true, true);
+ packagesListView = new ListView ();
+ packagesListView.BorderVisible = false;
+ packagesListView.HeadersVisible = false;
+ packagesListVBox.PackStart (packagesListView, true, true);
+
+ // Loading spinner.
+ var loadingSpinnerHBox = new HBox ();
+ loadingSpinnerHBox.HorizontalPlacement = WidgetPlacement.Center;
+ var loadingSpinner = new Spinner ();
+ loadingSpinner.Animate = true;
+ loadingSpinner.MinWidth = 20;
+ loadingSpinnerHBox.PackStart (loadingSpinner);
+
+ loadingSpinnerLabel = new Label ();
+ loadingSpinnerLabel.Text = GettextCatalog.GetString ("Loading package list...");
+ loadingSpinnerHBox.PackEnd (loadingSpinnerLabel);
+
+ loadingSpinnerFrame = new FrameBox ();
+ loadingSpinnerFrame.Visible = false;
+ loadingSpinnerFrame.BackgroundColor = Styles.BackgroundColor;
+ loadingSpinnerFrame.Content = loadingSpinnerHBox;
+ loadingSpinnerFrame.BorderWidth = new WidgetSpacing ();
+ packagesListVBox.PackStart (loadingSpinnerFrame, true, true);
+
+ // No packages found label.
+ var noPackagesFoundHBox = new HBox ();
+ noPackagesFoundHBox.HorizontalPlacement = WidgetPlacement.Center;
+
+ var noPackagesFoundLabel = new Label ();
+ noPackagesFoundLabel.Text = GettextCatalog.GetString ("No matching packages found.");
+ noPackagesFoundHBox.PackEnd (noPackagesFoundLabel);
+
+ noPackagesFoundFrame = new FrameBox ();
+ noPackagesFoundFrame.Visible = false;
+ noPackagesFoundFrame.BackgroundColor = Styles.BackgroundColor;
+ noPackagesFoundFrame.Content = noPackagesFoundHBox;
+ noPackagesFoundFrame.BorderWidth = new WidgetSpacing ();
+ packagesListVBox.PackStart (noPackagesFoundFrame, true, true);
+
+ // Package information
+ packageInfoVBox = new VBox ();
+ var packageInfoFrame = new FrameBox ();
+ packageInfoFrame.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ packageInfoFrame.BorderWidth = new WidgetSpacing ();
+ packageInfoFrame.Content = packageInfoVBox;
+ packageInfoVBox.Margin = new WidgetSpacing (15, 12, 15, 12);
+ var packageInfoContainerVBox = new VBox ();
+ packageInfoContainerVBox.WidthRequest = 328;
+ packageInfoContainerVBox.PackStart (packageInfoFrame, true, true);
+
+ var packageInfoScrollView = new ScrollView ();
+ packageInfoScrollView.BorderVisible = false;
+ packageInfoScrollView.HorizontalScrollPolicy = ScrollPolicy.Never;
+ packageInfoScrollView.Content = packageInfoContainerVBox;
+ packageInfoScrollView.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ var packageInfoScrollViewFrame = new FrameBox ();
+ packageInfoScrollViewFrame.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ packageInfoScrollViewFrame.BorderWidth = new WidgetSpacing (1, 0, 0, 0);
+ packageInfoScrollViewFrame.BorderColor = Styles.LineBorderColor;
+ packageInfoScrollViewFrame.Content = packageInfoScrollView;
+
+ // Package name and version.
+ packageNameHBox = new HBox ();
+ packageInfoVBox.PackStart (packageNameHBox);
+
+ packageNameLabel = new Label ();
+ packageNameLabel.Ellipsize = EllipsizeMode.End;
+ Font packageInfoSmallFont = packageNameLabel.Font.WithSize (packageInfoFontSize);
+ Font packageInfoBoldFont = packageInfoSmallFont.WithWeight (FontWeight.Bold);
+ packageNameLabel.Font = packageInfoSmallFont;
+ packageNameHBox.PackStart (packageNameLabel, true);
+
+ // Projects list view label.
+ projectsListViewLabel = new Label ();
+ projectsListViewLabel.Wrap = WrapMode.Word;
+ projectsListViewLabel.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ packageInfoVBox.PackStart (projectsListViewLabel);
+
+ // Projects list view.
+ projectsListViewVBox = new VBox ();
+ projectsListViewVBox.Margin = new WidgetSpacing ();
+ packageInfoVBox.PackStart (projectsListViewVBox, true, true);
+
+ // Package description.
+ packageDescription = new Label ();
+ packageDescription.Wrap = WrapMode.Word;
+ packageDescription.Font = packageNameLabel.Font.WithSize (packageInfoFontSize);
+ packageDescription.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ packageInfoVBox.PackStart (packageDescription);
+
+ // Package id.
+ var packageIdHBox = new HBox ();
+ packageIdHBox.MarginTop = 7;
+ packageInfoVBox.PackStart (packageIdHBox);
+
+ var packageIdLabel = new Label ();
packageIdLabel.Font = packageInfoBoldFont;
- packageIdLabel.Text = Catalog.GetString ("Id");
- packageIdHBox.PackStart (packageIdLabel);
-
- packageId = new Label ();
- packageId.Ellipsize = EllipsizeMode.End;
- packageId.TextAlignment = Alignment.End;
- packageId.Font = packageInfoSmallFont;
- packageIdLink = new LinkLabel ();
- packageIdLink.Ellipsize = EllipsizeMode.End;
- packageIdLink.TextAlignment = Alignment.End;
- packageIdLink.Font = packageInfoSmallFont;
- packageIdHBox.PackEnd (packageIdLink, true);
- packageIdHBox.PackEnd (packageId, true);
-
- // Package author
- var packageAuthorHBox = new HBox ();
- packageInfoVBox.PackStart (packageAuthorHBox);
-
- var packageAuthorLabel = new Label ();
- packageAuthorLabel.Text = Catalog.GetString ("Author");
- packageAuthorLabel.Font = packageInfoBoldFont;
- packageAuthorHBox.PackStart (packageAuthorLabel);
-
- packageAuthor = new Label ();
- packageAuthor.TextAlignment = Alignment.End;
- packageAuthor.Ellipsize = EllipsizeMode.End;
- packageAuthor.Font = packageInfoSmallFont;
- packageAuthorHBox.PackEnd (packageAuthor, true);
-
- // Package published
- var packagePublishedHBox = new HBox ();
- packageInfoVBox.PackStart (packagePublishedHBox);
-
- var packagePublishedLabel = new Label ();
- packagePublishedLabel.Text = Catalog.GetString ("Published");
- packagePublishedLabel.Font = packageInfoBoldFont;
- packagePublishedHBox.PackStart (packagePublishedLabel);
-
- packagePublishedDate = new Label ();
- packagePublishedDate.Font = packageInfoSmallFont;
- packagePublishedHBox.PackEnd (packagePublishedDate);
-
- // Package downloads
- var packageDownloadsHBox = new HBox ();
- packageInfoVBox.PackStart (packageDownloadsHBox);
-
- var packageDownloadsLabel = new Label ();
- packageDownloadsLabel.Text = Catalog.GetString ("Downloads");
- packageDownloadsLabel.Font = packageInfoBoldFont;
- packageDownloadsHBox.PackStart (packageDownloadsLabel);
-
- packageDownloads = new Label ();
- packageDownloads.Font = packageInfoSmallFont;
- packageDownloadsHBox.PackEnd (packageDownloads);
-
- // Package license.
- var packageLicenseHBox = new HBox ();
- packageInfoVBox.PackStart (packageLicenseHBox);
-
- var packageLicenseLabel = new Label ();
- packageLicenseLabel.Text = Catalog.GetString ("License");
+ packageIdLabel.Text = GettextCatalog.GetString ("Id");
+ packageIdHBox.PackStart (packageIdLabel);
+
+ packageId = new Label ();
+ packageId.Ellipsize = EllipsizeMode.End;
+ packageId.TextAlignment = Alignment.End;
+ packageId.Font = packageInfoSmallFont;
+ packageIdLink = new LinkLabel ();
+ packageIdLink.Ellipsize = EllipsizeMode.End;
+ packageIdLink.TextAlignment = Alignment.End;
+ packageIdLink.Font = packageInfoSmallFont;
+ packageIdHBox.PackEnd (packageIdLink, true);
+ packageIdHBox.PackEnd (packageId, true);
+
+ // Package author
+ var packageAuthorHBox = new HBox ();
+ packageInfoVBox.PackStart (packageAuthorHBox);
+
+ var packageAuthorLabel = new Label ();
+ packageAuthorLabel.Text = GettextCatalog.GetString ("Author");
+ packageAuthorLabel.Font = packageInfoBoldFont;
+ packageAuthorHBox.PackStart (packageAuthorLabel);
+
+ packageAuthor = new Label ();
+ packageAuthor.TextAlignment = Alignment.End;
+ packageAuthor.Ellipsize = EllipsizeMode.End;
+ packageAuthor.Font = packageInfoSmallFont;
+ packageAuthorHBox.PackEnd (packageAuthor, true);
+
+ // Package published
+ var packagePublishedHBox = new HBox ();
+ packageInfoVBox.PackStart (packagePublishedHBox);
+
+ var packagePublishedLabel = new Label ();
+ packagePublishedLabel.Text = GettextCatalog.GetString ("Published");
+ packagePublishedLabel.Font = packageInfoBoldFont;
+ packagePublishedHBox.PackStart (packagePublishedLabel);
+
+ packagePublishedDate = new Label ();
+ packagePublishedDate.Font = packageInfoSmallFont;
+ packagePublishedHBox.PackEnd (packagePublishedDate);
+
+ // Package downloads
+ var packageDownloadsHBox = new HBox ();
+ packageInfoVBox.PackStart (packageDownloadsHBox);
+
+ var packageDownloadsLabel = new Label ();
+ packageDownloadsLabel.Text = GettextCatalog.GetString ("Downloads");
+ packageDownloadsLabel.Font = packageInfoBoldFont;
+ packageDownloadsHBox.PackStart (packageDownloadsLabel);
+
+ packageDownloads = new Label ();
+ packageDownloads.Font = packageInfoSmallFont;
+ packageDownloadsHBox.PackEnd (packageDownloads);
+
+ // Package license.
+ var packageLicenseHBox = new HBox ();
+ packageInfoVBox.PackStart (packageLicenseHBox);
+
+ var packageLicenseLabel = new Label ();
+ packageLicenseLabel.Text = GettextCatalog.GetString ("License");
packageLicenseLabel.Font = packageInfoBoldFont;
- packageLicenseHBox.PackStart (packageLicenseLabel);
-
- packageLicenseLink = new LinkLabel ();
- packageLicenseLink.Text = Catalog.GetString ("View License");
- packageLicenseLink.Font = packageInfoSmallFont;
- packageLicenseHBox.PackEnd (packageLicenseLink);
-
- // Package project page.
- var packageProjectPageHBox = new HBox ();
- packageInfoVBox.PackStart (packageProjectPageHBox);
-
- var packageProjectPageLabel = new Label ();
- packageProjectPageLabel.Text = Catalog.GetString ("Project Page");
- packageProjectPageLabel.Font = packageInfoBoldFont;
- packageProjectPageHBox.PackStart (packageProjectPageLabel);
-
- packageProjectPageLink = new LinkLabel ();
- packageProjectPageLink.Text = Catalog.GetString ("Visit Page");
- packageProjectPageLink.Font = packageInfoSmallFont;
- packageProjectPageHBox.PackEnd (packageProjectPageLink);
-
- // Package dependencies
- packageDependenciesHBox = new HBox ();
- packageInfoVBox.PackStart (packageDependenciesHBox);
-
- var packageDependenciesLabel = new Label ();
- packageDependenciesLabel.Text = Catalog.GetString ("Dependencies");
- packageDependenciesLabel.Font = packageInfoBoldFont;
- packageDependenciesHBox.PackStart (packageDependenciesLabel);
-
- packageDependenciesNoneLabel = new Label ();
- packageDependenciesNoneLabel.Text = Catalog.GetString ("None");
- packageDependenciesNoneLabel.Font = packageInfoSmallFont;
- packageDependenciesHBox.PackEnd (packageDependenciesNoneLabel);
-
- // Package dependencies list.
- packageDependenciesListHBox = new HBox ();
- packageDependenciesListHBox.Visible = false;
- packageInfoVBox.PackStart (packageDependenciesListHBox);
-
- packageDependenciesList = new Label ();
- packageDependenciesList.Wrap = WrapMode.WordAndCharacter;
- packageDependenciesList.Margin = new WidgetSpacing (5);
- packageDependenciesList.Font = packageInfoSmallFont;
- packageDependenciesListHBox.PackStart (packageDependenciesList, true);
-
- // Package versions.
- packageVersionsHBox = new HBox ();
- packageVersionsHBox.Visible = false;
- packageVersionsHBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageVersionsHBox.Margin = new WidgetSpacing (15, 0, 15, 12);
- var packageVersionsLabel = new Label ();
- packageVersionsLabel.Font = packageInfoBoldFont;
- packageVersionsLabel.Text = Catalog.GetString ("Version");
- packageVersionsHBox.PackStart (packageVersionsLabel);
-
- packageVersionComboBox = new ComboBox ();
- packageVersionComboBox.Name = "packageVersionComboBox";
- packageVersionsHBox.Spacing = 15;
- packageVersionsHBox.PackStart (packageVersionComboBox, true, true);
-
- var packageInfoAndVersionsVBox = new VBox ();
- packageInfoAndVersionsVBox.Margin = new WidgetSpacing ();
- packageInfoAndVersionsVBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoAndVersionsVBox.PackStart (packageInfoScrollViewFrame, true, true);
- packageInfoAndVersionsVBox.PackStart (packageVersionsHBox, false, false);
- middleHBox.PackEnd (packageInfoAndVersionsVBox);
-
- // Bottom part of dialog:
- // Show pre-release packages and Close/Add to Project buttons.
- var bottomHBox = new HBox ();
- bottomHBox.Margin = new WidgetSpacing (8, 5, 14, 10);
- bottomHBox.Spacing = 5;
- mainVBox.PackStart (bottomHBox);
-
- showPrereleaseCheckBox = new CheckBox ();
- showPrereleaseCheckBox.Name = "addPackagesDialogShowPreReleaseCheckBox";
- showPrereleaseCheckBox.Label = Catalog.GetString ("Show pre-release packages");
- bottomHBox.PackStart (showPrereleaseCheckBox);
-
- addPackagesButton = new Button ();
- addPackagesButton.Name = "addPackagesDialogAddPackageButton";
- addPackagesButton.MinWidth = 120;
- addPackagesButton.MinHeight = 25;
- addPackagesButton.Label = Catalog.GetString ("Add Package");
- bottomHBox.PackEnd (addPackagesButton);
-
- var closeButton = new Button ();
- closeButton.Name = "addPackagesDialogCloseButton";
- closeButton.MinWidth = 120;
- closeButton.MinHeight = 25;
- closeButton.Label = Catalog.GetString ("Close");
- closeButton.Clicked += (sender, e) => Close ();
- bottomHBox.PackEnd (closeButton);
-
- packageSearchEntry.SetFocus ();
- packageInfoVBox.Visible = false;
- }
- }
-}
-
+ packageLicenseHBox.PackStart (packageLicenseLabel);
+
+ packageLicenseLink = new LinkLabel ();
+ packageLicenseLink.Text = GettextCatalog.GetString ("View License");
+ packageLicenseLink.Font = packageInfoSmallFont;
+ packageLicenseHBox.PackEnd (packageLicenseLink);
+
+ // Package project page.
+ var packageProjectPageHBox = new HBox ();
+ packageInfoVBox.PackStart (packageProjectPageHBox);
+
+ var packageProjectPageLabel = new Label ();
+ packageProjectPageLabel.Text = GettextCatalog.GetString ("Project Page");
+ packageProjectPageLabel.Font = packageInfoBoldFont;
+ packageProjectPageHBox.PackStart (packageProjectPageLabel);
+
+ packageProjectPageLink = new LinkLabel ();
+ packageProjectPageLink.Text = GettextCatalog.GetString ("Visit Page");
+ packageProjectPageLink.Font = packageInfoSmallFont;
+ packageProjectPageHBox.PackEnd (packageProjectPageLink);
+
+ // Package dependencies
+ packageDependenciesHBox = new HBox ();
+ packageInfoVBox.PackStart (packageDependenciesHBox);
+
+ var packageDependenciesLabel = new Label ();
+ packageDependenciesLabel.Text = GettextCatalog.GetString ("Dependencies");
+ packageDependenciesLabel.Font = packageInfoBoldFont;
+ packageDependenciesHBox.PackStart (packageDependenciesLabel);
+
+ packageDependenciesNoneLabel = new Label ();
+ packageDependenciesNoneLabel.Text = GettextCatalog.GetString ("None");
+ packageDependenciesNoneLabel.Font = packageInfoSmallFont;
+ packageDependenciesHBox.PackEnd (packageDependenciesNoneLabel);
+
+ // Package dependencies list.
+ packageDependenciesListHBox = new HBox ();
+ packageDependenciesListHBox.Visible = false;
+ packageInfoVBox.PackStart (packageDependenciesListHBox);
+
+ packageDependenciesList = new Label ();
+ packageDependenciesList.Wrap = WrapMode.WordAndCharacter;
+ packageDependenciesList.Margin = new WidgetSpacing (5);
+ packageDependenciesList.Font = packageInfoSmallFont;
+ packageDependenciesListHBox.PackStart (packageDependenciesList, true);
+
+ // Current package version.
+ currentPackageVersionHBox = new HBox ();
+ currentPackageVersionHBox.Spacing = 15;
+ currentPackageVersionHBox.Visible = false;
+ currentPackageVersionHBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ currentPackageVersionHBox.Margin = new WidgetSpacing (15, 0, 15, 0);
+ currentPackageVersionLabel = new Label ();
+ currentPackageVersionLabel.BoundsChanged += PackageVersionLabelBoundsChanged;
+ currentPackageVersionLabel.Font = packageInfoSmallFont;
+ currentPackageVersionLabel.Text = GettextCatalog.GetString ("Current Version:");
+ currentPackageVersionLabel.TextAlignment = Alignment.End;
+ currentPackageVersionHBox.PackStart (currentPackageVersionLabel);
+
+ var currentPackageVersionWithInfoPopoverHBox = new HBox ();
+ currentPackageVersionWithInfoPopoverHBox.Margin = new WidgetSpacing ();
+ currentPackageVersionWithInfoPopoverHBox.Spacing = 0;
+
+ currentPackageVersion = new Label ();
+ currentPackageVersion.Font = packageInfoSmallFont;
+ currentPackageVersionWithInfoPopoverHBox.PackStart (currentPackageVersion);
+
+ currentPackageVersionInfoPopoverWidget = new InformationPopoverWidget ();
+ currentPackageVersionInfoPopoverWidget.Severity = Ide.Tasks.TaskSeverity.Information;
+ currentPackageVersionInfoPopoverWidget.Margin = new WidgetSpacing (5, 0, 0, 2);
+ currentPackageVersionWithInfoPopoverHBox.PackStart (currentPackageVersionInfoPopoverWidget);
+
+ currentPackageVersionHBox.PackStart (currentPackageVersionWithInfoPopoverHBox);
+
+ // Package versions.
+ packageVersionsHBox = new HBox ();
+ packageVersionsHBox.Visible = false;
+ packageVersionsHBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ packageVersionsHBox.Margin = new WidgetSpacing (15, 0, 15, 12);
+ packageVersionsLabel = new Label ();
+ packageVersionsLabel.Font = packageInfoSmallFont;
+ packageVersionsLabel.Text = GettextCatalog.GetString ("New Version:");
+ packageVersionsLabel.TextAlignment = Alignment.End;
+ packageVersionsHBox.PackStart (packageVersionsLabel);
+
+ packageVersionComboBox = new ComboBox ();
+ packageVersionComboBox.Name = "packageVersionComboBox";
+ packageVersionsHBox.Spacing = 15;
+ packageVersionsHBox.PackStart (packageVersionComboBox, true, true);
+
+ var packageInfoAndVersionsVBox = new VBox ();
+ packageInfoAndVersionsVBox.Margin = new WidgetSpacing ();
+ packageInfoAndVersionsVBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
+ packageInfoAndVersionsVBox.PackStart (packageInfoScrollViewFrame, true, true);
+ packageInfoAndVersionsVBox.PackStart (currentPackageVersionHBox, false, false);
+ packageInfoAndVersionsVBox.PackStart (packageVersionsHBox, false, false);
+ middleHBox.PackEnd (packageInfoAndVersionsVBox);
+
+ // Bottom part of dialog:
+ // Show pre-release packages and Close/Add to Project buttons.
+ var bottomHBox = new HBox ();
+ bottomHBox.Margin = new WidgetSpacing (8, 5, 14, 10);
+ bottomHBox.Spacing = 5;
+ mainVBox.PackStart (bottomHBox);
+
+ showPrereleaseCheckBox = new CheckBox ();
+ showPrereleaseCheckBox.Name = "managePackagesDialogShowPreReleaseCheckBox";
+ showPrereleaseCheckBox.Label = GettextCatalog.GetString ("Show pre-release packages");
+ bottomHBox.PackStart (showPrereleaseCheckBox);
+
+ addPackagesButton = new Button ();
+ addPackagesButton.Name = "managePackagesDialogAddPackageButton";
+ addPackagesButton.MinWidth = 120;
+ addPackagesButton.MinHeight = 25;
+ addPackagesButton.Label = GettextCatalog.GetString ("Add Package");
+ bottomHBox.PackEnd (addPackagesButton);
+
+ closeButton = new Button ();
+ closeButton.Name = "managePackagesDialogCloseButton";
+ closeButton.MinWidth = 120;
+ closeButton.MinHeight = 25;
+ closeButton.Label = GettextCatalog.GetString ("Close");
+ bottomHBox.PackEnd (closeButton);
+
+ packageSearchEntry.SetFocus ();
+ packageInfoVBox.Visible = false;
+ }
+
+ double? maxPackageVersionLabelWidth;
+
+ void PackageVersionLabelBoundsChanged (object sender, EventArgs e)
+ {
+ if (!viewModel.IsUpdatesPageSelected)
+ return;
+
+ double currentPackageVersionLabelWidth = currentPackageVersionLabel.Size.Width;
+ double packageVersionsLabelWidth = packageVersionsLabel.Size.Width;
+
+ if (currentPackageVersionLabelWidth > packageVersionsLabelWidth) {
+ packageVersionsLabel.WidthRequest = currentPackageVersionLabelWidth;
+ maxPackageVersionLabelWidth = currentPackageVersionLabelWidth;
+ } else if (packageVersionsLabelWidth > currentPackageVersionLabelWidth) {
+ currentPackageVersionLabel.WidthRequest = packageVersionsLabelWidth;
+ maxPackageVersionLabelWidth = packageVersionsLabelWidth;
+ }
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs
index d6e867e140..2cf875404d 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs
@@ -1,822 +1,1200 @@
-//
-// AddPackagesDialog.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 System.Threading.Tasks;
-using Mono.Unix;
-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 AddPackagesDialog
- {
- IBackgroundPackageActionRunner backgroundActionRunner;
- AllPackagesViewModel viewModel;
- List<SourceRepositoryViewModel> packageSources;
- DataField<bool> packageHasBackgroundColorField = new DataField<bool> ();
- DataField<PackageSearchResultViewModel> packageViewModelField = new DataField<PackageSearchResultViewModel> ();
- DataField<Image> packageImageField = new DataField<Image> ();
- DataField<double> packageCheckBoxAlphaField = new DataField<double> ();
- const double packageCheckBoxSemiTransarentAlpha = 0.6;
- ListStore packageStore;
- PackageCellView packageCellView;
- TimeSpan searchDelayTimeSpan = TimeSpan.FromMilliseconds (500);
- IDisposable searchTimer;
- SourceRepositoryViewModel dummyPackageSourceRepresentingConfigureSettingsItem =
- new SourceRepositoryViewModel (Catalog.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;
-
- public AddPackagesDialog (AllPackagesViewModel viewModel, string initialSearch = null)
- : this (
- viewModel,
- initialSearch,
- PackageManagementServices.BackgroundPackageActionRunner)
- {
- }
-
- public AddPackagesDialog (
- AllPackagesViewModel viewModel,
- string initialSearch,
- IBackgroundPackageActionRunner backgroundActionRunner)
- {
- this.viewModel = viewModel;
- this.backgroundActionRunner = backgroundActionRunner;
-
- Build ();
-
- UpdatePackageSearchEntryWithInitialText (initialSearch);
-
- InitializeListView ();
- UpdateAddPackagesButton ();
- ShowLoadingMessage ();
- LoadViewModel (initialSearch);
-
- 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;
- }
-
- public bool ShowPreferencesForPackageSources { get; private set; }
-
- protected override void Dispose (bool disposing)
- {
- imageLoader.Loaded -= ImageLoaded;
- imageLoader.Dispose ();
-
- RemoveSelectedPackagePropertyChangedEventHandler ();
- viewModel.PropertyChanged -= ViewModelPropertyChanged;
- viewModel.Dispose ();
- DisposeExistingTimer ();
- DisposePopulatePackageVersionsTimer ();
- packageStore.Clear ();
- viewModel = null;
- base.Dispose (disposing);
- }
-
- 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 PackageCellView {
- PackageField = packageViewModelField,
- HasBackgroundColorField = packageHasBackgroundColorField,
- CheckBoxAlphaField = packageCheckBoxAlphaField,
- ImageField = packageImageField,
- CellWidth = 535
- };
- var textColumn = new ListViewColumn ("Package", packageCellView);
- packagesListView.Columns.Add (textColumn);
-
- packageCellView.PackageChecked += PackageCellViewPackageChecked;
- }
-
- 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 = Catalog.GetString ("Loading package list...");
- } else {
- loadingSpinnerLabel.Text = Catalog.GetString ("Searching packages...");
- }
- }
-
- void ShowNoPackagesFoundMessage ()
- {
- if (!String.IsNullOrWhiteSpace (packageSearchEntry.Text)) {
- packagesListView.Visible = false;
- noPackagesFoundFrame.Visible = true;
- }
- }
-
- 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.packageVersionsHBox.Visible = false;
- }
-
- 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 ();
-
- PackageSearchResultViewModel packageViewModel = GetSelectedPackageViewModel ();
- if (packageViewModel != null) {
- ShowPackageInformation (packageViewModel);
- } else {
- ClearSelectedPackageInformation ();
- }
- viewModel.SelectedPackage = packageViewModel;
- UpdateAddPackagesButton ();
- }
-
- PackageSearchResultViewModel GetSelectedPackageViewModel ()
- {
- if (packagesListView.SelectedRow != -1) {
- return packageStore.GetValue (packagesListView.SelectedRow, packageViewModelField);
- }
- return null;
- }
-
- void ShowPackageInformation (PackageSearchResultViewModel packageViewModel)
- {
- // 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);
-
- PopulatePackageVersions (packageViewModel);
-
- this.packageInfoVBox.Visible = true;
- this.packageVersionsHBox.Visible = true;
-
- packageViewModel.PropertyChanged += SelectedPackageViewModelChanged;
- viewModel.LoadPackageMetadata (packageViewModel);
- }
-
- 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) {
- PackageSearchResultViewModel 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 (PackageSearchResultViewModel 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, PackageSearchResultViewModel packageViewModel)
- {
- if (packageViewModel.HasIconUrl) {
- imageLoader.LoadFrom (packageViewModel.IconUrl, row);
- }
- }
-
- 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) {
- PackageSearchResultViewModel packageViewModel = packageStore.GetValue (row, packageViewModelField);
- if (packageViewModel != null) {
- return uri == packageViewModel.IconUrl;
- }
- }
- return false;
- }
-
- void AddPackagesButtonClicked (object sender, EventArgs e)
- {
- try {
- List<IPackageAction> packageActions = CreateInstallPackageActionsForSelectedPackages ();
- InstallPackages (packageActions);
- } catch (Exception ex) {
- LoggingService.LogError ("Adding packages failed.", ex);
- ShowErrorMessage (ex.Message);
- }
- }
-
- void InstallPackages (List<IPackageAction> packageActions)
- {
- if (packageActions.Count > 0) {
- ProgressMonitorStatusMessage progressMessage = GetProgressMonitorStatusMessages (packageActions);
- backgroundActionRunner.Run (progressMessage, packageActions);
-
- viewModel.OnInstallingSelectedPackages ();
- Close ();
- }
- }
-
- List<IPackageAction> CreateInstallPackageActionsForSelectedPackages ()
- {
- List<PackageSearchResultViewModel> packageViewModels = GetSelectedPackageViewModels ();
- if (packageViewModels.Count > 0) {
- return CreateInstallPackageActions (packageViewModels);
- }
- return new List<IPackageAction> ();
- }
-
- ProgressMonitorStatusMessage GetProgressMonitorStatusMessages (List<IPackageAction> packageActions)
- {
- if (packageActions.Count == 1) {
- string packageId = packageActions.OfType<INuGetPackageAction> ().First ().PackageId;
- if (OlderPackageInstalledThanPackageSelected ()) {
- return ProgressMonitorStatusMessageFactory.CreateUpdatingSinglePackageMessage (packageId);
- }
- return ProgressMonitorStatusMessageFactory.CreateInstallingSinglePackageMessage (packageId);
- }
- return ProgressMonitorStatusMessageFactory.CreateInstallingMultiplePackagesMessage (packageActions.Count);
- }
-
- List<PackageSearchResultViewModel> GetSelectedPackageViewModels ()
- {
- List<PackageSearchResultViewModel> packageViewModels = viewModel.CheckedPackageViewModels.ToList ();
- if (packageViewModels.Count > 0) {
- return packageViewModels;
- }
-
- PackageSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel ();
- if (selectedPackageViewModel != null) {
- packageViewModels.Add (selectedPackageViewModel);
- }
- return packageViewModels;
- }
-
- List<IPackageAction> CreateInstallPackageActions (IEnumerable<PackageSearchResultViewModel> packageViewModels)
- {
- return packageViewModels.Select (packageViewModel => viewModel.CreateInstallPackageAction (packageViewModel)).ToList ();
- }
-
- 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 {
- PackageSearchResultViewModel packageViewModel = packageStore.GetValue (e.RowIndex, packageViewModelField);
- InstallPackage (packageViewModel);
- }
- }
-
- void InstallPackage (PackageSearchResultViewModel packageViewModel)
- {
- try {
- if (packageViewModel != null) {
- List<IPackageAction> packageActions = CreateInstallPackageActions (
- new PackageSearchResultViewModel [] { packageViewModel });
- InstallPackages (packageActions);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Installing package failed.", ex);
- ShowErrorMessage (ex.Message);
- }
- }
-
- void PackageSearchEntryActivated (object sender, EventArgs e)
- {
- if (loadingMessageVisible)
- return;
-
- if (PackagesCheckedCount > 0) {
- AddPackagesButtonClicked (sender, e);
- } else {
- PackageSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel ();
- InstallPackage (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, PackageCellViewEventArgs e)
- {
- UpdateAddPackagesButton ();
- UpdatePackageListViewSelectionColor ();
- UpdatePackageListViewCheckBoxAlpha ();
- }
-
- void UpdateAddPackagesButton ()
- {
- string label = Catalog.GetPluralString ("Add Package", "Add Packages", GetPackagesCountForAddPackagesButtonLabel ());
- if (PackagesCheckedCount <= 1 && OlderPackageInstalledThanPackageSelected ()) {
- label = Catalog.GetString ("Update Package");
- }
- addPackagesButton.Label = label;
- addPackagesButton.Sensitive = IsAddPackagesButtonEnabled ();
- }
-
- 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;
- }
-
- PackageSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel ();
- if (selectedPackageViewModel != null) {
- return selectedPackageViewModel.IsOlderPackageInstalled ();
- }
- return false;
- }
-
- bool IsAddPackagesButtonEnabled ()
- {
- return !loadingMessageVisible && IsAtLeastOnePackageSelected ();
- }
-
- 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 {
- packagePublishedDate.Text = viewModel.SelectedPackage.GetLastPublishedDisplayText ();
- PopulatePackageDependencies (viewModel.SelectedPackage);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Error loading package versions.", ex);
- }
- }
-
- void PopulatePackageVersions (PackageSearchResultViewModel packageViewModel)
- {
- DisposePopulatePackageVersionsTimer ();
-
- ignorePackageVersionChanges = true;
- try {
- packageVersionComboBox.Items.Clear ();
- if (packageViewModel.Versions.Any ()) {
- 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);
- }
- } else {
- AddPackageVersionToComboBox (packageViewModel.Version);
- }
- packageVersionComboBox.SelectedItem = packageViewModel.SelectedVersion;
- } finally {
- ignorePackageVersionChanges = false;
- }
- }
-
- void AddPackageVersionToComboBox (NuGetVersion version)
- {
- packageVersionComboBox.Items.Add (version, version.ToString ());
- }
-
- void PackageVersionChanged (object sender, EventArgs e)
- {
- if (ignorePackageVersionChanges || viewModel.SelectedPackage == null)
- return;
-
- viewModel.SelectedPackage.SelectedVersion = (NuGetVersion)packageVersionComboBox.SelectedItem;
- UpdateAddPackagesButton ();
- }
-
- void PopulatePackageDependencies (PackageSearchResultViewModel 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 ()
- {
- PackageSearchResultViewModel 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;
- }
- }
+//
+// 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
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs
index 8551dfafcd..e766df17e2 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs
@@ -1,78 +1,85 @@
-//
-// AddPackagesDialogRunner.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 MonoDevelop.Ide;
-using MonoDevelop.Core;
-using MonoDevelop.Projects;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class AddPackagesDialogRunner
- {
- static RecentNuGetPackagesRepository recentPackagesRepository = new RecentNuGetPackagesRepository ();
-
- public void Run (string initialSearch = null)
- {
- Run (null, initialSearch);
- }
-
- public void Run (DotNetProject project, string initialSearch = null)
- {
- try {
- PackageManagementCredentialService.Reset ();
- bool configurePackageSources = false;
- do {
- using (AddPackagesDialog dialog = CreateDialog (project, initialSearch)) {
- dialog.ShowWithParent ();
- configurePackageSources = dialog.ShowPreferencesForPackageSources;
- initialSearch = dialog.SearchText;
- }
- if (configurePackageSources) {
- ShowPreferencesForPackageSources ();
- }
- } while (configurePackageSources);
-
- } catch (Exception ex) {
- LoggingService.LogInternalError (ex);
- }
- }
-
- AddPackagesDialog CreateDialog (DotNetProject project, string initialSearch)
- {
- var viewModel = AllPackagesViewModel.Create (project, recentPackagesRepository);
- return new AddPackagesDialog (
- viewModel,
- initialSearch);
- }
-
- void ShowPreferencesForPackageSources ()
- {
- IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "PackageSources");
- }
- }
-}
-
+//
+// ManagePackagesDialogRunner.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 MonoDevelop.Ide;
+using MonoDevelop.Core;
+using MonoDevelop.Projects;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal class ManagePackagesDialogRunner
+ {
+ static RecentManagedNuGetPackagesRepository recentPackagesRepository = new RecentManagedNuGetPackagesRepository ();
+
+ public void Run (IDotNetProject project = null, string initialSearch = null)
+ {
+ try {
+ bool configurePackageSources = false;
+ do {
+ using (ManagePackagesDialog dialog = CreateDialog (initialSearch, project)) {
+ dialog.ShowWithParent ();
+ configurePackageSources = dialog.ShowPreferencesForPackageSources;
+ initialSearch = dialog.SearchText;
+ }
+ if (configurePackageSources) {
+ ShowPreferencesForPackageSources ();
+ }
+ } while (configurePackageSources);
+
+ } catch (Exception ex) {
+ LoggingService.LogInternalError (ex);
+ }
+ }
+
+ public void Run (Project project, string initialSearch = null)
+ {
+ Run (CreateDotNetProjectProxy (project), initialSearch);
+ }
+
+ IDotNetProject CreateDotNetProjectProxy (Project project)
+ {
+ if (project is DotNetProject dotNetProject)
+ return new DotNetProjectProxy (dotNetProject);
+
+ return null;
+ }
+
+ ManagePackagesDialog CreateDialog (string initialSearch, IDotNetProject project)
+ {
+ var viewModel = ManagePackagesViewModel.Create (recentPackagesRepository, project);
+ return new ManagePackagesDialog (
+ viewModel,
+ initialSearch);
+ }
+
+ void ShowPreferencesForPackageSources ()
+ {
+ IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "PackageSources");
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs
new file mode 100644
index 0000000000..3a707ee2e6
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs
@@ -0,0 +1,117 @@
+//
+// SelectProjectsDialog.UI.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 Xwt;
+
+namespace MonoDevelop.PackageManagement
+{
+ partial class SelectProjectsDialog : Dialog
+ {
+ Label topLabel;
+ VBox projectsListView;
+ DialogButton okButton;
+ List<CheckBox> checkBoxes = new List<CheckBox> ();
+
+ void Build ()
+ {
+ Title = GettextCatalog.GetString ("Select Projects");
+ Width = 420;
+ Height = 330;
+ Padding = 20;
+
+ var mainVBox = new VBox ();
+ Content = mainVBox;
+
+ topLabel = new Label ();
+ topLabel.Wrap = WrapMode.Word;
+ mainVBox.PackStart (topLabel);
+
+ projectsListView = new VBox ();
+
+ var projectsListScrollView = new ScrollView (projectsListView);
+ projectsListScrollView.HorizontalScrollPolicy = ScrollPolicy.Never;
+ projectsListScrollView.VerticalScrollPolicy = ScrollPolicy.Automatic;
+ projectsListScrollView.BorderVisible = false;
+ projectsListScrollView.BackgroundColor = Ide.Gui.Styles.BackgroundColor;
+ projectsListScrollView.Content = projectsListView;
+
+ mainVBox.PackStart (projectsListScrollView, true, true);
+
+ var cancelButton = new DialogButton (Command.Cancel);
+ Buttons.Add (cancelButton);
+
+ okButton = new DialogButton (Command.Ok);
+ okButton.Sensitive = false;
+ Buttons.Add (okButton);
+ }
+
+ void AddProject (SelectedProjectViewModel project)
+ {
+ var hbox = new HBox ();
+ hbox.Tag = project;
+
+ var checkBox = new CheckBox ();
+ checkBox.Label = project.Name;
+ checkBox.Tag = project;
+ checkBox.Active = project.IsSelected;
+ checkBox.Clicked += ProjectCheckBoxClicked;
+ hbox.PackStart (checkBox);
+
+ checkBoxes.Add (checkBox);
+
+ projectsListView.PackStart (hbox);
+ }
+
+ void ProjectCheckBoxClicked (object sender, EventArgs e)
+ {
+ var checkBox = (CheckBox)sender;
+ var project = (SelectedProjectViewModel)checkBox.Tag;
+ project.IsSelected = checkBox.Active;
+
+ UpdateOkButtonSensitivity ();
+ }
+
+ void UpdateOkButtonSensitivity ()
+ {
+ okButton.Sensitive = viewModel.GetSelectedProjects ().Any ();
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ base.Dispose (disposing);
+
+ if (disposing) {
+ foreach (CheckBox checkBox in checkBoxes) {
+ checkBox.Clicked -= ProjectCheckBoxClicked;
+ }
+ }
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs
new file mode 100644
index 0000000000..0c8003b5b8
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs
@@ -0,0 +1,107 @@
+//
+// ManagePackagesDialog.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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.Collections.Generic;
+using System.Linq;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.PackageManagement
+{
+ partial class SelectProjectsDialog
+ {
+ SelectProjectsViewModel viewModel;
+
+ public SelectProjectsDialog (SelectProjectsViewModel viewModel)
+ {
+ this.viewModel = viewModel;
+
+ Build ();
+
+ UpdateTopLabel (viewModel.Projects.Count ());
+
+ AddProjects ();
+ }
+
+ public IEnumerable<IDotNetProject> GetSelectedProjects ()
+ {
+ return viewModel.GetSelectedProjects ();
+ }
+
+ void UpdateTopLabel (int projectsCount)
+ {
+ if (viewModel.IsAddingSinglePackage) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Add the package to the project:",
+ "Add the package to the projects:",
+ projectsCount);
+ } else if (viewModel.IsAddingMultiplePackages) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Add the packages to the project:",
+ "Add the packages to the projects:",
+ projectsCount);
+ } else if (viewModel.IsRemovingSinglePackage) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Remove the package from the project:",
+ "Remove the package from the projects:",
+ projectsCount);
+ } else if (viewModel.IsRemovingMultiplePackages) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Remove the packages from the project:",
+ "Remove the packages from the projects:",
+ projectsCount);
+ } else if (viewModel.IsUpdatingSinglePackage) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Update the package in the project:",
+ "Update the package in the projects:",
+ projectsCount);
+ } else if (viewModel.IsUpdatingMultiplePackages) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Update the packages in the project:",
+ "Update the packages in the projects:",
+ projectsCount);
+ } else if (viewModel.IsConsolidatingSinglePackage) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Consolidate the package in the project:",
+ "Consolidate the package in the projects:",
+ projectsCount);
+ } else if (viewModel.IsConsolidatingMultiplePackages) {
+ topLabel.Text = GettextCatalog.GetPluralString (
+ "Consolidate the packages in the project:",
+ "Consolidate the packages in the projects:",
+ projectsCount);
+ }
+ }
+
+ void AddProjects ()
+ {
+ foreach (SelectedProjectViewModel project in viewModel.Projects) {
+ AddProject (project);
+ }
+
+ UpdateOkButtonSensitivity ();
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs
index 03b3924ef9..8bf2b74441 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs
@@ -191,7 +191,7 @@ namespace MonoDevelop.PackageManagement.Refactoring
Runtime.RunInMainThread (delegate {
var project = IdeApp.Workbench.ActiveDocument?.Owner as DotNetProject;
if (project != null) {
- var runner = new AddPackagesDialogRunner ();
+ var runner = new ManagePackagesDialogRunner ();
runner.Run (project, packageName);
}
});
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs
index c981095f4e..2e289c0ef5 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs
@@ -83,12 +83,8 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
public IDotNetProject ResolveProject (ProjectReference projectReference)
{
- if (OnResolveProject != null)
- return OnResolveProject (projectReference);
return Projects.FirstOrDefault (project => project.Name == projectReference.Include);
}
-
- public Func<ProjectReference, IDotNetProject> OnResolveProject;
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageSearchResultViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesSearchResultViewModel.cs
index caeec5e53e..10bb57199d 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageSearchResultViewModel.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesSearchResultViewModel.cs
@@ -1,5 +1,5 @@
//
-// TestablePackageSearchResultViewModel.cs
+// TestableManagePackagesSearchResultViewModel.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -30,12 +30,12 @@ using NuGet.PackageManagement.UI;
namespace MonoDevelop.PackageManagement.Tests.Helpers
{
- class TestablePackageSearchResultViewModel : PackageSearchResultViewModel
+ class TestableManagePackagesSearchResultViewModel : ManagePackagesSearchResultViewModel
{
public FakeDotNetProject Project;
public FakeSolutionManager SolutionManager;
- public TestablePackageSearchResultViewModel (
+ public TestableManagePackagesSearchResultViewModel (
PackageItemListViewModel viewModel)
: this (
new FakeSolutionManager (),
@@ -44,19 +44,19 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
{
}
- public TestablePackageSearchResultViewModel (
- TestableAllPackagesViewModel parent,
+ public TestableManagePackagesSearchResultViewModel (
+ TestableManagePackagesViewModel parent,
PackageItemListViewModel viewModel)
: base (parent, viewModel)
{
}
- public TestablePackageSearchResultViewModel (
+ public TestableManagePackagesSearchResultViewModel (
FakeSolutionManager solutionManager,
FakeDotNetProject project,
PackageItemListViewModel viewModel)
: this (
- new TestableAllPackagesViewModel (solutionManager, project),
+ new TestableManagePackagesViewModel (solutionManager, project),
viewModel)
{
SolutionManager = solutionManager;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesViewModel.cs
index 9d2586dcbb..44e8697994 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesViewModel.cs
@@ -1,5 +1,5 @@
//
-// TestableAllPackagesViewModel.cs
+// TestableManagePackagesViewModel.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -25,36 +25,57 @@
// THE SOFTWARE.
using System;
-using System.Collections.Generic;
+using System.IO.IsolatedStorage;
using System.Threading;
using System.Threading.Tasks;
using NuGet.PackageManagement.UI;
-using NuGet.Protocol.Core.Types;
namespace MonoDevelop.PackageManagement.Tests.Helpers
{
- class TestableAllPackagesViewModel : AllPackagesViewModel
+ class TestableManagePackagesViewModel : ManagePackagesViewModel
{
- public RecentNuGetPackagesRepository RecentPackagesRepository;
+ public RecentManagedNuGetPackagesRepository RecentPackagesRepository;
public FakeNuGetProjectContext FakeNuGetProjectContext;
- public TestableAllPackagesViewModel (
+ public TestableManagePackagesViewModel (
IMonoDevelopSolutionManager solutionManager,
IDotNetProject dotNetProject)
: this (
solutionManager,
dotNetProject,
new FakeNuGetProjectContext (),
- new RecentNuGetPackagesRepository ())
+ new RecentManagedNuGetPackagesRepository ())
{
}
- public TestableAllPackagesViewModel (
+ public TestableManagePackagesViewModel (
IMonoDevelopSolutionManager solutionManager,
IDotNetProject dotNetProject,
FakeNuGetProjectContext projectContext,
- RecentNuGetPackagesRepository recentPackagesRepository)
- : base (solutionManager, dotNetProject, projectContext, recentPackagesRepository)
+ RecentManagedNuGetPackagesRepository recentPackagesRepository)
+ : base (solutionManager, dotNetProject.ParentSolution, projectContext, recentPackagesRepository, dotNetProject)
+ {
+ FakeNuGetProjectContext = projectContext;
+ RecentPackagesRepository = recentPackagesRepository;
+ }
+
+ public TestableManagePackagesViewModel (
+ IMonoDevelopSolutionManager solutionManager,
+ ISolution solution)
+ : this (
+ solutionManager,
+ solution,
+ new FakeNuGetProjectContext (),
+ new RecentManagedNuGetPackagesRepository ())
+ {
+ }
+
+ public TestableManagePackagesViewModel (
+ IMonoDevelopSolutionManager solutionManager,
+ ISolution solution,
+ FakeNuGetProjectContext projectContext,
+ RecentManagedNuGetPackagesRepository recentPackagesRepository)
+ : base (solutionManager, solution, projectContext, recentPackagesRepository, null)
{
FakeNuGetProjectContext = projectContext;
RecentPackagesRepository = recentPackagesRepository;
@@ -62,7 +83,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
public FakePackageFeed PackageFeed = new FakePackageFeed ();
- protected override IPackageFeed CreatePackageFeed (IEnumerable<SourceRepository> sourceRepositories)
+ protected override IPackageFeed CreatePackageFeed (PackageLoadContext context)
{
return PackageFeed;
}
@@ -92,9 +113,9 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
public Task GetPackagesInstalledInProjectTask;
- protected override Task GetPackagesInstalledInProject ()
+ protected override Task GetPackagesInstalledInProjects ()
{
- GetPackagesInstalledInProjectTask = base.GetPackagesInstalledInProject ();
+ GetPackagesInstalledInProjectTask = base.GetPackagesInstalledInProjects ();
return GetPackagesInstalledInProjectTask;
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj
index bbd00cd4ca..560775c805 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj
@@ -44,7 +44,7 @@
<Compile Include="MonoDevelop.PackageManagement.Tests\PackageSourceViewModelTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests\RegisteredPackageSourcesViewModelTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\PackageSourceCollectionAssert.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests\RecentNuGetPackagesRepositoryTests.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests\RecentManagedNuGetPackagesRepositoryTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSolution.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeProject.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageManagementProjectService.cs" />
@@ -86,17 +86,15 @@
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProjectAction.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProjectContext.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests\NuGetPackageUninstallerTests.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests\AllPackagesViewModelTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSolutionManager.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProject.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSourceRepositoryProvider.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetSettings.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests\FakePackageFeed.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableAllPackagesViewModel.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests\PackageSearchResultViewModelTests.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests\ManagePackagesSearchResultViewModelTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageMetadataProvider.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageSearchMetadata.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestablePackageSearchResultViewModel.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableManagePackagesSearchResultViewModel.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageMetadataResource.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageMetadataResourceProvider.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests\UpdatedNuGetPackagesInWorkspaceTests.cs" />
@@ -154,6 +152,8 @@
<Compile Include="MonoDevelop.PackageManagement.Tests\PackagesCommandHandlerTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableRestorePackagesHandler.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableRestorePackagesInProjectHandler.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests\ManagePackagesViewModelTests.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableManagePackagesViewModel.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj">
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageSearchResultViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesSearchResultViewModelTests.cs
index d2a033fe46..dad464ab8f 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageSearchResultViewModelTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesSearchResultViewModelTests.cs
@@ -1,5 +1,5 @@
//
-// PackageSearchResultViewModelTests.cs
+// ManagePackagesSearchResultViewModelTests.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -43,11 +43,11 @@ using NUnit.Framework;
namespace MonoDevelop.PackageManagement.Tests
{
[TestFixture]
- public class PackageSearchResultViewModelTests
+ public class ManagePackagesSearchResultViewModelTests
{
- TestablePackageSearchResultViewModel viewModel;
+ TestableManagePackagesSearchResultViewModel viewModel;
PackageItemListViewModel packageItemListViewModel;
- TestableAllPackagesViewModel parent;
+ TestableManagePackagesViewModel parent;
FakePackageMetadataProvider metadataProvider;
List<VersionInfo> packageVersions;
FakePackageSearchMetadata packageSearchMetadata;
@@ -78,8 +78,8 @@ namespace MonoDevelop.PackageManagement.Tests
packageSearchMetadata = metadataProvider.AddPackageMetadata (package.Id, package.Version.ToString ());
var solutionManager = new FakeSolutionManager ();
var project = new FakeDotNetProject ();
- parent = new TestableAllPackagesViewModel (solutionManager, project);
- viewModel = new TestablePackageSearchResultViewModel (parent, packageItemListViewModel);
+ parent = new TestableManagePackagesViewModel (solutionManager, project);
+ viewModel = new TestableManagePackagesSearchResultViewModel (parent, packageItemListViewModel);
}
Task LoadPackageMetadata ()
@@ -630,5 +630,59 @@ namespace MonoDevelop.PackageManagement.Tests
Assert.AreEqual ("1.2-beta1", viewModel.Versions[0].ToString ());
Assert.AreEqual ("1.0-beta2", viewModel.Versions[1].ToString ());
}
+
+ [Test]
+ public async Task ReadVersions_LatestVersionNotSelectedWhenConsolidating_SelectedVersionChangedToLatestVersion ()
+ {
+ CreateViewModel ();
+ viewModel.SelectLatestVersion = true;
+ AddVersionsToPackageItemListViewModel ("2.0", "1.2.3", "0.2", "0.1");
+
+ await ReadVersions ();
+
+ Assert.AreEqual (4, viewModel.Versions.Count);
+ Assert.AreEqual ("2.0", viewModel.Versions [0].ToString ());
+ Assert.AreEqual ("1.2.3", viewModel.Versions [1].ToString ());
+ Assert.AreEqual ("0.2", viewModel.Versions [2].ToString ());
+ Assert.AreEqual ("0.1", viewModel.Versions [3].ToString ());
+ Assert.AreEqual ("2.0", viewModel.SelectedVersion.ToString ());
+ }
+
+ [Test]
+ public async Task ReadVersions_LatestVersionNotSelectedWhenNotConsolidating_SelectedVersionNotChanged ()
+ {
+ CreateViewModel ();
+ viewModel.SelectLatestVersion = false;
+ AddVersionsToPackageItemListViewModel ("2.0", "1.2.3", "0.2", "0.1");
+
+ await ReadVersions ();
+
+ Assert.AreEqual (4, viewModel.Versions.Count);
+ Assert.AreEqual ("2.0", viewModel.Versions [0].ToString ());
+ Assert.AreEqual ("1.2.3", viewModel.Versions [1].ToString ());
+ Assert.AreEqual ("0.2", viewModel.Versions [2].ToString ());
+ Assert.AreEqual ("0.1", viewModel.Versions [3].ToString ());
+ Assert.AreEqual ("1.2.3", viewModel.SelectedVersion.ToString ());
+ }
+
+ [Test]
+ public async Task UpdateFromPreviouslyCheckedViewModel_VersionSelectedWasNotLatestVersion_VersionPreviouslySelectedIsReusedAfterReadingPackages ()
+ {
+ var package = CreatePackageItemListViewModel ();
+ package.Version = new NuGetVersion ("1.2.3");
+ CreateViewModel (package);
+ var checkedViewModel = viewModel;
+ checkedViewModel.IsChecked = true;
+ package = CreatePackageItemListViewModel ();
+ package.Version = new NuGetVersion ("1.2.3");
+ CreateViewModel (package);
+ viewModel.SelectLatestVersion = true;
+ AddVersionsToPackageItemListViewModel ("2.0", "1.2.3", "0.2", "0.1");
+ viewModel.UpdateFromPreviouslyCheckedViewModel (checkedViewModel);
+ await ReadVersions ();
+
+ Assert.IsTrue (viewModel.IsChecked);
+ Assert.AreEqual ("1.2.3", viewModel.SelectedVersion.ToString ());
+ }
}
} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesViewModelTests.cs
index 5a279f58e9..c4267ab94e 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesViewModelTests.cs
@@ -1,5 +1,5 @@
//
-// AllPackagesViewModelTests.cs
+// ManagePackagesViewModelTests.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -31,6 +31,8 @@ using System.Threading.Tasks;
using MonoDevelop.PackageManagement.Tests.Helpers;
using NuGet.Configuration;
using NuGet.PackageManagement.UI;
+using NuGet.Packaging;
+using NuGet.Packaging.Core;
using NuGet.ProjectManagement;
using NuGet.Versioning;
using NUnit.Framework;
@@ -38,28 +40,46 @@ using NUnit.Framework;
namespace MonoDevelop.PackageManagement.Tests
{
[TestFixture]
- public class AllPackagesViewModelTests
+ public class ManagePackagesViewModelTests
{
- TestableAllPackagesViewModel viewModel;
+ TestableManagePackagesViewModel viewModel;
FakeSolutionManager solutionManager;
FakeDotNetProject project;
+ FakeSolution solution;
FakePackageSourceProvider packageSourceProvider;
void CreateProject ()
{
+ solution = new FakeSolution ();
project = new FakeDotNetProject ();
+ project.ParentSolution = solution;
+ solution.Projects.Add (project);
solutionManager = new FakeSolutionManager ();
packageSourceProvider = solutionManager.SourceRepositoryProvider.FakePackageSourceProvider;
}
+ FakeDotNetProject AddProjectToSolution (string name)
+ {
+ var newProject = new FakeDotNetProject ();
+ newProject.Name = name;
+ solution.Projects.Add (newProject);
+ return newProject;
+ }
+
void CreateViewModel ()
{
- viewModel = new TestableAllPackagesViewModel (
+ viewModel = new TestableManagePackagesViewModel (
solutionManager,
project);
EnsurePackageSourcesLoaded ();
}
+ void CreateViewModelForSolution ()
+ {
+ viewModel = new TestableManagePackagesViewModel (solutionManager, solution);
+ EnsurePackageSourcesLoaded ();
+ }
+
void EnsurePackageSourcesLoaded ()
{
viewModel.PackageSources.ToList ();
@@ -110,29 +130,34 @@ namespace MonoDevelop.PackageManagement.Tests
viewModel.SelectedPackageSource = secondPackageSource;
}
- PackageSearchResultViewModel AddRecentPackage (string packageId, string packageVersion, string packageSource)
+ ManagePackagesSearchResultViewModel AddRecentPackage (string packageId, string packageVersion, string packageSource)
{
var searchResultViewModel = CreateRecentPackage (packageId, packageVersion, packageSource);
viewModel.RecentPackagesRepository.AddPackage (searchResultViewModel, packageSource);
return searchResultViewModel;
}
- PackageSearchResultViewModel CreateRecentPackage (string packageId, string packageVersion, string packageSource)
+ ManagePackagesSearchResultViewModel CreateRecentPackage (string packageId, string packageVersion, string packageSource)
{
- var allPackagesViewModelForRecentPackages = new TestableAllPackagesViewModel (
+ var packagesViewModelForRecentPackages = new TestableManagePackagesViewModel (
new FakeSolutionManager (),
new FakeDotNetProject ());
var recentPackage = new PackageItemListViewModel {
Id = packageId,
Version = new NuGetVersion (packageVersion)
};
- return new PackageSearchResultViewModel (allPackagesViewModelForRecentPackages, recentPackage);
+ return new ManagePackagesSearchResultViewModel (packagesViewModelForRecentPackages, recentPackage);
}
FakeNuGetProject CreateNuGetProjectForProject ()
{
- var nugetProject = new FakeNuGetProject (project);
- solutionManager.NuGetProjects[project] = nugetProject;
+ return CreateNuGetProjectForProject (project);
+ }
+
+ FakeNuGetProject CreateNuGetProjectForProject (IDotNetProject dotNetProject)
+ {
+ var nugetProject = new FakeNuGetProject (dotNetProject);
+ solutionManager.NuGetProjects [dotNetProject] = nugetProject;
return nugetProject;
}
@@ -1014,6 +1039,7 @@ namespace MonoDevelop.PackageManagement.Tests
Assert.AreEqual (1, viewModel.PackageViewModels.Count);
Assert.AreEqual ("Recent1", viewModel.PackageViewModels[0].Id);
Assert.AreEqual (4, recentPackage.Versions.Count);
+ Assert.IsFalse (viewModel.PackageViewModels[0].SelectLatestVersion);
}
[Test]
@@ -1031,6 +1057,377 @@ namespace MonoDevelop.PackageManagement.Tests
Assert.AreEqual ("All Sources", selectedPackageSource.Name);
Assert.IsTrue (selectedPackageSource.IsAggregate);
}
+
+ [Test]
+ public async Task Consolidate_ThreeProjectsDifferentPackageVersionInTwoProjects_ProjectVersionAndSelectionInformationAvailable ()
+ {
+ CreateProject ();
+ project.Name = "LibC";
+ var nugetProject = CreateNuGetProjectForProject (project);
+ nugetProject.AddPackageReference ("Test", "0.1");
+
+ var project2 = AddProjectToSolution ("LibA");
+ CreateNuGetProjectForProject (project2);
+
+ var project3 = AddProjectToSolution ("LibB");
+ nugetProject = CreateNuGetProjectForProject (project3);
+ nugetProject.AddPackageReference ("Test", "0.2");
+
+ AddOnePackageSourceToRegisteredSources ();
+ CreateViewModelForSolution ();
+ viewModel.PackageFeed.AddPackage ("Test", "0.2");
+ viewModel.PageSelected = ManagePackagesPage.Consolidate;
+
+ viewModel.ReadPackages ();
+ await viewModel.ReadPackagesTask;
+
+ var package = viewModel.PackageViewModels.Single ();
+ viewModel.SelectedPackage = package;
+ Assert.AreEqual ("Test", package.Id);
+ Assert.AreEqual ("0.2", package.Version.ToString ());
+
+ Assert.AreEqual (3, viewModel.ProjectViewModels.Count);
+
+ // Checked projects first.
+ var projectViewModel = viewModel.ProjectViewModels [0];
+ Assert.AreEqual ("LibB", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.2", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [1];
+ Assert.AreEqual ("LibC", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.1", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [2];
+ Assert.AreEqual ("LibA", projectViewModel.ProjectName);
+ Assert.AreEqual ("–", projectViewModel.PackageVersion);
+ Assert.IsFalse (projectViewModel.IsChecked);
+
+ Assert.IsTrue (viewModel.CanConsolidate ());
+
+ // Expecting one action since Test 0.2 is already installed in LibB.
+ var actions = viewModel.CreateConsolidatePackageActions (package).ToList ();
+ Assert.AreEqual (1, actions.Count);
+ var action = actions [0] as InstallNuGetPackageAction;
+ Assert.AreEqual (PackageActionType.Install, action.ActionType);
+ Assert.AreEqual ("Test", action.PackageId);
+ Assert.AreEqual ("0.2", action.Version.ToString ());
+ Assert.AreEqual ("LibC", action.Project.Name);
+
+ // Check LibA, which does not have the package.
+ viewModel.ProjectViewModels [2].IsChecked = true;
+
+ // Uncheck LibC.
+ viewModel.ProjectViewModels [1].IsChecked = false;
+
+ Assert.IsTrue (viewModel.CanConsolidate ());
+
+ actions = viewModel.CreateConsolidatePackageActions (package).ToList ();
+ Assert.AreEqual (1, actions.Count);
+ action = actions [0] as InstallNuGetPackageAction;
+ Assert.AreEqual (PackageActionType.Install, action.ActionType);
+ Assert.AreEqual ("Test", action.PackageId);
+ Assert.AreEqual ("0.2", action.Version.ToString ());
+ Assert.AreEqual ("LibA", action.Project.Name);
+
+ // Uncheck all projects. No items checked so cannot consolidate.
+ viewModel.ProjectViewModels [0].IsChecked = false;
+ viewModel.ProjectViewModels [1].IsChecked = false;
+ viewModel.ProjectViewModels [2].IsChecked = false;
+ Assert.IsFalse (viewModel.CanConsolidate ());
+
+ // Check LibB which has same package.
+ viewModel.ProjectViewModels [0].IsChecked = true;
+ Assert.IsFalse (viewModel.CanConsolidate ());
+
+ viewModel.SelectedPackage = null;
+ Assert.AreEqual (0, viewModel.ProjectViewModels.Count);
+ Assert.IsFalse (viewModel.CanConsolidate ());
+ }
+
+ [Test]
+ public async Task CheckedPackageViewModels_DifferentTabPageSelected_CheckedPackagesCleared ()
+ {
+ CreateProject ();
+ AddOnePackageSourceToRegisteredSources ();
+ CreateViewModel ();
+ viewModel.PackageFeed.AddPackage ("A", "1.2");
+ viewModel.PackageFeed.AddPackage ("B", "1.3");
+ viewModel.ReadPackages ();
+ await viewModel.ReadPackagesTask;
+
+ viewModel.PackageViewModels [0].IsChecked = true;
+
+ Assert.AreEqual (2, viewModel.PackageViewModels.Count);
+ Assert.AreEqual (1, viewModel.CheckedPackageViewModels.Count);
+ Assert.AreEqual ("A", viewModel.CheckedPackageViewModels [0].Id);
+ Assert.IsFalse (viewModel.PackageViewModels [0].SelectLatestVersion);
+ Assert.IsFalse (viewModel.PackageViewModels [1].SelectLatestVersion);
+
+ viewModel.PageSelected = ManagePackagesPage.Consolidate;
+
+ Assert.AreEqual (0, viewModel.CheckedPackageViewModels.Count);
+ }
+
+ [Test]
+ public async Task Consolidate_ThreeProjectsTwoPackages_ProjectVersionAndSelectionInformationAvailable ()
+ {
+ CreateProject ();
+ project.Name = "LibA";
+ var nugetProject = CreateNuGetProjectForProject (project);
+ nugetProject.AddPackageReference ("Test", "0.1");
+
+ var project2 = AddProjectToSolution ("LibB");
+ nugetProject = CreateNuGetProjectForProject (project2);
+ nugetProject.AddPackageReference ("Other", "0.1");
+
+ var project3 = AddProjectToSolution ("LibC");
+ nugetProject = CreateNuGetProjectForProject (project3);
+ nugetProject.AddPackageReference ("Test", "0.2");
+ nugetProject.AddPackageReference ("Other", "0.3");
+
+ AddOnePackageSourceToRegisteredSources ();
+ CreateViewModelForSolution ();
+ viewModel.PackageFeed.AddPackage ("Test", "0.2");
+ viewModel.PackageFeed.AddPackage ("Other", "0.3");
+ viewModel.PageSelected = ManagePackagesPage.Consolidate;
+
+ viewModel.ReadPackages ();
+ await viewModel.ReadPackagesTask;
+
+ // Select Test package.
+ var package = viewModel.PackageViewModels [0];
+ viewModel.SelectedPackage = package;
+
+ Assert.AreEqual (2, viewModel.PackageViewModels.Count);
+ Assert.AreEqual ("Test", package.Id);
+ Assert.AreEqual ("0.2", package.Version.ToString ());
+ Assert.IsTrue (package.SelectLatestVersion);
+ Assert.AreEqual ("Other", viewModel.PackageViewModels [1].Id);
+ Assert.AreEqual ("0.3", viewModel.PackageViewModels [1].Version.ToString ());
+ Assert.IsTrue (viewModel.PackageViewModels [1].SelectLatestVersion);
+
+ Assert.AreEqual (3, viewModel.ProjectViewModels.Count);
+
+ var projectViewModel = viewModel.ProjectViewModels [0];
+ Assert.AreEqual ("LibA", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.1", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [1];
+ Assert.AreEqual ("LibC", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.2", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [2];
+ Assert.AreEqual ("LibB", projectViewModel.ProjectName);
+ Assert.AreEqual ("–", projectViewModel.PackageVersion);
+ Assert.IsFalse (projectViewModel.IsChecked);
+
+ // Check LibB, Uncheck LibC
+ viewModel.ProjectViewModels [2].IsChecked = true;
+ viewModel.ProjectViewModels [1].IsChecked = false;
+
+ // Select Other package
+ package = viewModel.PackageViewModels [1];
+ viewModel.SelectedPackage = package;
+
+ Assert.AreEqual (3, viewModel.ProjectViewModels.Count);
+
+ projectViewModel = viewModel.ProjectViewModels [0];
+ Assert.AreEqual ("LibB", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.1", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [1];
+ Assert.AreEqual ("LibC", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.3", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [2];
+ Assert.AreEqual ("LibA", projectViewModel.ProjectName);
+ Assert.AreEqual ("–", projectViewModel.PackageVersion);
+ Assert.IsFalse (projectViewModel.IsChecked);
+
+ // Select Test package again.
+ package = viewModel.PackageViewModels [0];
+ viewModel.SelectedPackage = package;
+
+ projectViewModel = viewModel.ProjectViewModels [0];
+ Assert.AreEqual ("LibA", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.1", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [1];
+ Assert.AreEqual ("LibC", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.2", projectViewModel.PackageVersion);
+ Assert.IsFalse (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [2];
+ Assert.AreEqual ("LibB", projectViewModel.ProjectName);
+ Assert.AreEqual ("–", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ // Check that the cached project information is cleared after selecting a different
+ // tab and going back to the consolidate tab.
+ viewModel.PageSelected = ManagePackagesPage.Browse;
+ viewModel.SelectedPackage = null;
+ viewModel.PageSelected = ManagePackagesPage.Consolidate;
+ package = viewModel.PackageViewModels [0];
+ viewModel.SelectedPackage = package;
+
+ projectViewModel = viewModel.ProjectViewModels [0];
+ Assert.AreEqual ("LibA", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.1", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [1];
+ Assert.AreEqual ("LibC", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.2", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [2];
+ Assert.AreEqual ("LibB", projectViewModel.ProjectName);
+ Assert.AreEqual ("–", projectViewModel.PackageVersion);
+ Assert.IsFalse (projectViewModel.IsChecked);
+ }
+
+ [Test]
+ public async Task Consolidate_ThreeProjectsTwoPackages_PackagesChecked_CheckedPackagesCanBeConsolidated ()
+ {
+ CreateProject ();
+ project.Name = "LibA";
+ var nugetProject = CreateNuGetProjectForProject (project);
+ nugetProject.AddPackageReference ("Test", "0.1");
+
+ var project2 = AddProjectToSolution ("LibB");
+ nugetProject = CreateNuGetProjectForProject (project2);
+ nugetProject.AddPackageReference ("Other", "0.1");
+
+ var project3 = AddProjectToSolution ("LibC");
+ nugetProject = CreateNuGetProjectForProject (project3);
+ nugetProject.AddPackageReference ("Test", "0.2");
+ nugetProject.AddPackageReference ("Other", "0.3");
+
+ AddOnePackageSourceToRegisteredSources ();
+ CreateViewModelForSolution ();
+ viewModel.PackageFeed.AddPackage ("Test", "0.2");
+ viewModel.PackageFeed.AddPackage ("Other", "0.3");
+ viewModel.PageSelected = ManagePackagesPage.Consolidate;
+
+ viewModel.ReadPackages ();
+ await viewModel.ReadPackagesTask;
+
+ // Select Test package.
+ var package = viewModel.PackageViewModels [0];
+ viewModel.SelectedPackage = package;
+
+ Assert.AreEqual (2, viewModel.PackageViewModels.Count);
+ Assert.AreEqual ("Test", package.Id);
+ Assert.AreEqual ("0.2", package.Version.ToString ());
+ Assert.AreEqual ("Other", viewModel.PackageViewModels [1].Id);
+ Assert.AreEqual ("0.3", viewModel.PackageViewModels [1].Version.ToString ());
+
+ // Checked packages first.
+ var projectViewModel = viewModel.ProjectViewModels [0];
+ Assert.AreEqual ("LibA", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.1", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [1];
+ Assert.AreEqual ("LibC", projectViewModel.ProjectName);
+ Assert.AreEqual ("0.2", projectViewModel.PackageVersion);
+ Assert.IsTrue (projectViewModel.IsChecked);
+
+ projectViewModel = viewModel.ProjectViewModels [2];
+ Assert.AreEqual ("LibB", projectViewModel.ProjectName);
+ Assert.AreEqual ("–", projectViewModel.PackageVersion);
+ Assert.IsFalse (projectViewModel.IsChecked);
+
+ viewModel.ProjectViewModels [0].IsChecked = false;
+ viewModel.ProjectViewModels [1].IsChecked = false;
+ viewModel.ProjectViewModels [2].IsChecked = false;
+
+ Assert.IsFalse (viewModel.CanConsolidate ());
+
+ // Select other package, check it, then switch back to
+ // Test package
+ package = viewModel.PackageViewModels [1];
+ viewModel.SelectedPackage = package;
+ package.IsChecked = true;
+ viewModel.SelectedPackage = viewModel.PackageViewModels [0];
+
+ // Should be able to consolidate since Other package is checked even though
+ // Test package is selected and cannot be consolidated.
+ Assert.IsTrue (viewModel.CanConsolidate ());
+
+ // Check Test package too.
+ viewModel.SelectedPackage.IsChecked = true;
+ var actions = viewModel.CreateConsolidatePackageActions (viewModel.PackageViewModels [0]).ToList ();
+ // Should be no actions since all projects are unchecked for this package.
+ Assert.AreEqual (0, actions.Count);
+
+ actions = viewModel.CreateConsolidatePackageActions (viewModel.PackageViewModels [1]).ToList ();
+ var action = actions [0] as InstallNuGetPackageAction;
+ Assert.AreEqual (1, actions.Count);
+ Assert.AreEqual ("Other", action.PackageId);
+ Assert.AreEqual ("0.3", action.Version.ToString ());
+ Assert.AreEqual ("LibB", action.Project.Name);
+ }
+
+ [Test]
+ public async Task CurrentVersion_OneUpdate_PackageVersionInstalledInProjectReturned ()
+ {
+ CreateProject ();
+ var nugetProject = CreateNuGetProjectForProject (project);
+ nugetProject.AddPackageReference ("Test", "0.1");
+ AddOnePackageSourceToRegisteredSources ();
+ CreateViewModel ();
+ viewModel.PackageFeed.AddPackage ("Test", "0.2");
+ viewModel.PageSelected = ManagePackagesPage.Browse;
+
+ viewModel.ReadPackages ();
+ await viewModel.ReadPackagesTask;
+
+ var package = viewModel.PackageViewModels.Single ();
+ Assert.AreEqual ("Test", package.Id);
+ Assert.AreEqual ("0.2", package.Version.ToString ());
+ Assert.AreEqual ("0.1", package.GetCurrentPackageVersionText ());
+ Assert.AreEqual (string.Empty, package.GetCurrentPackageVersionAdditionalText ());
+ }
+
+ [Test]
+ public async Task CurrentVersion_DifferentPackageVersionInstalledInProjects_MultipleReturned ()
+ {
+ CreateProject ();
+ CreateProject ();
+ project.Name = "LibC";
+ var nugetProject = CreateNuGetProjectForProject (project);
+ nugetProject.AddPackageReference ("Test", "0.1");
+
+ var project2 = AddProjectToSolution ("LibA");
+ CreateNuGetProjectForProject (project2);
+
+ var project3 = AddProjectToSolution ("LibB");
+ nugetProject = CreateNuGetProjectForProject (project3);
+ nugetProject.AddPackageReference ("Test", "0.2");
+
+ AddOnePackageSourceToRegisteredSources ();
+ CreateViewModelForSolution ();
+ viewModel.PackageFeed.AddPackage ("Test", "0.2");
+
+ viewModel.PageSelected = ManagePackagesPage.Browse;
+
+ viewModel.ReadPackages ();
+ await viewModel.ReadPackagesTask;
+
+ string expectedAdditionalText = "LibB: 0.2, LibC: 0.1";
+ var package = viewModel.PackageViewModels.Single ();
+ Assert.AreEqual ("Test", package.Id);
+ Assert.AreEqual ("0.2", package.Version.ToString ());
+ Assert.AreEqual ("Multiple", package.GetCurrentPackageVersionText ());
+ Assert.AreEqual (expectedAdditionalText, package.GetCurrentPackageVersionAdditionalText ());
+ }
}
}
-
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentNuGetPackagesRepositoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentManagedNuGetPackagesRepositoryTests.cs
index 9bd5595b66..0f327d163a 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentNuGetPackagesRepositoryTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentManagedNuGetPackagesRepositoryTests.cs
@@ -1,5 +1,5 @@
//
-// RecentNuGetPackagesRepositoryTests.cs
+// RecentManagedNuGetPackagesRepositoryTests.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -33,37 +33,37 @@ using NUnit.Framework;
namespace MonoDevelop.PackageManagement.Tests
{
[TestFixture]
- public class RecentNuGetPackagesRepositoryTests
+ public class RecentManagedNuGetPackagesRepositoryTests
{
- RecentNuGetPackagesRepository repository;
+ RecentManagedNuGetPackagesRepository repository;
void CreateRepository ()
{
- repository = new RecentNuGetPackagesRepository ();
+ repository = new RecentManagedNuGetPackagesRepository ();
}
- PackageSearchResultViewModel AddOnePackageToRepository (string id, string packageSource)
+ ManagePackagesSearchResultViewModel AddOnePackageToRepository (string id, string packageSource)
{
var viewModel = CreatePackage (id);
repository.AddPackage (viewModel, packageSource);
return viewModel;
}
- PackageSearchResultViewModel CreatePackage (string id)
+ ManagePackagesSearchResultViewModel CreatePackage (string id)
{
var packageViewModel = new PackageItemListViewModel {
Id = id
};
- return new PackageSearchResultViewModel (null, packageViewModel);
+ return new ManagePackagesSearchResultViewModel (null, packageViewModel);
}
- IEnumerable<PackageSearchResultViewModel> AddTwoDifferentPackagesToRepository (string packageSource)
+ IEnumerable<ManagePackagesSearchResultViewModel> AddTwoDifferentPackagesToRepository (string packageSource)
{
yield return AddOnePackageToRepository ("Test.Package.1", packageSource);
yield return AddOnePackageToRepository ("Test.Package.2", packageSource);
}
- IEnumerable<PackageSearchResultViewModel> AddFourDifferentPackagesToRepository (string packageSource)
+ IEnumerable<ManagePackagesSearchResultViewModel> AddFourDifferentPackagesToRepository (string packageSource)
{
yield return AddOnePackageToRepository ("Test.Package.1", packageSource);
yield return AddOnePackageToRepository ("Test.Package.2", packageSource);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml
index dc351294d4..19c48c6789 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml
@@ -22,6 +22,18 @@
_label = "Add NuGet _Packages..."
defaultHandler = "MonoDevelop.PackageManagement.Commands.AddPackagesHandler" />
<Command
+ id="MonoDevelop.PackageManagement.Commands.ManagePackages"
+ _description="Manage packages for the solution"
+ _label="_Manage NuGet Packages..."
+ _displayName="Manage Packages (Solution)"
+ defaultHandler="MonoDevelop.PackageManagement.ManagePackagesHandler" />
+ <Command
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject"
+ _description="Manage packages for the project"
+ _label="_Manage NuGet Packages..."
+ _displayName="Manage Packages"
+ defaultHandler="MonoDevelop.PackageManagement.ManagePackagesInProjectHandler" />
+ <Command
id = "MonoDevelop.PackageManagement.Commands.RestorePackages"
_description = "Restore all missing packages in the solution"
_label = "_Restore NuGet Packages"
@@ -65,7 +77,7 @@
<Extension path="/MonoDevelop/Ide/MainMenu/Project">
<SeparatorItem insertafter="MonoDevelop.Ide.Commands.ProjectCommands.AddReference" />
- <CommandItem id="MonoDevelop.PackageManagement.Commands.AddPackages" />
+ <CommandItem id="MonoDevelop.PackageManagement.Commands.ManagePackages" />
<CommandItem id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution" />
<CommandItem id="MonoDevelop.PackageManagement.Commands.RestorePackages" />
<SeparatorItem />
@@ -73,18 +85,36 @@
<Extension path="/MonoDevelop/Ide/ContextMenu/ProjectPad">
<Condition id="ItemType" value="Solution">
+ <SeparatorItem
+ id="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertafter="MonoDevelop.Ide.Commands.ProjectCommands.AddReference"
+ insertbefore="AddSectionEnd" />
+ <CommandItem
+ id="MonoDevelop.PackageManagement.Commands.ManagePackages"
+ insertafter="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertbefore="AddSectionEnd" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution"
- insertafter="MonoDevelop.PackageManagement.Commands.AddReference"
+ insertafter="MonoDevelop.PackageManagement.Commands.ManagePackagese"
insertbefore="AddSectionEnd" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.RestorePackages"
insertafter="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution"
insertbefore="AddSectionEnd" />
</Condition>
+ <Condition id="ItemType" value="DotNetProject">
+ <SeparatorItem
+ id="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertafter="MonoDevelop.Ide.Commands.ProjectCommands.AddReference"
+ insertbefore="AddSectionEnd" />
+ <CommandItem
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject"
+ insertafter="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertbefore="AddSectionEnd" />
+ </Condition>
<Condition id="ItemType" value="MonoDevelop.PackageManagement.NodeBuilders.ProjectPackagesFolderNode">
<CommandItem
- id="MonoDevelop.PackageManagement.Commands.AddPackages" _label = "Add NuGet _Packages..." />
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.PackagesFolderNodeCommands.ReinstallAllPackagesInProject" />
<CommandItem
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj
index 6d2e380db0..851b54e052 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj
@@ -102,10 +102,6 @@
<Compile Include="MonoDevelop.PackageManagement.Gui\PackageManagementOptionsPanel.cs" />
<Compile Include="MonoDevelop.PackageManagement.Gui\PackageManagementOptionsWidget.cs" />
<Compile Include="MonoDevelop.PackageManagement.Commands\AddPackagesHandler.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Gui\AddPackagesDialog.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Gui\AddPackagesDialog.UI.cs">
- <DependentUpon>AddPackagesDialog.cs</DependentUpon>
- </Compile>
<Compile Include="MonoDevelop.PackageManagement\PackageRepositoryNodeExtensions.cs" />
<Compile Include="MonoDevelop.PackageManagement\ProjectTemplateNuGetPackageInstaller.cs" />
<Compile Include="MonoDevelop.PackageManagement\PackageManagementEventsMonitor.cs" />
@@ -127,9 +123,7 @@
<Compile Include="MonoDevelop.PackageManagement\ProgressMonitorStatusMessageFactory.cs" />
<Compile Include="MonoDevelop.PackageManagement\ProgressMonitorStatusMessage.cs" />
<Compile Include="AddinInfo.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Gui\PackageCellView.cs" />
<Compile Include="MonoDevelop.PackageManagement\SearchPackagesSearchCategory.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Gui\AddPackagesDialogRunner.cs" />
<Compile Include="MonoDevelop.PackageManagement.Commands\ProjectPackagesFolderNodeCommandHandler.cs" />
<Compile Include="MonoDevelop.PackageManagement.NodeBuilders\ProjectReferenceNodeBuilderExtension.cs" />
<Compile Include="MonoDevelop.PackageManagement\ProjectReferenceExtensions.cs" />
@@ -142,7 +136,6 @@
<DependentUpon>AddPackageSourceDialog.cs</DependentUpon>
</Compile>
<Compile Include="MonoDevelop.PackageManagement.Gui\DialogExtensions.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Gui\PackageCellViewEventArgs.cs" />
<Compile Include="MonoDevelop.PackageManagement.Gui\Styles.cs" />
<Compile Include="MonoDevelop.PackageManagement\ImageLoader.cs" />
<Compile Include="MonoDevelop.PackageManagement\ImageLoadedEventArgs.cs" />
@@ -153,7 +146,7 @@
<Compile Include="MonoDevelop.PackageManagement\ImageCache.cs" />
<Compile Include="MonoDevelop.PackageManagement\ProgressMonitorExtensions.cs" />
<Compile Include="MonoDevelop.PackageManagement\PackageListViewTextFormatter.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Gui\PackageCellViewCheckBox.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesCellViewCheckBox.cs" />
<Compile Include="MonoDevelop.PackageManagement\PackageManagementProgressMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\ISolution.cs" />
<Compile Include="MonoDevelop.PackageManagement\IProject.cs" />
@@ -197,13 +190,11 @@
<Compile Include="MonoDevelop.PackageManagement\PackageManagementSolutionProjectService.cs" />
<Compile Include="MonoDevelop.PackageManagement\NuGetPackageNewImportsHandler.cs" />
<Compile Include="MonoDevelop.PackageManagement\INuGetPackageNewImportsHandler.cs" />
- <Compile Include="MonoDevelop.PackageManagement\AllPackagesViewModel.cs" />
<Compile Include="MonoDevelop.PackageManagement\SourceRepositoryProvider.cs" />
<Compile Include="NuGet.PackageManagement.UI\SearchResult.cs" />
<Compile Include="NuGet.PackageManagement.UI\PackageItemListViewModel.cs" />
<Compile Include="NuGet.PackageManagement.UI\PackageStatus.cs" />
<Compile Include="NuGet.PackageManagement.UI\DisplayVersion.cs" />
- <Compile Include="MonoDevelop.PackageManagement\PackageSearchResultViewModel.cs" />
<Compile Include="MonoDevelop.PackageManagement\SourceRepositoryViewModel.cs" />
<Compile Include="MonoDevelop.PackageManagement\InstallNuGetPackageAction.cs" />
<Compile Include="MonoDevelop.PackageManagement\MonoDevelopSolutionManager.cs" />
@@ -270,8 +261,6 @@
<Compile Include="NuGet.PackageManagement.UI\IPackageMetadataProvider.cs" />
<Compile Include="NuGet.PackageManagement.UI\DetailControlModel.cs" />
<Compile Include="NuGet.PackageManagement.UI\PackageDetailControlModel.cs" />
- <Compile Include="MonoDevelop.PackageManagement\RecentNuGetPackagesRepository.cs" />
- <Compile Include="MonoDevelop.PackageManagement\PackageSearchResultViewModelComparer.cs" />
<Compile Include="MonoDevelop.PackageManagement\MonoDevelopPackageSourceProvider.cs" />
<Compile Include="MonoDevelop.PackageManagement\SettingsLoader.cs" />
<Compile Include="MonoDevelop.PackageManagement\INuGetPackageManager.cs" />
@@ -347,6 +336,35 @@
<Compile Include="MonoDevelop.PackageManagement\SdkProjectReloadMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\SdkProjectBuilderMaintainer.cs" />
<Compile Include="MonoDevelop.PackageManagement\SdkProjectFileRenamedHandler.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Commands\ManagePackagesHandler.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Commands\ManagePackagesInProjectHandler.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesDialog.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesDialog.UI.cs">
+ <DependentUpon>ManagePackagesDialog.cs</DependentUpon>
+ </Compile>
+ <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesDialogRunner.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Gui\SelectProjectsDialog.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Gui\SelectProjectsDialog.UI.cs">
+ <DependentUpon>SelectProjectsDialog.cs</DependentUpon>
+ </Compile>
+ <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesCellView.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesCellViewEventArgs.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\ManagedPackagesSearchResultViewModelComparer.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\ManagePackagesPage.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\ManagePackagesProjectInfo.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\ManagePackagesSearchResultViewModel.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\ManagePackagesViewModel.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\ConsolidatePackageFeed.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\InstalledPackageFeed.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\PackageCollection.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\PackageFeedEnumerator.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\PackageSearchMetadataCache.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\PlainPackageFeedBase.cs" />
+ <Compile Include="NuGet.PackageManagement.UI\UpdatePackageFeed.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\SelectedProjectViewModel.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\SelectProjectsViewModel.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\RecentManagedNuGetPackagesRepository.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\ManageProjectViewModel.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MonoDevelop.PackageManagement.addin.xml" />
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs
deleted file mode 100644
index f1c5036f80..0000000000
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs
+++ /dev/null
@@ -1,608 +0,0 @@
-//
-// AllPackagesViewModel.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2016 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.Collections.ObjectModel;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MonoDevelop.Core;
-using MonoDevelop.Ide;
-using MonoDevelop.Projects;
-using NuGet.Configuration;
-using NuGet.PackageManagement;
-using NuGet.PackageManagement.UI;
-using NuGet.Packaging;
-using NuGet.ProjectManagement;
-using NuGet.Protocol.Core.Types;
-using NuGet.Versioning;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class AllPackagesViewModel : ViewModelBase<AllPackagesViewModel>, INuGetUILogger
- {
- SourceRepositoryViewModel selectedPackageSource;
- IPackageSourceProvider packageSourceProvider;
- PackageItemLoader currentLoader;
- CancellationTokenSource cancellationTokenSource;
- List<SourceRepositoryViewModel> packageSources;
- bool includePrerelease;
- bool ignorePackageCheckedChanged;
- IMonoDevelopSolutionManager solutionManager;
- NuGetProject nugetProject;
- IDotNetProject dotNetProject;
- INuGetProjectContext projectContext;
- List<PackageReference> packageReferences = new List<PackageReference> ();
- AggregatePackageSourceErrorMessage aggregateErrorMessage;
- NuGetPackageManager packageManager;
- RecentNuGetPackagesRepository recentPackagesRepository;
-
- public static AllPackagesViewModel Create (RecentNuGetPackagesRepository recentPackagesRepository)
- {
- var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (IdeApp.ProjectOperations.CurrentSelectedSolution);
- var dotNetProject = new DotNetProjectProxy ((DotNetProject)IdeApp.ProjectOperations.CurrentSelectedProject);
- return new AllPackagesViewModel (solutionManager, dotNetProject, recentPackagesRepository);
- }
-
- public static AllPackagesViewModel Create (
- DotNetProject project,
- RecentNuGetPackagesRepository recentPackagesRepository)
- {
- if (project == null)
- return Create (recentPackagesRepository);
-
- var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (project.ParentSolution);
- var dotNetProject = new DotNetProjectProxy (project);
- return new AllPackagesViewModel (solutionManager, dotNetProject, recentPackagesRepository);
- }
-
- public AllPackagesViewModel (
- IMonoDevelopSolutionManager solutionManager,
- IDotNetProject dotNetProject,
- RecentNuGetPackagesRepository recentPackagesRepository)
- : this (
- solutionManager,
- dotNetProject,
- new NuGetProjectContext (solutionManager.Settings),
- recentPackagesRepository)
- {
- }
-
- public AllPackagesViewModel (
- IMonoDevelopSolutionManager solutionManager,
- IDotNetProject dotNetProject,
- INuGetProjectContext projectContext,
- RecentNuGetPackagesRepository recentPackagesRepository)
- {
- this.solutionManager = solutionManager;
- this.dotNetProject = dotNetProject;
- this.projectContext = projectContext;
- this.recentPackagesRepository = recentPackagesRepository;
- PackageViewModels = new ObservableCollection<PackageSearchResultViewModel> ();
- CheckedPackageViewModels = new ObservableCollection<PackageSearchResultViewModel> ();
- ErrorMessage = String.Empty;
-
- packageManager = new NuGetPackageManager (
- solutionManager.CreateSourceRepositoryProvider (),
- solutionManager.Settings,
- solutionManager,
- new DeleteOnRestartManager ()
- );
-
- nugetProject = solutionManager.GetNuGetProject (dotNetProject);
- GetPackagesInstalledInProject ();
- }
-
- public NuGetProject NuGetProject {
- get { return nugetProject; }
- }
-
- public IDotNetProject Project {
- get { return dotNetProject; }
- }
-
- public string SearchTerms { get; set; }
-
- public IEnumerable<SourceRepositoryViewModel> PackageSources {
- get {
- if (packageSources == null) {
- packageSources = GetPackageSources ().ToList ();
- }
- return packageSources;
- }
- }
-
- IEnumerable<SourceRepositoryViewModel> GetPackageSources ()
- {
- ISourceRepositoryProvider provider = solutionManager.CreateSourceRepositoryProvider ();
- packageSourceProvider = provider.PackageSourceProvider;
- var repositories = provider.GetRepositories ().ToList ();
-
- if (repositories.Count > 1) {
- yield return new AggregateSourceRepositoryViewModel (repositories);
- }
-
- foreach (SourceRepository repository in repositories) {
- yield return new SourceRepositoryViewModel (repository);
- }
- }
-
- public SourceRepositoryViewModel SelectedPackageSource {
- get {
- if (selectedPackageSource == null) {
- selectedPackageSource = GetActivePackageSource ();
- }
- return selectedPackageSource;
- }
- set {
- if (selectedPackageSource != value) {
- selectedPackageSource = value;
- SaveActivePackageSource ();
- ReadPackages ();
- OnPropertyChanged (null);
- }
- }
- }
-
- SourceRepositoryViewModel GetActivePackageSource ()
- {
- if (packageSources == null)
- return null;
-
- if (!String.IsNullOrEmpty (packageSourceProvider.ActivePackageSourceName)) {
- SourceRepositoryViewModel packageSource = packageSources
- .FirstOrDefault (viewModel => String.Equals (viewModel.PackageSource.Name, packageSourceProvider.ActivePackageSourceName, StringComparison.CurrentCultureIgnoreCase));
- if (packageSource != null) {
- return packageSource;
- }
- }
-
- return packageSources.FirstOrDefault (packageSource => !packageSource.IsAggregate);
- }
-
- void SaveActivePackageSource ()
- {
- if (selectedPackageSource == null || packageSourceProvider == null)
- return;
-
- packageSourceProvider.SaveActivePackageSource (selectedPackageSource.PackageSource);
- }
-
- public ObservableCollection<PackageSearchResultViewModel> PackageViewModels { get; private set; }
- public ObservableCollection<PackageSearchResultViewModel> CheckedPackageViewModels { get; private set; }
-
- public bool HasError { get; private set; }
- public string ErrorMessage { get; private set; }
-
- public bool IsLoadingNextPage { get; private set; }
- public bool IsReadingPackages { get; private set; }
- public bool HasNextPage { get; private set; }
-
- public bool IncludePrerelease {
- get { return includePrerelease; }
- set {
- if (includePrerelease != value) {
- includePrerelease = value;
- ReadPackages ();
- OnPropertyChanged (null);
- }
- }
- }
-
- public void Dispose()
- {
- OnDispose ();
- CancelReadPackagesTask ();
- IsDisposed = true;
- }
-
- protected virtual void OnDispose()
- {
- }
-
- public bool IsDisposed { get; private set; }
-
- public void Search ()
- {
- ReadPackages ();
- OnPropertyChanged (null);
- }
-
- public void ReadPackages ()
- {
- if (SelectedPackageSource == null) {
- return;
- }
-
- HasNextPage = false;
- IsLoadingNextPage = false;
- currentLoader = null;
- StartReadPackagesTask ();
- }
-
- void StartReadPackagesTask (bool clearPackages = true)
- {
- IsReadingPackages = true;
- ClearError ();
- if (clearPackages) {
- CancelReadPackagesTask ();
- ClearPackages ();
- }
- CreateReadPackagesTask ();
- }
-
- void CancelReadPackagesTask()
- {
- if (cancellationTokenSource != null) {
- // Cancel on another thread since CancellationTokenSource.Cancel can sometimes
- // take up to a second on Mono and we do not want to block the UI thread.
- var tokenSource = cancellationTokenSource;
- Task.Run (() => {
- try {
- tokenSource.Cancel ();
- tokenSource.Dispose ();
- } catch (Exception ex) {
- LoggingService.LogError ("Unable to cancel task.", ex);
- }
- });
- cancellationTokenSource = null;
- }
- }
-
- protected virtual Task CreateReadPackagesTask()
- {
- var loader = currentLoader ?? CreatePackageLoader ();
- cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource ();
- return LoadPackagesAsync (loader, cancellationTokenSource.Token)
- .ContinueWith (t => OnPackagesRead (t, loader), TaskScheduler.FromCurrentSynchronizationContext ());
- }
-
- PackageItemLoader CreatePackageLoader ()
- {
- var context = new PackageLoadContext (
- selectedPackageSource.GetSourceRepositories (),
- false,
- nugetProject);
-
- var loader = new PackageItemLoader (
- context,
- CreatePackageFeed (context.SourceRepositories),
- SearchTerms,
- IncludePrerelease
- );
-
- currentLoader = loader;
-
- return loader;
- }
-
- protected virtual IPackageFeed CreatePackageFeed (IEnumerable<SourceRepository> sourceRepositories)
- {
- return new MultiSourcePackageFeed (sourceRepositories, this);
- }
-
- protected virtual Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token)
- {
- return Task.Run (async () => {
- await loader.LoadNextAsync (null, token);
-
- while (loader.State.LoadingStatus == LoadingStatus.Loading) {
- token.ThrowIfCancellationRequested ();
- await loader.UpdateStateAsync (null, token);
- }
- });
- }
-
- void ClearError ()
- {
- HasError = false;
- ErrorMessage = String.Empty;
- aggregateErrorMessage = new AggregatePackageSourceErrorMessage (GetTotalPackageSources ());
- }
-
- int GetTotalPackageSources ()
- {
- if (selectedPackageSource != null) {
- return selectedPackageSource.GetSourceRepositories ().Count ();
- }
- return 0;
- }
-
- public void ShowNextPage ()
- {
- IsLoadingNextPage = true;
- StartReadPackagesTask (false);
- base.OnPropertyChanged (null);
- }
-
- void OnPackagesRead (Task task, PackageItemLoader loader)
- {
- IsReadingPackages = false;
- IsLoadingNextPage = false;
- if (task.IsFaulted) {
- SaveError (task.Exception);
- } else if (task.IsCanceled || !IsCurrentQuery (loader)) {
- // Ignore.
- return;
- } else {
- SaveAnyWarnings ();
- UpdatePackagesForSelectedPage (loader);
- }
- base.OnPropertyChanged (null);
- }
-
- bool IsCurrentQuery (PackageItemLoader loader)
- {
- return currentLoader == loader;
- }
-
- void SaveError (AggregateException ex)
- {
- HasError = true;
- ErrorMessage = GetErrorMessage (ex);
- LoggingService.LogInfo ("PackagesViewModel error", ex);
- }
-
- string GetErrorMessage (AggregateException ex)
- {
- var errorMessage = new AggregateExceptionErrorMessage (ex);
- return errorMessage.ToString ();
- }
-
- void SaveAnyWarnings ()
- {
- string warning = GetWarningMessage ();
- if (!String.IsNullOrEmpty (warning)) {
- HasError = true;
- ErrorMessage = warning;
- }
- }
-
- protected virtual string GetWarningMessage ()
- {
- return String.Empty;
- }
-
- void UpdatePackagesForSelectedPage (PackageItemLoader loader)
- {
- HasNextPage = loader.State.LoadingStatus == LoadingStatus.Ready;
-
- UpdatePackageViewModels (loader.GetCurrent ());
- }
-
- void UpdatePackageViewModels (IEnumerable<PackageItemListViewModel> newPackageViewModels)
- {
- var packages = ConvertToPackageViewModels (newPackageViewModels).ToList ();
- packages = PrioritizePackages (packages).ToList ();
-
- foreach (PackageSearchResultViewModel packageViewModel in packages) {
- PackageViewModels.Add (packageViewModel);
- }
- }
-
- public IEnumerable<PackageSearchResultViewModel> ConvertToPackageViewModels (IEnumerable<PackageItemListViewModel> itemViewModels)
- {
- foreach (PackageItemListViewModel itemViewModel in itemViewModels) {
- PackageSearchResultViewModel packageViewModel = CreatePackageViewModel (itemViewModel);
- UpdatePackageViewModelIfPreviouslyChecked (packageViewModel);
- yield return packageViewModel;
- }
- }
-
- PackageSearchResultViewModel CreatePackageViewModel (PackageItemListViewModel viewModel)
- {
- return new PackageSearchResultViewModel (this, viewModel);
- }
-
- void ClearPackages ()
- {
- PackageViewModels.Clear();
- }
-
- public void OnPackageCheckedChanged (PackageSearchResultViewModel packageViewModel)
- {
- if (ignorePackageCheckedChanged)
- return;
-
- if (packageViewModel.IsChecked) {
- UncheckExistingCheckedPackageWithDifferentVersion (packageViewModel);
- CheckedPackageViewModels.Add (packageViewModel);
- } else {
- CheckedPackageViewModels.Remove (packageViewModel);
- }
- }
-
- void UpdatePackageViewModelIfPreviouslyChecked (PackageSearchResultViewModel packageViewModel)
- {
- ignorePackageCheckedChanged = true;
- try {
- PackageSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id);
- if (existingPackageViewModel != null) {
- packageViewModel.UpdateFromPreviouslyCheckedViewModel (existingPackageViewModel);
- CheckedPackageViewModels.Remove (existingPackageViewModel);
- CheckedPackageViewModels.Add (packageViewModel);
- }
- } finally {
- ignorePackageCheckedChanged = false;
- }
- }
-
- void UncheckExistingCheckedPackageWithDifferentVersion (PackageSearchResultViewModel packageViewModel)
- {
- PackageSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id);
-
- if (existingPackageViewModel != null) {
- CheckedPackageViewModels.Remove (existingPackageViewModel);
- existingPackageViewModel.IsChecked = false;
- }
- }
-
- PackageSearchResultViewModel GetExistingCheckedPackageViewModel (string packageId)
- {
- return CheckedPackageViewModels
- .FirstOrDefault (item => item.Id == packageId);
- }
-
- public IPackageAction CreateInstallPackageAction (PackageSearchResultViewModel packageViewModel)
- {
- return new InstallNuGetPackageAction (
- SelectedPackageSource.GetSourceRepositories (),
- solutionManager,
- dotNetProject,
- projectContext
- ) {
- IncludePrerelease = IncludePrerelease,
- PackageId = packageViewModel.Id,
- Version = packageViewModel.SelectedVersion
- };
- }
-
- public PackageSearchResultViewModel SelectedPackage { get; set; }
-
- public bool IsOlderPackageInstalled (string id, NuGetVersion version)
- {
- return packageReferences.Any (packageReference => IsOlderPackageInstalled (packageReference, id, version));
- }
-
- bool IsOlderPackageInstalled (PackageReference packageReference, string id, NuGetVersion version)
- {
- return packageReference.PackageIdentity.Id == id &&
- packageReference.PackageIdentity.Version < version;
- }
-
- protected virtual Task GetPackagesInstalledInProject ()
- {
- return nugetProject
- .GetInstalledPackagesAsync (CancellationToken.None)
- .ContinueWith (task => OnReadInstalledPackages (task), TaskScheduler.FromCurrentSynchronizationContext ());
- }
-
- void OnReadInstalledPackages (Task<IEnumerable<PackageReference>> task)
- {
- try {
- if (task.IsFaulted) {
- LoggingService.LogError ("Unable to read installed packages.", task.Exception);
- } else {
- packageReferences = task.Result.ToList ();
- }
- } catch (Exception ex) {
- LoggingService.LogError ("OnReadInstalledPackages", ex);
- }
- }
-
- void INuGetUILogger.Log (MessageLevel level, string message, params object [] args)
- {
- if (level == MessageLevel.Error) {
- string fullErrorMessage = String.Format (message, args);
- AppendErrorMessage (fullErrorMessage);
- }
- }
-
- void AppendErrorMessage (string message)
- {
- aggregateErrorMessage.AddError (message);
- ErrorMessage = aggregateErrorMessage.ErrorMessage;
- HasError = true;
- OnPropertyChanged (null);
- }
-
- public void LoadPackageMetadata (PackageSearchResultViewModel packageViewModel)
- {
- var provider = new MultiSourcePackageMetadataProvider (
- selectedPackageSource.GetSourceRepositories (),
- packageManager.PackagesFolderSourceRepository,
- packageManager.GlobalPackageFolderRepositories,
- new [] { NuGetProject },
- false,
- new NuGet.Common.NullLogger ());
-
- packageViewModel.LoadPackageMetadata (provider, cancellationTokenSource.Token);
- }
-
- public void OnInstallingSelectedPackages ()
- {
- try {
- UpdateRecentPackages ();
- } catch (Exception ex) {
- LoggingService.LogError ("Unable to update recent packages", ex);
- }
- }
-
- void UpdateRecentPackages ()
- {
- if (SelectedPackageSource == null)
- return;
-
- if (CheckedPackageViewModels.Any ()) {
- foreach (PackageSearchResultViewModel packageViewModel in CheckedPackageViewModels) {
- recentPackagesRepository.AddPackage (packageViewModel, SelectedPackageSource.Name);
- }
- } else {
- recentPackagesRepository.AddPackage (SelectedPackage, SelectedPackageSource.Name);
- }
- }
-
- IEnumerable<PackageSearchResultViewModel> PrioritizePackages (IEnumerable<PackageSearchResultViewModel> packages)
- {
- var recentPackages = GetRecentPackages ().ToList ();
-
- foreach (PackageSearchResultViewModel package in recentPackages) {
- package.Parent = this;
- package.ResetForRedisplay (IncludePrerelease);
- yield return package;
- }
-
- foreach (PackageSearchResultViewModel package in packages) {
- if (!recentPackages.Contains (package, PackageSearchResultViewModelComparer.Instance)) {
- yield return package;
- }
- }
- }
-
- IEnumerable<PackageSearchResultViewModel> GetRecentPackages ()
- {
- if (PackageViewModels.Count == 0 &&
- String.IsNullOrEmpty (SearchTerms) &&
- selectedPackageSource != null) {
- return recentPackagesRepository.GetPackages (SelectedPackageSource.Name)
- .Where (SelectedVersionMatchesIncludePreleaseFilter);
- }
-
- return Enumerable.Empty<PackageSearchResultViewModel> ();
- }
-
- bool SelectedVersionMatchesIncludePreleaseFilter (PackageSearchResultViewModel package)
- {
- if (package.SelectedVersion.IsPrerelease) {
- return IncludePrerelease;
- }
-
- return true;
- }
- }
-}
-
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs
index c3d79c8989..25d00c0ccc 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs
@@ -226,6 +226,10 @@ namespace MonoDevelop.PackageManagement
return Version?.IsPrerelease == true;
}
+ internal IDotNetProject Project {
+ get { return dotNetProject; }
+ }
+
public bool IsForProject (DotNetProject project)
{
return dotNetProject.DotNetProject == project;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs
new file mode 100644
index 0000000000..3f2f1cd3bb
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs
@@ -0,0 +1,36 @@
+//
+// ManagePackagesPage.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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.
+
+namespace MonoDevelop.PackageManagement
+{
+ enum ManagePackagesPage
+ {
+ Browse,
+ Installed,
+ Updates,
+ Consolidate
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs
new file mode 100644
index 0000000000..91f32d76b9
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs
@@ -0,0 +1,60 @@
+//
+// ManagePackagesProjectInfo.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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 NuGet.Packaging.Core;
+using NuGet.Packaging;
+using System.Collections.Immutable;
+
+namespace MonoDevelop.PackageManagement
+{
+ class ManagePackagesProjectInfo : IComparable<ManagePackagesProjectInfo>
+ {
+ readonly ImmutableArray<PackageReference> packages;
+
+ public ManagePackagesProjectInfo (IDotNetProject project, IEnumerable<PackageReference> packages)
+ {
+ Project = project;
+ this.packages = ImmutableArray<PackageReference>.Empty.AddRange (packages);
+ }
+
+ public IDotNetProject Project { get; }
+
+ public IEnumerable<PackageIdentity> Packages {
+ get { return packages.Select (p => p.PackageIdentity); }
+ }
+
+ public int CompareTo (ManagePackagesProjectInfo other)
+ {
+ if (other == null)
+ return 1;
+
+ return string.Compare (Project.Name, other.Project.Name, StringComparison.CurrentCulture);
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesSearchResultViewModel.cs
index 2005caeaf0..6aa0d2c97a 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesSearchResultViewModel.cs
@@ -1,453 +1,472 @@
-//
-// PackageSearchResultViewModel.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2016 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.Collections.ObjectModel;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MonoDevelop.Core;
-using NuGet.Common;
-using NuGet.PackageManagement.UI;
-using NuGet.Packaging.Core;
-using NuGet.Protocol.Core.Types;
-using NuGet.Frameworks;
-using NuGet.Versioning;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class PackageSearchResultViewModel : ViewModelBase<PackageSearchResultViewModel>
- {
- AllPackagesViewModel parent;
- PackageItemListViewModel viewModel;
- PackageDetailControlModel packageDetailModel;
- List<PackageDependencyMetadata> dependencies;
- string summary;
- bool isChecked;
-
- public PackageSearchResultViewModel (
- AllPackagesViewModel parent,
- PackageItemListViewModel viewModel)
- {
- this.parent = parent;
- this.viewModel = viewModel;
-
- Versions = new ObservableCollection<NuGetVersion> ();
- SelectedVersion = Version;
- }
-
- public AllPackagesViewModel Parent {
- get { return parent; }
- set { parent = value; }
- }
-
- public string Id {
- get { return viewModel.Id; }
- }
-
- public NuGetVersion Version {
- get { return viewModel.Version; }
- }
-
- public string Title {
- get { return viewModel.Title; }
- }
-
- public string Name {
- get {
- if (String.IsNullOrEmpty (Title))
- return Id;
-
- return Title;
- }
- }
-
- public bool IsChecked {
- get { return isChecked; }
- set {
- if (value != isChecked) {
- isChecked = value;
- parent.OnPackageCheckedChanged (this);
- }
- }
- }
-
- public bool HasLicenseUrl {
- get { return LicenseUrl != null; }
- }
-
- public Uri LicenseUrl {
- get { return viewModel.LicenseUrl; }
- }
-
- public bool HasProjectUrl {
- get { return ProjectUrl != null; }
- }
-
- public Uri ProjectUrl {
- get { return viewModel.ProjectUrl; }
- }
-
- public bool HasGalleryUrl {
- get { return GalleryUrl != null; }
- }
-
- public bool HasNoGalleryUrl {
- get { return !HasGalleryUrl; }
- }
-
- public Uri GalleryUrl {
- get { return null; }
- //get { return viewModel.GalleryUrl; }
- }
-
- public Uri IconUrl {
- get { return viewModel.IconUrl; }
- }
-
- public bool HasIconUrl {
- get { return IconUrl != null; }
- }
-
- public string Author {
- get { return viewModel.Author; }
- }
-
- public string Summary {
- get {
- if (summary == null) {
- summary = StripNewLinesAndIndentation (GetSummaryOrDescription ());
- }
- return summary;
- }
- }
-
- string GetSummaryOrDescription ()
- {
- if (String.IsNullOrEmpty (viewModel.Summary))
- return viewModel.Description;
- return viewModel.Summary;
- }
-
- string StripNewLinesAndIndentation (string text)
- {
- return PackageListViewTextFormatter.Format (text);
- }
-
- public string Description {
- get { return viewModel.Description; }
- }
-
- public bool HasDownloadCount {
- get { return viewModel.DownloadCount >= 0; }
- }
-
- public string GetIdMarkup ()
- {
- return GetBoldText (Id);
- }
-
- public string GetNameMarkup ()
- {
- return GetBoldText (Name);
- }
-
- static string GetBoldText (string text)
- {
- return String.Format ("<b>{0}</b>", text);
- }
-
- public string GetDownloadCountOrVersionDisplayText ()
- {
- if (ShowVersionInsteadOfDownloadCount) {
- return Version.ToString ();
- }
-
- return GetDownloadCountDisplayText ();
- }
-
- public string GetDownloadCountDisplayText ()
- {
- if (HasDownloadCount) {
- return viewModel.DownloadCount.Value.ToString ("N0");
- }
- return String.Empty;
- }
-
- public bool ShowVersionInsteadOfDownloadCount { get; set; }
-
- public DateTimeOffset? LastPublished {
- get { return viewModel.Published; }
- }
-
- public bool HasLastPublished {
- get { return viewModel.Published.HasValue; }
- }
-
- public string GetLastPublishedDisplayText()
- {
- if (HasLastPublished) {
- return LastPublished.Value.Date.ToShortDateString ();
- }
- return String.Empty;
- }
-
- public NuGetVersion SelectedVersion { get; set; }
- public ObservableCollection<NuGetVersion> Versions { get; private set; }
-
- protected virtual Task ReadVersions (CancellationToken cancellationToken)
- {
- try {
- packageDetailModel = new PackageDetailControlModel (parent.NuGetProject);
- packageDetailModel.SelectedVersion = new DisplayVersion (SelectedVersion, null);
- return ReadVersionsFromPackageDetailControlModel (cancellationToken).ContinueWith (
- task => OnVersionsRead (task),
- TaskScheduler.FromCurrentSynchronizationContext ());
- } catch (Exception ex) {
- LoggingService.LogError ("ReadVersions error.", ex);
- }
- return Task.FromResult (0);
- }
-
- Task ReadVersionsFromPackageDetailControlModel (CancellationToken cancellationToken)
- {
- if (!IsRecentPackage) {
- return packageDetailModel.SetCurrentPackage (viewModel);
- }
-
- return ReadVersionsForRecentPackage (cancellationToken);
- }
-
- async Task ReadVersionsForRecentPackage (CancellationToken cancellationToken)
- {
- var identity = new PackageIdentity (viewModel.Id, viewModel.Version);
- foreach (var sourceRepository in parent.SelectedPackageSource.GetSourceRepositories ()) {
- try {
- var metadata = await sourceRepository.GetPackageMetadataAsync (identity, parent.IncludePrerelease, cancellationToken);
- if (metadata != null) {
- var packageViewModel = CreatePackageItemListViewModel (metadata);
- await packageDetailModel.SetCurrentPackage (packageViewModel);
- return;
- }
- } catch (Exception ex) {
- LoggingService.LogError (
- String.Format ("Unable to get metadata for {0} from source {1}.", identity, sourceRepository.PackageSource.Name),
- ex);
- }
- }
- }
-
- PackageItemListViewModel CreatePackageItemListViewModel (IPackageSearchMetadata metadata)
- {
- return new PackageItemListViewModel {
- Id = metadata.Identity.Id,
- Version = metadata.Identity.Version,
- IconUrl = metadata.IconUrl,
- Author = metadata.Authors,
- DownloadCount = metadata.DownloadCount,
- Summary = metadata.Summary,
- Description = metadata.Description,
- Title = metadata.Title,
- LicenseUrl = metadata.LicenseUrl,
- ProjectUrl = metadata.ProjectUrl,
- Published = metadata.Published,
- Versions = AsyncLazy.New (() => metadata.GetVersionsAsync ())
- };
- }
-
- void OnVersionsRead (Task task)
- {
- try {
- if (task.IsFaulted) {
- LoggingService.LogError ("Failed to read package versions.", task.Exception);
- } else if (task.IsCanceled) {
- // Ignore.
- } else {
- Versions.Clear ();
- foreach (NuGetVersion version in packageDetailModel.AllPackageVersions.OrderByDescending (v => v.Version)) {
- Versions.Add (version);
- }
- OnPropertyChanged (viewModel => viewModel.Versions);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Failed to read package versions.", ex);
- }
- }
-
- public bool IsOlderPackageInstalled ()
- {
- return parent.IsOlderPackageInstalled (Id, SelectedVersion);
- }
-
- public override bool Equals (object obj)
- {
- var other = obj as PackageSearchResultViewModel;
- if (other == null)
- return false;
-
- return StringComparer.OrdinalIgnoreCase.Equals (Id, other.Id);
- }
-
- public override int GetHashCode ()
- {
- return Id.GetHashCode ();
- }
-
- public void UpdateFromPreviouslyCheckedViewModel (PackageSearchResultViewModel packageViewModel)
+//
+// ManagedPackagesSearchResultViewModel.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using NuGet.Common;
+using NuGet.PackageManagement.UI;
+using NuGet.Packaging.Core;
+using NuGet.Protocol.Core.Types;
+using NuGet.Frameworks;
+using NuGet.Versioning;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal class ManagePackagesSearchResultViewModel : ViewModelBase<ManagePackagesSearchResultViewModel>
+ {
+ ManagePackagesViewModel parent;
+ PackageItemListViewModel viewModel;
+ PackageDetailControlModel packageDetailModel;
+ PackageDependencyMetadata[] dependencies;
+ string summary;
+ bool isChecked;
+
+ public ManagePackagesSearchResultViewModel (
+ ManagePackagesViewModel parent,
+ PackageItemListViewModel viewModel)
+ {
+ this.parent = parent;
+ this.viewModel = viewModel;
+
+ Versions = new ObservableCollection<NuGetVersion> ();
+ SelectedVersion = Version;
+ }
+
+ public ManagePackagesViewModel Parent {
+ get { return parent; }
+ set { parent = value; }
+ }
+
+ public string Id {
+ get { return viewModel.Id; }
+ }
+
+ public NuGetVersion Version {
+ get { return viewModel.Version; }
+ }
+
+ public string Title {
+ get { return viewModel.Title; }
+ }
+
+ public string Name {
+ get {
+ if (String.IsNullOrEmpty (Title))
+ return Id;
+
+ return Title;
+ }
+ }
+
+ public bool IsChecked {
+ get { return isChecked; }
+ set {
+ if (value != isChecked) {
+ isChecked = value;
+ parent.OnPackageCheckedChanged (this);
+ }
+ }
+ }
+
+ public bool HasLicenseUrl {
+ get { return LicenseUrl != null; }
+ }
+
+ public Uri LicenseUrl {
+ get { return viewModel.LicenseUrl; }
+ }
+
+ public bool HasProjectUrl {
+ get { return ProjectUrl != null; }
+ }
+
+ public Uri ProjectUrl {
+ get { return viewModel.ProjectUrl; }
+ }
+
+ public bool HasGalleryUrl {
+ get { return GalleryUrl != null; }
+ }
+
+ public bool HasNoGalleryUrl {
+ get { return !HasGalleryUrl; }
+ }
+
+ public Uri GalleryUrl {
+ get { return null; }
+ //get { return viewModel.GalleryUrl; }
+ }
+
+ public Uri IconUrl {
+ get { return viewModel.IconUrl; }
+ }
+
+ public bool HasIconUrl {
+ get { return IconUrl != null; }
+ }
+
+ public string Author {
+ get { return viewModel.Author; }
+ }
+
+ public string Summary {
+ get {
+ if (summary == null) {
+ summary = StripNewLinesAndIndentation (GetSummaryOrDescription ());
+ }
+ return summary;
+ }
+ }
+
+ string GetSummaryOrDescription ()
+ {
+ if (String.IsNullOrEmpty (viewModel.Summary))
+ return viewModel.Description;
+ return viewModel.Summary;
+ }
+
+ string StripNewLinesAndIndentation (string text)
+ {
+ return PackageListViewTextFormatter.Format (text);
+ }
+
+ public string Description {
+ get { return viewModel.Description; }
+ }
+
+ public bool HasDownloadCount {
+ get { return viewModel.DownloadCount >= 0; }
+ }
+
+ public string GetIdMarkup ()
+ {
+ return GetBoldText (Id);
+ }
+
+ public string GetNameMarkup ()
+ {
+ return GetBoldText (Name);
+ }
+
+ static string GetBoldText (string text)
+ {
+ return String.Format ("<b>{0}</b>", text);
+ }
+
+ public string GetDownloadCountOrVersionDisplayText ()
+ {
+ if (ShowVersionInsteadOfDownloadCount) {
+ return Version.ToString ();
+ }
+
+ return GetDownloadCountDisplayText ();
+ }
+
+ public string GetDownloadCountDisplayText ()
+ {
+ if (HasDownloadCount) {
+ return viewModel.DownloadCount.Value.ToString ("N0");
+ }
+ return String.Empty;
+ }
+
+ public bool ShowVersionInsteadOfDownloadCount { get; set; }
+
+ public DateTimeOffset? LastPublished {
+ get { return viewModel.Published; }
+ }
+
+ public bool HasLastPublished {
+ get { return viewModel.Published.HasValue; }
+ }
+
+ public string GetLastPublishedDisplayText()
+ {
+ if (HasLastPublished) {
+ return LastPublished.Value.Date.ToShortDateString ();
+ }
+ return String.Empty;
+ }
+
+ /// <summary>
+ /// Consolidating a package should select the latest version.
+ /// </summary>
+ internal bool SelectLatestVersion { get; set; }
+
+ public NuGetVersion SelectedVersion { get; set; }
+ public ObservableCollection<NuGetVersion> Versions { get; private set; }
+
+ protected virtual Task ReadVersions (CancellationToken cancellationToken)
{
+ try {
+ packageDetailModel = new PackageDetailControlModel (parent.NuGetProjects);
+ packageDetailModel.SelectedVersion = new DisplayVersion (SelectedVersion, null);
+ return ReadVersionsFromPackageDetailControlModel (cancellationToken).ContinueWith (
+ task => OnVersionsRead (task),
+ cancellationToken,
+ TaskContinuationOptions.NotOnCanceled,
+ TaskScheduler.FromCurrentSynchronizationContext ());
+ } catch (Exception ex) {
+ LoggingService.LogError ("ReadVersions error.", ex);
+ }
+ return Task.CompletedTask;
+ }
+
+ Task ReadVersionsFromPackageDetailControlModel (CancellationToken cancellationToken)
+ {
+ if (!IsRecentPackage) {
+ return packageDetailModel.SetCurrentPackage (viewModel);
+ }
+
+ return ReadVersionsForRecentPackage (cancellationToken);
+ }
+
+ async Task ReadVersionsForRecentPackage (CancellationToken cancellationToken)
+ {
+ var identity = new PackageIdentity (viewModel.Id, viewModel.Version);
+ foreach (var sourceRepository in parent.SelectedPackageSource.GetSourceRepositories ()) {
+ try {
+ var metadata = await sourceRepository.GetPackageMetadataAsync (identity, parent.IncludePrerelease, cancellationToken);
+ if (metadata != null) {
+ var packageViewModel = CreatePackageItemListViewModel (metadata);
+ await packageDetailModel.SetCurrentPackage (packageViewModel);
+ return;
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError (
+ String.Format ("Unable to get metadata for {0} from source {1}.", identity, sourceRepository.PackageSource.Name),
+ ex);
+ }
+ }
+ }
+
+ PackageItemListViewModel CreatePackageItemListViewModel (IPackageSearchMetadata metadata)
+ {
+ return new PackageItemListViewModel {
+ Id = metadata.Identity.Id,
+ Version = metadata.Identity.Version,
+ IconUrl = metadata.IconUrl,
+ Author = metadata.Authors,
+ DownloadCount = metadata.DownloadCount,
+ Summary = metadata.Summary,
+ Description = metadata.Description,
+ Title = metadata.Title,
+ LicenseUrl = metadata.LicenseUrl,
+ ProjectUrl = metadata.ProjectUrl,
+ Published = metadata.Published,
+ Versions = AsyncLazy.New (() => metadata.GetVersionsAsync ())
+ };
+ }
+
+ void OnVersionsRead (Task task)
+ {
+ try {
+ if (task.IsFaulted) {
+ LoggingService.LogError ("Failed to read package versions.", task.Exception);
+ } else if (task.IsCanceled) {
+ // Ignore.
+ } else {
+ Versions.Clear ();
+ foreach (NuGetVersion version in packageDetailModel.AllPackageVersions.OrderByDescending (v => v.Version)) {
+ Versions.Add (version);
+ }
+ if (SelectLatestVersion && Versions.Any ()) {
+ SelectedVersion = Versions [0];
+ }
+ OnPropertyChanged (viewModel => viewModel.Versions);
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError ("Failed to read package versions.", ex);
+ }
+ }
+
+ public bool IsOlderPackageInstalled ()
+ {
+ return parent.IsOlderPackageInstalled (Id, SelectedVersion);
+ }
+
+ public override bool Equals (object obj)
+ {
+ var other = obj as ManagePackagesSearchResultViewModel;
+ if (other == null)
+ return false;
+
+ return StringComparer.OrdinalIgnoreCase.Equals (Id, other.Id);
+ }
+
+ public override int GetHashCode ()
+ {
+ return Id.GetHashCode ();
+ }
+
+ public void UpdateFromPreviouslyCheckedViewModel (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ SelectLatestVersion = false;
IsChecked = packageViewModel.IsChecked;
SelectedVersion = packageViewModel.SelectedVersion;
if (SelectedVersion != Version) {
Versions.Add (Version);
Versions.Add (SelectedVersion);
}
- }
-
- public void LoadPackageMetadata (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken)
- {
- if (packageDetailModel != null) {
- return;
- }
-
- if (IsRecentPackage) {
- ReadVersions (cancellationToken).ContinueWith (
- task => LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken),
- TaskScheduler.FromCurrentSynchronizationContext ());
- } else {
- ReadVersions (cancellationToken);
- LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken);
- }
- }
-
- void LoadPackageMetadataFromPackageDetailModel (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken)
- {
- try {
- LoadPackageMetadataFromPackageDetailModelAsync (metadataProvider, cancellationToken);
- } catch (Exception ex) {
- LoggingService.LogError ("Error getting detailed package metadata.", ex);
- }
- }
-
- protected virtual Task LoadPackageMetadataFromPackageDetailModelAsync (
- IPackageMetadataProvider metadataProvider,
- CancellationToken cancellationToken)
- {
- return packageDetailModel.LoadPackageMetadaAsync (metadataProvider, cancellationToken).ContinueWith (
- task => OnPackageMetadataLoaded (task),
- TaskScheduler.FromCurrentSynchronizationContext ());
- }
-
- void OnPackageMetadataLoaded (Task task)
- {
- try {
- if (task.IsFaulted) {
- LoggingService.LogError ("Failed to read package metadata.", task.Exception);
- } else if (task.IsCanceled) {
- // Ignore.
- } else {
- var metadata = packageDetailModel?.PackageMetadata;
- if (metadata != null) {
- viewModel.Published = metadata.Published;
- dependencies = GetCompatibleDependencies ().ToList ();
- OnPropertyChanged ("Dependencies");
- }
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Failed to read package metadata.", ex);
- }
- }
-
- public bool HasDependencies {
- get { return CompatibleDependencies.Any (); }
- }
-
- public bool HasNoDependencies {
- get { return !HasDependencies; }
- }
-
- public string GetPackageDependenciesDisplayText ()
- {
- var displayText = new StringBuilder ();
- foreach (PackageDependencyMetadata dependency in CompatibleDependencies) {
- displayText.AppendLine (dependency.ToString ());
- }
- return displayText.ToString ();
- }
-
- IEnumerable<PackageDependencyMetadata> CompatibleDependencies {
- get { return dependencies ?? new List<PackageDependencyMetadata> (); }
- }
-
- IEnumerable<PackageDependencyMetadata> GetCompatibleDependencies ()
- {
- var metadata = packageDetailModel?.PackageMetadata;
- if (metadata?.HasDependencies == true) {
- var projectTargetFramework = new ProjectTargetFramework (parent.Project);
- var targetFramework = NuGetFramework.Parse (projectTargetFramework.TargetFrameworkName.FullName);
-
- foreach (var dependencySet in packageDetailModel.PackageMetadata.DependencySets) {
- if (DefaultCompatibilityProvider.Instance.IsCompatible (targetFramework, dependencySet.TargetFramework)) {
- return dependencySet.Dependencies;
- }
- }
- }
-
- return Enumerable.Empty<PackageDependencyMetadata> ();
- }
-
- public bool IsDependencyInformationAvailable {
- get { return dependencies != null; }
- }
-
- public bool IsRecentPackage { get; set; }
-
- public void ResetDetailedPackageMetadata ()
- {
- packageDetailModel = null;
+ }
+
+ public void LoadPackageMetadata (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken)
+ {
+ if (packageDetailModel != null) {
+ return;
+ }
+
+ if (IsRecentPackage) {
+ ReadVersions (cancellationToken).ContinueWith (
+ task => LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken),
+ TaskScheduler.FromCurrentSynchronizationContext ());
+ } else {
+ ReadVersions (cancellationToken);
+ LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken);
+ }
+ }
+
+ void LoadPackageMetadataFromPackageDetailModel (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken)
+ {
+ try {
+ LoadPackageMetadataFromPackageDetailModelAsync (metadataProvider, cancellationToken);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Error getting detailed package metadata.", ex);
+ }
+ }
+
+ protected virtual Task LoadPackageMetadataFromPackageDetailModelAsync (
+ IPackageMetadataProvider metadataProvider,
+ CancellationToken cancellationToken)
+ {
+ return packageDetailModel.LoadPackageMetadaAsync (metadataProvider, cancellationToken).ContinueWith (
+ task => OnPackageMetadataLoaded (task),
+ TaskScheduler.FromCurrentSynchronizationContext ());
+ }
+
+ void OnPackageMetadataLoaded (Task task)
+ {
+ try {
+ if (task.IsFaulted) {
+ LoggingService.LogError ("Failed to read package metadata.", task.Exception);
+ } else {
+ var metadata = packageDetailModel?.PackageMetadata;
+ if (metadata != null) {
+ viewModel.Published = metadata.Published;
+ dependencies = GetCompatibleDependencies ().ToArray ();
+ OnPropertyChanged ("Dependencies");
+ }
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError ("Failed to read package metadata.", ex);
+ }
+ }
+
+ public bool HasDependencies {
+ get { return CompatibleDependencies.Any (); }
+ }
+
+ public bool HasNoDependencies {
+ get { return !HasDependencies; }
+ }
+
+ public string GetPackageDependenciesDisplayText ()
+ {
+ var displayText = StringBuilderCache.Allocate ();
+ foreach (PackageDependencyMetadata dependency in CompatibleDependencies) {
+ displayText.AppendLine (dependency.ToString ());
+ }
+ return StringBuilderCache.ReturnAndFree (displayText);
+ }
+
+ IEnumerable<PackageDependencyMetadata> CompatibleDependencies {
+ get { return dependencies ?? Array.Empty<PackageDependencyMetadata> (); }
+ }
+
+ IEnumerable<PackageDependencyMetadata> GetCompatibleDependencies ()
+ {
+ var metadata = packageDetailModel?.PackageMetadata;
+ if (metadata?.HasDependencies == true) {
+ var projectTargetFramework = new ProjectTargetFramework (parent.Project);
+ var targetFramework = NuGetFramework.Parse (projectTargetFramework.TargetFrameworkName.FullName);
+
+ foreach (var dependencySet in packageDetailModel.PackageMetadata.DependencySets) {
+ if (DefaultCompatibilityProvider.Instance.IsCompatible (targetFramework, dependencySet.TargetFramework)) {
+ return dependencySet.Dependencies;
+ }
+ }
+ }
+
+ return Enumerable.Empty<PackageDependencyMetadata> ();
+ }
+
+ public bool IsDependencyInformationAvailable {
+ get { return dependencies != null; }
+ }
+
+ public bool IsRecentPackage { get; set; }
+
+ public void ResetDetailedPackageMetadata ()
+ {
+ packageDetailModel = null;
}
public void ResetForRedisplay (bool includePrereleaseVersions)
{
- ResetDetailedPackageMetadata ();
- IsChecked = false;
- if (!includePrereleaseVersions) {
- RemovePrereleaseVersions ();
+ ResetDetailedPackageMetadata ();
+ IsChecked = false;
+ if (!includePrereleaseVersions) {
+ RemovePrereleaseVersions ();
}
}
void RemovePrereleaseVersions ()
{
- var prereleaseVersions = Versions.Where (version => version.IsPrerelease).ToArray ();
-
- foreach (NuGetVersion prereleaseVersion in prereleaseVersions) {
- Versions.Remove (prereleaseVersion);
+ var prereleaseVersions = Versions.Where (version => version.IsPrerelease).ToArray ();
+
+ foreach (NuGetVersion prereleaseVersion in prereleaseVersions) {
+ Versions.Remove (prereleaseVersion);
}
- }
- }
-}
-
+ }
+
+ public string GetCurrentPackageVersionText ()
+ {
+ return parent.GetCurrentPackageVersionText (Id);
+ }
+
+ public string GetCurrentPackageVersionAdditionalText ()
+ {
+ return parent.GetCurrentPackageVersionAdditionalText (Id);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs
new file mode 100644
index 0000000000..02637c476a
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs
@@ -0,0 +1,1019 @@
+//
+// ManagePackagesViewModel.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using MonoDevelop.Ide;
+using NuGet.Common;
+using NuGet.Configuration;
+using NuGet.PackageManagement;
+using NuGet.PackageManagement.UI;
+using NuGet.Packaging.Core;
+using NuGet.ProjectManagement;
+using NuGet.Protocol.Core.Types;
+using NuGet.Versioning;
+
+namespace MonoDevelop.PackageManagement
+{
+ internal class ManagePackagesViewModel : ViewModelBase<ManagePackagesViewModel>, INuGetUILogger
+ {
+ SourceRepositoryViewModel selectedPackageSource;
+ ManagePackagesSearchResultViewModel selectedPackage;
+ ManagePackagesPage pageSelected;
+ IPackageSourceProvider packageSourceProvider;
+ PackageItemLoader currentLoader;
+ CancellationTokenSource cancellationTokenSource;
+ List<SourceRepositoryViewModel> packageSources;
+ bool includePrerelease;
+ bool ignorePackageCheckedChanged;
+ IMonoDevelopSolutionManager solutionManager;
+ List<NuGetProject> nugetProjects;
+ List<IDotNetProject> dotNetProjects;
+ INuGetProjectContext projectContext;
+ AggregatePackageSourceErrorMessage aggregateErrorMessage;
+ NuGetPackageManager packageManager;
+ RecentManagedNuGetPackagesRepository recentPackagesRepository;
+ List<ManagePackagesProjectInfo> projectInformation = new List<ManagePackagesProjectInfo> ();
+ Dictionary<string, List<ManageProjectViewModel>> cachedProjectViewModels =
+ new Dictionary<string, List<ManageProjectViewModel>> (StringComparer.OrdinalIgnoreCase);
+
+ public static ManagePackagesViewModel Create (
+ RecentManagedNuGetPackagesRepository recentPackagesRepository,
+ IDotNetProject project)
+ {
+ var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (IdeApp.ProjectOperations.CurrentSelectedSolution);
+ var solution = new SolutionProxy (IdeApp.ProjectOperations.CurrentSelectedSolution);
+ return new ManagePackagesViewModel (solutionManager, solution, recentPackagesRepository, project);
+ }
+
+ public ManagePackagesViewModel (
+ IMonoDevelopSolutionManager solutionManager,
+ ISolution solution,
+ RecentManagedNuGetPackagesRepository recentPackagesRepository,
+ IDotNetProject project)
+ : this (
+ solutionManager,
+ solution,
+ new NuGetProjectContext (solutionManager.Settings),
+ recentPackagesRepository,
+ project)
+ {
+ }
+
+ public ManagePackagesViewModel (
+ IMonoDevelopSolutionManager solutionManager,
+ ISolution solution,
+ INuGetProjectContext projectContext,
+ RecentManagedNuGetPackagesRepository recentPackagesRepository,
+ IDotNetProject project)
+ {
+ this.solutionManager = solutionManager;
+ this.projectContext = projectContext;
+ this.recentPackagesRepository = recentPackagesRepository;
+ IsManagingSolution = project == null;
+ PackageViewModels = new ObservableCollection<ManagePackagesSearchResultViewModel> ();
+ CheckedPackageViewModels = new ObservableCollection<ManagePackagesSearchResultViewModel> ();
+ ProjectViewModels = new ObservableCollection<ManageProjectViewModel> ();
+ ErrorMessage = String.Empty;
+ PageSelected = ManagePackagesPage.Browse;
+
+ if (project != null) {
+ dotNetProjects = new List<IDotNetProject> ();
+ dotNetProjects.Add (project);
+ } else {
+ dotNetProjects = solution.GetAllProjects ().ToList ();
+ }
+
+ packageManager = new NuGetPackageManager (
+ solutionManager.CreateSourceRepositoryProvider (),
+ solutionManager.Settings,
+ solutionManager,
+ new DeleteOnRestartManager ()
+ );
+
+ nugetProjects = dotNetProjects
+ .Select (dotNetProject => solutionManager.GetNuGetProject (dotNetProject))
+ .ToList ();
+
+ GetPackagesInstalledInProjects ().Ignore ();
+ }
+
+ public bool IsManagingSolution { get; private set; }
+
+ public IEnumerable<NuGetProject> NuGetProjects {
+ get { return nugetProjects; }
+ }
+
+ public IDotNetProject Project {
+ get { return dotNetProjects[0]; }
+ }
+
+ public IEnumerable<IDotNetProject> DotNetProjects {
+ get { return dotNetProjects; }
+ }
+
+ public string SearchTerms { get; set; }
+
+ public ManagePackagesPage PageSelected {
+ get { return pageSelected; }
+ set {
+ if (pageSelected != value) {
+ pageSelected = value;
+ CheckedPackageViewModels.Clear ();
+ cachedProjectViewModels.Clear ();
+ }
+ }
+ }
+
+ public bool IsConsolidatePageSelected {
+ get { return PageSelected == ManagePackagesPage.Consolidate; }
+ }
+
+ public bool IsInstalledPageSelected {
+ get { return PageSelected == ManagePackagesPage.Installed; }
+ }
+
+ public bool IsBrowsePageSelected {
+ get { return PageSelected == ManagePackagesPage.Browse; }
+ }
+
+ public bool IsUpdatesPageSelected {
+ get { return PageSelected == ManagePackagesPage.Updates; }
+ }
+
+ public IEnumerable<SourceRepositoryViewModel> PackageSources {
+ get {
+ if (packageSources == null) {
+ packageSources = GetPackageSources ().ToList ();
+ }
+ return packageSources;
+ }
+ }
+
+ IEnumerable<SourceRepositoryViewModel> GetPackageSources ()
+ {
+ ISourceRepositoryProvider provider = solutionManager.CreateSourceRepositoryProvider ();
+ packageSourceProvider = provider.PackageSourceProvider;
+ var repositories = provider.GetRepositories ().ToList ();
+
+ if (repositories.Count > 1) {
+ // All Sources - first package source if there are multiple sources.
+ yield return new AggregateSourceRepositoryViewModel (repositories);
+ }
+
+ foreach (SourceRepository repository in repositories) {
+ yield return new SourceRepositoryViewModel (repository);
+ }
+ }
+
+ public SourceRepositoryViewModel SelectedPackageSource {
+ get {
+ if (selectedPackageSource == null) {
+ selectedPackageSource = GetActivePackageSource ();
+ }
+ return selectedPackageSource;
+ }
+ set {
+ if (selectedPackageSource != value) {
+ selectedPackageSource = value;
+ SaveActivePackageSource ();
+ ReadPackages ();
+ OnPropertyChanged (null);
+ }
+ }
+ }
+
+ SourceRepositoryViewModel GetActivePackageSource ()
+ {
+ if (packageSources == null)
+ return null;
+
+ if (!String.IsNullOrEmpty (packageSourceProvider.ActivePackageSourceName)) {
+ SourceRepositoryViewModel packageSource = packageSources
+ .FirstOrDefault (viewModel => String.Equals (viewModel.PackageSource.Name, packageSourceProvider.ActivePackageSourceName, StringComparison.CurrentCultureIgnoreCase));
+ if (packageSource != null) {
+ return packageSource;
+ }
+ }
+
+ return packageSources.FirstOrDefault (packageSource => !packageSource.IsAggregate);
+ }
+
+ void SaveActivePackageSource ()
+ {
+ if (selectedPackageSource == null || packageSourceProvider == null)
+ return;
+
+ packageSourceProvider.SaveActivePackageSource (selectedPackageSource.PackageSource);
+ }
+
+ public ObservableCollection<ManagePackagesSearchResultViewModel> PackageViewModels { get; private set; }
+ public ObservableCollection<ManagePackagesSearchResultViewModel> CheckedPackageViewModels { get; private set; }
+ public ObservableCollection<ManageProjectViewModel> ProjectViewModels { get; private set; }
+
+ public bool HasError { get; private set; }
+ public string ErrorMessage { get; private set; }
+
+ public bool IsLoadingNextPage { get; private set; }
+ public bool IsReadingPackages { get; private set; }
+ public bool HasNextPage { get; private set; }
+
+ public bool IncludePrerelease {
+ get { return includePrerelease; }
+ set {
+ if (includePrerelease != value) {
+ includePrerelease = value;
+ ReadPackages ();
+ OnPropertyChanged (null);
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ OnDispose ();
+ CancelReadPackagesTask ();
+ IsDisposed = true;
+ }
+
+ protected virtual void OnDispose()
+ {
+ }
+
+ public bool IsDisposed { get; private set; }
+
+ public void Search ()
+ {
+ ReadPackages ();
+ OnPropertyChanged (null);
+ }
+
+ public void ReadPackages ()
+ {
+ if (SelectedPackageSource == null) {
+ return;
+ }
+
+ HasNextPage = false;
+ IsLoadingNextPage = false;
+ currentLoader = null;
+ StartReadPackagesTask ();
+ }
+
+ void StartReadPackagesTask (bool clearPackages = true)
+ {
+ IsReadingPackages = true;
+ ClearError ();
+ if (clearPackages) {
+ CancelReadPackagesTask ();
+ ClearPackages ();
+ }
+ CreateReadPackagesTask ();
+ }
+
+ void CancelReadPackagesTask()
+ {
+ if (cancellationTokenSource != null) {
+ // Cancel on another thread since CancellationTokenSource.Cancel can sometimes
+ // take up to a second on Mono and we do not want to block the UI thread.
+ var tokenSource = cancellationTokenSource;
+ Task.Run (() => {
+ try {
+ tokenSource.Cancel ();
+ tokenSource.Dispose ();
+ } catch (Exception ex) {
+ LoggingService.LogError ("Unable to cancel task.", ex);
+ }
+ });
+ cancellationTokenSource = null;
+ }
+ }
+
+ protected virtual Task CreateReadPackagesTask()
+ {
+ var loader = currentLoader ?? CreatePackageLoader ();
+ cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource ();
+ return LoadPackagesAsync (loader, cancellationTokenSource.Token)
+ .ContinueWith (t => OnPackagesRead (t, loader), TaskScheduler.FromCurrentSynchronizationContext ());
+ }
+
+ PackageItemLoader CreatePackageLoader ()
+ {
+ var context = new PackageLoadContext (
+ selectedPackageSource.GetSourceRepositories (),
+ true,
+ nugetProjects);
+
+ var loader = new PackageItemLoader (
+ context,
+ CreatePackageFeed (context),
+ SearchTerms,
+ IncludePrerelease
+ );
+
+ currentLoader = loader;
+
+ return loader;
+ }
+
+ protected virtual IPackageFeed CreatePackageFeed (PackageLoadContext context)
+ {
+ if (PageSelected == ManagePackagesPage.Browse)
+ return new MultiSourcePackageFeed (context.SourceRepositories, this);
+
+ if (PageSelected == ManagePackagesPage.Installed)
+ return new InstalledPackageFeed (context, CreatePackageMetadataProvider (), new NullLogger ());
+
+ if (PageSelected == ManagePackagesPage.Updates) {
+ return new UpdatePackageFeed (
+ context,
+ CreatePackageMetadataProvider (),
+ new PackageSearchMetadataCache (),
+ new NullLogger ());
+ }
+
+ if (PageSelected == ManagePackagesPage.Consolidate)
+ return new ConsolidatePackageFeed (context, CreatePackageMetadataProvider (), new NullLogger ());
+
+ throw new InvalidOperationException ("Unsupported package feed");
+ }
+
+ protected virtual Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token)
+ {
+ return Task.Run (async () => {
+ await loader.LoadNextAsync (null, token);
+
+ while (loader.State.LoadingStatus == LoadingStatus.Loading) {
+ token.ThrowIfCancellationRequested ();
+ await loader.UpdateStateAsync (null, token);
+ }
+ });
+ }
+
+ void ClearError ()
+ {
+ HasError = false;
+ ErrorMessage = String.Empty;
+ aggregateErrorMessage = new AggregatePackageSourceErrorMessage (GetTotalPackageSources ());
+ }
+
+ int GetTotalPackageSources ()
+ {
+ if (selectedPackageSource != null) {
+ return selectedPackageSource.GetSourceRepositories ().Count ();
+ }
+ return 0;
+ }
+
+ public void ShowNextPage ()
+ {
+ IsLoadingNextPage = true;
+ StartReadPackagesTask (false);
+ base.OnPropertyChanged (null);
+ }
+
+ void OnPackagesRead (Task task, PackageItemLoader loader)
+ {
+ IsReadingPackages = false;
+ IsLoadingNextPage = false;
+ if (task.IsFaulted) {
+ SaveError (task.Exception);
+ } else if (task.IsCanceled || !IsCurrentQuery (loader)) {
+ // Ignore.
+ return;
+ } else {
+ SaveAnyWarnings ();
+ UpdatePackagesForSelectedPage (loader);
+ }
+ base.OnPropertyChanged (null);
+ }
+
+ bool IsCurrentQuery (PackageItemLoader loader)
+ {
+ return currentLoader == loader;
+ }
+
+ void SaveError (AggregateException ex)
+ {
+ HasError = true;
+ ErrorMessage = GetErrorMessage (ex);
+ LoggingService.LogInfo ("PackagesViewModel error", ex);
+ }
+
+ string GetErrorMessage (AggregateException ex)
+ {
+ var errorMessage = new AggregateExceptionErrorMessage (ex);
+ return errorMessage.ToString ();
+ }
+
+ void SaveAnyWarnings ()
+ {
+ string warning = GetWarningMessage ();
+ if (!String.IsNullOrEmpty (warning)) {
+ HasError = true;
+ ErrorMessage = warning;
+ }
+ }
+
+ protected virtual string GetWarningMessage ()
+ {
+ return String.Empty;
+ }
+
+ void UpdatePackagesForSelectedPage (PackageItemLoader loader)
+ {
+ HasNextPage = loader.State.LoadingStatus == LoadingStatus.Ready;
+
+ UpdatePackageViewModels (loader.GetCurrent ());
+ }
+
+ void UpdatePackageViewModels (IEnumerable<PackageItemListViewModel> newPackageViewModels)
+ {
+ var packages = PrioritizePackages (ConvertToPackageViewModels (newPackageViewModels)).ToList ();
+
+ foreach (ManagePackagesSearchResultViewModel packageViewModel in packages) {
+ PackageViewModels.Add (packageViewModel);
+ }
+ }
+
+ public IEnumerable<ManagePackagesSearchResultViewModel> ConvertToPackageViewModels (IEnumerable<PackageItemListViewModel> itemViewModels)
+ {
+ foreach (PackageItemListViewModel itemViewModel in itemViewModels) {
+ ManagePackagesSearchResultViewModel packageViewModel = CreatePackageViewModel (itemViewModel);
+ UpdatePackageViewModelIfPreviouslyChecked (packageViewModel);
+ yield return packageViewModel;
+ }
+ }
+
+ ManagePackagesSearchResultViewModel CreatePackageViewModel (PackageItemListViewModel viewModel)
+ {
+ bool showVersion = ShowPackageVersionInsteadOfDownloadCount ();
+ return new ManagePackagesSearchResultViewModel (this, viewModel) {
+ ShowVersionInsteadOfDownloadCount = showVersion,
+ SelectLatestVersion = IsConsolidatePageSelected
+ };
+ }
+
+ bool ShowPackageVersionInsteadOfDownloadCount ()
+ {
+ return PageSelected != ManagePackagesPage.Browse;
+ }
+
+ void ClearPackages ()
+ {
+ PackageViewModels.Clear();
+ }
+
+ public void OnPackageCheckedChanged (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ if (ignorePackageCheckedChanged)
+ return;
+
+ if (packageViewModel.IsChecked) {
+ UncheckExistingCheckedPackageWithDifferentVersion (packageViewModel);
+ CheckedPackageViewModels.Add (packageViewModel);
+ } else {
+ CheckedPackageViewModels.Remove (packageViewModel);
+ }
+ }
+
+ void UpdatePackageViewModelIfPreviouslyChecked (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ ignorePackageCheckedChanged = true;
+ try {
+ ManagePackagesSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id);
+ if (existingPackageViewModel != null) {
+ packageViewModel.UpdateFromPreviouslyCheckedViewModel (existingPackageViewModel);
+ CheckedPackageViewModels.Remove (existingPackageViewModel);
+ CheckedPackageViewModels.Add (packageViewModel);
+ }
+ } finally {
+ ignorePackageCheckedChanged = false;
+ }
+ }
+
+ void UncheckExistingCheckedPackageWithDifferentVersion (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ ManagePackagesSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id);
+
+ if (existingPackageViewModel != null) {
+ CheckedPackageViewModels.Remove (existingPackageViewModel);
+ existingPackageViewModel.IsChecked = false;
+ }
+ }
+
+ ManagePackagesSearchResultViewModel GetExistingCheckedPackageViewModel (string packageId)
+ {
+ return CheckedPackageViewModels
+ .FirstOrDefault (item => item.Id == packageId);
+ }
+
+ public IEnumerable<IPackageAction> CreateInstallPackageActions (
+ ManagePackagesSearchResultViewModel packageViewModel,
+ IEnumerable<IDotNetProject> projects)
+ {
+ bool firstInstall = true;
+ foreach (IDotNetProject project in projects) {
+ yield return new InstallNuGetPackageAction (
+ SelectedPackageSource.GetSourceRepositories (),
+ solutionManager,
+ project,
+ projectContext
+ ) {
+ IncludePrerelease = IncludePrerelease,
+ PackageId = packageViewModel.Id,
+ Version = packageViewModel.SelectedVersion,
+ LicensesMustBeAccepted = firstInstall
+ };
+
+ firstInstall = false;
+ }
+ }
+
+ public IEnumerable<IPackageAction> CreateUninstallPackageActions (
+ ManagePackagesSearchResultViewModel packageViewModel,
+ IEnumerable<IDotNetProject> projects)
+ {
+ foreach (IDotNetProject project in projects) {
+ if (IsPackageInstalledInProject (project, packageViewModel.Id)) {
+ yield return new UninstallNuGetPackageAction (
+ solutionManager,
+ project
+ ) {
+ PackageId = packageViewModel.Id,
+ };
+ }
+ }
+ }
+
+ public IEnumerable<IPackageAction> CreateUpdatePackageActions (
+ ManagePackagesSearchResultViewModel packageViewModel,
+ IEnumerable<IDotNetProject> projects)
+ {
+ bool firstInstall = true;
+ foreach (IDotNetProject project in projects) {
+ if (IsPackageInstalledInProject (project, packageViewModel.Id)) {
+ yield return new InstallNuGetPackageAction (
+ SelectedPackageSource.GetSourceRepositories (),
+ solutionManager,
+ project,
+ projectContext
+ ) {
+ IncludePrerelease = IncludePrerelease,
+ PackageId = packageViewModel.Id,
+ Version = packageViewModel.SelectedVersion,
+ LicensesMustBeAccepted = firstInstall
+ };
+
+ firstInstall = false;
+ }
+ }
+ }
+
+ public IEnumerable<IPackageAction> CreateConsolidatePackageActions (
+ ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ bool firstInstall = true;
+ foreach (ManageProjectViewModel project in GetProjectViewModelsForPackage (packageViewModel)) {
+ if (!CanConsolidate (project, packageViewModel)) {
+ continue;
+ }
+
+ yield return new InstallNuGetPackageAction (
+ SelectedPackageSource.GetSourceRepositories (),
+ solutionManager,
+ project.Project,
+ projectContext
+ ) {
+ IncludePrerelease = IncludePrerelease,
+ PackageId = packageViewModel.Id,
+ Version = packageViewModel.SelectedVersion,
+ LicensesMustBeAccepted = firstInstall
+ };
+
+ firstInstall = false;
+ }
+ }
+
+ public List<IPackageAction> CreatePackageActions (
+ IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels,
+ IEnumerable<IDotNetProject> selectedProjects)
+ {
+ if (PageSelected == ManagePackagesPage.Browse) {
+ return CreatePackageActions (packageViewModels, selectedProjects, CreateInstallPackageActions);
+ } else if (PageSelected == ManagePackagesPage.Installed) {
+ return CreatePackageActions (packageViewModels, selectedProjects, CreateUninstallPackageActions);
+ } else if (PageSelected == ManagePackagesPage.Updates) {
+ return CreatePackageActions (packageViewModels, selectedProjects, CreateUpdatePackageActions);
+ }
+ return null;
+ }
+
+ List<IPackageAction> CreatePackageActions (
+ IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels,
+ IEnumerable<IDotNetProject> selectedProjects,
+ Func<ManagePackagesSearchResultViewModel, IEnumerable<IDotNetProject>, IEnumerable<IPackageAction>> transform)
+ {
+ var actions = new List<IPackageAction> ();
+ foreach (var packageViewModel in packageViewModels) {
+ actions.AddRange (transform (packageViewModel, selectedProjects));
+ }
+ return actions;
+ }
+
+ public List<IPackageAction> CreateConsolidatePackageActions (IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels)
+ {
+ var actions = new List<IPackageAction> ();
+ foreach (var packageViewModel in packageViewModels) {
+ actions.AddRange (CreateConsolidatePackageActions (packageViewModel));
+ }
+ return actions;
+ }
+
+ bool IsPackageInstalledInProject (IDotNetProject project, string packageId)
+ {
+ var matchedProjectInfo = projectInformation.FirstOrDefault (p => p.Project == project);
+ return matchedProjectInfo.Packages.Any (package => StringComparer.OrdinalIgnoreCase.Equals (packageId, package.Id));
+ }
+
+ bool CanConsolidate (ManageProjectViewModel projectViewModel, ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ if (!projectViewModel.IsChecked)
+ return false;
+
+ if (IsPackageInstalledInProjectWithSameVersion (
+ projectViewModel.ProjectInfo,
+ packageViewModel.Id,
+ packageViewModel.SelectedVersion)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool IsPackageInstalledInProjectWithSameVersion (ManagePackagesProjectInfo projectInfo, string packageId, NuGetVersion version)
+ {
+ var matchPackageId = new PackageIdentity (packageId, version);
+ return projectInfo.Packages.Any (package => PackageIdentityComparer.Default.Equals (package, matchPackageId));
+ }
+
+ public ManagePackagesSearchResultViewModel SelectedPackage {
+ get { return selectedPackage; }
+ set {
+ if (selectedPackage != value) {
+ selectedPackage = value;
+ OnSelectedPackageChanged ();
+ }
+ }
+ }
+
+ public bool IsOlderPackageInstalled (string id, NuGetVersion version)
+ {
+ foreach (ManagePackagesProjectInfo projectInfo in projectInformation) {
+ foreach (PackageIdentity package in projectInfo.Packages) {
+ if (IsOlderPackageInstalled (package, id, version)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool IsOlderPackageInstalled (PackageIdentity packageIdentity, string id, NuGetVersion version)
+ {
+ return packageIdentity.Id == id &&
+ packageIdentity.Version < version;
+ }
+
+ protected virtual Task GetPackagesInstalledInProjects ()
+ {
+ return GetInstalledPackagesProjectInfo ()
+ .ContinueWith (task => OnReadInstalledPackages (task), TaskScheduler.FromCurrentSynchronizationContext ());
+ }
+
+ async Task<List<ManagePackagesProjectInfo>> GetInstalledPackagesProjectInfo ()
+ {
+ var projectInfo = new List<ManagePackagesProjectInfo> ();
+ for (int i = 0; i < nugetProjects.Count; ++i) {
+ var nugetProject = nugetProjects[i];
+ var packages = await nugetProject.GetInstalledPackagesAsync (CancellationToken.None);
+ projectInfo.Add (new ManagePackagesProjectInfo (dotNetProjects[i], packages));
+ }
+ projectInfo.Sort ();
+ return projectInfo;
+ }
+
+ void OnReadInstalledPackages (Task<List<ManagePackagesProjectInfo>> task)
+ {
+ try {
+ if (task.IsFaulted) {
+ LoggingService.LogError ("Unable to read installed packages.", task.Exception);
+ } else {
+ projectInformation = task.Result;
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError ("OnReadInstalledPackages", ex);
+ }
+ }
+
+ void INuGetUILogger.Log (MessageLevel level, string message, params object [] args)
+ {
+ if (level == MessageLevel.Error) {
+ string fullErrorMessage = String.Format (message, args);
+ AppendErrorMessage (fullErrorMessage);
+ }
+ }
+
+ void AppendErrorMessage (string message)
+ {
+ aggregateErrorMessage.AddError (message);
+ ErrorMessage = aggregateErrorMessage.ErrorMessage;
+ HasError = true;
+ OnPropertyChanged (null);
+ }
+
+ public void LoadPackageMetadata (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ IPackageMetadataProvider provider = CreatePackageMetadataProvider ();
+
+ packageViewModel.LoadPackageMetadata (provider, cancellationTokenSource.Token);
+ }
+
+ IPackageMetadataProvider CreatePackageMetadataProvider ()
+ {
+ return new MultiSourcePackageMetadataProvider (
+ selectedPackageSource.GetSourceRepositories (),
+ packageManager.PackagesFolderSourceRepository,
+ packageManager.GlobalPackageFolderRepositories,
+ nugetProjects.ToArray (),
+ IsManagingSolution,
+ new NullLogger ());
+ }
+
+ public void OnInstallingSelectedPackages ()
+ {
+ try {
+ UpdateRecentPackages ();
+ } catch (Exception ex) {
+ LoggingService.LogError ("Unable to update recent packages", ex);
+ }
+ }
+
+ void UpdateRecentPackages ()
+ {
+ if (SelectedPackageSource == null)
+ return;
+
+ if (CheckedPackageViewModels.Any ()) {
+ foreach (ManagePackagesSearchResultViewModel packageViewModel in CheckedPackageViewModels) {
+ recentPackagesRepository.AddPackage (packageViewModel, SelectedPackageSource.Name);
+ }
+ } else {
+ recentPackagesRepository.AddPackage (SelectedPackage, SelectedPackageSource.Name);
+ }
+ }
+
+ IEnumerable<ManagePackagesSearchResultViewModel> PrioritizePackages (IEnumerable<ManagePackagesSearchResultViewModel> packages)
+ {
+ var recentPackages = GetRecentPackages ().ToList ();
+
+ foreach (ManagePackagesSearchResultViewModel package in recentPackages) {
+ package.Parent = this;
+ package.ResetForRedisplay (IncludePrerelease);
+ yield return package;
+ }
+
+ foreach (ManagePackagesSearchResultViewModel package in packages) {
+ if (!recentPackages.Contains (package, ManagedPackagesSearchResultViewModelComparer.Instance)) {
+ yield return package;
+ }
+ }
+ }
+
+ IEnumerable<ManagePackagesSearchResultViewModel> GetRecentPackages ()
+ {
+ if (PackageViewModels.Count == 0 &&
+ String.IsNullOrEmpty (SearchTerms) &&
+ selectedPackageSource != null &&
+ PageSelected == ManagePackagesPage.Browse) {
+ return recentPackagesRepository.GetPackages (SelectedPackageSource.Name)
+ .Where (SelectedVersionMatchesIncludePreleaseFilter);
+ }
+
+ return Enumerable.Empty<ManagePackagesSearchResultViewModel> ();
+ }
+
+ bool SelectedVersionMatchesIncludePreleaseFilter (ManagePackagesSearchResultViewModel package)
+ {
+ if (package.SelectedVersion.IsPrerelease) {
+ return IncludePrerelease;
+ }
+
+ return true;
+ }
+
+ public IEnumerable<IDotNetProject> GetDotNetProjectsToSelect (IEnumerable<string> packageIds)
+ {
+ if (PageSelected == ManagePackagesPage.Browse) {
+ return dotNetProjects;
+ }
+
+ return GetFilteredProjectsToSelect (packageIds);
+ }
+
+ IEnumerable<IDotNetProject> GetFilteredProjectsToSelect (IEnumerable<string> packageIds)
+ {
+ foreach (IDotNetProject project in dotNetProjects) {
+ foreach (var projectInfo in projectInformation) {
+ if (projectInfo.Project != project)
+ continue;
+
+ foreach (PackageIdentity package in projectInfo.Packages) {
+ foreach (string packageId in packageIds) {
+ if (StringComparer.OrdinalIgnoreCase.Equals (package.Id, packageId)) {
+ yield return project;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void OnSelectedPackageChanged ()
+ {
+ if (!IsConsolidatePageSelected) {
+ return;
+ }
+
+ ProjectViewModels.Clear ();
+
+ if (SelectedPackage == null) {
+ return;
+ }
+
+ List<ManageProjectViewModel> projectViewModels;
+ if (!cachedProjectViewModels.TryGetValue (SelectedPackage.Id, out projectViewModels)) {
+ projectViewModels = new List<ManageProjectViewModel> ();
+ var uncheckedProjectViewModels = new List<ManageProjectViewModel> ();
+ foreach (ManagePackagesProjectInfo projectInfo in projectInformation) {
+ var projectViewModel = new ManageProjectViewModel (projectInfo, SelectedPackage.Id);
+ if (projectViewModel.IsChecked)
+ projectViewModels.Add (projectViewModel);
+ else
+ uncheckedProjectViewModels.Add (projectViewModel);
+ }
+ // Show projects that have the package installed before the other projects.
+ projectViewModels.AddRange (uncheckedProjectViewModels);
+
+ cachedProjectViewModels [SelectedPackage.Id] = projectViewModels;
+ }
+
+ foreach (ManageProjectViewModel projectViewModel in projectViewModels) {
+ ProjectViewModels.Add (projectViewModel);
+ }
+ }
+
+ public bool CanConsolidate ()
+ {
+ if (!IsConsolidatePageSelected) {
+ return false;
+ }
+
+ if (CheckedPackageViewModels.Count == 0) {
+ return CanConsolidateSelectedPackage ();
+ }
+
+ return CanConsolidateCheckedPackages ();
+ }
+
+ bool CanConsolidateSelectedPackage ()
+ {
+ if (SelectedPackage == null) {
+ return false;
+ }
+
+ foreach (ManageProjectViewModel projectViewModel in ProjectViewModels) {
+ if (CanConsolidate (projectViewModel, SelectedPackage)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ bool CanConsolidateCheckedPackages ()
+ {
+ foreach (ManagePackagesSearchResultViewModel packageViewModel in CheckedPackageViewModels) {
+ foreach (ManageProjectViewModel projectViewModel in GetProjectViewModelsForPackage (packageViewModel)) {
+ if (CanConsolidate (projectViewModel, packageViewModel)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ IEnumerable<ManageProjectViewModel> GetProjectViewModelsForPackage (ManagePackagesSearchResultViewModel packageViewModel)
+ {
+ List<ManageProjectViewModel> projectViewModels;
+ if (cachedProjectViewModels.TryGetValue (packageViewModel.Id, out projectViewModels)) {
+ return projectViewModels;
+ }
+ return Enumerable.Empty<ManageProjectViewModel> ();
+ }
+
+ public string GetCurrentPackageVersionText (string packageId)
+ {
+ PackageIdentity currentPackage = null;
+ foreach (ManagePackagesProjectInfo projectInfo in projectInformation) {
+ foreach (PackageIdentity package in projectInfo.Packages) {
+ if (IsPackageIdMatch (package, packageId)) {
+ if (currentPackage == null) {
+ currentPackage = package;
+ } else {
+ return GettextCatalog.GetString ("Multiple");
+ }
+ }
+ }
+ }
+
+ if (currentPackage != null) {
+ return currentPackage.Version.ToString ();
+ }
+
+ return string.Empty;
+ }
+
+ static bool IsPackageIdMatch (PackageIdentity package, string packageId)
+ {
+ return StringComparer.OrdinalIgnoreCase.Equals (package.Id, packageId);
+ }
+
+ public string GetCurrentPackageVersionAdditionalText (string packageId)
+ {
+ if (!IsManagingSolution)
+ return string.Empty;
+
+ StringBuilder additionalText = null;
+ (PackageIdentity package, ManagePackagesProjectInfo projectInfo) previousMatch = (null, null);
+ foreach (ManagePackagesProjectInfo projectInfo in projectInformation) {
+ PackageIdentity foundPackage = projectInfo.Packages.FirstOrDefault (package => IsPackageIdMatch (package, packageId));
+ if (foundPackage != null) {
+ if (previousMatch.package == null) {
+ previousMatch.package = foundPackage;
+ previousMatch.projectInfo = projectInfo;
+ } else {
+ if (additionalText == null) {
+ additionalText = StringBuilderCache.Allocate ();
+ AppendAdditionalText (additionalText, previousMatch.projectInfo, previousMatch.package);
+ }
+ additionalText.Append (", ");
+ AppendAdditionalText (additionalText, projectInfo, foundPackage);
+ }
+ }
+ }
+
+ if (additionalText != null) {
+ return StringBuilderCache.ReturnAndFree (additionalText);
+ }
+
+ return string.Empty;
+ }
+
+ static void AppendAdditionalText (StringBuilder additionalText, ManagePackagesProjectInfo projectInfo, PackageIdentity foundPackage)
+ {
+ additionalText.AppendFormat ("{0}: {1}", projectInfo.Project.Name, foundPackage.Version);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs
new file mode 100644
index 0000000000..324164fb18
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs
@@ -0,0 +1,61 @@
+//
+// ManageProjectViewModel.cs
+//
+// Author:
+// Matt Ward <matt.ward@microsoft.com>
+//
+// Copyright (c) 2019 Microsoft
+//
+// 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.Linq;
+
+namespace MonoDevelop.PackageManagement
+{
+ class ManageProjectViewModel
+ {
+ public ManageProjectViewModel (ManagePackagesProjectInfo projectInfo, string packageId)
+ {
+ ProjectInfo = projectInfo;
+
+ var package = ProjectInfo.Packages.FirstOrDefault (package => StringComparer.OrdinalIgnoreCase.Equals (package.Id, packageId));
+ if (package != null) {
+ IsChecked = true;
+ PackageVersion = package.Version.ToString ();
+ } else {
+ PackageVersion = "–";
+ }
+ }
+
+ public IDotNetProject Project {
+ get { return ProjectInfo.Project; }
+ }
+
+ public string ProjectName {
+ get { return Project.Name; }
+ }
+
+ public string PackageVersion { get; set; }
+
+ public bool IsChecked { get; set; }
+
+ internal ManagePackagesProjectInfo ProjectInfo { get; set; }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModelComparer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagedPackagesSearchResultViewModelComparer.cs
index 69bb202950..756fdaac9b 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModelComparer.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagedPackagesSearchResultViewModelComparer.cs
@@ -1,5 +1,5 @@
//
-// PackageSearchResultViewModelComparer.cs
+// ManagedPackagesSearchResultViewModelComparer.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -29,17 +29,17 @@ using System.Collections.Generic;
namespace MonoDevelop.PackageManagement
{
- class PackageSearchResultViewModelComparer : IEqualityComparer<PackageSearchResultViewModel>
+ class ManagedPackagesSearchResultViewModelComparer : IEqualityComparer<ManagePackagesSearchResultViewModel>
{
- public static readonly PackageSearchResultViewModelComparer Instance =
- new PackageSearchResultViewModelComparer ();
+ public static readonly ManagedPackagesSearchResultViewModelComparer Instance =
+ new ManagedPackagesSearchResultViewModelComparer ();
- public bool Equals (PackageSearchResultViewModel x, PackageSearchResultViewModel y)
+ public bool Equals (ManagePackagesSearchResultViewModel x, ManagePackagesSearchResultViewModel y)
{
return x.Id.Equals (y.Id, StringComparison.OrdinalIgnoreCase);
}
- public int GetHashCode (PackageSearchResultViewModel obj)
+ public int GetHashCode (ManagePackagesSearchResultViewModel obj)
{
return obj.Id.GetHashCode ();
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentNuGetPackagesRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentManagedNuGetPackagesRepository.cs
index 05d7c1b8a3..8833f3cb51 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentNuGetPackagesRepository.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentManagedNuGetPackagesRepository.cs
@@ -1,5 +1,5 @@
//
-// RecentNuGetPackagesRepository.cs
+// RecentManagedNuGetPackagesRepository.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -30,7 +30,7 @@ using System.Linq;
namespace MonoDevelop.PackageManagement
{
- internal class RecentNuGetPackagesRepository
+ internal class RecentManagedNuGetPackagesRepository
{
public const int DefaultMaximumPackagesCount = 20;
@@ -43,14 +43,14 @@ namespace MonoDevelop.PackageManagement
set { maximumPackagesCount = value; }
}
- public IEnumerable<PackageSearchResultViewModel> GetPackages (string source)
+ public IEnumerable<ManagePackagesSearchResultViewModel> GetPackages (string source)
{
return packages
.Where (package => String.Equals (package.Source, source, StringComparison.OrdinalIgnoreCase))
.Select (package => package.PackageViewModel);
}
- public void AddPackage (PackageSearchResultViewModel viewModel, string source)
+ public void AddPackage (ManagePackagesSearchResultViewModel viewModel, string source)
{
var package = new RecentPackage (viewModel, source);
viewModel.IsRecentPackage = true;
@@ -74,7 +74,7 @@ namespace MonoDevelop.PackageManagement
bool IsMatch (RecentPackage x, RecentPackage y)
{
- return PackageSearchResultViewModelComparer.Instance.Equals (x.PackageViewModel, y.PackageViewModel);
+ return ManagedPackagesSearchResultViewModelComparer.Instance.Equals (x.PackageViewModel, y.PackageViewModel);
}
void AddPackageAtBeginning (RecentPackage package)
@@ -97,13 +97,13 @@ namespace MonoDevelop.PackageManagement
class RecentPackage
{
- public RecentPackage (PackageSearchResultViewModel viewModel, string source)
+ public RecentPackage (ManagePackagesSearchResultViewModel viewModel, string source)
{
PackageViewModel = viewModel;
Source = source;
}
- public PackageSearchResultViewModel PackageViewModel { get; set; }
+ public ManagePackagesSearchResultViewModel PackageViewModel { get; set; }
public string Source { get; set; }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs
index 95cc768120..cf565f615f 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs
@@ -70,8 +70,8 @@ namespace MonoDevelop.PackageManagement
public override void Activate ()
{
- var runner = new AddPackagesDialogRunner ();
- runner.Run (pattern.UnparsedPattern);
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject, pattern.UnparsedPattern);
}
public override string GetMarkupText (bool selected)
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs
new file mode 100644
index 0000000000..c2b00625df
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs
@@ -0,0 +1,101 @@
+//
+// SelectProjectsViewModel.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 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.Collections.Generic;
+using System.Linq;
+
+namespace MonoDevelop.PackageManagement
+{
+ class SelectProjectsViewModel
+ {
+ readonly List<SelectedProjectViewModel> projects;
+
+ public SelectProjectsViewModel (
+ IEnumerable<IDotNetProject> projects,
+ int packagesCount,
+ ManagePackagesPage page)
+ {
+ this.projects = projects
+ .OrderBy (project => project.Name)
+ .Select (project => new SelectedProjectViewModel (project))
+ .ToList ();
+
+ if (this.projects.Count == 1) {
+ this.projects[0].IsSelected = true;
+ }
+
+ bool multiplePackages = packagesCount > 1;
+
+ switch (page) {
+ case ManagePackagesPage.Installed:
+ IsRemovingMultiplePackages = multiplePackages;
+ IsRemovingSinglePackage = !IsAddingMultiplePackages;
+ break;
+ case ManagePackagesPage.Browse:
+ IsAddingMultiplePackages = multiplePackages;
+ IsAddingSinglePackage = !IsAddingMultiplePackages;
+ break;
+ case ManagePackagesPage.Updates:
+ IsUpdatingMultiplePackages = multiplePackages;
+ IsUpdatingSinglePackage = !IsAddingMultiplePackages;
+ SelectAllProjectsByDefault ();
+ break;
+ case ManagePackagesPage.Consolidate:
+ IsConsolidatingMultiplePackages = multiplePackages;
+ IsConsolidatingSinglePackage = !IsAddingMultiplePackages;
+ SelectAllProjectsByDefault ();
+ break;
+ }
+ }
+
+ public IEnumerable<SelectedProjectViewModel> Projects {
+ get { return projects; }
+ }
+
+ public bool IsAddingSinglePackage { get; }
+ public bool IsAddingMultiplePackages { get; }
+ public bool IsRemovingSinglePackage { get; }
+ public bool IsRemovingMultiplePackages { get; }
+ public bool IsUpdatingSinglePackage { get; }
+ public bool IsUpdatingMultiplePackages { get; }
+ public bool IsConsolidatingSinglePackage { get; }
+ public bool IsConsolidatingMultiplePackages { get; }
+
+ public IEnumerable<IDotNetProject> GetSelectedProjects ()
+ {
+ return projects
+ .Where (viewModel => viewModel.IsSelected)
+ .Select (viewModel => viewModel.Project);
+ }
+
+ void SelectAllProjectsByDefault ()
+ {
+ foreach (SelectedProjectViewModel project in projects) {
+ project.IsSelected = true;
+ }
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs
new file mode 100644
index 0000000000..fa3b0ca585
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs
@@ -0,0 +1,48 @@
+//
+// SelectedProjectViewModel.cs
+//
+// Author:
+// matt <matt.ward@xamarin.com>
+//
+// Copyright (c) 2016 matt
+//
+// 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 MonoDevelop.Core;
+
+namespace MonoDevelop.PackageManagement
+{
+ class SelectedProjectViewModel
+ {
+ public SelectedProjectViewModel (IDotNetProject project)
+ {
+ Project = project;
+ }
+
+ public IDotNetProject Project { get; }
+ public bool IsSelected { get; set; }
+
+ public string Name {
+ get { return Project.Name; }
+ }
+
+ public IconId Icon {
+ get { return Project.DotNetProject.StockIcon; }
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs
new file mode 100644
index 0000000000..5b68f63444
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs
@@ -0,0 +1,111 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Packaging.Core;
+using NuGet.Protocol.Core.Types;
+
+namespace NuGet.PackageManagement.UI
+{
+ /// <summary>
+ /// Package feed facilitating iteration over installed packages needing version consolidation
+ /// </summary>
+ internal class ConsolidatePackageFeed : PlainPackageFeedBase
+ {
+ IEnumerable<PackageIdentity> _installedPackages;
+ readonly IPackageMetadataProvider _metadataProvider;
+ PackageLoadContext _context;
+
+ public ConsolidatePackageFeed (
+ PackageLoadContext context,
+ IPackageMetadataProvider metadataProvider,
+ Common.ILogger logger)
+ : this (new PackageIdentity[0], metadataProvider, logger)
+ {
+ _context = context;
+ }
+
+ public ConsolidatePackageFeed (
+ IEnumerable<PackageIdentity> installedPackages,
+ IPackageMetadataProvider metadataProvider,
+ Common.ILogger logger)
+ {
+ if (installedPackages == null) {
+ throw new ArgumentNullException (nameof (installedPackages));
+ }
+ _installedPackages = installedPackages;
+
+ if (metadataProvider == null) {
+ throw new ArgumentNullException (nameof (metadataProvider));
+ }
+ _metadataProvider = metadataProvider;
+
+ if (logger == null) {
+ throw new ArgumentNullException (nameof (logger));
+ }
+
+ PageSize = 25;
+ }
+
+ public override async Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken)
+ {
+ var searchToken = continuationToken as FeedSearchContinuationToken;
+ if (searchToken == null) {
+ throw new InvalidOperationException ("Invalid token");
+ }
+
+ if (_context != null) {
+ _installedPackages = await _context.GetInstalledPackagesAsync ();
+ _context = null;
+ }
+
+ var packagesNeedingConsolidation = _installedPackages
+ .GroupById ()
+ .Where (g => g.Count () > 1)
+ .Select (g => new PackageIdentity (g.Key, g.Max ()))
+ .ToArray ();
+
+ var packages = packagesNeedingConsolidation
+ .Where (p => p.Id.IndexOf (searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1)
+ .OrderBy (p => p.Id)
+ .Skip (searchToken.StartIndex)
+ .Take (PageSize + 1)
+ .ToArray ();
+
+ var hasMoreItems = packages.Length > PageSize;
+ if (hasMoreItems) {
+ packages = packages.Take (packages.Length - 1).ToArray ();
+ }
+
+ var items = await TaskCombinators.ThrottledAsync (
+ packages,
+ (p, t) => _metadataProvider.GetPackageMetadataAsync (p, searchToken.SearchFilter.IncludePrerelease, t),
+ cancellationToken);
+
+ var result = SearchResult.FromItems (items.ToArray ());
+
+ var loadingStatus = hasMoreItems
+ ? LoadingStatus.Ready
+ : packages.Length == 0
+ ? LoadingStatus.NoItemsFound
+ : LoadingStatus.NoMoreItems;
+ result.SourceSearchStatus = new Dictionary<string, LoadingStatus> {
+ { "Consolidate", loadingStatus }
+ };
+
+ if (hasMoreItems) {
+ result.NextToken = new FeedSearchContinuationToken {
+ SearchString = searchToken.SearchString,
+ SearchFilter = searchToken.SearchFilter,
+ StartIndex = searchToken.StartIndex + packages.Length
+ };
+ }
+
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs
new file mode 100644
index 0000000000..9bbc222d85
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs
@@ -0,0 +1,119 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Packaging.Core;
+using NuGet.Protocol.Core.Types;
+
+namespace NuGet.PackageManagement.UI
+{
+ /// <summary>
+ /// Represents a package feed enumerating installed packages.
+ /// </summary>
+ internal class InstalledPackageFeed : PlainPackageFeedBase
+ {
+ IEnumerable<PackageIdentity> _installedPackages;
+ readonly IPackageMetadataProvider _metadataProvider;
+ PackageLoadContext _context;
+
+ public InstalledPackageFeed (
+ PackageLoadContext context,
+ IPackageMetadataProvider metadataProvider,
+ Common.ILogger logger)
+ : this (new PackageIdentity[0], metadataProvider, logger)
+ {
+ this._context = context;
+ }
+
+ public InstalledPackageFeed (
+ IEnumerable<PackageIdentity> installedPackages,
+ IPackageMetadataProvider metadataProvider,
+ Common.ILogger logger)
+ {
+ if (installedPackages == null) {
+ throw new ArgumentNullException (nameof (installedPackages));
+ }
+ _installedPackages = installedPackages;
+
+ if (metadataProvider == null) {
+ throw new ArgumentNullException (nameof (metadataProvider));
+ }
+ _metadataProvider = metadataProvider;
+
+ if (logger == null) {
+ throw new ArgumentNullException (nameof (logger));
+ }
+
+ PageSize = 25;
+ }
+
+ public override async Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken)
+ {
+ var searchToken = continuationToken as FeedSearchContinuationToken;
+ if (searchToken == null) {
+ throw new InvalidOperationException ("Invalid token");
+ }
+
+ if (_context != null) {
+ _installedPackages = await _context.GetInstalledPackagesAsync ();
+ _context = null;
+ }
+
+ var packages = _installedPackages
+ .GetLatest ()
+ .Where (p => p.Id.IndexOf (searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1)
+ .OrderBy (p => p.Id)
+ .Skip (searchToken.StartIndex)
+ .Take (PageSize + 1)
+ .ToArray ();
+
+ var hasMoreItems = packages.Length > PageSize;
+ if (hasMoreItems) {
+ packages = packages.Take (packages.Length - 1).ToArray ();
+ }
+
+ var items = await TaskCombinators.ThrottledAsync (
+ packages,
+ (p, t) => GetPackageMetadataAsync (p, searchToken.SearchFilter.IncludePrerelease, t),
+ cancellationToken);
+
+ // The packages were originally sorted which is important because we Skip and Take based on that sort
+ // however the asynchronous execution has randomly reordered the set. So we need to resort.
+ var result = SearchResult.FromItems (items.OrderBy (p => p.Identity.Id).ToArray ());
+
+ var loadingStatus = hasMoreItems
+ ? LoadingStatus.Ready
+ : packages.Length == 0
+ ? LoadingStatus.NoItemsFound
+ : LoadingStatus.NoMoreItems;
+ result.SourceSearchStatus = new Dictionary<string, LoadingStatus> {
+ { "Installed", loadingStatus }
+ };
+
+ if (hasMoreItems) {
+ result.NextToken = new FeedSearchContinuationToken {
+ SearchString = searchToken.SearchString,
+ SearchFilter = searchToken.SearchFilter,
+ StartIndex = searchToken.StartIndex + packages.Length
+ };
+ }
+
+ return result;
+ }
+
+ async Task<IPackageSearchMetadata> GetPackageMetadataAsync (PackageIdentity identity, bool includePrerelease, CancellationToken cancellationToken)
+ {
+ // first we try and load the metadata from a local package
+ var packageMetadata = await _metadataProvider.GetLocalPackageMetadataAsync (identity, includePrerelease, cancellationToken);
+ if (packageMetadata == null) {
+ // and failing that we go to the network
+ packageMetadata = await _metadataProvider.GetPackageMetadataAsync (identity, includePrerelease, cancellationToken);
+ }
+ return packageMetadata;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs
new file mode 100644
index 0000000000..c369377f40
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Packaging.Core;
+using NuGet.ProjectManagement;
+using NuGet.Versioning;
+
+namespace NuGet.PackageManagement.UI
+{
+ /// <summary>
+ /// Wrapper class consolidating common queries against a collection of packages
+ /// </summary>
+ internal class PackageCollection : IEnumerable<PackageIdentity>
+ {
+ readonly PackageIdentity[] _packages;
+ readonly ISet<string> _uniqueIds = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
+
+ public PackageCollection (PackageIdentity[] packages)
+ {
+ _packages = packages;
+ _uniqueIds.UnionWith (_packages.Select (p => p.Id));
+ }
+
+ public IEnumerator<PackageIdentity> GetEnumerator ()
+ {
+ return ((IEnumerable<PackageIdentity>)_packages).GetEnumerator ();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return ((IEnumerable<PackageIdentity>)_packages).GetEnumerator ();
+ }
+
+ public bool ContainsId (string packageId) => _uniqueIds.Contains (packageId);
+
+ public static async Task<PackageCollection> FromProjectsAsync (IEnumerable<NuGetProject> projects, CancellationToken cancellationToken)
+ {
+ var tasks = projects
+ .Select (project => project.GetInstalledPackagesAsync (cancellationToken));
+ var packageReferences = await Task.WhenAll (tasks);
+ var packages = packageReferences
+ .SelectMany (p => p)
+ .Where (p => p != null)
+ .Select (p => p.PackageIdentity)
+ .Distinct (PackageIdentity.Comparer)
+ .ToArray ();
+
+ return new PackageCollection (packages);
+ }
+ }
+
+ /// <summary>
+ /// Common package queries implementes as extension methods
+ /// </summary>
+ internal static class PackageCollectionExtensions
+ {
+ public static NuGetVersion[] GetPackageVersions (this IEnumerable<PackageIdentity> packages, string packageId)
+ {
+ return packages
+ .Where (p => StringComparer.OrdinalIgnoreCase.Equals (p.Id, packageId))
+ .Select (p => p.Version)
+ .ToArray ();
+ }
+
+ public static IEnumerable<IGrouping<string, NuGetVersion>> GroupById (this IEnumerable<PackageIdentity> packages)
+ {
+ return packages
+ .GroupBy (p => p.Id, p => p.Version, StringComparer.OrdinalIgnoreCase);
+ }
+
+ public static PackageIdentity[] GetLatest (this IEnumerable<PackageIdentity> packages)
+ {
+ return packages
+ .GroupById ()
+ .Select (g => new PackageIdentity (g.Key, g.MaxOrDefault ()))
+ .ToArray ();
+ }
+
+ public static PackageIdentity[] GetEarliest (this IEnumerable<PackageIdentity> packages)
+ {
+ return packages
+ .GroupById ()
+ .Select (g => new PackageIdentity (g.Key, g.MinOrDefault ()))
+ .ToArray ();
+ }
+ }
+
+ internal static class VersionCollectionExtensions
+ {
+ public static NuGetVersion MinOrDefault (this IEnumerable<NuGetVersion> versions)
+ {
+ return versions
+ .OrderBy (v => v, VersionComparer.Default)
+ .FirstOrDefault ();
+ }
+
+ public static NuGetVersion MaxOrDefault (this IEnumerable<NuGetVersion> versions)
+ {
+ return versions
+ .OrderByDescending (v => v, VersionComparer.Default)
+ .FirstOrDefault ();
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs
index 954558f2f6..89b94c5815 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs
@@ -25,7 +25,7 @@ namespace NuGet.PackageManagement.UI
IEnumerable<NuGetProject> nugetProjects)
: base(nugetProjects)
{
- Debug.Assert(nugetProjects.Count() == 1);
+ //Debug.Assert(nugetProjects.Count() == 1);
}
//public async override Task SetCurrentPackage(
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs
new file mode 100644
index 0000000000..b52e1f8c8a
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs
@@ -0,0 +1,119 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Protocol.Core.Types;
+
+namespace NuGet.PackageManagement.UI
+{
+ internal class PackageFeedEnumerator : IEnumerator<IPackageSearchMetadata>, IDisposable, IEnumerator
+ {
+ private readonly IPackageFeed _packageFeed;
+ private readonly Task<SearchResult<IPackageSearchMetadata>> _startFromTask;
+ private readonly CancellationToken _cancellationToken;
+
+ private Task<SearchResult<IPackageSearchMetadata>> _searchTask;
+ private IEnumerator<IPackageSearchMetadata> _current;
+
+ private PackageFeedEnumerator (
+ IPackageFeed packageFeed,
+ Task<SearchResult<IPackageSearchMetadata>> searchTask,
+ CancellationToken cancellationToken)
+ {
+ if (packageFeed == null) {
+ throw new ArgumentNullException (nameof (packageFeed));
+ }
+ _packageFeed = packageFeed;
+
+ if (searchTask == null) {
+ throw new ArgumentNullException (nameof (searchTask));
+ }
+ _startFromTask = searchTask;
+
+ _cancellationToken = cancellationToken;
+
+ Reset ();
+ }
+
+ private PackageFeedEnumerator (PackageFeedEnumerator other)
+ {
+ if (other == null) {
+ throw new ArgumentNullException (nameof (other));
+ }
+ _packageFeed = other._packageFeed;
+ _startFromTask = other._startFromTask;
+ _cancellationToken = other._cancellationToken;
+
+ Reset ();
+ }
+
+ public IPackageSearchMetadata Current => _current.Current;
+
+ object IEnumerator.Current => _current.Current;
+
+ public void Dispose ()
+ {
+ }
+
+ public bool MoveNext ()
+ {
+ if (_current.MoveNext ()) {
+ return true;
+ }
+
+ LoadNextAsync ().Wait ();
+ return _current.MoveNext ();
+ }
+
+ private async Task LoadNextAsync ()
+ {
+ var searchResult = await _searchTask;
+
+ while (searchResult.RefreshToken != null) {
+ searchResult = await _packageFeed.RefreshSearchAsync (searchResult.RefreshToken, _cancellationToken);
+ }
+
+ _current = searchResult.GetEnumerator ();
+
+ if (searchResult.NextToken != null) {
+ _searchTask = _packageFeed.ContinueSearchAsync (searchResult.NextToken, _cancellationToken);
+ } else {
+ _searchTask = Task.FromResult (SearchResult.Empty<IPackageSearchMetadata> ());
+ }
+ }
+
+ public void Reset ()
+ {
+ _searchTask = _startFromTask;
+ _current = Enumerable.Empty<IPackageSearchMetadata> ().GetEnumerator ();
+ }
+
+ public static IEnumerable<IPackageSearchMetadata> Enumerate (
+ IPackageFeed packageFeed,
+ Task<SearchResult<IPackageSearchMetadata>> searchTask,
+ CancellationToken cancellationToken)
+ {
+ var enumerator = new PackageFeedEnumerator (packageFeed, searchTask, cancellationToken);
+ return new PackageFeedEnumerable (enumerator);
+ }
+
+ private sealed class PackageFeedEnumerable : IEnumerable<IPackageSearchMetadata>
+ {
+ private readonly PackageFeedEnumerator _enumerator;
+
+ public PackageFeedEnumerable (PackageFeedEnumerator enumerator)
+ {
+ _enumerator = enumerator;
+ }
+
+ public IEnumerator<IPackageSearchMetadata> GetEnumerator () => new PackageFeedEnumerator (_enumerator);
+
+ IEnumerator IEnumerable.GetEnumerator () => this.GetEnumerator ();
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs
index e69db3cefb..994c60d122 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs
@@ -14,7 +14,7 @@ namespace NuGet.PackageManagement.UI
{
internal class PackageLoadContext
{
- //private readonly Task<PackageCollection> _installedPackagesTask;
+ Task<PackageCollection> installedPackagesTask;
public IEnumerable<SourceRepository> SourceRepositories { get; private set; }
@@ -32,18 +32,18 @@ namespace NuGet.PackageManagement.UI
public PackageLoadContext(
IEnumerable<SourceRepository> sourceRepositories,
bool isSolution,
- NuGetProject project)
+ IEnumerable<NuGetProject> projects)
{
SourceRepositories = sourceRepositories;
IsSolution = isSolution;
//PackageManager = uiContext.PackageManager;
- Projects = new [] { project };
+ Projects = projects.ToArray ();
//PackageManagerProviders = uiContext.PackageManagerProviders;
- //_installedPackagesTask = PackageCollection.FromProjectsAsync(Projects, CancellationToken.None);
+ installedPackagesTask = PackageCollection.FromProjectsAsync(Projects, CancellationToken.None);
}
- //public Task<PackageCollection> GetInstalledPackagesAsync() =>_installedPackagesTask;
+ public Task<PackageCollection> GetInstalledPackagesAsync() => installedPackagesTask;
// Returns the list of frameworks that we need to pass to the server during search
public IEnumerable<string> GetSupportedFrameworks()
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs
new file mode 100644
index 0000000000..e61d3dc360
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs
@@ -0,0 +1,17 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using NuGet.Protocol.Core.Types;
+
+namespace NuGet.PackageManagement.UI
+{
+ class PackageSearchMetadataCache
+ {
+ // Cached Package Metadata
+ public IReadOnlyList<IPackageSearchMetadata> Packages { get; set; }
+
+ // Remember the IncludePrerelease setting corresponding to the Cached Metadata
+ public bool IncludePrerelease { get; set; }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs
new file mode 100644
index 0000000000..360656f33e
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs
@@ -0,0 +1,36 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Protocol.Core.Types;
+
+namespace NuGet.PackageManagement.UI
+{
+ /// <summary>
+ /// Shared base implementation of plain package feeds.
+ /// </summary>
+ internal abstract class PlainPackageFeedBase : IPackageFeed
+ {
+ public int PageSize { get; protected set; } = 100;
+
+ // No, it's not.
+ public bool IsMultiSource => false;
+
+ public Task<SearchResult<IPackageSearchMetadata>> SearchAsync (string searchText, SearchFilter searchFilter, CancellationToken cancellationToken)
+ {
+ var searchToken = new FeedSearchContinuationToken {
+ SearchString = searchText,
+ SearchFilter = searchFilter,
+ StartIndex = 0
+ };
+
+ return ContinueSearchAsync (searchToken, cancellationToken);
+ }
+
+ public abstract Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken);
+
+ public Task<SearchResult<IPackageSearchMetadata>> RefreshSearchAsync (RefreshToken refreshToken, CancellationToken cancellationToken)
+ => Task.FromResult (SearchResult.Empty<IPackageSearchMetadata> ());
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs
new file mode 100644
index 0000000000..173cee7c64
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs
@@ -0,0 +1,121 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Packaging.Core;
+using NuGet.Protocol.Core.Types;
+using NuGet.Versioning;
+
+namespace NuGet.PackageManagement.UI
+{
+ /// <summary>
+ /// A package feed providing services of package enumeration of installed packages having updated versions in upstream source(s).
+ /// </summary>
+ internal class UpdatePackageFeed : PlainPackageFeedBase
+ {
+ IEnumerable<PackageIdentity> _installedPackages;
+ readonly IPackageMetadataProvider _metadataProvider;
+ readonly PackageSearchMetadataCache _cachedUpdates;
+ PackageLoadContext _context;
+
+ public UpdatePackageFeed (
+ PackageLoadContext context,
+ IPackageMetadataProvider metadataProvider,
+ PackageSearchMetadataCache cachedUpdates,
+ Common.ILogger logger)
+ : this (new PackageIdentity[0], metadataProvider, cachedUpdates, logger)
+ {
+ _context = context;
+ }
+
+ public UpdatePackageFeed (
+ IEnumerable<PackageIdentity> installedPackages,
+ IPackageMetadataProvider metadataProvider,
+ PackageSearchMetadataCache cachedUpdates,
+ Common.ILogger logger)
+ {
+ if (installedPackages == null) {
+ throw new ArgumentNullException (nameof (installedPackages));
+ }
+ _installedPackages = installedPackages;
+
+ if (metadataProvider == null) {
+ throw new ArgumentNullException (nameof (metadataProvider));
+ }
+ _metadataProvider = metadataProvider;
+
+ _cachedUpdates = cachedUpdates;
+
+ if (logger == null) {
+ throw new ArgumentNullException (nameof (logger));
+ }
+ }
+
+ public override async Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken)
+ {
+ var searchToken = continuationToken as FeedSearchContinuationToken;
+ if (searchToken == null) {
+ throw new InvalidOperationException ("Invalid token");
+ }
+
+ var packagesWithUpdates = (_cachedUpdates.Packages != null) && (_cachedUpdates?.IncludePrerelease == searchToken.SearchFilter.IncludePrerelease)
+ ?
+ GetPackagesFromCache (searchToken.SearchString)
+ :
+ await GetPackagesWithUpdatesAsync (searchToken.SearchString, searchToken.SearchFilter, cancellationToken);
+
+ var items = packagesWithUpdates
+ .Skip (searchToken.StartIndex)
+ .ToArray ();
+
+ var result = SearchResult.FromItems (items);
+
+ var loadingStatus = items.Length == 0
+ ? LoadingStatus.NoItemsFound
+ : LoadingStatus.NoMoreItems;
+ result.SourceSearchStatus = new Dictionary<string, LoadingStatus> {
+ { "Update", loadingStatus }
+ };
+
+ return result;
+ }
+
+ IEnumerable<IPackageSearchMetadata> GetPackagesFromCache (string searchText)
+ {
+ return _cachedUpdates.Packages.Where (p => p.Identity.Id.IndexOf (searchText, StringComparison.OrdinalIgnoreCase) != -1);
+ }
+
+ async Task<IEnumerable<IPackageSearchMetadata>> GetPackagesWithUpdatesAsync (string searchText, SearchFilter searchFilter, CancellationToken cancellationToken)
+ {
+ if (_context != null) {
+ _installedPackages = await _context.GetInstalledPackagesAsync ();
+ _context = null;
+ }
+
+ var packages = _installedPackages
+ .GetEarliest ()
+ .Where (p => p.Id.IndexOf (searchText, StringComparison.OrdinalIgnoreCase) != -1)
+ .OrderBy (p => p.Id);
+
+ var latestItems = await TaskCombinators.ThrottledAsync (
+ packages,
+ (p, t) => _metadataProvider.GetLatestPackageMetadataAsync (p, searchFilter.IncludePrerelease, t),
+ cancellationToken);
+
+ var packagesWithUpdates = packages
+ .Join (latestItems.Where (i => i != null),
+ p => p.Id,
+ m => m.Identity.Id,
+ (p, m) => new { cv = p.Version, m = m },
+ StringComparer.OrdinalIgnoreCase)
+ .Where (j => VersionComparer.VersionRelease.Compare (j.cv, j.m.Identity.Version) < 0)
+ .Select (j => j.m);
+
+ return packagesWithUpdates;
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs
index 36398008a6..336df933d5 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs
@@ -76,11 +76,19 @@ namespace MonoDevelop.AnalysisCore.Gui
protected override void Initialize ()
{
base.Initialize ();
-
+ if (Editor.Options is DefaultSourceEditorOptions options)
+ options.Changed += Options_Changed;
AnalysisOptions.AnalysisEnabled.Changed += AnalysisOptionsChanged;
AnalysisOptionsChanged (null, null);
}
+ void Options_Changed (object sender, EventArgs e)
+ {
+ if (DocumentContext == null || !enabled)
+ return;
+ UpdateInitialDiagnostics ();
+ }
+
void AnalysisOptionsChanged (object sender, EventArgs e)
{
Enabled = AnalysisOptions.AnalysisEnabled;
@@ -91,6 +99,8 @@ namespace MonoDevelop.AnalysisCore.Gui
if (disposed)
return;
enabled = false;
+ if (Editor.Options is DefaultSourceEditorOptions options)
+ options.Changed -= Options_Changed;
diagService.DiagnosticsUpdated -= OnDiagnosticsUpdated;
diagService = null;
CancelUpdateTimout ();
@@ -154,7 +164,7 @@ namespace MonoDevelop.AnalysisCore.Gui
if (!AnalysisOptions.EnableFancyFeatures)
return;
- var doc = DocumentContext.AnalysisDocument;
+ var doc = DocumentContext?.AnalysisDocument;
if (doc == null || DocumentContext.IsAdHocProject)
return;
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs
index 75aabfe88a..a630aca56b 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs
@@ -128,6 +128,9 @@ namespace MonoDevelop.Refactoring.PackageInstaller
installedPackages.ContainsKey (packageName);
}
+ public bool CanShowManagePackagesDialog ()
+ => true;
+
public void ShowManagePackagesDialog (string packageName)
{
PackageServices.ShowManagePackagesDialog (packageName);
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs
index 38d4003d5b..30fbbd073e 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs
@@ -725,20 +725,18 @@ namespace MonoDevelop.SourceEditor.QuickTasks
{
var breakpointStore = parentStrip.SourceEditorView.Breakpoints;
- lock (breakpointStore) {
- var breakPoints = breakpointStore.GetBreakpointsAtFile (TextEditor.FileName);
+ var breakPoints = breakpointStore.GetBreakpointsAtFile (TextEditor.FileName);
- if (breakPoints == null)
- return;
+ if (breakPoints == null)
+ return;
- foreach (var point in breakPoints) {
- int y = (int)GetYPosition (point.Line);
+ foreach (var point in breakPoints) {
+ int y = (int)GetYPosition (point.Line);
- cr.SetSourceColor (SyntaxHighlightingService.GetColor (TextEditor.EditorTheme, EditorThemeColors.BreakpointMarker));
- int r = 4;
- cr.Rectangle (0, y - r / 2, r, r);
- cr.Fill ();
- }
+ cr.SetSourceColor (SyntaxHighlightingService.GetColor (TextEditor.EditorTheme, EditorThemeColors.BreakpointMarker));
+ int r = 4;
+ cr.Rectangle (0, y - r / 2, r, r);
+ cr.Fill ();
}
}
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
index c9407e4dbe..365927bafe 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
@@ -1348,17 +1348,15 @@ namespace MonoDevelop.SourceEditor
int i = 0, count = 0;
bool mismatch = false;
- lock (breakpoints) {
- foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) {
- count++;
- if (i < breakpointSegments.Count) {
- int lineNumber = document.OffsetToLineNumber (breakpointSegments [i].TextMarker.Offset);
- if (lineNumber != bp.Line) {
- mismatch = true;
- break;
- }
- i++;
+ foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) {
+ count++;
+ if (i < breakpointSegments.Count) {
+ int lineNumber = document.OffsetToLineNumber (breakpointSegments [i].TextMarker.Offset);
+ if (lineNumber != bp.Line) {
+ mismatch = true;
+ break;
}
+ i++;
}
}
@@ -1383,11 +1381,9 @@ namespace MonoDevelop.SourceEditor
breakpointSegments.Clear ();
- lock (breakpoints) {
- foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) {
- lineNumbers.Add (bp.Line);
- AddBreakpoint (bp);
- }
+ foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) {
+ lineNumbers.Add (bp.Line);
+ AddBreakpoint (bp);
}
foreach (int lineNumber in lineNumbers) {
@@ -1506,8 +1502,7 @@ namespace MonoDevelop.SourceEditor
int column = TextEditor.Caret.Line == args.LineNumber ?
Math.Min (TextEditor.Caret.Column, args.LineSegment.Length) : 1;
- lock (breakpoints)
- breakpoints.Toggle (Document.FileName, args.LineNumber, column);
+ breakpoints.Toggle (Document.FileName, args.LineNumber, column);
}
}
}
diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml
index 3cbda1c2bc..c78c5cae0f 100644
--- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml
+++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml
@@ -97,8 +97,12 @@
-->
<Map id="MonoDevelop.Ide.Commands.SearchCommands.Find" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.SearchCommands.FindNext" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindNextCommandArgs" />
+ <Map id="MonoDevelop.Ide.Commands.SearchCommands.FindNextSelection" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindNextLikeSelectionCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.SearchCommands.FindPrevious" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindPreviousCommandArgs" />
+ <Map id="MonoDevelop.Ide.Commands.SearchCommands.FindPreviousSelection" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindPreviousLikeSelectionCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.SearchCommands.Replace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ReplaceCommandArgs" />
+ <Map id="MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForReplace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ReplaceCommandArgs" />
+ <Map id="MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForFind" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.SetSearchStringFromSelectionCommandArgs" />
<Map id="MonoDevelop.Refactoring.Navigate.GotoBaseMember" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.Navigation.GoToBaseMemberCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.SearchCommands.GotoLineNumber" argsType="Microsoft.VisualStudio.Text.Extras.GoToLine.GoToLineCommandArgs" />
</Extension>
diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml
index 969f61f267..0e5345b0a0 100644
--- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml
+++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml
@@ -146,7 +146,7 @@
<Map id="MonoDevelop.Ide.Commands.TextEditorCommands.ShowCodeTemplateWindow" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.InsertSnippetCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.TextEditorCommands.ShowCodeSurroundingsWindow" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.SurroundWithCommandArgs" />
- <Map id="MonoDevelop.Ide.Commands.TextEditorCommands.GotoMatchingBrace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.GoToMatchingBraceCommandArgs" />
+ <Map id="MonoDevelop.Ide.Commands.TextEditorCommands.GotoMatchingBrace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.GotoBraceCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.EditCommands.ToggleFolding" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ToggleOutliningExpansionCommandArgs" />
<Map id="MonoDevelop.Ide.Commands.EditCommands.ToggleAllFoldings" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ToggleAllOutliningCommandArgs" />
diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml
index 3d0d711c33..0e1bf46362 100644
--- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml
+++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml
@@ -32,7 +32,7 @@
</References>
<Packages>
- <Package ID="NUnit" Version="2.6.4" />
+ <Package ID="NUnit" Version="3.12.0" />
</Packages>
<Files>
diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml
index c6aa7ce400..f64fde474b 100644
--- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml
+++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml
@@ -32,7 +32,7 @@
</References>
<Packages>
- <Package ID="NUnit" Version="2.6.4" />
+ <Package ID="NUnit" Version="3.12.0" />
</Packages>
<Files>
diff --git a/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs b/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs
index 317e5d1840..017c404aef 100644
--- a/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs
+++ b/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs
@@ -53,12 +53,12 @@ namespace MonoDeveloper
public override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
{
- return Task.Run (() => (SolutionItem) ReadFile (fileName, false, monitor));
+ return Task.FromResult ((SolutionItem) ReadFile (fileName, false, monitor));
}
public override Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName)
{
- return Task.Run (() => (WorkspaceItem) ReadFile (fileName, false, monitor));
+ return Task.FromResult ((WorkspaceItem) ReadFile (fileName, false, monitor));
}
public object ReadFile (FilePath fileName, bool hasParentSolution, ProgressMonitor monitor)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj
index 700e35fb91..9634a9d7df 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj
@@ -51,6 +51,8 @@
<ProjectReference Include="..\..\..\..\external\libgit2sharp\LibGit2Sharp\LibGit2Sharp.csproj">
<Project>{EE6ED99F-CB12-4683-B055-D28FC7357A34}</Project>
<Name>LibGit2Sharp</Name>
+ <IncludeInPackage>true</IncludeInPackage>
+ <Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\MonoDevelop.SourceEditor2\MonoDevelop.SourceEditor.csproj">
<Project>{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}</Project>
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs
index f4bfaf9b98..0669b396e5 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs
@@ -38,10 +38,7 @@ namespace MonoDevelop.VersionControl
{
public static bool DefaultVCSViewCanHandle (VersionControlItem item, DocumentController controller)
{
- if (controller == null)
- return item.Repository.GetFileIsText (item.Path);
-
- return controller is TextEditorViewContent || controller.GetContent<ITextBuffer> () != null;
+ return item.Repository.GetFileIsText (item.Path);
}
public bool CanHandle (VersionControlItem item, DocumentController controller) => DefaultVCSViewCanHandle (item, controller);
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs
index 2ed8162614..d96e660e96 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs
@@ -1,4 +1,4 @@
-using MonoDevelop.Components.MainToolbar;
+using MonoDevelop.Components.MainToolbar;
using MonoDevelop.Components.Windows;
using MonoDevelop.Core;
using System;
@@ -25,24 +25,25 @@ namespace WindowsPlatform.MainToolbar
public class WPFToolbar : GtkWPFWidget, IMainToolbarView, INotifyPropertyChanged
{
ToolBar toolbar;
+
WPFToolbar (ToolBar toolbar) : base (toolbar)
{
this.toolbar = toolbar;
toolbar.ConfigurationMenu.SelectionChanged += (o, e) => {
- var comboMenu = (ComboMenu<IConfigurationModel>)o;
+ var comboMenu = (ComboMenu<IConfigurationModel>) o;
var newModel = e.Added;
if (newModel == null)
return;
- Runtime.RunInMainThread(() => {
+ Runtime.RunInMainThread (() => {
ActiveConfiguration = newModel;
ConfigurationChanged?.Invoke (o, e);
});
};
toolbar.RunConfigurationMenu.SelectionChanged += (o, e) => {
- var comboMenu = (ComboMenu<IRunConfigurationModel>)o;
+ var comboMenu = (ComboMenu<IRunConfigurationModel>) o;
var newModel = e.Added;
if (newModel == null)
return;
@@ -58,11 +59,11 @@ namespace WindowsPlatform.MainToolbar
if (newModel == null)
return;
- using (var mutableModel = newModel.GetMutableModel()) {
- Runtime.RunInMainThread(() => {
+ using (var mutableModel = newModel.GetMutableModel ()) {
+ Runtime.RunInMainThread (() => {
ActiveRuntime = newModel;
- var ea = new MonoDevelop.Components.MainToolbar.HandledEventArgs();
+ var ea = new MonoDevelop.Components.MainToolbar.HandledEventArgs ();
RuntimeChanged?.Invoke (o, ea);
if (ea.Handled)
@@ -80,7 +81,7 @@ namespace WindowsPlatform.MainToolbar
if (SearchText == SearchPlaceholderMessage)
return;
- if (SearchEntryChanged != null)
+ if (SearchEntryChanged != null)
SearchEntryChanged (o, e);
};
@@ -90,9 +91,7 @@ namespace WindowsPlatform.MainToolbar
toolbar.SearchBar.SearchText = toolbar.SearchBar.PlaceholderText;
};
- toolbar.SearchBar.SearchBar.GotKeyboardFocus += (o, e) => {
- SearchEntryActivated?.Invoke (o, e);
- };
+ toolbar.SearchBar.SearchBar.GotKeyboardFocus += (o, e) => { SearchEntryActivated?.Invoke (o, e); };
toolbar.SearchBar.SearchBar.SizeChanged += (o, e) => {
if (SearchEntryResized != null)
@@ -100,41 +99,41 @@ namespace WindowsPlatform.MainToolbar
};
toolbar.SearchBar.SearchBar.PreviewKeyDown += (o, e) => {
- var ka = new KeyEventArgs(KeyboardUtil.TranslateToXwtKey(e.Key), KeyboardUtil.GetModifiers(), e.IsRepeat, e.Timestamp);
- SendKeyPress(ka);
+ var ka = new KeyEventArgs (KeyboardUtil.TranslateToXwtKey (e.Key), KeyboardUtil.GetModifiers (),
+ e.IsRepeat, e.Timestamp);
+ SendKeyPress (ka);
e.Handled = ka.Handled;
};
- toolbar.SearchBar.ClearIconClicked += (o, e) =>
- {
- SendKeyPress(new KeyEventArgs(Xwt.Key.Escape, KeyboardUtil.GetModifiers(), false, 0));
+ toolbar.SearchBar.ClearIconClicked += (o, e) => {
+ SendKeyPress (new KeyEventArgs (Xwt.Key.Escape, KeyboardUtil.GetModifiers (), false, 0));
};
- }
+ }
- protected override void RepositionWpfWindow()
- {
- int scale = (int)MonoDevelop.Components.GtkWorkarounds.GetScaleFactor(this);
- RepositionWpfWindow (scale, scale);
- }
+ protected override void RepositionWpfWindow ()
+ {
+ int scale = (int) MonoDevelop.Components.GtkWorkarounds.GetScaleFactor (this);
+ RepositionWpfWindow (scale, scale);
+ }
- void SendKeyPress(KeyEventArgs ka)
+ void SendKeyPress (KeyEventArgs ka)
{
if (SearchEntryKeyPressed != null)
- SearchEntryKeyPressed(this, ka);
+ SearchEntryKeyPressed (this, ka);
}
public WPFToolbar () : this (new ToolBar ())
{
}
-
+
public IConfigurationModel ActiveConfiguration {
get { return toolbar.ConfigurationMenu.Active; }
set { toolbar.ConfigurationMenu.Active = value; }
}
-
+
public IRuntimeModel ActiveRuntime {
- get { return toolbar.RuntimeMenu.Active; }
- set { toolbar.RuntimeMenu.Active = value; }
+ get { return toolbar.RuntimeMenu.Active; }
+ set { toolbar.RuntimeMenu.Active = value; }
}
public IRunConfigurationModel ActiveRunConfiguration {
@@ -143,11 +142,11 @@ namespace WindowsPlatform.MainToolbar
}
public bool ButtonBarSensitivity {
- set { toolbar.ButtonBarPanel.IsEnabled = value; }
+ set { toolbar.ButtonBarPanel.IsEnabled = value; }
}
public IEnumerable<IConfigurationModel> ConfigurationModel {
- get { return toolbar.ConfigurationMenu.Model; }
+ get { return toolbar.ConfigurationMenu.Model; }
set { toolbar.ConfigurationMenu.Model = value; }
}
@@ -162,29 +161,26 @@ namespace WindowsPlatform.MainToolbar
}
bool configurationPlatformSensitivity;
- public bool ConfigurationPlatformSensitivity {
+
+ public bool ConfigurationPlatformSensitivity {
get { return configurationPlatformSensitivity; }
set {
configurationPlatformSensitivity = value;
- toolbar.ConfigurationMenu.IsEnabled = value && ConfigurationModel.Count() > 1;
- toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count() > 1;
- }
+ toolbar.ConfigurationMenu.IsEnabled = value && ConfigurationModel.Count () > 1;
+ toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count () > 1;
+ }
}
-
+
public bool PlatformSensitivity {
- set {
- toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count() > 1;
- }
+ set { toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count () > 1; }
}
public Gtk.Widget PopupAnchor {
- get {
- return this;
- }
+ get { return this; }
}
public OperationIcon RunButtonIcon {
- set { toolbar.RunButton.Icon = value; }
+ set { toolbar.RunButton.Icon = value; }
}
public bool RunButtonSensitivity {
@@ -195,14 +191,15 @@ namespace WindowsPlatform.MainToolbar
public bool RunConfigurationVisible {
get { return toolbar.RunConfigurationMenu.IsVisible; }
set {
- System.Windows.Visibility visible = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
+ System.Windows.Visibility visible =
+ value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
toolbar.RunConfigurationMenu.Visibility = visible;
toolbar.RunConfigurationSeparator.Visibility = visible;
}
}
public string SearchCategory {
- set {
+ set {
toolbar.SearchBar.SearchText = value;
FocusSearchBar ();
toolbar.SearchBar.SearchBar.Select (value.Length, 0);
@@ -210,18 +207,16 @@ namespace WindowsPlatform.MainToolbar
}
public IEnumerable<ISearchMenuModel> SearchMenuItems {
- set {
- toolbar.SearchBar.SearchMenuItems = value;
- }
+ set { toolbar.SearchBar.SearchMenuItems = value; }
}
public string SearchPlaceholderMessage {
get { return toolbar.SearchBar.PlaceholderText; }
- set { toolbar.SearchBar.PlaceholderText = value; }
+ set { toolbar.SearchBar.PlaceholderText = value; }
}
public bool SearchSensivitity {
- set { toolbar.SearchBar.IsEnabled = value; }
+ set { toolbar.SearchBar.IsEnabled = value; }
}
public string SearchText {
@@ -236,7 +231,7 @@ namespace WindowsPlatform.MainToolbar
}
public StatusBar StatusBar {
- get { return toolbar.StatusBar; }
+ get { return toolbar.StatusBar; }
}
public event EventHandler ConfigurationChanged;
@@ -245,6 +240,7 @@ namespace WindowsPlatform.MainToolbar
public event EventHandler SearchEntryActivated;
public event EventHandler SearchEntryChanged;
public event EventHandler<KeyEventArgs> SearchEntryKeyPressed;
+ public event EventHandler<SearchEntryCommandArgs> PerformCommand;
public event EventHandler SearchEntryLostFocus;
public event EventHandler SearchEntryResized;
@@ -258,27 +254,24 @@ namespace WindowsPlatform.MainToolbar
foreach (var item in toolbar.ButtonBarPanel.Children.OfType<IDisposable> ())
item.Dispose ();
- toolbar.ButtonBarPanel.Children.Clear ();
-
- // Remove empty groups so we know when to put a separator
+ toolbar.ButtonBarPanel.Children.Clear ();
+
+ // Remove empty groups so we know when to put a separator
var groupList = groups.ToList ();
groupList.RemoveAll ((g) => g.Buttons.Count == 0);
int idx = 0;
int count = groupList.Count;
- var sepStyle = toolbar.FindResource (System.Windows.Controls.ToolBar.SeparatorStyleKey) as System.Windows.Style;
+ var sepStyle =
+ toolbar.FindResource (System.Windows.Controls.ToolBar.SeparatorStyleKey) as System.Windows.Style;
foreach (var buttonGroup in groupList) {
bool needsSeparator = (idx < count - 1);
foreach (var button in buttonGroup.Buttons) {
if (needsSeparator)
toolbar.ButtonBarPanel.Children.Add (new DottedSeparator {
- Margin = new System.Windows.Thickness {
- Left = 3,
- Right = 3,
- },
- UseLayoutRounding = true,
+ Margin = new System.Windows.Thickness {Left = 3, Right = 3,}, UseLayoutRounding = true,
});
toolbar.ButtonBarPanel.Children.Add (new ButtonBarButton (button));
@@ -295,10 +288,10 @@ namespace WindowsPlatform.MainToolbar
PropertyChanged (this, new System.ComponentModel.PropertyChangedEventArgs (propName));
}
- public void Focus (Gtk.DirectionType direction, Action<Gtk.DirectionType> exitAction)
- {
+ public void Focus (Gtk.DirectionType direction, Action<Gtk.DirectionType> exitAction)
+ {
FocusSearchBar ();
- exitAction (direction);
+ exitAction (direction);
}
public void ShowAccessibilityAnnouncement (string message)
@@ -312,7 +305,7 @@ namespace WindowsPlatform.MainToolbar
public class NotNullConverter : IValueConverter
{
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null;
}
@@ -321,5 +314,5 @@ namespace WindowsPlatform.MainToolbar
{
throw new NotImplementedException ();
}
- }
+ }
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetFrameworkMoniker.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetFrameworkMoniker.cs
index 7b49c3be82..e6d4a4b32d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetFrameworkMoniker.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetFrameworkMoniker.cs
@@ -333,6 +333,10 @@ namespace MonoDevelop.Core.Assemblies
get { return new TargetFrameworkMoniker ("4.7.1"); }
}
+ public static TargetFrameworkMoniker NET_4_7_2 {
+ get { return new TargetFrameworkMoniker ("4.7.2"); }
+ }
+
public static TargetFrameworkMoniker PORTABLE_4_0 {
get { return new TargetFrameworkMoniker (ID_PORTABLE, "4.0", "Profile1"); }
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs
index c0e4238cb8..d48d076f05 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs
@@ -143,6 +143,14 @@ namespace MonoDevelop.Core
}
}
+ [Pure]
+ internal bool HasFileName (string name)
+ {
+ return fileName.Length > name.Length
+ && fileName.EndsWith (name, PathComparison)
+ && fileName [fileName.Length - name.Length - 1] == Path.DirectorySeparatorChar;
+ }
+
public string Extension {
get {
return Path.GetExtension (fileName);
@@ -153,8 +161,27 @@ namespace MonoDevelop.Core
public bool HasExtension (string extension)
{
return fileName.Length > extension.Length
- && fileName.EndsWith (extension, PathComparison)
- && fileName[fileName.Length - extension.Length - 1] != Path.PathSeparator;
+ && (extension == string.Empty
+ ? HasNoExtension (fileName)
+ : fileName.EndsWith (extension, PathComparison) && fileName [fileName.Length - extension.Length] == '.');
+
+ static bool HasNoExtension (string path)
+ {
+ // Look for the last dot that's after the last path separator
+ for (int i = path.Length - 1; i >= 0; --i) {
+ var ch = path [i];
+ if (ch == '.') {
+ // Check if it's the dot is the last character
+ // if it is, then we have no extension
+ return i == path.Length - 1;
+ }
+
+ if (ch == Path.DirectorySeparatorChar)
+ return true;
+ }
+
+ return true;
+ }
}
public string FileNameWithoutExtension {
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs
index 18d9d0e167..13d5beeaae 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/ProjectTypeNode.cs
@@ -45,7 +45,7 @@ namespace MonoDevelop.Projects.Extensions
Project project = null;
if (!string.IsNullOrEmpty (fileName)) {
- p = await MSBuildProject.LoadAsync (fileName);
+ p = await MSBuildProject.LoadAsync (fileName).ConfigureAwait (false);
if (ctx != null && ctx.Solution != null) {
p.EngineManager = ctx.Solution.MSBuildEngineManager;
p.SolutionDirectory = ctx.Solution.ItemDirectory;
@@ -53,7 +53,7 @@ namespace MonoDevelop.Projects.Extensions
var migrators = MSBuildProjectService.GetMigrableFlavors (p.ProjectTypeGuids);
if (migrators.Count > 0)
- await MSBuildProjectService.MigrateFlavors (monitor, fileName, Guid, p, migrators);
+ await MSBuildProjectService.MigrateFlavors (monitor, fileName, Guid, p, migrators).ConfigureAwait (false);
var unsupporedFlavor = p.ProjectTypeGuids.FirstOrDefault (fid => !MSBuildProjectService.IsKnownFlavorGuid (fid) && !MSBuildProjectService.IsKnownTypeGuid (fid));
if (unsupporedFlavor != null) {
@@ -72,7 +72,7 @@ namespace MonoDevelop.Projects.Extensions
}
if (project == null)
- project = await base.CreateSolutionItem (monitor, ctx, fileName) as Project;
+ project = await base.CreateSolutionItem (monitor, ctx, fileName).ConfigureAwait(false) as Project;
if (project == null)
throw new InvalidOperationException ("Project node type is not a subclass of MonoDevelop.Projects.Project");
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs
index 46fa87c880..3cd16adde0 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Extensions/SolutionItemTypeNode.cs
@@ -99,7 +99,7 @@ namespace MonoDevelop.Projects.Extensions
if (typeof(SolutionItemFactory).IsAssignableFrom (ItemType)) {
if (factory == null)
factory = (SolutionItemFactory)Activator.CreateInstance (ItemType);
- item = await factory.CreateItem (fileName, Guid);
+ item = await factory.CreateItem (fileName, Guid).ConfigureAwait (false);
} else
item = MSBuildProjectService.CreateUninitializedInstance (ItemType);
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs
index e821b48bf6..a22fc426c5 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs
@@ -850,7 +850,7 @@ namespace MonoDevelop.Projects.MSBuild
static bool IsWildcardInclude (string include)
{
- return include.IndexOf ('*') != -1;
+ return include.IndexOfAny (wildcards) != -1;
}
IEnumerable<MSBuildItemEvaluated> ExpandWildcardFilePath (ProjectInfo pinfo, MSBuildEvaluationContext context, MSBuildItem sourceItem, string path, Regex directoryExcludeRegex)
@@ -1018,7 +1018,7 @@ namespace MonoDevelop.Projects.MSBuild
return it;
}
- static char[] wildcards = { '*', '%' };
+ static char[] wildcards = { '*', '?' };
void Evaluate (ProjectInfo project, MSBuildEvaluationContext context, MSBuildProperty prop)
{
@@ -1174,7 +1174,7 @@ namespace MonoDevelop.Projects.MSBuild
var fileName = Path.GetFileName (path);
- if (fileName.IndexOfAny (new [] { '*', '?' }) == -1) {
+ if (fileName.IndexOfAny (wildcards) == -1) {
// Not a wildcard. Keep searching if the file doesn't exist.
var result = File.Exists (path) ? new [] { path } : null;
keepSearching = result == null;
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs
index 94ea9abfa3..e7626bece3 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs
@@ -614,10 +614,6 @@ namespace MonoDevelop.Projects.MSBuild
if (memberName.Length == 0)
return false;
- var member = ResolveMember (type, memberName.ToString (), instance == null);
- if (member == null || member.Length == 0)
- return false;
-
if (j < str.Length && str[j] == '(') {
// It is a method invocation
object [] parameterValues;
@@ -625,6 +621,10 @@ namespace MonoDevelop.Projects.MSBuild
if (!EvaluateParameters (str, ref j, out parameterValues))
return false;
+ var member = ResolveMember (type, memberName.ToString (), instance == null, MemberTypes.Method);
+ if (member == null || member.Length == 0)
+ return false;
+
if (!EvaluateMethod (str, member, instance, parameterValues, out val))
return false;
@@ -634,6 +634,10 @@ namespace MonoDevelop.Projects.MSBuild
} else {
// It has to be a property or field
try {
+ var member = ResolveMember (type, memberName.ToString (), instance == null, MemberTypes.Property | MemberTypes.Field);
+ if (member == null || member.Length == 0)
+ return false;
+
if (member[0] is PropertyInfo)
val = ((PropertyInfo)member[0]).GetValue (instance);
else if (member[0] is FieldInfo)
@@ -683,7 +687,7 @@ namespace MonoDevelop.Projects.MSBuild
internal bool EvaluateMember (ReadOnlySpan<char> str, Type type, string memberName, object instance, object [] parameterValues, out object val)
{
val = null;
- var member = ResolveMember (type, memberName, instance == null);
+ var member = ResolveMember (type, memberName, instance == null, MemberTypes.Method);
if (member == null || member.Length == 0)
return false;
return EvaluateMethod (str, member, instance, parameterValues, out val);
@@ -694,22 +698,17 @@ namespace MonoDevelop.Projects.MSBuild
val = null;
// Find a method with a matching number of parameters
- var method = FindBestOverload (member.OfType<MethodBase> (), parameterValues);
+ var (method, methodParams) = FindBestOverload (member, parameterValues, out var paramsArgType);
if (method == null)
return false;
try {
// Convert the given parameters to the types specified in the method signature
- var methodParams = method.GetParameters ();
-
var convertedArgs = (methodParams.Length == parameterValues.Length) ? parameterValues : new object [methodParams.Length];
int numArgs = methodParams.Length;
- Type paramsArgType = null;
- if (methodParams.Length > 0 && methodParams [methodParams.Length - 1].ParameterType.IsArray && methodParams [methodParams.Length - 1].IsDefined (typeof (ParamArrayAttribute))) {
- paramsArgType = methodParams [methodParams.Length - 1].ParameterType.GetElementType ();
+ if (paramsArgType != null)
numArgs--;
- }
if (method.DeclaringType == typeof (IntrinsicFunctions) && method.Name == nameof (IntrinsicFunctions.GetPathOfFileAbove) && parameterValues.Length == methodParams.Length - 1) {
string startingDirectory = String.IsNullOrWhiteSpace (FullFileName) ? String.Empty : Path.GetDirectoryName (FullFileName);
@@ -792,58 +791,158 @@ namespace MonoDevelop.Projects.MSBuild
return false;
}
- MethodBase FindBestOverload (IEnumerable<MethodBase> methods, object [] args)
+ (MethodBase method, ParameterInfo[] parameters) FindBestOverload (IEnumerable<MemberInfo> members, object [] args, out Type paramsArgType)
{
- MethodBase methodWithParams = null;
+ (MethodBase, ParameterInfo[]) methodWithParams = default;
+ (MethodBase, ParameterInfo[]) validMatch = default;
- foreach (var m in methods) {
- var argInfo = m.GetParameters ();
+ paramsArgType = null;
- // Exclude methods which take a complex object as argument
- if (argInfo.Any (a => a.ParameterType != typeof(object) && Type.GetTypeCode (a.ParameterType) == TypeCode.Object && !IsParamsArg(a)))
+ foreach (var member in members) {
+ if (!(member is MethodBase m))
continue;
- if (args.Length >= argInfo.Length - 1 && argInfo.Length > 0 && IsParamsArg (argInfo [argInfo.Length - 1])) {
- methodWithParams = m;
- continue;
- }
- if (args.Length != argInfo.Length) {
- if (args.Length == argInfo.Length - 1 && m.DeclaringType != typeof (IntrinsicFunctions) || m.Name != nameof(IntrinsicFunctions.GetPathOfFileAbove)) {
+ var argInfo = m.GetParameters ();
+
+ if (args.Length == argInfo.Length - 1) {
+ if (m.DeclaringType == typeof (IntrinsicFunctions) && m.Name == nameof (IntrinsicFunctions.GetPathOfFileAbove)) {
+ validMatch = (m, argInfo);
continue;
}
}
- bool isValid = true;
- for (int n = 0; n < args.Length; n++) {
- if (!CanConvertArg (m, n, args [n], argInfo [n].ParameterType)) {
- isValid = false;
- break;
- }
+ // Unable to match in this case.
+ if (args.Length < argInfo.Length - 1)
+ continue;
+
+ var kind = MatchArgs (args, argInfo);
+ if (kind == MatchKind.Exact)
+ return (m, argInfo);
+
+ if (kind == MatchKind.CanConvert)
+ validMatch = (m, argInfo);
+ else if (kind == MatchKind.Params) {
+ methodWithParams = (m, argInfo);
+ paramsArgType = argInfo [argInfo.Length - 1].ParameterType.GetElementType ();
}
- if (isValid)
- return m;
}
- return methodWithParams;
+
+ return validMatch != default ? validMatch : methodWithParams;
}
- bool IsParamsArg (ParameterInfo pi)
+ enum MatchKind
+ {
+ None,
+ Params,
+ CanConvert,
+ Exact,
+ }
+
+ static MatchKind MatchArgs (object[] args, ParameterInfo[] parameters)
+ {
+ bool isParams = parameters.Length > 0 && IsParamsArg (parameters [parameters.Length - 1]);
+
+ int last = parameters.Length;
+ if (isParams)
+ last--;
+ else if (args.Length != parameters.Length)
+ return MatchKind.None;
+
+ var kind = MatchKind.Exact;
+ for (int n = 0; n < last; n++) {
+ var parameterType = parameters [n].ParameterType;
+
+ var other = Match (parameterType, args [n]);
+ if (other == MatchKind.None)
+ return MatchKind.None;
+
+ if (other == MatchKind.CanConvert)
+ kind = MatchKind.CanConvert;
+ }
+
+ if (!isParams)
+ return kind;
+
+ // Check implicit argument
+ if (args.Length == last)
+ return MatchKind.Params;
+
+ var elementType = parameters[last].ParameterType.GetElementType ();
+ if (IsComplexType (elementType))
+ return MatchKind.None;
+
+ int argsRemaining = args.Length - last;
+ if (argsRemaining == 1 && elementType == typeof(char)) {
+ if (Match (parameters [last].ParameterType, args [last], checkComplexType: false) != MatchKind.None)
+ return MatchKind.Params;
+ }
+
+ for (int n_arg = last; n_arg < args.Length; ++n_arg) {
+ if (Match (elementType, args [n_arg]) == MatchKind.None)
+ return MatchKind.None;
+ }
+
+ return MatchKind.Params;
+
+ static bool IsComplexType (Type type)
+ {
+ return Type.GetTypeCode (type) == TypeCode.Object && type != typeof (object);
+ }
+
+ static MatchKind Match (Type parameterType, object argument, bool checkComplexType = true)
+ {
+ if (parameterType.IsInstanceOfType (argument))
+ return MatchKind.Exact;
+
+ if (checkComplexType && IsComplexType (parameterType))
+ return MatchKind.None;
+
+ if (CanConvertArg (argument, parameterType))
+ return MatchKind.CanConvert;
+
+
+ return MatchKind.None;
+ }
+ }
+
+ static bool IsParamsArg (ParameterInfo pi)
{
return pi.ParameterType.IsArray && pi.IsDefined (typeof (ParamArrayAttribute));
}
- bool CanConvertArg (MethodBase method, int argNum, object value, Type parameterType)
+ static bool CanConvertArg (object value, Type parameterType)
{
var sval = value as string;
if (sval == "null" || value == null)
- return !parameterType.IsValueType || typeof(Nullable).IsInstanceOfType (parameterType);
+ return !parameterType.IsValueType || Nullable.GetUnderlyingType (parameterType) != null;
if (sval != null && parameterType == typeof (char []))
return true;
- if (parameterType == typeof (char) && sval != null && sval.Length != 1)
+ if (sval != null && sval.Length != 1 && parameterType == typeof (char)) {
return false;
+ }
- return true;
+ if (sval != null && parameterType.IsEnum) {
+ // Enum.Parse expects comma separated values.
+ var enumValue = sval.Replace ('|', ',')
+ .Replace (parameterType.FullName + ".", "")
+ .Replace (parameterType.Name + ".", "");
+
+ try {
+ _ = Enum.Parse (parameterType, enumValue, ignoreCase: true);
+ return true;
+ } catch {
+ return false;
+ }
+ }
+
+ try {
+ _ = Convert.ChangeType (value, parameterType, CultureInfo.InvariantCulture);
+ return true;
+ } catch {
+ return false;
+ }
}
object ConvertArg (MethodBase method, int argNum, object value, Type parameterType)
@@ -856,11 +955,11 @@ namespace MonoDevelop.Projects.MSBuild
return sval.ToCharArray ();
if (sval != null && parameterType.IsEnum) {
- var enumValue = sval;
- if (enumValue.StartsWith (parameterType.Name, StringComparison.Ordinal))
- enumValue = enumValue.Substring (parameterType.Name.Length + 1);
- if (enumValue.StartsWith (parameterType.FullName, StringComparison.Ordinal))
- enumValue = enumValue.Substring (parameterType.FullName.Length + 1);
+ // Enum.Parse expects comma separated values.
+ var enumValue = sval.Replace ('|', ',')
+ .Replace (parameterType.FullName + ".", "")
+ .Replace (parameterType.Name + ".", "");
+
return Enum.Parse(parameterType, enumValue, ignoreCase: true);
}
@@ -907,15 +1006,15 @@ namespace MonoDevelop.Projects.MSBuild
{
if (typeName == "MSBuild")
return typeof (Microsoft.Build.Evaluation.IntrinsicFunctions);
- else {
- var t = supportedTypeMembers.FirstOrDefault (st => st.Item1.FullName == typeName);
- if (t == null)
- return null;
- return t.Item1;
+
+ foreach (var kvp in supportedTypeMembers) {
+ if (kvp.Key.FullName == typeName)
+ return kvp.Key;
}
+ return null;
}
- MemberInfo[] ResolveMember (Type type, string memberName, bool isStatic)
+ MemberInfo[] ResolveMember (Type type, string memberName, bool isStatic, MemberTypes memberTypes)
{
if (type == typeof (string) && memberName == "new")
memberName = "Copy";
@@ -923,52 +1022,68 @@ namespace MonoDevelop.Projects.MSBuild
type = typeof (Array);
var flags = isStatic ? BindingFlags.Static : BindingFlags.Instance;
if (type != typeof (Microsoft.Build.Evaluation.IntrinsicFunctions)) {
- var t = supportedTypeMembers.FirstOrDefault (st => st.Item1 == type);
- if (t == null)
+ if (!supportedTypeMembers.TryGetValue (type, out var list))
return null;
- if (t.Item2 != null && !t.Item2.Contains (memberName))
+
+ if (list != null && !list.Contains (memberName))
return null;
} else
flags |= BindingFlags.NonPublic;
-
- return type.GetMember (memberName, flags | BindingFlags.Public | BindingFlags.IgnoreCase);
+
+ return type.GetMember (memberName, memberTypes, flags | BindingFlags.Public | BindingFlags.IgnoreCase);
}
- static Tuple<Type, string []> [] supportedTypeMembers = {
- Tuple.Create (typeof(System.Array), (string[]) null),
- Tuple.Create (typeof(System.Byte), (string[]) null),
- Tuple.Create (typeof(System.Char), (string[]) null),
- Tuple.Create (typeof(System.Convert), (string[]) null),
- Tuple.Create (typeof(System.DateTime), (string[]) null),
- Tuple.Create (typeof(System.Decimal), (string[]) null),
- Tuple.Create (typeof(System.Double), (string[]) null),
- Tuple.Create (typeof(System.Enum), (string[]) null),
- Tuple.Create (typeof(System.Guid), (string[]) null),
- Tuple.Create (typeof(System.Int16), (string[]) null),
- Tuple.Create (typeof(System.Int32), (string[]) null),
- Tuple.Create (typeof(System.Int64), (string[]) null),
- Tuple.Create (typeof(System.IO.Path), (string[]) null),
- Tuple.Create (typeof(System.Math), (string[]) null),
- Tuple.Create (typeof(System.UInt16), (string[]) null),
- Tuple.Create (typeof(System.UInt32), (string[]) null),
- Tuple.Create (typeof(System.UInt64), (string[]) null),
- Tuple.Create (typeof(System.SByte), (string[]) null),
- Tuple.Create (typeof(System.Single), (string[]) null),
- Tuple.Create (typeof(System.String), (string[]) null),
- Tuple.Create (typeof(System.StringComparer), (string[]) null),
- Tuple.Create (typeof(System.TimeSpan), (string[]) null),
- Tuple.Create (typeof(System.Text.RegularExpressions.Regex), (string[]) null),
- Tuple.Create (typeof(Microsoft.Build.Utilities.ToolLocationHelper), (string[]) null),
- Tuple.Create (typeof(System.Globalization.CultureInfo), (string[]) null),
- Tuple.Create (typeof(System.Environment), new string [] {
- "CommandLine", "ExpandEnvironmentVariables", "GetEnvironmentVariable", "GetEnvironmentVariables", "GetFolderPath", "GetLogicalDrives"
- }),
- Tuple.Create (typeof(System.IO.Directory), new string [] {
- "GetDirectories", "GetFiles", "GetLastAccessTime", "GetLastWriteTime", "GetParent"
- }),
- Tuple.Create (typeof(System.IO.File), new string [] {
- "Exists", "GetCreationTime", "GetAttributes", "GetLastAccessTime", "GetLastWriteTime", "ReadAllText"
- }),
+ sealed class TypeEqualityComparer : IEqualityComparer<Type>
+ {
+ public bool Equals (Type x, Type y) => x == y;
+
+ public int GetHashCode (Type obj) => obj?.GetHashCode () ?? 0;
+ }
+
+ static readonly Dictionary<Type, string []> supportedTypeMembers = new Dictionary<Type, string []> (new TypeEqualityComparer()) {
+ { typeof(System.Array), null },
+ { typeof(System.Byte), null },
+ { typeof(System.Char), null },
+ { typeof(System.Convert), null },
+ { typeof(System.DateTime), null },
+ { typeof(System.Decimal), null },
+ { typeof(System.Double), null },
+ { typeof(System.Enum), null },
+ { typeof(System.Guid), null },
+ { typeof(System.Int16), null },
+ { typeof(System.Int32), null },
+ { typeof(System.Int64), null },
+ { typeof(System.IO.Path), null },
+ { typeof(System.Math), null },
+ { typeof(System.UInt16), null },
+ { typeof(System.UInt32), null },
+ { typeof(System.UInt64), null },
+ { typeof(System.SByte), null },
+ { typeof(System.Single), null },
+ { typeof(System.String), null },
+ { typeof(System.StringComparer), null },
+ { typeof(System.TimeSpan), null },
+ { typeof(System.Text.RegularExpressions.Regex), null },
+ { typeof(Microsoft.Build.Utilities.ToolLocationHelper), null },
+ { typeof(System.Globalization.CultureInfo), null },
+ {
+ typeof (System.Environment),
+ new string [] {
+ "CommandLine", "ExpandEnvironmentVariables", "GetEnvironmentVariable", "GetEnvironmentVariables", "GetFolderPath", "GetLogicalDrives"
+ }
+ },
+ {
+ typeof (System.IO.Directory),
+ new string [] {
+ "GetDirectories", "GetFiles", "GetLastAccessTime", "GetLastWriteTime", "GetParent"
+ }
+ },
+ {
+ typeof (System.IO.File),
+ new string [] {
+ "Exists", "GetCreationTime", "GetAttributes", "GetLastAccessTime", "GetLastWriteTime", "ReadAllText"
+ }
+ },
};
int FindNextTag (string str, int i)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildFileFormat.cs
index e7c8945f90..fe0e089335 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildFileFormat.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildFileFormat.cs
@@ -168,7 +168,7 @@ namespace MonoDevelop.Projects.MSBuild
internal async Task WriteFile (FilePath file, object obj, ProgressMonitor monitor)
{
if (slnFileFormat.CanWriteFile (obj, this)) {
- await slnFileFormat.WriteFile (file, obj, true, monitor);
+ await slnFileFormat.WriteFile (file, obj, true, monitor).ConfigureAwait (false);
} else {
throw new NotSupportedException ();
}
@@ -177,7 +177,7 @@ namespace MonoDevelop.Projects.MSBuild
internal async Task<object> ReadFile (FilePath file, Type expectedType, MonoDevelop.Core.ProgressMonitor monitor)
{
if (slnFileFormat.CanReadFile (file, this))
- return await slnFileFormat.ReadFile (file, monitor);
+ return await slnFileFormat.ReadFile (file, monitor).ConfigureAwait(false);
else
throw new NotSupportedException ();
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs
index a23254c86c..4b21073b76 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectInstance.cs
@@ -115,7 +115,7 @@ namespace MonoDevelop.Projects.MSBuild
} catch (Exception ex) {
// If the project can't be evaluated don't crash
LoggingService.LogError ("MSBuild project could not be evaluated", ex);
- throw new ProjectEvaluationException (msproject, ex.Message);
+ throw new ProjectEvaluationException (msproject, ex.Message, ex);
} finally {
if (oldProjectInstance != null)
engine.DisposeProjectInstance (oldProjectInstance);
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs
index 703bbcf97d..398aa31187 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildProjectService.cs
@@ -784,26 +784,24 @@ namespace MonoDevelop.Projects.MSBuild
return Task.FromResult<SolutionItem> (new GenericProject ());
// Unknown project types are already displayed in the solution view, we don't need to tell the user with a modal dialog as well
- return Task<SolutionItem>.Factory.StartNew (delegate {
- var t = ReadGenericProjectType (file);
- if (t == null)
- throw new UnknownSolutionItemTypeException (GettextCatalog.GetString ("Unknown project type"));
+ var t = ReadGenericProjectType (file);
+ if (t == null)
+ return Task.FromException<SolutionItem> (new UnknownSolutionItemTypeException (GettextCatalog.GetString ("Unknown project type")));
- var dt = Services.ProjectService.DataContext.GetConfigurationDataType (t);
- if (dt != null) {
- if (!typeof (Project).IsAssignableFrom (dt.ValueType))
- throw new UnknownSolutionItemTypeException (GettextCatalog.GetString ("Unknown project type: {0}", t));
+ var dt = Services.ProjectService.DataContext.GetConfigurationDataType (t);
+ if (dt != null) {
+ if (!typeof (Project).IsAssignableFrom (dt.ValueType))
+ return Task.FromException<SolutionItem> (new UnknownSolutionItemTypeException (GettextCatalog.GetString ("Unknown project type: {0}", t)));
- return (SolutionItem)Activator.CreateInstance (dt.ValueType);
- }
+ return Task.FromResult ((SolutionItem)Activator.CreateInstance (dt.ValueType));
+ }
- Type type;
- lock (genericProjectTypes) {
- if (!genericProjectTypes.TryGetValue (t, out type))
- throw new UnknownSolutionItemTypeException (GettextCatalog.GetString ("Unknown project type: {0}", t));
- }
- return (SolutionItem)Activator.CreateInstance (type);
- });
+ Type type;
+ lock (genericProjectTypes) {
+ if (!genericProjectTypes.TryGetValue (t, out type))
+ return Task.FromException<SolutionItem> (new UnknownSolutionItemTypeException (GettextCatalog.GetString ("Unknown project type: {0}", t)));
+ }
+ return Task.FromResult ((SolutionItem)Activator.CreateInstance (type));
}
static string ReadGenericProjectType (string file)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/ProjectEvaluationException.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/ProjectEvaluationException.cs
index 000fcea525..88775b3e5d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/ProjectEvaluationException.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/ProjectEvaluationException.cs
@@ -29,12 +29,16 @@ namespace MonoDevelop.Projects.MSBuild
{
public class ProjectEvaluationException: ApplicationException
{
- public ProjectEvaluationException (MSBuildProject project, string message): base (message)
+ internal ProjectEvaluationException (MSBuildProject project, string message, Exception innerException) : base (message, innerException)
{
Project = project;
}
- public MSBuildProject Project { get; private set; }
+ public ProjectEvaluationException (MSBuildProject project, string message): this (project, message, null)
+ {
+ }
+
+ public MSBuildProject Project { get; }
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/SlnFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/SlnFileFormat.cs
index 742edb3d99..581fef41d4 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/SlnFileFormat.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/SlnFileFormat.cs
@@ -64,22 +64,20 @@ namespace MonoDevelop.Projects.MSBuild
return obj is Solution;
}
- public Task WriteFile (string file, object obj, bool saveProjects, ProgressMonitor monitor)
+ public async Task WriteFile (string file, object obj, bool saveProjects, ProgressMonitor monitor)
{
- return Task.Run (async delegate {
- Solution sol = (Solution)obj;
+ Solution sol = (Solution)obj;
- try {
- monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1);
- await WriteFileInternal (file, file, sol, saveProjects, monitor).ConfigureAwait (false);
- } catch (Exception ex) {
- monitor.ReportError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
- LoggingService.LogError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
- throw;
- } finally {
- monitor.EndTask ();
- }
- });
+ try {
+ monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1);
+ await WriteFileInternal (file, file, sol, saveProjects, monitor).ConfigureAwait (false);
+ } catch (Exception ex) {
+ monitor.ReportError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
+ LoggingService.LogError (GettextCatalog.GetString ("Could not save solution: {0}", file), ex);
+ throw;
+ } finally {
+ monitor.EndTask ();
+ }
}
async Task WriteFileInternal (string file, string sourceFile, Solution solution, bool saveProjects, ProgressMonitor monitor)
@@ -91,7 +89,7 @@ namespace MonoDevelop.Projects.MSBuild
try {
monitor.BeginStep ();
item.SavingSolution = true;
- await item.SaveAsync (monitor);
+ await item.SaveAsync (monitor).ConfigureAwait (false);
} finally {
item.SavingSolution = false;
}
@@ -377,21 +375,19 @@ namespace MonoDevelop.Projects.MSBuild
try {
monitor.BeginTask (string.Format (GettextCatalog.GetString ("Loading solution: {0}"), fileName), 1);
monitor.BeginStep ();
- await sol.OnBeginLoad ();
+ await sol.OnBeginLoad ().ConfigureAwait (false);
var projectLoadMonitor = monitor as ProjectLoadProgressMonitor;
if (projectLoadMonitor != null)
projectLoadMonitor.CurrentSolution = sol;
- await Task.Run (() => {
- sol.ReadSolution (monitor);
- });
+ sol.ReadSolution (monitor);
} catch (Exception ex) {
monitor.ReportError (GettextCatalog.GetString ("Could not load solution: {0}", fileName), ex);
- await sol.OnEndLoad ();
+ await sol.OnEndLoad ().ConfigureAwait (false);
sol.NotifyItemReady ();
monitor.EndTask ();
throw;
}
- await sol.OnEndLoad ();
+ await sol.OnEndLoad ().ConfigureAwait (false);
sol.NotifyItemReady ();
monitor.EndTask ();
return sol;
@@ -533,7 +529,7 @@ namespace MonoDevelop.Projects.MSBuild
}
}
monitor.Step (1);
- });
+ }, TaskScheduler.Default);
loadTasks.Add (ft);
// Limit the number of concurrent tasks. Por solutions with many projects, spawning one thread per
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs
index ffaaef930f..4bb348eddc 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/CompiledAssemblyProject.cs
@@ -215,11 +215,9 @@ namespace MonoDevelop.Projects
public override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
{
- return Task<SolutionItem>.Factory.StartNew (delegate {
- CompiledAssemblyProject p = new CompiledAssemblyProject ();
- p.LoadFrom (fileName);
- return p;
- });
+ CompiledAssemblyProject p = new CompiledAssemblyProject ();
+ p.LoadFrom (fileName);
+ return Task.FromResult<SolutionItem> (p);
}
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MSBuildSerializationExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MSBuildSerializationExtension.cs
index f5b1f1922c..8172ed8212 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MSBuildSerializationExtension.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/MSBuildSerializationExtension.cs
@@ -41,26 +41,22 @@ namespace MonoDevelop.Projects
return false;
}
- public override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
+ public override async Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
{
- return Task.Run (() => {
- foreach (var f in MSBuildFileFormat.GetSupportedFormats ()) {
- if (f.CanReadFile (fileName, typeof(SolutionItem)))
- return MSBuildProjectService.LoadItem (monitor, fileName, f, typeGuid, itemGuid, ctx);
- }
- throw new NotSupportedException ();
- });
+ foreach (var f in MSBuildFileFormat.GetSupportedFormats ()) {
+ if (f.CanReadFile (fileName, typeof(SolutionItem)))
+ return await MSBuildProjectService.LoadItem (monitor, fileName, f, typeGuid, itemGuid, ctx).ConfigureAwait (false);
+ }
+ throw new NotSupportedException ();
}
- public override Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName)
+ public override async Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName)
{
- return Task.Run (async () => {
- foreach (var f in MSBuildFileFormat.GetSupportedFormats ()) {
- if (f.CanReadFile (fileName, typeof (WorkspaceItem)))
- return (WorkspaceItem)await f.ReadFile (fileName, typeof (WorkspaceItem), monitor).ConfigureAwait (false);
- }
- throw new NotSupportedException ();
- });
+ foreach (var f in MSBuildFileFormat.GetSupportedFormats ()) {
+ if (f.CanReadFile (fileName, typeof (WorkspaceItem)))
+ return (WorkspaceItem)await f.ReadFile (fileName, typeof (WorkspaceItem), monitor).ConfigureAwait (false);
+ }
+ throw new NotSupportedException ();
}
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
index 3df66730cc..a8a7c72dd0 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
@@ -415,9 +415,7 @@ namespace MonoDevelop.Projects
protected override Task OnLoad (ProgressMonitor monitor)
{
- return Task.Run (async delegate {
- await LoadAsync (monitor);
- });
+ return LoadAsync (monitor);
}
async Task LoadAsync (ProgressMonitor monitor)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs
index 7997a72146..4b57332e0d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs
@@ -54,7 +54,7 @@ namespace MonoDevelop.Projects
TargetFramework defaultTargetFramework;
string defaultPlatformTarget = "anycpu";
- static readonly TargetFrameworkMoniker DefaultTargetFrameworkId = TargetFrameworkMoniker.NET_4_7;
+ static readonly TargetFrameworkMoniker DefaultTargetFrameworkId = TargetFrameworkMoniker.NET_4_7_2;
public const string BuildTarget = "Build";
public const string CleanTarget = "Clean";
@@ -123,7 +123,7 @@ namespace MonoDevelop.Projects
var r = GetObjectReaderForFile (file, typeof(SolutionItem));
if (r == null)
throw new UnknownSolutionItemTypeException ();
- SolutionItem loadedItem = await r.LoadSolutionItem (monitor, ctx, file, format, typeGuid, itemGuid);
+ SolutionItem loadedItem = await Task.Run (() => r.LoadSolutionItem (monitor, ctx, file, format, typeGuid, itemGuid));
if (loadedItem != null) {
loadedItem.NeedsReload = false;
UpdateReadSolutionItemMetadata (metadata, loadedItem);
@@ -216,7 +216,7 @@ namespace MonoDevelop.Projects
var r = GetObjectReaderForFile (file, typeof(WorkspaceItem));
if (r == null)
throw new InvalidOperationException ("Invalid file format: " + file);
- WorkspaceItem item = await r.LoadWorkspaceItem (monitor, fullpath);
+ WorkspaceItem item = await Task.Run (() => r.LoadWorkspaceItem (monitor, fullpath));
if (item != null)
item.NeedsReload = false;
else
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectExtension.cs
index e7514fe8f1..195b692af1 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectExtension.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectExtension.cs
@@ -38,6 +38,8 @@ namespace MonoDevelop.Projects
[ExportProjectModelExtension]
public class SdkProjectExtension : DotNetProjectExtension
{
+ HashSet<(string Name, string Include)> evaluatedItems;
+
MSBuildSdkProject msbuildSdkProject = new MSBuildSdkProject ();
string[] cachedBuildActions;
@@ -53,8 +55,7 @@ namespace MonoDevelop.Projects
/// </summary>
internal static bool FileShouldBeHidden (FilePath file)
{
- return file.HasExtension (".userprefs") ||
- file.FileName == ".DS_Store";
+ return file.HasExtension (".userprefs") || file.HasFileName (".DS_Store");
}
public IEnumerable<string> TargetFrameworks {
@@ -109,6 +110,7 @@ namespace MonoDevelop.Projects
Project.UseFileWatcher = true;
cachedBuildActions = null;
+ evaluatedItems = null;
}
internal protected override void OnWriteProject (ProgressMonitor monitor, MSBuildProject msproject)
@@ -129,36 +131,15 @@ namespace MonoDevelop.Projects
{
var sourceFiles = await base.OnGetSourceFiles (monitor, configuration);
- return AddMissingProjectFiles (sourceFiles, configuration);
- }
-
- ImmutableArray<ProjectFile> AddMissingProjectFiles (ImmutableArray<ProjectFile> files, ConfigurationSelector configuration)
- {
- ImmutableArray<ProjectFile>.Builder missingFiles = null;
- foreach (ProjectFile existingFile in Project.Files.Where (file => file.BuildAction == BuildAction.Compile)) {
- if (!files.Any (file => file.FilePath == existingFile.FilePath)) {
- if (missingFiles == null)
- missingFiles = ImmutableArray.CreateBuilder<ProjectFile> ();
- missingFiles.Add (existingFile);
- }
- }
-
// Ensure generated assembly info file is available to type system. It is created in the obj
// directory and is excluded from the project with a wildcard exclude but the type system needs it to
// ensure the project's assembly information is correct to prevent diagnostic errors.
var generatedAssemblyInfoFile = GetGeneratedAssemblyInfoFile (configuration);
if (generatedAssemblyInfoFile != null) {
- if (missingFiles == null)
- missingFiles = ImmutableArray.CreateBuilder<ProjectFile> ();
- missingFiles.Add (generatedAssemblyInfoFile);
+ return sourceFiles.Add (generatedAssemblyInfoFile);
}
- if (missingFiles == null)
- return files;
-
- missingFiles.Capacity = missingFiles.Count + files.Length;
- missingFiles.AddRange (files);
- return missingFiles.MoveToImmutable ();
+ return sourceFiles;
}
ProjectFile GetGeneratedAssemblyInfoFile (ConfigurationSelector configuration)
@@ -185,14 +166,23 @@ namespace MonoDevelop.Projects
// project file is being saved.
}
- bool IsFSharpSdkProject ()
+ bool? isFSharpSdkProject;
+ bool IsLegacyFSharpSdkProject ()
{
- var sdks = Project.MSBuildProject.GetReferencedSDKs ();
- for (var i = 0; i < sdks.Length; i++) {
- if (sdks [i].Contains ("FSharp"))
- return true;
+ if (isFSharpSdkProject is null) {
+ isFSharpSdkProject = ContainsFSharpSdk (Project.MSBuildProject.GetReferencedSDKs ());
+ }
+
+ return isFSharpSdkProject.Value;
+
+ static bool ContainsFSharpSdk (string[] sdks)
+ {
+ for (var i = 0; i < sdks.Length; i++) {
+ if (sdks [i].Contains ("FSharp"))
+ return true;
+ }
+ return false;
}
- return false;
}
internal protected override bool OnGetSupportsImportedItem (IMSBuildItemEvaluated buildItem)
@@ -200,7 +190,7 @@ namespace MonoDevelop.Projects
if (!IsBuildActionSupported (buildItem.Name))
return false;
- if (IsFSharpSdkProject ()) {
+ if (IsLegacyFSharpSdkProject ()) {
// Ignore imported F# files. F# files are defined in the main project.
// This prevents duplicate F# files when a new project is first created.
if (buildItem.Include.EndsWith (".fs", StringComparison.OrdinalIgnoreCase))
@@ -210,11 +200,15 @@ namespace MonoDevelop.Projects
if (IsFromSharedProject (buildItem))
return false;
- // HACK: Remove any imported items that are not in the EvaluatedItems
- // This may happen if a condition excludes the item. All items passed to the
- // OnGetSupportsImportedItem are from the EvaluatedItemsIgnoringCondition
- return Project.MSBuildProject.EvaluatedItems
- .Any (item => item.IsImported && item.Name == buildItem.Name && item.Include == buildItem.Include);
+ evaluatedItems ??= CreateEvaluatedItemsCache (Project.MSBuildProject);
+ return evaluatedItems.Contains ((buildItem.Name, buildItem.Include));
+
+ static HashSet<(string, string)> CreateEvaluatedItemsCache (MSBuildProject project)
+ => new HashSet<(string Name, string Include)> (
+ project.EvaluatedItems
+ .Where (x => x.IsImported)
+ .Select (x => (x.Name, x.Include))
+ );
}
/// <summary>
@@ -262,6 +256,8 @@ namespace MonoDevelop.Projects
internal protected override async Task OnReevaluateProject (ProgressMonitor monitor)
{
await base.OnReevaluateProject (monitor);
+
+ isFSharpSdkProject = null;
UpdateHiddenFiles (Project.Files);
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs
index 6765edf762..2d42a1576f 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SdkProjectReader.cs
@@ -96,15 +96,13 @@ namespace MonoDevelop.Projects
return null;
}
- public override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
+ public override async Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
{
- return Task.Run (() => {
- if (CanRead (fileName, typeof (SolutionItem))) {
- return MSBuildProjectService.LoadItem (monitor, fileName, MSBuildFileFormat.VS2012, typeGuid, itemGuid, ctx);
- }
+ if (CanRead (fileName, typeof (SolutionItem))) {
+ return await MSBuildProjectService.LoadItem (monitor, fileName, MSBuildFileFormat.VS2012, typeGuid, itemGuid, ctx);
+ }
- throw new NotSupportedException ();
- });
+ throw new NotSupportedException ();
}
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs
index 8dce5f1327..2a9c0c96e3 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/SolutionItem.cs
@@ -460,7 +460,7 @@ namespace MonoDevelop.Projects
if (ItemExtension.OnCheckHasSolutionData () && !SavingSolution && ParentSolution != null) {
// The project has data that has to be saved in the solution, but the solution is not being saved. Do it now.
- await SolutionFormat.SlnFileFormat.WriteFile (ParentSolution.FileName, ParentSolution, false, monitor);
+ await Task.Run (() => SolutionFormat.SlnFileFormat.WriteFile (ParentSolution.FileName, ParentSolution, false, monitor));
ParentSolution.NeedsReload = false;
}
}
@@ -1232,12 +1232,12 @@ namespace MonoDevelop.Projects
protected virtual Task OnLoad (ProgressMonitor monitor)
{
- return Task.FromResult (0);
+ return Task.CompletedTask;
}
protected internal virtual Task OnSave (ProgressMonitor monitor)
{
- return Task.FromResult (0);
+ return Task.CompletedTask;
}
public FilePath GetAbsoluteChildPath (FilePath relPath)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs
index 639c96b249..7b4dec5b75 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceItem.cs
@@ -276,7 +276,7 @@ namespace MonoDevelop.Projects
FileService.RequestFileEdit (f);
try {
fileStatusTracker.BeginSave ();
- await ItemExtension.Save (monitor);
+ await Task.Run (() => ItemExtension.Save (monitor));
await OnSaveUserProperties (); // Call the virtual to avoid the lock
OnSaved (new WorkspaceItemEventArgs (this));
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectReader.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectReader.cs
index 9c0a453544..b205558a76 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectReader.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceObjectReader.cs
@@ -41,12 +41,12 @@ namespace MonoDevelop.Projects
public virtual Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid)
{
- throw new NotSupportedException ();
+ return Task.FromException<SolutionItem> (new NotSupportedException ());
}
public virtual Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName)
{
- throw new NotSupportedException ();
+ return Task.FromException<WorkspaceItem> (new NotSupportedException ());
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceSerializationExtension.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceSerializationExtension.cs
index f96243af37..7e4c748ab5 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceSerializationExtension.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/WorkspaceSerializationExtension.cs
@@ -45,13 +45,11 @@ namespace MonoDevelop.Projects
return false;
}
- public override Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName)
+ public override async Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName)
{
- return Task.Run (async () => {
- var workspaceItem = ReadWorkspaceItemFile (fileName, monitor);
- await workspaceItem.LoadUserProperties ().ConfigureAwait (false);
- return workspaceItem;
- });
+ var workspaceItem = ReadWorkspaceItemFile (fileName, monitor);
+ await workspaceItem.LoadUserProperties ().ConfigureAwait (false);
+ return workspaceItem;
}
WorkspaceItem ReadWorkspaceItemFile (FilePath fileName, ProgressMonitor monitor)
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
index 70c27e8047..a08baa0058 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
@@ -543,6 +543,16 @@
defaultHandler = "MonoDevelop.Ide.Commands.ReopenClosedTabHandler"
_label = "Reopen Closed Tab"
_description = "Opens the last tab that has been closed"/>
+ <Command id = "MonoDevelop.Ide.Commands.FileTabCommands.CloseAllExceptPinned"
+ defaultHandler = "MonoDevelop.Ide.Commands.CloseAllExceptPinnedHandler"
+ _label = "Close All Except _Pinned"
+ _description = "Close all files except pinned"
+ macShortcut = "Meta|Shift|P" />
+ <Command id = "MonoDevelop.Ide.Commands.FileTabCommands.PinTab"
+ defaultHandler = "MonoDevelop.Ide.Commands.PinTabHandler"
+ _label = "_Pin Tab"
+ _description = "Pin/Unpin current Tab selected"
+ macShortcut = "Meta|Alt|P" />
</Category>
<!-- ViewCommands -->
@@ -935,7 +945,7 @@
_label = "Find Next Like Selection"
_description = "Search forwards for the selected text"
shortcut = "Control|F3"
- macShortcut = "Meta|E Meta|F3" />
+ macShortcut = "Meta|F3" />
<Command id = "MonoDevelop.Ide.Commands.SearchCommands.FindPreviousSelection"
_label = "Find Previous Like Selection"
_description = "Search backwards for the selected text"
@@ -1012,10 +1022,11 @@
shortcut = "Control|I"
macShortcut = "Meta|L" />
<Command id = "MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForFind"
- _label = "Find Like Selection"
- _description = "Uses the current selection as find string"/>
+ _label = "Use Selection for Find"
+ _description = "Uses the current selection as find string"
+ macShortcut = "Meta|E" />
<Command id = "MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForReplace"
- _label = "Replace Like Selection"
+ _label = "Use Selection for Replace"
_description = "Uses the current selection as replace string"/>
</Category>
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
index feb4dea335..e9d314c67c 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
@@ -157,7 +157,7 @@
<CommandItem id = "MonoDevelop.Ide.Commands.SearchCommands.FindPrevious" />
<CommandItem id = "MonoDevelop.Ide.Commands.SearchCommands.FindNext" />
<CommandItem id = "MonoDevelop.Ide.Commands.SearchCommands.FindNextSelection" />
-
+ <CommandItem id = "MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForFind" />
<SeparatorItem id = "SearchSeparator2" />
<CommandItem id = "MonoDevelop.Ide.Commands.SearchCommands.FindInFiles" />
<CommandItem id = "MonoDevelop.Ide.Commands.SearchCommands.ReplaceInFiles" />
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
index 70690194fb..c25b4e1b7c 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
@@ -348,8 +348,10 @@
<Extension path = "/MonoDevelop/Ide/ContextMenu/DocumentTab">
<CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.CloseFile" />
<CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.CloseAll" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.CloseAllExceptPinned" />
<CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.CloseAllButThis" />
<CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.CloseAllToTheRight" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.PinTab" />
<CommandItem id = "MonoDevelop.Ide.Commands.FileTabCommands.ReopenClosedTab" />
<SeparatorItem id = "CloseSeparator" />
<CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.Save" />
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/ActionCommand.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/ActionCommand.cs
index fd92edcc49..4f7753ace4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/ActionCommand.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/ActionCommand.cs
@@ -109,15 +109,16 @@ namespace MonoDevelop.Components.Commands
info.Visible = false;
return;
}
- defaultHandler = (CommandHandler) Activator.CreateInstance (DefaultHandlerType);
+ defaultHandler = (CommandHandler)Activator.CreateInstance (DefaultHandlerType);
}
if (commandArray) {
info.ArrayInfo = new CommandArrayInfo (info);
defaultHandler.InternalUpdate (info.ArrayInfo);
- }
- else
+ } else
defaultHandler.InternalUpdate (info);
}
+
+ internal RuntimeAddin RuntimeAddin => defaultHandlerAddin;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
index 326e5a8299..67aea3f5a5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
@@ -478,8 +478,14 @@ namespace MonoDevelop.Components.Commands
}
#endif
// Handle the GDK key via MD commanding
- if (ProcessKeyEventCore (ev))
- return true;
+ try {
+ if (ProcessKeyEventCore (ev)) {
+ return true;
+ }
+ } catch (Exception ex) {
+ LoggingService.LogInternalError ("Exception while parsing command", ex);
+ return false;
+ }
#if MAC
// Otherwise if we have a native first responder that is not the GdkQuartzView
@@ -547,6 +553,10 @@ namespace MonoDevelop.Components.Commands
return false;
}
+ if (commands == null) {
+ return false;
+ }
+
var toplevelFocus = IdeApp.Workbench.HasToplevelFocus;
var conflict = new List<Command> ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs
index b12ecad3fb..1697cba57a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs
@@ -36,6 +36,7 @@ using MonoDevelop.Ide;
using MonoDevelop.Components.AtkCocoaHelper;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Shell;
+using System.Linq;
namespace MonoDevelop.Components.DockNotebook
{
@@ -136,6 +137,7 @@ namespace MonoDevelop.Components.DockNotebook
public event TabsReorderedHandler TabsReordered;
public event EventHandler<TabEventArgs> TabClosed;
+ public event EventHandler<TabEventArgs> TabPinned;
public event EventHandler<TabEventArgs> TabActivated;
public event EventHandler<TabEventArgs> PageAdded;
@@ -349,6 +351,8 @@ namespace MonoDevelop.Components.DockNotebook
PageAdded?.Invoke (this, new TabEventArgs { Tab = tab, });
+ tab.OnChangingPinned = OnTabPinned;
+
NotebookChanged?.Invoke (this, EventArgs.Empty);
return tab;
@@ -360,6 +364,24 @@ namespace MonoDevelop.Components.DockNotebook
((DockNotebookTab)pages [n]).Index = n;
}
+ void OnTabPinned (DockNotebookTab sender, bool value)
+ {
+ if (pages.Count == 1)
+ return;
+
+ var stickedPages = pages.Where (p => p.IsPinned);
+ var normalPages = pages.Where (p => !p.IsPinned);
+
+ if (value) {
+ if (stickedPages.Any ())
+ ReorderTab (sender, normalPages.MinValueOrDefault (s => s.Index) ?? stickedPages.MaxValueOrDefault (s => s.Index), false);
+ else
+ ReorderTab (sender, pages.FirstOrDefault (), false);
+ } else {
+ ReorderTab (sender, stickedPages.MaxValueOrDefault (s => s.Index) ?? normalPages.MinValueOrDefault (s => s.Index), false);
+ }
+ }
+
public DockNotebookTab GetTab (int n)
{
if (n < 0 || n >= pages.Count)
@@ -388,8 +410,11 @@ namespace MonoDevelop.Components.DockNotebook
NotebookChanged?.Invoke (this, EventArgs.Empty);
}
- internal void ReorderTab (DockNotebookTab tab, DockNotebookTab targetTab)
+ internal void ReorderTab (DockNotebookTab tab, DockNotebookTab targetTab, bool pinCheck = true)
{
+ if (pinCheck && tab.IsPinned != targetTab.IsPinned)
+ return;
+
if (tab == targetTab)
return;
int targetPos = targetTab.Index;
@@ -412,6 +437,12 @@ namespace MonoDevelop.Components.DockNotebook
TabClosed (this, new TabEventArgs () { Tab = tab });
}
+ internal void OnPinTab (DockNotebookTab tab)
+ {
+ if (TabPinned != null)
+ TabPinned (this, new TabEventArgs () { Tab = tab });
+ }
+
internal void OnActivateTab (DockNotebookTab tab)
{
if (TabActivated != null)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebookTab.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebookTab.cs
index fbd6a1ed22..53c1b62205 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebookTab.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebookTab.cs
@@ -35,6 +35,9 @@ namespace MonoDevelop.Components.DockNotebook
{
class DockNotebookTab: IAnimatable, IDisposable
{
+ public System.Action<DockNotebookTab, bool> OnChangingPinned;
+ public System.Action<DockNotebookTab, bool> OnChangedPinned;
+
DockNotebook notebook;
readonly TabStrip strip;
@@ -47,6 +50,8 @@ namespace MonoDevelop.Components.DockNotebook
Xwt.Drawing.Image icon;
Widget content;
+ internal Cairo.Rectangle PinButtonActiveArea;
+
Gdk.Rectangle allocation;
internal Gdk.Rectangle Allocation {
get {
@@ -113,6 +118,19 @@ namespace MonoDevelop.Components.DockNotebook
public double DirtyStrength { get; set; }
+ bool isPinned;
+ public bool IsPinned {
+ get { return isPinned; }
+ set {
+ if (isPinned == value)
+ return;
+ OnChangingPinned?.Invoke (this, value);
+ isPinned = value;
+ strip.Update ();
+ OnChangedPinned?.Invoke (this, value);
+ }
+ }
+
void IAnimatable.BatchBegin () { }
void IAnimatable.BatchCommit () { QueueDraw (); }
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
index 7f7743b443..6f32941ec4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
@@ -37,6 +37,7 @@ using MonoDevelop.Components.Docking;
using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide;
using System.Runtime.InteropServices;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.Components.DockNotebook
{
@@ -49,6 +50,8 @@ namespace MonoDevelop.Components.DockNotebook
static Xwt.Drawing.Image tabbarBackImage = Xwt.Drawing.Image.FromResource ("tabbar-back.9.png");
static Xwt.Drawing.Image tabCloseImage = Xwt.Drawing.Image.FromResource ("tab-close-9.png");
static Xwt.Drawing.Image tabDirtyImage = Xwt.Drawing.Image.FromResource ("tab-dirty-9.png");
+ static Xwt.Drawing.Image tabPinnedImage = Xwt.Drawing.Image.FromResource ("tab-pinned-9.png");
+ static Xwt.Drawing.Image tabUnPinnedImage = Xwt.Drawing.Image.FromResource ("tab-unpinned-9.png");
HBox innerBox;
@@ -84,8 +87,11 @@ namespace MonoDevelop.Components.DockNotebook
static readonly int VerticalTextSize = 11;
const int TabSpacing = 0;
const int LeanWidth = 12;
+ const int ButtonSize = 14;
const double CloseButtonMarginRight = 0;
const double CloseButtonMarginBottom = -1.0;
+ const double PinButtonMarginRight = 0;
+ const double PinButtonMarginBottom = -1.0;
const int TextOffset = 1;
@@ -235,7 +241,7 @@ namespace MonoDevelop.Components.DockNotebook
tab.AccessibilityPressCloseButton += OnAccessibilityPressCloseButton;
tab.AccessibilityShowMenu += OnAccessibilityShowMenu;
}
- }
+ }
UpdateAccessibilityTabs ();
notebook.PageAdded += PageAddedHandler;
notebook.PageRemoved += PageRemovedHandler;
@@ -254,14 +260,14 @@ namespace MonoDevelop.Components.DockNotebook
void PageAddedHandler (object sender, TabEventArgs args)
{
- var tab = args.Tab;
+ var tab = args.Tab;
- if (tab.Accessible != null) {
+ if (tab.Accessible != null) {
Accessible.AddAccessibleElement (tab.Accessible);
- Accessible.AddAccessibleElement (tab.CloseButtonAccessible);
-
- tab.AccessibilityPressTab += OnAccessibilityPressTab;
- tab.AccessibilityPressCloseButton += OnAccessibilityPressCloseButton;
+ Accessible.AddAccessibleElement (tab.CloseButtonAccessible);
+
+ tab.AccessibilityPressTab += OnAccessibilityPressTab;
+ tab.AccessibilityPressCloseButton += OnAccessibilityPressCloseButton;
tab.AccessibilityShowMenu += OnAccessibilityShowMenu;
}
@@ -272,13 +278,13 @@ namespace MonoDevelop.Components.DockNotebook
void PageRemovedHandler (object sender, TabEventArgs args)
{
- var tab = args.Tab;
+ var tab = args.Tab;
+
+ if (tab.Accessible != null) {
+ tab.AccessibilityPressTab -= OnAccessibilityPressTab;
+ tab.AccessibilityPressCloseButton -= OnAccessibilityPressCloseButton;
+ tab.AccessibilityShowMenu -= OnAccessibilityShowMenu;
- if (tab.Accessible != null) {
- tab.AccessibilityPressTab -= OnAccessibilityPressTab;
- tab.AccessibilityPressCloseButton -= OnAccessibilityPressCloseButton;
- tab.AccessibilityShowMenu -= OnAccessibilityShowMenu;
-
Accessible.RemoveAccessibleElement (tab.Accessible);
Accessible.RemoveAccessibleElement (tab.CloseButtonAccessible);
}
@@ -290,11 +296,11 @@ namespace MonoDevelop.Components.DockNotebook
UpdateAccessibilityTabs ();
}
- void PageReorderedHandler (DockNotebookTab tab, int oldPlacement, int newPlacement)
+ void PageReorderedHandler (DockNotebookTab tab, int oldPlacement, int newPlacement)
{
QueueResize ();
- UpdateAccessibilityTabs ();
+ UpdateAccessibilityTabs ();
}
void UpdateAccessibilityTabs ()
@@ -553,6 +559,7 @@ namespace MonoDevelop.Components.DockNotebook
return base.OnMotionNotifyEvent (evnt);
}
+ bool overPinOnPress;
bool overCloseOnPress;
bool allowDoubleClick;
@@ -573,6 +580,13 @@ namespace MonoDevelop.Components.DockNotebook
}
overCloseOnPress = false;
+ // Don't select the tab if we are clicking the pin button
+ if (IsOverPinButton (t, (int)evnt.X, (int)evnt.Y)) {
+ overPinOnPress = true;
+ return true;
+ }
+ overPinOnPress = false;
+
if (evnt.Type == EventType.TwoButtonPress) {
if (allowDoubleClick) {
notebook.OnActivateTab (t);
@@ -604,15 +618,22 @@ namespace MonoDevelop.Components.DockNotebook
return base.OnButtonReleaseEvent (evnt);
}
- if (!draggingTab && overCloseOnPress) {
+ if (!draggingTab) {
var t = FindTab ((int)evnt.X, (int)evnt.Y);
- if (t != null && IsOverCloseButton (t, (int)evnt.X, (int)evnt.Y)) {
+ if (t != null && overCloseOnPress && IsOverCloseButton (t, (int)evnt.X, (int)evnt.Y)) {
notebook.OnCloseTab (t);
allowDoubleClick = false;
return true;
+ } else if (t != null && overPinOnPress && IsOverPinButton (t, (int)evnt.X, (int)evnt.Y)) {
+ t.IsPinned = !t.IsPinned;
+ notebook.OnPinTab (t);
+ allowDoubleClick = false;
+ QueueDraw ();
+ return true;
}
}
overCloseOnPress = false;
+ overPinOnPress = false;
allowDoubleClick = true;
if (dragX != 0)
this.Animate ("EndDrag",
@@ -935,6 +956,7 @@ namespace MonoDevelop.Components.DockNotebook
// Cancel drag operations and animations
buttonPressedOnTab = false;
overCloseOnPress = false;
+ overPinOnPress = false;
allowDoubleClick = true;
draggingTab = false;
dragX = 0;
@@ -966,6 +988,11 @@ namespace MonoDevelop.Components.DockNotebook
return tab != null && tab.CloseButtonActiveArea.Contains (x, y);
}
+ static bool IsOverPinButton (DockNotebookTab tab, int x, int y)
+ {
+ return tab != null && tab.PinButtonActiveArea.Contains (x, y);
+ }
+
public void Update ()
{
if (!tracker.Hovered) {
@@ -1145,7 +1172,7 @@ namespace MonoDevelop.Components.DockNotebook
leftPadding = (leftPadding * Math.Min (1.0, Math.Max (0.5, (tabBounds.Width - 30) / 70.0)));
double bottomPadding = active ? TabActivePadding.Bottom : TabPadding.Bottom;
- DrawTabBackground (this, ctx, allocation, tabBounds.Width, tabBounds.X, active);
+ DrawTabBackground (this, ctx, allocation, tabBounds.Width, tabBounds.X, active, tab.IsPinned);
ctx.LineWidth = 1;
ctx.NewPath ();
@@ -1158,9 +1185,17 @@ namespace MonoDevelop.Components.DockNotebook
tab.CloseButtonActiveArea = closeButtonAlloation.Inflate (2, 2);
+ var spinButtonAllocation = new Cairo.Rectangle (closeButtonAlloation.X - rightPadding - PinButtonMarginRight,
+ closeButtonAlloation.Y,
+ tabPinnedImage.Width, tabPinnedImage.Height);
+
+ tab.PinButtonActiveArea = spinButtonAllocation.Inflate (2, 2);
+
bool closeButtonHovered = tracker.Hovered && tab.CloseButtonActiveArea.Contains (tracker.MousePosition);
+ bool pinButtonHovered = tracker.Hovered && tab.PinButtonActiveArea.Contains (tracker.MousePosition);
bool tabHovered = tracker.Hovered && tab.Allocation.Contains (tracker.MousePosition);
- bool drawCloseButton = active || tabHovered || focused;
+ bool drawCloseButton = tab.IsPinned || (active || tabHovered || focused);
+ bool drawPinButton = tab.IsPinned || tabHovered;
if (!closeButtonHovered && tab.DirtyStrength > 0.5) {
ctx.DrawImage (this, tabDirtyImage, closeButtonAlloation.X, closeButtonAlloation.Y);
@@ -1170,11 +1205,17 @@ namespace MonoDevelop.Components.DockNotebook
if (drawCloseButton)
ctx.DrawImage (this, tabCloseImage.WithAlpha ((closeButtonHovered ? 1.0 : 0.5) * tab.Opacity), closeButtonAlloation.X, closeButtonAlloation.Y);
+ if (drawPinButton)
+ ctx.DrawImage (this, (tab.IsPinned ? tabPinnedImage : tabUnPinnedImage).WithAlpha ((pinButtonHovered ? 1.0 : 0.5) * tab.Opacity), spinButtonAllocation.X, spinButtonAllocation.Y);
+
// Render Text
double tw = tabBounds.Width - (leftPadding + rightPadding);
if (drawCloseButton || tab.DirtyStrength > 0.5)
tw -= closeButtonAlloation.Width / 2;
+ if (drawPinButton || tab.DirtyStrength > 0.5)
+ tw -= spinButtonAllocation.Width / 2 + rightPadding;
+
double tx = tabBounds.X + leftPadding;
var baseline = la.GetLine (0).Layout.GetPixelBaseline ();
double ty = tabBounds.Height - bottomPadding - baseline;
@@ -1199,11 +1240,11 @@ namespace MonoDevelop.Components.DockNotebook
ctx.SetSource (lg);
Pango.CairoHelper.ShowLayout (ctx, la.GetLine (0).Layout);
}
- }
+ }
la.Dispose ();
}
- static void DrawTabBackground (Widget widget, Context ctx, Gdk.Rectangle allocation, int contentWidth, int px, bool active = true)
+ static void DrawTabBackground (Widget widget, Context ctx, Gdk.Rectangle allocation, int contentWidth, int px, bool active = true, bool isPinned = false)
{
int lean = Math.Min (LeanWidth, contentWidth / 2);
int halfLean = lean / 2;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs
index 1a54f5e800..9556f15db2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockBarItem.cs
@@ -39,6 +39,7 @@ using Animations = Xwt.Motion.AnimationExtensions;
using MonoDevelop.Core;
using MonoDevelop.Ide.Fonts;
using MonoDevelop.Ide;
+using Gdk;
namespace MonoDevelop.Components.Docking
{
@@ -369,6 +370,12 @@ namespace MonoDevelop.Components.Docking
if (autoShowTimeout == uint.MaxValue) {
autoShowTimeout = GLib.Timeout.Add (bar.Frame.AutoShowDelay, delegate {
autoShowTimeout = uint.MaxValue;
+
+ // Check is mouse over - it may be that the LeaveEvent wasn't fired becaues of a gtk bug. So we double check as a work around.
+ GetPointer (out int x, out int y);
+ bool isMouseOver = x >= 0 && y >= 0 && x <= Allocation.Width && y <= Allocation.Height;
+ if (!isMouseOver)
+ return false;
AutoShow ();
return false;
});
@@ -430,11 +437,23 @@ namespace MonoDevelop.Components.Docking
protected override bool OnEnterNotifyEvent (Gdk.EventCrossing evnt)
{
+ ScheduleAutoShowOnHover();
+ return base.OnEnterNotifyEvent (evnt);
+ }
+
+ protected override bool OnMotionNotifyEvent (EventMotion evnt)
+ {
+ ScheduleAutoHide (true);
+ ScheduleAutoShowOnHover ();
+ return base.OnMotionNotifyEvent (evnt);
+ }
+
+ void ScheduleAutoShowOnHover ()
+ {
if (bar.HoverActivationEnabled && autoShowFrame == null) {
ScheduleAutoShow ();
QueueDraw ();
}
- return base.OnEnterNotifyEvent (evnt);
}
void OnPerformPress (object sender, EventArgs args)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs
index 9084175639..ab8d215712 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/CommandSearchCategory.cs
@@ -26,27 +26,27 @@
using System;
using System.Threading;
using System.Threading.Tasks;
-using MonoDevelop.Core;
+using System.Linq;
using System.Collections.Generic;
-using MonoDevelop.Core.Instrumentation;
-using MonoDevelop.Projects;
-using MonoDevelop.Ide.Gui;
-using MonoDevelop.Ide;
-using ICSharpCode.NRefactory.TypeSystem;
-using MonoDevelop.Ide.TypeSystem;
+using MonoDevelop.Core;
using MonoDevelop.Core.Text;
-using Gtk;
-using System.Linq;
using MonoDevelop.Components.Commands;
+using MonoDevelop.Ide;
namespace MonoDevelop.Components.MainToolbar
{
class CommandSearchCategory : SearchCategory
{
static readonly List<Tuple<Command, string>> allCommands;
+ static readonly Mono.Addins.RuntimeAddin currentRuntimeAddin;
static CommandSearchCategory ()
{
+ // The AddinManager is not thread safe, so we need to make sure we're
+ // calling from the main thread.
+ Runtime.AssertMainThread ();
+ currentRuntimeAddin = Mono.Addins.AddinManager.CurrentAddin;
+
var hiddenCategory = GettextCatalog.GetString ("Hidden");
allCommands = IdeApp.CommandService.GetCommands ()
.Where (cmd => (cmd as ActionCommand)?.CommandArray != true && cmd.Category != hiddenCategory)
@@ -58,7 +58,7 @@ namespace MonoDevelop.Components.MainToolbar
{
}
- string[] validTags = new [] { "cmd", "command", "c" };
+ readonly string[] validTags = { "cmd", "command", "c" };
public override string [] Tags {
get {
@@ -86,10 +86,12 @@ namespace MonoDevelop.Components.MainToolbar
break;
var cmd = cmdTuple.Item1;
var matchString = cmdTuple.Item2;
- int rank;
- if (matcher.CalcMatchRank (matchString, out rank))
+ if (matcher.CalcMatchRank (matchString, out var rank)) {
+ if ((cmd as ActionCommand)?.RuntimeAddin == currentRuntimeAddin)
+ rank += 1; // we prefer commands comming from the addin
searchResultCallback.ReportResult (new CommandResult (cmd, null, route, pattern.Pattern, matchString, rank));
+ }
}
} catch (OperationCanceledException) {
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
index 0a25ce6227..0312ddd9bf 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/GtkWorkarounds.cs
@@ -45,20 +45,10 @@ using System.Windows.Input;
namespace MonoDevelop.Components
{
- public static class GtkWorkarounds
+ public static partial class GtkWorkarounds
{
- const string LIBOBJC ="/usr/lib/libobjc.dylib";
const string USER32DLL = "User32.dll";
- [DllImport (LIBOBJC, EntryPoint = "sel_registerName")]
- static extern IntPtr sel_registerName (string selector);
-
- [DllImport (LIBOBJC, EntryPoint = "objc_getClass")]
- static extern IntPtr objc_getClass (string klass);
-
- [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
- static extern IntPtr objc_msgSend_IntPtr (IntPtr klass, IntPtr selector);
-
[DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
static extern void objc_msgSend_void_bool (IntPtr klass, IntPtr selector, bool arg);
@@ -83,9 +73,6 @@ namespace MonoDevelop.Components
[DllImport (LIBOBJC, EntryPoint = "objc_msgSend_stret")]
static extern void objc_msgSend_CGRect64 (out CGRect64 rect, IntPtr klass, IntPtr selector);
- [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
- static extern void objc_msgSend_NSInt64_NSInt32 (IntPtr klass, IntPtr selector, int arg);
-
[DllImport (PangoUtil.LIBQUARTZ)]
static extern IntPtr gdk_quartz_window_get_nswindow (IntPtr window);
@@ -109,7 +96,7 @@ namespace MonoDevelop.Components
static IntPtr cls_NSScreen;
static IntPtr sel_screens, sel_objectEnumerator, sel_nextObject, sel_frame, sel_visibleFrame,
- sel_requestUserAttention, sel_setHasShadow, sel_invalidateShadow, sel_terminate;
+ sel_requestUserAttention, sel_setHasShadow, sel_invalidateShadow;
static IntPtr sharedApp;
static IntPtr cls_NSEvent;
static IntPtr sel_modifierFlags;
@@ -174,21 +161,9 @@ namespace MonoDevelop.Components
sel_modifierFlags = sel_registerName ("modifierFlags");
sel_setHasShadow = sel_registerName ("setHasShadow:");
sel_invalidateShadow = sel_registerName ("invalidateShadow");
- sel_terminate = sel_registerName ("terminate:");
sharedApp = objc_msgSend_IntPtr (objc_getClass ("NSApplication"), sel_registerName ("sharedApplication"));
}
- static void MacTerminate ()
- {
- objc_msgSend_NSInt64_NSInt32 (sharedApp, sel_terminate, 0);
- }
-
- public static void Terminate ()
- {
- if (Platform.IsMac)
- MacTerminate ();
- }
-
static Gdk.Rectangle MacGetUsableMonitorGeometry (Gdk.Screen screen, int monitor)
{
IntPtr array = objc_msgSend_IntPtr (cls_NSScreen, sel_screens);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Mac/NSViewExtensions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Mac/NSViewExtensions.cs
index 9d7e89b4cc..be3192f786 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Mac/NSViewExtensions.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Mac/NSViewExtensions.cs
@@ -22,6 +22,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+#if MAC
using System;
using System.Runtime.InteropServices;
using Foundation;
@@ -71,10 +72,12 @@ namespace AppKit
}
}
- static readonly IntPtr sel_sortSubviewsUsingFunction_context_ = Selector.GetHandle ("sortSubviewsUsingFunction:context:");
+ static readonly IntPtr sel_sortSubviewsUsingFunction_context_ =
+ Selector.GetHandle ("sortSubviewsUsingFunction:context:");
static void SortSubviews (NSView view, IntPtr function_pointer, IntPtr context)
{
MonoDevelop.Components.Mac.Messaging.void_objc_msgSend_IntPtr_IntPtr (view.Handle, sel_sortSubviewsUsingFunction_context_, function_pointer, context);
}
}
}
+#endif
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Shared/GtkWorkarounds.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Shared/GtkWorkarounds.cs
new file mode 100644
index 0000000000..9ae2811d82
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Shared/GtkWorkarounds.cs
@@ -0,0 +1,65 @@
+//
+// GtkWorkarounds.cs
+//
+// Author:
+// iain <iaholmes@microsoft.com>
+//
+// Copyright (c) 2019
+//
+// 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.Runtime.InteropServices;
+
+using MonoDevelop.Core;
+
+// This partial of the GtkWorkarounds class is shared between MonoDevelop.Ide.dll and md-tool.exe
+// Anything that only needs to be in MonoDevelop.Ide should go into the other part.
+namespace MonoDevelop.Components
+{
+ public static partial class GtkWorkarounds
+ {
+ const string LIBOBJC = "/usr/lib/libobjc.dylib";
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern IntPtr objc_msgSend_IntPtr (IntPtr klass, IntPtr selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "sel_registerName")]
+ static extern IntPtr sel_registerName (string selector);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_getClass")]
+ static extern IntPtr objc_getClass (string klass);
+
+ [DllImport (LIBOBJC, EntryPoint = "objc_msgSend")]
+ static extern void objc_msgSend_NSInt64_NSInt32 (IntPtr klass, IntPtr selector, int arg);
+
+ static void MacTerminate ()
+ {
+ var sel_terminate = sel_registerName ("terminate:");
+ var app = objc_msgSend_IntPtr (objc_getClass ("NSApplication"), sel_registerName ("sharedApplication"));
+
+ objc_msgSend_NSInt64_NSInt32 (app, sel_terminate, 0);
+ }
+
+ public static void Terminate ()
+ {
+ if (Platform.IsMac)
+ MacTerminate ();
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
index c2b43f1433..bc209f4124 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
@@ -444,4 +444,5 @@ namespace MonoDevelop.Ide.Commands
// MonoDevelop.Ide.Commands.CopyPathNameHandler Implemented in FileTabCommands.cs
// MonoDevelop.Ide.Commands.FileTabCommands.ToggleMaximize Implemented in FileTabCommands.cs
// MonoDevelop.Ide.Commands.FileTabCommands.ReopenClosedTab Implemented in FileTabCommands.cs
+ // MonoDevelop.Ide.Commands.FileTabCommands.CloseAllExceptPinned Implemented in FileTabCommands.cs
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs
index 65ade3f49b..295000ea11 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs
@@ -39,6 +39,10 @@ using MonoDevelop.Ide.Gui.Dialogs;
using MonoDevelop.Ide.Gui.Documents;
using MonoDevelop.Ide.Gui.Shell;
+using MonoDevelop.Components.DockNotebook;
+using System.Collections.Immutable;
+using MonoDevelop.Core;
+
namespace MonoDevelop.Ide.Commands
{
public enum FileTabCommands
@@ -48,14 +52,26 @@ namespace MonoDevelop.Ide.Commands
CopyPathName,
ToggleMaximize,
ReopenClosedTab,
- CloseAllToTheRight
+ CloseAllToTheRight,
+ CloseAllExceptPinned,
+ PinTab,
}
- class CloseAllHandler : CommandHandler
+ class CloseAllHandler : TabCommandHandler
{
- protected virtual Document GetDocumentException ()
+ protected virtual ImmutableArray<Document> GetDocumentExceptions ()
+ {
+ return ImmutableArray<Document>.Empty;
+ }
+
+ bool HasDistinctViewContent (ImmutableArray<Document> viewContents, Document document)
{
- return null;
+ for (int i = 0; i < viewContents.Length; i++) {
+ if (document.Window.Document == viewContents[i]) {
+ return false;
+ }
+ }
+ return true;
}
protected virtual bool StartAfterException => false;
@@ -67,15 +83,15 @@ namespace MonoDevelop.Ide.Commands
return;
var activeNotebook = ((SdiWorkspaceWindow)active.Window).TabControl;
- var except = GetDocumentException ();
+ var except = GetDocumentExceptions ();
var docs = new List<Document> ();
var dirtyDialogShown = false;
- var startRemoving = except == null || !StartAfterException;
+ var startRemoving = !except.Any () || !StartAfterException;
foreach (var doc in IdeApp.Workbench.Documents) {
if (((SdiWorkspaceWindow)doc.Window).TabControl == activeNotebook) {
- if (except != null && doc == except) {
+ if (except.Any () && !HasDistinctViewContent (except, doc)) {
startRemoving = true;
continue;
}
@@ -102,34 +118,72 @@ namespace MonoDevelop.Ide.Commands
}
}
- class CloseAllButThisHandler : CloseAllHandler
+ abstract class TabCommandHandler : CommandHandler
{
- protected override Document GetDocumentException ()
- {
- return IdeApp.Workbench.ActiveDocument;
+ protected DockNotebookTab GetTabFromActiveDocument () {
+ var document = IdeApp.Workbench.ActiveDocument;
+ if (document == null)
+ return null;
+ return ((SdiWorkspaceWindow)document.Window).DockNotebookTab;
}
+ }
+ class CloseAllExceptPinnedHandler : CloseAllHandler
+ {
protected override void Update (CommandInfo info)
{
- var documents = IdeApp.Workbench.Documents;
- var activeDoc = IdeApp.Workbench.ActiveDocument;
+ info.Visible = info.Enabled = IdeApp.Workbench.Documents.Count != 0;
+ }
- if (activeDoc == null) {
- info.Enabled = false;
+ protected override ImmutableArray<Document> GetDocumentExceptions ()
+ {
+ var active = IdeApp.Workbench.ActiveDocument;
+ if (active == null)
+ return ImmutableArray<Document>.Empty;
+
+ var activeNotebook = ((SdiWorkspaceWindow)active.Window).TabControl;
+
+ var contents = Microsoft.CodeAnalysis
+ .ImmutableArrayExtensions
+ .WhereAsArray (
+ IdeApp.Workbench.Documents.ToImmutableArray (),
+ doc => ((SdiWorkspaceWindow)doc.Window).TabControl == activeNotebook && (((SdiWorkspaceWindow)doc.Window).DockNotebookTab?.IsPinned ?? false)
+ );
+ return contents;
+ }
+ }
+
+ class PinTabHandler : TabCommandHandler
+ {
+ protected override void Update (CommandInfo info)
+ {
+ info.Visible = info.Enabled = IdeApp.Workbench.ActiveDocument != null;
+ if (!info.Visible)
return;
+
+ var selectedTab = GetTabFromActiveDocument ();
+ if (selectedTab != null) {
+ info.Text = (selectedTab.IsPinned) ? GettextCatalog.GetString ("Un_pin Tab") : GettextCatalog.GetString ("_Pin Tab");
}
+ }
- var activeNotebook = ((SdiWorkspaceWindow)activeDoc.Window).TabControl;
+ protected override void Run ()
+ {
+ var selectedTab = GetTabFromActiveDocument ();
+ if (selectedTab != null)
+ selectedTab.IsPinned = !selectedTab.IsPinned;
+ }
+ }
- // Disable if only document in tab strip
- foreach (var doc in documents) {
- if (doc != activeDoc && ((SdiWorkspaceWindow)doc.Window).TabControl == activeNotebook) {
- info.Enabled = true;
- return;
- }
+ class CloseAllButThisHandler : CloseAllHandler
+ {
+ protected override ImmutableArray<Document> GetDocumentExceptions ()
+ {
+ var active = IdeApp.Workbench.ActiveDocument;
+ if (active == null) {
+ return ImmutableArray<Document>.Empty;
}
-
- info.Enabled = false;
+ return ImmutableArray.Create (active.Window.Document);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs
index ef32d1a4ad..1721889cd2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs
@@ -310,8 +310,6 @@ namespace MonoDevelop.Ide.CustomTools
// Execute the generator
- Exception error = null;
-
// Share the one pad for all Tool output.
Pad pad = null;
@@ -337,7 +335,6 @@ namespace MonoDevelop.Ide.CustomTools
try {
await tool.Generate (monitor, project, file, result);
} catch (Exception ex) {
- error = ex;
result.UnhandledException = ex;
}
@@ -360,11 +357,7 @@ namespace MonoDevelop.Ide.CustomTools
UpdateCompleted (monitor, file, genFile, result, false);
} finally {
FileService.ThawEvents ();
- if (error == null)
- newTask.SetResult (true);
- else {
- newTask.SetException (error);
- }
+ newTask.TrySetResult (true);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs
index 3d812dfa67..9a47f7e362 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/DefaultSourceEditorOptions.cs
@@ -367,7 +367,7 @@ namespace MonoDevelop.Ide.Editor
showRulerFromContext = false;
}
}
-
+ this.FireChange ();
return Task.FromResult (true);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
index 74bdc40b31..eef174104a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
@@ -850,6 +850,7 @@ namespace MonoDevelop.Ide.Gui
if (!String.IsNullOrEmpty (document.FileName)) {
var dp = CreateDocumentPrefs (args, document);
dp.NotebookId = notebookId;
+ dp.IsPinned = tab.IsPinned;
files.Add (dp);
}
}
@@ -867,6 +868,16 @@ namespace MonoDevelop.Ide.Gui
dp.Line = line.LineNumber + 1;
dp.Column = pos.Position - line.Start + 1;
}
+
+ try {
+ var tab = ((SdiWorkspaceWindow)document.Window).DockNotebookTab;
+ if (tab != null) {
+ dp.IsPinned = tab.IsPinned;
+ }
+ } catch (Exception ex) {
+ LoggingService.LogInternalError (ex);
+ }
+
return dp;
}
@@ -953,6 +964,16 @@ namespace MonoDevelop.Ide.Gui
var document = await documentManager.BatchOpenDocument (pm, fileName, null, doc.Line, doc.Column, nb);
if (document != null) {
+
+ try {
+ var tab = ((SdiWorkspaceWindow)document.Window).DockNotebookTab;
+ if (tab != null) {
+ tab.IsPinned = doc.IsPinned;
+ }
+ } catch (Exception ex) {
+ LoggingService.LogInternalError (ex);
+ }
+
var t = new Tuple<Document,string> (document, fileName);
docViews.Add (t);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchMemento.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchMemento.cs
index d70c432c54..a8a35f8d5c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchMemento.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/WorkbenchMemento.cs
@@ -127,6 +127,9 @@ namespace MonoDevelop.Ide.Gui
[ItemProperty (DefaultValue = 0)]
public int NotebookId;
+
+ [ItemProperty (DefaultValue = false)]
+ public bool IsPinned;
}
[DataItem ("Pad")]
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index 4b27c74d7a..6879aa96f6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -142,6 +142,14 @@
<EmbeddedResource Include="templates\EmptyStruct.xft.xml" />
<EmbeddedResource Include="templates\EmptyTextFile.xft.xml" />
<EmbeddedResource Include="templates\EmptyXMLFile.xft.xml" />
+ <EmbeddedResource Include="icons\tab-pinned-9.png" />
+ <EmbeddedResource Include="icons\tab-pinned-9%402x.png" />
+ <EmbeddedResource Include="icons\tab-pinned-9~dark.png" />
+ <EmbeddedResource Include="icons\tab-pinned-9~dark%402x.png" />
+ <EmbeddedResource Include="icons\tab-unpinned-9.png" />
+ <EmbeddedResource Include="icons\tab-unpinned-9%402x.png" />
+ <EmbeddedResource Include="icons\tab-unpinned-9~dark.png" />
+ <EmbeddedResource Include="icons\tab-unpinned-9~dark%402x.png" />
<EmbeddedResource Include="icons\reference-assembly-16.png" />
<EmbeddedResource Include="icons\reference-assembly-16%402x.png" />
<EmbeddedResource Include="icons\reference-assembly-16~dark.png" />
@@ -4252,6 +4260,7 @@
<Compile Include="MonoDevelop.Components\Mac\DragEventTrapView.cs" />
<Compile Include="MonoDevelop.Components\Mac\NativeToolkitHelper.cs" />
<Compile Include="MonoDevelop.Components\Mac\NSViewExtensions.cs" />
+ <Compile Include="MonoDevelop.Components\Shared\GtkWorkarounds.cs" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'DebugMac' OR '$(Configuration)' == 'ReleaseMac'">
<Compile Include="MonoDevelop.Components\Mac\KeyCodes.cs" />
@@ -4353,6 +4362,9 @@
<InternalsVisibleTo Include="Xamarin.OSXEditor" />
<InternalsVisibleTo Include="Xamarin.Sketches" />
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="MonoDevelop.Components\Shared\" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
<Copy SourceFiles="@(Data)" DestinationFolder="..\..\..\build\data\%(Data.RelativeDir)" SkipUnchangedFiles="true" />
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
index da8982d467..1776fbeb3b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
@@ -541,9 +541,9 @@ namespace MonoDevelop.Ide
// If the user interacted with the IDE just a moment ago, wait a bit more time before
// running the action
- var interactionSpan = (int)(DateTime.Now - commandService.LastUserInteraction).TotalMilliseconds;
+ var interactionSpan = Math.Max (0, (DateTime.Now - commandService.LastUserInteraction).TotalMilliseconds);
if (interactionSpan < 500) {
- DispatchIdleActions (500 - interactionSpan);
+ DispatchIdleActions (500 - (int) interactionSpan);
return;
}
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9.png b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9.png
new file mode 100644
index 0000000000..edc1f09dd6
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9@2x.png b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9@2x.png
new file mode 100644
index 0000000000..86acbbbc16
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9@2x.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark.png b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark.png
new file mode 100644
index 0000000000..9fa86cb595
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark@2x.png b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark@2x.png
new file mode 100644
index 0000000000..ee2e2262ff
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-pinned-9~dark@2x.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9.png b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9.png
new file mode 100644
index 0000000000..24f9f94650
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9@2x.png b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9@2x.png
new file mode 100644
index 0000000000..cab628cf34
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9@2x.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark.png b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark.png
new file mode 100644
index 0000000000..e240b6cc83
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark.png
Binary files differ
diff --git a/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark@2x.png b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark@2x.png
new file mode 100644
index 0000000000..23838c89b2
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/icons/tab-unpinned-9~dark@2x.png
Binary files differ
diff --git a/main/src/tools/mdtool/mdtool.csproj b/main/src/tools/mdtool/mdtool.csproj
index 0910f01da2..69d8d48902 100644
--- a/main/src/tools/mdtool/mdtool.csproj
+++ b/main/src/tools/mdtool/mdtool.csproj
@@ -36,6 +36,9 @@
<None Include="..\..\core\MonoDevelop.Startup\app.config">
<Link>app.config</Link>
</None>
+ <Compile Include="..\..\core\MonoDevelop.Ide\MonoDevelop.Components\Shared\GtkWorkarounds.cs">
+ <Link>src\GtkWorkarounds.cs</Link>
+ </Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
diff --git a/main/src/tools/mdtool/src/mdtool.cs b/main/src/tools/mdtool/src/mdtool.cs
index 1ecaa580b7..778a3f5d7f 100644
--- a/main/src/tools/mdtool/src/mdtool.cs
+++ b/main/src/tools/mdtool/src/mdtool.cs
@@ -45,6 +45,7 @@ class MonoDevelopProcessHost
[STAThread]
public static int Main (string[] args)
{
+ int exitCode = -1;
try {
var sc = new ConsoleSynchronizationContext ();
SynchronizationContext.SetSynchronizationContext (sc);
@@ -115,7 +116,8 @@ class MonoDevelopProcessHost
//setup app needs to skip runtime initialization or we get addin engine races
if (toolName == "setup") {
- return RunSetup (toolArgs);
+ exitCode = RunSetup (toolArgs);
+ return exitCode;
}
// Only log fatal errors unless verbosity is specified. Command line tools should already
@@ -127,40 +129,57 @@ class MonoDevelopProcessHost
if (showHelp || badInput) {
ShowHelp (badInput, exeName);
- return badInput? 1 : 0;
+ exitCode = badInput? 1 : 0;
+ return exitCode;
}
- var tool = Runtime.ApplicationService.GetApplication (toolName);
- if (tool == null) {
- Console.Error.WriteLine ("Tool '{0}' not found.", toolName);
- listTools = true;
- badInput = true;
- }
-
- if (listTools) {
- ShowAvailableTools ();
- return badInput? 1 : 0;
- }
+ if (!showHelp && !badInput) {
+ var tool = Runtime.ApplicationService.GetApplication (toolName);
+ if (tool == null) {
+ Console.Error.WriteLine ("Tool '{0}' not found.", toolName);
+ listTools = true;
+ badInput = true;
+ }
- var task = tool.Run (toolArgs);
- task.ContinueWith ((t) => sc.ExitLoop ());
- sc.RunMainLoop ();
- return task.Result;
+ if (listTools) {
+ ShowAvailableTools ();
+ exitCode = badInput ? 1 : 0;
+ return exitCode;
+ }
+ if (tool != null) {
+ var task = tool.Run (toolArgs);
+ task.ContinueWith ((t) => sc.ExitLoop ());
+ sc.RunMainLoop ();
+ exitCode = task.Result;
+ }
+ }
} catch (UserException ex) {
Console.WriteLine (ex.Message);
- return -1;
+ exitCode = -1;
} catch (Exception ex) {
LoggingService.LogFatalError (ex.ToString ());
- return -1;
+ exitCode = -1;
} finally {
try {
- Runtime.Shutdown ();
+ var terminate = exitCode == 0;
+ Shutdown (terminate);
} catch {
// Ignore shutdown exceptions
}
LoggingService.Shutdown ();
}
+
+ return exitCode;
+ }
+
+ static void Shutdown (bool terminate)
+ {
+ Runtime.Shutdown ();
+
+ if (terminate) {
+ MonoDevelop.Components.GtkWorkarounds.Terminate ();
+ }
}
static void ShowHelp (bool shortHelp, string exeName)
diff --git a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/FilePathTests.cs b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/FilePathTests.cs
index 6d3bad23c5..f43f41eaba 100644
--- a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/FilePathTests.cs
+++ b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Core/FilePathTests.cs
@@ -24,6 +24,7 @@
// 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.IO;
using System.Linq;
using NUnit.Framework;
@@ -111,21 +112,58 @@ namespace MonoDevelop.Core
Assert.IsFalse (child.IsChildPathOf (child));
}
- [Test]
- public void FileExtensionIsProper ()
+ [TestCase("test.txt", "test")]
+ [TestCase(".gitignore", "")]
+ public void FileNameWithoutExtension (string fileName, string expected)
+ {
+ var path = FilePath.Build ("dir", fileName);
+
+ Assert.AreEqual (expected, path.FileNameWithoutExtension);
+ }
+
+
+ [TestCase ("test.txt", ".txt", true)]
+ [TestCase ("test.txt", ".TxT", null)]
+ [TestCase ("test.txt", ".cs", false)]
+ [TestCase ("test.txt", ".longer", false)]
+ [TestCase ("test.txt", "", false)]
+ [TestCase (".gitignore", ".gitignore", true)]
+ [TestCase (".gitignore", ".git", false)]
+ [TestCase (".gitignore", "", false)]
+ [TestCase ("a", "", true)]
+ [TestCase ("a.", "", true)]
+ [TestCase ("", "", true)]
+ [TestCase ("", "a", false)]
+ public void HasExtensionChecks (string fileName, string assertExtension, bool? expected)
{
- var path = new FilePath ("asdf.txt");
- Assert.AreEqual ("asdf.txt", path.FileName);
- Assert.IsTrue (path.HasExtension (".txt"));
- Assert.AreEqual (FilePath.PathComparison == StringComparison.OrdinalIgnoreCase, path.HasExtension (".TXT"));
- Assert.AreEqual (".txt", path.Extension);
- Assert.AreEqual ("asdf", path.FileNameWithoutExtension);
-
- path = new FilePath (".gitignore");
- Assert.False (path.HasExtension (".gitignore"));
- Assert.AreEqual (".gitignore", path.FileName);
- Assert.AreEqual (".gitignore", path.Extension);
- Assert.AreEqual ("", path.FileNameWithoutExtension);
+ IEqualityComparer<string> comparer = FilePath.PathComparer;
+ var expectedValue = expected ?? FilePath.PathComparison == StringComparison.OrdinalIgnoreCase;
+
+ var path = FilePath.Build ("dir", fileName);
+
+ Assert.AreEqual (expectedValue, path.HasExtension (assertExtension));
+
+ var expectedConstraint = expectedValue ? Is.EqualTo (assertExtension) : Is.Not.EqualTo (assertExtension);
+ Assert.That (path.Extension, expectedConstraint.Using (comparer));
+ }
+
+ [TestCase ("test.txt", "test.txt", true)]
+ [TestCase ("test.txt", "Test.txT", null)]
+ [TestCase ("test.txt", "abc.txt", false)]
+ [TestCase ("test.txt", "something", false)]
+ [TestCase (".gitignore", ".gitignore", true)]
+ [TestCase (".gitignore", ".git", false)]
+ public void HasFileNameChecks (string fileName, string assertFileName, bool? expected)
+ {
+ IEqualityComparer<string> comparer = FilePath.PathComparer;
+ var expectedValue = expected ?? FilePath.PathComparison == StringComparison.OrdinalIgnoreCase;
+
+ var path = FilePath.Build ("dir", fileName);
+
+ Assert.AreEqual (expectedValue, path.HasFileName (assertFileName));
+
+ var expectedConstraint = expectedValue ? Is.EqualTo (assertFileName) : Is.Not.EqualTo (assertFileName);
+ Assert.That (path.FileName, expectedConstraint.Using (comparer));
}
[Test]
diff --git a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/MSBuildProjectTests.cs b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/MSBuildProjectTests.cs
index 7b3738aa59..fbfe4e9454 100644
--- a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/MSBuildProjectTests.cs
+++ b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/MSBuildProjectTests.cs
@@ -494,6 +494,20 @@ namespace MonoDevelop.Projects
var specialFolder = Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
Assert.AreEqual (specialFolder, p.EvaluatedProperties.GetValue ("EnumFolderPath"));
+ var path = p.EvaluatedProperties.GetValue ("Path");
+
+ Assert.AreEqual (
+ path.Split (Path.DirectorySeparatorChar).Length,
+ p.EvaluatedProperties.GetValue<int> ("EnumFlagsSplitStringLength")
+ );
+ Assert.AreEqual (
+ path.Split (new [] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries).Length,
+ p.EvaluatedProperties.GetValue<int> ("EnumFlagsSplitStringRemoveEmptyLength")
+ );
+
+ Assert.AreEqual ("1", p.EvaluatedProperties.GetValue ("CorrectOverloadIndexOf"));
+ Assert.AreEqual ("a.cs;b.cs", p.EvaluatedProperties.GetValue ("CorrectOverloadIndexOfTransform"));
+
var basePath = Path.GetDirectoryName (p.FileName);
var targets = Path.Combine (basePath, "false.targets");
diff --git a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/ProjectWithWildcardsTests.cs b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/ProjectWithWildcardsTests.cs
index 97cf87adf3..8bf1f13c7d 100644
--- a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/ProjectWithWildcardsTests.cs
+++ b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/ProjectWithWildcardsTests.cs
@@ -1,4 +1,4 @@
-//
+//
// ProjectWithWildcardsTests.cs
//
// Author:
@@ -63,6 +63,31 @@ namespace MonoDevelop.Projects
}
[Test]
+ public async Task LoadProjectWithQuestionWildcards ()
+ {
+ string projFile = Util.GetSampleProject ("console-project-with-wildcards", "ConsoleProject-with-question-wildcard.csproj");
+
+ var p = await Services.ProjectService.ReadSolutionItem (Util.GetMonitor (), projFile);
+ Assert.IsInstanceOf<Project> (p);
+ var mp = (Project)p;
+ var files = mp.Files.Select (f => f.FilePath.FileName).OrderBy (f => f).ToArray ();
+ Assert.That (files, Is.EquivalentTo (new string [] {
+ "Data1.cs",
+ "Data2.cs",
+ "Data3.cs",
+ "maybe.js",
+ "maybe1.js",
+ "Program.cs",
+ "text1-1.txt",
+ "text1-2.txt",
+ "text2-1.txt",
+ "text2-2.txt",
+ }));
+
+ p.Dispose ();
+ }
+
+ [Test]
public async Task LoadProjectWithWildcardsAndExcludes ()
{
string projFile = Util.GetSampleProject ("console-project-with-wildcards", "ConsoleProject-with-excludes.csproj");
@@ -338,7 +363,7 @@ namespace MonoDevelop.Projects
}
/// <summary>
- /// If an MSBuild item has a property on loading then if all the properties are removed the
+ /// If an MSBuild item has a property on loading then if all the properties are removed the
/// project file when saved will still have an end element. So this test uses a different
/// .saved5 file compared with the previous test and includes the extra end tag for the
/// EmbeddedResource.
diff --git a/main/tests/test-projects/console-project-with-wildcards/ConsoleProject-with-question-wildcard.csproj b/main/tests/test-projects/console-project-with-wildcards/ConsoleProject-with-question-wildcard.csproj
new file mode 100755
index 0000000000..c94386b696
--- /dev/null
+++ b/main/tests/test-projects/console-project-with-wildcards/ConsoleProject-with-question-wildcard.csproj
@@ -0,0 +1,51 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4A9E3523-48F0-4BDF-A0F4-49DAD4431FAB}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>ConsoleProject</RootNamespace>
+ <AssemblyName>ConsoleProject</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>True</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>False</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>True</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Content\**\*.cs" />
+ <Content Include="Content\*.txt" />
+ <Content Include="Content\Data\*.txt" />
+ <Content Include="maybe?.js" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/main/tests/test-projects/console-project-with-wildcards/maybe.js b/main/tests/test-projects/console-project-with-wildcards/maybe.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/main/tests/test-projects/console-project-with-wildcards/maybe.js
diff --git a/main/tests/test-projects/console-project-with-wildcards/maybe1.js b/main/tests/test-projects/console-project-with-wildcards/maybe1.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/main/tests/test-projects/console-project-with-wildcards/maybe1.js
diff --git a/main/tests/test-projects/msbuild-tests/functions.csproj b/main/tests/test-projects/msbuild-tests/functions.csproj
index 5a96bebf3f..217f855153 100755
--- a/main/tests/test-projects/msbuild-tests/functions.csproj
+++ b/main/tests/test-projects/msbuild-tests/functions.csproj
@@ -1,10 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
- <ItemGroup>
+ <ItemGroup>
<File Include="$(P1).$(Prefix)Test1" />
<Result Include="$(Files)" />
- </ItemGroup>
- <PropertyGroup>
+ <DesignerCS Include="a.designer.cs;b.designer.cs"/>
+ <DesignerCSDependentFiles Include="@(DesignerCS)">
+ <DependentUpon>$([System.String]::Copy('%(Identity)').Substring(
+ 0,
+ $([System.String]::Copy('%(Identity)').LastIndexOf(
+ '.designer.cs',
+ System.StringComparison.OrdinalIgnoreCase))
+ )).cs
+ </DependentUpon>
+ </DesignerCSDependentFiles>
+ </ItemGroup>
+ <PropertyGroup>
<Prop>abcdefgh</Prop>
<SomeChars>1.0</SomeChars>
<TestFile>files\test.txt</TestFile>
@@ -37,7 +47,7 @@
<CharTrim>$(Path.Trim (\b))</CharTrim>
<OutDir>foo</OutDir>
<FullPath>$([System.IO.Path]::GetFullPath(`$([System.IO.Path]::Combine(`$(MSBuildProjectDirectory)`, `$(OutDir)`))`))</FullPath>
- <FullPathWithSpaces>$([System.IO.Path]::GetFullPath(`$([System.IO.Path]::Combine(`$(MSBuildProjectDirectory)`, `(a b)`))`))</FullPathWithSpaces>
+ <FullPathWithSpaces>$([System.IO.Path]::GetFullPath(`$([System.IO.Path]::Combine(`$(MSBuildProjectDirectory)`, `(a b)`))`))</FullPathWithSpaces>
<P1>AAA</P1>
<Files>$(P1);@(File)</Files>
<Prefix>Post</Prefix>
@@ -47,14 +57,18 @@
<DoubleNumberComplex>$([MSBuild]::Subtract($(DoubleNumber.Split('.')[0].Substring(3).Trim()), 8800))</DoubleNumberComplex>
<ParamsPathCombine>$([System.IO.Path]::Combine('a', 'b', 'c', 'd', 'e', 'f'))</ParamsPathCombine>
<EnumFolderPath>$([System.Environment]::GetFolderPath(SpecialFolder.LocalApplicationData))</EnumFolderPath>
+ <EnumFlagsSplitStringLength>$(Path.Split('\', StringSplitOptions.None).Length)</EnumFlagsSplitStringLength>
+ <EnumFlagsSplitStringRemoveEmptyLength>$(Path.Split('\', System.StringSplitOptions.None|RemoveEmptyEntries).Length)</EnumFlagsSplitStringRemoveEmptyLength>
<DirectoryNameOfFileAbove>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), false.targets))false.targets</DirectoryNameOfFileAbove>
<PathOfFileAbove>$([MSBuild]::GetPathOfFileAbove('false.targets'))</PathOfFileAbove>
<EnsureTrailingSlash>$([MSBuild]::EnsureTrailingSlash('$(CharTrim)'))</EnsureTrailingSlash>
<NormalizeDirectory>$([MSBuild]::NormalizeDirectory('$(CharTrim)'))</NormalizeDirectory>
<NormalizePath>$([MSBuild]::NormalizePath('$(CharTrim)'))</NormalizePath>
- </PropertyGroup>
- <PropertyGroup>
- </PropertyGroup>
+ <CorrectOverloadIndexOf>$([System.String]::Copy('a.designer.cs').LastIndexOf('.designer.cs', System.StringComparison.OrdinalIgnoreCase))</CorrectOverloadIndexOf>
+ <CorrectOverloadIndexOfTransform>@(DesignerCSDependentFiles->'%(DependentUpon)')</CorrectOverloadIndexOfTransform>
+ </PropertyGroup>
+ <PropertyGroup>
+ </PropertyGroup>
<Target Name="Test">
<Message Text="$(FullPath)" />
</Target>
diff --git a/version-checks b/version-checks
index b6284130b8..052d27b050 100644
--- a/version-checks
+++ b/version-checks
@@ -17,7 +17,7 @@ DEP[0]=md-addins
DEP_NAME[0]=MDADDINS
DEP_PATH[0]=${top_srcdir}/../md-addins
DEP_MODULE[0]=git@github.com:xamarin/md-addins.git
-DEP_NEEDED_VERSION[0]=f69d5f968f1b0d549818e286daafcf6416fbba9c
+DEP_NEEDED_VERSION[0]=cb7f1ec820c2396dea8cd21079f6ab3d4a5eb09f
DEP_BRANCH_AND_REMOTE[0]="master origin/master"
# heap-shot