From 109220f5a283245ed9ffb70f82ca061d4d6d3dad Mon Sep 17 00:00:00 2001 From: Sandy Armstrong Date: Wed, 18 Dec 2019 09:50:10 -0800 Subject: Sync with vs-editor-core@2b5d751fb --- build/Project.props | 3 + global.json | 4 +- .../PresentationCore/System.Windows.UIElement.cs | 27 ++++ .../Intellisense/IPopupIntellisensePresenter.cs | 2 +- .../Def/Intellisense/Snippet/CodeSnippet.cs | 123 --------------- .../Def/Intellisense/Snippet/ExpansionField.cs | 75 --------- .../Def/Intellisense/Snippet/ExpansionTemplate.cs | 148 ------------------ .../Def/Intellisense/Snippet/IExpansionClient.cs | 24 --- .../Def/Intellisense/Snippet/IExpansionFunction.cs | 30 ---- .../Def/Intellisense/Snippet/IExpansionManager.cs | 18 --- .../Def/Intellisense/Snippet/IExpansionService.cs | 18 --- .../Snippet/IExpansionServiceProvider.cs | 12 -- .../Def/Intellisense/Snippet/IExpansionSession.cs | 25 --- src/Editor/Text/Def/TextUI/AssemblyInfo.cs | 5 + src/Editor/Text/Def/TextUI/Editor/ITextView3.cs | 30 ---- .../Def/TextUI/Editor/ITextViewFactoryService.cs | 174 --------------------- .../Text/Def/TextUI/Editor/ITextViewZoomManager.cs | 46 ++++++ .../Text/Def/TextUI/Editor/IViewScroller2.cs | 30 ++++ .../TextUI/Editor/IViewSynchronizationManager.cs | 22 --- .../Def/TextUI/Operations/IEditorOperations4.cs | 23 ++- .../Text/Def/TextUICocoa/Editor/ICocoaTextView.cs | 20 ++- .../Editor/IViewSynchronizationManager.cs | 22 +++ .../Text/Def/TextUICocoa/Snippet/CodeSnippet.cs | 123 +++++++++++++++ .../Text/Def/TextUICocoa/Snippet/ExpansionField.cs | 75 +++++++++ .../Def/TextUICocoa/Snippet/ExpansionTemplate.cs | 148 ++++++++++++++++++ .../Def/TextUICocoa/Snippet/IExpansionClient.cs | 24 +++ .../Def/TextUICocoa/Snippet/IExpansionFunction.cs | 30 ++++ .../Def/TextUICocoa/Snippet/IExpansionManager.cs | 18 +++ .../Def/TextUICocoa/Snippet/IExpansionService.cs | 18 +++ .../Snippet/IExpansionServiceProvider.cs | 12 ++ .../Def/TextUICocoa/Snippet/IExpansionSession.cs | 25 +++ .../BraceCompletionAdornmentService.cs | 6 +- .../BraceCompletionAdornmentServiceFactory.cs | 2 +- .../BraceCompletion/BraceCompletionImpl.csproj | 2 +- .../Text/Impl/EditorOperations/EditorOperations.cs | 82 +++++----- .../EditorOperationsFactoryService.cs | 7 + src/Editor/Text/Util/TextDataUtil/AssemblyInfo.cs | 1 + .../Text/Util/TextUICocoaUtil/AssemblyInfo.cs | 48 ++++++ .../TextUICocoaUtil/CocoaTextViewZoomManager.cs | 65 ++++++++ .../Util/TextUICocoaUtil/DifferenceBrushManager.cs | 119 ++++++++++++++ .../TextUICocoaUtil/IDragDropMouseProcessor.cs | 27 ++++ .../Text/Util/TextUICocoaUtil/TelemetryLogger.cs | 142 +++++++++++++++++ .../Util/TextUICocoaUtil/TextUICocoaUtil.csproj | 35 +++++ .../Util/TextUIUtil/DefaultTextViewZoomManager.cs | 27 ++++ .../Text/Util/TextUIUtil/DifferenceBrushManager.cs | 119 -------------- .../Text/Util/TextUIUtil/ExtensionMethods.cs | 85 +++++----- .../Util/TextUIUtil/IDragDropMouseProcessor.cs | 27 ---- src/Editor/Text/Util/TextUIUtil/TelemetryLogger.cs | 142 ----------------- .../Text/Util/TextUIUtil/TextViewZoomManager.cs | 35 +++++ src/OpenSource.Impl.projitems | 16 +- 50 files changed, 1251 insertions(+), 1090 deletions(-) create mode 100644 src/Editor/FPF/PresentationCore/System.Windows.UIElement.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/CodeSnippet.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/ExpansionField.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/ExpansionTemplate.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/IExpansionClient.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/IExpansionFunction.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/IExpansionManager.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/IExpansionService.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/IExpansionServiceProvider.cs delete mode 100644 src/Editor/Language/Def/Intellisense/Snippet/IExpansionSession.cs delete mode 100644 src/Editor/Text/Def/TextUI/Editor/ITextView3.cs delete mode 100644 src/Editor/Text/Def/TextUI/Editor/ITextViewFactoryService.cs create mode 100644 src/Editor/Text/Def/TextUI/Editor/ITextViewZoomManager.cs create mode 100644 src/Editor/Text/Def/TextUI/Editor/IViewScroller2.cs delete mode 100644 src/Editor/Text/Def/TextUI/Editor/IViewSynchronizationManager.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Editor/IViewSynchronizationManager.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/CodeSnippet.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionField.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionTemplate.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionClient.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionFunction.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionManager.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionService.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionServiceProvider.cs create mode 100644 src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionSession.cs create mode 100644 src/Editor/Text/Util/TextUICocoaUtil/AssemblyInfo.cs create mode 100644 src/Editor/Text/Util/TextUICocoaUtil/CocoaTextViewZoomManager.cs create mode 100644 src/Editor/Text/Util/TextUICocoaUtil/DifferenceBrushManager.cs create mode 100644 src/Editor/Text/Util/TextUICocoaUtil/IDragDropMouseProcessor.cs create mode 100644 src/Editor/Text/Util/TextUICocoaUtil/TelemetryLogger.cs create mode 100644 src/Editor/Text/Util/TextUICocoaUtil/TextUICocoaUtil.csproj create mode 100644 src/Editor/Text/Util/TextUIUtil/DefaultTextViewZoomManager.cs delete mode 100644 src/Editor/Text/Util/TextUIUtil/DifferenceBrushManager.cs delete mode 100644 src/Editor/Text/Util/TextUIUtil/IDragDropMouseProcessor.cs delete mode 100644 src/Editor/Text/Util/TextUIUtil/TelemetryLogger.cs create mode 100644 src/Editor/Text/Util/TextUIUtil/TextViewZoomManager.cs diff --git a/build/Project.props b/build/Project.props index fcbd918..a575b49 100644 --- a/build/Project.props +++ b/build/Project.props @@ -13,6 +13,9 @@ net472 + net472 + netstandard2.0;net472 + netstandard2.0 8.0 __MACOS__;$(DefineConstants) diff --git a/global.json b/global.json index 575257f..a39754e 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "msbuild-sdks": { "Microsoft.Build.Traversal": "1.0.45", - "Xamarin.MSBuild.Sdk": "0.29.0", - "Xamarin.Mac.Sdk": "0.29.0" + "Xamarin.MSBuild.Sdk": "0.31.0", + "Xamarin.Mac.Sdk": "0.31.0" } } \ No newline at end of file diff --git a/src/Editor/FPF/PresentationCore/System.Windows.UIElement.cs b/src/Editor/FPF/PresentationCore/System.Windows.UIElement.cs new file mode 100644 index 0000000..b659184 --- /dev/null +++ b/src/Editor/FPF/PresentationCore/System.Windows.UIElement.cs @@ -0,0 +1,27 @@ +using System; +using AppKit; + +namespace System.Windows +{ + public class UIElement + { +#pragma warning disable CS3003 // Type is not CLS-compliant + public NSView NSView { get; } +#pragma warning restore CS3003 // Type is not CLS-compliant + + public UIElement(NSView view) + { + NSView = view; + } + + public static implicit operator UIElement(NSView view) + { + return new UIElement(view); + } + + public static implicit operator NSView(UIElement uiElement) + { + return uiElement.NSView; + } + } +} diff --git a/src/Editor/Language/Def/Intellisense/IPopupIntellisensePresenter.cs b/src/Editor/Language/Def/Intellisense/IPopupIntellisensePresenter.cs index 8b00604..498c3d0 100644 --- a/src/Editor/Language/Def/Intellisense/IPopupIntellisensePresenter.cs +++ b/src/Editor/Language/Def/Intellisense/IPopupIntellisensePresenter.cs @@ -19,7 +19,7 @@ namespace Microsoft.VisualStudio.Language.Intellisense /// Gets the WPF that the presenter wants to be displayed inside a /// popup. /// - object SurfaceElement { get; } + UIElement SurfaceElement { get; } /// /// Occurs when the WPF SurfaceElement is changed. diff --git a/src/Editor/Language/Def/Intellisense/Snippet/CodeSnippet.cs b/src/Editor/Language/Def/Intellisense/Snippet/CodeSnippet.cs deleted file mode 100644 index e5f0fa1..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/CodeSnippet.cs +++ /dev/null @@ -1,123 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System.Collections.Generic; -using System.Linq; -using System.Xml; -using System.Xml.Linq; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public class CodeSnippet - { - public string Title { get; set; } - public string Shortcut { get; set; } - public string Description { get; set; } - public string Author { get; set; } - public List SnippetTypes { get; set; } - public string Code { get; set; } - public List Fields { get; set; } - public string FilePath { get; set; } - public string Language { get; set; } - public XElement Snippet { get; set; } - - public CodeSnippet() - { - - } - - public CodeSnippet(XElement codeSnippetElement, string filePath) - { - this.FilePath = filePath; - this.Fields = new List(); - this.SnippetTypes = new List(); - - var header = codeSnippetElement.Element(GetXName("Header")); - this.Title = GetElementInnerText(header, "Title"); - this.Shortcut = GetElementInnerText(header, "Shortcut") ?? ""; // https://github.com/dotnet/roslyn/pull/31738 - this.Description = GetElementInnerText(header, "Description"); - this.Author = GetElementInnerText(header, "Author"); - var snippetTypes = header.Element(GetXName("SnippetTypes")); - if (snippetTypes != null) - { - var snippetTypeElements = snippetTypes.Elements(); - foreach (var snippetType in snippetTypeElements) - { - SnippetTypes.Add(snippetType.Value); - } - } - - Snippet = codeSnippetElement.Element(GetXName("Snippet")); - var declarations = Snippet.Element(GetXName("Declarations")); - ReadDeclarations(declarations); - var code = Snippet.Element(GetXName("Code")); - this.Code = code.Value.Replace("\n", "\r\n"); - this.Language = code.Attribute("Language").Value; - } - - private void ReadDeclarations(XElement declarations) - { - if (declarations == null) - { - return; - } - - foreach (var declarationElement in declarations.Elements()) - { - var defaultAttribute = declarationElement.Attribute("Default"); - var editableAttribute = declarationElement.Attribute("Editable"); - this.Fields.Add(new ExpansionField - { - ID = GetElementInnerText(declarationElement, "ID"), - ToolTip = GetElementInnerText(declarationElement, "ToolTip"), - Default = GetElementInnerText(declarationElement, "Default") ?? " ", - Function = GetElementInnerText(declarationElement, "Function"), - IsDefault = defaultAttribute != null && defaultAttribute.Value == "true", - Editable = editableAttribute == null || editableAttribute.Value == "true" || editableAttribute.Value == "1" - }); - } - } - - private static string GetElementInnerText(XElement element, string subElementName) - { - var subElement = element.Element(GetXName(subElementName)); - if (subElement == null) - { - return null; - } - - return subElement.Value; - } - - public static IEnumerable ReadSnippetsFromFile(string filePath) - { - try - { - XDocument document = XDocument.Load(filePath); - var codeSnippetsElement = document.Root; - IEnumerable codeSnippetElements = null; - if (codeSnippetsElement.Name.LocalName == "CodeSnippets") - { - codeSnippetElements = codeSnippetsElement.Elements(GetXName("CodeSnippet")); - } - else - { - codeSnippetElements = new[] { codeSnippetsElement }; - } - - return codeSnippetElements.Select(element => new CodeSnippet(element, filePath)); - } - catch (XmlException) - { - return Enumerable.Empty(); - } - } - - private static XName GetXName(string localName) - { - return XName.Get(localName, "http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"); - } - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/ExpansionField.cs b/src/Editor/Language/Def/Intellisense/Snippet/ExpansionField.cs deleted file mode 100644 index 9bdef92..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/ExpansionField.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml.Linq; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public class ExpansionField - { - public string ID { get; set; } - public string ToolTip { get; set; } - public string Default { get; set; } - public string Function { get; set; } - - private List offsets = new List(); - - public int GetOffsetCount() - { - return offsets.Count; - } - - public void AddOffset(int offset) - { - offsets.Add(offset); - } - - public int GetOffset(int index) - { - return offsets[index]; - } - - public string GetDefault() - { - return Default; - } - - public int GetLength() - { - return Default.Length; - } - - public bool IsEditable() - { - return Editable; - } - - public XElement GetFunctionXML() - { - return new XElement(XName.Get("ExpansionField")) - { - Value = Function - }; - } - - public bool UsesFunction() - { - return Function != null; - } - - public bool IsDefault { get; set; } - public bool Editable { get; set; } - - public string GetName() - { - return ID; - } - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/ExpansionTemplate.cs b/src/Editor/Language/Def/Intellisense/Snippet/ExpansionTemplate.cs deleted file mode 100644 index 356d2bd..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/ExpansionTemplate.cs +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public class ExpansionTemplate - { - private string snippetFullText; - private readonly List tokens = new List(); - private int selectedOffset; - private int editOffset; - private string snippetFirst; - private string snippetLast; - - public CodeSnippet Snippet { get; set; } - - public ExpansionTemplate(string filePath) - :this(CodeSnippet.ReadSnippetsFromFile(filePath).First()) - { - - } - - public ExpansionTemplate(CodeSnippet snippet) - { - Snippet = snippet; - Parse(); - } - - private void Parse() - { - foreach (var field in Snippet.Fields) - { - tokens.Add(field); - } - - var matches = Regex.Matches(Snippet.Code, @"\$(\w+)\$"); - - var total = new StringBuilder(); - int index = 0; - int indexCorrection = 0; - foreach (Match match in matches) - { - string fieldName = match.Groups[1].Value; - string substitution = GetDefaultValue(fieldName) ?? ""; - if (match.Index > index) - { - total.Append(Snippet.Code.Substring(index, match.Index - index)); - } - - AddToken(total.Length, fieldName); - total.Append(substitution); - - index = match.Index + match.Length; - indexCorrection += substitution.Length; - } - - if (index <= Snippet.Code.Length - 1) - { - total.Append(Snippet.Code.Substring(index, Snippet.Code.Length - index)); - } - - this.snippetFullText = total.ToString(); - this.snippetFirst = snippetFullText.Substring(0, selectedOffset); - this.snippetLast = snippetFullText.Substring(selectedOffset, snippetFullText.Length - selectedOffset); - } - - private string GetDefaultValue(string fieldName) - { - ExpansionField field = FindField(fieldName); - if (field == null) - { - return null; - } - - return field.Default; - } - - private void AddToken(int position, string fieldName) - { - ExpansionField field = FindField(fieldName); - if (field != null) - { - field.AddOffset(position); - } - else if (fieldName == "selected") - { - this.selectedOffset = position; - } - else if (fieldName == "end") - { - this.editOffset = position; - } - } - - private ExpansionField FindField(string fieldName) - { - return tokens.FirstOrDefault(t => t.ID == fieldName); - } - - public string GetCodeSnippet() - { - return snippetFullText; - } - - public int GetSelectedOffset() - { - return selectedOffset; - } - - public int GetEditOffset() - { - return editOffset; - } - - public string GetCodeSnippet(bool all, bool first) - { - if (all) - { - return snippetFullText; - } - else if (first) - { - return snippetFirst; - } - else - { - return snippetLast; - } - } - - public IEnumerable Fields - { - get - { - return tokens; - } - } - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionClient.cs b/src/Editor/Language/Def/Intellisense/Snippet/IExpansionClient.cs deleted file mode 100644 index f04d13c..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionClient.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; -using System.Xml.Linq; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public interface IExpansionClient - { - IExpansionFunction GetExpansionFunction(XElement xmlFunctionNode, string fieldName); - void FormatSpan(SnapshotSpan span); - - void EndExpansion(); - - void OnBeforeInsertion(IExpansionSession session); - void OnAfterInsertion(IExpansionSession session); - - void PositionCaretForEditing(ITextView textView, SnapshotPoint point); - void OnItemChosen(string tittle, string path); - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionFunction.cs b/src/Editor/Language/Def/Intellisense/Snippet/IExpansionFunction.cs deleted file mode 100644 index af945a5..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionFunction.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public enum ExpansionFunctionType - { - List, - Value - }; - - public interface IExpansionFunction - { - void GetDefaultValue(out string value, out bool hasDefaultValue); - - void GetCurrentValue(out string value, out bool hasCurrentValue); - - bool FieldChanged(string fieldName); - - ExpansionFunctionType GetFunctionType(); - - int GetListCount(); - - string GetListText(int index); - - void ReleaseFunction(); - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionManager.cs b/src/Editor/Language/Def/Intellisense/Snippet/IExpansionManager.cs deleted file mode 100644 index 077b20b..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionManager.cs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; -using System.Collections.Generic; -using Microsoft.VisualStudio.Utilities; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public interface IExpansionManager - { - IEnumerable EnumerateExpansions(IContentType contentType, bool shortcutOnly, string[] snippetTypes, bool includeNullType, bool includeDuplicates); - ExpansionTemplate GetTemplateByName(IExpansionClient expansionClient, IContentType contentType, string name, string filePath, ITextView textView, SnapshotSpan span, bool showDisambiguationUI); - ExpansionTemplate GetTemplateByShortcut(IExpansionClient expansionClient, string shortcut, IContentType contentType, ITextView textView, SnapshotSpan span, bool showDisambiguationUI); - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionService.cs b/src/Editor/Language/Def/Intellisense/Snippet/IExpansionService.cs deleted file mode 100644 index 193edf5..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionService.cs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; -using System.Threading; -using Microsoft.VisualStudio.Utilities; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public interface IExpansionService - { - IExpansionSession InsertExpansion(SnapshotSpan triggerSpan, IExpansionClient expansionClient, IContentType contentType, CancellationToken cancellationToken = default); - IExpansionSession InsertNamedExpansion(string title, string pszPath, SnapshotSpan triggerSpan, IExpansionClient expansionClient, IContentType contentType, bool showDisambiguationUI); - void InvokeInsertionUI(IExpansionClient expansionClient, IContentType contentType, string[] types, bool includeNullType, string[] kinds, bool includeNullKind, string prefixText, string completionChar); - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionServiceProvider.cs b/src/Editor/Language/Def/Intellisense/Snippet/IExpansionServiceProvider.cs deleted file mode 100644 index cead20d..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionServiceProvider.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public interface IExpansionServiceProvider - { - IExpansionService GetExpansionService(ITextView textView); - } -} diff --git a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionSession.cs b/src/Editor/Language/Def/Intellisense/Snippet/IExpansionSession.cs deleted file mode 100644 index 9845f93..0000000 --- a/src/Editor/Language/Def/Intellisense/Snippet/IExpansionSession.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; -using System.Xml.Linq; - -namespace Microsoft.VisualStudio.Text.Editor.Expansion -{ - public interface IExpansionSession - { - void EndCurrentExpansion(bool leaveCaret); - bool GoToNextExpansionField(bool commitIfLast); - bool GoToPreviousExpansionField(); - string GetFieldValue(string fieldName); - void SetFieldDefault(string fieldName, string newValue); - SnapshotSpan GetFieldSpan(string fieldName); - XElement GetHeaderNode(); - XElement GetDeclarationNode(); - XElement GetSnippetNode(); - SnapshotSpan GetSnippetSpan(); - SnapshotSpan EndSpan { get; set; } - } -} diff --git a/src/Editor/Text/Def/TextUI/AssemblyInfo.cs b/src/Editor/Text/Def/TextUI/AssemblyInfo.cs index b904d55..174963d 100644 --- a/src/Editor/Text/Def/TextUI/AssemblyInfo.cs +++ b/src/Editor/Text/Def/TextUI/AssemblyInfo.cs @@ -18,10 +18,15 @@ using System.Security.Permissions; [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Platform.VSEditor, PublicKey=" + ThisAssembly.PublicKey)] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.DifferenceViewer.Implementation, PublicKey=" + ThisAssembly.PublicKey)] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.Outlining.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.EditorOperations.Implementation, PublicKey=" + ThisAssembly.PublicKey)] // InternalsVisibleTo for VS for Mac implementation assembly: [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.Implementation, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e57febc1f220077550a65e338d3d15d7cbd189cf4f62f7c3829dcb2f8441a6c40631d172e3deb4dc0bb7237b44ec9daeb9bd7d72c3d64c4f52b968795443cb58bc341583c29440345b8c35f72f6a31aecb2903376136f8fc35779bb422eb643f8668fa6605c697bff927e3bb10745328ff878bd1b7e42bbcb839f04baa8460bd")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Cocoa.View.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.AdornmentLibrary.VisibleWhitespace.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.UI.Cocoa.Utilities, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("MonoDevelop.TextEditor, PublicKey=002400000c800000940000000602000000240000525341310004000001000100e1290d741888d13312c0cd1f72bb843236573c80158a286f11bb98de5ee8acc3142c9c97b472684e521ae45125d7414558f2e70ac56504f3e8fe80830da2cdb1cda8504e8d196150d05a214609234694ec0ebf4b37fc7537e09d877c3e65000f7467fa3adb6e62c82b10ada1af4a83651556c7d949959817fed97480839dd39b")] + // // General Information about an assembly is controlled through the following diff --git a/src/Editor/Text/Def/TextUI/Editor/ITextView3.cs b/src/Editor/Text/Def/TextUI/Editor/ITextView3.cs deleted file mode 100644 index f7b5b64..0000000 --- a/src/Editor/Text/Def/TextUI/Editor/ITextView3.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// - -using System; - -using Microsoft.VisualStudio.Text.Formatting; - -namespace Microsoft.VisualStudio.Text.Editor -{ - public interface ITextView3 : ITextView2 - { - /// - /// Gets or sets the Zoom level for the between 20% to 400% - /// - double ZoomLevel { get; set; } - - IXPlatAdornmentLayer GetXPlatAdornmentLayer(string name); - - ITextViewLineSource FormattedLineSource { get; } - - void Focus(); - - bool IsKeyboardFocused { get; } - event EventHandler IsKeyboardFocusedChanged; - - IViewSynchronizationManager SynchronizationManager { get; set; } - } -} \ No newline at end of file diff --git a/src/Editor/Text/Def/TextUI/Editor/ITextViewFactoryService.cs b/src/Editor/Text/Def/TextUI/Editor/ITextViewFactoryService.cs deleted file mode 100644 index 6ceea3b..0000000 --- a/src/Editor/Text/Def/TextUI/Editor/ITextViewFactoryService.cs +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// -// This file contain internal APIs that are subject to change without notice. -// Use at your own risk. -// - -using System; -using System.Collections.Generic; - -using Microsoft.VisualStudio.Utilities; - -namespace Microsoft.VisualStudio.Text.Editor -{ - public interface ITextViewFactoryService - { - /// - /// Creates an that displays the contents of . - /// - /// The that provides the text buffers for the view. - /// The set of roles filled by the view. - /// The options environment for the text view. - /// An . - /// or or is null. - ITextView CreateTextView(ITextViewModel viewModel, ITextViewRoleSet roles, IEditorOptions parentOptions); - - /// - /// Creates an that displays the contents of . - /// - /// The that provides the text buffers over which an - /// will be built for the view. - /// The set of roles filled by the view. - /// The options environment for the text view. - /// An . - /// - /// An can be displayed in multiple views. An will be constructed based on - /// the of the and the . - /// - /// or or is null. - ITextView CreateTextView(ITextDataModel dataModel, ITextViewRoleSet roles, IEditorOptions parentOptions); - - /// - /// Creates an that displays the contents of . - /// - /// The that provides the text for the view. - /// The set of roles filled by the view. - /// The options environment for the text view. - /// An . - /// - /// An can be displayed in multiple views. A trivial will be constructed and - /// an will be constructed based on - /// the of the and the . - /// - /// or or is null. - ITextView CreateTextView(ITextBuffer textBuffer, ITextViewRoleSet roles, IEditorOptions parentOptions); - - /// - /// Creates an that displays the contents of . - /// - /// The that provides the text for the view. - /// The set of roles filled by the view. - /// An . - /// - /// An can be displayed in multiple views. A trivial will be constructed and - /// an will be constructed based on - /// the of the and the . - /// - /// or is null. - ITextView CreateTextView(ITextBuffer textBuffer, ITextViewRoleSet roles); - - /// - /// Creates an that displays the contents of . - /// - /// The that provides the text for the view. - /// An having the default set of text view roles. - /// - /// An can be displayed in multiple views. A trivial will be constructed and - /// an will be constructed based on - /// the of the . - /// - /// is null. - ITextView CreateTextView(ITextBuffer textBuffer); - - /// - /// Creates an on a newly created having - /// content type Text. - /// - /// A . - ITextView CreateTextView(); - - ///// - ///// Creates a host for the text view. - ///// - ///// The text view to host. - ///// true if the should take focus after it is initialized, false otherwise. - ///// An . - ///// is null. - //IWpfTextViewHost CreateTextViewHost(ITextView wpfTextView, bool setFocus); - - /// - /// The empty ITextViewRoleSet. - /// - ITextViewRoleSet NoRoles { get; } - - /// - /// The set of all predefined text view roles. - /// - ITextViewRoleSet AllPredefinedRoles { get; } - - /// - /// The set of roles that are used when creating a text view without specifying text view roles. - /// - ITextViewRoleSet DefaultRoles { get; } - - /// - /// Creates a containing the given roles. - /// - /// The roles of interest. - /// The text view role set. - /// roles is null. - ITextViewRoleSet CreateTextViewRoleSet(IEnumerable roles); - - /// - /// Creates a containing the given roles. - /// - /// The roles of interest. - /// The text view role set. - ITextViewRoleSet CreateTextViewRoleSet(params string[] roles); - - /// - /// Raised when any is created. - /// - event EventHandler TextViewCreated; - - /// - /// Creates an that displays the contents of without initializing it. - /// - /// The that provides the text buffers over which an - /// will be built for the view. - /// The set of roles filled by the view. - /// The options environment for the text view. - /// An . - /// - /// An can be displayed in multiple views. An will be constructed based on - /// the of the and the . - /// ITextEditorFactoryService2.InitializeTextView(view) must be called on the view returned by this funtion. - /// - /// or or is null. - ITextView CreateTextViewWithoutInitialization(ITextDataModel dataModel, ITextViewRoleSet roles, IEditorOptions parentOptions); - - ///// - ///// Creates a host for the text view without initializing it. - ///// - ///// The text view to host. - ///// true if the should take focus after it is initialized, false otherwise. - ///// An . - ///// - ///// ITextEditorFactoryService2.InitializeTextViewHost(host) must be called on the host returned by this funtion. - ///// - ///// is null. - //IWpfTextViewHost CreateTextViewHostWithoutInitialization(IWpfTextView wpfTextView, bool setFocus); - - /// - /// Initialize a view created using CreateTextViewWithoutInitialization. - /// - void InitializeTextView(ITextView view); - - ///// - ///// Initialize a view created using CreateTextViewHostWithoutInitialization. - ///// - //void InitializeTextViewHost(IWpfTextViewHost host); - } -} diff --git a/src/Editor/Text/Def/TextUI/Editor/ITextViewZoomManager.cs b/src/Editor/Text/Def/TextUI/Editor/ITextViewZoomManager.cs new file mode 100644 index 0000000..eb4974b --- /dev/null +++ b/src/Editor/Text/Def/TextUI/Editor/ITextViewZoomManager.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +namespace Microsoft.VisualStudio.Text.Editor +{ + /// + /// Provides methods to manipulate zoom level of text views. + /// + /// This is a MEF Component, and should be imported as follows: + /// + /// [Import] + /// ITextViewZoomManager zoomManager = null; + /// + /// + internal interface ITextViewZoomManager + { + /// + /// Zooms in to the text view by a scaling factor of 10%. + /// + /// + /// The maximum zooming scale is 400%. + /// + void ZoomIn(ITextView textView); + + /// + /// Zooms out of the text view by a scaling factor of 10%. + /// + /// + /// The minimum zooming scale is 20%. + /// + void ZoomOut(ITextView textView); + + /// + /// Applies the given zoomLevel to the text view. + /// + /// The zoom level to apply between 20% to 400%. + void ZoomTo(ITextView textView, double zoomLevel); + + /// + /// Gets ZoomLevel between 20% to 400% of text view. + /// + double ZoomLevel(ITextView textView); + } +} diff --git a/src/Editor/Text/Def/TextUI/Editor/IViewScroller2.cs b/src/Editor/Text/Def/TextUI/Editor/IViewScroller2.cs new file mode 100644 index 0000000..0856fcb --- /dev/null +++ b/src/Editor/Text/Def/TextUI/Editor/IViewScroller2.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +namespace Microsoft.VisualStudio.Text.Editor +{ + internal interface IViewScroller2 : IViewScroller + { + /// + /// Gets the width of a column in pixels. + /// + double ColumnWidth { get; } + + /// + /// Scrolls the view one column to the left. + /// + /// + /// A column is the width of a space in the default font. + /// + void ScrollColumnLeft(); + + /// + /// Scrolls the view one column to the right. + /// + /// + /// A column is the width of a space in the default font. + /// + void ScrollColumnRight(); + } +} diff --git a/src/Editor/Text/Def/TextUI/Editor/IViewSynchronizationManager.cs b/src/Editor/Text/Def/TextUI/Editor/IViewSynchronizationManager.cs deleted file mode 100644 index 70eddaa..0000000 --- a/src/Editor/Text/Def/TextUI/Editor/IViewSynchronizationManager.cs +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// -namespace Microsoft.VisualStudio.Text.Formatting -{ - using Microsoft.VisualStudio.Text.Editor; - - /// - /// Manage the simultaneous layout to two . - /// - public interface IViewSynchronizationManager - { - ITextView GetSubordinateView(ITextView masterView); - - bool TryGetAnchorPointInSubordinateView(SnapshotPoint anchorPoint, out SnapshotPoint correspondingAnchorPoint); - - SnapshotPoint GetAnchorPointAboveInSubordinateView(SnapshotPoint anchorPoint); - - void WhichPairedLinesShouldBeDisplayed(SnapshotPoint masterAnchorPoint, SnapshotPoint subordinateAnchorPoint, out bool layoutMaster, out bool layoutSubordinate, bool goingUp); - } -} \ No newline at end of file diff --git a/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs b/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs index 1cbfd40..c6cd992 100644 --- a/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs +++ b/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs @@ -1,14 +1,25 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Text.Operations; + namespace Microsoft.VisualStudio.Text.Operations { /// /// Defines operations relating to the editor, in addition to operations defined by . /// - public interface IEditorOperations4 : IEditorOperations3 + internal interface IEditorOperations4 : IEditorOperations3 { + /// + /// Returns a string with the original content except for newlines, which are replaced to match the document + /// + /// Text to normalize newlines + /// The normalized string, if the document has enough information to normalize with. The original string otherwise. + /// This method uses the newline state associated with the document buffer. + string NormalizeNewlinesInString(string text); + /// /// Determines whether zooming operations are possible. /// @@ -44,4 +55,4 @@ namespace Microsoft.VisualStudio.Text.Operations /// void JoinSelectedLines(); } -} \ No newline at end of file +} diff --git a/src/Editor/Text/Def/TextUICocoa/Editor/ICocoaTextView.cs b/src/Editor/Text/Def/TextUICocoa/Editor/ICocoaTextView.cs index f7fe9e5..7a3160b 100644 --- a/src/Editor/Text/Def/TextUICocoa/Editor/ICocoaTextView.cs +++ b/src/Editor/Text/Def/TextUICocoa/Editor/ICocoaTextView.cs @@ -7,10 +7,11 @@ using System; using AppKit; using CoreGraphics; +using Microsoft.VisualStudio.Text.Formatting; namespace Microsoft.VisualStudio.Text.Editor { - public interface ICocoaTextView : ITextView3 + public interface ICocoaTextView : ITextView2 { /// /// Gets the that renders the view. @@ -35,5 +36,22 @@ namespace Microsoft.VisualStudio.Text.Editor void PushCursor(object context, NSCursor cursor); void PopCursor(object context); + + + /// + /// Gets or sets the Zoom level for the between 20% to 400% + /// + double ZoomLevel { get; set; } + + IXPlatAdornmentLayer GetXPlatAdornmentLayer(string name); + + ITextViewLineSource FormattedLineSource { get; } + + void Focus(); + + bool IsKeyboardFocused { get; } + event EventHandler IsKeyboardFocusedChanged; + + IViewSynchronizationManager SynchronizationManager { get; set; } } } \ No newline at end of file diff --git a/src/Editor/Text/Def/TextUICocoa/Editor/IViewSynchronizationManager.cs b/src/Editor/Text/Def/TextUICocoa/Editor/IViewSynchronizationManager.cs new file mode 100644 index 0000000..70eddaa --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Editor/IViewSynchronizationManager.cs @@ -0,0 +1,22 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +namespace Microsoft.VisualStudio.Text.Formatting +{ + using Microsoft.VisualStudio.Text.Editor; + + /// + /// Manage the simultaneous layout to two . + /// + public interface IViewSynchronizationManager + { + ITextView GetSubordinateView(ITextView masterView); + + bool TryGetAnchorPointInSubordinateView(SnapshotPoint anchorPoint, out SnapshotPoint correspondingAnchorPoint); + + SnapshotPoint GetAnchorPointAboveInSubordinateView(SnapshotPoint anchorPoint); + + void WhichPairedLinesShouldBeDisplayed(SnapshotPoint masterAnchorPoint, SnapshotPoint subordinateAnchorPoint, out bool layoutMaster, out bool layoutSubordinate, bool goingUp); + } +} \ No newline at end of file diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/CodeSnippet.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/CodeSnippet.cs new file mode 100644 index 0000000..e5f0fa1 --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/CodeSnippet.cs @@ -0,0 +1,123 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System.Collections.Generic; +using System.Linq; +using System.Xml; +using System.Xml.Linq; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public class CodeSnippet + { + public string Title { get; set; } + public string Shortcut { get; set; } + public string Description { get; set; } + public string Author { get; set; } + public List SnippetTypes { get; set; } + public string Code { get; set; } + public List Fields { get; set; } + public string FilePath { get; set; } + public string Language { get; set; } + public XElement Snippet { get; set; } + + public CodeSnippet() + { + + } + + public CodeSnippet(XElement codeSnippetElement, string filePath) + { + this.FilePath = filePath; + this.Fields = new List(); + this.SnippetTypes = new List(); + + var header = codeSnippetElement.Element(GetXName("Header")); + this.Title = GetElementInnerText(header, "Title"); + this.Shortcut = GetElementInnerText(header, "Shortcut") ?? ""; // https://github.com/dotnet/roslyn/pull/31738 + this.Description = GetElementInnerText(header, "Description"); + this.Author = GetElementInnerText(header, "Author"); + var snippetTypes = header.Element(GetXName("SnippetTypes")); + if (snippetTypes != null) + { + var snippetTypeElements = snippetTypes.Elements(); + foreach (var snippetType in snippetTypeElements) + { + SnippetTypes.Add(snippetType.Value); + } + } + + Snippet = codeSnippetElement.Element(GetXName("Snippet")); + var declarations = Snippet.Element(GetXName("Declarations")); + ReadDeclarations(declarations); + var code = Snippet.Element(GetXName("Code")); + this.Code = code.Value.Replace("\n", "\r\n"); + this.Language = code.Attribute("Language").Value; + } + + private void ReadDeclarations(XElement declarations) + { + if (declarations == null) + { + return; + } + + foreach (var declarationElement in declarations.Elements()) + { + var defaultAttribute = declarationElement.Attribute("Default"); + var editableAttribute = declarationElement.Attribute("Editable"); + this.Fields.Add(new ExpansionField + { + ID = GetElementInnerText(declarationElement, "ID"), + ToolTip = GetElementInnerText(declarationElement, "ToolTip"), + Default = GetElementInnerText(declarationElement, "Default") ?? " ", + Function = GetElementInnerText(declarationElement, "Function"), + IsDefault = defaultAttribute != null && defaultAttribute.Value == "true", + Editable = editableAttribute == null || editableAttribute.Value == "true" || editableAttribute.Value == "1" + }); + } + } + + private static string GetElementInnerText(XElement element, string subElementName) + { + var subElement = element.Element(GetXName(subElementName)); + if (subElement == null) + { + return null; + } + + return subElement.Value; + } + + public static IEnumerable ReadSnippetsFromFile(string filePath) + { + try + { + XDocument document = XDocument.Load(filePath); + var codeSnippetsElement = document.Root; + IEnumerable codeSnippetElements = null; + if (codeSnippetsElement.Name.LocalName == "CodeSnippets") + { + codeSnippetElements = codeSnippetsElement.Elements(GetXName("CodeSnippet")); + } + else + { + codeSnippetElements = new[] { codeSnippetsElement }; + } + + return codeSnippetElements.Select(element => new CodeSnippet(element, filePath)); + } + catch (XmlException) + { + return Enumerable.Empty(); + } + } + + private static XName GetXName(string localName) + { + return XName.Get(localName, "http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"); + } + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionField.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionField.cs new file mode 100644 index 0000000..9bdef92 --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionField.cs @@ -0,0 +1,75 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public class ExpansionField + { + public string ID { get; set; } + public string ToolTip { get; set; } + public string Default { get; set; } + public string Function { get; set; } + + private List offsets = new List(); + + public int GetOffsetCount() + { + return offsets.Count; + } + + public void AddOffset(int offset) + { + offsets.Add(offset); + } + + public int GetOffset(int index) + { + return offsets[index]; + } + + public string GetDefault() + { + return Default; + } + + public int GetLength() + { + return Default.Length; + } + + public bool IsEditable() + { + return Editable; + } + + public XElement GetFunctionXML() + { + return new XElement(XName.Get("ExpansionField")) + { + Value = Function + }; + } + + public bool UsesFunction() + { + return Function != null; + } + + public bool IsDefault { get; set; } + public bool Editable { get; set; } + + public string GetName() + { + return ID; + } + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionTemplate.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionTemplate.cs new file mode 100644 index 0000000..356d2bd --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/ExpansionTemplate.cs @@ -0,0 +1,148 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public class ExpansionTemplate + { + private string snippetFullText; + private readonly List tokens = new List(); + private int selectedOffset; + private int editOffset; + private string snippetFirst; + private string snippetLast; + + public CodeSnippet Snippet { get; set; } + + public ExpansionTemplate(string filePath) + :this(CodeSnippet.ReadSnippetsFromFile(filePath).First()) + { + + } + + public ExpansionTemplate(CodeSnippet snippet) + { + Snippet = snippet; + Parse(); + } + + private void Parse() + { + foreach (var field in Snippet.Fields) + { + tokens.Add(field); + } + + var matches = Regex.Matches(Snippet.Code, @"\$(\w+)\$"); + + var total = new StringBuilder(); + int index = 0; + int indexCorrection = 0; + foreach (Match match in matches) + { + string fieldName = match.Groups[1].Value; + string substitution = GetDefaultValue(fieldName) ?? ""; + if (match.Index > index) + { + total.Append(Snippet.Code.Substring(index, match.Index - index)); + } + + AddToken(total.Length, fieldName); + total.Append(substitution); + + index = match.Index + match.Length; + indexCorrection += substitution.Length; + } + + if (index <= Snippet.Code.Length - 1) + { + total.Append(Snippet.Code.Substring(index, Snippet.Code.Length - index)); + } + + this.snippetFullText = total.ToString(); + this.snippetFirst = snippetFullText.Substring(0, selectedOffset); + this.snippetLast = snippetFullText.Substring(selectedOffset, snippetFullText.Length - selectedOffset); + } + + private string GetDefaultValue(string fieldName) + { + ExpansionField field = FindField(fieldName); + if (field == null) + { + return null; + } + + return field.Default; + } + + private void AddToken(int position, string fieldName) + { + ExpansionField field = FindField(fieldName); + if (field != null) + { + field.AddOffset(position); + } + else if (fieldName == "selected") + { + this.selectedOffset = position; + } + else if (fieldName == "end") + { + this.editOffset = position; + } + } + + private ExpansionField FindField(string fieldName) + { + return tokens.FirstOrDefault(t => t.ID == fieldName); + } + + public string GetCodeSnippet() + { + return snippetFullText; + } + + public int GetSelectedOffset() + { + return selectedOffset; + } + + public int GetEditOffset() + { + return editOffset; + } + + public string GetCodeSnippet(bool all, bool first) + { + if (all) + { + return snippetFullText; + } + else if (first) + { + return snippetFirst; + } + else + { + return snippetLast; + } + } + + public IEnumerable Fields + { + get + { + return tokens; + } + } + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionClient.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionClient.cs new file mode 100644 index 0000000..f04d13c --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionClient.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Xml.Linq; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public interface IExpansionClient + { + IExpansionFunction GetExpansionFunction(XElement xmlFunctionNode, string fieldName); + void FormatSpan(SnapshotSpan span); + + void EndExpansion(); + + void OnBeforeInsertion(IExpansionSession session); + void OnAfterInsertion(IExpansionSession session); + + void PositionCaretForEditing(ITextView textView, SnapshotPoint point); + void OnItemChosen(string tittle, string path); + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionFunction.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionFunction.cs new file mode 100644 index 0000000..af945a5 --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionFunction.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public enum ExpansionFunctionType + { + List, + Value + }; + + public interface IExpansionFunction + { + void GetDefaultValue(out string value, out bool hasDefaultValue); + + void GetCurrentValue(out string value, out bool hasCurrentValue); + + bool FieldChanged(string fieldName); + + ExpansionFunctionType GetFunctionType(); + + int GetListCount(); + + string GetListText(int index); + + void ReleaseFunction(); + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionManager.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionManager.cs new file mode 100644 index 0000000..077b20b --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionManager.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public interface IExpansionManager + { + IEnumerable EnumerateExpansions(IContentType contentType, bool shortcutOnly, string[] snippetTypes, bool includeNullType, bool includeDuplicates); + ExpansionTemplate GetTemplateByName(IExpansionClient expansionClient, IContentType contentType, string name, string filePath, ITextView textView, SnapshotSpan span, bool showDisambiguationUI); + ExpansionTemplate GetTemplateByShortcut(IExpansionClient expansionClient, string shortcut, IContentType contentType, ITextView textView, SnapshotSpan span, bool showDisambiguationUI); + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionService.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionService.cs new file mode 100644 index 0000000..193edf5 --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionService.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Threading; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public interface IExpansionService + { + IExpansionSession InsertExpansion(SnapshotSpan triggerSpan, IExpansionClient expansionClient, IContentType contentType, CancellationToken cancellationToken = default); + IExpansionSession InsertNamedExpansion(string title, string pszPath, SnapshotSpan triggerSpan, IExpansionClient expansionClient, IContentType contentType, bool showDisambiguationUI); + void InvokeInsertionUI(IExpansionClient expansionClient, IContentType contentType, string[] types, bool includeNullType, string[] kinds, bool includeNullKind, string prefixText, string completionChar); + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionServiceProvider.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionServiceProvider.cs new file mode 100644 index 0000000..cead20d --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionServiceProvider.cs @@ -0,0 +1,12 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public interface IExpansionServiceProvider + { + IExpansionService GetExpansionService(ITextView textView); + } +} diff --git a/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionSession.cs b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionSession.cs new file mode 100644 index 0000000..9845f93 --- /dev/null +++ b/src/Editor/Text/Def/TextUICocoa/Snippet/IExpansionSession.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Xml.Linq; + +namespace Microsoft.VisualStudio.Text.Editor.Expansion +{ + public interface IExpansionSession + { + void EndCurrentExpansion(bool leaveCaret); + bool GoToNextExpansionField(bool commitIfLast); + bool GoToPreviousExpansionField(); + string GetFieldValue(string fieldName); + void SetFieldDefault(string fieldName, string newValue); + SnapshotSpan GetFieldSpan(string fieldName); + XElement GetHeaderNode(); + XElement GetDeclarationNode(); + XElement GetSnippetNode(); + SnapshotSpan GetSnippetSpan(); + SnapshotSpan EndSpan { get; set; } + } +} diff --git a/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentService.cs b/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentService.cs index 430e947..c6a1704 100644 --- a/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentService.cs +++ b/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentService.cs @@ -24,7 +24,7 @@ namespace Microsoft.VisualStudio.Text.BraceCompletion.Implementation #region Private Members private ITrackingPoint _trackingPoint; - private ITextView3 _textView; + private ICocoaTextView _textView; private IXPlatAdornmentLayer _adornmentLayer; private readonly IEditorFormatMap _editorFormatMap; private Brush _brush; @@ -33,9 +33,9 @@ namespace Microsoft.VisualStudio.Text.BraceCompletion.Implementation #region Constructors - public BraceCompletionAdornmentService(ITextView3 textView, IEditorFormatMap editorFormatMap) + public BraceCompletionAdornmentService(ITextView textView, IEditorFormatMap editorFormatMap) { - _textView = textView; + _textView = (ICocoaTextView)textView; _editorFormatMap = editorFormatMap; if (_textView == null) diff --git a/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentServiceFactory.cs b/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentServiceFactory.cs index 6938df8..d5c0b62 100644 --- a/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentServiceFactory.cs +++ b/src/Editor/Text/Impl/BraceCompletion/BraceCompletionAdornmentServiceFactory.cs @@ -29,7 +29,7 @@ namespace Microsoft.VisualStudio.Text.BraceCompletion.Implementation { // Get the service from the view's property bag return textView.Properties.GetOrCreateSingletonProperty( - () => new BraceCompletionAdornmentService((ITextView3)textView, _editorFormatMapService.GetEditorFormatMap(textView))); + () => new BraceCompletionAdornmentService(textView, _editorFormatMapService.GetEditorFormatMap(textView))); } #endregion diff --git a/src/Editor/Text/Impl/BraceCompletion/BraceCompletionImpl.csproj b/src/Editor/Text/Impl/BraceCompletion/BraceCompletionImpl.csproj index bb50037..d8eb0fc 100644 --- a/src/Editor/Text/Impl/BraceCompletion/BraceCompletionImpl.csproj +++ b/src/Editor/Text/Impl/BraceCompletion/BraceCompletionImpl.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs b/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs index 3f6107d..3a2c915 100644 --- a/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs +++ b/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs @@ -27,6 +27,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation using Microsoft.VisualStudio.Text.Tagging; using Microsoft.VisualStudio.Language.Intellisense.Utilities; using Microsoft.VisualStudio.Text.Utilities; + using Microsoft.VisualStudio.Text.Data.Utilities; /// /// Provides a default operations set on top of the text editor @@ -56,7 +57,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation #region Private Members - readonly ITextView3 _textView; + readonly ITextView _textView; readonly EditorOperationsFactoryService _factory; readonly ITextDocument _textDocument; readonly ITextStructureNavigator _textStructureNavigator; @@ -96,7 +97,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation if (factory == null) throw new ArgumentNullException(nameof(factory)); - _textView = (Microsoft.VisualStudio.Text.Editor.ITextView3) textView; + _textView = textView; _factory = factory; _multiSelectionBroker = _textView.GetMultiSelectionBroker(); _editorPrimitives = factory.EditorPrimitivesProvider.GetViewPrimitives(textView); @@ -3188,14 +3189,20 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation public void ScrollColumnLeft() { - // A column is defined as the width of a space in the default font - _textView.ViewScroller.ScrollViewportHorizontallyByPixels(_textView.FormattedLineSource.ColumnWidth * -1.0); + if (_textView.ViewScroller is IViewScroller2 viewScroller) + { + // A column is defined as the width of a space in the default font + viewScroller.ScrollColumnLeft(); + } } public void ScrollColumnRight() { - // A column is defined as the width of a space in the default font - _textView.ViewScroller.ScrollViewportHorizontallyByPixels(_textView.FormattedLineSource.ColumnWidth); + if (_textView.ViewScroller is IViewScroller2 viewScroller) + { + // A column is defined as the width of a space in the default font + viewScroller.ScrollColumnRight(); + } } public void ScrollLineBottom() @@ -3229,54 +3236,35 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation _undoHistory.CurrentTransaction.AddUndo(beforeTextBufferChangeUndoPrimitive); } - public bool CanZoomIn => CanZoomTo && _textView.ZoomLevel < _textView.Options.GlobalOptions.MaxZoom(); + public bool CanZoomIn => CanZoomTo && _factory.ZoomManager.ZoomLevel(_textView) < _textView.Options.GlobalOptions.MaxZoom(); - public void ZoomIn() - { - if (CanZoomIn) - { - var maxZoom = _textView.Options.GlobalOptions.MaxZoom(); - double zoomLevel = Math.Min(_textView.ZoomLevel * ZoomConstants.ScalingFactor, maxZoom); - if (zoomLevel < maxZoom || Math.Abs(zoomLevel - maxZoom) < 0.00001) - { - _textView.Options.GlobalOptions.SetOptionValue(DefaultTextViewOptions.ZoomLevelId, zoomLevel); - } - } - } + public bool CanZoomOut => CanZoomTo && _factory.ZoomManager.ZoomLevel(_textView) > _textView.Options.GlobalOptions.MinZoom(); - public bool CanZoomOut => CanZoomTo && _textView.ZoomLevel > _textView.Options.GlobalOptions.MinZoom(); + public bool CanZoomTo => _textView.Roles.Contains(PredefinedTextViewRoles.Zoomable); - public void ZoomOut() + public bool CanZoomReset => CanZoomTo && _factory.ZoomManager.ZoomLevel(_textView) != ZoomConstants.DefaultZoom; + + public void ZoomReset() { - if (CanZoomOut) + if (CanZoomReset) { - var minZoom = _textView.Options.GlobalOptions.MinZoom(); - double zoomLevel = Math.Max(_textView.ZoomLevel / ZoomConstants.ScalingFactor, minZoom); - if (zoomLevel > minZoom || Math.Abs(zoomLevel - minZoom) < 0.00001) - { - _textView.Options.GlobalOptions.SetOptionValue(DefaultTextViewOptions.ZoomLevelId, zoomLevel); - } + ZoomTo(ZoomConstants.DefaultZoom); } } - public bool CanZoomTo => _textView.Roles.Contains(PredefinedTextViewRoles.Zoomable); - - public void ZoomTo(double zoomLevel) + public void ZoomIn() { - if (CanZoomTo) - { - _textView.Options.GlobalOptions.SetZoomLevel(zoomLevel); - } + _factory.ZoomManager.ZoomIn(_textView); } - public bool CanZoomReset => CanZoomTo && _textView.ZoomLevel != ZoomConstants.DefaultZoom; + public void ZoomOut() + { + _factory.ZoomManager.ZoomOut(_textView); + } - public void ZoomReset() + public void ZoomTo(double zoomLevel) { - if (CanZoomReset) - { - ZoomTo(ZoomConstants.DefaultZoom); - } + _factory.ZoomManager.ZoomTo(_textView, zoomLevel); } #endregion // IEditorOperations Members @@ -5350,6 +5338,18 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation }); } } + + public string NormalizeNewlinesInString(string text) + { + if (_factory.WhitespaceManagerFactory.TryGetExistingWhitespaceManager(_textView.TextDataModel.DocumentBuffer, out var whitespaceManager)) + { + return whitespaceManager.NewlineState.NormalizeNewlines(text); + } + else + { + return text; + } + } } /// diff --git a/src/Editor/Text/Impl/EditorOperations/EditorOperationsFactoryService.cs b/src/Editor/Text/Impl/EditorOperations/EditorOperationsFactoryService.cs index b58c2ca..3e39491 100644 --- a/src/Editor/Text/Impl/EditorOperations/EditorOperationsFactoryService.cs +++ b/src/Editor/Text/Impl/EditorOperations/EditorOperationsFactoryService.cs @@ -15,6 +15,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation using Microsoft.VisualStudio.Utilities; using Microsoft.VisualStudio.Text.Outlining; using Microsoft.VisualStudio.Language.Intellisense.Utilities; + using Microsoft.VisualStudio.Text.Document; [Export(typeof(IEditorOperationsFactoryService))] internal sealed class EditorOperationsFactoryService : IEditorOperationsFactoryService @@ -59,6 +60,12 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation [Import(AllowDefault = true)] internal IOutliningManagerService OutliningManagerService { get; set; } + [Import] + internal IWhitespaceManagerFactory WhitespaceManagerFactory { get; set; } + + [Import] + internal ITextViewZoomManager ZoomManager { get; set; } + /// /// Provides a operations implementation for a given text view. /// diff --git a/src/Editor/Text/Util/TextDataUtil/AssemblyInfo.cs b/src/Editor/Text/Util/TextDataUtil/AssemblyInfo.cs index ccc6bf1..4d26ded 100644 --- a/src/Editor/Text/Util/TextDataUtil/AssemblyInfo.cs +++ b/src/Editor/Text/Util/TextDataUtil/AssemblyInfo.cs @@ -73,6 +73,7 @@ using System.Runtime.ConstrainedExecution; [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.MultiSelection.Implementation.UI.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Cocoa.View.Implementation, PublicKey=" + ThisAssembly.PublicKey)] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Platform.VSEditor, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.EditorOperations.Implementation, PublicKey=" + ThisAssembly.PublicKey)] // // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information diff --git a/src/Editor/Text/Util/TextUICocoaUtil/AssemblyInfo.cs b/src/Editor/Text/Util/TextUICocoaUtil/AssemblyInfo.cs new file mode 100644 index 0000000..04d474d --- /dev/null +++ b/src/Editor/Text/Util/TextUICocoaUtil/AssemblyInfo.cs @@ -0,0 +1,48 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Security.Permissions; + +[assembly: InternalsVisibleTo("EditorTestApp, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Language.Intellisense.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.DifferenceViewer.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.Differencing.DifferenceViewer.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.Editor.PrintingService.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.MultiCaret.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.MultiCaret.Implementation.UI, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.OverviewMargin.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.TextViewUnitTestHelper, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.UI.Utilities.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.AdornmentLibrary.TextMarker.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.AdornmentLibrary.ToolTip.Wpf.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Commanding.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Commanding.Implementation.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.CurrentLineHighlighter.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.TextMarkerAdornment.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.Classification.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.DragDrop.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.GlyphMargin.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.Input.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.Input.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.OverviewMargin.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.View.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.View.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Wpf.FileHealthIndicator.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Implementation, PublicKey=" + ThisAssembly.PublicKey)] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Text.UI.Utilities.UnitTests, PublicKey=" + ThisAssembly.PublicKey)] + +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.UI.Text.Cocoa.View.Implementation, PublicKey=" + ThisAssembly.PublicKey)] + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: SecurityPermission(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.Execution)] +[assembly: ReliabilityContract(Consistency.MayCorruptProcess, Cer.MayFail)] diff --git a/src/Editor/Text/Util/TextUICocoaUtil/CocoaTextViewZoomManager.cs b/src/Editor/Text/Util/TextUICocoaUtil/CocoaTextViewZoomManager.cs new file mode 100644 index 0000000..b245487 --- /dev/null +++ b/src/Editor/Text/Util/TextUICocoaUtil/CocoaTextViewZoomManager.cs @@ -0,0 +1,65 @@ + +using System; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.VisualStudio.Text.Utilities +{ + [ExportImplementation(typeof(ITextViewZoomManager))] + [Name("Cocoa zoom manager")] + [Order(Before = "default")] + internal class CocoaTextViewZoomManager : ITextViewZoomManager + { + public double ZoomLevel(ITextView textView) => ((ICocoaTextView)textView).ZoomLevel; + + public void ZoomIn(ITextView textView) + { + if (textView is null) + { + throw new ArgumentNullException(nameof(textView)); + } + + ICocoaTextView cocoaTextView = textView as ICocoaTextView; + if (cocoaTextView != null && cocoaTextView.Roles.Contains(PredefinedTextViewRoles.Zoomable)) + { + double zoomLevel = cocoaTextView.ZoomLevel * ZoomConstants.ScalingFactor; + if (zoomLevel < ZoomConstants.MaxZoom || Math.Abs(zoomLevel - ZoomConstants.MaxZoom) < 0.00001) + { + cocoaTextView.Options.GlobalOptions.SetOptionValue(DefaultTextViewOptions.ZoomLevelId, zoomLevel); + } + } + } + + public void ZoomOut(ITextView textView) + { + if (textView is null) + { + throw new ArgumentNullException(nameof(textView)); + } + + ICocoaTextView cocoaTextView = textView as ICocoaTextView; + if (cocoaTextView != null && cocoaTextView.Roles.Contains(PredefinedTextViewRoles.Zoomable)) + { + double zoomLevel = cocoaTextView.ZoomLevel / ZoomConstants.ScalingFactor; + if (zoomLevel > ZoomConstants.MinZoom || Math.Abs(zoomLevel - ZoomConstants.MinZoom) < 0.00001) + { + cocoaTextView.Options.GlobalOptions.SetOptionValue(DefaultTextViewOptions.ZoomLevelId, zoomLevel); + } + } + } + + public void ZoomTo(ITextView textView, double zoomLevel) + { + if (textView is null) + { + throw new ArgumentNullException(nameof(textView)); + } + + ICocoaTextView cocoaTextView = textView as ICocoaTextView; + if (cocoaTextView != null && cocoaTextView.Roles.Contains(PredefinedTextViewRoles.Zoomable)) + { + cocoaTextView.Options.GlobalOptions.SetOptionValue(DefaultTextViewOptions.ZoomLevelId, zoomLevel); + } + } + } +} diff --git a/src/Editor/Text/Util/TextUICocoaUtil/DifferenceBrushManager.cs b/src/Editor/Text/Util/TextUICocoaUtil/DifferenceBrushManager.cs new file mode 100644 index 0000000..929e29c --- /dev/null +++ b/src/Editor/Text/Util/TextUICocoaUtil/DifferenceBrushManager.cs @@ -0,0 +1,119 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +// This file contain implementations details that are subject to change without notice. +// Use at your own risk. +// +using System; +using System.Linq; +using System.Windows.Media; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Text.Editor; + +namespace Microsoft.VisualStudio.Text.Utilities +{ + class DifferenceBrushManager + { + public static DifferenceBrushManager GetBrushManager(ITextView view, IEditorFormatMapService formatMapService) + { + return view.Properties.GetOrCreateSingletonProperty(() => new DifferenceBrushManager(view, formatMapService.GetEditorFormatMap(view))); + } + + public static DifferenceBrushManager GetBrushManager(ITextView view, IEditorFormatMap formatMap) + { + return view.Properties.GetOrCreateSingletonProperty(() => new DifferenceBrushManager(view, formatMap)); + } + + // internal for unit testing + internal static readonly SolidColorBrush _defaultRemovedLineBrush = Brushes.PaleVioletRed; + internal static readonly SolidColorBrush _defaultAddedLineBrush = Brushes.LightYellow; + internal static readonly SolidColorBrush _defaultRemovedWordBrush = Brushes.Red; + internal static readonly SolidColorBrush _defaultAddedWordBrush = Brushes.Yellow; + + IEditorFormatMap _formatMap; + + #region Public properties (brushes) and changed event + + public Brush RemovedLineBrush { get; private set; } + public Brush AddedLineBrush { get; private set; } + + public Brush RemovedWordBrush { get; private set; } + public Brush RemovedWordForegroundBrush { get; private set; } + public Pen RemovedWordForegroundPen { get; private set; } + public Brush AddedWordBrush { get; private set; } + public Brush AddedWordForegroundBrush { get; private set; } + public Pen AddedWordForegroundPen { get; private set; } + + public Brush ViewportBrush { get; private set; } + public Pen ViewportPen { get; private set; } + public Brush OverviewBrush { get; private set; } + + public event EventHandler BrushesChanged; + + #endregion + + internal DifferenceBrushManager(ITextView view, IEditorFormatMap formatMap) + { + _formatMap = formatMap; + + InitializeBrushes(); + + _formatMap.FormatMappingChanged += FormatMapChanged; + view.Closed += (s, a) => { _formatMap.FormatMappingChanged -= FormatMapChanged; }; + } + + void InitializeBrushes() + { + RemovedLineBrush = GetBrushValue("deltadiff.remove.line", _defaultRemovedLineBrush); + RemovedWordBrush = GetBrushValue("deltadiff.remove.word", _defaultRemovedWordBrush); + RemovedWordForegroundBrush = GetBrushValue("deltadiff.remove.word", _defaultRemovedWordBrush, EditorFormatDefinition.ForegroundBrushId); + RemovedWordForegroundPen = new Pen(RemovedWordForegroundBrush, 2.0); + RemovedWordForegroundPen.Freeze(); + + AddedLineBrush = GetBrushValue("deltadiff.add.line", _defaultAddedLineBrush); + AddedWordBrush = GetBrushValue("deltadiff.add.word", _defaultAddedWordBrush); + AddedWordForegroundBrush = GetBrushValue("deltadiff.add.word", _defaultAddedWordBrush, EditorFormatDefinition.ForegroundBrushId); + AddedWordForegroundPen = new Pen(AddedWordForegroundBrush, 2.0); + AddedWordForegroundPen.Freeze(); + + ViewportBrush = GetBrushValue("deltadiff.overview.color", Brushes.DarkGray, EditorFormatDefinition.ForegroundBrushId); + ViewportPen = new Pen(ViewportBrush, 2.0); + ViewportPen.Freeze(); + + OverviewBrush = GetBrushValue("deltadiff.overview.color", Brushes.Gray); + + var temp = BrushesChanged; + if (temp != null) + temp(this, EventArgs.Empty); + } + + Brush GetBrushValue(string formatName, Brush defaultValue, string resource = EditorFormatDefinition.BackgroundBrushId) + { + var formatProperties = _formatMap.GetProperties(formatName); + if (formatProperties != null && formatProperties.Contains(resource)) + { + var brushValue = formatProperties[resource] as Brush; + if (brushValue != null) + return brushValue; + } + + return defaultValue; + } + + void FormatMapChanged(object sender, FormatItemsEventArgs e) + { + bool updateRequired = e.ChangedItems.Any(item => + string.Equals(item, "deltadiff.add.word", System.StringComparison.OrdinalIgnoreCase) || + string.Equals(item, "deltadiff.add.line", System.StringComparison.OrdinalIgnoreCase) || + string.Equals(item, "deltadiff.remove.word", System.StringComparison.OrdinalIgnoreCase) || + string.Equals(item, "deltadiff.remove.line", System.StringComparison.OrdinalIgnoreCase) || + string.Equals(item, "deltadiff.overview.color", System.StringComparison.OrdinalIgnoreCase)); + + if (updateRequired) + { + InitializeBrushes(); + } + } + } +} diff --git a/src/Editor/Text/Util/TextUICocoaUtil/IDragDropMouseProcessor.cs b/src/Editor/Text/Util/TextUICocoaUtil/IDragDropMouseProcessor.cs new file mode 100644 index 0000000..185f0a8 --- /dev/null +++ b/src/Editor/Text/Util/TextUICocoaUtil/IDragDropMouseProcessor.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +namespace Microsoft.VisualStudio.Text.Utilities +{ + using System.Windows; + using System.Windows.Input; + + /// + /// This interface is a used as an abstraction of the DragDropMouseProcessor so that it can be called from the left margin + /// to handle drag/drop. + /// + public interface IDragDropMouseProcessor + { + void DoPreprocessMouseLeftButtonDown(MouseButtonEventArgs e, Point position); + void DoPreprocessMouseLeftButtonUp(MouseButtonEventArgs e, Point position); + void DoPostprocessMouseLeftButtonUp(MouseButtonEventArgs e, Point position); + void DoPreprocessMouseMove(MouseEventArgs e, Point position); + void DoPreprocessDrop(DragEventArgs e, Point position); + void DoPreprocessDragEnter(DragEventArgs e, Point position); + void DoPreprocessDragLeave(DragEventArgs e); + void DoPreprocessDragOver(DragEventArgs e, Point position); + void DoPreprocessQueryContinueDrag(QueryContinueDragEventArgs e); + void DoPostprocessMouseLeave(MouseEventArgs e); + } +} \ No newline at end of file diff --git a/src/Editor/Text/Util/TextUICocoaUtil/TelemetryLogger.cs b/src/Editor/Text/Util/TextUICocoaUtil/TelemetryLogger.cs new file mode 100644 index 0000000..912930c --- /dev/null +++ b/src/Editor/Text/Util/TextUICocoaUtil/TelemetryLogger.cs @@ -0,0 +1,142 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// +using System; +using System.ComponentModel.Composition; +using System.Windows.Threading; + +namespace Microsoft.VisualStudio.Text.Utilities +{ + [Export] + [PartCreationPolicy(CreationPolicy.Shared)] + internal sealed class TelemetryLogger + { + // This import may fail if we are running outside of VS, in scenarios such as CodeFlow. That is ok + // and this logging code should gracefully no-op in that case. + [Import(AllowDefault = true)] + private ILoggingServiceInternal LoggingService { get; set; } + + public const string VSEditorKey = "VS/Editor"; + + const string ExceptionEventName = VSEditorKey + "/Exception"; + + DispatcherTimer _touchZoomTimer = null; + DispatcherTimer _touchScrollTimer = null; + DispatcherTimer _zoomTimer = null; + DispatcherTimer _scrollTimer = null; + + uint _lastZoomLevel = 0; + readonly TimeSpan _timeout = TimeSpan.FromMilliseconds(1000.0); + + public void LogTouchZoom() + { + if (LoggingService != null) + { + if (_touchZoomTimer == null) + { + _touchZoomTimer = new DispatcherTimer(); + _touchZoomTimer.Interval = _timeout; + _touchZoomTimer.Tick += (s, e) => + { + _touchZoomTimer.Stop(); + LoggingService.AdjustCounter(TelemetryLogger.VSEditorKey, "TouchZoom", delta: 1); + }; + } + + // Restart timer + _touchZoomTimer.Stop(); + _touchZoomTimer.Start(); + } + } + + public void LogZoom(uint finalZoomLevel) + { + if (LoggingService != null) + { + if (_zoomTimer == null) + { + _zoomTimer = new DispatcherTimer(); + _zoomTimer.Interval = _timeout; + _zoomTimer.Tick += (s, e) => + { + _zoomTimer.Stop(); + LoggingService.PostEvent("VS/Editor/Zoom", "VS.Editor.Zoom.LastZoomLevel", _lastZoomLevel); + }; + } + + // Restart timer + _zoomTimer.Stop(); + + // Set _lastZoomLevel between stop and start out of paranoia regarding race conditions that shouldn't + // actually occur while using DispatcherTimer, since it runs all on the same thread. However, if the + // underlying timer get's changed, and this set were above the stop, there's a chance that we could + // occasionally log incorrect data if the set happened, and then tick occurred before the stop. + _lastZoomLevel = finalZoomLevel; + + _zoomTimer.Start(); + } + } + + public void LogTouchScroll() + { + if (LoggingService != null) + { + if (_touchScrollTimer == null) + { + _touchScrollTimer = new DispatcherTimer(); + _touchScrollTimer.Interval = _timeout; + _touchScrollTimer.Tick += (s, e) => + { + _touchScrollTimer.Stop(); + LoggingService.AdjustCounter(TelemetryLogger.VSEditorKey, "TouchScroll", delta: 1); + }; + } + + // Restart timer + _touchScrollTimer.Stop(); + _touchScrollTimer.Start(); + } + } + + public void LogScroll() + { + if (LoggingService != null) + { + if (_scrollTimer == null) + { + _scrollTimer = new DispatcherTimer(); + _scrollTimer.Interval = _timeout; + _scrollTimer.Tick += (s, e) => + { + _scrollTimer.Stop(); + LoggingService.AdjustCounter(TelemetryLogger.VSEditorKey, "Scroll", delta: 1); + }; + } + + // Restart timer + _scrollTimer.Stop(); + _scrollTimer.Start(); + } + } + + public void LogException( + Exception exception, + string description = "An unhandled exception occurred in the editor") + { + try + { + LoggingService?.PostFault( + ExceptionEventName, + description, + exception); + } + catch { } + } + + public void PostCounters() + { + LoggingService?.PostCounters(); + } + } +} \ No newline at end of file diff --git a/src/Editor/Text/Util/TextUICocoaUtil/TextUICocoaUtil.csproj b/src/Editor/Text/Util/TextUICocoaUtil/TextUICocoaUtil.csproj new file mode 100644 index 0000000..ae46b47 --- /dev/null +++ b/src/Editor/Text/Util/TextUICocoaUtil/TextUICocoaUtil.csproj @@ -0,0 +1,35 @@ + + + + Microsoft.VisualStudio.Text.UI.Cocoa.Utilities + $(AssemblyName) + + + $(FullNETFrameworkVersion) + + 436;$(NoWarn) + true + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Editor/Text/Util/TextUIUtil/DefaultTextViewZoomManager.cs b/src/Editor/Text/Util/TextUIUtil/DefaultTextViewZoomManager.cs new file mode 100644 index 0000000..92c8820 --- /dev/null +++ b/src/Editor/Text/Util/TextUIUtil/DefaultTextViewZoomManager.cs @@ -0,0 +1,27 @@ +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.VisualStudio.Text.Utilities +{ + [ExportImplementation(typeof(ITextViewZoomManager))] + [Name("default")] + internal class DefaultTextViewZoomManager : ITextViewZoomManager + { + public void ZoomIn(ITextView textView) + { + } + + public double ZoomLevel(ITextView textView) + { + return 100; + } + + public void ZoomOut(ITextView textView) + { + } + + public void ZoomTo(ITextView textView, double zoomLevel) + { + } + } +} diff --git a/src/Editor/Text/Util/TextUIUtil/DifferenceBrushManager.cs b/src/Editor/Text/Util/TextUIUtil/DifferenceBrushManager.cs deleted file mode 100644 index 8773c20..0000000 --- a/src/Editor/Text/Util/TextUIUtil/DifferenceBrushManager.cs +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// -// This file contain implementations details that are subject to change without notice. -// Use at your own risk. -// -using System; -using System.Linq; -using System.Windows.Media; -using Microsoft.VisualStudio.Text.Classification; -using Microsoft.VisualStudio.Text.Editor; - -namespace Microsoft.VisualStudio.Text.Utilities -{ - class DifferenceBrushManager - { - public static DifferenceBrushManager GetBrushManager(ITextView3 view, IEditorFormatMapService formatMapService) - { - return view.Properties.GetOrCreateSingletonProperty(() => new DifferenceBrushManager(view, formatMapService.GetEditorFormatMap(view))); - } - - public static DifferenceBrushManager GetBrushManager(ITextView3 view, IEditorFormatMap formatMap) - { - return view.Properties.GetOrCreateSingletonProperty(() => new DifferenceBrushManager(view, formatMap)); - } - - // internal for unit testing - internal static readonly SolidColorBrush _defaultRemovedLineBrush = Brushes.PaleVioletRed; - internal static readonly SolidColorBrush _defaultAddedLineBrush = Brushes.LightYellow; - internal static readonly SolidColorBrush _defaultRemovedWordBrush = Brushes.Red; - internal static readonly SolidColorBrush _defaultAddedWordBrush = Brushes.Yellow; - - IEditorFormatMap _formatMap; - - #region Public properties (brushes) and changed event - - public Brush RemovedLineBrush { get; private set; } - public Brush AddedLineBrush { get; private set; } - - public Brush RemovedWordBrush { get; private set; } - public Brush RemovedWordForegroundBrush { get; private set; } - public Pen RemovedWordForegroundPen { get; private set; } - public Brush AddedWordBrush { get; private set; } - public Brush AddedWordForegroundBrush { get; private set; } - public Pen AddedWordForegroundPen { get; private set; } - - public Brush ViewportBrush { get; private set; } - public Pen ViewportPen { get; private set; } - public Brush OverviewBrush { get; private set; } - - public event EventHandler BrushesChanged; - - #endregion - - internal DifferenceBrushManager(ITextView3 view, IEditorFormatMap formatMap) - { - _formatMap = formatMap; - - InitializeBrushes(); - - _formatMap.FormatMappingChanged += FormatMapChanged; - view.Closed += (s,a) => { _formatMap.FormatMappingChanged -= FormatMapChanged; }; - } - - void InitializeBrushes() - { - RemovedLineBrush = GetBrushValue("deltadiff.remove.line", _defaultRemovedLineBrush); - RemovedWordBrush = GetBrushValue("deltadiff.remove.word", _defaultRemovedWordBrush); - RemovedWordForegroundBrush = GetBrushValue("deltadiff.remove.word", _defaultRemovedWordBrush, EditorFormatDefinition.ForegroundBrushId); - RemovedWordForegroundPen = new Pen(RemovedWordForegroundBrush, 2.0); - RemovedWordForegroundPen.Freeze(); - - AddedLineBrush = GetBrushValue("deltadiff.add.line", _defaultAddedLineBrush); - AddedWordBrush = GetBrushValue("deltadiff.add.word", _defaultAddedWordBrush); - AddedWordForegroundBrush = GetBrushValue("deltadiff.add.word", _defaultAddedWordBrush, EditorFormatDefinition.ForegroundBrushId); - AddedWordForegroundPen = new Pen(AddedWordForegroundBrush, 2.0); - AddedWordForegroundPen.Freeze(); - - ViewportBrush = GetBrushValue("deltadiff.overview.color", Brushes.DarkGray, EditorFormatDefinition.ForegroundBrushId); - ViewportPen = new Pen(ViewportBrush, 2.0); - ViewportPen.Freeze(); - - OverviewBrush = GetBrushValue("deltadiff.overview.color", Brushes.Gray); - - var temp = BrushesChanged; - if (temp != null) - temp(this, EventArgs.Empty); - } - - Brush GetBrushValue(string formatName, Brush defaultValue, string resource = EditorFormatDefinition.BackgroundBrushId) - { - var formatProperties = _formatMap.GetProperties(formatName); - if (formatProperties != null && formatProperties.Contains(resource)) - { - var brushValue = formatProperties[resource] as Brush; - if (brushValue != null) - return brushValue; - } - - return defaultValue; - } - - void FormatMapChanged(object sender, FormatItemsEventArgs e) - { - bool updateRequired = e.ChangedItems.Any(item => - string.Equals(item, "deltadiff.add.word", System.StringComparison.OrdinalIgnoreCase) || - string.Equals(item, "deltadiff.add.line", System.StringComparison.OrdinalIgnoreCase) || - string.Equals(item, "deltadiff.remove.word", System.StringComparison.OrdinalIgnoreCase) || - string.Equals(item, "deltadiff.remove.line", System.StringComparison.OrdinalIgnoreCase) || - string.Equals(item, "deltadiff.overview.color", System.StringComparison.OrdinalIgnoreCase)); - - if (updateRequired) - { - InitializeBrushes(); - } - } - } -} diff --git a/src/Editor/Text/Util/TextUIUtil/ExtensionMethods.cs b/src/Editor/Text/Util/TextUIUtil/ExtensionMethods.cs index 9c1ba00..c22c853 100644 --- a/src/Editor/Text/Util/TextUIUtil/ExtensionMethods.cs +++ b/src/Editor/Text/Util/TextUIUtil/ExtensionMethods.cs @@ -7,47 +7,6 @@ namespace Microsoft.VisualStudio.Text.MultiSelection { public static class ExtensionMethods { - public static VirtualSnapshotPoint NormalizePoint(this ITextView view, VirtualSnapshotPoint point) - { - var line = view.GetTextViewLineContainingBufferPosition(point.Position); - - //If point is at the end of the line, return it (including any virtual space offset) - if (point.Position >= line.End) - { - return new VirtualSnapshotPoint(line.End, point.VirtualSpaces); - } - else - { - //Otherwise align it with the begining of the containing text element & - //return that (losing any virtual space). - SnapshotSpan element = line.GetTextElementSpan(point.Position); - return new VirtualSnapshotPoint(element.Start); - } - } - - public static Selection MapToSnapshot(this Selection region, ITextSnapshot snapshot, ITextView view) - { - var newInsertion = view.NormalizePoint(region.InsertionPoint.TranslateTo(snapshot)); - var newActive = view.NormalizePoint(region.ActivePoint.TranslateTo(snapshot)); - var newAnchor = view.NormalizePoint(region.AnchorPoint.TranslateTo(snapshot)); - PositionAffinity positionAffinity; - - if (region.Extent.Length == 0) - { - // Selection is just a caret, respect the caret's prefered affinity. - positionAffinity = region.InsertionPointAffinity; - } - else - { - // Selection is non-zero length, adjust affinity so that it is always toward the body of the selection. - // This attempts to ensure that the caret is always on the same line as the body of the selection in - // word wrap scenarios. - positionAffinity = newAnchor < newActive ? PositionAffinity.Predecessor : PositionAffinity.Successor; - } - - return new Selection(newInsertion, newAnchor, newActive, positionAffinity); - } - /// /// Remaps a given x-coordinate to a valid point. If the provided x-coordinate is past the right end of the line, it will /// be clipped to the correct position depending on the virtual space settings. If the ISmartIndent is providing indentation @@ -80,8 +39,7 @@ namespace Microsoft.VisualStudio.Text.MultiSelection { //The indentation specified by the smart indent service is desired column position of the caret. Find out how much virtual space //need to be at the end of the line to satisfy that. - // TODO: need a way to determine column width in xplat scenarios, bug https://devdiv.visualstudio.com/DevDiv/_workitems/edit/637741 - double columnWidth = (textView is ITextView3 textView3) ? textView3.FormattedLineSource.ColumnWidth : throw new NotSupportedException(); + double columnWidth = (textView.ViewScroller is IViewScroller2 viewScroller) ? viewScroller.ColumnWidth : 7; indentationWidth = Math.Max(0.0, (((double)indentation.Value) * columnWidth - textLine.TextWidth)); // if the coordinate is specified by the user and the user has selected a coordinate to the left @@ -98,6 +56,47 @@ namespace Microsoft.VisualStudio.Text.MultiSelection return xCoordinate; } + public static VirtualSnapshotPoint NormalizePoint(this ITextView view, VirtualSnapshotPoint point) + { + var line = view.GetTextViewLineContainingBufferPosition(point.Position); + + //If point is at the end of the line, return it (including any virtual space offset) + if (point.Position >= line.End) + { + return new VirtualSnapshotPoint(line.End, point.VirtualSpaces); + } + else + { + //Otherwise align it with the begining of the containing text element & + //return that (losing any virtual space). + SnapshotSpan element = line.GetTextElementSpan(point.Position); + return new VirtualSnapshotPoint(element.Start); + } + } + + public static Selection MapToSnapshot(this Selection region, ITextSnapshot snapshot, ITextView view) + { + var newInsertion = view.NormalizePoint(region.InsertionPoint.TranslateTo(snapshot)); + var newActive = view.NormalizePoint(region.ActivePoint.TranslateTo(snapshot)); + var newAnchor = view.NormalizePoint(region.AnchorPoint.TranslateTo(snapshot)); + PositionAffinity positionAffinity; + + if (region.Extent.Length == 0) + { + // Selection is just a caret, respect the caret's prefered affinity. + positionAffinity = region.InsertionPointAffinity; + } + else + { + // Selection is non-zero length, adjust affinity so that it is always toward the body of the selection. + // This attempts to ensure that the caret is always on the same line as the body of the selection in + // word wrap scenarios. + positionAffinity = newAnchor < newActive ? PositionAffinity.Predecessor : PositionAffinity.Successor; + } + + return new Selection(newInsertion, newAnchor, newActive, positionAffinity); + } + /// /// If you are looking at this, you're likely maintaining selection code, and should be aware that /// virtual whitespace allowances are not simply checking a flag. diff --git a/src/Editor/Text/Util/TextUIUtil/IDragDropMouseProcessor.cs b/src/Editor/Text/Util/TextUIUtil/IDragDropMouseProcessor.cs deleted file mode 100644 index 185f0a8..0000000 --- a/src/Editor/Text/Util/TextUIUtil/IDragDropMouseProcessor.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// -namespace Microsoft.VisualStudio.Text.Utilities -{ - using System.Windows; - using System.Windows.Input; - - /// - /// This interface is a used as an abstraction of the DragDropMouseProcessor so that it can be called from the left margin - /// to handle drag/drop. - /// - public interface IDragDropMouseProcessor - { - void DoPreprocessMouseLeftButtonDown(MouseButtonEventArgs e, Point position); - void DoPreprocessMouseLeftButtonUp(MouseButtonEventArgs e, Point position); - void DoPostprocessMouseLeftButtonUp(MouseButtonEventArgs e, Point position); - void DoPreprocessMouseMove(MouseEventArgs e, Point position); - void DoPreprocessDrop(DragEventArgs e, Point position); - void DoPreprocessDragEnter(DragEventArgs e, Point position); - void DoPreprocessDragLeave(DragEventArgs e); - void DoPreprocessDragOver(DragEventArgs e, Point position); - void DoPreprocessQueryContinueDrag(QueryContinueDragEventArgs e); - void DoPostprocessMouseLeave(MouseEventArgs e); - } -} \ No newline at end of file diff --git a/src/Editor/Text/Util/TextUIUtil/TelemetryLogger.cs b/src/Editor/Text/Util/TextUIUtil/TelemetryLogger.cs deleted file mode 100644 index 912930c..0000000 --- a/src/Editor/Text/Util/TextUIUtil/TelemetryLogger.cs +++ /dev/null @@ -1,142 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. -// -using System; -using System.ComponentModel.Composition; -using System.Windows.Threading; - -namespace Microsoft.VisualStudio.Text.Utilities -{ - [Export] - [PartCreationPolicy(CreationPolicy.Shared)] - internal sealed class TelemetryLogger - { - // This import may fail if we are running outside of VS, in scenarios such as CodeFlow. That is ok - // and this logging code should gracefully no-op in that case. - [Import(AllowDefault = true)] - private ILoggingServiceInternal LoggingService { get; set; } - - public const string VSEditorKey = "VS/Editor"; - - const string ExceptionEventName = VSEditorKey + "/Exception"; - - DispatcherTimer _touchZoomTimer = null; - DispatcherTimer _touchScrollTimer = null; - DispatcherTimer _zoomTimer = null; - DispatcherTimer _scrollTimer = null; - - uint _lastZoomLevel = 0; - readonly TimeSpan _timeout = TimeSpan.FromMilliseconds(1000.0); - - public void LogTouchZoom() - { - if (LoggingService != null) - { - if (_touchZoomTimer == null) - { - _touchZoomTimer = new DispatcherTimer(); - _touchZoomTimer.Interval = _timeout; - _touchZoomTimer.Tick += (s, e) => - { - _touchZoomTimer.Stop(); - LoggingService.AdjustCounter(TelemetryLogger.VSEditorKey, "TouchZoom", delta: 1); - }; - } - - // Restart timer - _touchZoomTimer.Stop(); - _touchZoomTimer.Start(); - } - } - - public void LogZoom(uint finalZoomLevel) - { - if (LoggingService != null) - { - if (_zoomTimer == null) - { - _zoomTimer = new DispatcherTimer(); - _zoomTimer.Interval = _timeout; - _zoomTimer.Tick += (s, e) => - { - _zoomTimer.Stop(); - LoggingService.PostEvent("VS/Editor/Zoom", "VS.Editor.Zoom.LastZoomLevel", _lastZoomLevel); - }; - } - - // Restart timer - _zoomTimer.Stop(); - - // Set _lastZoomLevel between stop and start out of paranoia regarding race conditions that shouldn't - // actually occur while using DispatcherTimer, since it runs all on the same thread. However, if the - // underlying timer get's changed, and this set were above the stop, there's a chance that we could - // occasionally log incorrect data if the set happened, and then tick occurred before the stop. - _lastZoomLevel = finalZoomLevel; - - _zoomTimer.Start(); - } - } - - public void LogTouchScroll() - { - if (LoggingService != null) - { - if (_touchScrollTimer == null) - { - _touchScrollTimer = new DispatcherTimer(); - _touchScrollTimer.Interval = _timeout; - _touchScrollTimer.Tick += (s, e) => - { - _touchScrollTimer.Stop(); - LoggingService.AdjustCounter(TelemetryLogger.VSEditorKey, "TouchScroll", delta: 1); - }; - } - - // Restart timer - _touchScrollTimer.Stop(); - _touchScrollTimer.Start(); - } - } - - public void LogScroll() - { - if (LoggingService != null) - { - if (_scrollTimer == null) - { - _scrollTimer = new DispatcherTimer(); - _scrollTimer.Interval = _timeout; - _scrollTimer.Tick += (s, e) => - { - _scrollTimer.Stop(); - LoggingService.AdjustCounter(TelemetryLogger.VSEditorKey, "Scroll", delta: 1); - }; - } - - // Restart timer - _scrollTimer.Stop(); - _scrollTimer.Start(); - } - } - - public void LogException( - Exception exception, - string description = "An unhandled exception occurred in the editor") - { - try - { - LoggingService?.PostFault( - ExceptionEventName, - description, - exception); - } - catch { } - } - - public void PostCounters() - { - LoggingService?.PostCounters(); - } - } -} \ No newline at end of file diff --git a/src/Editor/Text/Util/TextUIUtil/TextViewZoomManager.cs b/src/Editor/Text/Util/TextUIUtil/TextViewZoomManager.cs new file mode 100644 index 0000000..fa7abb5 --- /dev/null +++ b/src/Editor/Text/Util/TextUIUtil/TextViewZoomManager.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.VisualStudio.Text.Utilities +{ + [Export(typeof(ITextViewZoomManager))] + internal class TextViewZoomManager : BaseProxyService, ITextViewZoomManager + { + [ImportImplementations(typeof(ITextViewZoomManager))] + protected override IEnumerable> UnorderedImplementations { get; set; } + + public void ZoomIn(ITextView textView) + { + BestImplementation.ZoomIn(textView); + } + + public void ZoomOut(ITextView textView) + { + BestImplementation.ZoomOut(textView); + } + + public void ZoomTo(ITextView textView, double zoomLevel) + { + BestImplementation.ZoomTo(textView, zoomLevel); + } + + public double ZoomLevel(ITextView textView) + { + return BestImplementation.ZoomLevel(textView); + } + } +} diff --git a/src/OpenSource.Impl.projitems b/src/OpenSource.Impl.projitems index edc92a9..aa6304f 100644 --- a/src/OpenSource.Impl.projitems +++ b/src/OpenSource.Impl.projitems @@ -45,10 +45,6 @@ $(ReferencesVSEditorCopyToOutput) true - - $(ReferencesVSEditorCopyToOutput) - true - $(ReferencesVSEditorCopyToOutput) true @@ -122,4 +118,16 @@ true + + + + + $(ReferencesVSEditorCopyToOutput) + true + + + $(ReferencesVSEditorCopyToOutput) + true + + \ No newline at end of file -- cgit v1.2.3