PageRenderTime 70ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/SharePoint Manager 2010 v2/Src/Libraries/AvalonEdit/Rendering/LinkElementGenerator.cs

#
C# | 143 lines | 81 code | 18 blank | 44 comment | 10 complexity | 212b8a83bf8a06141b4eb9f0e430f201 MD5 | raw file
  1. // <file>
  2. // <copyright see="prj:///doc/copyright.txt"/>
  3. // <license see="prj:///doc/license.txt"/>
  4. // <author name="Daniel Grunwald"/>
  5. // <version>$Revision: 5529 $</version>
  6. // </file>
  7. using System;
  8. using System.Diagnostics;
  9. using System.Text.RegularExpressions;
  10. using System.Windows;
  11. using System.Windows.Documents;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.TextFormatting;
  15. using ICSharpCode.AvalonEdit.Document;
  16. using System.Windows.Navigation;
  17. namespace ICSharpCode.AvalonEdit.Rendering
  18. {
  19. // This class is public because it can be used as a base class for custom links.
  20. /// <summary>
  21. /// Detects hyperlinks and makes them clickable.
  22. /// </summary>
  23. /// <remarks>
  24. /// This element generator can be easily enabled and configured using the
  25. /// <see cref="TextEditorOptions"/>.
  26. /// </remarks>
  27. public class LinkElementGenerator : VisualLineElementGenerator, IBuiltinElementGenerator
  28. {
  29. // a link starts with a protocol (or just with www), followed by 0 or more 'link characters', followed by a link end character
  30. // (this allows accepting punctuation inside links but not at the end)
  31. internal readonly static Regex defaultLinkRegex = new Regex(@"\b(https?://|ftp://|www\.)[\w\d\._/\-~%@()+:?&=#!]*[\w\d/]");
  32. // try to detect email addresses
  33. internal readonly static Regex defaultMailRegex = new Regex(@"\b[\w\d\.\-]+\@[\w\d\.\-]+\.[a-z]{2,6}\b");
  34. readonly Regex linkRegex;
  35. /// <summary>
  36. /// Gets/Sets whether the user needs to press Control to click the link.
  37. /// The default value is true.
  38. /// </summary>
  39. public bool RequireControlModifierForClick { get; set; }
  40. /// <summary>
  41. /// Creates a new LinkElementGenerator.
  42. /// </summary>
  43. public LinkElementGenerator()
  44. {
  45. this.linkRegex = defaultLinkRegex;
  46. this.RequireControlModifierForClick = true;
  47. }
  48. /// <summary>
  49. /// Creates a new LinkElementGenerator using the specified regex.
  50. /// </summary>
  51. protected LinkElementGenerator(Regex regex) : this()
  52. {
  53. if (regex == null)
  54. throw new ArgumentNullException("regex");
  55. this.linkRegex = regex;
  56. }
  57. void IBuiltinElementGenerator.FetchOptions(TextEditorOptions options)
  58. {
  59. this.RequireControlModifierForClick = options.RequireControlModifierForHyperlinkClick;
  60. }
  61. Match GetMatch(int startOffset)
  62. {
  63. int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset;
  64. string relevantText = CurrentContext.Document.GetText(startOffset, endOffset - startOffset);
  65. return linkRegex.Match(relevantText);
  66. }
  67. /// <inheritdoc/>
  68. public override int GetFirstInterestedOffset(int startOffset)
  69. {
  70. Match m = GetMatch(startOffset);
  71. return m.Success ? startOffset + m.Index : -1;
  72. }
  73. /// <inheritdoc/>
  74. public override VisualLineElement ConstructElement(int offset)
  75. {
  76. Match m = GetMatch(offset);
  77. if (m.Success && m.Index == 0) {
  78. Uri uri = GetUriFromMatch(m);
  79. if (uri == null)
  80. return null;
  81. VisualLineLinkText linkText = new VisualLineLinkText(CurrentContext.VisualLine, m.Length);
  82. linkText.NavigateUri = uri;
  83. linkText.RequireControlModifierForClick = this.RequireControlModifierForClick;
  84. return linkText;
  85. } else {
  86. return null;
  87. }
  88. }
  89. /// <summary>
  90. /// Fetches the URI from the regex match. Returns null if the URI format is invalid.
  91. /// </summary>
  92. protected virtual Uri GetUriFromMatch(Match match)
  93. {
  94. string targetUrl = match.Value;
  95. if (targetUrl.StartsWith("www.", StringComparison.Ordinal))
  96. targetUrl = "http://" + targetUrl;
  97. if (Uri.IsWellFormedUriString(targetUrl, UriKind.Absolute))
  98. return new Uri(targetUrl);
  99. return null;
  100. }
  101. }
  102. // This class is internal because it does not need to be accessed by the user - it can be configured using TextEditorOptions.
  103. /// <summary>
  104. /// Detects e-mail addresses and makes them clickable.
  105. /// </summary>
  106. /// <remarks>
  107. /// This element generator can be easily enabled and configured using the
  108. /// <see cref="TextEditorOptions"/>.
  109. /// </remarks>
  110. sealed class MailLinkElementGenerator : LinkElementGenerator
  111. {
  112. /// <summary>
  113. /// Creates a new MailLinkElementGenerator.
  114. /// </summary>
  115. public MailLinkElementGenerator()
  116. : base(defaultMailRegex)
  117. {
  118. }
  119. /// <inheritdoc/>
  120. protected override Uri GetUriFromMatch(Match match)
  121. {
  122. return new Uri("mailto:" + match.Value);
  123. }
  124. }
  125. }