PageRenderTime 100ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/IronPython_Main/Tools/IronStudio/IronStudioCore/IronStudioCore/Repl/ReplPrompt.cs

#
C# | 139 lines | 91 code | 16 blank | 32 comment | 5 complexity | 425ef92d0a5e6701dbe675061a48d2d8 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. * ***************************************************************************/
  14. using System;
  15. using System.Collections.Generic;
  16. using System.ComponentModel.Composition;
  17. using System.Windows;
  18. using System.Windows.Controls;
  19. using System.Windows.Media;
  20. using Microsoft.Scripting.Utils;
  21. using Microsoft.VisualStudio.Text;
  22. using Microsoft.VisualStudio.Text.Editor;
  23. using Microsoft.VisualStudio.Text.Formatting;
  24. using Microsoft.VisualStudio.Text.Tagging;
  25. using Microsoft.VisualStudio.Utilities;
  26. namespace Microsoft.IronStudio.Core.Repl {
  27. /// <summary>
  28. /// Any <see cref="ITextBuffer"/> with content type <see cref="CoreConstants.DlrContentTypeName"/>, role <see cref="CoreConstants.ReplTextViewRole"/>
  29. /// and property <see cref="IReplPromptProvider"/> gets prompt glyphs in its glyph margin.
  30. /// </summary>
  31. public interface IReplPromptProvider {
  32. /// <summary>
  33. /// The prompt text to display in the margin.
  34. /// </summary>
  35. string/*!*/ Prompt { get; }
  36. /// <summary>
  37. /// The control that hosts the text view.
  38. /// </summary>
  39. Control/*!*/ HostControl { get; }
  40. /// <summary>
  41. /// Should we draw a prompt glyph for given line.
  42. /// </summary>
  43. bool HasPromptForLine(ITextSnapshot/*!*/ snapshot, int lineNumber);
  44. /// <summary>
  45. /// Notifies glyph margin that prompt glyph(s) need to be updated.
  46. /// </summary>
  47. event Action<SnapshotSpan> PromptChanged;
  48. }
  49. /// <summary>
  50. /// Implements prompt glyphs in a GlyphMargin.
  51. /// </summary>
  52. internal static class ReplPrompt {
  53. internal const string GlyphName = "ReplPromptGlyph";
  54. internal sealed class ReplGlyphTag : IGlyphTag {
  55. internal static readonly ReplGlyphTag Instance = new ReplGlyphTag();
  56. }
  57. internal sealed class Tagger : ITagger<ReplGlyphTag> {
  58. private readonly IReplPromptProvider/*!*/ _promptProvider;
  59. public Tagger(IReplPromptProvider/*!*/ promptProvider) {
  60. Assert.NotNull(promptProvider);
  61. _promptProvider = promptProvider;
  62. _promptProvider.PromptChanged += new Action<SnapshotSpan>((span) => {
  63. var tagsChanged = TagsChanged;
  64. if (tagsChanged != null) {
  65. tagsChanged(this, new SnapshotSpanEventArgs(span));
  66. }
  67. });
  68. }
  69. public IEnumerable<ITagSpan<ReplGlyphTag>>/*!*/ GetTags(NormalizedSnapshotSpanCollection/*!*/ spans) {
  70. foreach (SnapshotSpan span in spans) {
  71. if (_promptProvider.HasPromptForLine(span.Snapshot, span.Start.GetContainingLine().LineNumber)) {
  72. yield return new TagSpan<ReplGlyphTag>(span, ReplGlyphTag.Instance);
  73. }
  74. }
  75. }
  76. public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
  77. }
  78. [Export(typeof(ITaggerProvider))]
  79. [TagType(typeof(ReplGlyphTag))]
  80. [ContentType(CoreConstants.DlrContentTypeName)]
  81. [TextViewRole(CoreConstants.ReplTextViewRole)]
  82. internal sealed class TaggerProvider : ITaggerProvider {
  83. public ITagger<T> CreateTagger<T>(ITextBuffer/*!*/ buffer) where T : ITag {
  84. IReplPromptProvider promptProvider;
  85. if (buffer.Properties.TryGetProperty(typeof(IReplPromptProvider), out promptProvider)) {
  86. return (ITagger<T>)(object)new Tagger(promptProvider);
  87. }
  88. return null;
  89. }
  90. }
  91. internal sealed class GlyphFactory : IGlyphFactory {
  92. private readonly IReplPromptProvider/*!*/ _promptProvider;
  93. private static readonly FontFamily _Consolas = new FontFamily("Consolas");
  94. public GlyphFactory(IReplPromptProvider/*!*/ promptProvider) {
  95. Assert.NotNull(promptProvider);
  96. _promptProvider = promptProvider;
  97. }
  98. public UIElement/*!*/ GenerateGlyph(IWpfTextViewLine/*!*/ line, IGlyphTag tag) {
  99. TextBlock block = new TextBlock();
  100. block.Text = _promptProvider.Prompt;
  101. block.Foreground = _promptProvider.HostControl.Foreground;
  102. block.FontSize = _promptProvider.HostControl.FontSize;
  103. block.FontFamily = _Consolas; // TODO: get the font family from the editor?
  104. return block;
  105. }
  106. }
  107. [Export(typeof(IGlyphFactoryProvider))]
  108. [Name(GlyphName)]
  109. [Order(After = "VsTextMarker")]
  110. [TagType(typeof(ReplGlyphTag))]
  111. [ContentType(CoreConstants.DlrContentTypeName)]
  112. [TextViewRole(CoreConstants.ReplTextViewRole)]
  113. internal sealed class GlyphFactoryProvider : IGlyphFactoryProvider {
  114. public IGlyphFactory GetGlyphFactory(IWpfTextView/*!*/ view, IWpfTextViewMargin/*!*/ margin) {
  115. IReplPromptProvider promptProvider;
  116. if (view.TextBuffer.Properties.TryGetProperty(typeof(IReplPromptProvider), out promptProvider)) {
  117. return new GlyphFactory(promptProvider);
  118. }
  119. return null;
  120. }
  121. }
  122. }
  123. }