📄 textareapainter.cs
字号:
// SharpTextArea.cs
// Copyright (C) 2000 Mike Krueger
// Copyright (C) 2000 Andrea Paatz
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections;
using System.IO;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Drawing.Text;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.InteropServices;
using System.Xml;
using SharpDevelop.Gui;
using SharpDevelop.Tool.Data;
using SharpDevelop.Internal.Text;
namespace SharpDevelop.Gui.Edit.Text {
public delegate void ToolTipEvent(int xpos, int ypos);
/// <summary>
/// To add a own painter, make this delagte.
/// </summary>
public delegate void LinePainter(Graphics g, int line, RectangleF rect, PointF pos);
/// <summary>
/// This class paints the textarea.
/// </summary>
public class TextAreaPainter : UserControl
{
TextBuffer buffer;
MainWindow mainwindow;
PrintDocument printdocument;
Selection selection = new Selection();
Caret caret = null;
Highlight highlight = null;
BracketHighlighter brackethighlighter = null;
public ToolTip ToolTip = new ToolTip();
public event ToolTipEvent ToolTipEvent;
public event LinePainter LinePainter;
float fontWidth;
float fontHeight;
public PrintDocument PrintDocument {
get { // TODO
return printdocument;
}
}
public Highlight Highlight {
get {
return highlight;
}
set {
highlight = value;
}
}
public Selection Selection {
get {
return selection;
}
}
public Caret Caret {
get {
return caret;
}
}
public TextBuffer Buffer {
get {
return buffer;
}
}
public BufferOptions Options {
get {
return buffer.Options;
}
}
public float FontWidth {
get {
return fontWidth;
}
}
public new float FontHeight {
get {
return fontHeight;
}
}
public void OnToolTipEvent(int xpos, int ypos)
{
if (ToolTipEvent != null)
ToolTipEvent(xpos, ypos);
}
/// <summary>
/// This Method paints the characters on the screen
/// </summary>
void PaintLine(Graphics g, int line, RectangleF rect, PointF pos)
{
int xpos = (int)(pos.X / fontWidth);
if (line >= Buffer.Length) {
if (Options.ShowInvalidLines)
g.DrawString("~", Buffer.Syntax.InvalidLineColor.Font, new SolidBrush(Buffer.Syntax.InvalidLineColor.Color), pos);
} else {
TextLine words = Buffer[line];
if (words != null)
for (int i = 0; i < words.Length; ++i) {
switch (words[i].Type) {
case TextWordType.Space:
if (Options.ShowSpaces && pos.X < rect.X + rect.Width) {
g.DrawString("\u00B7", Buffer.Syntax.SpaceMarkerColor.Font, new SolidBrush(Buffer.Syntax.SpaceMarkerColor.Color), xpos * fontWidth, pos.Y);
}
++xpos;
break;
case TextWordType.Tab:
if (Options.ShowTabs && pos.X < rect.X + rect.Width) {
g.DrawString("\u00BB", Buffer.Syntax.SpaceMarkerColor.Font, new SolidBrush(Buffer.Syntax.SpaceMarkerColor.Color), xpos * fontWidth, pos.Y);
}
xpos += Options.TabIndent;
break;
case TextWordType.Word:
g.DrawString(words[i].Word, words[i].Font, new SolidBrush(words[i].Color), xpos * fontWidth, pos.Y);
xpos += words[i].Word.Length;
break;
}
}
if (Options.ShowEOLMarkers && pos.X < rect.X + rect.Width) {
g.DrawString("\u00B6", Buffer.Syntax.EolMarkerColor.Font, new SolidBrush(Buffer.Syntax.EolMarkerColor.Color), xpos * fontWidth, pos.Y);
}
}
}
void PaintCursorLine(object sender, PaintEventArgs pe)
{
if (Options.LineViewerStyle == LineViewerStyle.FullRow) {
Rectangle rectangle = new Rectangle(0, (int)(Caret.PhysicalCaretPos.Y * fontHeight), Width, (int)fontHeight);
pe.Graphics.FillRectangle(new SolidBrush(Buffer.Syntax.CaretmarkerColor.Color), rectangle);
}
}
void PaintBracketHighlight(object sender, PaintEventArgs pe)
{
if (highlight != null) {
Graphics g = pe.Graphics;
if (Buffer[highlight.Begin.Y].Visible) {
Point p1 = Caret.GetPhysicalPos(highlight.Begin);
Point p2 = Caret.GetPhysicalPos(highlight.End);
Rectangle r = new Rectangle((int)(p1.X * fontWidth) + 3,
(int)(p1.Y * fontHeight) + 1,
(int)((p2.X - p1.X + 1) * fontWidth) - 1,
(int)((p2.Y - p1.Y + 1) * fontHeight) - 1);
g.DrawRectangle(new Pen(new SolidBrush(Buffer.Syntax.HRulerColor.Color)), r);
}
}
}
void PaintHRuler(object sender, PaintEventArgs pe)
{
if (Options.ShowHRuler) {
Graphics g = pe.Graphics;
int xpos = (int)(Options.HRulerRrow * fontWidth);
g.DrawLine(new Pen(Buffer.Syntax.HRulerColor.Color), xpos, pe.ClipRectangle.Y, xpos, pe.ClipRectangle.Y + pe.ClipRectangle.Height);
}
}
void PaintCaret(Graphics g)
{
if (caret.Visible) {
int ypos = (int)(caret.PhysicalCaretPos.Y * fontHeight);
int xpos = (int)(caret.PhysicalCaretPos.X * fontWidth);
if (caret.InsertMode) {
g.DrawLine(new Pen(Buffer.Syntax.CaretColor.Color), new Point(xpos + 2, ypos),
new Point(xpos + 2, ypos + (int)fontHeight - 1)
);
g.DrawLine(new Pen(Buffer.Syntax.CaretColor.Color), new Point(xpos + 3, ypos),
new Point(xpos + 3, ypos + (int)fontHeight - 1)
);
} else {
g.DrawLine(
new Pen(Buffer.Syntax.CaretColor.Color),
new Point(xpos + 2, ypos + (int)fontHeight - 4),
new Point(xpos + (int)fontWidth + 2, ypos + (int)fontHeight - 4)
);
g.DrawLine(
new Pen(Buffer.Syntax.CaretColor.Color),
new Point(xpos + 2, ypos + (int)fontHeight - 3),
new Point(xpos + (int)fontWidth + 2, ypos + (int)fontHeight - 3)
);
}
}
}
/////////// !! HACK WARNING !!
// I have to do this, because the Focused property seem not to work
// correctly, I need to know if this control has the focus, because I want
// to draw the caret only in the focused window, if the Focused property works
// remove this hack and change TextAreaControl.CaretThreadMethod so that it uses
// the Focused property, try this in every new version of .NET I HATE HACKS !!!
//
// Mike
public bool IHaveTheFocus = false;
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
IHaveTheFocus = true;
}
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
IHaveTheFocus = false;
}
/////////// END HACK WARNING
protected override void OnPaint(PaintEventArgs pe)
{
Graphics drawTo = pe.Graphics;
Rectangle rectangle = pe.ClipRectangle;
if (Enabled) {
if (Options.UseAntiAliasFont) {
drawTo.CompositingQuality = CompositingQuality.AssumeLinear;
drawTo.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
drawTo.SmoothingMode = SmoothingMode.AntiAlias;
drawTo.InterpolationMode = InterpolationMode.High;
}
PaintCursorLine(null, pe);
PaintHRuler(null, pe);
Font textFont = FontContainer.DefaultFont;
drawTo.SmoothingMode = SmoothingMode.HighSpeed;
drawTo.InterpolationMode = InterpolationMode.Low;
int firstInvalid = (int)(rectangle.Y / fontHeight);
int lastInvalid = (int)((rectangle.Y + rectangle.Height - 1) / fontHeight);
int realline = buffer.Foldings.GetPhysicalLine(firstInvalid);
if (LinePainter != null)
for (int line = firstInvalid; line <= lastInvalid; ++line) {
while (realline < Buffer.Length && !Buffer[realline].Visible)
++realline;
LinePainter(drawTo, realline, (RectangleF)rectangle, new PointF(0, line * fontHeight));
++realline;
}
PaintBracketHighlight(null, pe);
PaintCaret(drawTo);
}
}
void PaintBookMarks(Graphics g, int line, RectangleF rect, PointF pos)
{
if (Buffer.Bookmark.IsMark(line)) {
Rectangle rectangle = new Rectangle(0, (int)pos.Y, Width, (int)fontHeight);
g.FillRectangle(new SolidBrush(Buffer.Syntax.BookmarkColor.Color), rectangle);
}
}
/// <summary>
/// This Method paints the background of a selected area
/// </summary>
void PaintSelectedArea(Graphics g, int line, RectangleF rect, PointF pos)
{
int r_Begin = int.MaxValue;
int r_End = 0;
if (!Selection.HasSomethingSelected || line >= Buffer.Length || line < Selection.RealStart.Y || line > Selection.RealEnd.Y)
return;
if (Selection.SelectionStart.Y != Selection.SelectionEnd.Y) {
if (line == Selection.RealStart.Y) {
r_Begin = Caret.GetPhysicalPos(Selection.RealStart).X;
r_End = Caret.GetPhysicalPos(new Point(Buffer[line].Text.Length + 1, line)).X;
} else
if (line == Selection.RealEnd.Y) {
r_Begin = 0;
r_End = Caret.GetPhysicalPos(Selection.RealEnd).X;
} else {
r_Begin = 0;
r_End = Caret.GetPhysicalPos(new Point(Buffer[line].Text.Length + 1, line)).X;
}
} else {
r_Begin = Caret.GetPhysicalPos(Selection.RealStart).X;
r_End = Caret.GetPhysicalPos(Selection.RealEnd).X;
}
// Draw the selection rectangle
if (r_End > 0) {
g.FillRectangle(new SolidBrush(Buffer.Syntax.SelectionColor.Color),
new Rectangle((int)(r_Begin * fontWidth) + 2,
(int)pos.Y,
(int)((r_End - r_Begin) * fontWidth) + 2,
(int)fontHeight + 1));
}
}
protected override void OnPaintBackground(PaintEventArgs pe)
{
Color color = Enabled ? Buffer.Syntax.BackgroundColor : SystemColors.InactiveBorder;
pe.Graphics.FillRectangle(new SolidBrush(color), pe.ClipRectangle);
}
public void CalculateFontSize()
{
Graphics g = CreateGraphics();
fontHeight = Buffer.Options.DefaultFont.GetHeight(g);
Console.WriteLine("Old width = " + fontWidth);
fontWidth = fontHeight / 1.831f;
Console.WriteLine("New width = " + fontWidth);
}
public TextAreaPainter(TextBuffer buffer, MainWindow mainwindow)
{
this.buffer = buffer;
this.mainwindow = mainwindow;
this.ToolTip = new ToolTip();
CalculateFontSize();
caret = new Caret(buffer);
brackethighlighter = new BracketHighlighter(this);
Cursor = Cursors.IBeam;
printdocument = new PrintDocument();
printdocument.BeginPrint += new PrintEventHandler(BeginPrint);
printdocument.PrintPage += new PrintPageEventHandler(PrintPage);
// Paint += new PaintEventHandler(PaintHRuler);
ResizeRedraw = false;
LinePainter += new LinePainter(PaintBookMarks);
LinePainter += new LinePainter(PaintSelectedArea);
LinePainter += new LinePainter(PaintLine);
}
int printedline = 0;
void BeginPrint(object sender, PrintEventArgs e)
{
printedline = 0;
}
void PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
float linesPerPage = 0;
float leftMargin = e.MarginBounds.Left;
linesPerPage = e.MarginBounds.Height / fontHeight - 1;
for (int line = 0; line < linesPerPage; ++line)
PaintLine(e.Graphics, printedline++, e.MarginBounds,new PointF((int)leftMargin, e.MarginBounds.Y + line * fontHeight));
g.DrawLine(new Pen(Color.Black), e.MarginBounds.Left, e.MarginBounds.Bottom + 2, e.MarginBounds.Right, e.MarginBounds.Bottom + 2);
g.DrawLine(new Pen(Color.Black), e.MarginBounds.Left, e.MarginBounds.Top - 2, e.MarginBounds.Right, e.MarginBounds.Top - 2);
string pagestr = "Page " + (int)(printedline / linesPerPage) + "/" + (int)(buffer.Length / linesPerPage + 1);
int width = (int)(g.MeasureString(pagestr, FontContainer.DefaultFont).Width + 5);
g.DrawString(pagestr, FontContainer.DefaultFont, new SolidBrush(Color.Black), e.MarginBounds.Right - width, e.MarginBounds.Bottom + 4);
e.HasMorePages = printedline < buffer.Length;
}
public void InvalidatePos(Point pos)
{
float width = fontWidth;
float y = pos.Y * fontHeight;
float x = pos.X * fontWidth;
Invalidate(new Rectangle((int)x + 2,
(int)y - 1,
(int)width + 1,
(int)FontHeight + 2));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -