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
// ****************************************************************
7
using System.Collections.Generic;
9
using NUnit.UiException.CodeFormatters;
11
using System.Diagnostics;
13
namespace NUnit.UiException.Controls
15
public class DefaultCodeRenderer :
19
/// These constants below address an issue at measure text time
20
/// that sometimes can cause big lines of text to be misaligned.
22
private readonly static float MEASURECHAR_BIG_WIDTH = 5000f;
23
private readonly static float MEASURECHAR_BIG_HEIGHT = 100f;
25
public PaintLineLocation[] ViewportLines(FormattedCode code, RectangleF viewport, float fontHeight)
27
List<PaintLineLocation> list = new List<PaintLineLocation>();
28
int visibles = CountVisibleLines(viewport.Height, fontHeight);
29
// int topIndex = YCoordinateToLineIndex(viewport.Top, fontHeight);
30
int lineIndex = YCoordinateToLineIndex(viewport.Top, fontHeight);
33
for (i = 0; i < visibles; ++i, lineIndex++)
38
if (lineIndex >= code.LineCount)
42
new PaintLineLocation(lineIndex, code.GetTextAt(lineIndex),
43
new PointF(-viewport.Left,
44
LineIndexToYCoordinate(lineIndex, fontHeight) -
48
return (list.ToArray());
51
#region ICodeRenderer Membres
53
public void DrawToGraphics(FormattedCode code, CodeRenderingContext args, Rectangle viewport)
55
UiExceptionHelper.CheckNotNull(code, "code");
56
UiExceptionHelper.CheckNotNull(args, "args");
58
ClassifiedTokenCollection line;
59
PaintLineLocation[] lines;
60
ClassifiedToken token;
67
fontHeight = LineIndexToYCoordinate(1, args.Graphics, args.Font);
68
lines = ViewportLines(code, viewport, fontHeight);
70
foreach (PaintLineLocation paintLine in lines)
72
// All lines that differ from CurrentLine are displayed
73
// in using different styles of Brush to make a distinction
74
// between code, keyword, comments.
75
if (paintLine.LineIndex != args.CurrentLine)
77
line = code[paintLine.LineIndex];
81
for (i = 0; i < line.Count; ++i)
85
args.Graphics.DrawString(token.Text, args.Font, args.GetBrush(token.Tag),
86
paintLine.Location.X + x, paintLine.Location.Y);
88
tk_width = measureStringWidth(args.Graphics, args.Font, text,
89
token.IndexStart, token.Text.Length);
97
// The current line is emphasized by using a
98
// specific couples of Background & Foreground colors
100
args.Graphics.FillRectangle(
101
args.CurrentLineBackBrush,
102
0, paintLine.Location.Y,
103
viewport.Width, fontHeight);
105
args.Graphics.DrawString(
106
paintLine.Text, args.Font,
107
args.CurrentLineForeBrush,
108
paintLine.Location.X, paintLine.Location.Y);
114
public SizeF GetDocumentSize(FormattedCode code, Graphics g, Font font)
116
UiExceptionHelper.CheckNotNull(code, "code");
117
UiExceptionHelper.CheckNotNull(g, "g");
118
UiExceptionHelper.CheckNotNull(font, "font");
120
StringBuilder sample;
124
sample = new StringBuilder();
125
for (i = code.MaxLength; i > 0; --i)
128
measure = g.MeasureString(sample.ToString(), font);
130
return (new SizeF(measure.Width, measure.Height * code.LineCount));
133
public float LineIndexToYCoordinate(int lineIndex, Graphics g, Font font)
135
UiExceptionHelper.CheckNotNull(g, "g");
136
UiExceptionHelper.CheckNotNull(font, "font");
138
SizeF sz = g.MeasureString("m", font);
139
return (lineIndex * sz.Height);
145
/// Utility method that measures a region of text in the given string.
147
/// <param name="g">The graphics instance used to render this text.</param>
148
/// <param name="font">The font instance used to render this text.</param>
149
/// <param name="text">The text that contains the region to be rendered.</param>
150
/// <param name="indexStart">Starting startingPosition of this region.</param>
151
/// <param name="length">Length of this region.</param>
152
/// <returns>The width of this region of text.</returns>
153
private float measureStringWidth(Graphics g, Font font, string text, int indexStart, int length)
155
CharacterRange[] ranges;
162
length = Math.Min(length, text.Length);
164
ranges = new CharacterRange[] { new CharacterRange(indexStart, length) };
165
sf = new StringFormat();
167
// the string of text may contains white spaces that need to
168
// be measured correctly.
170
sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
172
sf.SetMeasurableCharacterRanges(ranges);
174
// here : giving a layout too small can cause returned measure
177
regions = g.MeasureCharacterRanges(
178
text, font, new RectangleF(
179
0, 0, MEASURECHAR_BIG_WIDTH, MEASURECHAR_BIG_HEIGHT), sf);
181
return (regions[0].GetBounds(g).Width);
184
int CountVisibleLines(float viewportHeight, float fontHeight)
186
return ((int)(viewportHeight / fontHeight) + 1);
189
int YCoordinateToLineIndex(float y, float fontHeight)
191
return (int)(y / fontHeight);
194
float LineIndexToYCoordinate(int index, float fontHeight)
196
return (index * fontHeight);
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
// ****************************************************************
7
using System.Collections.Generic;
9
using NUnit.UiException.CodeFormatters;
11
using System.Diagnostics;
13
namespace NUnit.UiException.Controls
15
public class DefaultCodeRenderer :
19
/// These constants below address an issue at measure text time
20
/// that sometimes can cause big lines of text to be misaligned.
22
private readonly static float MEASURECHAR_BIG_WIDTH = 5000f;
23
private readonly static float MEASURECHAR_BIG_HEIGHT = 100f;
25
public PaintLineLocation[] ViewportLines(FormattedCode code, RectangleF viewport, float fontHeight)
27
List<PaintLineLocation> list = new List<PaintLineLocation>();
28
int visibles = CountVisibleLines(viewport.Height, fontHeight);
29
// int topIndex = YCoordinateToLineIndex(viewport.Top, fontHeight);
30
int lineIndex = YCoordinateToLineIndex(viewport.Top, fontHeight);
33
for (i = 0; i < visibles; ++i, lineIndex++)
38
if (lineIndex >= code.LineCount)
42
new PaintLineLocation(lineIndex, code.GetTextAt(lineIndex),
43
new PointF(-viewport.Left,
44
LineIndexToYCoordinate(lineIndex, fontHeight) -
48
return (list.ToArray());
51
#region ICodeRenderer Membres
53
public void DrawToGraphics(FormattedCode code, CodeRenderingContext args, Rectangle viewport)
55
UiExceptionHelper.CheckNotNull(code, "code");
56
UiExceptionHelper.CheckNotNull(args, "args");
58
ClassifiedTokenCollection line;
59
PaintLineLocation[] lines;
60
ClassifiedToken token;
67
fontHeight = LineIndexToYCoordinate(1, args.Graphics, args.Font);
68
lines = ViewportLines(code, viewport, fontHeight);
70
foreach (PaintLineLocation paintLine in lines)
72
// All lines that differ from CurrentLine are displayed
73
// in using different styles of Brush to make a distinction
74
// between code, keyword, comments.
75
if (paintLine.LineIndex != args.CurrentLine)
77
line = code[paintLine.LineIndex];
81
for (i = 0; i < line.Count; ++i)
85
args.Graphics.DrawString(token.Text, args.Font, args.GetBrush(token.Tag),
86
paintLine.Location.X + x, paintLine.Location.Y);
88
tk_width = measureStringWidth(args.Graphics, args.Font, text,
89
token.IndexStart, token.Text.Length);
97
// The current line is emphasized by using a
98
// specific couples of Background & Foreground colors
100
args.Graphics.FillRectangle(
101
args.CurrentLineBackBrush,
102
0, paintLine.Location.Y,
103
viewport.Width, fontHeight);
105
args.Graphics.DrawString(
106
paintLine.Text, args.Font,
107
args.CurrentLineForeBrush,
108
paintLine.Location.X, paintLine.Location.Y);
114
public SizeF GetDocumentSize(FormattedCode code, Graphics g, Font font)
116
UiExceptionHelper.CheckNotNull(code, "code");
117
UiExceptionHelper.CheckNotNull(g, "g");
118
UiExceptionHelper.CheckNotNull(font, "font");
120
StringBuilder sample;
124
sample = new StringBuilder();
125
for (i = code.MaxLength; i > 0; --i)
128
measure = g.MeasureString(sample.ToString(), font);
130
return (new SizeF(measure.Width, measure.Height * code.LineCount));
133
public float LineIndexToYCoordinate(int lineIndex, Graphics g, Font font)
135
UiExceptionHelper.CheckNotNull(g, "g");
136
UiExceptionHelper.CheckNotNull(font, "font");
138
SizeF sz = g.MeasureString("m", font);
139
return (lineIndex * sz.Height);
145
/// Utility method that measures a region of text in the given string.
147
/// <param name="g">The graphics instance used to render this text.</param>
148
/// <param name="font">The font instance used to render this text.</param>
149
/// <param name="text">The text that contains the region to be rendered.</param>
150
/// <param name="indexStart">Starting startingPosition of this region.</param>
151
/// <param name="length">Length of this region.</param>
152
/// <returns>The width of this region of text.</returns>
153
private float measureStringWidth(Graphics g, Font font, string text, int indexStart, int length)
155
CharacterRange[] ranges;
162
length = Math.Min(length, text.Length);
164
ranges = new CharacterRange[] { new CharacterRange(indexStart, length) };
165
sf = new StringFormat();
167
// the string of text may contains white spaces that need to
168
// be measured correctly.
170
sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
172
sf.SetMeasurableCharacterRanges(ranges);
174
// here : giving a layout too small can cause returned measure
177
regions = g.MeasureCharacterRanges(
178
text, font, new RectangleF(
179
0, 0, MEASURECHAR_BIG_WIDTH, MEASURECHAR_BIG_HEIGHT), sf);
181
return (regions[0].GetBounds(g).Width);
184
int CountVisibleLines(float viewportHeight, float fontHeight)
186
return ((int)(viewportHeight / fontHeight) + 1);
189
int YCoordinateToLineIndex(float y, float fontHeight)
191
return (int)(y / fontHeight);
194
float LineIndexToYCoordinate(int index, float fontHeight)
196
return (index * fontHeight);