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
path: root/main
diff options
context:
space:
mode:
authorSandy Armstrong <sandy@xamarin.com>2019-01-25 18:05:34 +0300
committerSandy Armstrong <sandy@xamarin.com>2019-01-25 18:24:42 +0300
commit2325b5d4c5f79fcbe37acf617eb87e23c56a1684 (patch)
treef9c8fd4da08b7bbac6b26ef1602fd35ec7ac4bd9 /main
parent4a92358ddf393435c36fb742aeecda2e45d9c238 (diff)
parent2e188887d8e5ee2901fd803d4374f0c0fb8ad69a (diff)
Merge remote-tracking branch 'origin/master' into pr-sandy-md-master
Diffstat (limited to 'main')
m---------main/external/debugger-libs0
m---------main/external/macdoc0
m---------main/external/xwt0
-rw-r--r--main/src/addins/CSharpBinding/CSharpBinding.addin.xml1
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextPasteHandler.cs2
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs107
-rw-r--r--main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs2
-rw-r--r--main/src/addins/MacPlatform/MacInterop/LaunchServices.cs3
-rw-r--r--main/src/addins/MacPlatform/MacInterop/ProcessManager.cs37
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/SelectorView.cs43
-rw-r--r--main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config1
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs8
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs8
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs7
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/TextEntryWithCodeCompletion.cs61
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/CodeTemplateToolboxProvider.cs3
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/IToolboxProvider.cs10
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolbox.cs2
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolboxWidget.cs7
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs29
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Gui/DotNetCoreSdkLocationWidget.UI.cs21
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreMSBuildProjectTests.cs35
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreMSBuildProject.cs18
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs30
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs4
-rw-r--r--main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdkPaths.cs31
-rw-r--r--main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs8
-rw-r--r--main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditor.cs20
-rw-r--r--main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditorDebugger.cs2
-rw-r--r--main/src/addins/MonoDevelop.HexEditor/Mono.MHex/SimpleEditMode.cs6
-rw-r--r--main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs2
-rw-r--r--main/src/addins/MonoDevelop.Packaging/Gui/MonoDevelop.Packaging.Gui.GtkNuGetPackageMetadataOptionsPanelWidget.cs4
-rw-r--r--main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs159
-rw-r--r--main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkProjectNuGetBuildOptionsPanelWidget.cs19
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs218
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs2
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs4
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/IconMargin.cs57
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs9
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ClipboardRingService.cs3
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs18
-rw-r--r--main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/ExternalTestRunner.cs3
-rw-r--r--main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs3
-rw-r--r--main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/ClipboardColoredText.cs6
-rw-r--r--main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Document/TextDocument.cs1
-rw-r--r--main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Styles.cs2
-rw-r--r--main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextEditorData.cs39
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/AssemblyUtilities.cs82
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs38
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs20
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessExecutionCommand.cs11
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/RemoteProcessConnection.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/BacktrackingStringMatcher.cs5
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj1
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs13
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs629
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs7
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml4
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml1
-rw-r--r--main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Gui.OptionPanels.LoadSavePanelWidget.cs162
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs16
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs22
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/ItemTemplateExtensionNode.cs73
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs37
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.Caching.cs62
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs345
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs68
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ISyntaxHighlighting.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/OSXEditor.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs18
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ExternalTools/ExternalToolPanel.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs28
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs48
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsPanel.cs17
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/PolicyOptionsPanel.cs21
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LoadSavePanel.cs19
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectPadContextMenu.addin.xml5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CommonAssemblySigningPreferences.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/RunConfigurationsList.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkProjectConfigurationWidget.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewSolutionRunConfigurationDialog.cs98
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs135
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/HackyWorkspaceFilesCache.cs236
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs23
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs13
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs103
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs32
-rw-r--r--main/src/core/MonoDevelop.Ide/gtkrc7
-rw-r--r--main/src/core/MonoDevelop.Ide/gtkrc.mac9
-rw-r--r--main/src/core/MonoDevelop.Ide/gtkrc.mac-dark6
-rw-r--r--main/src/core/MonoDevelop.Ide/gtkrc.win327
-rw-r--r--main/src/core/MonoDevelop.Ide/gtkrc.win32-dark4
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.Gui/CompletionListWindowTests.cs21
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.RoslynServices/MonoDevelopProjectCacheHostServiceTests.cs1
-rw-r--r--main/tests/MacPlatform.Tests/MacPlatform.Tests.csproj1
-rw-r--r--main/tests/MacPlatform.Tests/ProcessManagerTests.cs44
117 files changed, 2345 insertions, 1337 deletions
diff --git a/main/external/debugger-libs b/main/external/debugger-libs
-Subproject 6fdcde8355fd6497fb741145bbd740115b2493a
+Subproject 30829f533f7f17be7a39d014b59c25552d4d755
diff --git a/main/external/macdoc b/main/external/macdoc
-Subproject 09751517e1fa5fae9ca38369fdfcdbe27122a9d
+Subproject 1b1bc1072851608930f872b0f54296afd4813a6
diff --git a/main/external/xwt b/main/external/xwt
-Subproject b57194e95dc6f102cf0f5f0a949e5a4436ab589
+Subproject 0bb3624360311e682396231f1b93e7eaa3b724c
diff --git a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml
index a0f29aa524..2d78c132f9 100644
--- a/main/src/addins/CSharpBinding/CSharpBinding.addin.xml
+++ b/main/src/addins/CSharpBinding/CSharpBinding.addin.xml
@@ -60,6 +60,7 @@
type="array"
_label = "Refactory Operations" />
<Command id = "MonoDevelop.CSharp.Refactoring.Commands.SortAndRemoveImports"
+ defaultHandler = "MonoDevelop.CSharp.Refactoring.RemoveAndSortUsingsHandler"
_label = "R_emove and Sort Usings"
_displayName = "Remove Unused and Sort (Usings)"
/>
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextPasteHandler.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextPasteHandler.cs
index c1288027a1..9dce8b43f9 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextPasteHandler.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Formatting/CSharpTextPasteHandler.cs
@@ -106,6 +106,8 @@ namespace MonoDevelop.CSharp.Formatting
indent.Editor.Options.IndentStyle == IndentStyle.Auto)
return;
var doc = indent.DocumentContext.AnalysisDocument;
+ if (doc == null)
+ return;
var options = await doc.GetOptionsAsync ();
if (!options.GetOption (FeatureOnOffOptions.FormatOnPaste, doc.Project.Language))
return;
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs
index 5dcca9c6f6..c20004ddbd 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring/RefactoryCommands.cs
@@ -58,7 +58,70 @@ namespace MonoDevelop.CSharp.Refactoring
SortAndRemoveImports,
}
- sealed class CurrentRefactoryOperationsHandler : CommandHandler
+ abstract class RefactoringHandler : CommandHandler
+ {
+ protected bool TryGetDocument (out Document analysisDocument, out Ide.Gui.Document doc)
+ {
+ doc = IdeApp.Workbench.ActiveDocument;
+ if (doc == null || doc.FileName == null) {
+ analysisDocument = null;
+ return false;
+ }
+
+ analysisDocument = doc.AnalysisDocument;
+ return doc != null;
+ }
+ }
+
+ sealed class RemoveAndSortUsingsHandler : RefactoringHandler
+ {
+ protected override void Update (CommandInfo info)
+ {
+ info.Enabled = TryGetDocument (out var doc, out var _) && IsSortAndRemoveImportsSupported (doc);
+ }
+
+ protected override void Run ()
+ {
+ if (TryGetDocument (out var doc, out var _))
+ SortAndRemoveUnusedImports (doc, CancellationToken.None).Ignore ();
+ }
+
+ internal static bool IsSortAndRemoveImportsSupported (Document document)
+ {
+ var workspace = document.Project.Solution.Workspace;
+
+ if (!workspace.CanApplyChange (ApplyChangesKind.ChangeDocument)) {
+ return false;
+ }
+
+ if (workspace.Kind == WorkspaceKind.MiscellaneousFiles) {
+ return false;
+ }
+
+ return workspace.Services.GetService<IDocumentSupportsFeatureService> ().SupportsRefactorings (document);
+ }
+
+ internal static async Task SortAndRemoveUnusedImports (Document originalDocument, CancellationToken cancellationToken)
+ {
+ if (originalDocument == null)
+ return;
+
+ var workspace = originalDocument.Project.Solution.Workspace;
+
+ var unnecessaryImportsService = originalDocument.GetLanguageService<IRemoveUnnecessaryImportsService> ();
+
+ // Remove unnecessary imports and sort them
+ var removedImportsDocument = await unnecessaryImportsService.RemoveUnnecessaryImportsAsync (originalDocument, cancellationToken);
+ var resultDocument = await OrganizeImportsService.OrganizeImportsAsync (removedImportsDocument, cancellationToken);
+
+ // Apply the document change if needed
+ if (resultDocument != originalDocument) {
+ workspace.ApplyDocumentChanges (resultDocument, cancellationToken);
+ }
+ }
+ }
+
+ sealed class CurrentRefactoryOperationsHandler : RefactoringHandler
{
protected override void Run (object dataItem)
{
@@ -69,9 +132,7 @@ namespace MonoDevelop.CSharp.Refactoring
protected override async Task UpdateAsync (CommandArrayInfo ainfo, CancellationToken cancelToken)
{
- var doc = IdeApp.Workbench.ActiveDocument;
- var analysisDocument = doc.AnalysisDocument;
- if (doc == null || doc.FileName == FilePath.Null || analysisDocument == null)
+ if (!TryGetDocument (out var analysisDocument, out var doc))
return;
var semanticModel = await analysisDocument.GetSemanticModelAsync (cancelToken);
if (semanticModel == null)
@@ -87,12 +148,12 @@ namespace MonoDevelop.CSharp.Refactoring
}));
}
- bool isSortAndRemoveUsingsSupported = IsSortAndRemoveImportsSupported (analysisDocument);
+ bool isSortAndRemoveUsingsSupported = RemoveAndSortUsingsHandler.IsSortAndRemoveImportsSupported (analysisDocument);
if (isSortAndRemoveUsingsSupported) {
var sortAndRemoveImportsInfo = IdeApp.CommandService.GetCommandInfo (Commands.SortAndRemoveImports);
sortAndRemoveImportsInfo.Enabled = true;
ainfo.Add (sortAndRemoveImportsInfo, new Action (async delegate {
- await SortAndRemoveUnusedImports (analysisDocument, cancelToken);
+ await RemoveAndSortUsingsHandler.SortAndRemoveUnusedImports (analysisDocument, cancelToken);
}));
}
@@ -140,40 +201,6 @@ namespace MonoDevelop.CSharp.Refactoring
}
}
- static bool IsSortAndRemoveImportsSupported (Document document)
- {
- var workspace = document.Project.Solution.Workspace;
-
- if (!workspace.CanApplyChange (ApplyChangesKind.ChangeDocument)) {
- return false;
- }
-
- if (workspace.Kind == WorkspaceKind.MiscellaneousFiles) {
- return false;
- }
-
- return workspace.Services.GetService<IDocumentSupportsFeatureService> ().SupportsRefactorings (document);
- }
-
- static async Task SortAndRemoveUnusedImports (Document originalDocument, CancellationToken cancellationToken)
- {
- if (originalDocument == null)
- return;
-
- var workspace = originalDocument.Project.Solution.Workspace;
-
- var unnecessaryImportsService = originalDocument.GetLanguageService<IRemoveUnnecessaryImportsService> ();
-
- // Remove unnecessary imports and sort them
- var removedImportsDocument = await unnecessaryImportsService.RemoveUnnecessaryImportsAsync (originalDocument, cancellationToken);
- var resultDocument = await OrganizeImportsService.OrganizeImportsAsync (removedImportsDocument, cancellationToken);
-
- // Apply the document change if needed
- if (resultDocument != originalDocument) {
- workspace.ApplyDocumentChanges (resultDocument, cancellationToken);
- }
- }
-
static string FormatFileName (string fileName)
{
if (fileName == null)
diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs
index 4cec8f48b9..ad47d39987 100644
--- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs
+++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment/DefaultDeployServiceExtension.cs
@@ -26,7 +26,7 @@ namespace MonoDevelop.Deployment
evalCtx.ItemsToEvaluate.Add ("AllPublishItemsFullPathWithTargetPath");
if (project.MSBuildProject.UseMSBuildEngine) {
- var result = project.RunTarget (null, "GetCopyToPublishDirectoryItems", configuration, evalCtx).Result;
+ var result = project.RunTarget (new ProgressMonitor (), "GetCopyToPublishDirectoryItems", configuration, evalCtx).Result;
foreach (var item in result.Items) {
if (item.Name == "AllPublishItemsFullPathWithTargetPath") {
var fromPath = MSBuildProjectService.FromMSBuildPath (project.ItemDirectory, item.Include);
diff --git a/main/src/addins/MacPlatform/MacInterop/LaunchServices.cs b/main/src/addins/MacPlatform/MacInterop/LaunchServices.cs
index c8549b32fa..4a42e43f59 100644
--- a/main/src/addins/MacPlatform/MacInterop/LaunchServices.cs
+++ b/main/src/addins/MacPlatform/MacInterop/LaunchServices.cs
@@ -48,6 +48,7 @@ namespace MonoDevelop.MacInterop
public string[] Args { get; set; }
public bool Async { get; set; }
public bool NewInstance { get; set; }
+ public bool HideFromRecentApps { get; set; }
}
public class LaunchServicesException : Exception
@@ -144,6 +145,8 @@ namespace MonoDevelop.MacInterop
options |= (UInt32) LaunchOptions.NSWorkspaceLaunchAsync;
if (application.NewInstance)
options |= (UInt32) LaunchOptions.NSWorkspaceLaunchNewInstance;
+ if (application.HideFromRecentApps)
+ options |= (UInt32) LaunchOptions.NSWorkspaceLaunchWithoutAddingToRecents;
IntPtr error;
var appHandle = IntPtr_objc_msgSend_IntPtr_UInt32_IntPtr_IntPtr (NSWorkspace.SharedWorkspace.Handle, launchApplicationAtURLOptionsConfigurationErrorSelector, appUrl.Handle, options, config.Handle, out error);
diff --git a/main/src/addins/MacPlatform/MacInterop/ProcessManager.cs b/main/src/addins/MacPlatform/MacInterop/ProcessManager.cs
index 6861c33696..565ed251a1 100644
--- a/main/src/addins/MacPlatform/MacInterop/ProcessManager.cs
+++ b/main/src/addins/MacPlatform/MacInterop/ProcessManager.cs
@@ -33,28 +33,6 @@ namespace MonoDevelop.MacInterop
{
public static class ProcessManager
{
- const string CARBON = "/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon";
-
- [DllImport (CARBON)]
- static extern OSStatus GetProcessPID (ref ProcessSerialNumber psn, out int pid);
-
- [DllImport (CARBON)]
- static extern OSStatus KillProcess (ref ProcessSerialNumber process);
-
- public static int GetProcessPid (ProcessSerialNumber psn)
- {
- int pid;
- if (GetProcessPID (ref psn, out pid) == OSStatus.Ok)
- return pid;
- return -1;
- }
-
- [Obsolete ("Use KillProcess (int pid) instead")]
- public static bool KillProcess (ProcessSerialNumber psn)
- {
- return KillProcess (ref psn) == OSStatus.Ok;
- }
-
public static bool KillProcess (int pid)
{
NSRunningApplication runningApp = NSRunningApplication.GetRunningApplication (pid);
@@ -74,20 +52,5 @@ namespace MonoDevelop.MacInterop
Ok = 0
}
}
-
- public struct ProcessSerialNumber
- {
- uint high;
- uint low;
-
- public ProcessSerialNumber (uint high, uint low)
- {
- this.high = high;
- this.low = low;
- }
-
- public uint High { get { return high; } }
- public uint Low { get { return low; } }
- }
}
diff --git a/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs b/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
index ffaace2c12..d28760db4c 100644
--- a/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
+++ b/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
@@ -124,22 +124,10 @@ namespace MonoDevelop.MacIntegration.MainToolbar
internal void OnSizeChanged ()
{
- if (SizeChanged != null) {
- SizeChanged (this, EventArgs.Empty);
- }
+ SizeChanged?.Invoke (this, EventArgs.Empty);
}
- public override bool BecomeFirstResponder()
- {
- if (Window.FirstResponder != RealSelectorView)
- return Window.MakeFirstResponder(RealSelectorView);
- return false;
- }
-
- public override bool AcceptsFirstResponder()
- {
- return Window.FirstResponder != RealSelectorView;
- }
+ public override bool AcceptsFirstResponder () => false;
#region PathSelectorView
[Register]
@@ -585,26 +573,26 @@ namespace MonoDevelop.MacIntegration.MainToolbar
// 0x30 is Tab
if (theEvent.KeyCode == (ushort)KeyCodes.Tab) {
if ((theEvent.ModifierFlags & NSEventModifierMask.ShiftKeyMask) == NSEventModifierMask.ShiftKeyMask) {
- focusedCellIndex--;
- if (focusedCellIndex < 0) {
+ if (focusedCellIndex <= 0) {
if (PreviousKeyView != null) {
SetSelection ();
focusedCellIndex = 0;
focusedItem = null;
}
} else {
+ focusedCellIndex--;
SetSelection ();
return;
}
} else {
- focusedCellIndex++;
- if (focusedCellIndex >= VisibleCellIds.Length) {
+ if (focusedCellIndex >= VisibleCellIds.Length - 1) {
if (NextKeyView != null) {
SetSelection ();
focusedCellIndex = 0;
focusedItem = null;
}
} else {
+ focusedCellIndex++;
SetSelection ();
return;
}
@@ -616,15 +604,20 @@ namespace MonoDevelop.MacIntegration.MainToolbar
void SetSelection ()
{
- if (focusedItem != null) {
- focusedItem.HasFocus = false;
- }
+ //ensures our cells are in the correct enabled state
if (focusedCellIndex >= 0 && focusedCellIndex < Cells.Length) {
- var item = Cells [focusedCellIndex].Cell as NSPathComponentCellFocusable;
- focusedItem = item;
- if (item != null)
- item.HasFocus = true;
+ focusedItem = Cells [focusedCellIndex].Cell as NSPathComponentCellFocusable;
+ if (focusedItem != null)
+ focusedItem.HasFocus = true;
+ }
+
+ //we want ensure our state is correct in other elements
+ for (int i = 0; i < Cells.Length; i++) {
+ if (i != focusedCellIndex && Cells [i].Cell is NSPathComponentCellFocusable focusable) {
+ focusable.HasFocus = false;
+ }
}
+
SetNeedsDisplay ();
}
diff --git a/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config
new file mode 100644
index 0000000000..5f282702bb
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/packages.config
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
index f852bfc07b..5800ba5fe4 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
@@ -830,7 +830,7 @@ namespace MonoDevelop.Debugger
void UpdateDebugSessionCounter ()
{
- var metadata = new Dictionary<string, string> ();
+ var metadata = new Dictionary<string, object> ();
metadata ["Success"] = (!SessionError).ToString ();
metadata ["DebuggerType"] = Engine.Id;
@@ -843,7 +843,7 @@ namespace MonoDevelop.Debugger
}
}
- Counters.DebugSession.Inc (metadata);
+ Counters.DebugSession.Inc (1, null, metadata);
}
void UpdateEvaluationStatsCounter ()
@@ -853,7 +853,7 @@ namespace MonoDevelop.Debugger
return;
}
- var metadata = new Dictionary<string, string> ();
+ var metadata = new Dictionary<string, object> ();
metadata ["DebuggerType"] = Engine.Id;
metadata ["AverageDuration"] = Session.EvaluationStats.AverageTime.ToString ();
metadata ["MaximumDuration"] = Session.EvaluationStats.MaxTime.ToString ();
@@ -861,7 +861,7 @@ namespace MonoDevelop.Debugger
metadata ["FailureCount"] = Session.EvaluationStats.FailureCount.ToString ();
metadata ["SuccessCount"] = Session.EvaluationStats.TimingsCount.ToString ();
- Counters.EvaluationStats.Inc (metadata);
+ Counters.EvaluationStats.Inc (1, null, metadata);
}
bool ExceptionHandler (Exception ex)
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
index b1a2498285..1364ab3939 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
@@ -65,6 +65,10 @@ namespace MonoDevelop.Debugger
public static AsyncOperation DebugApplication (this ProjectOperations opers, string executableFile, string args, string workingDir, IDictionary<string,string> envVars)
{
+ if (!IdeApp.Workbench.RootWindow.Visible) {
+ IdeApp.Workbench.RootWindow.Show ();
+ }
+
var monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor (System.IO.Path.GetFileName (executableFile));
var oper = DebuggingService.Run (executableFile, args, workingDir, envVars, monitor.Console);
@@ -79,6 +83,10 @@ namespace MonoDevelop.Debugger
public static AsyncOperation AttachToProcess (this ProjectOperations opers, DebuggerEngine debugger, ProcessInfo proc)
{
+ if (!IdeApp.Workbench.RootWindow.Visible) {
+ IdeApp.Workbench.RootWindow.Show ();
+ }
+
var oper = DebuggingService.AttachToProcess (debugger, proc);
opers.AddRunOperation (oper);
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs
index 89db6240e6..8a5fb4f50e 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs
@@ -2190,9 +2190,12 @@ namespace MonoDevelop.Debugger
var val = (ObjectValue) store.GetValue (iter, ObjectColumn);
if (val != null && val.Name == DebuggingService.DebuggerSession.EvaluationOptions.CurrentExceptionTag)
DebuggingService.ShowExceptionCaughtDialog ();
+
+ if (val != null && DebuggingService.HasValueVisualizers (val))
+ DebuggingService.ShowValueVisualizer (val);
}
-
-
+
+
bool GetCellAtPos (int x, int y, out TreePath path, out TreeViewColumn col, out CellRenderer cellRenderer)
{
if (GetPathAtPos (x, y, out path, out col)) {
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/TextEntryWithCodeCompletion.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/TextEntryWithCodeCompletion.cs
index ceb0633283..b68f8e5762 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/TextEntryWithCodeCompletion.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/TextEntryWithCodeCompletion.cs
@@ -34,21 +34,18 @@ namespace MonoDevelop.Debugger
class TextEntryWithCodeCompletion : TextEntry, ICompletionWidget
{
CodeCompletionContext ctx;
- Gtk.Entry gtkEntry;
- Gdk.ModifierType modifier;
+ Xwt.ModifierKeys modifier;
bool keyHandled = false;
uint keyValue;
char keyChar;
- Gdk.Key key;
+ Key key;
public TextEntryWithCodeCompletion ()
{
- gtkEntry = Xwt.Toolkit.CurrentEngine.GetNativeWidget (this) as Gtk.Entry;
- if (gtkEntry == null)
- throw new NotImplementedException ();
- gtkEntry.KeyReleaseEvent += HandleKeyReleaseEvent;
- gtkEntry.KeyPressEvent += HandleKeyPressEvent;
+ KeyPressed += HandleKeyPressEvent;
+ KeyReleased += HandleKeyReleaseEvent;
+
CompletionWindowManager.WindowClosed += HandleWindowClosed;
}
@@ -65,32 +62,40 @@ namespace MonoDevelop.Debugger
CompletionContextChanged (this, EventArgs.Empty);
}
+ char CharFromKey (Xwt.Key xwtKey)
+ {
+ if (xwtKey >= Key.Exclamation && xwtKey <= Key.Tilde) {
+ return (char)xwtKey;
+ }
+
+ return '\0';
+ }
+
[GLib.ConnectBeforeAttribute]
- void HandleKeyPressEvent (object o, Gtk.KeyPressEventArgs args)
+ void HandleKeyPressEvent (object o, KeyEventArgs args)
{
keyHandled = false;
- keyChar = (char)args.Event.Key;
- keyValue = args.Event.KeyValue;
- modifier = args.Event.State;
- key = args.Event.Key;
+ keyChar = CharFromKey (args.Key);
+ modifier = args.Modifiers;
+ key = args.Key;
- if ((args.Event.Key == Gdk.Key.Down || args.Event.Key == Gdk.Key.Up)) {
+ if ((args.Key == Key.Down || args.Key == Key.Up)) {
keyChar = '\0';
}
if (list != null)
- args.RetVal = keyHandled = CompletionWindowManager.PreProcessKeyEvent (KeyDescriptor.FromGtk (key, keyChar, modifier));
+ args.Handled = keyHandled = CompletionWindowManager.PreProcessKeyEvent (KeyDescriptor.FromXwt (key, keyChar, modifier));
}
- void HandleKeyReleaseEvent (object o, Gtk.KeyReleaseEventArgs args)
+ void HandleKeyReleaseEvent (object o, KeyEventArgs args)
{
if (keyHandled)
return;
string text = ctx == null ? Text : Text.Substring (Math.Max (0, Math.Min (ctx.TriggerOffset, Text.Length)));
CompletionWindowManager.UpdateWordSelection (text);
- CompletionWindowManager.PostProcessKeyEvent (KeyDescriptor.FromGtk (key, keyChar, modifier));
+ CompletionWindowManager.PostProcessKeyEvent (KeyDescriptor.FromXwt (key, keyChar, modifier));
PopupCompletion ();
}
@@ -121,7 +126,7 @@ namespace MonoDevelop.Debugger
/// </summary>
class NullDotKeyHandler : ICompletionKeyHandler
{
- #region ICompletionKeyHandler implementation
+#region ICompletionKeyHandler implementation
public bool PreProcessKey (CompletionListWindow listWindow, KeyDescriptor descriptor, out KeyActions keyAction)
{
@@ -141,10 +146,10 @@ namespace MonoDevelop.Debugger
return false;
}
- #endregion
+#endregion
}
- #region ICompletionWidget implementation
+#region ICompletionWidget implementation
public event EventHandler CompletionContextChanged;
@@ -186,11 +191,11 @@ namespace MonoDevelop.Debugger
public CodeCompletionContext CreateCodeCompletionContext (int triggerOffset)
{
- var height = gtkEntry.SizeRequest ().Height;
+ var height = Size.Height;
var location = ConvertToScreenCoordinates (new Point (0, height));
return new CodeCompletionContext (
- (int)location.X, (int)location.Y, height,
+ (int)location.X, (int)location.Y, (int)height,
triggerOffset, 0, triggerOffset, CaretOffset
);
}
@@ -203,13 +208,13 @@ namespace MonoDevelop.Debugger
public void SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word)
{
Text = complete_word;
- gtkEntry.Position = complete_word.Length;
+ CursorPosition = complete_word.Length;
}
public void SetCompletionText (CodeCompletionContext ctx, string partial_word, string complete_word, int completeWordOffset)
{
Text = complete_word;
- gtkEntry.Position = complete_word.Length;
+ CursorPosition = complete_word.Length;
}
public CodeCompletionContext CurrentCodeCompletionContext {
@@ -220,10 +225,10 @@ namespace MonoDevelop.Debugger
public int CaretOffset {
get {
- return gtkEntry.Position;
+ return CursorPosition;
}
set {
- gtkEntry.Position = value;
+ CursorPosition = value;
}
}
@@ -241,7 +246,7 @@ namespace MonoDevelop.Debugger
public Gtk.Style GtkStyle {
get {
- return gtkEntry.Style;
+ return null;
}
}
@@ -250,7 +255,7 @@ namespace MonoDevelop.Debugger
return 1;
}
}
- #endregion
+#endregion
}
}
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/CodeTemplateToolboxProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/CodeTemplateToolboxProvider.cs
index 5ed2482524..e65e76b079 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/CodeTemplateToolboxProvider.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/CodeTemplateToolboxProvider.cs
@@ -40,7 +40,6 @@ namespace MonoDevelop.DesignerSupport.Toolbox
{
static string category = MonoDevelop.Core.GettextCatalog.GetString ("Text Snippets");
-
public System.Collections.Generic.IEnumerable<ItemToolboxNode> GetDynamicItems (IToolboxConsumer consumer)
{
var content = consumer as ViewContent;
@@ -58,7 +57,7 @@ namespace MonoDevelop.DesignerSupport.Toolbox
};
}
}
-
+
public event EventHandler ItemsChanged {
add { CodeTemplateService.TemplatesChanged += value; }
remove { CodeTemplateService.TemplatesChanged -= value; }
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/IToolboxProvider.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/IToolboxProvider.cs
index 3498dccd20..041c9cf194 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/IToolboxProvider.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/IToolboxProvider.cs
@@ -35,7 +35,13 @@ using System.Collections.Generic;
namespace MonoDevelop.DesignerSupport.Toolbox
{
-
+ public interface IToolboxDynamicProviderDeleteSupport
+ {
+ bool DeleteDynamicItem (ItemToolboxNode node);
+
+ bool CanDeleteDynamicItem (ItemToolboxNode node);
+ }
+
//Used to fetch or generate the default toolbox items at the beginning of each MD session
public interface IToolboxDefaultProvider
{
@@ -53,7 +59,7 @@ namespace MonoDevelop.DesignerSupport.Toolbox
//This method will be called each time the consumer changes. Return null if not
//returning any items for a specific consumer.
IEnumerable<ItemToolboxNode> GetDynamicItems (IToolboxConsumer consumer);
-
+
event EventHandler ItemsChanged;
}
}
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolbox.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolbox.cs
index f96b00e16f..470addae0c 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolbox.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolbox.cs
@@ -447,7 +447,7 @@ namespace MonoDevelop.DesignerSupport.Toolbox
{
// Hack manually filter out gtk# widgets & container since they cannot be re added
// because they're missing the toolbox attributes.
- info.Enabled = selectedNode != null
+ info.Enabled = selectedNode != null && toolboxService.CanRemoveUserItem (selectedNode)
&& (selectedNode.ItemDomain != GtkWidgetDomain
|| (selectedNode.Category != "Widgets" && selectedNode.Category != "Container"));
}
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolboxWidget.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolboxWidget.cs
index 63562a7689..361798aca1 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolboxWidget.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/MacToolboxWidget.cs
@@ -255,6 +255,7 @@ namespace MonoDevelop.DesignerSupport.Toolbox
base.SetFrameSize (newSize);
var frame = messageTextField.Frame;
messageTextField.Frame = new CGRect (frame.Location, newSize);
+ RedrawItems (true, false);
}
public override void MouseDown (NSEvent theEvent)
@@ -344,12 +345,6 @@ namespace MonoDevelop.DesignerSupport.Toolbox
RegisterClassForItem (typeof (HeaderCollectionViewItem), HeaderViewItemName);
RegisterClassForItem (typeof (LabelCollectionViewItem), LabelViewItemName);
RegisterClassForItem (typeof (ImageCollectionViewItem), ImageViewItemName);
-
- NSNotificationCenter.DefaultCenter.AddObserver (FrameChangedNotification, (s => {
- if (s.Object == this) {
- RedrawItems (true, false);
- }
- }));
}
protected override void Dispose (bool disposing)
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs
index ec9c9db283..fbfe40baee 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/ToolboxService.cs
@@ -152,8 +152,16 @@ namespace MonoDevelop.DesignerSupport
public void RemoveUserItem (ItemToolboxNode node)
{
- Configuration.ItemList.Remove (node);
- SaveConfiguration ();
+ if (Configuration.ItemList.Remove (node)) {
+ SaveConfiguration ();
+ } else {
+ //we need check in the dynamic providers
+ foreach (var prov in dynamicProviders) {
+ if (prov is IToolboxDynamicProviderDeleteSupport provDelSupport && provDelSupport.DeleteDynamicItem (node)) {
+ break;
+ }
+ }
+ }
OnToolboxContentsChanged ();
}
@@ -526,7 +534,22 @@ namespace MonoDevelop.DesignerSupport
//we assume permitted, so only return false when blocked by a filter
return true;
}
-
+
+ internal bool CanRemoveUserItem (ItemToolboxNode node)
+ {
+ if (Configuration.ItemList.Contains (node)) {
+ return true;
+ } else {
+ //we need check in the dynamic providers
+ foreach (var prov in dynamicProviders) {
+ if (prov is IToolboxDynamicProviderDeleteSupport provDelSupport && provDelSupport.CanDeleteDynamicItem (node)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
//evaluate a filter attribute against a list, and check whether permitted
private bool FilterPermitted (ItemToolboxNode node, ToolboxItemFilterAttribute desFa,
ICollection<ToolboxItemFilterAttribute> filterAgainst, IToolboxConsumer consumer)
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Gui/DotNetCoreSdkLocationWidget.UI.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Gui/DotNetCoreSdkLocationWidget.UI.cs
index 247746fe46..1221d49c2e 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Gui/DotNetCoreSdkLocationWidget.UI.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Gui/DotNetCoreSdkLocationWidget.UI.cs
@@ -80,6 +80,14 @@ namespace MonoDevelop.DotNetCore.Gui
locationBox.PackStart (locationLabel, false, false);
locationFileSelector = new CustomFileSelector ();
+ locationFileSelector.TextEntry.SetCommonAccessibilityAttributes (
+ "DotNetCoreSdkLocationWidget.Location",
+ locationLabel.Text,
+ GettextCatalog.GetString ("Enter the .NET Core SDK location"));
+ locationFileSelector.BrowseButton.SetCommonAccessibilityAttributes (
+ "DotNetCoreSdkLocationWidget.Browse",
+ GettextCatalog.GetString ("Browse"),
+ GettextCatalog.GetString ("Select a folder for the .NET Core SDK location"));
locationBox.PackStart (locationFileSelector, true, true);
// .NET Core SDK section.
@@ -148,7 +156,7 @@ namespace MonoDevelop.DotNetCore.Gui
void UpdateCommandLineIconAccessibility (bool found)
{
- sdkFoundIcon.SetCommonAccessibilityAttributes (
+ commandLineFoundIcon.SetCommonAccessibilityAttributes (
"DotNetCoreCommandLineFoundImage",
found ? GettextCatalog.GetString ("A Tick") : GettextCatalog.GetString ("A Cross"),
found ? GettextCatalog.GetString ("The .NET Core command line was found") : GettextCatalog.GetString ("The .NET Core command line was not found"));
@@ -171,6 +179,7 @@ namespace MonoDevelop.DotNetCore.Gui
class CustomFileSelector : Widget
{
TextEntry entry;
+ Button browseButton;
FileDialog dialog;
string currentFolder;
string title;
@@ -182,13 +191,21 @@ namespace MonoDevelop.DotNetCore.Gui
entry.Changed += EntryChanged;
box.PackStart (entry, true);
- var browseButton = new Button ("…");
+ browseButton = new Button ("…");
box.PackStart (browseButton);
browseButton.Clicked += BrowseButtonClicked;
Content = box;
}
+ internal TextEntry TextEntry {
+ get { return entry; }
+ }
+
+ internal Button BrowseButton {
+ get { return browseButton; }
+ }
+
public string CurrentFolder {
get {
return dialog != null ? dialog.CurrentFolder : currentFolder;
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreMSBuildProjectTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreMSBuildProjectTests.cs
index 75efb748ab..bd7cf6e50d 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreMSBuildProjectTests.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreMSBuildProjectTests.cs
@@ -88,11 +88,10 @@ namespace MonoDevelop.DotNetCore.Tests
"</Project>");
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
Assert.AreEqual ("15.0", project.ToolsVersion);
Assert.IsFalse (project.IsOutputTypeDefined);
- Assert.AreEqual ("Microsoft.NET.Sdk", project.Sdk);
Assert.IsTrue (project.HasSdk);
}
@@ -115,6 +114,24 @@ namespace MonoDevelop.DotNetCore.Tests
}
[Test]
+ public void ReadProject_ExplicityReferences ()
+ {
+ CreateMSBuildProject (
+ "<Project ToolsVersion=\"15.0\">\r\n" +
+ " <PropertyGroup>\r\n" +
+ " <OutputType>Exe</OutputType>\r\n" +
+ " <TargetFramework>netcoreapp1.0</TargetFramework>\r\n" +
+ " </PropertyGroup>\r\n" +
+ " <Import Sdk=\"Microsoft.NET.Sdk\" Project=\"Sdk.targets\" />" +
+ "</Project>");
+ msbuildProject.Evaluate ();
+
+ ReadProject ();
+
+ Assert.That (msbuildProject.GetReferencedSDKs (), Is.Not.Empty);
+ }
+
+ [Test]
public void WriteProject_ProjectGuidAddedAndToolsVersionChanged_ProjectGuidIsRemovedAndToolsVersionReset ()
{
CreateMSBuildProject (
@@ -313,7 +330,7 @@ namespace MonoDevelop.DotNetCore.Tests
" </PropertyGroup>\r\n" +
"</Project>");
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
msbuildProject.ToolsVersion = "4.0";
WriteProject ();
@@ -332,7 +349,7 @@ namespace MonoDevelop.DotNetCore.Tests
" </PropertyGroup>\r\n" +
"</Project>");
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
var projectReferenceItem = msbuildProject.AddNewItem ("ProjectReference", @"Lib\Lib.csproj");
projectReferenceItem.Metadata.SetValue ("Name", "Lib");
projectReferenceItem.Metadata.SetValue ("Project", "{F109E7DF-F561-4CD6-A46E-CFB27A8B6F2C}");
@@ -359,7 +376,7 @@ namespace MonoDevelop.DotNetCore.Tests
"</Project>");
msbuildProject.Evaluate ();
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
WriteProject (".NETCoreApp,Version=v1.1");
@@ -380,7 +397,7 @@ namespace MonoDevelop.DotNetCore.Tests
"</Project>");
msbuildProject.Evaluate ();
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
WriteProject (".NETCoreApp,Version=v1.1");
WriteProject (".NETCoreApp,Version=v1.0");
@@ -402,7 +419,7 @@ namespace MonoDevelop.DotNetCore.Tests
"</Project>");
msbuildProject.Evaluate ();
ReadProject (".NET Standard,Version=v1.0");
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
WriteProject (".NETStandard,Version=v1.6");
@@ -423,7 +440,7 @@ namespace MonoDevelop.DotNetCore.Tests
"</Project>");
msbuildProject.Evaluate ();
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
WriteProject (".NETFramework,Version=v4.6");
@@ -444,7 +461,7 @@ namespace MonoDevelop.DotNetCore.Tests
"</Project>");
msbuildProject.Evaluate ();
ReadProject ();
- project.Sdk = "Microsoft.NET.Sdk";
+ project.HasSdk = true;
WriteProject (".NETCoreApp,Version=v1.1");
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreMSBuildProject.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreMSBuildProject.cs
index da870db57f..0034e373fd 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreMSBuildProject.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreMSBuildProject.cs
@@ -45,24 +45,14 @@ namespace MonoDevelop.DotNetCore
public string ToolsVersion { get; private set; }
public bool IsOutputTypeDefined { get; private set; }
- public string Sdk { get; set; }
- public IEnumerable<string> TargetFrameworks {
- get { return targetFrameworks; }
- }
+ public IEnumerable<string> TargetFrameworks => targetFrameworks;
- public bool HasSdk {
- get { return Sdk != null; }
- }
+ public bool HasSdk { get; set; }
- public bool HasToolsVersion ()
- {
- return !string.IsNullOrEmpty (ToolsVersion);
- }
+ public bool HasToolsVersion () => !string.IsNullOrEmpty (ToolsVersion);
- public CompileTarget DefaultCompileTarget {
- get { return defaultCompileTarget; }
- }
+ public CompileTarget DefaultCompileTarget => defaultCompileTarget;
/// <summary>
/// Ensure MSBuildProject has ToolsVersion set to 15.0 so the correct
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs
index 92872f158b..d51f3c8538 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreProjectExtension.cs
@@ -93,7 +93,7 @@ namespace MonoDevelop.DotNetCore
/// </summary>
bool IsSdkProject (DotNetProject project)
{
- return project.MSBuildProject.GetReferencedSDKs ().Any ();
+ return project.MSBuildProject.GetReferencedSDKs ().Length > 0;
}
protected override bool OnGetCanReferenceProject (DotNetProject targetProject, out string reason)
@@ -409,7 +409,12 @@ namespace MonoDevelop.DotNetCore
if (ProjectNeedsRestore ()) {
return CreateNuGetRestoreRequiredBuildResult ();
}
- if ((HasSdk && !IsDotNetCoreSdkInstalled ()) || (HasSdk && sdkPaths.IsUnsupportedSdkVersion)) {
+
+ if (!Project.TargetFramework.Id.IsNetStandardOrNetCoreApp ()) {
+ return null;
+ }
+
+ if ((HasSdk && !IsDotNetCoreSdkInstalled ()) || (sdkPaths != null && sdkPaths.IsUnsupportedSdkVersion)) {
return CreateDotNetCoreSdkRequiredBuildResult ();
}
return null;
@@ -468,13 +473,10 @@ namespace MonoDevelop.DotNetCore
protected override void OnBeginLoad ()
{
- dotNetCoreMSBuildProject.Sdk = Project.MSBuildProject.Sdk;
base.OnBeginLoad ();
}
- public bool HasSdk {
- get { return dotNetCoreMSBuildProject.HasSdk; }
- }
+ public bool HasSdk => Project.MSBuildProject.GetReferencedSDKs ().Length > 0;
protected bool IsWebProject (DotNetProject project)
{
@@ -491,10 +493,11 @@ namespace MonoDevelop.DotNetCore
if (!HasSdk)
return;
-
- sdkPaths = DotNetCoreSdk.FindSdkPaths (dotNetCoreMSBuildProject.Sdk);
- }
+ var referencedSdks = project.GetReferencedSDKs ();
+ sdkPaths = DotNetCoreSdk.FindSdkPaths (referencedSdks);
+ dotNetCoreMSBuildProject.HasSdk = referencedSdks.Length > 0;
+ }
protected override async Task<ImmutableArray<ProjectFile>> OnGetSourceFiles (ProgressMonitor monitor, ConfigurationSelector configuration)
{
var sourceFiles = await base.OnGetSourceFiles (monitor, configuration);
@@ -608,7 +611,14 @@ namespace MonoDevelop.DotNetCore
bool IsFSharpSdkProject ()
{
- return HasSdk && dotNetCoreMSBuildProject.Sdk.Contains ("FSharp");
+ if (HasSdk) {
+ var sdks = Project.MSBuildProject.GetReferencedSDKs ();
+ for (var i = 0; i < sdks.Length; i++) {
+ if (sdks [i].Contains ("FSharp"))
+ return true;
+ }
+ }
+ return false;
}
/// <summary>
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs
index df0ef2a820..3da4bca039 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdk.cs
@@ -82,9 +82,9 @@ namespace MonoDevelop.DotNetCore
{
}
- internal static DotNetCoreSdkPaths FindSdkPaths (string sdk)
+ internal static DotNetCoreSdkPaths FindSdkPaths (string[] sdks)
{
- sdkPaths.FindSdkPaths (sdk);
+ sdkPaths.FindSdkPaths (sdks);
return sdkPaths;
}
diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdkPaths.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdkPaths.cs
index 87122fbd1a..b41d895b9c 100644
--- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdkPaths.cs
+++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreSdkPaths.cs
@@ -119,12 +119,12 @@ namespace MonoDevelop.DotNetCore
IsUnsupportedSdkVersion = false;
}
- public void FindSdkPaths (string sdk)
+ public void FindSdkPaths (string [] sdks)
{
if (string.IsNullOrEmpty (MSBuildSDKsPath))
return;
- Exist = CheckSdksExist (sdk);
+ Exist = CheckSdksExist (sdks);
if (Exist) {
IsUnsupportedSdkVersion = !CheckIsSupportedSdkVersion (SdksParentDirectory);
@@ -149,18 +149,13 @@ namespace MonoDevelop.DotNetCore
string SdksParentDirectory { get; set; }
- static IEnumerable<string> SplitSdks (string sdk) => sdk.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
-
- bool CheckSdksExist (string sdk)
+ bool CheckSdksExist (string[] sdks)
{
- if (sdk.Contains (';')) {
- foreach (string sdkItem in SplitSdks (sdk)) {
- if (!SdkPathExists (sdkItem))
- return false;
- }
- return true;
+ foreach (string sdkItem in sdks) {
+ if (!SdkPathExists (sdkItem))
+ return false;
}
- return SdkPathExists (sdk);
+ return true;
}
bool SdkPathExists (string sdk)
@@ -238,10 +233,14 @@ namespace MonoDevelop.DotNetCore
using (var r = new StreamReader (GlobalJsonPath)) {
try {
var token = JObject.Parse (r.ReadToEnd ());
- if (token == null)
- return string.Empty;
- var version = (string)token.SelectToken ("sdk").SelectToken ("version");
- return version;
+
+ if (token != null && token.TryGetValue ("sdk", out var sdkToken)) {
+ var version = sdkToken ["version"];
+ if (version != null)
+ return version.Value<string>();
+ }
+
+ return string.Empty;
} catch (Exception e) {
LoggingService.LogWarning ($"Unable to parse {GlobalJsonPath}.", e);
return string.Empty;
diff --git a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs
index 1616424340..2df3434088 100644
--- a/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs
+++ b/main/src/addins/MonoDevelop.GtkCore/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs
@@ -14,7 +14,7 @@ using MonoDevelop.Components;
namespace MonoDevelop.GtkCore.GuiBuilder
{
- public class ToolboxProvider: IToolboxDynamicProvider, IToolboxDefaultProvider
+ public class ToolboxProvider: IToolboxDynamicProvider, IToolboxDefaultProvider, IToolboxDynamicProviderDeleteSupport
{
internal static ToolboxProvider Instance;
@@ -82,7 +82,11 @@ namespace MonoDevelop.GtkCore.GuiBuilder
{
yield return typeof(Stetic.Wrapper.Widget).Assembly.Location;
}
-
+
+ public virtual bool DeleteDynamicItem (ItemToolboxNode node) => false;
+
+ public virtual bool CanDeleteDynamicItem (ItemToolboxNode node) => false;
+
public event EventHandler ItemsChanged;
}
diff --git a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditor.cs b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditor.cs
index bdea66542d..c6bf1290fc 100644
--- a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditor.cs
+++ b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditor.cs
@@ -37,6 +37,8 @@ using Xwt;
using Mono.MHex.Data;
using Mono.MHex.Rendering;
using Xwt.Drawing;
+using MonoDevelop.Components.AtkCocoaHelper;
+using MonoDevelop.Core;
namespace Mono.MHex
{
@@ -99,8 +101,14 @@ namespace Mono.MHex
}
}
+ public bool IsReadOnly { get; set; }
+
+ readonly Gtk.Widget hexWidget;
+
public HexEditor ()
{
+ hexWidget = (Gtk.Widget)Xwt.Toolkit.CurrentEngine.GetNativeWidget (this);
+
BackgroundColor = Color.FromBytes (0, 0, 0);
CanGetFocus = true;
HexEditorData = new HexEditorData ();
@@ -112,6 +120,7 @@ namespace Mono.MHex
if (HexEditorData.Caret.AutoScrollToCaret)
ScrollToCaret ();
RepaintLine (HexEditorData.Caret.Line);
+ AnnounceCurrentSelection ();
};
HexEditorData.Caret.OffsetChanged += delegate(object sender, CaretLocationEventArgs e) {
if (!HexEditorData.Caret.PreserveSelection)
@@ -516,6 +525,17 @@ namespace Mono.MHex
requestResetCaretBlink = true;
}
+ void AnnounceCurrentSelection ()
+ {
+ try {
+ var character = HexEditorData.Bytes [HexEditorData.Caret.Offset];
+ var data = Convert.ToString (character, 16);
+ var message = GettextCatalog.GetString ("Selected '{0}' char:'{1}'", data [HexEditorData.Caret.SubPosition], (char)character);
+ hexWidget.Accessible.MakeAccessibilityAnnouncement (message);
+ } catch {
+ }
+ }
+
public void DrawCaret (Context ctx, Rectangle area)
{
if (!caretBlink || HexEditorData.IsSomethingSelected)
diff --git a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditorDebugger.cs b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditorDebugger.cs
index 28bac51da9..68e508820b 100644
--- a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditorDebugger.cs
+++ b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/HexEditorDebugger.cs
@@ -80,6 +80,8 @@ namespace Mono.MHex
comboBox.Items.Add ("Hex 16");
comboBox.SelectedIndex = 0;
editor.Options.StringRepresentationType = StringRepresentationTypes.ASCII;
+ editor.Accessible.Label = GettextCatalog.GetString ("Hexadecimal Text Editor");
+
comboBox.SelectionChanged += delegate {
switch (comboBox.SelectedIndex) {
case 0:
diff --git a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/SimpleEditMode.cs b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/SimpleEditMode.cs
index 6b16f35e5b..29db8e9ab0 100644
--- a/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/SimpleEditMode.cs
+++ b/main/src/addins/MonoDevelop.HexEditor/Mono.MHex/SimpleEditMode.cs
@@ -184,8 +184,10 @@ namespace Mono.MHex
keyBindings [keyCode] (HexEditorData);
return;
}
-
- InsertCharacter (unicodeChar);
+
+ if (!Editor.IsReadOnly) {
+ InsertCharacter (unicodeChar);
+ }
}
void InsertCharacter (uint unicodeChar)
diff --git a/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs b/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs
index 7897809fdd..40c0f444db 100644
--- a/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs
+++ b/main/src/addins/MonoDevelop.HexEditor/MonoDevelop.HexEditor/HexEditorVisualizer.cs
@@ -130,7 +130,7 @@ namespace MonoDevelop.HexEditor
}
hexEditor.HexEditorData.Buffer = buffer;
- hexEditor.Editor.Sensitive = CanEdit (val);
+ hexEditor.Editor.IsReadOnly = !CanEdit (val);
var xwtScrollView = new Xwt.ScrollView (hexEditor);
var scrollWidget = (Widget) Xwt.Toolkit.CurrentEngine.GetNativeWidget (xwtScrollView);
diff --git a/main/src/addins/MonoDevelop.Packaging/Gui/MonoDevelop.Packaging.Gui.GtkNuGetPackageMetadataOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.Packaging/Gui/MonoDevelop.Packaging.Gui.GtkNuGetPackageMetadataOptionsPanelWidget.cs
index 49a3bd30d5..7af75f47b5 100644
--- a/main/src/addins/MonoDevelop.Packaging/Gui/MonoDevelop.Packaging.Gui.GtkNuGetPackageMetadataOptionsPanelWidget.cs
+++ b/main/src/addins/MonoDevelop.Packaging/Gui/MonoDevelop.Packaging.Gui.GtkNuGetPackageMetadataOptionsPanelWidget.cs
@@ -48,7 +48,7 @@ namespace MonoDevelop.Packaging.Gui
private global::Gtk.HBox packageLanguageHBox;
- private global::Gtk.ComboBoxEntry packageLanguageComboBox;
+ private global::Gtk.ComboBox packageLanguageComboBox;
private global::Gtk.Label packageLanguageLabel;
@@ -321,7 +321,7 @@ namespace MonoDevelop.Packaging.Gui
this.packageLanguageHBox.Name = "packageLanguageHBox";
this.packageLanguageHBox.Spacing = 6;
// Container child packageLanguageHBox.Gtk.Box+BoxChild
- this.packageLanguageComboBox = global::Gtk.ComboBoxEntry.NewText();
+ this.packageLanguageComboBox = global::Gtk.ComboBox.NewText();
this.packageLanguageComboBox.Name = "packageLanguageComboBox";
this.packageLanguageHBox.Add(this.packageLanguageComboBox);
global::Gtk.Box.BoxChild w19 = ((global::Gtk.Box.BoxChild)(this.packageLanguageHBox[this.packageLanguageComboBox]));
diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs
index 3f6f091de5..8e2ab47e58 100644
--- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs
+++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkNuGetPackageMetadataOptionsPanelWidget.cs
@@ -42,6 +42,8 @@ namespace MonoDevelop.Packaging.Gui
NuGetPackageMetadata metadata;
bool projectOriginallyHadMetadata;
bool hasPackageId;
+ List<CultureInfo> languages;
+ ListStore languagesListStore;
public GtkNuGetPackageMetadataOptionsPanelWidget ()
{
@@ -58,85 +60,68 @@ namespace MonoDevelop.Packaging.Gui
packageReleaseNotesPaddingLabel.Accessible.Role = Atk.Role.Filler;
packageIdTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.ID",
- GettextCatalog.GetString ("ID"),
- GettextCatalog.GetString ("Enter the ID of the NuGet package"));
- packageIdTextBox.SetAccessibilityLabelRelationship (packageIdLabel);
+ packageIdLabel,
+ GettextCatalog.GetString ("Enter the ID of the NuGet package"));
packageVersionTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Version",
- GettextCatalog.GetString ("Version"),
- GettextCatalog.GetString ("Enter the version of the NuGet package"));
- packageVersionTextBox.SetAccessibilityLabelRelationship (packageVersionLabel);
+ packageVersionLabel,
+ GettextCatalog.GetString ("Enter the version of the NuGet package"));
packageAuthorsTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Authors",
- GettextCatalog.GetString ("Authors"),
- GettextCatalog.GetString ("Enter the authors of the NuGet package"));
- packageAuthorsTextBox.SetAccessibilityLabelRelationship (packageAuthorsLabel);
+ packageAuthorsLabel,
+ GettextCatalog.GetString ("Enter the authors of the NuGet package"));
packageDescriptionTextView.SetCommonAccessibilityAttributes ("NuGetMetadata.Description",
- GettextCatalog.GetString ("Description"),
- GettextCatalog.GetString ("Enter the description of the NuGet package"));
- packageDescriptionTextView.SetAccessibilityLabelRelationship (packageDescriptionLabel);
+ packageDescriptionLabel,
+ GettextCatalog.GetString ("Enter the description of the NuGet package"));
packageOwnersTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Owners",
- GettextCatalog.GetString ("Owners"),
- GettextCatalog.GetString ("Enter the owners of the NuGet package"));
- packageOwnersTextBox.SetAccessibilityLabelRelationship (packageOwnersLabel);
+ packageOwnersLabel,
+ GettextCatalog.GetString ("Enter the owners of the NuGet package"));
packageCopyrightTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Copyright",
- GettextCatalog.GetString ("Copyright"),
- GettextCatalog.GetString ("Enter the copyright statement for the NuGet package"));
- packageCopyrightTextBox.SetAccessibilityLabelRelationship (packageCopyrightLabel);
+ packageCopyrightLabel,
+ GettextCatalog.GetString ("Enter the copyright statement for the NuGet package"));
packageTitleTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Title",
- GettextCatalog.GetString ("Title"),
- GettextCatalog.GetString ("Enter the title of the NuGet package"));
- packageTitleTextBox.SetAccessibilityLabelRelationship (packageTitleLabel);
+ packageTitleLabel,
+ GettextCatalog.GetString ("Enter the title of the NuGet package"));
packageSummaryTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Summary",
- GettextCatalog.GetString ("Summary"),
- GettextCatalog.GetString ("Enter the summary for the NuGet package"));
- packageSummaryTextBox.SetAccessibilityLabelRelationship (packageSummaryLabel);
+ packageSummaryLabel,
+ GettextCatalog.GetString ("Enter the summary for the NuGet package"));
packageProjectUrlTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.URL",
- GettextCatalog.GetString ("Project URL"),
- GettextCatalog.GetString ("Enter the project URL for the NuGet package"));
- packageProjectUrlTextBox.SetAccessibilityLabelRelationship (packageProjectUrlLabel);
+ packageProjectUrlLabel,
+ GettextCatalog.GetString ("Enter the project URL for the NuGet package"));
packageIconUrlTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Icon",
- GettextCatalog.GetString ("Icon URL"),
- GettextCatalog.GetString ("Enter the URL for the NuGet package's icon"));
- packageIconUrlTextBox.SetAccessibilityLabelRelationship (packageIconUrlLabel);
+ packageIconUrlLabel,
+ GettextCatalog.GetString ("Enter the URL for the NuGet package's icon"));
packageLicenseUrlTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.licence",
- GettextCatalog.GetString ("License URL"),
- GettextCatalog.GetString ("Enter the URL for the NuGet package's license"));
- packageLicenseUrlTextBox.SetAccessibilityLabelRelationship (packageLicenseUrlLabel);
+ packageLicenseUrlLabel,
+ GettextCatalog.GetString ("Enter the URL for the NuGet package's license"));
packageRequireLicenseAcceptanceCheckBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Acceptance",
- GettextCatalog.GetString ("Require License Acceptance"),
- GettextCatalog.GetString ("Check to require the user to accept the NuGet package's license"));
- packageRequireLicenseAcceptanceCheckBox.SetAccessibilityLabelRelationship (packageRequireLicenseAcceptanceLabel);
+ packageRequireLicenseAcceptanceLabel,
+ GettextCatalog.GetString ("Check to require the user to accept the NuGet package's license"));
packageDevelopmentDependencyCheckBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Development",
- GettextCatalog.GetString ("Development Dependency"),
- GettextCatalog.GetString ("Check to indicate that this is a development dependency"));
- packageDevelopmentDependencyCheckBox.SetAccessibilityLabelRelationship (packageDevelopmentDependencyLabel);
+ packageDevelopmentDependencyLabel,
+ GettextCatalog.GetString ("Check to indicate that this is a development dependency"));
packageTagsTextBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Tags",
- GettextCatalog.GetString ("Tags"),
- GettextCatalog.GetString ("Enter the tags for this NuGet package"));
- packageTagsTextBox.SetAccessibilityLabelRelationship (packageTagsLabel);
+ packageTagsLabel,
+ GettextCatalog.GetString ("Enter the tags for this NuGet package"));
packageLanguageComboBox.SetCommonAccessibilityAttributes ("NuGetMetadata.Language",
- GettextCatalog.GetString ("Language"),
- GettextCatalog.GetString ("Select the language for this NuGet package"));
- packageLanguageComboBox.SetAccessibilityLabelRelationship (packageLanguageLabel);
+ packageLanguageLabel,
+ GettextCatalog.GetString ("Select the language for this NuGet package"));
packageReleaseNotesTextView.SetCommonAccessibilityAttributes ("NuGetMetadata.ReleaseNotes",
- GettextCatalog.GetString ("Release Notes"),
- GettextCatalog.GetString ("Enter the release notes for this NuGet package"));
- packageReleaseNotesTextView.SetAccessibilityLabelRelationship (packageReleaseNotesLabel);
-
+ packageReleaseNotesLabel,
+ GettextCatalog.GetString ("Enter the release notes for this NuGet package"));
}
internal static System.Action<bool> OnProjectHasMetadataChanged;
@@ -168,7 +153,7 @@ namespace MonoDevelop.Packaging.Gui
packageCopyrightTextBox.Text = GetTextBoxText (metadata.Copyright);
packageDevelopmentDependencyCheckBox.Active = metadata.DevelopmentDependency;
packageIconUrlTextBox.Text = GetTextBoxText (metadata.IconUrl);
- packageLanguageComboBox.Entry.Text = GetTextBoxText (metadata.Language);
+ LoadLanguage (metadata.Language);
packageLicenseUrlTextBox.Text = GetTextBoxText (metadata.LicenseUrl);
packageOwnersTextBox.Text = GetTextBoxText (metadata.Owners);
packageProjectUrlTextBox.Text = GetTextBoxText (metadata.ProjectUrl);
@@ -184,6 +169,35 @@ namespace MonoDevelop.Packaging.Gui
return text ?? string.Empty;
}
+ void LoadLanguage (string language)
+ {
+ if (string.IsNullOrEmpty (language)) {
+ packageLanguageComboBox.Active = 0;
+ return;
+ }
+
+ int index = GetLanguageIndex (language);
+ if (index >= 0) {
+ packageLanguageComboBox.Active = index + 1;
+ return;
+ }
+
+ // Language does not match so we need to add it to the combo box.
+ TreeIter iter = languagesListStore.AppendValues (language);
+ packageLanguageComboBox.SetActiveIter (iter);
+ }
+
+ int GetLanguageIndex (string language)
+ {
+ for (int i = 0; i < languages.Count; ++i) {
+ CultureInfo culture = languages [i];
+ if (string.Equals (culture.Name, language, StringComparison.OrdinalIgnoreCase)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
internal void Save (PackagingProject project)
{
UpdateMetadata ();
@@ -220,7 +234,7 @@ namespace MonoDevelop.Packaging.Gui
metadata.Copyright = packageCopyrightTextBox.Text;
metadata.DevelopmentDependency = packageDevelopmentDependencyCheckBox.Active;
metadata.IconUrl = packageIconUrlTextBox.Text;
- metadata.Language = packageLanguageComboBox.Entry.Text;
+ metadata.Language = GetSelectedLanguage ();
metadata.LicenseUrl = packageLicenseUrlTextBox.Text;
metadata.Owners = packageOwnersTextBox.Text;
metadata.ProjectUrl = packageProjectUrlTextBox.Text;
@@ -231,20 +245,49 @@ namespace MonoDevelop.Packaging.Gui
metadata.Title = packageTitleTextBox.Text;
}
+ string GetSelectedLanguage ()
+ {
+ if (packageLanguageComboBox.Active == 0) {
+ // 'None' selected.
+ return string.Empty;
+ }
+
+ int languageIndex = packageLanguageComboBox.Active - 1;
+ if (languageIndex < languages.Count) {
+ return languages [languageIndex].Name;
+ }
+
+ // No match for language so just return the combo box text.
+ return packageLanguageComboBox.ActiveText;
+ }
+
void PopulateLanguages ()
{
- var languagesListStore = new ListStore (typeof (string));
+ languagesListStore = new ListStore (typeof (string));
packageLanguageComboBox.Model = languagesListStore;
- List<string> languages = CultureInfo.GetCultures(CultureTypes.AllCultures)
- .Select (c => c.Name)
- .ToList ();
+ languages = new List<CultureInfo> ();
- languages.Sort ();
+ foreach (CultureInfo culture in CultureInfo.GetCultures (CultureTypes.AllCultures)) {
+ if (!string.IsNullOrEmpty (culture.Name)) {
+ languages.Add (culture);
+ }
+ }
- foreach (string language in languages) {
- languagesListStore.AppendValues (language);
+ languages.Sort (CompareLanguages);
+
+ languagesListStore.AppendValues (GettextCatalog.GetString ("None"));
+
+ foreach (CultureInfo language in languages) {
+ languagesListStore.AppendValues (language.DisplayName);
}
+
+ packageLanguageComboBox.Active = 0;
+ }
+
+ static int CompareLanguages (CultureInfo x, CultureInfo y)
+ {
+ return string.Compare (x.DisplayName, y.DisplayName, StringComparison.CurrentCulture);
}
bool ProjectHasMetadata ()
diff --git a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkProjectNuGetBuildOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkProjectNuGetBuildOptionsPanelWidget.cs
index 3645bd12ac..38468f2f14 100644
--- a/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkProjectNuGetBuildOptionsPanelWidget.cs
+++ b/main/src/addins/MonoDevelop.Packaging/MonoDevelop.Packaging.Gui/GtkProjectNuGetBuildOptionsPanelWidget.cs
@@ -44,9 +44,13 @@ namespace MonoDevelop.Packaging.Gui
SetupAccessibility ();
}
- void SetupAccessibility ()
+ void SetupAccessibility (bool includeMissingMetadataLabelText = false)
{
- packOnBuildButton.SetCommonAccessibilityAttributes ("NugetBuildOptionsPanel.PackOnBuild", "",
+ string accessibilityLabel = packOnBuildButton.Label;
+ if (includeMissingMetadataLabelText) {
+ accessibilityLabel += " " + missingMetadataLabel.Text;
+ }
+ packOnBuildButton.SetCommonAccessibilityAttributes ("NugetBuildOptionsPanel.PackOnBuild", accessibilityLabel,
GettextCatalog.GetString ("Check to create a NuGet package when building"));
}
@@ -73,10 +77,15 @@ namespace MonoDevelop.Packaging.Gui
void UpdateMissingMetadataLabelVisibility ()
{
- if (packOnBuildButton.Active) {
- missingMetadataLabel.Visible = !ProjectHasMetadata;
+ bool visible = packOnBuildButton.Active && !ProjectHasMetadata;
+ missingMetadataLabel.Visible = visible;
+
+ // Refresh accessibility information so missing metadata label text is available to Voice Over
+ // when the check box is selected.
+ if (visible) {
+ SetupAccessibility (includeMissingMetadataLabelText: true);
} else {
- missingMetadataLabel.Visible = false;
+ SetupAccessibility ();
}
}
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 4d246a48f9..2461c716ba 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs
@@ -92,16 +92,24 @@ namespace MonoDevelop.AnalysisCore.Gui
diagService.DiagnosticsUpdated -= OnDiagnosticsUpdated;
CancelUpdateTimout ();
AnalysisOptions.AnalysisEnabled.Changed -= AnalysisOptionsChanged;
- foreach (var queue in markers) {
- foreach (var marker in queue.Value)
- Editor.RemoveMarker (marker);
- }
+ RemoveAllMarkers ();
disposed = true;
base.Dispose ();
}
+
+ void RemoveAllMarkers ()
+ {
+ foreach (var markerQueue in markers) {
+ foreach (var marker in markerQueue.Value) {
+ Editor.RemoveMarker (marker);
+ }
+ PutBackCachedList (markerQueue.Value);
+ }
+ markers.Clear ();
+ }
bool enabled;
-
+
public bool Enabled {
get { return enabled; }
set {
@@ -247,40 +255,39 @@ namespace MonoDevelop.AnalysisCore.Gui
}
}
+ const int MaxCacheSize = 10;
+ Queue<List<IGenericTextSegmentMarker>> listCache = new Queue<List<IGenericTextSegmentMarker>> ();
+
+ List<IGenericTextSegmentMarker> GetCachedList ()
+ {
+ if (listCache.Count == 0)
+ return new List<IGenericTextSegmentMarker> ();
+ return listCache.Dequeue ();
+ }
+
+ void PutBackCachedList (List<IGenericTextSegmentMarker> list)
+ {
+ list.Clear ();
+ if (listCache.Count < MaxCacheSize)
+ listCache.Enqueue (list);
+ }
- class ResultsUpdater
+ class ResultsUpdater
{
readonly ResultsEditorExtension ext;
readonly CancellationToken cancellationToken;
-
+
//the number of markers at the head of the queue that need tp be removed
int oldMarkerIndex;
- readonly List<IGenericTextSegmentMarker> oldMarkers;
+ List<IGenericTextSegmentMarker> oldMarkers;
int curResult = 0;
IReadOnlyList<Result> results;
- private List<IGenericTextSegmentMarker> newMarkers;
+ List<IGenericTextSegmentMarker> newMarkers;
ImmutableArray<QuickTask>.Builder builder;
object id;
- const int MaxCacheSize = 200;
- readonly static Queue<List<IGenericTextSegmentMarker>> listCache = new Queue<List<IGenericTextSegmentMarker>> ();
-
- static List<IGenericTextSegmentMarker> GetCachedList ()
- {
- if (listCache.Count == 0)
- return new List<IGenericTextSegmentMarker> ();
- return listCache.Dequeue ();
- }
-
- static void PutBackCachedList (List<IGenericTextSegmentMarker> list)
- {
- list.Clear ();
- if (listCache.Count < MaxCacheSize)
- listCache.Enqueue (list);
- }
-
public ResultsUpdater (ResultsEditorExtension ext, IReadOnlyList<Result> results, object resultsId, CancellationToken cancellationToken)
{
if (ext == null)
@@ -292,13 +299,13 @@ namespace MonoDevelop.AnalysisCore.Gui
this.cancellationToken = cancellationToken;
if (resultsId != null) {
- if (!ext.markers.TryGetValue (id, out oldMarkers))
- ext.markers [id] = oldMarkers = GetCachedList ();
+ ext.markers.TryGetValue (id, out oldMarkers);
}
builder = ImmutableArray<QuickTask>.Empty.ToBuilder ();
this.results = results;
- newMarkers = GetCachedList ();
+ newMarkers = ext.GetCachedList ();
+ Debug.Assert (newMarkers != null);
}
public void Update ()
@@ -341,88 +348,99 @@ namespace MonoDevelop.AnalysisCore.Gui
//in order to to block the GUI thread, we batch them in UPDATE_COUNT
bool IdleHandler ()
{
- if (cancellationToken.IsCancellationRequested)
- return false;
- var editor = ext.Editor;
- if (editor == null)
- return false;
- if (id == null) {
- foreach (var markerQueue in ext.markers) {
- foreach (var marker in markerQueue.Value) {
- editor.RemoveMarker (marker);
- }
- PutBackCachedList (markerQueue.Value);
+ try {
+ var editor = ext.Editor;
+ if (editor == null)
+ return false;
+ if (id == null) {
+ ext.RemoveAllMarkers ();
+ lock (ext.tasks)
+ ext.tasks.Clear ();
+ ext.OnTasksUpdated (EventArgs.Empty);
+ return false;
}
- ext.markers.Clear ();
- }
- if (id == null) {
- lock (ext.tasks)
- ext.tasks.Clear ();
- ext.OnTasksUpdated (EventArgs.Empty);
- return false;
- }
-
- //clear the old results out at the same rate we add in the new ones
- for (int i = 0; oldMarkerIndex < oldMarkers.Count && i < UPDATE_COUNT; i++) {
- if (cancellationToken.IsCancellationRequested)
+ if (cancellationToken.IsCancellationRequested) {
+ FinishUpdateRun ();
return false;
- var oldMarker = oldMarkers [oldMarkerIndex++];
-
- if (curResult < results.Count && results [curResult].Equals ((Result)oldMarker.Tag, oldMarker.Offset)) {
- oldMarker.Tag = results [curResult];
- newMarkers.Add (oldMarker);
- curResult++;
- continue;
}
- editor.RemoveMarker (oldMarker);
- }
- //add in the new markers
- for (int i = 0; i < UPDATE_COUNT; i++) {
- if (curResult >= results.Count) {
- lock (ext.tasks)
- ext.tasks [id] = builder.ToImmutable ();
- ext.OnTasksUpdated (EventArgs.Empty);
- // remove remaining old markers
- while (oldMarkerIndex < oldMarkers.Count) {
- editor.RemoveMarker (oldMarkers[oldMarkerIndex]);
- oldMarkerIndex++;
+ //clear the old results out at the same rate we add in the new ones
+ if (oldMarkers != null) {
+ for (int i = 0; oldMarkerIndex < oldMarkers.Count && i < UPDATE_COUNT; i++) {
+ var oldMarker = oldMarkers [oldMarkerIndex++];
+
+ var oldResult = (Result)oldMarker.Tag;
+ if (oldResult != null && curResult < results.Count) {
+ Result currentResult = results [curResult];
+ if (currentResult.Equals (oldResult, oldMarker.Offset)) {
+ oldMarker.Tag = currentResult;
+ newMarkers.Add (oldMarker);
+ if (oldResult.QuickTask != null) {
+ currentResult.QuickTask = oldResult.QuickTask;
+ builder.Add (currentResult.QuickTask);
+ }
+ curResult++;
+ continue;
+ }
+ }
+ editor.RemoveMarker (oldMarker);
}
-
- PutBackCachedList (ext.markers [id]);
- ext.markers [id] = newMarkers;
-
- return false;
}
- if (cancellationToken.IsCancellationRequested)
- return false;
- var currentResult = results [curResult++];
- if (currentResult.InspectionMark != IssueMarker.None) {
- int start = currentResult.Region.Start;
- int end = currentResult.Region.End;
- if (start > end)
- continue;
-
- // In case a diagnostic has a 0 length span, force it to 1.
- if (start == end)
- end = end + 1;
-
- var marker = TextMarkerFactory.CreateGenericTextSegmentMarker (editor, GetSegmentMarkerEffect (currentResult.InspectionMark), TextSegment.FromBounds (start, end));
- marker.Tag = currentResult;
- marker.IsVisible = currentResult.Underline;
-
- if (currentResult.InspectionMark != IssueMarker.GrayOut) {
- marker.Color = GetColor (editor, currentResult);
- marker.IsVisible &= currentResult.Level != DiagnosticSeverity.Hidden;
+ //add in the new markers
+ for (int i = 0; i < UPDATE_COUNT; i++) {
+ if (curResult >= results.Count) {
+ FinishUpdateRun ();
+ return false;
+ }
+ var currentResult = results [curResult++];
+ if (currentResult.InspectionMark != IssueMarker.None) {
+ int start = currentResult.Region.Start;
+ int end = currentResult.Region.End;
+ if (start > end)
+ continue;
+
+ // In case a diagnostic has a 0 length span, force it to 1.
+ if (start == end)
+ end = end + 1;
+
+ var marker = TextMarkerFactory.CreateGenericTextSegmentMarker (editor, GetSegmentMarkerEffect (currentResult.InspectionMark), TextSegment.FromBounds (start, end));
+ marker.Tag = currentResult;
+ marker.IsVisible = currentResult.Underline;
+
+ if (currentResult.InspectionMark != IssueMarker.GrayOut) {
+ marker.Color = GetColor (editor, currentResult);
+ marker.IsVisible &= currentResult.Level != DiagnosticSeverity.Hidden;
+ }
+ editor.AddMarker (marker);
+ newMarkers.Add (marker);
}
- editor.AddMarker (marker);
- newMarkers.Add (marker);
+ builder.Add (currentResult.QuickTask = new QuickTask (currentResult.Message, currentResult.Region.Start, currentResult.Level));
+ }
+ return true;
+ } catch (Exception ex) {
+ LoggingService.LogInternalError ("Error while ResutsUpdater.IdleHandler", ex);
+ return false;
+ }
+ }
+
+ void FinishUpdateRun ()
+ {
+ var editor = ext.Editor;
+ // remove remaining old markers
+ if (oldMarkers != null) {
+ while (oldMarkerIndex < oldMarkers.Count) {
+ editor.RemoveMarker (oldMarkers [oldMarkerIndex]);
+ oldMarkerIndex++;
}
- builder.Add (new QuickTask (currentResult.Message, currentResult.Region.Start, currentResult.Level));
+ ext.PutBackCachedList (oldMarkers);
+ oldMarkers = null;
}
- return true;
+ ext.markers [id] = newMarkers;
+ lock (ext.tasks)
+ ext.tasks [id] = builder.ToImmutable ();
+ ext.OnTasksUpdated (EventArgs.Empty);
}
}
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs
index ae207cbf0d..3ed4732bc1 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs
@@ -27,6 +27,7 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
+using MonoDevelop.Ide.Editor.Extension;
namespace MonoDevelop.AnalysisCore
{
@@ -67,6 +68,7 @@ namespace MonoDevelop.AnalysisCore
public TextSpan Region { get; private set; }
public bool Underline { get; private set; }
+ public QuickTask QuickTask { get; internal set; }
internal bool Equals (Result other, int correctedOffset)
{
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs
index 69270698f2..fe9805aa9e 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewTooltipWindow.cs
@@ -353,7 +353,7 @@ namespace MonoDevelop.Refactoring
return;
}
- drawingLayout.SetMarkup (lineResult.TextMarkup);
+ drawingLayout.SetMarkup (lineResult.TextMarkup ?? "");
drawingLayout.GetPixelSize (out int w, out int h);
x = Math.Max (x, w);
y += lineHeight;
@@ -398,7 +398,7 @@ namespace MonoDevelop.Refactoring
{
using (var drawingLayout = new Pango.Layout (PangoContext)) {
drawingLayout.FontDescription = fontDescription;
- drawingLayout.SetMarkup (lineResult.TextMarkup);
+ drawingLayout.SetMarkup (lineResult.TextMarkup ?? "");
g.Save ();
g.Translate (textBorder, y);
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/IconMargin.cs b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/IconMargin.cs
index a0db793606..cfdd1730b0 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/IconMargin.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/IconMargin.cs
@@ -43,16 +43,21 @@ namespace Mono.TextEditor
public IconMargin (MonoTextEditor editor)
{
- this.editor = editor;
-
- editor.Document.MarkerAdded += OnMarkerAdded;
- editor.Document.MarkerRemoved += OnMarkerRemoved;
+ this.editor = editor;
+
+ if (IdeTheme.AccessibilityEnabled) {
+ editor.Document.MarkerAdded += OnMarkerAdded;
+ editor.Document.MarkerRemoved += OnMarkerRemoved;
+ markerToAccessible = new Dictionary<TextLineMarker, AccessibilityMarkerProxy> ();
+ }
}
public override void Dispose ()
{
- editor.Document.MarkerAdded -= OnMarkerAdded;
- editor.Document.MarkerRemoved -= OnMarkerRemoved;
+ if (IdeTheme.AccessibilityEnabled) {
+ editor.Document.MarkerAdded -= OnMarkerAdded;
+ editor.Document.MarkerRemoved -= OnMarkerRemoved;
+ }
if (markerToAccessible != null) {
foreach (var proxy in markerToAccessible.Values) {
@@ -187,44 +192,30 @@ namespace Mono.TextEditor
}
}
- Dictionary<TextLineMarker, AccessibilityMarkerProxy> markerToAccessible = null;
+ Dictionary<TextLineMarker, AccessibilityMarkerProxy> markerToAccessible;
+
void OnMarkerAdded (object sender, TextMarkerEvent e)
{
- if (!IdeTheme.AccessibilityEnabled) {
- return;
+ lock (markerToAccessible) {
+ var proxy = new AccessibilityMarkerProxy (e.TextMarker, editor, this);
+ Accessible.AddAccessibleChild (proxy.Accessible);
+ markerToAccessible [e.TextMarker] = proxy;
}
- if (markerToAccessible == null) {
- markerToAccessible = new Dictionary<TextLineMarker, AccessibilityMarkerProxy> ();
- }
-
- var proxy = new AccessibilityMarkerProxy (e.TextMarker, editor, this);
- Accessible.AddAccessibleChild (proxy.Accessible);
-
- markerToAccessible [e.TextMarker] = proxy;
-
if (focusMarkers != null) {
UpdateMarkers ();
- }
+ }
}
void OnMarkerRemoved (object sender, TextMarkerEvent e)
{
- if (!IdeTheme.AccessibilityEnabled) {
- return;
+ lock (markerToAccessible) {
+ if (!markerToAccessible.TryGetValue (e.TextMarker, out var proxy)) {
+ return;
+ }
+ Accessible.RemoveAccessibleChild (proxy.Accessible);
+ markerToAccessible.Remove (e.TextMarker);
}
-
- if (markerToAccessible == null) {
- return;
- }
-
- var proxy = markerToAccessible [e.TextMarker];
- if (proxy == null) {
- throw new Exception ("No accessible found for marker");
- }
-
- Accessible.RemoveAccessibleChild (proxy.Accessible);
- markerToAccessible.Remove (e.TextMarker);
if (focusMarkers != null) {
UpdateMarkers ();
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs
index 20f8c18b96..6cb5586a22 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/Mono.TextEditor/Gui/TextViewMargin.cs
@@ -670,18 +670,23 @@ namespace Mono.TextEditor
#if MAC
try {
lineHeight = System.Math.Ceiling (0.5 + OSXEditor.GetLineHeight(font.ToString ()));
+ if (lineHeight < 0)
+ lineHeight = GetLineHeight (metrics);
} catch (Exception e) {
LoggingService.LogError ("Error while getting the macOS font metrics for " + font, e);
- lineHeight = System.Math.Ceiling (0.5 + (metrics.Ascent + metrics.Descent) / Pango.Scale.PangoScale);
+ lineHeight = GetLineHeight (metrics);
}
#else
- lineHeight = System.Math.Ceiling(0.5 + (metrics.Ascent + metrics.Descent) / Pango.Scale.PangoScale);
+ lineHeight = GetLineHeight (metrics);
#endif
underlinePosition = metrics.UnderlinePosition;
underLineThickness = metrics.UnderlineThickness;
charWidth = metrics.ApproximateCharWidth / Pango.Scale.PangoScale;
}
}
+
+ static double GetLineHeight (Pango.FontMetrics metrics) => System.Math.Ceiling (0.5 + (metrics.Ascent + metrics.Descent) / Pango.Scale.PangoScale);
+
public override void Dispose ()
{
CancelCodeSegmentTooltip ();
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ClipboardRingService.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ClipboardRingService.cs
index 8b7b82c1c5..7267c06042 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ClipboardRingService.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/ClipboardRingService.cs
@@ -31,6 +31,7 @@ using MonoDevelop.Core;
using MonoDevelop.DesignerSupport.Toolbox;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui;
+using System.Linq;
namespace MonoDevelop.SourceEditor
{
@@ -102,6 +103,8 @@ namespace MonoDevelop.SourceEditor
return clipboardRing;
}
+ internal static bool DeleteItem (ItemToolboxNode node) => clipboardRing.Remove (node as ClipboardToolboxNode);
+
class ClipboardToolboxNode : ItemToolboxNode, ITextToolboxNode, ICustomTooltipToolboxNode
{
static readonly ToolboxItemFilterAttribute filterAtt = new ToolboxItemFilterAttribute ("text/plain", ToolboxItemFilterType.Allow);
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
index 844c92afd5..020f46d3bd 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs
@@ -66,7 +66,7 @@ using System.Collections.Immutable;
namespace MonoDevelop.SourceEditor
{
partial class SourceEditorView : ViewContent, IBookmarkBuffer, IClipboardHandler, ITextFile,
- ICompletionWidget2, ISplittable, IFoldable, IToolboxDynamicProvider,
+ ICompletionWidget2, ISplittable, IFoldable, IToolboxDynamicProvider, IToolboxDynamicProviderDeleteSupport,
ICustomFilteringToolboxConsumer, IZoomable, ITextEditorResolver, ITextEditorDataProvider,
ICodeTemplateHandler, ICodeTemplateContextProvider, IPrintable,
ITextEditorImpl, ITextMarkerFactory, IUndoHandler
@@ -3091,14 +3091,20 @@ namespace MonoDevelop.SourceEditor
string ITextEditorImpl.GetMarkup (int offset, int length, MarkupOptions options)
{
+ return GetMarkupAsync (offset, length, options, default).WaitAndGetResult (default);
+ }
+
+ public async Task<string> GetMarkupAsync (int offset, int length, MarkupOptions options, CancellationToken cancellationToken = default)
+ {
+ Runtime.AssertMainThread ();
var data = TextEditor.GetTextEditorData ();
switch (options.MarkupFormat) {
case MarkupFormat.Pango:
- return data.GetMarkup (offset, length, false, replaceTabs: false, fitIdeStyle: options.FitIdeStyle);
+ return await data.GetMarkupAsync (offset, length, false, replaceTabs: false, fitIdeStyle: options.FitIdeStyle, cancellationToken: cancellationToken);
case MarkupFormat.Html:
- return HtmlWriter.GenerateHtml (ClipboardColoredText.GetChunks (data, new TextSegment (offset, length)).WaitAndGetResult (default (System.Threading.CancellationToken)), data.ColorStyle, data.Options);
+ return HtmlWriter.GenerateHtml (await ClipboardColoredText.GetChunks (data, new TextSegment (offset, length), cancellationToken), data.ColorStyle, data.Options);
case MarkupFormat.RichText:
- return RtfWriter.GenerateRtf (ClipboardColoredText.GetChunks (data, new TextSegment (offset, length)).WaitAndGetResult (default (System.Threading.CancellationToken)), data.ColorStyle, data.Options);
+ return RtfWriter.GenerateRtf (await ClipboardColoredText.GetChunks (data, new TextSegment (offset, length), cancellationToken), data.ColorStyle, data.Options);
default:
throw new ArgumentOutOfRangeException ();
}
@@ -3393,6 +3399,10 @@ namespace MonoDevelop.SourceEditor
return TextEditor.GetLineHeight (line);
}
+ public bool DeleteDynamicItem (ItemToolboxNode node) => ClipboardRingService.DeleteItem (node);
+
+ public bool CanDeleteDynamicItem (ItemToolboxNode node) => ClipboardRingService.GetToolboxItems ().Contains (node);
+
public bool HasFocus {
get {
return this.TextEditor.HasFocus;
diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/ExternalTestRunner.cs b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/ExternalTestRunner.cs
index 51fa5342d2..2cbf788fe0 100644
--- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/ExternalTestRunner.cs
+++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/ExternalTestRunner.cs
@@ -48,6 +48,8 @@ namespace MonoDevelop.UnitTesting.NUnit.External
IRemoteEventListener listener;
readonly string assemblyDirectory;
+ public ProcessExecutionArchitecture ProcessExecutionArchitecture { get; set; }
+
public ExternalTestRunner ()
{
}
@@ -61,6 +63,7 @@ namespace MonoDevelop.UnitTesting.NUnit.External
{
var exePath = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), version.ToString (), "NUnitRunner.exe");
connection = new RemoteProcessConnection (exePath, assemblyDirectory, executionHandler, console, Runtime.MainSynchronizationContext);
+ connection.ProcessExecutionArchitecture = ProcessExecutionArchitecture;
connection.AddListener (this);
return connection.Connect ();
}
diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs
index b75a993743..5b3e57bbed 100644
--- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs
+++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/MonoDevelop.UnitTesting.NUnit/NUnitAssemblyTestSuite.cs
@@ -44,6 +44,7 @@ using System.Xml.Linq;
using System.Linq;
using System.Globalization;
using System.Threading.Tasks;
+using MonoDevelop.Core.Assemblies;
namespace MonoDevelop.UnitTesting.NUnit
{
@@ -333,6 +334,7 @@ namespace MonoDevelop.UnitTesting.NUnit
try {
if (File.Exists (ld.Path)) {
runner = new ExternalTestRunner (Path.GetDirectoryName (ld.Path));
+ runner.ProcessExecutionArchitecture = AssemblyUtilities.GetProcessExecutionArchitectureForAssembly (ld.Path);
runner.Connect (ld.NUnitVersion).Wait ();
var supportAssemblies = new List<string> (ld.SupportAssemblies.Result);
ld.Info = runner.GetTestInfo (ld.Path, supportAssemblies).Result;
@@ -398,6 +400,7 @@ namespace MonoDevelop.UnitTesting.NUnit
OperationConsoleFactory.CreateConsoleOptions.Default.WithTitle (GettextCatalog.GetString ("Unit Tests")));
ExternalTestRunner runner = new ExternalTestRunner (Path.GetDirectoryName (AssemblyPath));
+ runner.ProcessExecutionArchitecture = AssemblyUtilities.GetProcessExecutionArchitectureForAssembly (AssemblyPath);
runner.Connect (NUnitVersion, testContext.ExecutionContext.ExecutionHandler, console).Wait ();
LocalTestMonitor localMonitor = new LocalTestMonitor (testContext, test, suiteName, testName != null);
diff --git a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/ClipboardColoredText.cs b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/ClipboardColoredText.cs
index 4ecfda0278..1115115d51 100644
--- a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/ClipboardColoredText.cs
+++ b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor.Utils/ClipboardColoredText.cs
@@ -34,6 +34,7 @@ using MonoDevelop.Core.Text;
using MonoDevelop.Ide.Editor.Highlighting;
using System.Collections.Immutable;
using System.Threading.Tasks;
+using System.Threading;
namespace Mono.TextEditor.Utils
{
@@ -48,7 +49,7 @@ namespace Mono.TextEditor.Utils
this.Text = doc.GetTextAt (chunk);
}
- public static async Task<List<List<ClipboardColoredText>>> GetChunks (TextEditorData data, ISegment selectedSegment)
+ public static async Task<List<List<ClipboardColoredText>>> GetChunks (TextEditorData data, ISegment selectedSegment, CancellationToken cancellationToken = default)
{
int startLineNumber = data.OffsetToLineNumber (selectedSegment.Offset);
int endLineNumber = data.OffsetToLineNumber (selectedSegment.EndOffset);
@@ -59,7 +60,8 @@ namespace Mono.TextEditor.Utils
var chunks = await data.GetChunks (
line,
offset,
- length
+ length,
+ cancellationToken
);
copiedColoredChunks.Add (
chunks
diff --git a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Document/TextDocument.cs b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Document/TextDocument.cs
index 1fc96c57d8..4ac4cf29c3 100644
--- a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Document/TextDocument.cs
+++ b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Document/TextDocument.cs
@@ -1684,6 +1684,7 @@ namespace Mono.TextEditor
OnHeightChanged (EventArgs.Empty);
}
}
+ marker.parent = null;
if (updateLine)
this.CommitLineUpdate (line);
}
diff --git a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Styles.cs b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Styles.cs
index 6fe1fc0ac6..7de9bbeea7 100644
--- a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Styles.cs
+++ b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/Styles.cs
@@ -55,7 +55,7 @@ namespace Mono.TextEditor.PopupWindow
public static void LoadStyles ()
{
- var bgColor = Platform.IsMac ? Color.FromName ("#5189ed") : Color.FromName ("#cce8ff");
+ var bgColor = Platform.IsMac ? Color.FromName ("#2862d9") : Color.FromName ("#cce8ff");
var fgColor = Platform.IsMac ? Color.FromName ("#ffffff") : Color.FromName ("#000000");
ModeHelpWindowTokenOutlineColor = fgColor;
diff --git a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextEditorData.cs b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextEditorData.cs
index e669554bee..2accdab270 100644
--- a/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextEditorData.cs
+++ b/main/src/core/Mono.TextEditor.Shared/Mono.TextEditor/TextEditorData.cs
@@ -1,4 +1,4 @@
-// TextEditorData.cs
+// TextEditorData.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
@@ -413,6 +413,11 @@ namespace Mono.TextEditor
public string GetMarkup (int offset, int length, bool removeIndent, bool useColors = true, bool replaceTabs = true, bool fitIdeStyle = false)
{
+ return GetMarkupAsync (offset, length, removeIndent, useColors, replaceTabs, fitIdeStyle).WaitAndGetResult (default (CancellationToken));
+ }
+
+ public async Task<string> GetMarkupAsync (int offset, int length, bool removeIndent, bool useColors = true, bool replaceTabs = true, bool fitIdeStyle = false, CancellationToken cancellationToken = default)
+ {
var doc = Document;
var mode = doc.SyntaxMode;
var style = fitIdeStyle ? SyntaxHighlightingService.GetEditorTheme (Parent.GetIdeColorStyleName ()) : ColorStyle;
@@ -441,7 +446,7 @@ namespace Mono.TextEditor
}
}
- foreach (var chunk in GetChunks (line, curOffset, toOffset - curOffset).WaitAndGetResult (default (CancellationToken))) {
+ foreach (var chunk in await GetChunks (line, curOffset, toOffset - curOffset, cancellationToken)) {
if (chunk.Length == 0)
continue;
var chunkStyle = style.GetChunkStyle (chunk.ScopeStack);
@@ -486,14 +491,30 @@ namespace Mono.TextEditor
return StringBuilderCache.ReturnAndFree (result);
}
- internal async Task<IEnumerable<MonoDevelop.Ide.Editor.Highlighting.ColoredSegment>> GetChunks (DocumentLine line, int offset, int length)
+ internal async Task<IEnumerable<MonoDevelop.Ide.Editor.Highlighting.ColoredSegment>> GetChunks (DocumentLine line, int offset, int length, CancellationToken cancellationToken = default)
{
- var lineOffset = line.Offset;
- return TextViewMargin.TrimChunks (
- (await document.SyntaxMode.GetHighlightedLineAsync (line, CancellationToken.None).ConfigureAwait(false))
- .Segments
- .Select (c => c.WithOffset (c.Offset + lineOffset))
- .ToList (), offset, length);
+ if (line == null)
+ throw new ArgumentNullException (nameof (line));
+ if (document == null)
+ throw new InvalidOperationException ("TextEditorData was disposed.");
+ Runtime.AssertMainThread ();
+ try {
+ var lineOffset = line.Offset;
+ var syntaxMode = document.SyntaxMode;
+ var highlightedLine = await syntaxMode.GetHighlightedLineAsync (line, cancellationToken).ConfigureAwait (false);
+ var result = new List<MonoDevelop.Ide.Editor.Highlighting.ColoredSegment> (highlightedLine.Segments.Count);
+ foreach (var segment in highlightedLine.Segments) {
+ if (segment == null) {
+ LoggingService.LogInternalError (new InvalidOperationException ("Segment== null insede highlighed line " + highlightedLine));
+ continue;
+ }
+ result.Add (segment.WithOffset (segment.Offset + lineOffset));
+ }
+ return TextViewMargin.TrimChunks (result, offset, length);
+ } catch (Exception e) {
+ LoggingService.LogInternalError ("Error while getting chunks.", e);
+ return new [] { new MonoDevelop.Ide.Editor.Highlighting.ColoredSegment (offset, length, ScopeStack.Empty) };
+ }
}
public int Insert (int offset, string value)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/AssemblyUtilities.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/AssemblyUtilities.cs
new file mode 100644
index 0000000000..d4eb34291f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/AssemblyUtilities.cs
@@ -0,0 +1,82 @@
+//
+// AssemblyUtilities.cs
+//
+// Author:
+// Mike Krüger <mikkrg@microsoft.com>
+//
+// Copyright (c) 2019 Microsoft Corporation. All rights reserved.
+//
+// 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.Threading;
+using System.IO;
+using System.Xml;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using MonoDevelop.Core;
+using MonoDevelop.Core.Execution;
+using MonoDevelop.Core.AddIns;
+using MonoDevelop.Core.Serialization;
+using Mono.Addins;
+using Mono.PkgConfig;
+
+namespace MonoDevelop.Core.Assemblies
+{
+ public static class AssemblyUtilities
+ {
+ static bool Is64BitPE (Mono.Cecil.TargetArchitecture machine)
+ {
+ return machine == Mono.Cecil.TargetArchitecture.AMD64 ||
+ machine == Mono.Cecil.TargetArchitecture.IA64 ||
+ machine == Mono.Cecil.TargetArchitecture.ARM64;
+ }
+
+ public static ProcessExecutionArchitecture GetProcessExecutionArchitectureForAssembly (string assemblyPath)
+ {
+ if (string.IsNullOrEmpty (assemblyPath))
+ throw new ArgumentNullException (nameof (assemblyPath));
+
+ try {
+ Mono.Cecil.ModuleAttributes peKind;
+ Mono.Cecil.TargetArchitecture machine;
+ if (!File.Exists (assemblyPath))
+ return ProcessExecutionArchitecture.Unspecified;
+ try {
+ using (var adef = Mono.Cecil.AssemblyDefinition.ReadAssembly (assemblyPath)) {
+ peKind = adef.MainModule.Attributes;
+ machine = adef.MainModule.Architecture;
+ }
+ } catch {
+ peKind = Mono.Cecil.ModuleAttributes.ILOnly;
+ machine = Mono.Cecil.TargetArchitecture.I386;
+ }
+ if ((peKind & (Mono.Cecil.ModuleAttributes.Required32Bit | Mono.Cecil.ModuleAttributes.Preferred32Bit)) != 0)
+ return ProcessExecutionArchitecture.X86;
+ if (Is64BitPE (machine))
+ return ProcessExecutionArchitecture.X64;
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while determining 64/32 bit assembly.", e);
+ }
+ return ProcessExecutionArchitecture.Unspecified;
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs
index 57c6ab4c57..67c332cc6d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs
@@ -294,13 +294,6 @@ namespace MonoDevelop.Core.Assemblies
return new ExecutionEnvironment (EnvironmentVariables);
}
- static bool Is64BitPE (Mono.Cecil.TargetArchitecture machine)
- {
- return machine == Mono.Cecil.TargetArchitecture.AMD64 ||
- machine == Mono.Cecil.TargetArchitecture.IA64 ||
- machine == Mono.Cecil.TargetArchitecture.ARM64;
- }
-
/// <summary>
/// Get the Mono executable best matching the assembly architecture flags.
/// </summary>
@@ -309,35 +302,30 @@ namespace MonoDevelop.Core.Assemblies
/// <param name="assemblyPath">Assembly path.</param>
public string GetMonoExecutableForAssembly (string assemblyPath)
{
- Mono.Cecil.ModuleAttributes peKind;
- Mono.Cecil.TargetArchitecture machine;
-
- try {
- using (var adef = Mono.Cecil.AssemblyDefinition.ReadAssembly (assemblyPath)) {
- peKind = adef.MainModule.Attributes;
- machine = adef.MainModule.Architecture;
- }
- } catch {
- peKind = Mono.Cecil.ModuleAttributes.ILOnly;
- machine = Mono.Cecil.TargetArchitecture.I386;
- }
+ return GetMonoExecutable (AssemblyUtilities.GetProcessExecutionArchitectureForAssembly (assemblyPath));
+ }
+ internal string GetMonoExecutable (ProcessExecutionArchitecture use64Bit)
+ {
string monoPath;
-
- if ((peKind & (Mono.Cecil.ModuleAttributes.Required32Bit | Mono.Cecil.ModuleAttributes.Preferred32Bit)) != 0) {
- monoPath = Path.Combine (MonoRuntimeInfo.Prefix, "bin", "mono32");
+ switch (use64Bit) {
+ case ProcessExecutionArchitecture.X64:
+ monoPath = Path.Combine (MonoRuntimeInfo.Prefix, "bin", "mono64");
if (File.Exists (monoPath))
return monoPath;
- } else if (Is64BitPE (machine)) {
- monoPath = Path.Combine (MonoRuntimeInfo.Prefix, "bin", "mono64");
+ break;
+ case ProcessExecutionArchitecture.X86:
+ monoPath = Path.Combine (MonoRuntimeInfo.Prefix, "bin", "mono32");
if (File.Exists (monoPath))
return monoPath;
+ break;
}
return monoPath = Path.Combine (MonoRuntimeInfo.Prefix, "bin", "mono");
}
+
}
-
+
class PcFileCacheContext: Mono.PkgConfig.IPcFileCacheContext<LibraryPackageInfo>
{
public void ReportError (string message, System.Exception ex)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs
index 845ffd7727..6e832f7296 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/MonoPlatformExecutionHandler.cs
@@ -45,18 +45,24 @@ namespace MonoDevelop.Core.Execution
public override ProcessAsyncOperation Execute (ExecutionCommand command, OperationConsole console)
{
- var dotcmd = (DotNetExecutionCommand) command;
-
- string runtimeArgs = string.IsNullOrEmpty (dotcmd.RuntimeArguments) ? "--debug" : dotcmd.RuntimeArguments;
+ var dotcmd = (DotNetExecutionCommand)command;
- var monoRunner = runtime.GetMonoExecutableForAssembly (dotcmd.Command);
-
+ string runtimeArgs = string.IsNullOrEmpty (dotcmd.RuntimeArguments) ? "--debug" : dotcmd.RuntimeArguments;
+ var monoRunner = GetExecutionRunner (command, dotcmd);
string args = string.Format ("{2} \"{0}\" {1}", dotcmd.Command, dotcmd.Arguments, runtimeArgs);
NativeExecutionCommand cmd = new NativeExecutionCommand (monoRunner, args, dotcmd.WorkingDirectory, dotcmd.EnvironmentVariables);
-
+
return base.Execute (cmd, console);
}
-
+
+ private string GetExecutionRunner (ExecutionCommand command, DotNetExecutionCommand dotcmd)
+ {
+ if (command is ProcessExecutionCommand processExecutionCommand && processExecutionCommand.ProcessExecutionArchitecture != ProcessExecutionArchitecture.Unspecified) {
+ return runtime.GetMonoExecutable (processExecutionCommand.ProcessExecutionArchitecture);
+ }
+ return runtime.GetMonoExecutableForAssembly (dotcmd.Command);
+ }
+
public override bool CanExecute (ExecutionCommand command)
{
return command is DotNetExecutionCommand;
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessExecutionCommand.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessExecutionCommand.cs
index 76b3af1915..01af607c01 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessExecutionCommand.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/ProcessExecutionCommand.cs
@@ -29,6 +29,13 @@ using System.Collections.Generic;
namespace MonoDevelop.Core.Execution
{
+ public enum ProcessExecutionArchitecture
+ {
+ Unspecified,
+ X86,
+ X64
+ }
+
public class ProcessExecutionCommand: ExecutionCommand
{
IDictionary<string, string> environmentVariables;
@@ -69,7 +76,9 @@ namespace MonoDevelop.Core.Execution
}
public string WorkingDirectory { get; set; }
-
+
+ public ProcessExecutionArchitecture ProcessExecutionArchitecture { get; set; }
+
public IDictionary<string, string> EnvironmentVariables {
get {
if (environmentVariables == null)
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/RemoteProcessConnection.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/RemoteProcessConnection.cs
index 74c89622dd..aa974f8028 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/RemoteProcessConnection.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Execution/RemoteProcessConnection.cs
@@ -285,6 +285,8 @@ namespace MonoDevelop.Core.Execution
SetStatus (ConnectionStatus.ConnectionFailed, ex.Message, ex);
}
+ public ProcessExecutionArchitecture ProcessExecutionArchitecture { get; set; }
+
Task StartRemoteProcess ()
{
return Task.Run (() => {
@@ -296,7 +298,7 @@ namespace MonoDevelop.Core.Execution
// Explicitly propagate the PATH var to the process. It ensures that tools required
// to run XS are also in the PATH for remote processes.
cmd.EnvironmentVariables ["PATH"] = Environment.GetEnvironmentVariable ("PATH");
-
+ cmd.ProcessExecutionArchitecture = ProcessExecutionArchitecture;
process = executionHandler.Execute (cmd, console);
process.Task.ContinueWith (t => ProcessExited ());
});
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/BacktrackingStringMatcher.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/BacktrackingStringMatcher.cs
index ada6e0c8c6..f0fa0c4205 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/BacktrackingStringMatcher.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Text/BacktrackingStringMatcher.cs
@@ -250,6 +250,11 @@ namespace MonoDevelop.Core.Text
// clear cache
return result;
}
+
+ public override string ToString ()
+ {
+ return string.Format ("[BacktrackingStringMatcher: filterText={0}]", filterText);
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
index 854ee00f7d..6e0979ad80 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
@@ -720,6 +720,7 @@
<Compile Include="MonoDevelop.Core.FeatureConfiguration\FeatureSwitchCondition.cs" />
<Compile Include="MonoDevelop.Projects.MSBuild\MSBuildProcessService.cs" />
<Compile Include="MonoDevelop.Core.FeatureConfiguration\IFeatureSwitchController.cs" />
+ <Compile Include="MonoDevelop.Core.Assemblies\AssemblyUtilities.cs" />
</ItemGroup>
<ItemGroup>
<None Include="BuildVariables.cs.in" />
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
index d6918eeaf4..0bdbbf77a4 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
@@ -215,7 +215,7 @@ namespace MonoDevelop.Core
static void OnLoad (object s, AddinEventArgs args)
{
- Counters.AddinsLoaded.Inc ("Add-in loaded: " + args.AddinId, new Dictionary<string, string> {
+ Counters.AddinsLoaded.Inc (1, "Add-in loaded: " + args.AddinId, new Dictionary<string, object> {
{ "AddinId", args.AddinId },
{ "LoadTrace", Environment.StackTrace },
});
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs
index ec0a17aa31..d9d2e29b79 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs
@@ -266,10 +266,8 @@ namespace MonoDevelop.Projects.MSBuild
builders.Add (builderKey, builder);
builder.ReferenceCount = 0;
builder.BuildSessionId = buildSessionId;
- builder.Disconnected += async delegate {
- using (await buildersLock.EnterAsync ().ConfigureAwait (false))
- builders.Remove (builder);
- };
+
+ builder.Disconnected += OnBuilderDisconnected;
if (setBusy)
builder.SetBusy ();
if (buildSessionId != null) {
@@ -280,6 +278,13 @@ namespace MonoDevelop.Projects.MSBuild
});
}
+ // PERF: Avoid making this an instance method, as it will cause delegates to be retained.
+ static async Task OnBuilderDisconnected (object sender, EventArgs args)
+ {
+ var disconnectedBuilder = (RemoteBuildEngine)sender;
+ using (await buildersLock.EnterAsync ().ConfigureAwait (false))
+ builders.Remove (disconnectedBuilder);
+ }
/// <summary>
/// Unloads a project from all engines
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs
index 6d3bc6eae2..0e61f56418 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/FileWatcherService.cs
@@ -1,322 +1,319 @@
-//
-// FileWatcherService.cs
-//
-// Author:
-// Matt Ward <matt.ward@microsoft.com>
-//
-// Copyright (c) 2018 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.Collections.Generic;
-using System.Diagnostics;
+//
+// FileWatcherService.cs
+//
+// Author:
+// Matt Ward <matt.ward@microsoft.com>
+//
+// Copyright (c) 2018 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.Collections.Generic;
+using System.Diagnostics;
using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MonoDevelop.Core;
-using MonoDevelop.FSW;
-
-namespace MonoDevelop.Projects
-{
- public static class FileWatcherService
- {
- // We don't want more than 8 threads for FileSystemWatchers.
- const int maxWatchers = 8;
-
- static readonly PathTree tree = new PathTree ();
- static readonly Dictionary<FilePath, FileWatcherWrapper> watchers = new Dictionary<FilePath, FileWatcherWrapper> ();
- static readonly Dictionary<object, HashSet<FilePath>> monitoredDirectories = new Dictionary<object, HashSet<FilePath>> ();
- static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource ();
-
- public static Task Add (WorkspaceItem item)
- {
- lock (watchers) {
- item.RootDirectoriesChanged += OnRootDirectoriesChanged;
- return WatchDirectories (item, item.GetRootDirectories ());
- }
- }
-
- public static Task Remove (WorkspaceItem item)
- {
- lock (watchers) {
- item.RootDirectoriesChanged -= OnRootDirectoriesChanged;
- return WatchDirectories (item, null);
- }
- }
-
- static void OnRootDirectoriesChanged (object sender, EventArgs args)
- {
- lock (watchers) {
- var item = (WorkspaceItem)sender;
- WatchDirectories (item, item.GetRootDirectories ()).Ignore ();
- }
- }
-
- static Task UpdateWatchersAsync ()
- {
- cancellationTokenSource.Cancel ();
- cancellationTokenSource = new CancellationTokenSource ();
- CancellationToken token = cancellationTokenSource.Token;
-
- return Task.Run (() => UpdateWatchers (token));
- }
-
- static void UpdateWatchers (CancellationToken token)
- {
- if (token.IsCancellationRequested)
- return;
-
- lock (watchers) {
- if (token.IsCancellationRequested)
- return;
-
- var newPathsToWatch = tree.Normalize (maxWatchers).Select (node => (FilePath)node.GetPath ().ToString ());
- var newWatchers = new HashSet<FilePath> (newPathsToWatch.Where (dir => Directory.Exists (dir)));
- if (newWatchers.Count == 0 && watchers.Count == 0) {
- // Unchanged.
- return;
- }
-
- List<FilePath> toRemove;
- if (newWatchers.Count == 0)
- toRemove = watchers.Keys.ToList ();
- else {
- toRemove = new List<FilePath> ();
- foreach (var kvp in watchers) {
- var directory = kvp.Key;
- if (!newWatchers.Contains (directory))
- toRemove.Add (directory);
- }
- }
-
- // After this point, the watcher update is real and a destructive operation, so do not use the token.
- if (token.IsCancellationRequested)
- return;
-
- // First remove the watchers, so we don't spin too many threads.
- foreach (var directory in toRemove) {
- RemoveWatcher_NoLock (directory);
- }
-
- // Add the new ones.
- if (newWatchers.Count == 0)
- return;
-
- foreach (var path in newWatchers) {
- // Don't modify a watcher that already exists.
- if (watchers.ContainsKey (path)) {
- continue;
- }
- var watcher = new FileWatcherWrapper (path);
- watchers.Add (path, watcher);
- try {
- watcher.EnableRaisingEvents = true;
- } catch (UnauthorizedAccessException e) {
- LoggingService.LogWarning ("Access to " + path + " denied. Stopping file watcher.", e);
- watcher.Dispose ();
- watchers.Remove (path);
- }
- }
-
- }
- }
-
- static void RemoveWatcher_NoLock (FilePath directory)
- {
- Debug.Assert (Monitor.IsEntered (watchers));
-
- if (watchers.TryGetValue (directory, out FileWatcherWrapper watcher)) {
- watcher.EnableRaisingEvents = false;
- watcher.Dispose ();
- watchers.Remove (directory);
- }
- }
-
- public static Task WatchDirectories (object id, IEnumerable<FilePath> directories)
- {
- lock (watchers) {
- HashSet<FilePath> set = null;
- if (directories != null)
- set = new HashSet<FilePath> (directories.Where (x => !x.IsNullOrEmpty));
-
- if (RegisterDirectoriesInTree_NoLock (id, set))
- return UpdateWatchersAsync ();
- return Task.CompletedTask;
- }
- }
-
- static bool RegisterDirectoriesInTree_NoLock (object id, HashSet<FilePath> set)
- {
- Debug.Assert (Monitor.IsEntered (watchers));
-
- // Remove paths subscribed for this id.
-
- bool modified = false;
-
- if (monitoredDirectories.TryGetValue (id, out var oldDirectories)) {
- HashSet<FilePath> toRemove = null;
- if (set != null) {
- toRemove = new HashSet<FilePath> (oldDirectories);
- // Remove the old ones which are not in the new set.
- toRemove.ExceptWith (set);
- } else
- toRemove = oldDirectories;
-
- foreach (var dir in toRemove) {
- var node = tree.RemoveNode (dir, id);
-
- bool wasRemoved = node != null && !node.IsLive;
- modified |= wasRemoved;
- }
- }
-
- // Remove the current registered directories
- monitoredDirectories.Remove (id);
- if (set == null)
- return modified;
-
- HashSet<FilePath> toAdd = null;
- if (oldDirectories != null) {
- toAdd = new HashSet<FilePath> (set);
- toAdd.ExceptWith (oldDirectories);
- } else
- toAdd = set;
-
- // Apply new ones if we have any
- if (set.Count > 0) {
- monitoredDirectories [id] = set;
- foreach (var path in toAdd) {
- tree.AddNode (path, id, out bool isNew);
-
- // We have only modified the tree if there is any new pathtree node item added
- modified |= isNew;
- }
- }
- return modified;
- }
-
- /// <summary>
- /// Used by unit tests to ensure the file watcher is up to date.
- /// </summary>
- internal static Task Update ()
- {
- lock (watchers) {
- return UpdateWatchersAsync ();
- }
- }
- }
-
- class FileWatcherWrapper : IDisposable
- {
- FSW.FileSystemWatcher watcher;
-
- public FileWatcherWrapper (FilePath path)
- {
- Path = path;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
+using MonoDevelop.FSW;
+
+namespace MonoDevelop.Projects
+{
+ public static class FileWatcherService
+ {
+ // We don't want more than 8 threads for FileSystemWatchers.
+ const int maxWatchers = 8;
+
+ static readonly PathTree tree = new PathTree ();
+ static readonly Dictionary<FilePath, FileWatcherWrapper> watchers = new Dictionary<FilePath, FileWatcherWrapper> ();
+ static readonly Dictionary<object, HashSet<FilePath>> monitoredDirectories = new Dictionary<object, HashSet<FilePath>> ();
+ static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource ();
+
+ public static Task Add (WorkspaceItem item)
+ {
+ lock (watchers) {
+ item.RootDirectoriesChanged += OnRootDirectoriesChanged;
+ return WatchDirectories (item, item.GetRootDirectories ());
+ }
+ }
+
+ public static Task Remove (WorkspaceItem item)
+ {
+ lock (watchers) {
+ item.RootDirectoriesChanged -= OnRootDirectoriesChanged;
+ return WatchDirectories (item, null);
+ }
+ }
+
+ static void OnRootDirectoriesChanged (object sender, EventArgs args)
+ {
+ lock (watchers) {
+ var item = (WorkspaceItem)sender;
+ WatchDirectories (item, item.GetRootDirectories ()).Ignore ();
+ }
+ }
+
+ static Task UpdateWatchersAsync ()
+ {
+ cancellationTokenSource.Cancel ();
+ cancellationTokenSource = new CancellationTokenSource ();
+ CancellationToken token = cancellationTokenSource.Token;
+
+ return Task.Run (() => UpdateWatchers (token));
+ }
+ static HashSet<FilePath> newWatchers = new HashSet<FilePath>();
+ static List<FilePath> toRemove = new List<FilePath> ();
+
+ static void UpdateWatchers (CancellationToken token)
+ {
+ if (token.IsCancellationRequested)
+ return;
+ lock (watchers) {
+ if (token.IsCancellationRequested)
+ return;
+ newWatchers.Clear ();
+ foreach (var node in tree.Normalize (maxWatchers)) {
+ if (token.IsCancellationRequested)
+ return;
+ var dir = node.GetPath ().ToString ();
+ if (Directory.Exists (dir))
+ newWatchers.Add (dir);
+ }
+ if (newWatchers.Count == 0 && watchers.Count == 0) {
+ // Unchanged.
+ return;
+ }
+ toRemove.Clear ();
+ foreach (var kvp in watchers) {
+ var directory = kvp.Key;
+ if (!newWatchers.Contains (directory))
+ toRemove.Add (directory);
+ }
+
+ // After this point, the watcher update is real and a destructive operation, so do not use the token.
+ if (token.IsCancellationRequested)
+ return;
+
+ // First remove the watchers, so we don't spin too many threads.
+ foreach (var directory in toRemove) {
+ RemoveWatcher_NoLock (directory);
+ }
+
+ // Add the new ones.
+ foreach (var path in newWatchers) {
+ // Don't modify a watcher that already exists.
+ if (watchers.ContainsKey (path)) {
+ continue;
+ }
+ var watcher = new FileWatcherWrapper (path);
+ watchers.Add (path, watcher);
+ try {
+ watcher.EnableRaisingEvents = true;
+ } catch (UnauthorizedAccessException e) {
+ LoggingService.LogWarning ("Access to " + path + " denied. Stopping file watcher.", e);
+ watcher.Dispose ();
+ watchers.Remove (path);
+ }
+ }
+
+ }
+ }
+
+ static void RemoveWatcher_NoLock (FilePath directory)
+ {
+ Debug.Assert (Monitor.IsEntered (watchers));
+
+ if (watchers.TryGetValue (directory, out FileWatcherWrapper watcher)) {
+ watcher.EnableRaisingEvents = false;
+ watcher.Dispose ();
+ watchers.Remove (directory);
+ }
+ }
+
+ public static Task WatchDirectories (object id, IEnumerable<FilePath> directories)
+ {
+ lock (watchers) {
+ HashSet<FilePath> set = null;
+ if (directories != null)
+ set = new HashSet<FilePath> (directories.Where (x => !x.IsNullOrEmpty));
+
+ if (RegisterDirectoriesInTree_NoLock (id, set))
+ return UpdateWatchersAsync ();
+ return Task.CompletedTask;
+ }
+ }
+
+ static bool RegisterDirectoriesInTree_NoLock (object id, HashSet<FilePath> set)
+ {
+ Debug.Assert (Monitor.IsEntered (watchers));
+
+ // Remove paths subscribed for this id.
+
+ bool modified = false;
+
+ if (monitoredDirectories.TryGetValue (id, out var oldDirectories)) {
+ HashSet<FilePath> toRemove = null;
+ if (set != null) {
+ toRemove = new HashSet<FilePath> (oldDirectories);
+ // Remove the old ones which are not in the new set.
+ toRemove.ExceptWith (set);
+ } else
+ toRemove = oldDirectories;
+
+ foreach (var dir in toRemove) {
+ var node = tree.RemoveNode (dir, id);
+
+ bool wasRemoved = node != null && !node.IsLive;
+ modified |= wasRemoved;
+ }
+ }
+
+ // Remove the current registered directories
+ monitoredDirectories.Remove (id);
+ if (set == null)
+ return modified;
+
+ HashSet<FilePath> toAdd = null;
+ if (oldDirectories != null) {
+ toAdd = new HashSet<FilePath> (set);
+ toAdd.ExceptWith (oldDirectories);
+ } else
+ toAdd = set;
+
+ // Apply new ones if we have any
+ if (set.Count > 0) {
+ monitoredDirectories [id] = set;
+ foreach (var path in toAdd) {
+ tree.AddNode (path, id, out bool isNew);
+
+ // We have only modified the tree if there is any new pathtree node item added
+ modified |= isNew;
+ }
+ }
+ return modified;
+ }
+
+ /// <summary>
+ /// Used by unit tests to ensure the file watcher is up to date.
+ /// </summary>
+ internal static Task Update ()
+ {
+ lock (watchers) {
+ return UpdateWatchersAsync ();
+ }
+ }
+ }
+
+ class FileWatcherWrapper : IDisposable
+ {
+ FSW.FileSystemWatcher watcher;
+
+ public FileWatcherWrapper (FilePath path)
+ {
+ Path = path;
watcher = new FSW.FileSystemWatcher (path) {
// Need LastWrite otherwise no file change events are generated by the native file watcher.
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
IncludeSubdirectories = true,
InternalBufferSize = 32768
- };
-
- watcher.Changed += OnFileChanged;
- watcher.Created += OnFileCreated;
- watcher.Deleted += OnFileDeleted;
- watcher.Renamed += OnFileRenamed;
- watcher.Error += OnFileWatcherError;
- }
-
- public FilePath Path { get; }
-
- public bool EnableRaisingEvents {
- get { return watcher.EnableRaisingEvents; }
- set { watcher.EnableRaisingEvents = value; }
- }
-
- public void Dispose ()
- {
- watcher.Changed -= OnFileChanged;
- watcher.Created -= OnFileCreated;
- watcher.Deleted -= OnFileDeleted;
- watcher.Renamed -= OnFileRenamed;
- watcher.Error -= OnFileWatcherError;
- watcher.Dispose ();
- }
-
- void OnFileChanged (object sender, FileSystemEventArgs e)
- {
- FileService.NotifyFileChanged (e.FullPath);
- }
-
- void OnFileCreated (object sender, FileSystemEventArgs e)
- {
- FileService.NotifyFileCreated (e.FullPath);
-
- // The native file watcher sometimes generates a single Created event for a file when it is renamed
- // from a non-monitored directory to a monitored directory. So this is turned into a Changed
- // event so the file will be reloaded.
- FileService.NotifyFileChanged (e.FullPath);
- }
-
- void OnFileDeleted (object sender, FileSystemEventArgs e)
- {
- // The native file watcher sometimes generates a Changed, Created and Deleted event in
- // that order from a single native file event. So check the file has been deleted before raising
- // a FileRemoved event.
- if (!File.Exists (e.FullPath) && !Directory.Exists (e.FullPath))
- FileService.NotifyFileRemoved (e.FullPath);
- }
-
- /// <summary>
- /// File rename events have various problems.
- /// 1. They are sometimes raised out of order.
- /// 2. Sometimes the rename information is incorrect with the wrong file names being used.
- /// 3. Some applications use a rename to update the original file so these are turned into
- /// a change event and a remove event.
- /// </summary>
- void OnFileRenamed (object sender, RenamedEventArgs e)
- {
- FileService.NotifyFileRenamedExternally (e.OldFullPath, e.FullPath);
- // Some applications, such as TextEdit.app, will create a backup file
- // and then rename that to the original file. This results in no file
- // change event being generated by the file watcher. To handle this
- // a rename is treated as a file change for the destination file.
- FileService.NotifyFileChanged (e.FullPath);
-
- // Deleting a file with Finder will move the file to the ~/.Trashes
- // folder. To handle this a remove event is fired for the source
- // file being renamed. Also handle file events being received out of
- // order on saving a file in TextEdit.app - with a rename event of
- // the original file to the temp file being the last event even though
- // the original file still exists.
- if (File.Exists (e.OldFullPath))
- FileService.NotifyFileChanged (e.OldFullPath);
- else
- FileService.NotifyFileRemoved (e.OldFullPath);
- }
-
- void OnFileWatcherError (object sender, ErrorEventArgs e)
- {
- LoggingService.LogError ("FileService.FileWatcher error", e.GetException ());
- }
- }
-}
+ };
+
+ watcher.Changed += OnFileChanged;
+ watcher.Created += OnFileCreated;
+ watcher.Deleted += OnFileDeleted;
+ watcher.Renamed += OnFileRenamed;
+ watcher.Error += OnFileWatcherError;
+ }
+
+ public FilePath Path { get; }
+
+ public bool EnableRaisingEvents {
+ get { return watcher.EnableRaisingEvents; }
+ set { watcher.EnableRaisingEvents = value; }
+ }
+
+ public void Dispose ()
+ {
+ watcher.Changed -= OnFileChanged;
+ watcher.Created -= OnFileCreated;
+ watcher.Deleted -= OnFileDeleted;
+ watcher.Renamed -= OnFileRenamed;
+ watcher.Error -= OnFileWatcherError;
+ watcher.Dispose ();
+ }
+
+ void OnFileChanged (object sender, FileSystemEventArgs e)
+ {
+ FileService.NotifyFileChanged (e.FullPath);
+ }
+
+ void OnFileCreated (object sender, FileSystemEventArgs e)
+ {
+ FileService.NotifyFileCreated (e.FullPath);
+
+ // The native file watcher sometimes generates a single Created event for a file when it is renamed
+ // from a non-monitored directory to a monitored directory. So this is turned into a Changed
+ // event so the file will be reloaded.
+ FileService.NotifyFileChanged (e.FullPath);
+ }
+
+ void OnFileDeleted (object sender, FileSystemEventArgs e)
+ {
+ // The native file watcher sometimes generates a Changed, Created and Deleted event in
+ // that order from a single native file event. So check the file has been deleted before raising
+ // a FileRemoved event.
+ if (!File.Exists (e.FullPath) && !Directory.Exists (e.FullPath))
+ FileService.NotifyFileRemoved (e.FullPath);
+ }
+
+ /// <summary>
+ /// File rename events have various problems.
+ /// 1. They are sometimes raised out of order.
+ /// 2. Sometimes the rename information is incorrect with the wrong file names being used.
+ /// 3. Some applications use a rename to update the original file so these are turned into
+ /// a change event and a remove event.
+ /// </summary>
+ void OnFileRenamed (object sender, RenamedEventArgs e)
+ {
+ FileService.NotifyFileRenamedExternally (e.OldFullPath, e.FullPath);
+ // Some applications, such as TextEdit.app, will create a backup file
+ // and then rename that to the original file. This results in no file
+ // change event being generated by the file watcher. To handle this
+ // a rename is treated as a file change for the destination file.
+ FileService.NotifyFileChanged (e.FullPath);
+
+ // Deleting a file with Finder will move the file to the ~/.Trashes
+ // folder. To handle this a remove event is fired for the source
+ // file being renamed. Also handle file events being received out of
+ // order on saving a file in TextEdit.app - with a rename event of
+ // the original file to the temp file being the last event even though
+ // the original file still exists.
+ if (File.Exists (e.OldFullPath))
+ FileService.NotifyFileChanged (e.OldFullPath);
+ else
+ FileService.NotifyFileRemoved (e.OldFullPath);
+ }
+
+ void OnFileWatcherError (object sender, ErrorEventArgs e)
+ {
+ LoggingService.LogError ("FileService.FileWatcher error", e.GetException ());
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
index c08e57f1de..508f29b838 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
@@ -4528,6 +4528,13 @@ namespace MonoDevelop.Projects
void OnFileCreatedExternally (FilePath fileName)
{
+ if (sourceProject == null) {
+ // sometimes this method is called after disposing this class.
+ // (i.e. when quitting MD or creating a new project.)
+ LoggingService.LogWarning ("File created externally not processed. {0}", fileName);
+ return;
+ }
+
// Check file is inside the project directory. The file globs would exclude the file anyway
// if the relative path starts with "..\" but checking here avoids checking the file globs.
if (!fileName.IsChildPathOf (BaseDirectory))
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs
index c37c7ed678..62fcb98017 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectItem.cs
@@ -49,7 +49,8 @@ namespace MonoDevelop.Projects
get {
return project;
}
- internal set {
+ // HACK: internal
+ set {
project = value;
OnProjectSet ();
}
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
index 9bb9cb676f..cd0d4d9e31 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
@@ -221,6 +221,10 @@
defaultHandler = "MonoDevelop.Ide.Commands.SolutionItemOptionsHandler"
_label = "_Options"
_description = "Show options window" />
+ <Command id = "MonoDevelop.Ide.Commands.ProjectCommands.SetStartupProjects"
+ defaultHandler = "MonoDevelop.Ide.Commands.SetStartupProjectsHandler"
+ _label = "Se_t Startup Projects..."
+ _description = "Set multiple startup projects" />
<Command id = "MonoDevelop.Ide.Commands.ProjectCommands.SolutionOptions"
defaultHandler = "MonoDevelop.Ide.Commands.SolutionOptionsHandler"
icon = "gtk-preferences"
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
index 007c4a671a..aeec88b1a6 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
@@ -205,6 +205,7 @@
<CommandItem id = "MonoDevelop.Ide.Commands.ProjectCommands.ExportPolicy" />
<SeparatorItem id = "PolicyToolsEnd" />
<SeparatorItem id = "OptionsSeparator" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.ProjectCommands.SetStartupProjects" />
<CommandItem id = "MonoDevelop.Ide.Commands.ProjectCommands.SolutionOptions" />
<CommandItem id = "MonoDevelop.Ide.Commands.ProjectCommands.ProjectOptions" />
<SeparatorItem id = "ProjectToolsSeparator" />
diff --git a/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Gui.OptionPanels.LoadSavePanelWidget.cs b/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Gui.OptionPanels.LoadSavePanelWidget.cs
index 4a8327ae06..6622f7e893 100644
--- a/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Gui.OptionPanels.LoadSavePanelWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/Gui/MonoDevelop.Ide.Gui.OptionPanels.LoadSavePanelWidget.cs
@@ -10,15 +10,15 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
private global::Gtk.VBox vbox18;
private global::Gtk.Label loadLabel;
private global::Gtk.HBox hbox14;
- private global::Gtk.Label label25;
private global::Gtk.HBox hbox10;
private global::Gtk.VBox vbox65;
private global::Gtk.CheckButton loadUserDataCheckButton;
- private global::Gtk.CheckButton loadPrevProjectCheckButton;
+ private global::Gtk.RadioButton openStartWindowRadioButton;
+ private global::Gtk.RadioButton loadPrevProjectRadioButton;
+ private global::Gtk.RadioButton emptyEnvironmentRadioButton;
private global::Gtk.VBox vbox19;
private global::Gtk.Label saveLabel;
private global::Gtk.HBox hbox11;
- private global::Gtk.Label label21;
private global::Gtk.VBox vbox20;
private global::Gtk.CheckButton createBackupCopyCheckButton;
@@ -43,24 +43,14 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
this.locationLabel.Yalign = 0F;
this.locationLabel.LabelProp = global::Mono.Unix.Catalog.GetString ("Default _Solution location");
this.locationLabel.UseUnderline = true;
- this.vbox26.Add (this.locationLabel);
- global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox26 [this.locationLabel]));
- w1.Position = 0;
- w1.Expand = false;
- w1.Fill = false;
+ this.vbox26.PackStart (this.locationLabel, false, false, 0);
+
// Container child vbox26.Gtk.Box+BoxChild
this.folderEntry = new global::MonoDevelop.Components.FolderEntry ();
this.folderEntry.Name = "folderEntry";
this.folderEntry.DisplayAsRelativePath = false;
- this.vbox26.Add (this.folderEntry);
- global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox26 [this.folderEntry]));
- w2.Position = 1;
- w2.Expand = false;
- w2.Fill = false;
- this.vbox17.Add (this.vbox26);
- global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.vbox17 [this.vbox26]));
- w3.Position = 0;
- w3.Expand = false;
+ this.vbox26.PackStart (this.folderEntry, false, false, 0);
+ this.vbox17.PackStart (this.vbox26, false, false, 0);
// Container child vbox17.Gtk.Box+BoxChild
this.vbox18 = new global::Gtk.VBox ();
this.vbox18.Name = "vbox18";
@@ -72,27 +62,12 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
this.loadLabel.Yalign = 0F;
this.loadLabel.LabelProp = global::Mono.Unix.Catalog.GetString ("<b>Load</b>");
this.loadLabel.UseMarkup = true;
- this.vbox18.Add (this.loadLabel);
- global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox18 [this.loadLabel]));
- w4.Position = 0;
- w4.Expand = false;
- w4.Fill = false;
+ this.vbox18.PackStart (this.loadLabel, false, false, 0);
// Container child vbox18.Gtk.Box+BoxChild
this.hbox14 = new global::Gtk.HBox ();
this.hbox14.Name = "hbox14";
this.hbox14.Spacing = 6;
// Container child hbox14.Gtk.Box+BoxChild
- this.label25 = new global::Gtk.Label ();
- this.label25.Name = "label25";
- this.label25.Xalign = 0F;
- this.label25.Yalign = 0F;
- this.label25.LabelProp = " ";
- this.hbox14.Add (this.label25);
- global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.hbox14 [this.label25]));
- w5.Position = 0;
- w5.Expand = false;
- w5.Fill = false;
- // Container child hbox14.Gtk.Box+BoxChild
this.hbox10 = new global::Gtk.HBox ();
this.hbox10.Name = "hbox10";
this.hbox10.Spacing = 6;
@@ -106,38 +81,60 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
this.loadUserDataCheckButton.Label = global::Mono.Unix.Catalog.GetString ("Load user-specific settings with the document");
this.loadUserDataCheckButton.DrawIndicator = true;
this.loadUserDataCheckButton.UseUnderline = true;
- this.vbox65.Add (this.loadUserDataCheckButton);
- global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox65 [this.loadUserDataCheckButton]));
- w6.Position = 0;
- w6.Expand = false;
- w6.Fill = false;
- // Container child vbox65.Gtk.Box+BoxChild
- this.loadPrevProjectCheckButton = new global::Gtk.CheckButton ();
- this.loadPrevProjectCheckButton.Name = "loadPrevProjectCheckButton";
- this.loadPrevProjectCheckButton.Label = global::Mono.Unix.Catalog.GetString ("_Load previous solution on startup");
- this.loadPrevProjectCheckButton.DrawIndicator = true;
- this.loadPrevProjectCheckButton.UseUnderline = true;
- this.vbox65.Add (this.loadPrevProjectCheckButton);
- global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.vbox65 [this.loadPrevProjectCheckButton]));
- w7.Position = 1;
- w7.Expand = false;
- w7.Fill = false;
- this.hbox10.Add (this.vbox65);
- global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.hbox10 [this.vbox65]));
- w8.Position = 0;
- w8.Expand = false;
- w8.Fill = false;
- this.hbox14.Add (this.hbox10);
- global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.hbox14 [this.hbox10]));
- w9.Position = 1;
- this.vbox18.Add (this.hbox14);
- global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox18 [this.hbox14]));
- w10.Position = 1;
- this.vbox17.Add (this.vbox18);
- global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.vbox17 [this.vbox18]));
- w11.Position = 1;
- w11.Expand = false;
- // Container child vbox17.Gtk.Box+BoxChild
+ this.vbox65.PackStart (this.loadUserDataCheckButton, false, false, 0);
+
+ // Startup options
+ var startSectionVbox = new global::Gtk.VBox ();
+ startSectionVbox.Name = "startVbox";
+ startSectionVbox.Spacing = 6;
+
+ var startSectionLabel = new global::Gtk.Label ();
+ startSectionLabel.Name = "startSectionLabel";
+ startSectionLabel.Xalign = 0F;
+ startSectionLabel.Yalign = 0F;
+ startSectionLabel.LabelProp = global::Mono.Unix.Catalog.GetString ("<b>Start</b>");
+ startSectionLabel.UseMarkup = true;
+ startSectionVbox.PackStart (startSectionLabel, false, false, 0);
+
+ var startContentHbox = new global::Gtk.HBox ();
+ startSectionVbox.PackStart (startContentHbox, false, false, 0);
+
+ var startContentVbox = new global::Gtk.VBox ();
+ startContentVbox.Name = "startContentVbox";
+ startContentVbox.Spacing = 6;
+ startContentHbox.PackStart (startContentVbox, false, false, 24);
+
+ this.openStartWindowRadioButton = new global::Gtk.RadioButton ((global::Gtk.RadioButton) null) {
+ Name = "openStartWindowCheckButton",
+ Label = global::Mono.Unix.Catalog.GetString ("_Always show me the Start Window"),
+ DrawIndicator = true,
+ UseUnderline = true
+ };
+ startContentVbox.PackStart (this.openStartWindowRadioButton, false, false, 0);
+
+ // Container child vbox65.Gtk.Box+BoxChild
+ this.loadPrevProjectRadioButton = new global::Gtk.RadioButton (this.openStartWindowRadioButton);
+ this.loadPrevProjectRadioButton.Name = "loadPrevProjectCheckButton";
+ this.loadPrevProjectRadioButton.Label = global::Mono.Unix.Catalog.GetString ("_Load previous solution on startup");
+ this.loadPrevProjectRadioButton.DrawIndicator = true;
+ this.loadPrevProjectRadioButton.UseUnderline = true;
+ startContentVbox.PackStart (this.loadPrevProjectRadioButton, false, false, 0);
+
+ this.emptyEnvironmentRadioButton = new global::Gtk.RadioButton (this.openStartWindowRadioButton) {
+ Name = "emptyEnvironmentCheckButton",
+ Label = global::Mono.Unix.Catalog.GetString ("_Show empty environment"),
+ DrawIndicator = true,
+ UseUnderline = true
+ };
+ startContentVbox.PackStart (this.emptyEnvironmentRadioButton, false, false, 0);
+
+ this.hbox10.PackStart (this.vbox65, false, false, 0);
+ this.hbox14.PackStart (this.hbox10, false, false, 24);
+ this.vbox18.PackStart (this.hbox14, false, false, 0);
+ this.vbox17.PackStart (startSectionVbox, false, false, 0);
+ this.vbox17.PackStart (this.vbox18, false, false, 0);
+
+ // Container child vbox17.Gtk.Box+BoxChild
this.vbox19 = new global::Gtk.VBox ();
this.vbox19.Name = "vbox19";
this.vbox19.Spacing = 6;
@@ -148,27 +145,12 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
this.saveLabel.Yalign = 0F;
this.saveLabel.LabelProp = global::Mono.Unix.Catalog.GetString ("<b>Save</b>");
this.saveLabel.UseMarkup = true;
- this.vbox19.Add (this.saveLabel);
- global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.vbox19 [this.saveLabel]));
- w12.Position = 0;
- w12.Expand = false;
- w12.Fill = false;
+ this.vbox19.PackStart (this.saveLabel, false, false, 0);
// Container child vbox19.Gtk.Box+BoxChild
this.hbox11 = new global::Gtk.HBox ();
this.hbox11.Name = "hbox11";
this.hbox11.Spacing = 6;
// Container child hbox11.Gtk.Box+BoxChild
- this.label21 = new global::Gtk.Label ();
- this.label21.Name = "label21";
- this.label21.Xalign = 0F;
- this.label21.Yalign = 0F;
- this.label21.LabelProp = " ";
- this.hbox11.Add (this.label21);
- global::Gtk.Box.BoxChild w13 = ((global::Gtk.Box.BoxChild)(this.hbox11 [this.label21]));
- w13.Position = 0;
- w13.Expand = false;
- w13.Fill = false;
- // Container child hbox11.Gtk.Box+BoxChild
this.vbox20 = new global::Gtk.VBox ();
this.vbox20.Name = "vbox20";
this.vbox20.Spacing = 6;
@@ -178,20 +160,12 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
this.createBackupCopyCheckButton.Label = global::Mono.Unix.Catalog.GetString ("Always create backup copy");
this.createBackupCopyCheckButton.DrawIndicator = true;
this.createBackupCopyCheckButton.UseUnderline = true;
- this.vbox20.Add (this.createBackupCopyCheckButton);
- global::Gtk.Box.BoxChild w14 = ((global::Gtk.Box.BoxChild)(this.vbox20 [this.createBackupCopyCheckButton]));
- w14.Position = 0;
- w14.Expand = false;
- w14.Fill = false;
- this.hbox11.Add (this.vbox20);
- global::Gtk.Box.BoxChild w15 = ((global::Gtk.Box.BoxChild)(this.hbox11 [this.vbox20]));
- w15.Position = 1;
- this.vbox19.Add (this.hbox11);
- global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.vbox19 [this.hbox11]));
- w16.Position = 1;
- this.vbox17.Add (this.vbox19);
+ this.vbox20.PackStart (this.createBackupCopyCheckButton, false, false, 0);
+ this.hbox11.PackStart (this.vbox20, false, false, 24);
+ this.vbox19.PackStart (this.hbox11, false, false, 0);
+ this.vbox17.PackStart (this.vbox19, false, false, 0);
global::Gtk.Box.BoxChild w17 = ((global::Gtk.Box.BoxChild)(this.vbox17 [this.vbox19]));
- w17.Position = 2;
+ w17.Position = 3;
this.Add (this.vbox17);
if ((this.Child != null)) {
this.Child.ShowAll ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs
index a07c47b6ca..3cbdd0fdd4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/EventEditor.cs
@@ -45,14 +45,20 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
IEventBindingService evtBind;
protected override void Initialize ()
- {
- IComponent comp = Instance as IComponent;
- evtBind = (IEventBindingService) comp.Site.GetService (typeof (IEventBindingService));
- base.Initialize ();
+ {
+ IComponent comp = Instance as IComponent;
+ if (comp != null) {
+ evtBind = (IEventBindingService)comp.Site.GetService (typeof (IEventBindingService));
+ base.Initialize ();
+ }
}
protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state)
- {
+ {
+ if (evtBind == null) {
+ return null;
+ }
+
//get existing method names
ICollection IColl = evtBind.GetCompatibleMethods (evtBind.GetEvent (Property)) ;
string[] methods = new string [IColl.Count + 1];
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs
index 89b90e9b4d..afe01c968e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/BaseFileEntry.cs
@@ -154,6 +154,12 @@ namespace MonoDevelop.Components
pathEntry.SetCommonAccessibilityAttributes (name, label, help);
}
+
+ public void SetEntryAccessibleTitleUIElement (Atk.Object accessible)
+ {
+ pathEntry.Accessible.SetTitleUIElement (accessible);
+ }
+
public Atk.Object EntryAccessible {
get {
return pathEntry.Accessible;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs
index 707aba213a..446faa8a23 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/InformationPopoverWidget.cs
@@ -108,11 +108,24 @@ namespace MonoDevelop.Components
ShowPopover ();
}
+ bool WorkaroundNestedDialogFlickering ()
+ {
+ // There seems to be a problem with Gdk.Window focus events when the parent
+ // window is transient for another modal window (i.e. dialogs on top of the Ide preferences window).
+ // A native tooltip seems to confuse Gdk in this case and it rapidly fires LeaveNotify/EnterNotify
+ // events leading to fast flickering of the tooltip.
+ if (ParentWindow != null && Surface.ToolkitEngine.GetNativeWindow (ParentWindow) is Gtk.Window gtkWindow) {
+ if (gtkWindow.TransientFor?.TransientFor != null)
+ return true;
+ }
+ return false;
+ }
+
void ShowPopover ()
{
if (popover != null)
popover.Destroy ();
- popover = TooltipPopoverWindow.Create ();
+ popover = TooltipPopoverWindow.Create (!WorkaroundNestedDialogFlickering ());
popover.ShowArrow = true;
popover.Text = message;
popover.Severity = severity;
@@ -137,6 +150,13 @@ namespace MonoDevelop.Components
DestroyPopover ();
}
+ protected override void OnPreferredSizeChanged ()
+ {
+ base.OnPreferredSizeChanged ();
+ if (!Visible)
+ DestroyPopover ();
+ }
+
void DestroyPopover ()
{
if (popover != null) {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
index e0803887c0..1a5e7364d8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SearchEntry.cs
@@ -683,6 +683,13 @@ namespace MonoDevelop.Components
}
+ public void SetEntryAccessibilityAttributes (string name, string label, string help)
+ {
+ entry.SetCommonAccessibilityAttributes (name, label, help);
+ }
+
+ public Atk.Object EntryAccessible => entry.Accessible;
+
private class FramelessEntry : Entry
{
private SearchEntry parent;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
index a8c9cd2c29..bf110fc8c5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
@@ -136,6 +136,7 @@ namespace MonoDevelop.Components
proxies [i] = tab.Accessible;
tab.Accessible.Index = i;
i++;
+ tab.Allocation = GetBounds (tab);
}
Accessible.SetTabs (proxies);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs
index 9cde49a350..a1d8ba495d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionDataList.cs
@@ -192,7 +192,7 @@ namespace MonoDevelop.Ide.CodeCompletion
{
// default - word with highest match rating in the list.
int idx = -1;
- if (DefaultCompletionString != null && DefaultCompletionString.StartsWith (partialWord, StringComparison.OrdinalIgnoreCase)) {
+ if (DefaultCompletionString != null && string.IsNullOrEmpty(partialWord)) {
partialWord = DefaultCompletionString;
}
CompletionDataMatcher matcher = null;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs
index 191409be2b..034be04164 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplatePanel.cs
@@ -32,6 +32,7 @@ using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Dialogs;
using MonoDevelop.Components;
using MonoDevelop.Ide.Editor;
+using MonoDevelop.Ide.Gui;
namespace MonoDevelop.Ide.CodeTemplates
{
@@ -177,7 +178,7 @@ namespace MonoDevelop.Ide.CodeTemplates
GLib.Markup.EscapeText (GettextCatalog.GetString (template.Description)) + ")";
} else {
crt.Markup = GLib.Markup.EscapeText (template.Shortcut) + " <span foreground=\"" +
- GetColorString (Style.Text (StateType.Insensitive)) + "\">("
+ Styles.SecondaryTextColorHexString + "\">("
+ GLib.Markup.EscapeText (GettextCatalog.GetString (template.Description)) + ")</span>";
}
}
@@ -210,11 +211,6 @@ namespace MonoDevelop.Ide.CodeTemplates
return templateStore.AppendValues (null, groupName, "<b>" + groupName + "</b>");
}
- internal static string GetColorString (Gdk.Color color)
- {
- return string.Format ("#{0:X02}{1:X02}{2:X02}", color.Red / 256, color.Green / 256, color.Blue / 256);
- }
-
TreeIter InsertTemplate (CodeTemplate template)
{
TreeIter iter = GetGroup (template.Group);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/ItemTemplateExtensionNode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/ItemTemplateExtensionNode.cs
index f794ada120..ace4ca75b7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/ItemTemplateExtensionNode.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Codons/ItemTemplateExtensionNode.cs
@@ -1,45 +1,59 @@
-//
-// ItemTemplateExtensionNode.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2017 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.
-
+//
+// ItemTemplateExtensionNode.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2017 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 Mono.Addins;
namespace MonoDevelop.Ide.Codons
{
[ExtensionNode (Description = "A file template")]
class ItemTemplateExtensionNode : ExtensionNode
- {
- //these fields are assigned by reflection, suppress "never assigned" warning
+ {
+ //these fields are assigned by reflection, suppress "never assigned" warning
#pragma warning disable 649
[NodeAttribute ("path", "A .nupkg file or a folder.")]
string path;
+ public string ScanPath {
+ get {
+ // If the path starts with '${' then the path contains a placeholder
+ // that the StringParserService will replace. The path is returned
+ // without calling Addin.GetFilePath to prevent the addin directory
+ // being prefixed to the path.
+ if (path != null && path.StartsWith ("${", StringComparison.Ordinal)) {
+ return path;
+ }
+ return Addin.GetFilePath (path);
+ }
+ }
+
[NodeAttribute ("templateId", "Overrides the template id from the extension node id. Allows the same template to be used with different parameters.")]
string templateId;
-
+
#pragma warning restore 649
[NodeAttribute ("_overrideName", "Override name used in template.json file.", Localizable = true)]
@@ -51,7 +65,6 @@ namespace MonoDevelop.Ide.Codons
[NodeAttribute ("supportedParameters", "Parameters supported by the template.")]
public string SupportedParameters { get; private set; }
- public string ScanPath => Addin.GetFilePath (path);
public string TemplateId => templateId ?? Id;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
index 7d9a07dc49..f8464dec79 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
@@ -87,7 +87,8 @@ namespace MonoDevelop.Ide.Commands
SelectActiveConfiguration,
SelectActiveRuntime,
EditSolutionItem,
- Unload
+ Unload,
+ SetStartupProjects
}
internal class SolutionOptionsHandler : CommandHandler
@@ -131,6 +132,40 @@ namespace MonoDevelop.Ide.Commands
}
}
+ internal class SetStartupProjectsHandler : CommandHandler
+ {
+ protected override void Update (CommandInfo info)
+ {
+ info.Enabled = IdeApp.ProjectOperations.CurrentSelectedSolution?.GetAllProjects ()?.Skip (1)?.Any () ?? false;
+ }
+
+ protected override void Run ()
+ {
+ var sol = IdeApp.ProjectOperations.CurrentSelectedSolution;
+ if (sol != null) {
+ MultiItemSolutionRunConfiguration config = null;
+ if (!sol.MultiStartupRunConfigurations.Any ()) {
+ Xwt.Toolkit.NativeEngine.Invoke (() => {
+ using (var dlg = new NewSolutionRunConfigurationDialog ()) {
+ if (dlg.Run ().Id == "create") {
+ config = new MultiItemSolutionRunConfiguration (dlg.RunConfigurationName, dlg.RunConfigurationName);
+ sol.MultiStartupRunConfigurations.Add (config);
+ sol.StartupConfiguration = config;
+ }
+ }
+ });
+ } else {
+ config = sol.MultiStartupRunConfigurations.FirstOrDefault ();
+ }
+
+ // Show run configurations dialog
+ if (config != null) {
+ IdeApp.ProjectOperations.ShowRunConfiguration (sol, config);
+ }
+ }
+ }
+ }
+
internal class EditReferencesHandler : CommandHandler
{
protected override void Update (CommandInfo info)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs
index 18eb5d3f9f..ffca7a2eba 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ViewCommands.cs
@@ -129,7 +129,7 @@ namespace MonoDevelop.Ide.Commands
pad.Visible = true;
pad.BringToFront (true);
- Counters.PadShown.Inc (new Dictionary<string,string> {{ "Pad", pad.Id }});
+ Counters.PadShown.Inc (1, null, new Dictionary<string,object> {{ "Pad", pad.Id }});
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.Caching.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.Caching.cs
index 3b02af4b92..8793e3596a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.Caching.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.Caching.cs
@@ -53,7 +53,7 @@ namespace MonoDevelop.Ide.Composition
internal class Caching
{
internal static bool writeCache;
- readonly ICachingFaultInjector cachingFaultInjector;
+ readonly ICachingFaultInjector cachingFaultInjector;
Task saveTask;
public HashSet<Assembly> Assemblies { get; }
internal string MefCacheFile { get; }
@@ -99,44 +99,42 @@ namespace MonoDevelop.Ide.Composition
// If we don't have a control file, bail early
if (!File.Exists (MefCacheControlFile) || !File.Exists (MefCacheFile))
return false;
+
+ // Read the cache from disk
+ var serializer = new JsonSerializer ();
+ MefControlCache controlCache;
- using (var timer = Counters.CompositionCacheControl.BeginTiming ()) {
- // Read the cache from disk
- var serializer = new JsonSerializer ();
- MefControlCache controlCache;
-
- try {
- using (var sr = File.OpenText (MefCacheControlFile)) {
- controlCache = (MefControlCache)serializer.Deserialize (sr, typeof(MefControlCache));
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Could not deserialize MEF cache control", ex);
- DeleteFiles ();
- return false;
+ try {
+ using (var sr = File.OpenText (MefCacheControlFile)) {
+ controlCache = (MefControlCache)serializer.Deserialize (sr, typeof (MefControlCache));
}
+ } catch (Exception ex) {
+ LoggingService.LogError ("Could not deserialize MEF cache control", ex);
+ DeleteFiles ();
+ return false;
+ }
- //this can return null (if the cache format changed?). clean up and start over.
- if (controlCache == null) {
- LoggingService.LogError ("MEF cache control deserialized as null");
- DeleteFiles ();
- return false;
- }
+ //this can return null (if the cache format changed?). clean up and start over.
+ if (controlCache == null) {
+ LoggingService.LogError ("MEF cache control deserialized as null");
+ DeleteFiles ();
+ return false;
+ }
- var currentAssemblies = new HashSet<string> (Assemblies.Select (asm => asm.Location));
+ var currentAssemblies = new HashSet<string> (Assemblies.Select (asm => asm.Location));
- // Short-circuit on number of assemblies change
- if (controlCache.AssemblyInfos.Length != currentAssemblies.Count)
- return false;
+ // Short-circuit on number of assemblies change
+ if (controlCache.AssemblyInfos.Length != currentAssemblies.Count)
+ return false;
- // Validate that the assemblies match and we have the same time stamps on them.
- foreach (var assemblyInfo in controlCache.AssemblyInfos) {
- cachingFaultInjector?.FaultAssemblyInfo (assemblyInfo);
- if (!currentAssemblies.Contains (assemblyInfo.Location))
- return false;
+ // Validate that the assemblies match and we have the same time stamps on them.
+ foreach (var assemblyInfo in controlCache.AssemblyInfos) {
+ cachingFaultInjector?.FaultAssemblyInfo (assemblyInfo);
+ if (!currentAssemblies.Contains (assemblyInfo.Location))
+ return false;
- if (File.GetLastWriteTimeUtc (assemblyInfo.Location) != assemblyInfo.LastWriteTimeUtc)
- return false;
- }
+ if (File.GetLastWriteTimeUtc (assemblyInfo.Location) != assemblyInfo.LastWriteTimeUtc)
+ return false;
}
return true;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs
index 515118d678..fce217127d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Composition/CompositionManager.cs
@@ -1,53 +1,53 @@
-// CompositionManager.cs
-//
-// Author:
-// Kirill Osenkov <https://github.com/KirillOsenkov>
-//
-// Copyright (c) 2017 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.
-//
-//
-
+// CompositionManager.cs
+//
+// Author:
+// Kirill Osenkov <https://github.com/KirillOsenkov>
+//
+// Copyright (c) 2017 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.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
-using Microsoft.CodeAnalysis.Host;
-using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.Host;
+using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.Composition;
using Mono.Addins;
using MonoDevelop.Core;
-using MonoDevelop.Core.AddIns;
+using MonoDevelop.Core.AddIns;
using MonoDevelop.Core.Instrumentation;
namespace MonoDevelop.Ide.Composition
-{
+{
/// <summary>
/// The host of the MonoDevelop MEF composition. Uses https://github.com/Microsoft/vs-mef.
/// </summary>
public partial class CompositionManager
- {
+ {
static Task<CompositionManager> creationTask;
static CompositionManager instance;
@@ -57,19 +57,19 @@ namespace MonoDevelop.Ide.Composition
new AttributedPartDiscovery (StandardResolver, true));
public static CompositionManager Instance {
- get {
- if (instance == null) {
- var task = InitializeAsync ();
- if (!task.IsCompleted && Runtime.IsMainThread) {
- LoggingService.LogInfo ("UI thread queried MEF while it was still being built:{0}{1}", Environment.NewLine, Environment.StackTrace);
- }
- instance = task.Result;
+ get {
+ if (instance == null) {
+ var task = InitializeAsync ();
+ if (!task.IsCompleted && Runtime.IsMainThread) {
+ LoggingService.LogInfo ("UI thread queried MEF while it was still being built:{0}{1}", Environment.NewLine, Environment.StackTrace);
+ }
+ instance = task.Result;
}
return instance;
}
- }
-
+ }
+
/// <summary>
/// Starts initializing the MEF composition on a background thread. Thread-safe.
/// </summary>
@@ -89,21 +89,21 @@ namespace MonoDevelop.Ide.Composition
/// <summary>
/// Returns an instance of type T that is exported by some composition part. The instance is shared (singleton).
/// </summary>
- public static T GetExportedValue<T> () => Instance.ExportProvider.GetExportedValue<T> ();
-
- /// <summary>
- /// Returns all instances of type T that are exported by some composition part. The instances are shared (singletons).
- /// </summary>
+ public static T GetExportedValue<T> () => Instance.ExportProvider.GetExportedValue<T> ();
+
+ /// <summary>
+ /// Returns all instances of type T that are exported by some composition part. The instances are shared (singletons).
+ /// </summary>
public static IEnumerable<T> GetExportedValues<T> () => Instance.ExportProvider.GetExportedValues<T> ();
- /// <summary>
- /// Returns a lazy holding the instance of type T that is exported by some composition part. The instance is shared (singleton).
- /// </summary>
+ /// <summary>
+ /// Returns a lazy holding the instance of type T that is exported by some composition part. The instance is shared (singleton).
+ /// </summary>
public static Lazy<T> GetExport<T> () => new Lazy<T> (() => Instance.ExportProvider.GetExportedValue<T> ());
- /// <summary>
- /// Returns a lazy holding all instances of type T that are exported by some composition part. The instances are shared (singletons).
- /// </summary>
+ /// <summary>
+ /// Returns a lazy holding all instances of type T that are exported by some composition part. The instances are shared (singletons).
+ /// </summary>
public static Lazy<IEnumerable<T>> GetExports<T> () => new Lazy<IEnumerable<T>> (() => Instance.ExportProvider.GetExportedValues<T> ());
public RuntimeComposition RuntimeComposition { get; private set; }
@@ -116,124 +116,141 @@ namespace MonoDevelop.Ide.Composition
}
static async Task<CompositionManager> CreateInstanceAsync ()
- {
- var compositionManager = new CompositionManager ();
+ {
+ var compositionManager = new CompositionManager ();
await compositionManager.InitializeInstanceAsync ();
return compositionManager;
- }
-
+ }
+
async Task InitializeInstanceAsync ()
- {
- var assemblies = ReadAssembliesFromAddins ();
- var caching = new Caching (assemblies);
-
- // Try to use cached MEF data
- if (caching.CanUse ()) {
- RuntimeComposition = await TryCreateRuntimeCompositionFromCache (caching);
+ {
+ var timings = new Dictionary<string, long> ();
+ var metadata = new CompositionLoadMetadata (timings);
+
+ using (var timer = Counters.CompositionLoad.BeginTiming (metadata)) {
+ var fullTimer = System.Diagnostics.Stopwatch.StartNew ();
+ var stepTimer = System.Diagnostics.Stopwatch.StartNew ();
+
+ var assemblies = ReadAssembliesFromAddins (timer);
+ timings ["ReadFromAddins"] = stepTimer.ElapsedMilliseconds;
+ stepTimer.Restart ();
+
+ var caching = new Caching (assemblies);
+
+ // Try to use cached MEF data
+
+ var canUse = metadata.ValidCache = caching.CanUse ();
+ if (canUse) {
+ RuntimeComposition = await TryCreateRuntimeCompositionFromCache (caching);
+ }
+ timings ["LoadFromCache"] = stepTimer.ElapsedMilliseconds;
+ stepTimer.Restart ();
+
+ // Otherwise fallback to runtime discovery.
+ if (RuntimeComposition == null) {
+ RuntimeComposition = await CreateRuntimeCompositionFromDiscovery (caching, timer);
+
+ CachedComposition cacheManager = new CachedComposition ();
+ caching.Write (RuntimeComposition, cacheManager).Ignore ();
+ }
+ timings ["LoadRuntimeComposition"] = stepTimer.ElapsedMilliseconds;
+ stepTimer.Restart ();
+
+ ExportProviderFactory = RuntimeComposition.CreateExportProviderFactory ();
+ ExportProvider = ExportProviderFactory.CreateExportProvider ();
+ HostServices = Microsoft.VisualStudio.LanguageServices.VisualStudioMefHostServices.Create (ExportProvider);
+
+ timings ["CreateServices"] = stepTimer.ElapsedMilliseconds;
+ metadata.Duration = fullTimer.ElapsedMilliseconds;
}
+ }
+
+ internal static async Task<RuntimeComposition> TryCreateRuntimeCompositionFromCache (Caching caching)
+ {
+ CachedComposition cacheManager = new CachedComposition ();
- // Otherwise fallback to runtime discovery.
- if (RuntimeComposition == null) {
- RuntimeComposition = await CreateRuntimeCompositionFromDiscovery (caching);
-
- CachedComposition cacheManager = new CachedComposition ();
- caching.Write (RuntimeComposition, cacheManager).Ignore ();
- }
-
- ExportProviderFactory = RuntimeComposition.CreateExportProviderFactory ();
- ExportProvider = ExportProviderFactory.CreateExportProvider ();
- HostServices = Microsoft.VisualStudio.LanguageServices.VisualStudioMefHostServices.Create (ExportProvider);
- }
-
- internal static async Task<RuntimeComposition> TryCreateRuntimeCompositionFromCache (Caching caching)
- {
- CachedComposition cacheManager = new CachedComposition ();
-
try {
- using (Counters.CompositionCache.BeginTiming ())
using (var cacheStream = caching.OpenCacheStream ()) {
return await cacheManager.LoadRuntimeCompositionAsync (cacheStream, StandardResolver);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Could not deserialize MEF cache", ex);
- caching.DeleteFiles ();
- }
- return null;
- }
-
- internal static async Task<RuntimeComposition> CreateRuntimeCompositionFromDiscovery (Caching caching)
- {
- using (var timer = Counters.CompositionDiscovery.BeginTiming ()) {
- var parts = await Discovery.CreatePartsAsync (caching.Assemblies);
- timer.Trace ("Composition parts discovered");
-
- ComposableCatalog catalog = ComposableCatalog.Create (StandardResolver)
- .WithCompositionService ()
- .AddParts (parts);
-
- var discoveryErrors = catalog.DiscoveredParts.DiscoveryErrors;
- if (!discoveryErrors.IsEmpty) {
- foreach (var error in discoveryErrors) {
- LoggingService.LogInfo ("MEF discovery error", error);
- }
-
- // throw new ApplicationException ("MEF discovery errors");
- }
-
- CompositionConfiguration configuration = CompositionConfiguration.Create (catalog);
-
- if (!configuration.CompositionErrors.IsEmpty) {
- // capture the errors in an array for easier debugging
- var errors = configuration.CompositionErrors.SelectMany (e => e).ToArray ();
- foreach (var error in errors) {
- LoggingService.LogInfo ("MEF composition error: " + error.Message);
- }
-
- // For now while we're still transitioning to VSMEF it's useful to work
- // even if the composition has some errors. TODO: re-enable this.
- //configuration.ThrowOnErrors ();
- }
-
- timer.Trace ("Composition configured");
-
- var runtimeComposition = RuntimeComposition.CreateRuntimeComposition (configuration);
- return runtimeComposition;
- }
- }
-
- internal static HashSet<Assembly> ReadAssembliesFromAddins ()
- {
- using (var timer = Counters.CompositionAddinLoad.BeginTiming ()) {
- var assemblies = new HashSet<Assembly> ();
- ReadAssemblies (assemblies, "/MonoDevelop/Ide/TypeService/PlatformMefHostServices", timer);
- ReadAssemblies (assemblies, "/MonoDevelop/Ide/TypeService/MefHostServices", timer);
- ReadAssemblies (assemblies, "/MonoDevelop/Ide/Composition", timer);
- return assemblies;
- }
-
- void ReadAssemblies (HashSet<Assembly> assemblies, string extensionPath, ITimeTracker timer)
- {
- foreach (var node in AddinManager.GetExtensionNodes (extensionPath)) {
- if (node is AssemblyExtensionNode assemblyNode) {
- try {
- string id = assemblyNode.Addin.Id;
- string assemblyName = assemblyNode.FileName;
- timer.Trace ("Start: " + assemblyName);
- // Make sure the add-in that registered the assembly is loaded, since it can bring other
- // other assemblies required to load this one
- AddinManager.LoadAddin (null, id);
-
- var assemblyFilePath = assemblyNode.Addin.GetFilePath (assemblyNode.FileName);
- var assembly = Runtime.LoadAssemblyFrom (assemblyFilePath);
- assemblies.Add (assembly);
-
- timer.Trace ("Loaded: " + assemblyName);
- } catch (Exception e) {
- LoggingService.LogError ("Composition can't load assembly: " + assemblyNode.FileName, e);
- }
- }
- }
- }
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError ("Could not deserialize MEF cache", ex);
+ caching.DeleteFiles ();
+ }
+ return null;
+ }
+
+ internal static async Task<RuntimeComposition> CreateRuntimeCompositionFromDiscovery (Caching caching, ITimeTracker timer = null)
+ {
+ var parts = await Discovery.CreatePartsAsync (caching.Assemblies);
+ timer?.Trace ("Composition parts discovered");
+
+ ComposableCatalog catalog = ComposableCatalog.Create (StandardResolver)
+ .WithCompositionService ()
+ .AddParts (parts);
+
+ var discoveryErrors = catalog.DiscoveredParts.DiscoveryErrors;
+ if (!discoveryErrors.IsEmpty) {
+ foreach (var error in discoveryErrors) {
+ LoggingService.LogInfo ("MEF discovery error", error);
+ }
+
+ // throw new ApplicationException ("MEF discovery errors");
+ }
+
+ CompositionConfiguration configuration = CompositionConfiguration.Create (catalog);
+
+ if (!configuration.CompositionErrors.IsEmpty) {
+ // capture the errors in an array for easier debugging
+ var errors = configuration.CompositionErrors.SelectMany (e => e).ToArray ();
+ foreach (var error in errors) {
+ LoggingService.LogInfo ("MEF composition error: " + error.Message);
+ }
+
+ // For now while we're still transitioning to VSMEF it's useful to work
+ // even if the composition has some errors. TODO: re-enable this.
+ //configuration.ThrowOnErrors ();
+ }
+ timer?.Trace ("Composition configured");
+
+ var runtimeComposition = RuntimeComposition.CreateRuntimeComposition (configuration);
+ timer?.Trace ("Composition created");
+
+ return runtimeComposition;
+ }
+
+ internal static HashSet<Assembly> ReadAssembliesFromAddins (ITimeTracker<CompositionLoadMetadata> timer = null)
+ {
+ var readAssemblies = new HashSet<Assembly> ();
+
+ timer?.Trace ("Start: reading assemblies");
+ ReadAssemblies (readAssemblies, "/MonoDevelop/Ide/TypeService/PlatformMefHostServices");
+ ReadAssemblies (readAssemblies, "/MonoDevelop/Ide/TypeService/MefHostServices");
+ ReadAssemblies (readAssemblies, "/MonoDevelop/Ide/Composition");
+ timer?.Trace ("Start: end reading assemblies");
+
+ return readAssemblies;
+
+ void ReadAssemblies (HashSet<Assembly> assemblies, string extensionPath)
+ {
+ foreach (var node in AddinManager.GetExtensionNodes (extensionPath)) {
+ if (node is AssemblyExtensionNode assemblyNode) {
+ try {
+ string id = assemblyNode.Addin.Id;
+ string assemblyName = assemblyNode.FileName;
+ // Make sure the add-in that registered the assembly is loaded, since it can bring other
+ // other assemblies required to load this one
+ AddinManager.LoadAddin (null, id);
+
+ var assemblyFilePath = assemblyNode.Addin.GetFilePath (assemblyNode.FileName);
+ var assembly = Runtime.LoadAssemblyFrom (assemblyFilePath);
+ assemblies.Add (assembly);
+ } catch (Exception e) {
+ LoggingService.LogError ("Composition can't load assembly: " + assemblyNode.FileName, e);
+ }
+ }
+ }
+ }
}
}
-} \ No newline at end of file
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs
index 2bd8411834..b578cc7d9e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/PlatformService.cs
@@ -51,13 +51,6 @@ namespace MonoDevelop.Ide.Desktop
public abstract string Name { get; }
- [Obsolete]
- public virtual string DefaultControlLeftRightBehavior {
- get {
- return "MonoDevelop";
- }
- }
-
public virtual void Initialize ()
{
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs
index e3c42db2d7..d11ed56097 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Extension/KeyDescriptor.cs
@@ -59,6 +59,74 @@ namespace MonoDevelop.Ide.Editor.Extension
return string.Format ("[KeyDescriptor: SpecialKey={0}, KeyChar={1}, ModifierKeys={2}]", SpecialKey, KeyChar, ModifierKeys);
}
+ #region XWT
+ public static KeyDescriptor FromXwt (Xwt.Key key, char c, Xwt.ModifierKeys modifiers)
+ {
+ return new KeyDescriptor (ConvertKey (key), c, ConvertModifiers (modifiers), Tuple.Create (key, modifiers));
+ }
+
+ static SpecialKey ConvertKey (Xwt.Key key)
+ {
+ switch (key) {
+ case Xwt.Key.BackSpace:
+ return SpecialKey.BackSpace;
+ case Xwt.Key.Tab:
+ case Xwt.Key.NumPadTab:
+ return SpecialKey.Tab;
+ case Xwt.Key.Return:
+ case Xwt.Key.NumPadEnter:
+ return SpecialKey.Return;
+ case Xwt.Key.Escape:
+ return SpecialKey.Escape;
+ case Xwt.Key.Space:
+ case Xwt.Key.NumPadSpace:
+ return SpecialKey.Space;
+ case Xwt.Key.PageUp:
+ return SpecialKey.PageUp;
+ case Xwt.Key.PageDown:
+ return SpecialKey.PageDown;
+ case Xwt.Key.End:
+ case Xwt.Key.NumPadEnd:
+ return SpecialKey.End;
+ case Xwt.Key.Home:
+ case Xwt.Key.NumPadHome:
+ return SpecialKey.Home;
+ case Xwt.Key.Left:
+ case Xwt.Key.NumPadLeft:
+ return SpecialKey.Left;
+ case Xwt.Key.Up:
+ case Xwt.Key.NumPadUp:
+ return SpecialKey.Up;
+ case Xwt.Key.Right:
+ case Xwt.Key.NumPadRight:
+ return SpecialKey.Right;
+ case Xwt.Key.Down:
+ case Xwt.Key.NumPadDown:
+ return SpecialKey.Down;
+ case Xwt.Key.Delete:
+ case Xwt.Key.NumPadDelete:
+ return SpecialKey.Delete;
+ }
+ return SpecialKey.None;
+ }
+
+ static ModifierKeys ConvertModifiers (Xwt.ModifierKeys s)
+ {
+ ModifierKeys m = ModifierKeys.None;
+ if ((s & Xwt.ModifierKeys.Shift) != 0)
+ m |= ModifierKeys.Shift;
+ if ((s & Xwt.ModifierKeys.Control) != 0)
+ m |= ModifierKeys.Control;
+ if ((s & Xwt.ModifierKeys.Alt) != 0)
+ m |= ModifierKeys.Alt;
+ if ((s & Xwt.ModifierKeys.Command) != 0)
+ m |= ModifierKeys.Command;
+ if ((s & Xwt.ModifierKeys.Command) != 0)
+ m |= ModifierKeys.Command;
+ return m;
+ }
+ #endregion
+
#region GTK
public static KeyDescriptor FromGtk (Gdk.Key key, char ch, Gdk.ModifierType state)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ISyntaxHighlighting.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ISyntaxHighlighting.cs
index 6ff8b67139..74b3652f72 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ISyntaxHighlighting.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor.Highlighting/ISyntaxHighlighting.cs
@@ -61,6 +61,11 @@ namespace MonoDevelop.Ide.Editor.Highlighting
TextSegment = textSegment;
Segments = segments;
}
+
+ public override string ToString ()
+ {
+ return string.Format ("[HighlightedLine: TextSegment={0}, #Segments={1}, IsContinuedBeyondLineEnd={2}]", TextSegment, Segments?.Count, IsContinuedBeyondLineEnd);
+ }
}
/// <summary>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs
index 5f484ca83c..f47accabf2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/InternalExtensionAPI/ITextEditorImpl.cs
@@ -178,7 +178,9 @@ namespace MonoDevelop.Ide.Editor
string GetMarkup (int offset, int length, MarkupOptions options);
- IndentationTracker IndentationTracker { get; set; }
+ Task<string> GetMarkupAsync (int offset, int length, MarkupOptions options, CancellationToken cancellationToken);
+
+ IndentationTracker IndentationTracker { get; set; }
void SetSelectionSurroundingProvider (SelectionSurroundingProvider surroundingProvider);
void SetTextPasteHandler (TextPasteHandler textPasteHandler);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/OSXEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/OSXEditor.cs
index c16e62ebb9..2aff415590 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/OSXEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/OSXEditor.cs
@@ -67,8 +67,10 @@ namespace MonoDevelop.Ide.Editor
var editorFont = Xwt.Drawing.Font.FromName(fontName);
var nsFont = NSFont.FromFontName(editorFont.Family, (nfloat)editorFont.Size);
- using (var lm = new NSLayoutManager())
- return lm.DefaultLineHeightForFont(nsFont);
+ if (nsFont == null)
+ return -1;
+ using (var lm = new NSLayoutManager ())
+ return lm.DefaultLineHeightForFont (nsFont);
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs
index 2a9c71bebd..65610dcf2f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditor.cs
@@ -1274,7 +1274,7 @@ namespace MonoDevelop.Ide.Editor
return GetMarkup (offset, length, new MarkupOptions (MarkupFormat.Pango, fitIdeStyle));
}
- [Obsolete ("Use GetMarkup")]
+ [Obsolete ("Use GetMarkupAsync")]
public string GetPangoMarkup (ISegment segment, bool fitIdeStyle = false)
{
if (segment == null)
@@ -1298,6 +1298,22 @@ namespace MonoDevelop.Ide.Editor
return textEditorImpl.GetMarkup (segment.Offset, segment.Length, options);
}
+ public Task<string> GetMarkupAsync (int offset, int length, MarkupOptions options, CancellationToken cancellationToken = default)
+ {
+ if (options == null)
+ throw new ArgumentNullException (nameof (options));
+ return textEditorImpl.GetMarkupAsync (offset, length, options, cancellationToken);
+ }
+
+ public Task<string> GetMarkupAsync (ISegment segment, MarkupOptions options, CancellationToken cancellationToken = default)
+ {
+ if (options == null)
+ throw new ArgumentNullException (nameof (options));
+ if (segment == null)
+ throw new ArgumentNullException (nameof (segment));
+ return textEditorImpl.GetMarkupAsync (segment.Offset, segment.Length, options, cancellationToken);
+ }
+
public static implicit operator Microsoft.CodeAnalysis.Text.SourceText (TextEditor editor)
{
return new MonoDevelopSourceText (editor);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs
index 3a58a3156f..b4a27fa0df 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Editor/TextEditorViewContent.cs
@@ -85,7 +85,8 @@ namespace MonoDevelop.Ide.Editor
base.OnContentNameChanged ();
if (ContentName != textEditorImpl.ContentName && !string.IsNullOrEmpty (textEditorImpl.ContentName))
AutoSave.RemoveAutoSaveFile (textEditorImpl.ContentName);
- textEditor.FileName = ContentName;
+ if (ContentName != null) // Happens when a file is converted to an untitled file, but even in that case the text editor should be associated with the old location, otherwise typing can be messed up due to change of .editconfig settings etc.
+ textEditor.FileName = ContentName;
if (this.WorkbenchWindow?.Document != null)
textEditor.InitializeExtensionChain (this.WorkbenchWindow.Document);
UpdateTextEditorOptions (null, null);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ExternalTools/ExternalToolPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ExternalTools/ExternalToolPanel.cs
index 7e984d5b06..803b6f3985 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ExternalTools/ExternalToolPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.ExternalTools/ExternalToolPanel.cs
@@ -153,7 +153,7 @@ namespace MonoDevelop.Ide.ExternalTools
GettextCatalog.GetString ("Enter the title for this command"));
browseButton.Accessible.SetCommonAttributes ("ExternalTools.Command", null,
GettextCatalog.GetString ("Enter or select the path for the external command"));
- browseButton.Accessible.SetTitleUIElement (commandLabel.Accessible);
+ browseButton.SetEntryAccessibleTitleUIElement (commandLabel.Accessible);
argumentTextBox.SetCommonAccessibilityAttributes ("ExternalTools.Arguments", "",
GettextCatalog.GetString ("Enter the arguments for the external command"));
argumentTextBox.SetAccessibilityLabelRelationship (argumentLabel);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
index 58f710ad14..b33d81cc41 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
@@ -242,33 +242,37 @@ namespace MonoDevelop.Ide.FindInFiles
void SetupAccessibility ()
{
comboboxentryFind.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxentryFind",
- "Find",
+ labelFind,
GettextCatalog.GetString ("Enter string to find"));
- comboboxentryFind.SetAccessibilityLabelRelationship (labelFind);
+
+ comboboxScope.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxScope",
+ labelScope,
+ GettextCatalog.GetString ("Select where to search"));
}
void SetupAccessibilityForReplace ()
{
comboboxentryReplace.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxentryReplace",
- "Replace",
+ labelReplace,
GettextCatalog.GetString ("Enter string to replace"));
- comboboxentryReplace.SetAccessibilityLabelRelationship (labelReplace);
}
void SetupAccessibilityForPath ()
{
comboboxentryPath.SetCommonAccessibilityAttributes ("FindInFilesDialog.comboboxentryPath",
- "Path",
+ labelPath,
GettextCatalog.GetString ("Enter the Path"));
- comboboxentryPath.SetAccessibilityLabelRelationship (labelPath);
+
+ buttonBrowsePaths.SetCommonAccessibilityAttributes ("FindInFilesDialog.buttonBrowsePaths",
+ GettextCatalog.GetString ("Browse Path"),
+ GettextCatalog.GetString ("Select a folder"));
}
void SetupAccessibilityForSearch ()
{
- searchentryFileMask.SetCommonAccessibilityAttributes ("FindInFilesDialog.searchentryFileMask",
- "File Mask",
+ searchentryFileMask.SetEntryAccessibilityAttributes ("FindInFilesDialog.searchentryFileMask",
+ labelFileMask.Text,
GettextCatalog.GetString ("Enter the file mask"));
- searchentryFileMask.SetAccessibilityLabelRelationship (labelFileMask);
}
static void TableAddRow (Table table, uint row, Widget column1, Widget column2)
@@ -432,9 +436,7 @@ namespace MonoDevelop.Ide.FindInFiles
labelPath.MnemonicWidget = comboboxentryPath;
- SetupAccessibilityForPath ();
-
- buttonBrowsePaths = new Button { Label = "..." };
+ buttonBrowsePaths = new Button { Label = "…" };
buttonBrowsePaths.Clicked += ButtonBrowsePathsClicked;
buttonBrowsePaths.Show ();
hboxPath.PackStart (buttonBrowsePaths, false, false, 0);
@@ -454,6 +456,8 @@ namespace MonoDevelop.Ide.FindInFiles
checkbuttonRecursively.Show ();
TableAddRow (tableFindAndReplace, row, null, checkbuttonRecursively);
+
+ SetupAccessibilityForPath ();
}
void HideDirectoryPathUI ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs
index 18ad2c64d9..a3aba5fda2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/SearchResult.cs
@@ -121,7 +121,7 @@ namespace MonoDevelop.Ide.FindInFiles
const int maximumMarkupLength = 78;
- void CreateMarkup (SearchResultWidget widget, TextEditor doc, Editor.IDocumentLine line)
+ async void CreateMarkup (SearchResultWidget widget, TextEditor doc, Editor.IDocumentLine line)
{
int startIndex = 0, endIndex = 0;
@@ -175,35 +175,31 @@ namespace MonoDevelop.Ide.FindInFiles
markup = FormatMarkup (PangoHelper.ColorMarkupBackground (selectedMarkup, (int)startIndex, (int)endIndex, searchColor), trimStart, trimEnd, tabSize);
selectedMarkup = FormatMarkup (PangoHelper.ColorMarkupBackground (selectedMarkup, (int)startIndex, (int)endIndex, selectedSearchColor), trimStart, trimEnd, tabSize);
- Task.Run (delegate {
- var newMarkup = doc.GetMarkup (line.Offset + markupStartOffset + indent, length, new MarkupOptions (MarkupFormat.Pango));
- Runtime.RunInMainThread (delegate {
- newMarkup = widget.AdjustColors (newMarkup);
+ var newMarkup = await doc.GetMarkupAsync (line.Offset + markupStartOffset + indent, length, new MarkupOptions (MarkupFormat.Pango));
+ newMarkup = widget.AdjustColors (newMarkup);
- try {
- double delta = Math.Abs (b1 - b2);
- if (delta < 0.1) {
- var color1 = SyntaxHighlightingService.GetColor (widget.HighlightStyle, EditorThemeColors.FindHighlight);
- if (color1.L + 0.5 > 1.0) {
- color1.L -= 0.5;
- } else {
- color1.L += 0.5;
- }
- searchColor = color1;
- }
- if (startIndex != endIndex) {
- newMarkup = PangoHelper.ColorMarkupBackground (newMarkup, (int)startIndex, (int)endIndex, searchColor);
- }
- } catch (Exception e) {
- LoggingService.LogError ("Error while setting the text renderer markup to: " + newMarkup, e);
+ try {
+ double delta = Math.Abs (b1 - b2);
+ if (delta < 0.1) {
+ var color1 = SyntaxHighlightingService.GetColor (widget.HighlightStyle, EditorThemeColors.FindHighlight);
+ if (color1.L + 0.5 > 1.0) {
+ color1.L -= 0.5;
+ } else {
+ color1.L += 0.5;
}
+ searchColor = color1;
+ }
+ if (startIndex != endIndex) {
+ newMarkup = PangoHelper.ColorMarkupBackground (newMarkup, (int)startIndex, (int)endIndex, searchColor);
+ }
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while setting the text renderer markup to: " + newMarkup, e);
+ }
- newMarkup = FormatMarkup (newMarkup, trimStart, trimEnd, tabSize);
+ newMarkup = FormatMarkup (newMarkup, trimStart, trimEnd, tabSize);
- this.markup = newMarkup;
- widget.QueueDraw ();
- });
- });
+ this.markup = newMarkup;
+ widget.QueueDraw ();
}
static string FormatMarkup (string str, bool trimeStart, bool trimEnd, int tabSize)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsPanel.cs
index 62fc2913f1..dcc8dbdbc4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/MultiConfigItemOptionsPanel.cs
@@ -33,6 +33,7 @@ using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Dialogs;
using MonoDevelop.Projects;
using MonoDevelop.Components.AutoTest;
+using MonoDevelop.Components.AtkCocoaHelper;
using System.ComponentModel;
namespace MonoDevelop.Ide.Gui.Dialogs
@@ -104,7 +105,8 @@ namespace MonoDevelop.Ide.Gui.Dialogs
Gtk.VBox cbox = new Gtk.VBox (false, 6);
Gtk.HBox combosBox = new Gtk.HBox (false, 6) { Name = "panelWidgetCombosBox" };
cbox.PackStart (combosBox, false, false, 0);
- combosBox.PackStart (new Gtk.Label (GettextCatalog.GetString ("Configuration:")), false, false, 0);
+ var configurationLabel = new Gtk.Label (GettextCatalog.GetString ("Configuration:"));
+ combosBox.PackStart (configurationLabel, false, false, 0);
configListStore = new Gtk.ListStore (typeof(string), typeof(string));
configCombo = new Gtk.ComboBox (configListStore) { Name = "panelWidgetConfigurationCombo" };
SemanticModelAttribute modelAttr = new SemanticModelAttribute ("configListStore__DisplayName", "configListStore__ConfigName");
@@ -113,13 +115,24 @@ namespace MonoDevelop.Ide.Gui.Dialogs
configCombo.PackStart (cell, true);
configCombo.AddAttribute (cell, "text", 0);
combosBox.PackStart (configCombo, false, false, 0);
- combosBox.PackStart (new Gtk.Label (GettextCatalog.GetString ("Platform:")), false, false, 0);
+ var platformLabel = new Gtk.Label (GettextCatalog.GetString ("Platform:"));
+ combosBox.PackStart (platformLabel, false, false, 0);
platformCombo = Gtk.ComboBox.NewText ();
platformCombo.Name = "panelWidgetPlatformCombo";
combosBox.PackStart (platformCombo, false, false, 0);
cbox.PackStart (new Gtk.HSeparator (), false, false, 0);
cbox.ShowAll ();
+ configCombo.SetCommonAccessibilityAttributes (
+ configCombo.Name,
+ configurationLabel,
+ GettextCatalog.GetString ("Select a configuration"));
+
+ platformCombo.SetCommonAccessibilityAttributes (
+ platformCombo.Name,
+ platformLabel,
+ GettextCatalog.GetString ("Select a platform"));
+
cbox.Hidden += OnPageHidden;
cbox.Shown += OnPageShown;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/PolicyOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/PolicyOptionsPanel.cs
index e7e33028f1..f394643d00 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/PolicyOptionsPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/PolicyOptionsPanel.cs
@@ -122,8 +122,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs
}
policyCombo.Changed += HandlePolicyComboChanged;
-
- return vbox;
+
+ var widget = new PolicyOptionsWidgetContainer (vbox);
+ return widget;
}
void LoadPolicy (T policy)
@@ -340,5 +341,21 @@ namespace MonoDevelop.Ide.Gui.Dialogs
loading = false;
}
}
+
+ /// <summary>
+ /// Container for the VBox used to display the options panel information.
+ /// This is needed since using just a VBox causes Voice Over on the Mac to
+ /// read out the UI widgets multiple times with using the arrow keys.
+ /// </summary>
+ class PolicyOptionsWidgetContainer : Bin
+ {
+ public PolicyOptionsWidgetContainer (VBox child)
+ {
+ BinContainer.Attach (this);
+
+ Add (child);
+ ShowAll ();
+ }
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LoadSavePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LoadSavePanel.cs
index ce367f5dd7..5412251028 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LoadSavePanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LoadSavePanel.cs
@@ -81,7 +81,9 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
loadUserDataCheckButton.Active = IdeApp.Preferences.LoadDocumentUserProperties;
createBackupCopyCheckButton.Active = IdeApp.Preferences.CreateFileBackupCopies;
- loadPrevProjectCheckButton.Active = IdeApp.Preferences.LoadPrevSolutionOnStartup.Value;
+ openStartWindowRadioButton.Active = IdeApp.Preferences.StartupBehaviour.Value == OnStartupBehaviour.ShowStartWindow;
+ loadPrevProjectRadioButton.Active = IdeApp.Preferences.StartupBehaviour.Value == OnStartupBehaviour.LoadPreviousSolution;
+ emptyEnvironmentRadioButton.Active = IdeApp.Preferences.StartupBehaviour.Value == OnStartupBehaviour.EmptyEnvironment;
SetupAccessibility ();
}
@@ -95,8 +97,12 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
loadUserDataCheckButton.SetCommonAccessibilityAttributes ("LoadSavePanel.loadUserData", "",
GettextCatalog.GetString ("Check to load the user specific settings with the solution"));
- loadPrevProjectCheckButton.SetCommonAccessibilityAttributes ("LoadSavePanel.loadPrevious", "",
+ openStartWindowRadioButton.SetCommonAccessibilityAttributes ("LoadSavePanel.openStartWindow", "",
+ GettextCatalog.GetString ("Check to load the Start Window when starting the application"));
+ loadPrevProjectRadioButton.SetCommonAccessibilityAttributes ("LoadSavePanel.loadPrevious", "",
GettextCatalog.GetString ("Check to load the previous solution when starting the application"));
+ emptyEnvironmentRadioButton.SetCommonAccessibilityAttributes ("LoadSavePanel.emptyEnvironment", "",
+ GettextCatalog.GetString ("Check to load an empty environment when starting the application"));
createBackupCopyCheckButton.SetCommonAccessibilityAttributes ("LoadSavePanel.createBackup", "",
GettextCatalog.GetString ("Check to always create a backup copy"));
}
@@ -116,7 +122,14 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
public void Store ()
{
- IdeApp.Preferences.LoadPrevSolutionOnStartup.Value = loadPrevProjectCheckButton.Active;
+ if (openStartWindowRadioButton.Active) {
+ IdeApp.Preferences.StartupBehaviour.Value = OnStartupBehaviour.ShowStartWindow;
+ } else if (loadPrevProjectRadioButton.Active) {
+ IdeApp.Preferences.StartupBehaviour.Value = OnStartupBehaviour.LoadPreviousSolution;
+ } else if (emptyEnvironmentRadioButton.Active) {
+ IdeApp.Preferences.StartupBehaviour.Value = OnStartupBehaviour.EmptyEnvironment;
+ }
+
IdeApp.Preferences.LoadDocumentUserProperties.Value = loadUserDataCheckButton.Active;
IdeApp.Preferences.CreateFileBackupCopies.Value = createBackupCopyCheckButton.Active;
IdeApp.Preferences.ProjectsDefaultPath.Value = folderEntry.Path;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
index 7aae5b5548..d313c4f2e1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
@@ -451,7 +451,7 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
project.ParentSolution.StartupItem = project;
await project.ParentSolution.SaveUserProperties ();
}
-
+
public override void DeleteItem ()
{
Project prj = CurrentNode.DataItem as Project;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectPadContextMenu.addin.xml b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectPadContextMenu.addin.xml
index 864d1822a8..c711f6e07d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectPadContextMenu.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectPadContextMenu.addin.xml
@@ -52,6 +52,9 @@
<Condition id="ItemType" value="Project">
<CommandItem id = "MonoDevelop.Ide.Commands.ProjectCommands.SetAsStartupProject" />
</Condition>
+ <Condition id="ItemType" value="Solution">
+ <CommandItem id="MonoDevelop.Ide.Commands.ProjectCommands.SetStartupProjects" />
+ </Condition>
<SeparatorItem id = "RunSectionEnd" />
<!-- Publish section -->
@@ -151,7 +154,7 @@
</Condition>
<Condition id="ItemType" value="IBuildTarget">
<CommandItem id = "MonoDevelop.Ide.Commands.ProjectCommands.Options" />
- </Condition>
+ </Condition>
<Condition id="ItemType" value="ProjectItem">
<CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.ShowProperties" />
</Condition>
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs
index ac494f3372..17e480b13d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs
@@ -57,7 +57,7 @@ namespace MonoDevelop.Ide.Gui.Pads
tree_view.AppendColumn ("name_col", tree_view.TextRenderer, "text", 0);
tree_view.RowExpanded += new Gtk.RowExpandedHandler (RowExpanded);
- tree_view.Selection.Changed += new EventHandler (RowActivated);
+ tree_view.RowActivated += RowActivated;
store = new TreeStore (typeof (string), typeof (Node));
tree_view.Model = store;
@@ -110,10 +110,16 @@ namespace MonoDevelop.Ide.Gui.Pads
{
Gtk.TreeIter iter;
Gtk.TreeModel model;
-
+
if (tree_view.Selection.GetSelected (out model, out iter)) {
+ var path = store.GetPath (iter);
+
+ if (path.Equals (store.GetPath (root_iter))) return;
- if (store.GetPath (iter).Equals (store.GetPath (root_iter))) return;
+ if (store.IterHasChild (iter)) {
+ tree_view.ExpandRow (path, false);
+ return;
+ }
Node n = (Node)store.GetValue (iter, 1);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
index 36f1a59736..5aff4156f8 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
@@ -427,7 +427,7 @@ namespace MonoDevelop.Ide.Gui
} else
type = "(not a file)";
- var metadata = new Dictionary<string,string> () {
+ var metadata = new Dictionary<string,object> () {
{ "FileType", type },
{ "DisplayBinding", content.GetType ().FullName },
};
@@ -435,7 +435,7 @@ namespace MonoDevelop.Ide.Gui
if (isFile)
metadata ["DisplayBindingAndType"] = type + " | " + content.GetType ().FullName;
- Counters.DocumentOpened.Inc (metadata);
+ Counters.DocumentOpened.Inc (1, null, metadata);
var mimeimage = PrepareShowView (content);
var addToControl = notebook ?? DockNotebook.ActiveNotebook ?? tabControl;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs
index c566cf06e8..bb3392ae93 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Styles.cs
@@ -473,7 +473,7 @@ namespace MonoDevelop.Ide.Gui
PrimaryBackgroundColor = BaseBackgroundColor;
SecondaryBackgroundDarkerColor = Color.FromName ("#e7eaee");
SecondaryBackgroundLighterColor = Color.FromName ("#f9f9fb");
- SecondaryTextColorHexString = "#888888";
+ SecondaryTextColorHexString = "#767676";
SecondaryTextColor = Color.FromName (SecondaryTextColorHexString);
SecondarySelectionTextColor = Color.FromName ("#ffffff");
PadBackground = Color.FromName ("#fafafa");
@@ -597,7 +597,7 @@ namespace MonoDevelop.Ide.Gui
PrimaryBackgroundColor = BaseBackgroundColor;
SecondaryBackgroundDarkerColor = Color.FromName ("#484848");
SecondaryBackgroundLighterColor = SeparatorColor;
- SecondaryTextColorHexString = "#777777";
+ SecondaryTextColorHexString = "#ababab";
SecondaryTextColor = Color.FromName (SecondaryTextColorHexString);
SecondarySelectionTextColor = Color.FromName ("#ffffff");
PadBackground = Color.FromName ("#525252");
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CommonAssemblySigningPreferences.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CommonAssemblySigningPreferences.cs
index 737e07a91f..b51fe44504 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CommonAssemblySigningPreferences.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CommonAssemblySigningPreferences.cs
@@ -53,7 +53,6 @@ namespace MonoDevelop.Ide.Projects.OptionPanels
signAssemblyCheckbutton.SetCommonAccessibilityAttributes ("SigningOptions.Sign", "",
GettextCatalog.GetString ("Check to enable assembly signing"));
strongNameFileEntry.EntryAccessible.Name = "SigningOptions.NameFile";
- strongNameFileEntry.EntryAccessible.SetLabel (GettextCatalog.GetString ("Strong Name File"));
strongNameFileEntry.EntryAccessible.Description = GettextCatalog.GetString ("Enter the Strong Name File");
strongNameFileEntry.EntryAccessible.SetTitleUIElement (strongNameFileLabel.Accessible);
strongNameFileLabel.Accessible.SetTitleFor (strongNameFileEntry.EntryAccessible);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs
index 1c3cfc7ec8..1011a33b74 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/CustomCommandWidget.cs
@@ -198,10 +198,6 @@ namespace MonoDevelop.Ide.Projects.OptionPanels
} else
cmd.Type = supportedTypes [comboType.Active];
UpdateControls ();
- if (cmd.Type == CustomCommandType.Custom)
- entryName.GrabFocus ();
- else
- entryCommand.GrabFocus ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/RunConfigurationsList.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/RunConfigurationsList.cs
index 5fb0b15aff..320f9ed81e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/RunConfigurationsList.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/RunConfigurationsList.cs
@@ -38,17 +38,19 @@ namespace MonoDevelop.Ide.Projects.OptionPanels
Xwt.ListStore listStore;
Xwt.DataField<RunConfiguration> configCol = new Xwt.DataField<RunConfiguration> ();
Xwt.DataField<string> configNameCol = new Xwt.DataField<string> ();
+ Xwt.DataField<string> accessibleCol = new Xwt.DataField<string> ();
Xwt.DataField<Xwt.Drawing.Image> configIconCol = new Xwt.DataField<Xwt.Drawing.Image> ();
public RunConfigurationsList ()
{
- listStore = new Xwt.ListStore (configCol, configNameCol, configIconCol);
+ listStore = new Xwt.ListStore (configCol, configNameCol, configIconCol, accessibleCol);
list = new Xwt.ListView (listStore);
list.HeadersVisible = false;
var imgCell = new ImageCellView { ImageField = configIconCol };
var textCell = new TextCellView { MarkupField = configNameCol };
list.Columns.Add (GettextCatalog.GetString ("Name"), imgCell, textCell);
+ textCell.AccessibleFields.Label = accessibleCol;
Content = list;
@@ -64,7 +66,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels
var r = listStore.AddRow ();
var txt = "<b>" + c.Name + "</b>\n" + c.Summary;
var icon = !string.IsNullOrEmpty (c.IconId) ? ImageService.GetIcon (c.IconId) : ImageService.GetIcon ("md-prefs-play", Gtk.IconSize.Dnd);
- listStore.SetValues (r, configCol, c, configNameCol, txt, configIconCol, icon);
+ listStore.SetValues (r, configCol, c, configNameCol, txt, configIconCol, icon, accessibleCol, c.Name + " " + c.Summary);
}
if (currentRow != -1) {
if (currentRow < listStore.RowCount)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs
index 1076e98024..0fa378a615 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects.OptionPanels/SolutionRunConfigurationsPanel.cs
@@ -53,11 +53,11 @@ namespace MonoDevelop.Ide.Projects.OptionPanels
Solution = (Solution)dataObject;
- foreach (var rc in Solution.MultiStartupRunConfigurations)
- configs.Add (new SolutionRunConfigInfo { ProjectConfig = rc, EditedConfig = new MultiItemSolutionRunConfiguration (rc) });
-
- foreach (var c in configs)
+ foreach (var rc in Solution.MultiStartupRunConfigurations) {
+ var c = new SolutionRunConfigInfo { ProjectConfig = rc, EditedConfig = new MultiItemSolutionRunConfiguration (rc) };
+ configs.Add (c);
AddPanel (c);
+ }
ParentDialog.ExpandChildren (this);
}
@@ -120,7 +120,7 @@ namespace MonoDevelop.Ide.Projects.OptionPanels
internal void ShowConfiguration (MultiItemSolutionRunConfiguration editedConfig)
{
- var rc = configs.First (ci => ci.EditedConfig == editedConfig);
+ var rc = configs.First (ci => ci.EditedConfig.Name == editedConfig.Name);
var section = sections [rc];
ParentDialog.ShowPage (section);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkProjectConfigurationWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkProjectConfigurationWidget.cs
index 24717e2c89..ec65b9a593 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkProjectConfigurationWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkProjectConfigurationWidget.cs
@@ -87,6 +87,13 @@ namespace MonoDevelop.Ide.Projects
projectNameTextBox.Accessible.Description = GettextCatalog.GetString ("Enter the name for the new project");
projectNameTextBox.Accessible.SetTitleUIElement (projectNameLabel.Accessible);
+ solutionNameLabel.Accessible.Name = "ProjectConfigurationWidget.SolutionNameLabel";
+ solutionNameLabel.Accessible.SetTitleFor (solutionNameTextBox.Accessible);
+
+ solutionNameTextBox.Accessible.Name = "ProjectConfigurationWidget.SolutionNameTextBox";
+ solutionNameTextBox.Accessible.Description = GettextCatalog.GetString ("Enter the name for the new solution");
+ solutionNameTextBox.Accessible.SetTitleUIElement (solutionNameLabel.Accessible);
+
locationLabel.Accessible.Name = "ProjectConfigurationWidget.LocationLabel";
locationLabel.Accessible.SetTitleFor (locationTextBox.Accessible, browseButton.Accessible);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewSolutionRunConfigurationDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewSolutionRunConfigurationDialog.cs
new file mode 100644
index 0000000000..e6a0986279
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewSolutionRunConfigurationDialog.cs
@@ -0,0 +1,98 @@
+//
+// NewSolutionRunConfigurationDialog.cs
+//
+// Author:
+// Rodrigo Moya <rodrigo.moya@xamarin.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 Xwt;
+using MonoDevelop.Core;
+
+namespace MonoDevelop.Ide.Projects
+{
+ public class NewSolutionRunConfigurationDialog : Dialog
+ {
+ readonly TextEntry runConfigNameEntry;
+ readonly DialogButton createButton;
+
+ public NewSolutionRunConfigurationDialog ()
+ {
+ Title = GettextCatalog.GetString ("Create Solution Run Configuration");
+ Resizable = false;
+
+ var box = new VBox ();
+ Content = box;
+
+ var label = new Label (GettextCatalog.GetString ("Solution run configurations let you run multiple projects at once. Please provide a name to\nbe shown in the toolbar for this Solution run configuration.")) {
+ CanGetFocus = false,
+ Wrap = WrapMode.Word
+ };
+ box.PackStart (label, expand: true, marginBottom: 12);
+
+ var hbox = new HBox ();
+ hbox.PackStart (new Label (GettextCatalog.GetString ("Run configuration name:")) {
+ CanGetFocus = false
+ });
+
+ runConfigNameEntry = new TextEntry {
+ Text = GettextCatalog.GetString ("Multiple Projects")
+ };
+ runConfigNameEntry.Changed += OnConfigNameChanged;
+ hbox.PackStart (runConfigNameEntry, true, true);
+
+ box.PackStart (hbox, true, true);
+
+ createButton = new DialogButton (new Command ("create", GettextCatalog.GetString ("Create Run Configuration")));
+ Buttons.Add (Command.Cancel);
+ Buttons.Add (createButton);
+ DefaultCommand = createButton.Command;
+ }
+
+ public string RunConfigurationName => runConfigNameEntry.Text;
+
+ void OnConfigNameChanged (object sender, EventArgs e)
+ {
+ createButton.Sensitive = !string.IsNullOrEmpty (runConfigNameEntry.Text);
+ }
+
+ protected override void OnCommandActivated (Command cmd)
+ {
+ if (cmd.Id == createButton.Command.Id) {
+ Respond (cmd);
+ return;
+ }
+ base.OnCommandActivated (cmd);
+ }
+
+ protected override void OnShown ()
+ {
+ base.OnShown ();
+ runConfigNameEntry.SetFocus ();
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ runConfigNameEntry.Changed -= OnConfigNameChanged;
+ base.Dispose (disposing);
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs
index f297eeec48..8013d83a31 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/SelectReferenceDialog.cs
@@ -67,10 +67,11 @@ namespace MonoDevelop.Ide.Projects
const int RecentFileListSize = 75;
const int NameColumn = 0;
- const int TypeNameColumn = 1;
- const int LocationColumn = 2;
- const int ProjectReferenceColumn = 3;
- const int IconColumn = 4;
+ const int SecondaryNameColumn = 1;
+ const int TypeNameColumn = 2;
+ const int LocationColumn = 3;
+ const int ProjectReferenceColumn = 4;
+ const int IconColumn = 5;
public ProjectReferenceCollection ReferenceInformations {
get {
@@ -127,9 +128,9 @@ namespace MonoDevelop.Ide.Projects
TreeIter AddAssemplyReference (ProjectReference refInfo)
{
- string txt = GLib.Markup.EscapeText (System.IO.Path.GetFileName (refInfo.Reference)) + "\n";
- txt += "<span color='darkgrey'><small>" + GLib.Markup.EscapeText (System.IO.Path.GetFullPath (refInfo.HintPath)) + "</small></span>";
- return refTreeStore.AppendValues (txt, GetTypeText (refInfo), System.IO.Path.GetFullPath (refInfo.Reference), refInfo, ImageService.GetIcon ("md-empty-file-icon", IconSize.Dnd));
+ string txt = GLib.Markup.EscapeText (System.IO.Path.GetFileName (refInfo.Reference));
+ string secondaryTxt = GLib.Markup.EscapeText (System.IO.Path.GetFullPath (refInfo.HintPath));
+ return refTreeStore.AppendValues (txt, secondaryTxt, GetTypeText (refInfo), System.IO.Path.GetFullPath (refInfo.Reference), refInfo, ImageService.GetIcon ("md-empty-file-icon", IconSize.Dnd));
}
TreeIter AddProjectReference (ProjectReference refInfo)
@@ -139,19 +140,22 @@ namespace MonoDevelop.Ide.Projects
Project p = refInfo.ResolveProject (c);
if (p == null) return TreeIter.Zero;
-
- string txt = GLib.Markup.EscapeText (System.IO.Path.GetFileName (refInfo.Reference)) + "\n";
- txt += "<span color='darkgrey'><small>" + GLib.Markup.EscapeText (p.BaseDirectory.ToString ()) + "</small></span>";
- return refTreeStore.AppendValues (txt, GetTypeText (refInfo), p.BaseDirectory.ToString (), refInfo, ImageService.GetIcon ("md-project", IconSize.Dnd));
+
+ string txt = GLib.Markup.EscapeText (System.IO.Path.GetFileName (refInfo.Reference));
+ string secondaryTxt = GLib.Markup.EscapeText (p.BaseDirectory.ToString ());
+ return refTreeStore.AppendValues (txt, secondaryTxt, GetTypeText (refInfo), p.BaseDirectory.ToString (), refInfo, ImageService.GetIcon ("md-project", IconSize.Dnd));
}
TreeIter AddPackageReference (ProjectReference refInfo)
{
string txt = GLib.Markup.EscapeText (System.IO.Path.GetFileNameWithoutExtension (refInfo.Reference));
+ string secondaryTxt = string.Empty;
int i = refInfo.Reference.IndexOf (',');
- if (i != -1)
- txt = GLib.Markup.EscapeText (txt.Substring (0, i)) + "\n<span color='darkgrey'><small>" + GLib.Markup.EscapeText (refInfo.Reference.Substring (i+1).Trim()) + "</small></span>";
- return refTreeStore.AppendValues (txt, GetTypeText (refInfo), refInfo.Reference, refInfo, ImageService.GetIcon ("md-package", IconSize.Dnd));
+ if (i != -1) {
+ txt = GLib.Markup.EscapeText (txt.Substring (0, i));
+ secondaryTxt = GLib.Markup.EscapeText (refInfo.Reference.Substring (i + 1).Trim ());
+ }
+ return refTreeStore.AppendValues (txt, secondaryTxt, GetTypeText (refInfo), refInfo.Reference, refInfo, ImageService.GetIcon ("md-package", IconSize.Dnd));
}
public SelectReferenceDialog ()
@@ -169,7 +173,7 @@ namespace MonoDevelop.Ide.Projects
boxRefs.WidthRequest = 200;
- refTreeStore = new ListStore (typeof (string), typeof(string), typeof(string), typeof(ProjectReference), typeof(Xwt.Drawing.Image));
+ refTreeStore = new ListStore (typeof (string), typeof(string), typeof(string), typeof(string), typeof(ProjectReference), typeof(Xwt.Drawing.Image));
ReferencesTreeView.Model = refTreeStore;
TreeViewColumn col = new TreeViewColumn ();
@@ -178,9 +182,10 @@ namespace MonoDevelop.Ide.Projects
crp.Yalign = 0f;
col.PackStart (crp, false);
col.AddAttribute (crp, "image", IconColumn);
- CellRendererText text_render = new CellRendererText ();
+ var text_render = new CustomSelectedReferenceCellRenderer ();
col.PackStart (text_render, true);
- col.AddAttribute (text_render, "markup", NameColumn);
+ col.AddAttribute (text_render, "text-markup", NameColumn);
+ col.AddAttribute (text_render, "secondary-text-markup", SecondaryNameColumn);
text_render.Ellipsize = Pango.EllipsizeMode.End;
ReferencesTreeView.AppendColumn (col);
@@ -236,7 +241,7 @@ namespace MonoDevelop.Ide.Projects
header.Add (w);
selectedHeader.Add (header);
- RemoveReferenceButton.CanFocus = false;
+ RemoveReferenceButton.CanFocus = true;
ReferencesTreeView.Selection.Changed += new EventHandler (OnChanged);
Child.ShowAll ();
OnChanged (null, null);
@@ -551,5 +556,99 @@ namespace MonoDevelop.Ide.Projects
filterEntry.SizeAllocate (new Gdk.Rectangle (Allocation.Width - w - 1, 0, w, h));
}
}
+
+ class CustomSelectedReferenceCellRenderer : CellRendererText
+ {
+ Pango.Layout layout;
+ string markup;
+ string secondarymarkup;
+
+ [GLib.Property ("text-markup")]
+ public string TextMarkup {
+ get { return markup; }
+ set {
+ markup = value;
+ if (!string.IsNullOrEmpty (secondarymarkup))
+ Markup = markup + " " + secondarymarkup;
+ else
+ Markup = markup;
+ }
+ }
+
+ [GLib.Property ("secondary-text-markup")]
+ public string SecondaryTextMarkup {
+ get { return secondarymarkup; }
+ set {
+ secondarymarkup = value;
+ if (!string.IsNullOrEmpty (secondarymarkup))
+ Markup = markup + " " + secondarymarkup;
+ else
+ Markup = markup;
+ }
+ }
+
+ protected override void Render (Gdk.Drawable window, Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, CellRendererState flags)
+ {
+ StateType st = StateType.Normal;
+ if ((flags & CellRendererState.Prelit) != 0)
+ st = StateType.Prelight;
+ if ((flags & CellRendererState.Focused) != 0)
+ st = StateType.Normal;
+ if ((flags & CellRendererState.Insensitive) != 0)
+ st = StateType.Insensitive;
+ if ((flags & CellRendererState.Selected) != 0)
+ st = widget.HasFocus ? StateType.Selected : Gtk.StateType.Active;
+
+ SetupLayout (widget, flags);
+
+ int w, h;
+ layout.GetPixelSize (out w, out h);
+
+ const int textXOffset = 2; // Shift text up slightly in the row.
+ int tx = cell_area.X + (int)Xpad;
+ int ty = cell_area.Y + (cell_area.Height - h) / 2 - textXOffset;
+
+ int textPixelWidth = cell_area.Width - ((int)Xpad * 2) ;
+ layout.Width = (int)(textPixelWidth * Pango.Scale.PangoScale);
+
+ window.DrawLayout (widget.Style.TextGC (st), tx, ty, layout);
+ }
+
+ public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
+ {
+ base.GetSize (widget, ref cell_area, out x_offset, out y_offset, out width, out height);
+ SetupLayout (widget);
+
+ int layoutWidth = 0;
+ layout.GetPixelSize (out layoutWidth, out height);
+ }
+
+ void SetupLayout (Widget widget, CellRendererState flags = 0)
+ {
+ if (layout == null || layout.Context != widget.PangoContext) {
+ if (layout != null)
+ layout.Dispose ();
+ layout = new Pango.Layout (widget.PangoContext);
+ layout.Ellipsize = Ellipsize;
+ }
+
+ string newmarkup = TextMarkup;
+ if (!string.IsNullOrEmpty (SecondaryTextMarkup)) {
+ if (Platform.IsMac && flags.HasFlag (CellRendererState.Selected))
+ newmarkup += "\n<span foreground='" + Gui.Styles.SecondarySelectionTextColor.ToHexString (false) + "'><small>" + SecondaryTextMarkup + "</small></span>";
+ else
+ newmarkup += "\n<span foreground='" + Gui.Styles.SecondaryTextColor.ToHexString (false) + "'><small>" + SecondaryTextMarkup + "</small></span>";
+ }
+
+ layout.SetMarkup (newmarkup);
+ }
+
+ protected override void OnDestroyed ()
+ {
+ base.OnDestroyed ();
+ if (layout != null)
+ layout.Dispose ();
+ }
+ }
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/HackyWorkspaceFilesCache.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/HackyWorkspaceFilesCache.cs
new file mode 100644
index 0000000000..cdeaf0aa90
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/HackyWorkspaceFilesCache.cs
@@ -0,0 +1,236 @@
+//
+// HackyWorkspaceFilesCache.cs
+//
+// Author:
+// Marius Ungureanu <maungu@microsoft.com>
+//
+// Copyright (c) 2019 Microsoft Inc.
+//
+// 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.Immutable;
+using System.IO;
+using System.Linq;
+using MonoDevelop.Core;
+using MonoDevelop.Core.FeatureConfiguration;
+using MonoDevelop.Projects;
+using Newtonsoft.Json;
+
+namespace MonoDevelop.Ide.TypeSystem
+{
+ class HackyWorkspaceFilesCache
+ {
+ const int format = 1;
+ readonly bool enabled = FeatureSwitchService.IsFeatureEnabled ("HackyCache").GetValueOrDefault ();
+
+ readonly FilePath cacheDir;
+
+ Dictionary<FilePath, ProjectCache> cachedItems = new Dictionary<FilePath, ProjectCache> ();
+
+ public HackyWorkspaceFilesCache (Solution solution)
+ {
+ if (!IdeApp.IsInitialized || !enabled || solution == null)
+ return;
+
+ cacheDir = solution.GetPreferencesDirectory ().Combine ("hacky-project-cache");
+ Directory.CreateDirectory (cacheDir);
+
+ LoadCache (solution);
+ }
+
+ void LoadCache (Solution sol)
+ {
+ var solConfig = sol.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
+
+ var serializer = new JsonSerializer ();
+ foreach (var project in sol.GetAllProjects ()) {
+ var config = solConfig.GetMappedConfiguration (project);
+
+ var projectFilePath = project.FileName;
+ var cacheFilePath = GetProjectCacheFile (project, config);
+
+ try {
+ if (!File.Exists (cacheFilePath))
+ continue;
+
+ using (var sr = File.OpenText (cacheFilePath)) {
+ var value = (ProjectCache)serializer.Deserialize (sr, typeof (ProjectCache));
+
+ if (format != value.Format || value.TimeStamp != File.GetLastWriteTimeUtc (projectFilePath))
+ continue;
+
+ cachedItems [projectFilePath] = value;
+
+ }
+ } catch (Exception ex) {
+ LoggingService.LogError ("Could not deserialize project cache", ex);
+ TryDeleteFile (cacheFilePath);
+ continue;
+ }
+ }
+ }
+
+ string GetProjectCacheFile (Project proj, string configuration)
+ {
+ return cacheDir.Combine (proj.FileName.FileNameWithoutExtension + "-" + configuration + ".json");
+ }
+
+ static void TryDeleteFile (string file)
+ {
+ try {
+ File.Delete (file);
+ } catch (Exception ex) {
+ LoggingService.LogError ("Could not delete cache file", ex);
+ }
+ }
+
+ public void Update (ProjectConfiguration projConfig, Project proj, MonoDevelopWorkspace.ProjectDataMap projectMap,
+ ImmutableArray<ProjectFile> files,
+ ImmutableArray<FilePath> analyzers,
+ ImmutableArray<MonoDevelopMetadataReference> metadataReferences,
+ ImmutableArray<Microsoft.CodeAnalysis.ProjectReference> projectReferences)
+ {
+ if (!enabled)
+ return;
+
+ var paths = new string [files.Length];
+ var actions = new string [files.Length];
+
+ for (int i = 0; i < files.Length; ++i) {
+ paths [i] = files [i].FilePath;
+ actions [i] = files [i].BuildAction;
+ }
+
+ var projectRefs = new ReferenceItem [projectReferences.Length];
+ for (int i = 0; i < projectReferences.Length; ++i) {
+ var pr = projectReferences [i];
+ var mdProject = projectMap.GetMonoProject (pr.ProjectId);
+ projectRefs [i] = new ReferenceItem {
+ FilePath = mdProject.FileName,
+ Aliases = pr.Aliases.ToArray (),
+ };
+ }
+
+ var item = new ProjectCache {
+ Format = format,
+ Analyzers = analyzers.Select(x => (string)x).ToArray (),
+ Files = paths,
+ BuildActions = actions,
+ TimeStamp = File.GetLastWriteTimeUtc (proj.FileName),
+ MetadataReferences = metadataReferences.Select(x => {
+ var ri = new ReferenceItem {
+ FilePath = x.FilePath,
+ Aliases = x.Properties.Aliases.ToArray (),
+ };
+ return ri;
+ }).ToArray (),
+ ProjectReferences = projectRefs,
+ };
+
+ var cacheFile = GetProjectCacheFile (proj, projConfig.Id);
+
+ var serializer = new JsonSerializer ();
+ using (var fs = File.Open (cacheFile, FileMode.Create))
+ using (var sw = new StreamWriter (fs)) {
+ serializer.Serialize (sw, item);
+ }
+ }
+
+
+ public bool TryGetCachedItems (Project p, MonoDevelopMetadataReferenceManager provider, MonoDevelopWorkspace.ProjectDataMap projectMap,
+ out ImmutableArray<ProjectFile> files,
+ out ImmutableArray<FilePath> analyzers,
+ out ImmutableArray<MonoDevelopMetadataReference> metadataReferences,
+ out ImmutableArray<Microsoft.CodeAnalysis.ProjectReference> projectReferences)
+ {
+ files = ImmutableArray<ProjectFile>.Empty;
+ analyzers = ImmutableArray<FilePath>.Empty;
+ metadataReferences = ImmutableArray<MonoDevelopMetadataReference>.Empty;
+ projectReferences = ImmutableArray<Microsoft.CodeAnalysis.ProjectReference>.Empty;
+
+ if (!cachedItems.TryGetValue (p.FileName, out var cachedData)) {
+ return false;
+ }
+
+ cachedItems.Remove (p.FileName);
+
+ if (cachedData.TimeStamp != File.GetLastWriteTimeUtc (p.FileName))
+ return false;
+
+ var filesBuilder = ImmutableArray.CreateBuilder<ProjectFile> (cachedData.Files.Length);
+ for (int i = 0; i < cachedData.Files.Length; ++i) {
+ filesBuilder.Add(new ProjectFile (cachedData.Files [i], cachedData.BuildActions [i]) {
+ Project = p,
+ });
+ }
+
+ files = filesBuilder.MoveToImmutable ();
+
+ var analyzersBuilder = ImmutableArray.CreateBuilder<FilePath> (cachedData.Analyzers.Length);
+ foreach (var analyzer in cachedData.Analyzers)
+ analyzersBuilder.Add (analyzer);
+ analyzers = analyzersBuilder.MoveToImmutable ();
+
+ var mrBuilder = ImmutableArray.CreateBuilder<MonoDevelopMetadataReference> (cachedData.MetadataReferences.Length);
+ foreach (var item in cachedData.MetadataReferences) {
+ var aliases = item.Aliases != null ? item.Aliases.ToImmutableArray () : default;
+ var reference = provider.GetOrCreateMetadataReference (item.FilePath, new Microsoft.CodeAnalysis.MetadataReferenceProperties(aliases: aliases));
+ mrBuilder.Add (reference);
+ }
+ metadataReferences = mrBuilder.MoveToImmutable ();
+
+ var sol = p.ParentSolution;
+ var solConfig = sol.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
+ var allProjects = sol.GetAllProjects ().ToDictionary (x => x.FileName, x => x);
+
+ var prBuilder = ImmutableArray.CreateBuilder<Microsoft.CodeAnalysis.ProjectReference> (cachedData.ProjectReferences.Length);
+ foreach (var item in cachedData.ProjectReferences) {
+ if (!allProjects.TryGetValue (item.FilePath, out var mdProject))
+ return false;
+
+ var aliases = item.Aliases != null ? item.Aliases.ToImmutableArray () : default;
+ var pr = new Microsoft.CodeAnalysis.ProjectReference (projectMap.GetOrCreateId (mdProject, null), aliases.ToImmutableArray ());
+ prBuilder.Add (pr);
+ }
+ projectReferences = prBuilder.MoveToImmutable ();
+ return true;
+ }
+
+ [Serializable]
+ class ProjectCache
+ {
+ public int Format;
+ public DateTime TimeStamp;
+
+ public ReferenceItem [] ProjectReferences;
+ public ReferenceItem[] MetadataReferences;
+ public string [] Files;
+ public string [] BuildActions;
+ public string [] Analyzers;
+ }
+
+ [Serializable]
+ internal class ReferenceItem
+ {
+ public string FilePath;
+ public string [] Aliases = Array.Empty<string> ();
+ }
+ }
+}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs
index 32a52a8ca6..66d10598f3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/MonoDevelopWorkspace.ProjectSystemHandler.cs
@@ -37,6 +37,7 @@ using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
using MonoDevelop.Core;
using MonoDevelop.Ide.Editor.Projection;
+using MonoDevelop.Projects;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -49,6 +50,7 @@ namespace MonoDevelop.Ide.TypeSystem
readonly ProjectionData projections;
readonly Lazy<MetadataReferenceHandler> metadataHandler;
readonly Lazy<HostDiagnosticUpdateSource> hostDiagnosticUpdateSource;
+ readonly HackyWorkspaceFilesCache hackyCache;
bool added;
readonly object addLock = new object ();
@@ -60,6 +62,7 @@ namespace MonoDevelop.Ide.TypeSystem
this.workspace = workspace;
this.projectMap = projectMap;
this.projections = projections;
+ this.hackyCache = new HackyWorkspaceFilesCache (workspace.MonoDevelopSolution);
metadataHandler = new Lazy<MetadataReferenceHandler> (() => new MetadataReferenceHandler (workspace.MetadataReferenceManager, projectMap));
hostDiagnosticUpdateSource = new Lazy<HostDiagnosticUpdateSource> (() => new HostDiagnosticUpdateSource (workspace, Composition.CompositionManager.GetExportedValue<IDiagnosticUpdateSourceRegistrationService> ()));
@@ -118,15 +121,21 @@ namespace MonoDevelop.Ide.TypeSystem
if (fileName.IsNullOrEmpty)
fileName = new FilePath (p.Name + ".dll");
- var (references, projectReferences) = await metadataHandler.Value.CreateReferences (p, token);
- if (token.IsCancellationRequested)
- return null;
+ if (!hackyCache.TryGetCachedItems (p, workspace.MetadataReferenceManager, projectMap, out var sourceFiles, out var analyzerFiles, out var references, out var projectReferences)) {
+ (references, projectReferences) = await metadataHandler.Value.CreateReferences (p, token);
+ if (token.IsCancellationRequested)
+ return null;
- var sourceFiles = await p.GetSourceFilesAsync (config?.Selector).ConfigureAwait (false);
- if (token.IsCancellationRequested)
- return null;
+ sourceFiles = await p.GetSourceFilesAsync (config?.Selector).ConfigureAwait (false);
+ if (token.IsCancellationRequested)
+ return null;
+
+ analyzerFiles = await p.GetAnalyzerFilesAsync (config?.Selector).ConfigureAwait (false);
+
+ if (config != null)
+ hackyCache.Update (config, p, projectMap, sourceFiles, analyzerFiles, references, projectReferences);
+ }
- var analyzerFiles = await p.GetAnalyzerFilesAsync (config?.Selector).ConfigureAwait (false);
if (token.IsCancellationRequested)
return null;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index f7c8ff428c..5123450841 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -4204,6 +4204,8 @@
<Compile Include="MonoDevelop.Components\Mac\NSStackViewExtensions.cs" />
<Compile Include="MonoDevelop.Components\Mac\NSLabel.cs" />
<Compile Include="MonoDevelop.Components\Mac\NSLine.cs" />
+ <Compile Include="MonoDevelop.Ide.Projects\NewSolutionRunConfigurationDialog.cs" />
+ <Compile Include="MonoDevelop.Ide.TypeSystem\HackyWorkspaceFilesCache.cs" />
</ItemGroup>
<ItemGroup>
<Data Include="options\DefaultEditingLayout.xml" />
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs
index ddf38b4be9..3e00fb85a6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/DesktopService.cs
@@ -133,13 +133,6 @@ namespace MonoDevelop.Ide
get { return PlatformService.Name; }
}
- [Obsolete]
- public static string DefaultControlLeftRightBehavior {
- get {
- return PlatformService.DefaultControlLeftRightBehavior;
- }
- }
-
public static void ShowUrl (string url)
{
PlatformService.ShowUrl (url);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs
index a83a27648a..6982adec4f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdePreferences.cs
@@ -64,7 +64,14 @@ namespace MonoDevelop.Ide
Compact,
VeryCompact
}
-
+
+ public enum OnStartupBehaviour
+ {
+ ShowStartWindow,
+ LoadPreviousSolution,
+ EmptyEnvironment
+ }
+
public class IdePreferences
{
internal RoslynPreferences Roslyn { get; }
@@ -119,7 +126,7 @@ namespace MonoDevelop.Ide
public readonly ConfigurationProperty<string> UserInterfaceLanguage = Runtime.Preferences.UserInterfaceLanguage;
public readonly ConfigurationProperty<string> UserInterfaceThemeName = ConfigurationProperty.Create ("MonoDevelop.Ide.UserInterfaceTheme", Platform.IsLinux ? "" : "Light");
public readonly ConfigurationProperty<WorkbenchCompactness> WorkbenchCompactness = ConfigurationProperty.Create ("MonoDevelop.Ide.WorkbenchCompactness", MonoDevelop.Ide.WorkbenchCompactness.Normal);
- public readonly ConfigurationProperty<bool> LoadPrevSolutionOnStartup = ConfigurationProperty.Create ("SharpDevelop.LoadPrevProjectOnStartup", false);
+ public readonly ConfigurationProperty<OnStartupBehaviour> StartupBehaviour = ConfigurationProperty.Create ("MonoDevelop.Ide.StartupBehaviour", OnStartupBehaviour.ShowStartWindow);
public readonly ConfigurationProperty<bool> CreateFileBackupCopies = ConfigurationProperty.Create ("SharpDevelop.CreateBackupCopy", false);
public readonly ConfigurationProperty<bool> LoadDocumentUserProperties = ConfigurationProperty.Create ("SharpDevelop.LoadDocumentProperties", true);
public readonly ConfigurationProperty<bool> EnableDocumentSwitchDialog = ConfigurationProperty.Create ("MonoDevelop.Core.Gui.EnableDocumentSwitchDialog", true);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
index 0b8064d536..1dac022edc 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
@@ -66,6 +66,7 @@ namespace MonoDevelop.Ide
Socket listen_socket = null;
List<AddinError> errorsList = new List<AddinError> ();
bool initialized;
+ static StartupInfo startupInfo;
static readonly int ipcBasePort = 40000;
static Stopwatch startupTimer = new Stopwatch ();
static Stopwatch startupSectionTimer = new Stopwatch ();
@@ -184,7 +185,7 @@ namespace MonoDevelop.Ide
AddinManager.AddinLoadError += OnAddinError;
- var startupInfo = new StartupInfo (args);
+ startupInfo = new StartupInfo (args);
// If a combine was specified, force --newwindow.
@@ -280,7 +281,7 @@ namespace MonoDevelop.Ide
// XBC #33699
Counters.Initialization.Trace ("Initializing IdeApp");
- hideWelcomePage = startupInfo.HasFiles;
+ hideWelcomePage = startupInfo.HasFiles || IdeApp.Preferences.StartupBehaviour.Value != OnStartupBehaviour.ShowStartWindow;
IdeApp.Initialize (monitor, hideWelcomePage);
sectionTimings ["AppInitialization"] = startupSectionTimer.ElapsedMilliseconds;
startupSectionTimer.Restart ();
@@ -301,7 +302,7 @@ namespace MonoDevelop.Ide
// load previous combine
RecentFile openedProject = null;
- if (IdeApp.Preferences.LoadPrevSolutionOnStartup && !startupInfo.HasSolutionFile && !IdeApp.Workspace.WorkspaceItemIsOpening && !IdeApp.Workspace.IsOpen) {
+ if (IdeApp.Preferences.StartupBehaviour.Value == OnStartupBehaviour.LoadPreviousSolution && !startupInfo.HasSolutionFile && !IdeApp.Workspace.WorkspaceItemIsOpening && !IdeApp.Workspace.IsOpen) {
openedProject = DesktopService.RecentFiles.MostRecentlyUsedProject;
if (openedProject != null) {
var metadata = GetOpenWorkspaceOnStartupMetadata ();
@@ -469,19 +470,21 @@ namespace MonoDevelop.Ide
WelcomePage.WelcomePageService.ShowWelcomePage ();
Counters.Initialization.Trace ("Showed welcome page");
IdeApp.Workbench.Show ();
+ } else if (hideWelcomePage && !startupInfo.OpenedFiles) {
+ IdeApp.Workbench.Show ();
}
return false;
}
- void CreateStartupMetadata (StartupInfo startupInfo, Dictionary<string, long> timings)
+ void CreateStartupMetadata (StartupInfo si, Dictionary<string, long> timings)
{
var result = DesktopService.PlatformTelemetry;
if (result == null) {
return;
}
- var startupMetadata = GetStartupMetadata (startupInfo, result, timings);
+ var startupMetadata = GetStartupMetadata (si, result, timings);
Counters.Startup.Inc (startupMetadata);
if (ttcMetadata != null) {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs
index 5a41930ccf..b27e22998c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/MessageService.cs
@@ -355,10 +355,13 @@ namespace MonoDevelop.Ide
}).Wait ();
#endif
+ var initialRootWindow = Xwt.MessageDialog.RootWindow;
try {
+ Xwt.MessageDialog.RootWindow = Xwt.Toolkit.CurrentEngine.WrapWindow (dialog);
IdeApp.DisableIdleActions ();
return GtkWorkarounds.RunDialogWithNotification (dialog);
} finally {
+ Xwt.MessageDialog.RootWindow = initialRootWindow;
IdeApp.EnableIdleActions ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
index a95c85d240..46a04cac4c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
@@ -48,6 +48,7 @@ using MonoDevelop.Ide.TypeSystem;
using MonoDevelop.Projects;
using MonoDevelop.Projects.MSBuild;
using ExecutionContext = MonoDevelop.Projects.ExecutionContext;
+using MonoDevelop.Ide.Projects.OptionPanels;
namespace MonoDevelop.Ide
{
@@ -55,8 +56,9 @@ namespace MonoDevelop.Ide
/// This is the basic interface to the workspace.
/// </summary>
public partial class ProjectOperations
- {
- AsyncOperation<BuildResult> currentBuildOperation = new AsyncOperation<BuildResult> (Task.FromResult (BuildResult.CreateSuccess ()), null);
+ {
+ static AsyncOperation<BuildResult> DefaultBuildOperation = new AsyncOperation<BuildResult> (Task.FromResult (BuildResult.CreateSuccess ()), null);
+ AsyncOperation<BuildResult> currentBuildOperation = DefaultBuildOperation;
MultipleAsyncOperation currentRunOperation = MultipleAsyncOperation.CompleteMultipleOperation;
IBuildTarget currentBuildOperationOwner;
List<IBuildTarget> currentRunOperationOwners = new List<IBuildTarget> ();
@@ -67,19 +69,12 @@ namespace MonoDevelop.Ide
WorkspaceItem currentWorkspaceItem = null;
object currentItem;
- BuildResult lastResult = new BuildResult ();
-
internal ProjectOperations ()
{
IdeApp.Workspace.WorkspaceItemUnloaded += OnWorkspaceItemUnloaded;
IdeApp.Workspace.ItemUnloading += IdeAppWorkspaceItemUnloading;
}
-
- [Obsolete ("This property will be removed.")]
- public BuildResult LastCompilerResult {
- get { return lastResult; }
- }
public Project CurrentSelectedProject {
get {
@@ -153,7 +148,13 @@ namespace MonoDevelop.Ide
public AsyncOperation CurrentRunOperation {
get { return currentRunOperation; }
set { AddRunOperation (value); }
- }
+ }
+
+ void ResetCurrentBuildOperation ()
+ {
+ currentBuildOperation = DefaultBuildOperation;
+ currentBuildOperationOwner = null;
+ }
public void AddRunOperation (AsyncOperation runOperation)
{
@@ -692,6 +693,35 @@ namespace MonoDevelop.Ide
}
}
}
+
+ public async void ShowRunConfiguration (Solution solution, MultiItemSolutionRunConfiguration runConfiguration)
+ {
+ var optionsDialog = new CombineOptionsDialog (IdeApp.Workbench.RootWindow, solution);
+ optionsDialog.CurrentConfig = IdeApp.Workspace.ActiveConfigurationId;
+ try {
+ optionsDialog.SelectPanel ("Run");
+ if (runConfiguration != null) {
+ void shownCallback (object sender, EventArgs args)
+ {
+ var panel = optionsDialog.GetPanel<SolutionRunConfigurationsPanel> ("General");
+ if (panel != null) {
+ panel.ShowConfiguration (runConfiguration);
+ }
+ optionsDialog.Shown -= shownCallback;
+ }
+
+ optionsDialog.Shown += shownCallback;
+ }
+
+ if (MessageService.RunCustomDialog (optionsDialog) == (int)Gtk.ResponseType.Ok) {
+ await SaveAsync (solution);
+ await IdeApp.Workspace.SavePreferences (solution);
+ }
+ } finally {
+ optionsDialog.Destroy ();
+ optionsDialog.Dispose ();
+ }
+ }
public Task<bool> NewSolution ()
{
@@ -1205,21 +1235,17 @@ namespace MonoDevelop.Ide
var t = CleanAsync (entry, monitor, tt, false, operationContext);
- t = t.ContinueWith (ta => {
- currentBuildOperationOwner = null;
- return ta.Result;
- });
-
var op = new AsyncOperation<BuildResult> (t, cs);
currentBuildOperation = op;
- currentBuildOperationOwner = entry;
+ currentBuildOperationOwner = entry;
+
+ t.ContinueWith (ta => { ResetCurrentBuildOperation (); });
+ return op;
}
catch {
tt.End ();
throw;
}
-
- return currentBuildOperation;
}
async Task<BuildResult> CleanAsync (IBuildTarget entry, ProgressMonitor monitor, ITimeTracker tt, bool isRebuilding, OperationContext operationContext)
@@ -1343,14 +1369,13 @@ namespace MonoDevelop.Ide
ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetRebuildProgressMonitor ().WithCancellationSource (cs);
var t = RebuildAsync (entry, monitor, operationContext);
- t = t.ContinueWith (ta => {
- currentBuildOperationOwner = null;
- return ta.Result;
- });
- var op = new AsyncOperation<BuildResult> (t, cs);
-
- return currentBuildOperation = op;
+ var op = new AsyncOperation<BuildResult> (t, cs);
+ currentBuildOperation = op;
+ currentBuildOperationOwner = entry;
+
+ t.ContinueWith (ta => { ResetCurrentBuildOperation (); });
+ return op;
}
async Task<BuildResult> RebuildAsync (IBuildTarget entry, ProgressMonitor monitor, OperationContext operationContext)
@@ -1641,15 +1666,19 @@ namespace MonoDevelop.Ide
cs = CancellationTokenSource.CreateLinkedTokenSource (cs.Token, cancellationToken.Value);
ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor ().WithCancellationSource (cs);
BeginBuild (monitor, tt, false);
- var t = BuildSolutionItemAsync (entry, monitor, tt, skipPrebuildCheck, operationContext);
- currentBuildOperation = new AsyncOperation<BuildResult> (t, cs);
- currentBuildOperationOwner = entry;
- t.ContinueWith ((ta) => currentBuildOperationOwner = null);
+
+ var t = BuildSolutionItemAsync (entry, monitor, tt, skipPrebuildCheck, operationContext);
+
+ var op = new AsyncOperation<BuildResult> (t, cs);
+ currentBuildOperation = op;
+ currentBuildOperationOwner = entry;
+
+ t.ContinueWith (ta => { ResetCurrentBuildOperation (); });
+ return op;
} catch {
tt.End ();
throw;
}
- return currentBuildOperation;
}
async Task<BuildResult> BuildSolutionItemAsync (IBuildTarget entry, ProgressMonitor monitor, ITimeTracker tt, bool skipPrebuildCheck = false, OperationContext operationContext = null)
@@ -1776,7 +1805,6 @@ namespace MonoDevelop.Ide
tt.Trace ("Begin reporting build result");
try {
if (result != null) {
- lastResult = result;
monitor.Log.WriteLine ();
var msg = GettextCatalog.GetString (
@@ -1796,7 +1824,7 @@ namespace MonoDevelop.Ide
if (monitor.CancellationToken.IsCancellationRequested) {
monitor.ReportError (GettextCatalog.GetString ("Build canceled."), null);
- } else if (result.ErrorCount == 0 && result.WarningCount == 0 && lastResult.FailedBuildCount == 0) {
+ } else if (result.ErrorCount == 0 && result.WarningCount == 0 && result.FailedBuildCount == 0) {
monitor.ReportSuccess (GettextCatalog.GetString ("Build successful."));
} else if (result.ErrorCount == 0 && result.WarningCount > 0) {
monitor.ReportWarning(GettextCatalog.GetString("Build: ") + errorString + ", " + warningString);
@@ -1806,7 +1834,7 @@ namespace MonoDevelop.Ide
monitor.ReportError(GettextCatalog.GetString("Build failed."), null);
}
tt.Trace ("End build event");
- OnEndBuild (monitor, lastResult.FailedBuildCount == 0, lastResult, entry as SolutionFolderItem);
+ OnEndBuild (monitor, result.FailedBuildCount == 0, result, entry as SolutionFolderItem);
} else {
tt.Trace ("End build event");
OnEndBuild (monitor, false);
@@ -2587,13 +2615,14 @@ namespace MonoDevelop.Ide
public void AddOperation (AsyncOperation op)
{
Operations.Add (op);
- op.Task.ContinueWith (CheckForCompletion);
+ op.Task.ContinueWith (t => CheckForCompletion (t));
}
- void CheckForCompletion (Task obj)
+ void CheckForCompletion (Task obj)
{
- if (Operations.All (op => op.IsCompleted))
- TaskCompletionSource.SetResult (0);
+ if (Operations.All (op => op.IsCompleted)) {
+ TaskCompletionSource.SetResult (0);
+ }
}
void MultiCancel ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs
index dd7d7e6166..ba8547f61a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Services.cs
@@ -60,10 +60,7 @@ namespace MonoDevelop.Ide
internal static TimerCounter SaveAllTimer = InstrumentationService.CreateTimerCounter ("Save all documents", "IDE", id:"Ide.Shell.SaveAll");
internal static TimerCounter CloseWorkspaceTimer = InstrumentationService.CreateTimerCounter ("Workspace closed", "IDE", id:"Ide.Shell.CloseWorkspace");
internal static Counter<StartupMetadata> Startup = InstrumentationService.CreateCounter<StartupMetadata> ("IDE Startup", "IDE", id:"Ide.Startup");
- internal static TimerCounter CompositionAddinLoad = InstrumentationService.CreateTimerCounter ("MEF Composition Addin Load", "IDE", id: "Ide.Startup.Composition.ExtensionLoad");
- internal static TimerCounter CompositionDiscovery = InstrumentationService.CreateTimerCounter ("MEF Composition From Discovery", "IDE", id:"Ide.Startup.Composition.Discovery");
- internal static TimerCounter CompositionCacheControl = InstrumentationService.CreateTimerCounter ("MEF Composition Control Cache", "IDE", id: "Ide.Startup.Composition.ControlCache");
- internal static TimerCounter CompositionCache = InstrumentationService.CreateTimerCounter ("MEF Composition From Cache", "IDE", id: "Ide.Startup.Composition.Cache");
+ internal static TimerCounter<CompositionLoadMetadata> CompositionLoad = InstrumentationService.CreateTimerCounter<CompositionLoadMetadata> ("MEF Composition Load", "IDE", id: "Ide.Startup.Composition.Load");
internal static TimerCounter CompositionSave = InstrumentationService.CreateTimerCounter ("MEF Composition Save", "IDE", id: "Ide.CompositionSave");
internal static TimerCounter AnalysisTimer = InstrumentationService.CreateTimerCounter ("Code Analysis", "IDE", id:"Ide.CodeAnalysis");
internal static TimerCounter ProcessCodeCompletion = InstrumentationService.CreateTimerCounter ("Process Code Completion", "IDE", id: "Ide.ProcessCodeCompletion", logMessages:false);
@@ -210,5 +207,32 @@ namespace MonoDevelop.Ide
set => SetProperty (value);
}
}
+
+ class CompositionLoadMetadata : CounterMetadata
+ {
+ public CompositionLoadMetadata ()
+ {
+ }
+
+ public CompositionLoadMetadata (Dictionary<string, long> timings)
+ {
+ Timings = timings;
+ }
+
+ public Dictionary<string, long> Timings {
+ get => GetProperty<Dictionary<string, long>> ();
+ set => SetProperty (value);
+ }
+
+ public bool ValidCache {
+ get => GetProperty<bool> ();
+ set => SetProperty (value);
+ }
+
+ public long Duration {
+ get => GetProperty<long> ();
+ set => SetProperty (value);
+ }
+ }
}
diff --git a/main/src/core/MonoDevelop.Ide/gtkrc b/main/src/core/MonoDevelop.Ide/gtkrc
index 0144ec125d..1dbc980702 100644
--- a/main/src/core/MonoDevelop.Ide/gtkrc
+++ b/main/src/core/MonoDevelop.Ide/gtkrc
@@ -1,5 +1,5 @@
# Xamarin Studio GTK Theme
-# Copyright 2012-2016 Xamarin Inc.
+# Copyright 2012-2019 Xamarin Inc.
# Authors:
# Christian Kellner <christian.kellner@lanedo.com>
# Carlos Garnacho <carlos.garnacho@lanedo.com>
@@ -13,6 +13,7 @@ gtk-color-scheme =
fg_color: #000
base_color: #fff
text_color: #000
+dim_color: #767676
selected_bg_color: #649dd6
selected_fg_color: #fff
tooltip_bg_color: #fff9e5
@@ -42,13 +43,13 @@ style "default" {
fg[NORMAL] = @fg_color
fg[PRELIGHT] = @fg_color
fg[SELECTED] = @selected_fg_color
- fg[INSENSITIVE] = darker (@bg_color)
+ fg[INSENSITIVE] = @dim_color
fg[ACTIVE] = @fg_color
text[NORMAL] = @fg_color
text[PRELIGHT] = @fg_color
text[SELECTED] = @selected_fg_color
- text[INSENSITIVE] = darker (@bg_color)
+ text[INSENSITIVE] = @dim_color
text[ACTIVE] = @fg_color
base[NORMAL] = @base_color
diff --git a/main/src/core/MonoDevelop.Ide/gtkrc.mac b/main/src/core/MonoDevelop.Ide/gtkrc.mac
index fbfc7736b6..84972e73f9 100644
--- a/main/src/core/MonoDevelop.Ide/gtkrc.mac
+++ b/main/src/core/MonoDevelop.Ide/gtkrc.mac
@@ -1,5 +1,5 @@
# Xamarin Studio Light Mac GTK Theme
-# Copyright 2012-2016 Xamarin Inc.
+# Copyright 2012-2019 Xamarin Inc.
# Authors:
# Christian Kellner <christian.kellner@lanedo.com>
# Carlos Garnacho <carlos.garnacho@lanedo.com>
@@ -14,7 +14,8 @@ fg_color: #272727
base_color: #fff
text_color: #272727
link_color: #175fde
-selected_bg_color: #5189ed
+dim_color: #767676
+selected_bg_color: #2862d9
selected_fg_color: #fff
tooltip_bg_color: #f2f2f2
tooltip_fg_color: #272727
@@ -49,13 +50,13 @@ style "default" {
fg[NORMAL] = @fg_color
fg[PRELIGHT] = @fg_color
fg[SELECTED] = @selected_fg_color
- fg[INSENSITIVE] = darker (@bg_color)
+ fg[INSENSITIVE] = @dim_color
fg[ACTIVE] = @fg_color
text[NORMAL] = @fg_color
text[PRELIGHT] = @fg_color
text[SELECTED] = @selected_fg_color
- text[INSENSITIVE] = darker (@bg_color)
+ text[INSENSITIVE] = @dim_color
text[ACTIVE] = @fg_color
base[NORMAL] = @base_color
diff --git a/main/src/core/MonoDevelop.Ide/gtkrc.mac-dark b/main/src/core/MonoDevelop.Ide/gtkrc.mac-dark
index f107bcc673..687ae9b48a 100644
--- a/main/src/core/MonoDevelop.Ide/gtkrc.mac-dark
+++ b/main/src/core/MonoDevelop.Ide/gtkrc.mac-dark
@@ -1,5 +1,5 @@
# Xamarin Studio Dark Mac GTK Theme
-# Copyright 2012-2016 Xamarin Inc.
+# Copyright 2012-2019 Xamarin Inc.
# Authors:
# Christian Kellner <christian.kellner@lanedo.com>
# Carlos Garnacho <carlos.garnacho@lanedo.com>
@@ -14,8 +14,8 @@ fg_color: #d7d7d7
base_color: #404040
text_color: #d7d7d7
link_color: #ace2ff
-dim_color: #777777
-selected_bg_color: #5189ed
+dim_color: #ababab
+selected_bg_color: #2257c9
selected_fg_color: #fff
tooltip_bg_color: #5a5a5a
tooltip_fg_color: #d2d5cd
diff --git a/main/src/core/MonoDevelop.Ide/gtkrc.win32 b/main/src/core/MonoDevelop.Ide/gtkrc.win32
index f0e6db4d26..5ebcd9b1db 100644
--- a/main/src/core/MonoDevelop.Ide/gtkrc.win32
+++ b/main/src/core/MonoDevelop.Ide/gtkrc.win32
@@ -1,5 +1,5 @@
# Xamarin Studio Light Windows GTK Theme
-# Copyright 2012-2016 Xamarin Inc.
+# Copyright 2012-2019 Xamarin Inc.
# Authors:
# Christian Kellner <christian.kellner@lanedo.com>
# Carlos Garnacho <carlos.garnacho@lanedo.com>
@@ -14,6 +14,7 @@ fg_color: #000
base_color: #fff
text_color: #000
link_color: #175fde
+dim_color: #767676
selected_bg_color: #cce8ff
selected_fg_color: #000
tooltip_bg_color: #f2f2f2
@@ -48,13 +49,13 @@ style "default" {
fg[NORMAL] = @fg_color
fg[PRELIGHT] = @fg_color
fg[SELECTED] = @selected_fg_color
- fg[INSENSITIVE] = darker (@bg_color)
+ fg[INSENSITIVE] = @dim_color
fg[ACTIVE] = @fg_color
text[NORMAL] = @fg_color
text[PRELIGHT] = @fg_color
text[SELECTED] = @selected_fg_color
- text[INSENSITIVE] = darker (@bg_color)
+ text[INSENSITIVE] = @dim_color
text[ACTIVE] = @fg_color
base[NORMAL] = @base_color
diff --git a/main/src/core/MonoDevelop.Ide/gtkrc.win32-dark b/main/src/core/MonoDevelop.Ide/gtkrc.win32-dark
index 35836699c5..074f97a9d8 100644
--- a/main/src/core/MonoDevelop.Ide/gtkrc.win32-dark
+++ b/main/src/core/MonoDevelop.Ide/gtkrc.win32-dark
@@ -1,5 +1,5 @@
# Xamarin Studio Dark Windows GTK Theme
-# Copyright 2012-2016 Xamarin Inc.
+# Copyright 2012-2019 Xamarin Inc.
# Authors:
# Christian Kellner <christian.kellner@lanedo.com>
# Carlos Garnacho <carlos.garnacho@lanedo.com>
@@ -14,7 +14,7 @@ fg_color: #d7d7d7
base_color: #404040
text_color: #d7d7d7
link_color: #ace2ff
-dim_color: #777777
+dim_color: #ababab
selected_bg_color: #4c5e6e
selected_fg_color: #bfbfbf
tooltip_bg_color: #5a5a5a
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/CompletionListWindowTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/CompletionListWindowTests.cs
index fa76281524..42284d1f27 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/CompletionListWindowTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui/CompletionListWindowTests.cs
@@ -1164,6 +1164,7 @@ namespace MonoDevelop.Ide.Gui
/// Bug 55298 - Autocomplete () doesn't work
/// </summary>
[Test]
+ [Ignore("The case in https://bugzilla.xamarin.com/show_bug.cgi?id=55298 is handled differently but propertly by the roslyn engine. This beahivor in that test collides with VSTS 760389 and produces a bug on default string prefix equality which was tested here.")]
public void TestBug55298 ()
{
string output = RunSimulation (new SimulationSettings () {
@@ -1581,5 +1582,25 @@ namespace MonoDevelop.Ide.Gui
}
+
+ /// <summary>
+ /// VSTS 760389: [Feedback] Autocomplete chooses wrong variable name
+ /// </summary>
+ [Test]
+ public void TestVSTS760389 ()
+ {
+ var word = RunSimulation (new SimulationSettings {
+ SimulatedInput = "i\t",
+ AutoSelect = true,
+ CompleteWithSpaceOrPunctuation = true,
+ AutoCompleteEmptyMatch = false,
+ CompletionData = new [] {
+ "iFoo",
+ "i"
+ },
+ DefaultCompletionString = "iFoo"
+ });
+ Assert.AreEqual ("i", word);
+ }
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.RoslynServices/MonoDevelopProjectCacheHostServiceTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.RoslynServices/MonoDevelopProjectCacheHostServiceTests.cs
index 42a98e46f5..cf7ec25b7c 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.RoslynServices/MonoDevelopProjectCacheHostServiceTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.RoslynServices/MonoDevelopProjectCacheHostServiceTests.cs
@@ -134,6 +134,7 @@ namespace MonoDevelop.Ide.RoslynServices
}
[Test]
+ [Ignore ("Disabled for now")]
public void TestCacheDoesNotKeepObjectsAliveAfterOwnerIsCollected2 ()
{
Test ((cacheService, projectId, owner, instance) => {
diff --git a/main/tests/MacPlatform.Tests/MacPlatform.Tests.csproj b/main/tests/MacPlatform.Tests/MacPlatform.Tests.csproj
index 5d95cd7f17..4a47a350a5 100644
--- a/main/tests/MacPlatform.Tests/MacPlatform.Tests.csproj
+++ b/main/tests/MacPlatform.Tests/MacPlatform.Tests.csproj
@@ -23,7 +23,6 @@
<Compile Include="KeychainTests.cs" />
<Compile Include="CredentialsProviderTests.cs" />
<Compile Include="CoreFoundationTests.cs" />
- <Compile Include="ProcessManagerTests.cs" />
<Compile Include="LaunchServicesTests.cs" />
<Compile Include="AppleScriptTests.cs" />
<Compile Include="CarbonTests.cs" />
diff --git a/main/tests/MacPlatform.Tests/ProcessManagerTests.cs b/main/tests/MacPlatform.Tests/ProcessManagerTests.cs
deleted file mode 100644
index b51c435cad..0000000000
--- a/main/tests/MacPlatform.Tests/ProcessManagerTests.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// ProcessManagementTests.cs
-//
-// Author:
-// iain holmes <iain@xamarin.com>
-//
-// Copyright (c) 2015 Xamarin, Inc
-//
-// 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.MacInterop;
-using NUnit.Framework;
-
-namespace MacPlatform.Tests
-{
- public class ProcessManagerTests
- {
- [Test]
- public static void TestPid ()
- {
- var psn = new ProcessSerialNumber (0, 2 /* kCurrentProcess */);
- int pid = ProcessManager.GetProcessPid (psn);
-
- Assert.AreNotEqual (-1, pid);
- }
- }
-}
-