PageRenderTime 37ms CodeModel.GetById 17ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 19using System;
 20using System.Windows.Input;
 21using ICSharpCode.AvalonEdit.Document;
 22using ICSharpCode.AvalonEdit.Rendering;
 23
 24namespace ICSharpCode.ILSpy.TextView
 25{
 26	/// <summary>
 27	/// Creates hyperlinks in the text view.
 28	/// </summary>
 29	sealed class ReferenceElementGenerator : VisualLineElementGenerator
 30	{
 31		readonly Action<ReferenceSegment> referenceClicked;
 32		readonly Predicate<ReferenceSegment> isLink;
 33		
 34		/// <summary>
 35		/// The collection of references (hyperlinks).
 36		/// </summary>
 37		public TextSegmentCollection<ReferenceSegment> References { get; set; }
 38		
 39		public ReferenceElementGenerator(Action<ReferenceSegment> referenceClicked, Predicate<ReferenceSegment> isLink)
 40		{
 41			if (referenceClicked == null)
 42				throw new ArgumentNullException(nameof(referenceClicked));
 43			if (isLink == null)
 44				throw new ArgumentNullException(nameof(isLink));
 45			this.referenceClicked = referenceClicked;
 46			this.isLink = isLink;
 47		}
 48		
 49		public override int GetFirstInterestedOffset(int startOffset)
 50		{
 51			if (this.References == null)
 52				return -1;
 53			// inform AvalonEdit about the next position where we want to build a hyperlink
 54			var segment = this.References.FindFirstSegmentWithStartAfter(startOffset);
 55			return segment != null ? segment.StartOffset : -1;
 56		}
 57		
 58		public override VisualLineElement ConstructElement(int offset)
 59		{
 60			if (this.References == null)
 61				return null;
 62			foreach (var segment in this.References.FindSegmentsContaining(offset)) {
 63				// skip all non-links
 64				if (!isLink(segment))
 65					continue;
 66				// ensure that hyperlinks don't span several lines (VisualLineElements can't contain line breaks)
 67				int endOffset = Math.Min(segment.EndOffset, CurrentContext.VisualLine.LastDocumentLine.EndOffset);
 68				// don't create hyperlinks with length 0
 69				if (offset < endOffset) {
 70					return new VisualLineReferenceText(CurrentContext.VisualLine, endOffset - offset, this, segment);
 71				}
 72			}
 73			return null;
 74		}
 75		
 76		internal void JumpToReference(ReferenceSegment referenceSegment)
 77		{
 78			referenceClicked(referenceSegment);
 79		}
 80	}
 81	
 82	/// <summary>
 83	/// VisualLineElement that represents a piece of text and is a clickable link.
 84	/// </summary>
 85	sealed class VisualLineReferenceText : VisualLineText
 86	{
 87		readonly ReferenceElementGenerator parent;
 88		readonly ReferenceSegment referenceSegment;
 89		
 90		/// <summary>
 91		/// Creates a visual line text element with the specified length.
 92		/// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
 93		/// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
 94		/// </summary>
 95		public VisualLineReferenceText(VisualLine parentVisualLine, int length, ReferenceElementGenerator parent, ReferenceSegment referenceSegment) : base(parentVisualLine, length)
 96		{
 97			this.parent = parent;
 98			this.referenceSegment = referenceSegment;
 99		}
100		
101		/// <inheritdoc/>
102		protected override void OnQueryCursor(QueryCursorEventArgs e)
103		{
104			e.Handled = true;
105			e.Cursor = referenceSegment.IsLocal ? Cursors.Arrow : Cursors.Hand;
106		}
107		
108		/// <inheritdoc/>
109		protected override VisualLineText CreateInstance(int length)
110		{
111			return new VisualLineReferenceText(ParentVisualLine, length, parent, referenceSegment);
112		}
113	}
114}