연습: 스마트 태그 표시
스마트 태그 작업 집합을 표시 하는 확장 태그 텍스트입니다. 예를 들어, 변수 이름이 같은 식별자의 이름을 바꿀 때 단어에서 Visual Basic 또는 C# 프로젝트에서 빨간색 선이 나타납니다. 밑줄 위에 마우스 포인터를 이동 하면 포인터 근처에 단추가 표시 됩니다. 이 단추를 클릭 하는 경우와 제안 된 작업이 표시 됩니다 Isready에 이름 바꾸기 IsRead. 작업을 클릭할 경우 IsRead 프로젝트의 모든 참조 이름을 변경 됩니다 IsReady.
스마트 태그 편집기에서 IntelliSense 구현 부분 이지만, 하위 클래스에서 스마트 태그를 구현할 수 있습니다 SmartTag, 및 구현 하 고 있는 ITagger 인터페이스와 IViewTaggerProvider 인터페이스.
참고
태그의 다른 종류와 유사한 방식으로 구현할 수 있습니다.
다음 연습에서는 현재 단어에 표시 되는 스마트 태그를 만드는 방법을 보여 줍니다 및 두 개의 작업을 제안 했습니다: 를 대문자로 변환 및 소문자로 변환.
사전 요구 사항
이 연습을 완료 하려면 설치 해야 해당 Visual Studio 2010 SDK.
참고
Visual Studio SDK에 대 한 자세한 내용은 참조 하십시오. Visual Studio 개요를 확장합니다..Visual Studio SDK를 다운로드 하는 방법를 참조 하십시오. Visual Studio 확장성 개발자 센터 MSDN 웹 사이트에서.
관리 되는 확장성 프레임 워크 (MEF) 프로젝트 만들기
MEF 프로젝트를 만들려면
편집기 분류자 프로젝트를 만듭니다. 솔루션의 이름을 SmartTagTest.
VSIX 매니페스트 편집기에서 source.extension.vsixmanifest 파일을 엽니다.
Content MEF 구성 요소 콘텐츠 형식 및 해당 제목 포함은 Path Smarttagtest.dll으로 설정 됩니다.
저장 하 고 source.extension.vsixmanifest를 닫습니다.
다음 참조를 프로젝트에 추가 하 고 설정 CopyLocal 에 false:
Microsoft.VisualStudio.Language.Intellisense
기존 클래스 파일을 삭제 합니다.
스마트 태그를 구현 하는 Tagger
스마트 태그는 tagger 구현 하기
클래스 파일을 추가 하 고 이름을 TestSmartTag.
다음 imports 추가 합니다.
Imports System Imports System.Collections.Generic Imports System.ComponentModel.Composition Imports System.Collections.ObjectModel Imports System.Windows.Media Imports Microsoft.VisualStudio.Language.Intellisense Imports Microsoft.VisualStudio.Text Imports Microsoft.VisualStudio.Text.Editor Imports Microsoft.VisualStudio.Text.Operations Imports Microsoft.VisualStudio.Text.Tagging Imports Microsoft.VisualStudio.Utilities
using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.Collections.ObjectModel; using System.Windows.Media; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Operations; using Microsoft.VisualStudio.Text.Tagging; using Microsoft.VisualStudio.Utilities;
라는 클래스를 추가 합니다. TestSmartTag 는 상속에서 SmartTag.
Friend Class TestSmartTag Inherits SmartTag
internal class TestSmartTag : SmartTag
생성자는 기본 생성자를 호출 하는이 클래스에 추가 된 SmartTagType 의 Factoid, 단어의 첫 번째 문자를 아래에 파란색 선이 생성. (사용 하는 경우 Ephemeral, 마지막 문자 단어를 아래에 빨간색 선이 표시 됩니다.)
Public Sub New(ByVal actionSets As ReadOnlyCollection(Of SmartTagActionSet)) MyBase.New(SmartTagType.Factoid, actionSets) End Sub
public TestSmartTag(ReadOnlyCollection<SmartTagActionSet> actionSets) : base(SmartTagType.Factoid, actionSets) { }
라는 클래스를 추가 합니다. TestSmartTagger 에서 상속 되 ITagger 형식 TestSmartTag을 구현 하 고 IDisposable.
Friend Class TestSmartTagger Implements ITagger(Of TestSmartTag), IDisposable
internal class TestSmartTagger : ITagger<TestSmartTag>, IDisposable
Tagger 클래스에 전용 필드를 추가 합니다.
Private m_buffer As ITextBuffer Private m_view As ITextView Private m_provider As TestSmartTaggerProvider Private m_disposed As Boolean
private ITextBuffer m_buffer; private ITextView m_view; private TestSmartTaggerProvider m_provider; private bool m_disposed;
추가 전용 필드를 설정 하 고 구독 하는 생성자는 LayoutChanged 이벤트입니다.
Public Sub New(ByVal buffer As ITextBuffer, ByVal view As ITextView, ByVal provider As TestSmartTaggerProvider) m_buffer = buffer m_view = view m_provider = provider AddHandler m_view.LayoutChanged, AddressOf OnLayoutChanged End Sub
public TestSmartTagger(ITextBuffer buffer, ITextView view, TestSmartTaggerProvider provider) { m_buffer = buffer; m_view = view; m_provider = provider; m_view.LayoutChanged += OnLayoutChanged; }
구현 GetTags 태그에 대 한 현재 단어를 만들 수 있도록 합니다. (이 메서드는 전용 메서드가 호출 GetSmartTagActions 나중에 설명 되어 있습니다.)
Public Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection) As IEnumerable(Of ITagSpan(Of TestSmartTag)) Implements ITagger(Of TestSmartTag).GetTags Dim snapshot As ITextSnapshot = m_buffer.CurrentSnapshot If snapshot.Length = 0 Then Return Nothing Exit Function End If 'set up the navigator Dim navigator As ITextStructureNavigator = m_provider.NavigatorService.GetTextStructureNavigator(m_buffer) 'set up a list to contain the tags Dim list As List(Of TagSpan(Of TestSmartTag)) list = New List(Of TagSpan(Of TestSmartTag))() For Each span In spans Dim caret As ITextCaret = m_view.Caret Dim point As SnapshotPoint If CInt(caret.Position.BufferPosition) > 0 Then point = caret.Position.BufferPosition - 1 Else Exit For End If Dim extent As TextExtent = navigator.GetExtentOfWord(point) 'don't display the tag if the extent has whitespace If extent.IsSignificant Then list.Add(New TagSpan(Of TestSmartTag)(extent.Span, New TestSmartTag(GetSmartTagActions(extent.Span)))) Else Exit For End If Next span Return list End Function
public IEnumerable<ITagSpan<TestSmartTag>> GetTags(NormalizedSnapshotSpanCollection spans) { ITextSnapshot snapshot = m_buffer.CurrentSnapshot; if (snapshot.Length == 0) yield break; //don't do anything if the buffer is empty //set up the navigator ITextStructureNavigator navigator = m_provider.NavigatorService.GetTextStructureNavigator(m_buffer); foreach (var span in spans) { ITextCaret caret = m_view.Caret; SnapshotPoint point; if (caret.Position.BufferPosition > 0) point = caret.Position.BufferPosition - 1; else yield break; TextExtent extent = navigator.GetExtentOfWord(point); //don't display the tag if the extent has whitespace if (extent.IsSignificant) yield return new TagSpan<TestSmartTag>(extent.Span, new TestSmartTag(GetSmartTagActions(extent.Span))); else yield break; } }
추가 된 GetSmartTagActions 메서드는 스마트 태그 동작을 설정할 수 있습니다. 동작 자체는 이후 단계에서 구현 됩니다.
Private Function GetSmartTagActions(ByVal span As SnapshotSpan) As ReadOnlyCollection(Of SmartTagActionSet) Dim actionSetList As New List(Of SmartTagActionSet)() Dim actionList As New List(Of ISmartTagAction)() Dim trackingSpan As ITrackingSpan = span.Snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeInclusive) actionList.Add(New UpperCaseSmartTagAction(trackingSpan)) actionList.Add(New LowerCaseSmartTagAction(trackingSpan)) Dim actionSet As New SmartTagActionSet(actionList.AsReadOnly()) actionSetList.Add(actionSet) Return actionSetList.AsReadOnly() End Function
private ReadOnlyCollection<SmartTagActionSet> GetSmartTagActions(SnapshotSpan span) { List<SmartTagActionSet> actionSetList = new List<SmartTagActionSet>(); List<ISmartTagAction> actionList = new List<ISmartTagAction>(); ITrackingSpan trackingSpan = span.Snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeInclusive); actionList.Add(new UpperCaseSmartTagAction(trackingSpan)); actionList.Add(new LowerCaseSmartTagAction(trackingSpan)); SmartTagActionSet actionSet = new SmartTagActionSet(actionList.AsReadOnly()); actionSetList.Add(actionSet); return actionSetList.AsReadOnly(); }
선언에서 SmartTagsChanged 이벤트입니다.
Public Event TagsChanged As EventHandler(Of SnapshotSpanEventArgs) Implements ITagger(Of TestSmartTag).TagsChanged
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
구현에서 OnLayoutChanged 를 발생 시키는 이벤트 처리기는 TagsChanged 발생 하는 이벤트 GetTags 호출 하.
Private Sub OnLayoutChanged(ByVal sender As Object, ByVal e As TextViewLayoutChangedEventArgs) Dim snapshot As ITextSnapshot = e.NewSnapshot 'don't do anything if this is just a change in case If Not snapshot.GetText().ToLower().Equals(e.OldSnapshot.GetText().ToLower()) Then Dim span As New SnapshotSpan(snapshot, New Span(0, snapshot.Length)) Dim handler As EventHandler(Of SnapshotSpanEventArgs) = Me.TagsChangedEvent If handler IsNot Nothing Then handler(Me, New SnapshotSpanEventArgs(span)) End If End If End Sub
private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e) { ITextSnapshot snapshot = e.NewSnapshot; //don't do anything if this is just a change in case if (!snapshot.GetText().ToLower().Equals(e.OldSnapshot.GetText().ToLower())) { SnapshotSpan span = new SnapshotSpan(snapshot, new Span(0, snapshot.Length)); EventHandler<SnapshotSpanEventArgs> handler = this.TagsChanged; if (handler != null) { handler(this, new SnapshotSpanEventArgs(span)); } } }
구현에서 Dispose it에서 등록을 취소 하도록 메서드를 LayoutChanged 이벤트.
Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub Private Sub Dispose(ByVal disposing As Boolean) If disposing Then RemoveHandler m_view.LayoutChanged, AddressOf OnLayoutChanged m_view = Nothing End If m_disposed = True End Sub
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!this.m_disposed) { if (disposing) { m_view.LayoutChanged -= OnLayoutChanged; m_view = null; } m_disposed = true; } }
스마트 태그 Tagger 공급자 구현
스마트 태그 tagger 공급자를 구현 하려면
라는 클래스를 추가 합니다. TestSmartTagTaggerProvider 는 상속에서 IViewTaggerProvider. 와 내보내기는 ContentTypeAttribute "텍스트"는 OrderAttribute 의 전 "기본" = a TagTypeAttribute 의 SmartTag.
<Export(GetType(IViewTaggerProvider))> <ContentType("text")> <Order(Before:="default")> <TagType(GetType(SmartTag))> Friend Class TestSmartTaggerProvider Implements IViewTaggerProvider
[Export(typeof(IViewTaggerProvider))] [ContentType("text")] [Order(Before = "default")] [TagType(typeof(SmartTag))] internal class TestSmartTaggerProvider : IViewTaggerProvider
가져오기는 ITextStructureNavigatorSelectorService 속성으로.
<Import(GetType(ITextStructureNavigatorSelectorService))> Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
[Import(typeof(ITextStructureNavigatorSelectorService))] internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
CreateTagger``1 메서드를 구현합니다.
Public Function CreateTagger(Of T As ITag)(ByVal textView As ITextView, ByVal buffer As ITextBuffer) As ITagger(Of T) Implements IViewTaggerProvider.CreateTagger If buffer Is Nothing OrElse textView Is Nothing Then Return Nothing End If 'make sure we are tagging only the top buffer If buffer Is textView.TextBuffer Then Return New TestSmartTagger(buffer, textView, Me) Else Return Nothing End If End Function
public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag { if (buffer == null || textView == null) { return null; } //make sure we are tagging only the top buffer if (buffer == textView.TextBuffer) { return new TestSmartTagger(buffer, textView, this) as ITagger<T>; } else return null; }
스마트 태그 동작을 구현합니다.
스마트 태그 동작을 구현 하려면
두 클래스를 만드는 첫 번째 라는 UpperCaseSmartTagAction 두 번째 명명 된 LowerCaseSmartTagAction. 두 클래스 구현 ISmartTagAction.
Friend Class UpperCaseSmartTagAction Implements ISmartTagAction
internal class UpperCaseSmartTagAction : ISmartTagAction
Friend Class LowerCaseSmartTagAction Implements ISmartTagAction
internal class LowerCaseSmartTagAction : ISmartTagAction
하나를 호출 하는 두 클래스 모두에 게 있습니다 ToUpper 및 기타 호출 ToLower. 다음 단계는 대문자 동작 클래스 포함 하지만 두 클래스를 구현 해야 합니다. 대문자 소문자 동작을 구현 하는 패턴으로 동작을 구현 하기 위한 단계를 사용 합니다.
전용 필드를 선언 합니다.
Private m_span As ITrackingSpan Private m_upper As String Private m_display As String Private m_snapshot As ITextSnapshot
private ITrackingSpan m_span; private string m_upper; private string m_display; private ITextSnapshot m_snapshot;
필드를 설정 하는 생성자를 추가 합니다.
Public Sub New(ByVal span As ITrackingSpan) m_span = span m_snapshot = span.TextBuffer.CurrentSnapshot m_upper = span.GetText(m_snapshot).ToUpper() m_display = "Convert to upper case" End Sub
public UpperCaseSmartTagAction(ITrackingSpan span) { m_span = span; m_snapshot = span.TextBuffer.CurrentSnapshot; m_upper = span.GetText(m_snapshot).ToUpper(); m_display = "Convert to upper case"; }
속성을 다음과 같이 구현 합니다.
Public ReadOnly Property DisplayText() As String Implements ISmartTagAction.DisplayText Get Return m_display End Get End Property Public ReadOnly Property Icon() As ImageSource Implements ISmartTagAction.Icon Get Return Nothing End Get End Property Public ReadOnly Property IsEnabled() As Boolean Implements ISmartTagAction.IsEnabled Get Return True End Get End Property Private privateSource As ISmartTagSource Public Property Source() As ISmartTagSource Get Return privateSource End Get Private Set(ByVal value As ISmartTagSource) privateSource = value End Set End Property Public ReadOnly Property ActionSets() As ReadOnlyCollection(Of SmartTagActionSet) Implements ISmartTagAction.ActionSets Get Return Nothing End Get End Property
public string DisplayText { get { return m_display; } } public ImageSource Icon { get { return null; } } public bool IsEnabled { get { return true; } } public ISmartTagSource Source { get; private set; } public ReadOnlyCollection<SmartTagActionSet> ActionSets { get { return null; } }
구현에서 Invoke 가 해당 범위에 있는 텍스트와 해당 대문자로 바꾸는 방법입니다.
Public Sub Invoke() Implements ISmartTagAction.Invoke m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper) End Sub
public void Invoke() { m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper); }
빌드 및 코드 테스트
이 코드를 테스트 하려면 SmartTagTest 솔루션을 빌드하고 실험 인스턴스를 실행 합니다.
빌드 및 SmartTagTest 솔루션을 테스트 하려면
솔루션을 빌드합니다.
이 프로젝트를 디버거에서 실행할 때 Visual Studio 두 번째 인스턴스를 인스턴스화합니다.
텍스트 파일을 만들고 일부 텍스트를 입력 합니다.
텍스트의 첫 번째 단어의 첫 글자 아래 파란색 줄을 표시 합니다.
파란색 줄 위로 포인터를 이동 합니다.
근처에 포인터 단추를 표시 합니다.
이 단추를 클릭 하면 두 작업 표시 제안: 를 대문자로 변환 및 소문자로 변환. 첫 번째 작업을 클릭 하면 현재 단어의 모든 텍스트를 대문자로 변환 합니다. 두 번째 작업을 클릭 하면 텍스트를 모두 소문자로 변환 합니다.