Code Coverage Statistics for Source File

c:\Tools\SD3\src\Libraries\ICSharpCode.TextEditor\Project\Src\Document\FoldingStrategy\FoldingManager.cs

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
333
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="Mike Krüger" email="mike@icsharpcode.net"/>
5
//     <version>$Revision: 2691 $</version>
6
// </file>
7
8
using System;
9
using System.Collections.Generic;
10
using System.Drawing;
11
using System.Text;
12
13
namespace ICSharpCode.TextEditor.Document
14
{
15
	public class FoldingManager
16
	{
17
		List<FoldMarker>    foldMarker      = new List<FoldMarker>();
18
		List<FoldMarker>    foldMarkerByEnd = new List<FoldMarker>();
19
		IFoldingStrategy    foldingStrategy = null;
20
		IDocument document;
21
		
22
		public IList<FoldMarker> FoldMarker {
23
			get {
24
				return foldMarker.AsReadOnly();
25
			}
26
		}
27
		
28
		public IFoldingStrategy FoldingStrategy {
29
			get {
30
				return foldingStrategy;
31
			}
32
			set {
33
				foldingStrategy = value;
34
			}
35
		}
36
		
37
		internal FoldingManager(IDocument document, LineManager lineTracker)
38
		{
39
			this.document = document;
40
			document.DocumentChanged += new DocumentEventHandler(DocumentChanged);
41
			
42
//			lineTracker.LineCountChanged  += new LineManagerEventHandler(LineManagerLineCountChanged);
43
//			lineTracker.LineLengthChanged += new LineLengthEventHandler(LineManagerLineLengthChanged);
44
//			foldMarker.Add(new FoldMarker(0, 5, 3, 5));
45
//
46
//			foldMarker.Add(new FoldMarker(5, 5, 10, 3));
47
//			foldMarker.Add(new FoldMarker(6, 0, 8, 2));
48
//
49
//			FoldMarker fm1 = new FoldMarker(10, 4, 10, 7);
50
//			FoldMarker fm2 = new FoldMarker(10, 10, 10, 14);
51
//
52
//			fm1.IsFolded = true;
53
//			fm2.IsFolded = true;
54
//
55
//			foldMarker.Add(fm1);
56
//			foldMarker.Add(fm2);
57
//			foldMarker.Sort();
58
		}
59
		
60
		void DocumentChanged(object sender, DocumentEventArgs e)
61
		{
62
			int oldCount = foldMarker.Count;
63
			document.UpdateSegmentListOnDocumentChange(foldMarker, e);
64
			if (oldCount != foldMarker.Count) {
65
				document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
66
			}
67
		}
68
		
69
		public List<FoldMarker> GetFoldingsFromPosition(int line, int column)
70
		{
71
			List<FoldMarker> foldings = new List<FoldMarker>();
72
			if (foldMarker != null) {
73
				for (int i = 0; i < foldMarker.Count; ++i) {
74
					FoldMarker fm = foldMarker[i];
75
					if ((fm.StartLine == line && column > fm.StartColumn && !(fm.EndLine == line && column >= fm.EndColumn)) ||
76
					    (fm.EndLine == line && column < fm.EndColumn && !(fm.StartLine == line && column <= fm.StartColumn)) ||
77
					    (line > fm.StartLine && line < fm.EndLine)) {
78
						foldings.Add(fm);
79
					}
80
				}
81
			}
82
			return foldings;
83
		}
84
		
85
		class StartComparer : IComparer<FoldMarker>
86
		{
87
			public readonly static StartComparer Instance = new StartComparer();
88
			
89
			public int Compare(FoldMarker x, FoldMarker y)
90
			{
91
				if (x.StartLine < y.StartLine)
92
					return -1;
93
				else if (x.StartLine == y.StartLine)
94
					return x.StartColumn.CompareTo(y.StartColumn);
95
				else
96
					return 1;
97
			}
98
		}
99
		
100
		class EndComparer : IComparer<FoldMarker>
101
		{
102
			public readonly static EndComparer Instance = new EndComparer();
103
			
104
			public int Compare(FoldMarker x, FoldMarker y)
105
			{
106
				if (x.EndLine < y.EndLine)
107
					return -1;
108
				else if (x.EndLine == y.EndLine)
109
					return x.EndColumn.CompareTo(y.EndColumn);
110
				else
111
					return 1;
112
			}
113
		}
114
		
115
		List<FoldMarker> GetFoldingsByStartAfterColumn(int lineNumber, int column, bool forceFolded)
116
		{
117
			List<FoldMarker> foldings = new List<FoldMarker>();
118
			
119
			if (foldMarker != null) {
120
				int index = foldMarker.BinarySearch(
121
					new FoldMarker(document, lineNumber, column, lineNumber, column),
122
					StartComparer.Instance);
123
				if (index < 0) index = ~index;
124
				
125
				for (; index < foldMarker.Count; index++) {
126
					FoldMarker fm = foldMarker[index];
127
					if (fm.StartLine > lineNumber)
128
						break;
129
					if (fm.StartColumn <= column)
130
						continue;
131
					if (!forceFolded || fm.IsFolded)
132
						foldings.Add(fm);
133
				}
134
			}
135
			return foldings;
136
		}
137
		
138
		public List<FoldMarker> GetFoldingsWithStart(int lineNumber)
139
		{
140
			return GetFoldingsByStartAfterColumn(lineNumber, -1, false);
141
		}
142
		
143
		public List<FoldMarker> GetFoldedFoldingsWithStart(int lineNumber)
144
		{
145
			return GetFoldingsByStartAfterColumn(lineNumber, -1, true);
146
		}
147
		
148
		public List<FoldMarker> GetFoldedFoldingsWithStartAfterColumn(int lineNumber, int column)
149
		{
150
			return GetFoldingsByStartAfterColumn(lineNumber, column, true);
151
		}
152
		
153
		List<FoldMarker> GetFoldingsByEndAfterColumn(int lineNumber, int column, bool forceFolded)
154
		{
155
			List<FoldMarker> foldings = new List<FoldMarker>();
156
			
157
			if (foldMarker != null) {
158
				int index =  foldMarkerByEnd.BinarySearch(
159
					new FoldMarker(document, lineNumber, column, lineNumber, column),
160
					EndComparer.Instance);
161
				if (index < 0) index = ~index;
162
				
163
				for (; index < foldMarkerByEnd.Count; index++) {
164
					FoldMarker fm = foldMarkerByEnd[index];
165
					if (fm.EndLine > lineNumber)
166
						break;
167
					if (fm.EndColumn <= column)
168
						continue;
169
					if (!forceFolded || fm.IsFolded)
170
						foldings.Add(fm);
171
				}
172
			}
173
			return foldings;
174
		}
175
		
176
		public List<FoldMarker> GetFoldingsWithEnd(int lineNumber)
177
		{
178
			return GetFoldingsByEndAfterColumn(lineNumber, -1, false);
179
		}
180
		
181
		public List<FoldMarker> GetFoldedFoldingsWithEnd(int lineNumber)
182
		{
183
			return GetFoldingsByEndAfterColumn(lineNumber, -1, true);
184
		}
185
		
186
		public bool IsFoldStart(int lineNumber)
187
		{
188
			return GetFoldingsWithStart(lineNumber).Count > 0;
189
		}
190
		
191
		public bool IsFoldEnd(int lineNumber)
192
		{
193
			return GetFoldingsWithEnd(lineNumber).Count > 0;
194
		}
195
		
196
		public List<FoldMarker> GetFoldingsContainsLineNumber(int lineNumber)
197
		{
198
			List<FoldMarker> foldings = new List<FoldMarker>();
199
			if (foldMarker != null) {
200
				foreach (FoldMarker fm in foldMarker) {
201
					if (fm.StartLine < lineNumber && lineNumber < fm.EndLine) {
202
						foldings.Add(fm);
203
					}
204
				}
205
			}
206
			return foldings;
207
		}
208
		
209
		public bool IsBetweenFolding(int lineNumber)
210
		{
211
			return GetFoldingsContainsLineNumber(lineNumber).Count > 0;
212
		}
213
		
214
		public bool IsLineVisible(int lineNumber)
215
		{
216
			foreach (FoldMarker fm in GetFoldingsContainsLineNumber(lineNumber)) {
217
				if (fm.IsFolded)
218
					return false;
219
			}
220
			return true;
221
		}
222
		
223
		public List<FoldMarker> GetTopLevelFoldedFoldings()
224
		{
225
			List<FoldMarker> foldings = new List<FoldMarker>();
226
			if (foldMarker != null) {
227
				Point end = new Point(0, 0);
228
				foreach (FoldMarker fm in foldMarker) {
229
					if (fm.IsFolded && (fm.StartLine > end.Y || fm.StartLine == end.Y && fm.StartColumn >= end.X)) {
230
						foldings.Add(fm);
231
						end = new Point(fm.EndColumn, fm.EndLine);
232
					}
233
				}
234
			}
235
			return foldings;
236
		}
237
		
238
		public void UpdateFoldings(string fileName, object parseInfo)
239
		{
240
			UpdateFoldings(foldingStrategy.GenerateFoldMarkers(document, fileName, parseInfo));
241
		}
242
		
243
		public void UpdateFoldings(List<FoldMarker> newFoldings)
244
		{
245
			int oldFoldingsCount = foldMarker.Count;
246
			lock (this) {
247
				if (newFoldings != null && newFoldings.Count != 0) {
248
					newFoldings.Sort();
249
					if (foldMarker.Count == newFoldings.Count) {
250
						for (int i = 0; i < foldMarker.Count; ++i) {
251
							newFoldings[i].IsFolded = foldMarker[i].IsFolded;
252
						}
253
						foldMarker = newFoldings;
254
					} else {
255
						for (int i = 0, j = 0; i < foldMarker.Count && j < newFoldings.Count;) {
256
							int n = newFoldings[j].CompareTo(foldMarker[i]);
257
							if (n > 0) {
258
								++i;
259
							} else {
260
								if (n == 0) {
261
									newFoldings[j].IsFolded = foldMarker[i].IsFolded;
262
								}
263
								++j;
264
							}
265
						}
266
					}
267
				}
268
				if (newFoldings != null) {
269
					foldMarker = newFoldings;
270
					foldMarkerByEnd = new List<FoldMarker>(newFoldings);
271
					foldMarkerByEnd.Sort(EndComparer.Instance);
272
				} else {
273
					foldMarker.Clear();
274
					foldMarkerByEnd.Clear();
275
				}
276
			}
277
			if (oldFoldingsCount != foldMarker.Count) {
278
				document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
279
				document.CommitUpdate();
280
			}
281
		}
282
		
283
		public string SerializeToString()
284
		{
285
			StringBuilder sb = new StringBuilder();
286
			foreach (FoldMarker marker in this.foldMarker) {
287
				sb.Append(marker.Offset);sb.Append("\n");
288
				sb.Append(marker.Length);sb.Append("\n");
289
				sb.Append(marker.FoldText);sb.Append("\n");
290
				sb.Append(marker.IsFolded);sb.Append("\n");
291
			}
292
			return sb.ToString();
293
		}
294
		
295
		public void DeserializeFromString(string str)
296
		{
297
			try {
298
				string[] lines = str.Split('\n');
299
				for (int i = 0; i < lines.Length && lines[i].Length > 0; i += 4) {
300
					int    offset = Int32.Parse(lines[i]);
301
					int    length = Int32.Parse(lines[i + 1]);
302
					string text   = lines[i + 2];
303
					bool isFolded = Boolean.Parse(lines[i + 3]);
304
					bool found    = false;
305
					foreach (FoldMarker marker in foldMarker) {
306
						if (marker.Offset == offset && marker.Length == length) {
307
							marker.IsFolded = isFolded;
308
							found = true;
309
							break;
310
						}
311
					}
312
					if (!found) {
313
						foldMarker.Add(new FoldMarker(document, offset, length, text, isFolded));
314
					}
315
				}
316
				if (lines.Length > 0) {
317
					NotifyFoldingsChanged(EventArgs.Empty);
318
				}
319
			} catch (Exception) {
320
			}
321
		}
322
		
323
		public void NotifyFoldingsChanged(EventArgs e)
324
		{
325
			if (FoldingsChanged != null) {
326
				FoldingsChanged(this, e);
327
			}
328
		}
329
		
330
		
331
		public event EventHandler FoldingsChanged;
332
	}
333
}