⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textareapainter.cs

📁 c#精彩编程百例(源代码)
💻 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 + -