Code Coverage Statistics for Source File

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

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
275
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: 2063 $</version>
6
// </file>
7
8
using System;
9
using System.Collections.Generic;
10
using System.Drawing;
11
using System.Windows.Forms;
12
13
using ICSharpCode.TextEditor.Document;
14
15
namespace ICSharpCode.TextEditor
16
{
17
	/// <summary>
18
	/// This class views the line numbers and folding markers.
19
	/// </summary>
20
	public class FoldMargin : AbstractMargin
21
	{
22
		int selectedFoldLine = -1;
23
		
24
		public override Size Size {
25
			get {
26
				return new Size((int)(textArea.TextView.FontHeight),
27
				                -1);
28
			}
29
		}
30
		
31
		public override bool IsVisible {
32
			get {
33
				return textArea.TextEditorProperties.EnableFolding;
34
			}
35
		}
36
		
37
		public FoldMargin(TextArea textArea) : base(textArea)
38
		{
39
		}
40
		
41
		public override void Paint(Graphics g, Rectangle rect)
42
		{
43
			if (rect.Width <= 0 || rect.Height <= 0) {
44
				return;
45
			}
46
			HighlightColor lineNumberPainterColor = textArea.Document.HighlightingStrategy.GetColorFor("LineNumbers");
47
			HighlightColor foldLineColor          = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
48
			
49
			
50
			for (int y = 0; y < (DrawingPosition.Height + textArea.TextView.VisibleLineDrawingRemainder) / textArea.TextView.FontHeight + 1; ++y) {
51
				Rectangle markerRectangle = new Rectangle(DrawingPosition.X,
52
				                                          DrawingPosition.Top + y * textArea.TextView.FontHeight - textArea.TextView.VisibleLineDrawingRemainder,
53
				                                          DrawingPosition.Width,
54
				                                          textArea.TextView.FontHeight);
55
				
56
				if (rect.IntersectsWith(markerRectangle)) {
57
					// draw dotted separator line
58
					if (textArea.Document.TextEditorProperties.ShowLineNumbers) {
59
						g.FillRectangle(BrushRegistry.GetBrush(textArea.Enabled ? lineNumberPainterColor.BackgroundColor : SystemColors.InactiveBorder),
60
						                new Rectangle(markerRectangle.X + 1, markerRectangle.Y, markerRectangle.Width - 1, markerRectangle.Height));
61
						
62
						g.DrawLine(BrushRegistry.GetDotPen(lineNumberPainterColor.Color, lineNumberPainterColor.BackgroundColor),
63
						           base.drawingPosition.X,
64
						           markerRectangle.Y,
65
						           base.drawingPosition.X,
66
						           markerRectangle.Bottom);
67
					} else {
68
						g.FillRectangle(BrushRegistry.GetBrush(textArea.Enabled ? lineNumberPainterColor.BackgroundColor : SystemColors.InactiveBorder), markerRectangle);
69
					}
70
					
71
					int currentLine = textArea.Document.GetFirstLogicalLine(textArea.TextView.FirstPhysicalLine + y);
72
					if (currentLine < textArea.Document.TotalNumberOfLines) {
73
						PaintFoldMarker(g, currentLine, markerRectangle);
74
					}
75
				}
76
			}
77
		}
78
		
79
		bool SelectedFoldingFrom(List<FoldMarker> list)
80
		{
81
			if (list != null) {
82
				for (int i = 0; i < list.Count; ++i) {
83
					if (this.selectedFoldLine == list[i].StartLine) {
84
						return true;
85
					}
86
				}
87
			}
88
			return false;
89
		}
90
		
91
		void PaintFoldMarker(Graphics g, int lineNumber, Rectangle drawingRectangle)
92
		{
93
			HighlightColor foldLineColor    = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
94
			HighlightColor selectedFoldLine = textArea.Document.HighlightingStrategy.GetColorFor("SelectedFoldLine");
95
			
96
			List<FoldMarker> foldingsWithStart = textArea.Document.FoldingManager.GetFoldingsWithStart(lineNumber);
97
			List<FoldMarker> foldingsBetween   = textArea.Document.FoldingManager.GetFoldingsContainsLineNumber(lineNumber);
98
			List<FoldMarker> foldingsWithEnd   = textArea.Document.FoldingManager.GetFoldingsWithEnd(lineNumber);
99
			
100
			bool isFoldStart = foldingsWithStart.Count > 0;
101
			bool isBetween   = foldingsBetween.Count > 0;
102
			bool isFoldEnd   = foldingsWithEnd.Count > 0;
103
			
104
			bool isStartSelected   = SelectedFoldingFrom(foldingsWithStart);
105
			bool isBetweenSelected = SelectedFoldingFrom(foldingsBetween);
106
			bool isEndSelected     = SelectedFoldingFrom(foldingsWithEnd);
107
			
108
			int foldMarkerSize = (int)Math.Round(textArea.TextView.FontHeight * 0.57f);
109
			foldMarkerSize -= (foldMarkerSize) % 2;
110
			int foldMarkerYPos = drawingRectangle.Y + (int)((drawingRectangle.Height - foldMarkerSize) / 2);
111
			int xPos = drawingRectangle.X + (drawingRectangle.Width - foldMarkerSize) / 2 + foldMarkerSize / 2;
112
			
113
			
114
			if (isFoldStart) {
115
				bool isVisible         = true;
116
				bool moreLinedOpenFold = false;
117
				foreach (FoldMarker foldMarker in foldingsWithStart) {
118
					if (foldMarker.IsFolded) {
119
						isVisible = false;
120
					} else {
121
						moreLinedOpenFold = foldMarker.EndLine > foldMarker.StartLine;
122
					}
123
				}
124
				
125
				bool isFoldEndFromUpperFold = false;
126
				foreach (FoldMarker foldMarker in foldingsWithEnd) {
127
					if (foldMarker.EndLine > foldMarker.StartLine && !foldMarker.IsFolded) {
128
						isFoldEndFromUpperFold = true;
129
					}
130
				}
131
				
132
				DrawFoldMarker(g, new RectangleF(drawingRectangle.X + (drawingRectangle.Width - foldMarkerSize) / 2,
133
				                                 foldMarkerYPos,
134
				                                 foldMarkerSize,
135
				                                 foldMarkerSize),
136
				               isVisible,
137
				               isStartSelected
138
				              );
139
				
140
				// draw line above fold marker
141
				if (isBetween || isFoldEndFromUpperFold) {
142
					g.DrawLine(BrushRegistry.GetPen(isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color),
143
					           xPos,
144
					           drawingRectangle.Top,
145
					           xPos,
146
					           foldMarkerYPos - 1);
147
				}
148
				
149
				// draw line below fold marker
150
				if (isBetween || moreLinedOpenFold) {
151
					g.DrawLine(BrushRegistry.GetPen(isEndSelected || (isStartSelected && isVisible) || isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color),
152
					           xPos,
153
					           foldMarkerYPos + foldMarkerSize + 1,
154
					           xPos,
155
					           drawingRectangle.Bottom);
156
				}
157
			} else {
158
				if (isFoldEnd) {
159
					int midy = drawingRectangle.Top + drawingRectangle.Height / 2;
160
					
161
					// draw fold end marker
162
					g.DrawLine(BrushRegistry.GetPen(isEndSelected ? selectedFoldLine.Color : foldLineColor.Color),
163
					           xPos,
164
					           midy,
165
					           xPos + foldMarkerSize / 2,
166
					           midy);
167
					
168
					// draw line above fold end marker
169
					// must be drawn after fold marker because it might have a different color than the fold marker
170
					g.DrawLine(BrushRegistry.GetPen(isBetweenSelected || isEndSelected ? selectedFoldLine.Color : foldLineColor.Color),
171
					           xPos,
172
					           drawingRectangle.Top,
173
					           xPos,
174
					           midy);
175
					
176
					// draw line below fold end marker
177
					if (isBetween) {
178
						g.DrawLine(BrushRegistry.GetPen(isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color),
179
						           xPos,
180
						           midy + 1,
181
						           xPos,
182
						           drawingRectangle.Bottom);
183
					}
184
				} else if (isBetween) {
185
					// just draw the line :)
186
					g.DrawLine(BrushRegistry.GetPen(isBetweenSelected ? selectedFoldLine.Color : foldLineColor.Color),
187
					           xPos,
188
					           drawingRectangle.Top,
189
					           xPos,
190
					           drawingRectangle.Bottom);
191
				}
192
			}
193
		}
194
		
195
		public override void HandleMouseMove(Point mousepos, MouseButtons mouseButtons)
196
		{
197
			bool  showFolding  = textArea.Document.TextEditorProperties.EnableFolding;
198
			int   physicalLine = + (int)((mousepos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight);
199
			int   realline     = textArea.Document.GetFirstLogicalLine(physicalLine);
200
			
201
			if (!showFolding || realline < 0 || realline + 1 >= textArea.Document.TotalNumberOfLines) {
202
				return;
203
			}
204
			
205
			List<FoldMarker> foldMarkers = textArea.Document.FoldingManager.GetFoldingsWithStart(realline);
206
			int oldSelection = selectedFoldLine;
207
			if (foldMarkers.Count > 0) {
208
				selectedFoldLine = realline;
209
			} else {
210
				selectedFoldLine = -1;
211
			}
212
			if (oldSelection != selectedFoldLine) {
213
				textArea.Refresh(this);
214
			}
215
		}
216
		
217
		public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons)
218
		{
219
			bool  showFolding  = textArea.Document.TextEditorProperties.EnableFolding;
220
			int   physicalLine = + (int)((mousepos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight);
221
			int   realline     = textArea.Document.GetFirstLogicalLine(physicalLine);
222
			
223
			// focus the textarea if the user clicks on the line number view
224
			textArea.Focus();
225
			
226
			if (!showFolding || realline < 0 || realline + 1 >= textArea.Document.TotalNumberOfLines) {
227
				return;
228
			}
229
			
230
			List<FoldMarker> foldMarkers = textArea.Document.FoldingManager.GetFoldingsWithStart(realline);
231
			foreach (FoldMarker fm in foldMarkers) {
232
				fm.IsFolded = !fm.IsFolded;
233
			}
234
			textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty);
235
		}
236
		
237
		public override void HandleMouseLeave(EventArgs e)
238
		{
239
			if (selectedFoldLine != -1) {
240
				selectedFoldLine = -1;
241
				textArea.Refresh(this);
242
			}
243
		}
244
		
245
		#region Drawing functions
246
		void DrawFoldMarker(Graphics g, RectangleF rectangle, bool isOpened, bool isSelected)
247
		{
248
			HighlightColor foldMarkerColor = textArea.Document.HighlightingStrategy.GetColorFor("FoldMarker");
249
			HighlightColor foldLineColor   = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
250
			HighlightColor selectedFoldLine = textArea.Document.HighlightingStrategy.GetColorFor("SelectedFoldLine");
251
			
252
			Rectangle intRect = new Rectangle((int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height);
253
			g.FillRectangle(BrushRegistry.GetBrush(foldMarkerColor.BackgroundColor), intRect);
254
			g.DrawRectangle(BrushRegistry.GetPen(isSelected ? selectedFoldLine.Color : foldMarkerColor.Color), intRect);
255
			
256
			int space  = (int)Math.Round(((double)rectangle.Height) / 8d) + 1;
257
			int mid    = intRect.Height / 2 + intRect.Height % 2;
258
			
259
			g.DrawLine(BrushRegistry.GetPen(foldLineColor.BackgroundColor),
260
			           rectangle.X + space,
261
			           rectangle.Y + mid,
262
			           rectangle.X + rectangle.Width - space,
263
			           rectangle.Y + mid);
264
			
265
			if (!isOpened) {
266
				g.DrawLine(BrushRegistry.GetPen(foldLineColor.BackgroundColor),
267
				           rectangle.X + mid,
268
				           rectangle.Y + space,
269
				           rectangle.X + mid,
270
				           rectangle.Y + rectangle.Height - space);
271
			}
272
		}
273
		#endregion
274
	}
275
}