Code Coverage Statistics for Source File

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

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
460
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.Diagnostics;
11
using System.Drawing;
12
13
using ICSharpCode.TextEditor.Undo;
14
15
namespace ICSharpCode.TextEditor.Document
16
{
17
	/// <summary>
18
	/// Describes the caret marker
19
	/// </summary>
20
	public enum LineViewerStyle {
21
		/// <summary>
22
		/// No line viewer will be displayed
23
		/// </summary>
24
		None,
25
		
26
		/// <summary>
27
		/// The row in which the caret is will be marked
28
		/// </summary>
29
		FullRow
30
	}
31
	
32
	/// <summary>
33
	/// Describes the indent style
34
	/// </summary>
35
	public enum IndentStyle {
36
		/// <summary>
37
		/// No indentation occurs
38
		/// </summary>
39
		None,
40
		
41
		/// <summary>
42
		/// The indentation from the line above will be
43
		/// taken to indent the curent line
44
		/// </summary>
45
		Auto,
46
		
47
		/// <summary>
48
		/// Inteligent, context sensitive indentation will occur
49
		/// </summary>
50
		Smart
51
	}
52
	
53
	/// <summary>
54
	/// Describes the bracket highlighting style
55
	/// </summary>
56
	public enum BracketHighlightingStyle {
57
		
58
		/// <summary>
59
		/// Brackets won't be highlighted
60
		/// </summary>
61
		None,
62
		
63
		/// <summary>
64
		/// Brackets will be highlighted if the caret is on the bracket
65
		/// </summary>
66
		OnBracket,
67
		
68
		/// <summary>
69
		/// Brackets will be highlighted if the caret is after the bracket
70
		/// </summary>
71
		AfterBracket
72
	}
73
	
74
	/// <summary>
75
	/// Describes the selection mode of the text area
76
	/// </summary>
77
	public enum DocumentSelectionMode {
78
		/// <summary>
79
		/// The 'normal' selection mode.
80
		/// </summary>
81
		Normal,
82
		
83
		/// <summary>
84
		/// Selections will be added to the current selection or new
85
		/// ones will be created (multi-select mode)
86
		/// </summary>
87
		Additive
88
	}
89
	
90
	/// <summary>
91
	/// The default <see cref="IDocument"/> implementation.
92
	/// </summary>
93
	internal sealed class DefaultDocument : IDocument
94
	{
95
		bool readOnly = false;
96
		
97
		LineManager           lineTrackingStrategy;
98
		ICustomLineManager    customLineManager;
99
		BookmarkManager       bookmarkManager;
100
		ITextBufferStrategy   textBufferStrategy;
101
		IFormattingStrategy   formattingStrategy;
102
		FoldingManager        foldingManager;
103
		UndoStack             undoStack = new UndoStack();
104
		ITextEditorProperties textEditorProperties = new DefaultTextEditorProperties();
105
		MarkerStrategy        markerStrategy;
106
		
107
		public LineManager LineManager {
108
			get { return lineTrackingStrategy; }
109
			set { lineTrackingStrategy = value; }
110
		}
111
		
112
		public event EventHandler<LineLengthChangeEventArgs> LineLengthChanged {
113
			add { lineTrackingStrategy.LineLengthChanged += value; }
114
			remove { lineTrackingStrategy.LineLengthChanged -= value; }
115
		}
116
		public event EventHandler<LineCountChangeEventArgs> LineCountChanged {
117
			add { lineTrackingStrategy.LineCountChanged += value; }
118
			remove { lineTrackingStrategy.LineCountChanged -= value; }
119
		}
120
		public event EventHandler<LineEventArgs> LineDeleted {
121
			add { lineTrackingStrategy.LineDeleted += value; }
122
			remove { lineTrackingStrategy.LineDeleted -= value; }
123
		}
124
		
125
		public MarkerStrategy MarkerStrategy {
126
			get { return markerStrategy; }
127
			set { markerStrategy = value; }
128
		}
129
		
130
		public ITextEditorProperties TextEditorProperties {
131
			get {
132
				return textEditorProperties;
133
			}
134
			set {
135
				textEditorProperties = value;
136
			}
137
		}
138
		
139
		public UndoStack UndoStack {
140
			get {
141
				return undoStack;
142
			}
143
		}
144
		
145
		public IList<LineSegment> LineSegmentCollection {
146
			get {
147
				return lineTrackingStrategy.LineSegmentCollection;
148
			}
149
		}
150
		
151
		public bool ReadOnly {
152
			get {
153
				return readOnly;
154
			}
155
			set {
156
				readOnly = value;
157
			}
158
		}
159
		
160
		public ITextBufferStrategy TextBufferStrategy {
161
			get {
162
				return textBufferStrategy;
163
			}
164
			set {
165
				textBufferStrategy = value;
166
			}
167
		}
168
		
169
		public IFormattingStrategy FormattingStrategy {
170
			get {
171
				return formattingStrategy;
172
			}
173
			set {
174
				formattingStrategy = value;
175
			}
176
		}
177
		
178
		public FoldingManager FoldingManager {
179
			get {
180
				return foldingManager;
181
			}
182
			set {
183
				foldingManager = value;
184
			}
185
		}
186
		
187
		public IHighlightingStrategy HighlightingStrategy {
188
			get {
189
				return lineTrackingStrategy.HighlightingStrategy;
190
			}
191
			set {
192
				lineTrackingStrategy.HighlightingStrategy = value;
193
			}
194
		}
195
		
196
		public int TextLength {
197
			get {
198
				return textBufferStrategy.Length;
199
			}
200
		}
201
		
202
		public BookmarkManager BookmarkManager {
203
			get {
204
				return bookmarkManager;
205
			}
206
			set {
207
				bookmarkManager = value;
208
			}
209
		}
210
		
211
		
212
		public ICustomLineManager CustomLineManager {
213
			get {
214
				return customLineManager;
215
			}
216
			set {
217
				customLineManager = value;
218
			}
219
		}
220
		
221
		public string TextContent {
222
			get {
223
				return GetText(0, textBufferStrategy.Length);
224
			}
225
			set {
226
				Debug.Assert(textBufferStrategy != null);
227
				Debug.Assert(lineTrackingStrategy != null);
228
				OnDocumentAboutToBeChanged(new DocumentEventArgs(this, 0, 0, value));
229
				textBufferStrategy.SetContent(value);
230
				lineTrackingStrategy.SetContent(value);
231
				undoStack.ClearAll();
232
				
233
				OnDocumentChanged(new DocumentEventArgs(this, 0, 0, value));
234
				OnTextContentChanged(EventArgs.Empty);
235
			}
236
		}
237
		
238
		public void Insert(int offset, string text)
239
		{
240
			if (readOnly) {
241
				return;
242
			}
243
			OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, -1, text));
244
			
245
			textBufferStrategy.Insert(offset, text);
246
			lineTrackingStrategy.Insert(offset, text);
247
			
248
			undoStack.Push(new UndoableInsert(this, offset, text));
249
			
250
			OnDocumentChanged(new DocumentEventArgs(this, offset, -1, text));
251
		}
252
		
253
		public void Remove(int offset, int length)
254
		{
255
			if (readOnly) {
256
				return;
257
			}
258
			OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, length));
259
			undoStack.Push(new UndoableDelete(this, offset, GetText(offset, length)));
260
			
261
			textBufferStrategy.Remove(offset, length);
262
			lineTrackingStrategy.Remove(offset, length);
263
			
264
			OnDocumentChanged(new DocumentEventArgs(this, offset, length));
265
		}
266
		
267
		public void Replace(int offset, int length, string text)
268
		{
269
			if (readOnly) {
270
				return;
271
			}
272
			OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, length, text));
273
			undoStack.Push(new UndoableReplace(this, offset, GetText(offset, length), text));
274
			
275
			textBufferStrategy.Replace(offset, length, text);
276
			lineTrackingStrategy.Replace(offset, length, text);
277
			
278
			OnDocumentChanged(new DocumentEventArgs(this, offset, length, text));
279
		}
280
		
281
		public char GetCharAt(int offset)
282
		{
283
			return textBufferStrategy.GetCharAt(offset);
284
		}
285
		
286
		public string GetText(int offset, int length)
287
		{
288
			#if DEBUG
289
			if (length < 0) throw new ArgumentOutOfRangeException("length", length, "length < 0");
290
			#endif
291
			return textBufferStrategy.GetText(offset, length);
292
		}
293
		public string GetText(ISegment segment)
294
		{
295
			return GetText(segment.Offset, segment.Length);
296
		}
297
		
298
		public int TotalNumberOfLines {
299
			get {
300
				return lineTrackingStrategy.TotalNumberOfLines;
301
			}
302
		}
303
		
304
		public int GetLineNumberForOffset(int offset)
305
		{
306
			return lineTrackingStrategy.GetLineNumberForOffset(offset);
307
		}
308
		
309
		public LineSegment GetLineSegmentForOffset(int offset)
310
		{
311
			return lineTrackingStrategy.GetLineSegmentForOffset(offset);
312
		}
313
		
314
		public LineSegment GetLineSegment(int line)
315
		{
316
			return lineTrackingStrategy.GetLineSegment(line);
317
		}
318
		
319
		public int GetFirstLogicalLine(int lineNumber)
320
		{
321
			return lineTrackingStrategy.GetFirstLogicalLine(lineNumber);
322
		}
323
		
324
		public int GetLastLogicalLine(int lineNumber)
325
		{
326
			return lineTrackingStrategy.GetLastLogicalLine(lineNumber);
327
		}
328
		
329
		public int GetVisibleLine(int lineNumber)
330
		{
331
			return lineTrackingStrategy.GetVisibleLine(lineNumber);
332
		}
333
		
334
//		public int GetVisibleColumn(int logicalLine, int logicalColumn)
335
//		{
336
//			return lineTrackingStrategy.GetVisibleColumn(logicalLine, logicalColumn);
337
//		}
338
//
339
		public int GetNextVisibleLineAbove(int lineNumber, int lineCount)
340
		{
341
			return lineTrackingStrategy.GetNextVisibleLineAbove(lineNumber, lineCount);
342
		}
343
		
344
		public int GetNextVisibleLineBelow(int lineNumber, int lineCount)
345
		{
346
			return lineTrackingStrategy.GetNextVisibleLineBelow(lineNumber, lineCount);
347
		}
348
		
349
		public TextLocation OffsetToPosition(int offset)
350
		{
351
			int lineNr = GetLineNumberForOffset(offset);
352
			LineSegment line = GetLineSegment(lineNr);
353
			return new TextLocation(offset - line.Offset, lineNr);
354
		}
355
		
356
		public int PositionToOffset(TextLocation p)
357
		{
358
			if (p.Y >= this.TotalNumberOfLines) {
359
				return 0;
360
			}
361
			LineSegment line = GetLineSegment(p.Y);
362
			return Math.Min(this.TextLength, line.Offset + Math.Min(line.Length, p.X));
363
		}
364
		
365
		public void UpdateSegmentListOnDocumentChange<T>(List<T> list, DocumentEventArgs e) where T : ISegment
366
		{
367
			for (int i = 0; i < list.Count; ++i) {
368
				ISegment fm = list[i];
369
				
370
				if (e.Offset <= fm.Offset && fm.Offset <= e.Offset + e.Length ||
371
				    e.Offset <= fm.Offset + fm.Length && fm.Offset + fm.Length <= e.Offset + e.Length) {
372
					list.RemoveAt(i);
373
					--i;
374
					continue;
375
				}
376
				
377
				if (fm.Offset  <= e.Offset && e.Offset <= fm.Offset + fm.Length) {
378
					if (e.Text != null) {
379
						fm.Length += e.Text.Length;
380
					}
381
					if (e.Length > 0) {
382
						fm.Length -= e.Length;
383
					}
384
					continue;
385
				}
386
				
387
				if (fm.Offset >= e.Offset) {
388
					if (e.Text != null) {
389
						fm.Offset += e.Text.Length;
390
					}
391
					if (e.Length > 0) {
392
						fm.Offset -= e.Length;
393
					}
394
				}
395
			}
396
		}
397
		
398
		void OnDocumentAboutToBeChanged(DocumentEventArgs e)
399
		{
400
			if (DocumentAboutToBeChanged != null) {
401
				DocumentAboutToBeChanged(this, e);
402
			}
403
		}
404
		
405
		void OnDocumentChanged(DocumentEventArgs e)
406
		{
407
			if (DocumentChanged != null) {
408
				DocumentChanged(this, e);
409
			}
410
		}
411
		
412
		public event DocumentEventHandler DocumentAboutToBeChanged;
413
		public event DocumentEventHandler DocumentChanged;
414
		
415
		// UPDATE STUFF
416
		List<TextAreaUpdate> updateQueue = new List<TextAreaUpdate>();
417
		
418
		public List<TextAreaUpdate> UpdateQueue {
419
			get {
420
				return updateQueue;
421
			}
422
		}
423
		
424
		public void RequestUpdate(TextAreaUpdate update)
425
		{
426
			if (updateQueue.Count == 1 && updateQueue[0].TextAreaUpdateType == TextAreaUpdateType.WholeTextArea) {
427
				// if we're going to update the whole text area, we don't need to store detail updates
428
				return;
429
			}
430
			if (update.TextAreaUpdateType == TextAreaUpdateType.WholeTextArea) {
431
				// if we're going to update the whole text area, we don't need to store detail updates
432
				updateQueue.Clear();
433
			}
434
			updateQueue.Add(update);
435
		}
436
		
437
		public void CommitUpdate()
438
		{
439
			if (UpdateCommited != null) {
440
				UpdateCommited(this, EventArgs.Empty);
441
			}
442
		}
443
		
444
		void OnTextContentChanged(EventArgs e)
445
		{
446
			if (TextContentChanged != null) {
447
				TextContentChanged(this, e);
448
			}
449
		}
450
		
451
		public event EventHandler UpdateCommited;
452
		public event EventHandler TextContentChanged;
453
		
454
		[Conditional("DEBUG")]
455
		internal static void ValidatePosition(IDocument document, TextLocation position)
456
		{
457
			document.GetLineSegment(position.Line);
458
		}
459
	}
460
}