/// <summary> /// Draws a single <see cref="LineNumberItem"/>. /// </summary> /// <param name="item"></param> /// <param name="graphics">The <see cref="Graphics"/> to draw on.</param> /// <param name="brush"></param> /// <param name="textFormat"></param> /// <param name="path">The <see cref="GraphicsPath"/> to update with the drawn data.</param> private void DrawLineNumber(LineNumberItem item, Graphics graphics, Brush brush, StringFormat textFormat, GraphicsPath path) { var text = _lineNumbersShowAsHexadecimal ? item.LineNumber.ToString("X") : _lineNumbersShowLeadingZeroes ? item.LineNumber.ToString(_lineNumbersFormat) : item.LineNumber.ToString(); var textSize = graphics.MeasureString(text, Font, new Point(0, 0), textFormat); var point = GetLineNumberDrawingStartPoint(item, textSize); // TextClipping var itemClipRectangle = new RectangleF(point, textSize.ToSize()); if (_lineNumbersClipByItemRectangle) { // If selected, the text will be clipped so that it doesn't spill out of its own LineNumberItem-area. // Only the part of the text inside the LineNumberItem.Rectangle should be visible, so intersect with the ItemRectangle // The SetClip method temporary restricts the drawing area of the control for whatever is drawn next. itemClipRectangle.Intersect(item.Rectangle); graphics.SetClip(itemClipRectangle); } // TextDrawing graphics.DrawString(text, Font, brush, point, textFormat); graphics.ResetClip(); // The GraphicsPath for the LineNumber is just a rectangle behind the text, to keep the paintingspeed high and avoid ugly artifacts. path.AddRectangle(itemClipRectangle); path.CloseFigure(); }
/// <summary> /// Draws a grid for the specified <see cref="LineNumberItem"/>. /// </summary> /// <param name="item"></param> /// <param name="graphics">The <see cref="Graphics"/> to draw on.</param> /// <param name="pen"></param> /// <param name="path">The <see cref="GraphicsPath"/> to update with the drawn data.</param> private void DrawGridLines(LineNumberItem item, Graphics graphics, Pen pen, GraphicsPath path) { graphics.DrawLine(pen, new PointF(0, item.Rectangle.Y), new PointF(Width, item.Rectangle.Y)); // Every item in a GraphicsPath is a closed figure, so instead of adding gridlines as lines, we'll add them // as rectangles that loop out of sight. Their height uses the zContentRectangle which is the maxsize of // the ParentRichTextBox's contents. // // Slight adjustment needed when the first item has a negative Y coordinate. // This explains the " - zLNIs(0).Rectangle.Y" (which adds the negative size to the height // to make sure the rectangle's bottompart stays out of sight) path.AddRectangle(new RectangleF(-_gridLinesThickness, item.Rectangle.Y, Width + _gridLinesThickness * 2, Height - item.Rectangle.Y + _gridLinesThickness)); path.CloseFigure(); }
/// <summary> /// Gets the point where the specified <see cref="LineNumberItem"/> should be drawn. /// The return value is based on <see cref="Alignment"/>, <paramref name="textSize"/>, and <paramref name="item.Rectangle"/>. /// </summary> /// <param name="item"></param> /// <param name="textSize"></param> /// <returns></returns> private PointF GetLineNumberDrawingStartPoint(LineNumberItem item, SizeF textSize) { if (_lineNumbersAlignment == ContentAlignment.TopLeft) { return(new PointF(item.Rectangle.Left + Padding.Left + _lineNumbersOffset.Width, item.Rectangle.Top + Padding.Top + _lineNumbersOffset.Height)); } if (_lineNumbersAlignment == ContentAlignment.MiddleLeft) { return(new PointF(item.Rectangle.Left + Padding.Left + _lineNumbersOffset.Width, item.Rectangle.Top + (item.Rectangle.Height / 2) + _lineNumbersOffset.Height - textSize.Height / 2)); } if (_lineNumbersAlignment == ContentAlignment.BottomLeft) { return(new PointF(item.Rectangle.Left + Padding.Left + _lineNumbersOffset.Width, item.Rectangle.Bottom - Padding.Bottom + 1 + _lineNumbersOffset.Height - textSize.Height)); } if (_lineNumbersAlignment == ContentAlignment.TopCenter) { return(new PointF(item.Rectangle.Width / 2 + _lineNumbersOffset.Width - textSize.Width / 2, item.Rectangle.Top + Padding.Top + _lineNumbersOffset.Height)); } if (_lineNumbersAlignment == ContentAlignment.MiddleCenter) { return(new PointF(item.Rectangle.Width / 2 + _lineNumbersOffset.Width - textSize.Width / 2, item.Rectangle.Top + (item.Rectangle.Height / 2) + _lineNumbersOffset.Height - textSize.Height / 2)); } if (_lineNumbersAlignment == ContentAlignment.BottomCenter) { return(new PointF(item.Rectangle.Width / 2 + _lineNumbersOffset.Width - textSize.Width / 2, item.Rectangle.Bottom - Padding.Bottom + 1 + _lineNumbersOffset.Height - textSize.Height)); } if (_lineNumbersAlignment == ContentAlignment.TopRight) { return(new PointF(item.Rectangle.Right - Padding.Right + _lineNumbersOffset.Width - textSize.Width, item.Rectangle.Top + Padding.Top + _lineNumbersOffset.Height)); } if (_lineNumbersAlignment == ContentAlignment.MiddleRight) { return(new PointF(item.Rectangle.Right - Padding.Right + _lineNumbersOffset.Width - textSize.Width, item.Rectangle.Top + (item.Rectangle.Height / 2) + _lineNumbersOffset.Height - textSize.Height / 2)); } if (_lineNumbersAlignment == ContentAlignment.BottomRight) { return(new PointF(item.Rectangle.Right - Padding.Right + _lineNumbersOffset.Width - textSize.Width, item.Rectangle.Bottom - Padding.Bottom + 1 + _lineNumbersOffset.Height - textSize.Height)); } return(new PointF(0, 0)); }
/// <summary> /// Draws a single <see cref="LineNumberItem"/>. /// </summary> /// <param name="item"></param> /// <param name="graphics">The <see cref="Graphics"/> to draw on.</param> /// <param name="brush"></param> /// <param name="textFormat"></param> /// <param name="path">The <see cref="GraphicsPath"/> to update with the drawn data.</param> private void DrawLineNumber(LineNumberItem item, Graphics graphics, Brush brush, StringFormat textFormat, GraphicsPath path) { var text = _lineNumbersShowAsHexadecimal ? item.LineNumber.ToString("X") : _lineNumbersShowLeadingZeroes ? item.LineNumber.ToString(_lineNumbersFormat) : item.LineNumber.ToString(); var textSize = graphics.MeasureString(text, Font, new Point(0, 0), textFormat); var point = GetLineNumberDrawingStartPoint(item, textSize); // TextClipping var itemClipRectangle = new RectangleF(point, textSize.ToSize()); if (_lineNumbersClipByItemRectangle) { // If selected, the text will be clipped so that it doesn't spill out of its own LineNumberItem-area. // Only the part of the text inside the LineNumberItem.Rectangle should be visible, so intersect with the ItemRectangle // The SetClip method temporary restricts the drawing area of the control for whatever is drawn next. itemClipRectangle.Intersect(item.Rectangle); graphics.SetClip(itemClipRectangle); } // TextDrawing graphics.DrawString(text, Font, brush, point, textFormat); graphics.ResetClip(); // The GraphicsPath for the LineNumber is just a rectangle behind the text, to keep the paintingspeed high and avoid ugly artifacts. path.AddRectangle(itemClipRectangle); path.CloseFigure(); }
/// <summary> /// Draws a grid for the specified <see cref="LineNumberItem"/>. /// </summary> /// <param name="item"></param> /// <param name="graphics">The <see cref="Graphics"/> to draw on.</param> /// <param name="pen"></param> /// <param name="path">The <see cref="GraphicsPath"/> to update with the drawn data.</param> private void DrawGridLines(LineNumberItem item, Graphics graphics, Pen pen, GraphicsPath path) { graphics.DrawLine(pen, new PointF(0, item.Rectangle.Y), new PointF(Width, item.Rectangle.Y)); // Every item in a GraphicsPath is a closed figure, so instead of adding gridlines as lines, we'll add them // as rectangles that loop out of sight. Their height uses the zContentRectangle which is the maxsize of // the ParentRichTextBox's contents. // // Slight adjustment needed when the first item has a negative Y coordinate. // This explains the " - zLNIs(0).Rectangle.Y" (which adds the negative size to the height // to make sure the rectangle's bottompart stays out of sight) path.AddRectangle(new RectangleF(-_gridLinesThickness, item.Rectangle.Y, Width + _gridLinesThickness*2, Height - item.Rectangle.Y + _gridLinesThickness)); path.CloseFigure(); }
/// <summary> /// Draws a gradient for the specified <see cref="LineNumberItem"/>. /// </summary> /// <param name="item"></param> /// <param name="graphics">The <see cref="Graphics"/> to draw on.</param> private void DrawGradient(LineNumberItem item, Graphics graphics) { using (var gradientBrush = new LinearGradientBrush(item.Rectangle, _gradientStarColor, _gradientEndColor, _gradientDirection)) graphics.FillRectangle(gradientBrush, item.Rectangle); }
/// <summary> /// Gets the point where the specified <see cref="LineNumberItem"/> should be drawn. /// The return value is based on <see cref="Alignment"/>, <paramref name="textSize"/>, and <paramref name="item.Rectangle"/>. /// </summary> /// <param name="item"></param> /// <param name="textSize"></param> /// <returns></returns> private PointF GetLineNumberDrawingStartPoint(LineNumberItem item, SizeF textSize) { if (_lineNumbersAlignment == ContentAlignment.TopLeft) return new PointF(item.Rectangle.Left + Padding.Left + _lineNumbersOffset.Width, item.Rectangle.Top + Padding.Top + _lineNumbersOffset.Height); if (_lineNumbersAlignment == ContentAlignment.MiddleLeft) return new PointF(item.Rectangle.Left + Padding.Left + _lineNumbersOffset.Width, item.Rectangle.Top + (item.Rectangle.Height / 2) + _lineNumbersOffset.Height - textSize.Height / 2); if (_lineNumbersAlignment == ContentAlignment.BottomLeft) return new PointF(item.Rectangle.Left + Padding.Left + _lineNumbersOffset.Width, item.Rectangle.Bottom - Padding.Bottom + 1 + _lineNumbersOffset.Height - textSize.Height); if (_lineNumbersAlignment == ContentAlignment.TopCenter) return new PointF(item.Rectangle.Width / 2 + _lineNumbersOffset.Width - textSize.Width / 2, item.Rectangle.Top + Padding.Top + _lineNumbersOffset.Height); if (_lineNumbersAlignment == ContentAlignment.MiddleCenter) return new PointF(item.Rectangle.Width / 2 + _lineNumbersOffset.Width - textSize.Width / 2, item.Rectangle.Top + (item.Rectangle.Height / 2) + _lineNumbersOffset.Height - textSize.Height / 2); if (_lineNumbersAlignment == ContentAlignment.BottomCenter) return new PointF(item.Rectangle.Width / 2 + _lineNumbersOffset.Width - textSize.Width / 2, item.Rectangle.Bottom - Padding.Bottom + 1 + _lineNumbersOffset.Height - textSize.Height); if (_lineNumbersAlignment == ContentAlignment.TopRight) return new PointF(item.Rectangle.Right - Padding.Right + _lineNumbersOffset.Width - textSize.Width, item.Rectangle.Top + Padding.Top + _lineNumbersOffset.Height); if (_lineNumbersAlignment == ContentAlignment.MiddleRight) return new PointF(item.Rectangle.Right - Padding.Right + _lineNumbersOffset.Width - textSize.Width, item.Rectangle.Top + (item.Rectangle.Height / 2) + _lineNumbersOffset.Height - textSize.Height / 2); if (_lineNumbersAlignment == ContentAlignment.BottomRight) return new PointF(item.Rectangle.Right - Padding.Right + _lineNumbersOffset.Width - textSize.Width, item.Rectangle.Bottom - Padding.Bottom + 1 + _lineNumbersOffset.Height - textSize.Height); return new PointF(0, 0); }
/// <summary> /// Draws a gradient for the specified <see cref="LineNumberItem"/>. /// </summary> /// <param name="item"></param> /// <param name="graphics">The <see cref="Graphics"/> to draw on.</param> private void DrawGradient(LineNumberItem item, Graphics graphics) { using (var gradientBrush = new LinearGradientBrush(item.Rectangle, _gradientStarColor, _gradientEndColor, _gradientDirection)) graphics.FillRectangle(gradientBrush, item.Rectangle); }