Mono.TextEditor.TextViewMargin.Draw C# (CSharp) Method

Draw() protected method

protected Draw ( Cairo cr, Cairo area, Mono.TextEditor.DocumentLine line, int lineNr, double x, double y, double _lineHeight ) : void
cr Cairo
area Cairo
line Mono.TextEditor.DocumentLine
lineNr int
x double
y double
_lineHeight double
return void
		protected internal override void Draw (Cairo.Context cr, Cairo.Rectangle area, DocumentLine line, int lineNr, double x, double y, double _lineHeight)
		{
//			double xStart = System.Math.Max (area.X, XOffset);
//			xStart = System.Math.Max (0, xStart);
			var correctedXOffset = System.Math.Floor (XOffset) - 1;
			var lineArea = new Cairo.Rectangle (correctedXOffset, y, textEditor.Allocation.Width - correctedXOffset, _lineHeight);
			double position = x - textEditor.HAdjustment.Value + TextStartPosition;
			defaultBgColor = Document.ReadOnly ? ColorStyle.BackgroundReadOnly.Color : ColorStyle.PlainText.Background;
			var startLineNr = lineNr;
			// Draw the default back color for the whole line. Colors other than the default
			// background will be drawn when rendering the text chunks.
			if (BackgroundRenderer == null)
				DrawRectangleWithRuler (cr, x, lineArea, defaultBgColor, true);
			bool isSelectionDrawn = false;

			// Check if line is beyond the document length
			if (line == null) {
				DrawScrollShadow (cr, x, y, _lineHeight);

				var marker = Document.GetExtendingTextMarker (lineNr);
				if (marker != null)
					marker.Draw (textEditor, cr, lineNr, lineArea);
				return;
			}
			
			IEnumerable<FoldSegment> foldings = Document.GetStartFoldings (line);
			int offset = line.Offset;
			int caretOffset = Caret.Offset;
			bool isEolFolded = false;
			restart:
			int logicalRulerColumn = line.GetLogicalColumn (textEditor.GetTextEditorData (), textEditor.Options.RulerColumn);

			if ((HighlightCaretLine || textEditor.GetTextEditorData ().HighlightCaretLine) && Caret.Line == lineNr)
				DrawCaretLineMarker (cr, x, y, TextStartPosition, _lineHeight);

			foreach (FoldSegment folding in foldings) {
				int foldOffset = folding.StartLine.Offset + folding.Column - 1;
				if (foldOffset < offset)
					continue;

				if (folding.IsFolded) {
					
					DrawLinePart (cr, line, lineNr, logicalRulerColumn, offset, foldOffset - offset, ref position, ref isSelectionDrawn, y, area.X + area.Width, _lineHeight);
					
					offset = folding.EndLine.Offset + folding.EndColumn - 1;
					markerLayout.SetText (folding.Description);
					int width, height;
					markerLayout.GetPixelSize (out width, out height);
					
					bool isFoldingSelected = !this.HideSelection && textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (folding.Segment);
					double pixelX = 0.5 + System.Math.Floor (position);
					double foldXMargin = foldMarkerXMargin * textEditor.Options.Zoom;
					double pixelWidth = System.Math.Floor (position + width - pixelX + foldXMargin * 2);
					var foldingRectangle = new Cairo.Rectangle (
						pixelX, 
						y, 
						pixelWidth, 
						this.LineHeight);

					if (BackgroundRenderer == null && isFoldingSelected) {
						cr.SetSourceColor (SelectionColor.Background);
						cr.Rectangle (foldingRectangle);
						cr.Fill ();
					}

					if (isFoldingSelected && SelectionColor.TransparentForeground) {
						cr.SetSourceColor (ColorStyle.CollapsedText.Foreground);
					} else {
						cr.SetSourceColor (isFoldingSelected ? SelectionColor.Foreground : ColorStyle.CollapsedText.Foreground);
					}
					var boundingRectangleHeight = foldingRectangle.Height - 1;
					var boundingRectangleY = System.Math.Floor (foldingRectangle.Y + (foldingRectangle.Height - boundingRectangleHeight) / 2);
					RoundedRectangle (cr,
					                 System.Math.Floor (foldingRectangle.X) + 0.5,
					                 boundingRectangleY + 0.5,
					                 System.Math.Floor (foldingRectangle.Width - cr.LineWidth),
					                 System.Math.Floor (boundingRectangleHeight - cr.LineWidth),
					                 LineHeight / 8, CairoCorners.All, false);
					cr.Stroke ();
					
					cr.Save ();
					cr.Translate (
						position + foldXMargin,
						System.Math.Floor (boundingRectangleY + System.Math.Max (0, boundingRectangleHeight - height) / 2));
					cr.ShowLayout (markerLayout);
					cr.Restore ();

					if (caretOffset == foldOffset && !string.IsNullOrEmpty (folding.Description)) {
						var cx = (int)position;
						SetVisibleCaretPosition (cx, y, cx, y);
					}
					position += foldingRectangle.Width;
					if (caretOffset == foldOffset + folding.Length && !string.IsNullOrEmpty (folding.Description)) {
						var cx = (int)position;
						SetVisibleCaretPosition (cx, y, cx, y);
					}

					if (folding.EndLine != line) {
						line = folding.EndLine;
						lineNr = line.LineNumber;
						foldings = Document.GetStartFoldings (line);
						isEolFolded = line.Length <= folding.EndColumn;
						goto restart;
					}
					isEolFolded = line.Length <= folding.EndColumn;
				}
			}
			
			// Draw remaining line - must be called for empty line parts as well because the caret may be at this positon
			// and the caret position is calculated in DrawLinePart.
			if (line.EndOffsetIncludingDelimiter - offset >= 0) {
				DrawLinePart (cr, line, lineNr, logicalRulerColumn, offset, line.Offset + line.Length - offset, ref position, ref isSelectionDrawn, y, area.X + area.Width, _lineHeight);
			}

			bool isEolSelected = 
				!this.HideSelection && 
				textEditor.IsSomethingSelected && 
				textEditor.SelectionMode == SelectionMode.Normal && 
				textEditor.MainSelection.ContainsLine (lineNr) &&
				textEditor.MainSelection.Contains (lineNr + 1, 1);

			var lx = (int)position;
			lineArea = new Cairo.Rectangle (lx,
				lineArea.Y,
				textEditor.Allocation.Width - lx,
				lineArea.Height);

			if (textEditor.SelectionMode == SelectionMode.Block && textEditor.IsSomethingSelected && textEditor.SelectionRange.Contains (line.Offset + line.Length)) {
				DocumentLocation start = textEditor.MainSelection.Anchor;
				DocumentLocation end = textEditor.MainSelection.Lead;
				DocumentLocation visStart = textEditor.LogicalToVisualLocation (start);
				DocumentLocation visEnd = textEditor.LogicalToVisualLocation (end);
				
				double x1 = this.ColumnToX (line, visStart.Column);
				double x2 = this.ColumnToX (line, visEnd.Column);
				if (x1 > x2) {
					var tmp = x1;
					x1 = x2;
					x2 = tmp;
				}
				x1 += correctedXOffset - textEditor.HAdjustment.Value;
				x2 += correctedXOffset - textEditor.HAdjustment.Value;

				if (x2 > lineArea.X && BackgroundRenderer == null)  {
					if (x1 - lineArea.X > 0) {
						DrawRectangleWithRuler (cr, x, new Cairo.Rectangle (lineArea.X, lineArea.Y, x1 - lineArea.X, lineArea.Height), defaultBgColor, false);
						lineArea = new Cairo.Rectangle (x1, lineArea.Y, lineArea.Width, lineArea.Height);
					}
					DrawRectangleWithRuler (cr, x, new Cairo.Rectangle (lineArea.X, lineArea.Y, x2 - lineArea.X, lineArea.Height), this.SelectionColor.Background, false);
					lineArea = new Cairo.Rectangle (x2, lineArea.Y, textEditor.Allocation.Width - lineArea.X, lineArea.Height);
				}
			}
			LayoutWrapper wrapper = null;
			if (!isSelectionDrawn && BackgroundRenderer == null) {
				if (isEolSelected) {
					// prevent "gaps" in the selection drawing ('fuzzy' lines problem)
					wrapper = GetLayout (line);
					if (lineNr == textEditor.MainSelection.Start.Line && line.Length == 0 && textEditor.MainSelection.Start.Column > 1) {
						using (var vwrapper = GetVirtualSpaceLayout (line, textEditor.MainSelection.Start)) {
							lineArea = new Cairo.Rectangle (
								lineArea.X + vwrapper.Width,
								lineArea.Y + System.Math.Max (0, wrapper.Height - LineHeight),
								textEditor.Allocation.Width - (lineArea.X + vwrapper.Width),
								LineHeight
							);
						}
					} else  {
						var eolStartX = System.Math.Floor (position);
						lineArea = new Cairo.Rectangle (
							eolStartX,
							lineArea.Y + System.Math.Max (0, wrapper.Height - LineHeight),
							textEditor.Allocation.Width - eolStartX,
							LineHeight);
					}
					if (lineNr != textEditor.MainSelection.End.Line)
						DrawRectangleWithRuler (cr, x, lineArea, this.SelectionColor.Background, false);
					if (line.Length == 0)
						DrawIndent (cr, wrapper, line, lx, y);
				} else if (!(HighlightCaretLine || textEditor.GetTextEditorData ().HighlightCaretLine) || Caret.Line != lineNr && Caret.Line != startLineNr) {
					wrapper = GetLayout (line);
					if (wrapper.EolSpanStack != null) {
						foreach (var span in wrapper.EolSpanStack) {
							var spanStyle = textEditor.ColorStyle.GetChunkStyle (span.Color);
							if (spanStyle == null)
								continue;
							if (!spanStyle.TransparentBackground && GetPixel (ColorStyle.PlainText.Background) != GetPixel (spanStyle.Background)) {
								DrawRectangleWithRuler (cr, x, lineArea, spanStyle.Background, false);
								break;
							}
						}
					}
				} else {
					double xPos = position;
					DrawCaretLineMarker (cr, xPos, y, lineArea.X + lineArea.Width - xPos, _lineHeight);
				}
			}
			
			if (textEditor.Options.ShowWhitespaces != ShowWhitespaces.Never) {
				switch (textEditor.Options.ShowWhitespaces) {
				case ShowWhitespaces.Selection:
					if (!isEolFolded && isEolSelected)
					if (!(BackgroundRenderer != null && textEditor.Options.ShowWhitespaces == ShowWhitespaces.Selection))
					if (textEditor.MainSelection.Contains (lineNr, 2 + line.Length) &&
					    !(lineNr == Caret.Line && Caret.Column > 1 && textEditor.MainSelection.Anchor.Line < textEditor.MainSelection.Lead.Line) &&
					    textEditor.MainSelection.Anchor.Line != textEditor.MainSelection.Lead.Line)
						goto case ShowWhitespaces.Always;
					break;
				case ShowWhitespaces.Always:
					if (wrapper == null)
						wrapper = GetLayout (line);
					DrawEolMarker (cr, line, isEolSelected, position, y + System.Math.Max (0, wrapper.Height - LineHeight));
					break;
				}
			}

			var extendingMarker = Document.GetExtendingTextMarker (lineNr);
			if (extendingMarker != null)
				extendingMarker.Draw (textEditor, cr, lineNr, lineArea);

			if (BackgroundRenderer == null) {
				var metrics = new EndOfLineMetrics {
					LineSegment = line,
					TextRenderEndPosition = TextStartPosition + position,
					LineHeight = _lineHeight,
					LineYRenderStartPosition = y
				};
				foreach (var marker in line.Markers) {
					marker.DrawAfterEol (textEditor, cr, metrics);
				}
			}

			lastLineRenderWidth = position;
			DrawScrollShadow (cr, x, y, _lineHeight);
			if (wrapper != null && wrapper.IsUncached)
				wrapper.Dispose ();
		}