Code Coverage Statistics for Source File

c:\Tools\SD3\src\Libraries\ICSharpCode.TextEditor\Project\Src\Gui\DrawableLine.cs

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
190
Highlight: Uncovered Code Covered Code
L V Source
1
// <file>
2
//     <copyright see="prj:///doc/copyright.txt"/>
3
//     <license see="prj:///doc/license.txt"/>
4
//     <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
5
//     <version>$Revision: 1965 $</version>
6
// </file>
7
8
using System;
9
using System.Collections.Generic;
10
using System.Drawing;
11
12
using ICSharpCode.TextEditor.Document;
13
14
namespace ICSharpCode.TextEditor
15
{
16
	/// <summary>
17
	/// A class that is able to draw a line on any control (outside the text editor)
18
	/// </summary>
19
	public class DrawableLine
20
	{
21
		static StringFormat sf = (StringFormat)System.Drawing.StringFormat.GenericTypographic.Clone();
22
		
23
		List<SimpleTextWord> words = new List<SimpleTextWord>();
24
		SizeF spaceSize;
25
		Font monospacedFont;
26
		Font boldMonospacedFont;
27
		
28
		private class SimpleTextWord {
29
			internal TextWordType Type;
30
			internal string       Word;
31
			internal bool         Bold;
32
			internal Color        Color;
33
			
34
			public SimpleTextWord(TextWordType Type, string Word, bool Bold, Color Color)
35
			{
36
				this.Type = Type;
37
				this.Word = Word;
38
				this.Bold = Bold;
39
				this.Color = Color;
40
			}
41
			
42
			internal readonly static SimpleTextWord Space = new SimpleTextWord(TextWordType.Space, " ", false, Color.Black);
43
			internal readonly static SimpleTextWord Tab = new SimpleTextWord(TextWordType.Tab, "\t", false, Color.Black);
44
		}
45
		
46
		public DrawableLine(IDocument document, LineSegment line, Font monospacedFont, Font boldMonospacedFont)
47
		{
48
			this.monospacedFont = monospacedFont;
49
			this.boldMonospacedFont = boldMonospacedFont;
50
			if (line.Words != null) {
51
				foreach (TextWord word in line.Words) {
52
					if (word.Type == TextWordType.Space) {
53
						words.Add(SimpleTextWord.Space);
54
					} else if (word.Type == TextWordType.Tab) {
55
						words.Add(SimpleTextWord.Tab);
56
					} else {
57
						words.Add(new SimpleTextWord(TextWordType.Word, word.Word, word.Bold, word.Color));
58
					}
59
				}
60
			} else {
61
				words.Add(new SimpleTextWord(TextWordType.Word, document.GetText(line), false, Color.Black));
62
			}
63
		}
64
		
65
		public int LineLength {
66
			get {
67
				int length = 0;
68
				foreach (SimpleTextWord word in words) {
69
					length += word.Word.Length;
70
				}
71
				return length;
72
			}
73
		}
74
		
75
		public void SetBold(int startIndex, int endIndex, bool bold)
76
		{
77
			if (startIndex < 0)
78
				throw new ArgumentException("startIndex must be >= 0");
79
			if (startIndex > endIndex)
80
				throw new ArgumentException("startIndex must be <= endIndex");
81
			if (startIndex == endIndex) return;
82
			int pos = 0;
83
			for (int i = 0; i < words.Count; i++) {
84
				SimpleTextWord word = words[i];
85
				if (pos >= endIndex)
86
					break;
87
				int wordEnd = pos + word.Word.Length;
88
				// 3 possibilities:
89
				if (startIndex <= pos && endIndex >= wordEnd) {
90
					// word is fully in region:
91
					word.Bold = bold;
92
				} else if (startIndex <= pos) {
93
					// beginning of word is in region
94
					int inRegionLength = endIndex - pos;
95
					SimpleTextWord newWord = new SimpleTextWord(word.Type, word.Word.Substring(inRegionLength), word.Bold, word.Color);
96
					words.Insert(i + 1, newWord);
97
					
98
					word.Bold = bold;
99
					word.Word = word.Word.Substring(0, inRegionLength);
100
				} else if (startIndex < wordEnd) {
101
					// end of word is in region (or middle of word is in region)
102
					int notInRegionLength = startIndex - pos;
103
					
104
					SimpleTextWord newWord = new SimpleTextWord(word.Type, word.Word.Substring(notInRegionLength), word.Bold, word.Color);
105
					// newWord.Bold will be set in the next iteration
106
					words.Insert(i + 1, newWord);
107
					
108
					word.Word = word.Word.Substring(0, notInRegionLength);
109
				}
110
				pos = wordEnd;
111
			}
112
		}
113
		
114
		public static float DrawDocumentWord(Graphics g, string word, PointF position, Font font, Color foreColor)
115
		{
116
			if (word == null || word.Length == 0) {
117
				return 0f;
118
			}
119
			SizeF wordSize = g.MeasureString(word, font, 32768, sf);
120
			
121
			g.DrawString(word,
122
			             font,
123
			             BrushRegistry.GetBrush(foreColor),
124
			             position,
125
			             sf);
126
			return wordSize.Width;
127
		}
128
		
129
		public SizeF GetSpaceSize(Graphics g)
130
		{
131
			if (spaceSize.IsEmpty) {
132
				spaceSize = g.MeasureString("-", boldMonospacedFont,  new PointF(0, 0), sf);
133
			}
134
			return spaceSize;
135
		}
136
		
137
		public void DrawLine(Graphics g, ref float xPos, float xOffset, float yPos, Color c)
138
		{
139
			SizeF spaceSize = GetSpaceSize(g);
140
			foreach (SimpleTextWord word in words) {
141
				switch (word.Type) {
142
					case TextWordType.Space:
143
						xPos += spaceSize.Width;
144
						break;
145
					case TextWordType.Tab:
146
						float tabWidth = spaceSize.Width * 4;
147
						xPos += tabWidth;
148
						xPos = (int)((xPos + 2) / tabWidth) * tabWidth;
149
						break;
150
					case TextWordType.Word:
151
						xPos += DrawDocumentWord(g,
152
						                         word.Word,
153
						                         new PointF(xPos + xOffset, yPos),
154
						                         word.Bold ? boldMonospacedFont : monospacedFont,
155
						                         c == Color.Empty ? word.Color : c
156
						                        );
157
						break;
158
				}
159
			}
160
		}
161
		
162
		public void DrawLine(Graphics g, ref float xPos, float xOffset, float yPos)
163
		{
164
			DrawLine(g, ref xPos, xOffset, yPos, Color.Empty);
165
		}
166
		
167
		public float MeasureWidth(Graphics g, float xPos)
168
		{
169
			SizeF spaceSize = GetSpaceSize(g);
170
			foreach (SimpleTextWord word in words) {
171
				switch (word.Type) {
172
					case TextWordType.Space:
173
						xPos += spaceSize.Width;
174
						break;
175
					case TextWordType.Tab:
176
						float tabWidth = spaceSize.Width * 4;
177
						xPos += tabWidth;
178
						xPos = (int)((xPos + 2) / tabWidth) * tabWidth;
179
						break;
180
					case TextWordType.Word:
181
						if (word.Word != null && word.Word.Length > 0) {
182
							xPos += g.MeasureString(word.Word, word.Bold ? boldMonospacedFont : monospacedFont, 32768, sf).Width;
183
						}
184
						break;
185
				}
186
			}
187
			return xPos;
188
		}
189
	}
190
}