PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NUnit/UiException/Controls/DefaultCodeRenderer.cs

#
C# | 199 lines | 130 code | 42 blank | 27 comment | 9 complexity | 19d468164fcd44b1912ac2670dcae233 MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // This is free software licensed under the NUnit license. You may
  3. // obtain a copy of the license at http://nunit.org
  4. // ****************************************************************
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. using NUnit.UiException.CodeFormatters;
  9. using System.Drawing;
  10. using System.Diagnostics;
  11. namespace NUnit.UiException.Controls
  12. {
  13. public class DefaultCodeRenderer :
  14. ICodeRenderer
  15. {
  16. /// <summary>
  17. /// These constants below address an issue at measure text time
  18. /// that sometimes can cause big lines of text to be misaligned.
  19. /// </summary>
  20. private readonly static float MEASURECHAR_BIG_WIDTH = 5000f;
  21. private readonly static float MEASURECHAR_BIG_HEIGHT = 100f;
  22. public PaintLineLocation[] ViewportLines(FormattedCode code, RectangleF viewport, float fontHeight)
  23. {
  24. List<PaintLineLocation> list = new List<PaintLineLocation>();
  25. int visibles = CountVisibleLines(viewport.Height, fontHeight);
  26. // int topIndex = YCoordinateToLineIndex(viewport.Top, fontHeight);
  27. int lineIndex = YCoordinateToLineIndex(viewport.Top, fontHeight);
  28. int i;
  29. for (i = 0; i < visibles; ++i, lineIndex++)
  30. {
  31. if (lineIndex < 0)
  32. continue;
  33. if (lineIndex >= code.LineCount)
  34. break;
  35. list.Add(
  36. new PaintLineLocation(lineIndex, code.GetTextAt(lineIndex),
  37. new PointF(-viewport.Left,
  38. LineIndexToYCoordinate(lineIndex, fontHeight) -
  39. viewport.Top)));
  40. }
  41. return (list.ToArray());
  42. }
  43. #region ICodeRenderer Membres
  44. public void DrawToGraphics(FormattedCode code, CodeRenderingContext args, Rectangle viewport)
  45. {
  46. UiExceptionHelper.CheckNotNull(code, "code");
  47. UiExceptionHelper.CheckNotNull(args, "args");
  48. ClassifiedTokenCollection line;
  49. PaintLineLocation[] lines;
  50. ClassifiedToken token;
  51. float fontHeight;
  52. string text;
  53. float tk_width;
  54. int i;
  55. float x;
  56. fontHeight = LineIndexToYCoordinate(1, args.Graphics, args.Font);
  57. lines = ViewportLines(code, viewport, fontHeight);
  58. foreach (PaintLineLocation paintLine in lines)
  59. {
  60. // All lines that differ from CurrentLine are displayed
  61. // in using different styles of Brush to make a distinction
  62. // between code, keyword, comments.
  63. if (paintLine.LineIndex != args.CurrentLine)
  64. {
  65. line = code[paintLine.LineIndex];
  66. x = 0;
  67. text = line.Text;
  68. for (i = 0; i < line.Count; ++i)
  69. {
  70. token = line[i];
  71. args.Graphics.DrawString(token.Text, args.Font, args.GetBrush(token.Tag),
  72. paintLine.Location.X + x, paintLine.Location.Y);
  73. tk_width = measureStringWidth(args.Graphics, args.Font, text,
  74. token.IndexStart, token.Text.Length);
  75. x += tk_width;
  76. }
  77. continue;
  78. }
  79. // The current line is emphasized by using a
  80. // specific couples of Background & Foreground colors
  81. args.Graphics.FillRectangle(
  82. args.CurrentLineBackBrush,
  83. 0, paintLine.Location.Y,
  84. viewport.Width, fontHeight);
  85. args.Graphics.DrawString(
  86. paintLine.Text, args.Font,
  87. args.CurrentLineForeBrush,
  88. paintLine.Location.X, paintLine.Location.Y);
  89. }
  90. return;
  91. }
  92. public SizeF GetDocumentSize(FormattedCode code, Graphics g, Font font)
  93. {
  94. UiExceptionHelper.CheckNotNull(code, "code");
  95. UiExceptionHelper.CheckNotNull(g, "g");
  96. UiExceptionHelper.CheckNotNull(font, "font");
  97. StringBuilder sample;
  98. SizeF measure;
  99. int i;
  100. sample = new StringBuilder();
  101. for (i = code.MaxLength; i > 0; --i)
  102. sample.Append("m");
  103. measure = g.MeasureString(sample.ToString(), font);
  104. return (new SizeF(measure.Width, measure.Height * code.LineCount));
  105. }
  106. public float LineIndexToYCoordinate(int lineIndex, Graphics g, Font font)
  107. {
  108. UiExceptionHelper.CheckNotNull(g, "g");
  109. UiExceptionHelper.CheckNotNull(font, "font");
  110. SizeF sz = g.MeasureString("m", font);
  111. return (lineIndex * sz.Height);
  112. }
  113. #endregion
  114. /// <summary>
  115. /// Utility method that measures a region of text in the given string.
  116. /// </summary>
  117. /// <param name="g">The graphics instance used to render this text.</param>
  118. /// <param name="font">The font instance used to render this text.</param>
  119. /// <param name="text">The text that contains the region to be rendered.</param>
  120. /// <param name="indexStart">Starting startingPosition of this region.</param>
  121. /// <param name="length">Length of this region.</param>
  122. /// <returns>The width of this region of text.</returns>
  123. private float measureStringWidth(Graphics g, Font font, string text, int indexStart, int length)
  124. {
  125. CharacterRange[] ranges;
  126. StringFormat sf;
  127. Region[] regions;
  128. if (length == 0)
  129. return (0);
  130. length = Math.Min(length, text.Length);
  131. ranges = new CharacterRange[] { new CharacterRange(indexStart, length) };
  132. sf = new StringFormat();
  133. // the string of text may contains white spaces that need to
  134. // be measured correctly.
  135. sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
  136. sf.SetMeasurableCharacterRanges(ranges);
  137. // here : giving a layout too small can cause returned measure
  138. // to be wrong.
  139. regions = g.MeasureCharacterRanges(
  140. text, font, new RectangleF(
  141. 0, 0, MEASURECHAR_BIG_WIDTH, MEASURECHAR_BIG_HEIGHT), sf);
  142. return (regions[0].GetBounds(g).Width);
  143. }
  144. int CountVisibleLines(float viewportHeight, float fontHeight)
  145. {
  146. return ((int)(viewportHeight / fontHeight) + 1);
  147. }
  148. int YCoordinateToLineIndex(float y, float fontHeight)
  149. {
  150. return (int)(y / fontHeight);
  151. }
  152. float LineIndexToYCoordinate(int index, float fontHeight)
  153. {
  154. return (index * fontHeight);
  155. }
  156. }
  157. }