/ILSpy/TextView/ReferenceElementGenerator.cs

http://github.com/icsharpcode/ILSpy · C# · 114 lines · 66 code · 11 blank · 37 comment · 11 complexity · 11564475b7c1dd8894c0c5502dc7258c MD5 · raw file

  1. // Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4. // software and associated documentation files (the "Software"), to deal in the Software
  5. // without restriction, including without limitation the rights to use, copy, modify, merge,
  6. // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7. // to whom the Software is furnished to do so, subject to the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be included in all copies or
  10. // substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  13. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14. // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  15. // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  16. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  17. // DEALINGS IN THE SOFTWARE.
  18. using System;
  19. using System.Windows.Input;
  20. using ICSharpCode.AvalonEdit.Document;
  21. using ICSharpCode.AvalonEdit.Rendering;
  22. namespace ICSharpCode.ILSpy.TextView
  23. {
  24. /// <summary>
  25. /// Creates hyperlinks in the text view.
  26. /// </summary>
  27. sealed class ReferenceElementGenerator : VisualLineElementGenerator
  28. {
  29. readonly Action<ReferenceSegment> referenceClicked;
  30. readonly Predicate<ReferenceSegment> isLink;
  31. /// <summary>
  32. /// The collection of references (hyperlinks).
  33. /// </summary>
  34. public TextSegmentCollection<ReferenceSegment> References { get; set; }
  35. public ReferenceElementGenerator(Action<ReferenceSegment> referenceClicked, Predicate<ReferenceSegment> isLink)
  36. {
  37. if (referenceClicked == null)
  38. throw new ArgumentNullException(nameof(referenceClicked));
  39. if (isLink == null)
  40. throw new ArgumentNullException(nameof(isLink));
  41. this.referenceClicked = referenceClicked;
  42. this.isLink = isLink;
  43. }
  44. public override int GetFirstInterestedOffset(int startOffset)
  45. {
  46. if (this.References == null)
  47. return -1;
  48. // inform AvalonEdit about the next position where we want to build a hyperlink
  49. var segment = this.References.FindFirstSegmentWithStartAfter(startOffset);
  50. return segment != null ? segment.StartOffset : -1;
  51. }
  52. public override VisualLineElement ConstructElement(int offset)
  53. {
  54. if (this.References == null)
  55. return null;
  56. foreach (var segment in this.References.FindSegmentsContaining(offset)) {
  57. // skip all non-links
  58. if (!isLink(segment))
  59. continue;
  60. // ensure that hyperlinks don't span several lines (VisualLineElements can't contain line breaks)
  61. int endOffset = Math.Min(segment.EndOffset, CurrentContext.VisualLine.LastDocumentLine.EndOffset);
  62. // don't create hyperlinks with length 0
  63. if (offset < endOffset) {
  64. return new VisualLineReferenceText(CurrentContext.VisualLine, endOffset - offset, this, segment);
  65. }
  66. }
  67. return null;
  68. }
  69. internal void JumpToReference(ReferenceSegment referenceSegment)
  70. {
  71. referenceClicked(referenceSegment);
  72. }
  73. }
  74. /// <summary>
  75. /// VisualLineElement that represents a piece of text and is a clickable link.
  76. /// </summary>
  77. sealed class VisualLineReferenceText : VisualLineText
  78. {
  79. readonly ReferenceElementGenerator parent;
  80. readonly ReferenceSegment referenceSegment;
  81. /// <summary>
  82. /// Creates a visual line text element with the specified length.
  83. /// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
  84. /// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
  85. /// </summary>
  86. public VisualLineReferenceText(VisualLine parentVisualLine, int length, ReferenceElementGenerator parent, ReferenceSegment referenceSegment) : base(parentVisualLine, length)
  87. {
  88. this.parent = parent;
  89. this.referenceSegment = referenceSegment;
  90. }
  91. /// <inheritdoc/>
  92. protected override void OnQueryCursor(QueryCursorEventArgs e)
  93. {
  94. e.Handled = true;
  95. e.Cursor = referenceSegment.IsLocal ? Cursors.Arrow : Cursors.Hand;
  96. }
  97. /// <inheritdoc/>
  98. protected override VisualLineText CreateInstance(int length)
  99. {
  100. return new VisualLineReferenceText(ParentVisualLine, length, parent, referenceSegment);
  101. }
  102. }
  103. }