/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/DocumentColorizingTransformer.cs

http://github.com/icsharpcode/ILSpy · C# · 98 lines · 54 code · 8 blank · 36 comment · 11 complexity · 24704c30ab4ab29df0378c45ad8a8443 MD5 · raw file

  1. // Copyright (c) 2014 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.Linq;
  20. using ICSharpCode.AvalonEdit.Document;
  21. namespace ICSharpCode.AvalonEdit.Rendering
  22. {
  23. /// <summary>
  24. /// Base class for <see cref="IVisualLineTransformer"/> that helps
  25. /// colorizing the document. Derived classes can work with document lines
  26. /// and text offsets and this class takes care of the visual lines and visual columns.
  27. /// </summary>
  28. public abstract class DocumentColorizingTransformer : ColorizingTransformer
  29. {
  30. DocumentLine currentDocumentLine;
  31. int firstLineStart;
  32. int currentDocumentLineStartOffset, currentDocumentLineEndOffset;
  33. /// <summary>
  34. /// Gets the current ITextRunConstructionContext.
  35. /// </summary>
  36. protected ITextRunConstructionContext CurrentContext { get; private set; }
  37. /// <inheritdoc/>
  38. protected override void Colorize(ITextRunConstructionContext context)
  39. {
  40. if (context == null)
  41. throw new ArgumentNullException("context");
  42. this.CurrentContext = context;
  43. currentDocumentLine = context.VisualLine.FirstDocumentLine;
  44. firstLineStart = currentDocumentLineStartOffset = currentDocumentLine.Offset;
  45. currentDocumentLineEndOffset = currentDocumentLineStartOffset + currentDocumentLine.Length;
  46. int currentDocumentLineTotalEndOffset = currentDocumentLineStartOffset + currentDocumentLine.TotalLength;
  47. if (context.VisualLine.FirstDocumentLine == context.VisualLine.LastDocumentLine) {
  48. ColorizeLine(currentDocumentLine);
  49. } else {
  50. ColorizeLine(currentDocumentLine);
  51. // ColorizeLine modifies the visual line elements, loop through a copy of the line elements
  52. foreach (VisualLineElement e in context.VisualLine.Elements.ToArray()) {
  53. int elementOffset = firstLineStart + e.RelativeTextOffset;
  54. if (elementOffset >= currentDocumentLineTotalEndOffset) {
  55. currentDocumentLine = context.Document.GetLineByOffset(elementOffset);
  56. currentDocumentLineStartOffset = currentDocumentLine.Offset;
  57. currentDocumentLineEndOffset = currentDocumentLineStartOffset + currentDocumentLine.Length;
  58. currentDocumentLineTotalEndOffset = currentDocumentLineStartOffset + currentDocumentLine.TotalLength;
  59. ColorizeLine(currentDocumentLine);
  60. }
  61. }
  62. }
  63. currentDocumentLine = null;
  64. this.CurrentContext = null;
  65. }
  66. /// <summary>
  67. /// Override this method to colorize an individual document line.
  68. /// </summary>
  69. protected abstract void ColorizeLine(DocumentLine line);
  70. /// <summary>
  71. /// Changes a part of the current document line.
  72. /// </summary>
  73. /// <param name="startOffset">Start offset of the region to change</param>
  74. /// <param name="endOffset">End offset of the region to change</param>
  75. /// <param name="action">Action that changes an individual <see cref="VisualLineElement"/>.</param>
  76. protected void ChangeLinePart(int startOffset, int endOffset, Action<VisualLineElement> action)
  77. {
  78. if (startOffset < currentDocumentLineStartOffset || startOffset > currentDocumentLineEndOffset)
  79. throw new ArgumentOutOfRangeException("startOffset", startOffset, "Value must be between " + currentDocumentLineStartOffset + " and " + currentDocumentLineEndOffset);
  80. if (endOffset < startOffset || endOffset > currentDocumentLineEndOffset)
  81. throw new ArgumentOutOfRangeException("endOffset", endOffset, "Value must be between " + startOffset + " and " + currentDocumentLineEndOffset);
  82. VisualLine vl = this.CurrentContext.VisualLine;
  83. int visualStart = vl.GetVisualColumn(startOffset - firstLineStart);
  84. int visualEnd = vl.GetVisualColumn(endOffset - firstLineStart);
  85. if (visualStart < visualEnd) {
  86. ChangeVisualElements(visualStart, visualEnd, action);
  87. }
  88. }
  89. }
  90. }