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

📄 caret.cs

📁 Fireball.CodeEditor is an source code editor control derived from the best compona SyntaxBox Control
💻 CS
字号:
//ORIGINAL LGPL SOURCE CODE FINDED ON COMPONA LGPL SOURCE CODE

using System;
using System.Diagnostics;
using Fireball.Syntax;

namespace Fireball.Windows.Forms.CodeEditor
{
	/// <summary>
	/// Caret class used by the SyntaxBoxControl
	/// </summary>
	public sealed class Caret
	{
		/// <summary>
		/// Event fired when the carets position has changed.
		/// </summary>
		public event EventHandler Change = null;

		#region General Declarations

		// X Position of the caret (in logical units (eg. 1 tab = 5 chars)
		private int OldLogicalXPos = 0;

		/// <summary>
		/// The Position of the caret in Chars (Column and Row index)
		/// </summary>
		private TextPoint _Position;

		/// <summary>
		/// Used by the painter to determine if the caret should be rendered or not
		/// </summary>
		public bool Blink;

		// to what control does the caret belong??
		private EditViewControl Control;

		#endregion

		#region Constructor(s)

		/// <summary>
		/// Caret constructor
		/// </summary>
		/// <param name="control">The control that will use the caret</param>
		public Caret(EditViewControl control)
		{
			this.Position = new TextPoint(0, 0);
			Control = control;
		}

		#endregion

		#region Helpers

		private void RememberXPos()
		{
			OldLogicalXPos = LogicalPosition.X;
		}

		/// <summary>
		/// Confines the caret to a valid position within the active document
		/// </summary>
		public void CropPosition()
		{
			if (this.Position.X < 0)
				this.Position.X = 0;

			if (this.Position.Y >= Control.Document.Count)
				this.Position.Y = Control.Document.Count - 1;

			if (this.Position.Y < 0)
				this.Position.Y = 0;

			Row xtr = CurrentRow;

			if (this.Position.X > xtr.Text.Length && !Control.VirtualWhitespace)
				this.Position.X = xtr.Text.Length;
		}

		#endregion

		#region Movement Methods

		/// <summary>
		/// Moves the caret right one step.
		/// if the caret is placed at the last column of a row the caret will move down one row and be placed at the first column of that row.
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveRight(bool Select)
		{
			this.CropPosition();
			this.Position.X ++;

			if (this.CurrentRow.IsCollapsed)
			{
				if (this.Position.X > this.CurrentRow.Expansion_EndChar)
				{
					this.Position.Y = this.CurrentRow.Expansion_EndRow.Index;
					this.Position.X = this.CurrentRow.Expansion_EndRow.Expansion_StartChar;
					this.CropPosition();
				}
				RememberXPos();
				CaretMoved(Select);

			}
			else
			{
				Row xtr = CurrentRow;
				if (this.Position.X > xtr.Text.Length && !Control.VirtualWhitespace)
				{
					if (this.Position.Y < Control.Document.Count - 1)
					{
						this.MoveDown(Select);
						this.Position.X = 0;
						//this.Position.Y ++;
						this.CropPosition();
					}
					else
						this.CropPosition();
				}
				RememberXPos();
				CaretMoved(Select);
			}
		}

		/// <summary>
		/// Moves the caret up one row.
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveUp(bool Select)
		{
			this.CropPosition();
			int x = OldLogicalXPos;
			//error here
			
				if (this.CurrentRow != null && this.CurrentRow.PrevVisibleRow != null)
				{
					this.Position.Y = this.CurrentRow.PrevVisibleRow.Index;
					if (this.CurrentRow.IsCollapsed)
					{
						x = 0;
					}
				}
	
			 
				this.CropPosition();
				this.LogicalPosition = new TextPoint(x, this.Position.Y);
				this.CropPosition();
				CaretMoved(Select);
			 
		}

		/// <summary>
		/// Moves the caret up x rows
		/// </summary>
		/// <param name="rows">Number of rows the caret should be moved up</param>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
        public void MoveUp(int rows, bool Select)
        {
            this.CropPosition();
            int x = OldLogicalXPos;
            //try
            //{
            int pos = this.CurrentRow.VisibleIndex;
            pos -= rows;
            if (pos < 0)
                pos = 0;
            Row r = this.Control.Document.VisibleRows[pos];
            pos = r.Index;


            this.Position.Y = pos;

            //				for (int i=0;i<rows;i++)
            //				{
            //					this.Position.Y =  this.CurrentRow.PrevVisibleRow.Index;
            //				}
            if (this.CurrentRow.IsCollapsed)
            {
                x = 0;
            }
            //}
            //catch
            //{
            //}
            this.CropPosition();
            this.LogicalPosition = new TextPoint(x, this.Position.Y);
            this.CropPosition();
            CaretMoved(Select);
        }

		/// <summary>
		/// Moves the caret down x rows.
		/// </summary>
		/// <param name="rows">The number of rows the caret should be moved down</param>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
        public void MoveDown(int rows, bool Select)
        {
            int x = OldLogicalXPos;
            this.CropPosition();
            //this.Position.Y +=rows;
            try
            {
                int pos = this.CurrentRow.VisibleIndex;
                pos += rows;
                if (pos > this.Control.Document.VisibleRows.Count - 1)
                    pos = this.Control.Document.VisibleRows.Count - 1;

                Row r = this.Control.Document.VisibleRows[pos];
                pos = r.Index;
                this.Position.Y = pos;

                //				for (int i=0;i<rows;i++)
                //				{
                //					this.Position.Y =  this.CurrentRow.NextVisibleRow.Index;
                //					
                //				}
                if (this.CurrentRow.IsCollapsed)
                {
                    x = 0;
                }
            }
            //catch
            //{
            //}
            finally
            {
                this.CropPosition();
                this.LogicalPosition = new TextPoint(x, this.Position.Y);
                this.CropPosition();
                CaretMoved(Select);
            }
        }


		/// <summary>
		/// Moves the caret down one row.
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
        public void MoveDown(bool Select)
        {
            this.CropPosition();
            int x = OldLogicalXPos;
            //error here


            Row r = this.CurrentRow;
            Row r2 = r.NextVisibleRow;

            if (r2 != null)
            {
                this.Position.Y = r2.Index;
                if (this.CurrentRow.IsCollapsed)
                {
                    x = 0;
                }
            }

            this.CropPosition();
            this.LogicalPosition = new TextPoint(x, this.Position.Y);
            this.CropPosition();
            CaretMoved(Select);
        }

		/// <summary>
		/// Moves the caret left one step.
		/// if the caret is placed at the first column the caret will be moved up one line and placed at the last column of the row.
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveLeft(bool Select)
		{
			this.CropPosition();
			this.Position.X --;

			if (this.CurrentRow.IsCollapsedEndPart)
			{
				if (this.Position.X < this.CurrentRow.Expansion_StartChar)
				{
					if (this.CurrentRow.Expansion_StartRow.Index == -1)
						Debugger.Break();
					this.Position.Y = this.CurrentRow.Expansion_StartRow.Index;
					this.Position.X = this.CurrentRow.Expansion_StartRow.Expansion_EndChar;
					this.CropPosition();
				}
				RememberXPos();
				CaretMoved(Select);

			}
			else
			{
				if (this.Position.X < 0)
				{
					if (this.Position.Y > 0)
					{
						this.MoveUp(Select);
						this.CropPosition();
						Row xtr = CurrentRow;
						this.Position.X = xtr.Text.Length;
						if (this.CurrentRow.IsCollapsed)
						{
							this.Position.Y = this.CurrentRow.Expansion_EndRow.Index;
							this.Position.X = this.CurrentRow.Text.Length;
						}
					}
					else
						this.CropPosition();


				}
				RememberXPos();
				CaretMoved(Select);
			}
		}


		/// <summary>
		/// Moves the caret to the first non whitespace column at the active row
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveHome(bool Select)
		{
			this.CropPosition();
			if (this.CurrentRow.IsCollapsedEndPart)
			{
				this.Position.Y = this.CurrentRow.Expansion_StartRow.Index;
				this.MoveHome(Select);
			}
			else
			{
				int i = CurrentRow.GetLeadingWhitespace().Length;
				if (this.Position.X == i)
				{
					this.Position.X = 0;
				}
				else
				{
					this.Position.X = i;
				}
				RememberXPos();
				CaretMoved(Select);
			}
		}

		/// <summary>
		/// Moves the caret to the end of a row ignoring any whitespace characters at the end of the row
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveEnd(bool Select)
		{
			if (this.CurrentRow.IsCollapsed)
			{
				this.Position.Y = this.CurrentRow.Expansion_EndRow.Index;
				this.MoveEnd(Select);
			}
			else
			{
				this.CropPosition();
				Row xtr = CurrentRow;
				this.Position.X = xtr.Text.Length;
				RememberXPos();
				CaretMoved(Select);
			}
		}

		public void CaretMoved(bool Select)
		{
			Control.ScrollIntoView();
			if (!Select)
				Control.Selection.ClearSelection();
			else
				Control.Selection.MakeSelection();
		}

		/// <summary>
		/// Moves the caret to the first column of the active row
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveAbsoluteHome(bool Select)
		{
			this.Position.X = 0;
			this.Position.Y = 0;
			RememberXPos();
			CaretMoved(Select);
		}

		/// <summary>
		/// Moves the caret to the absolute end of the active row
		/// </summary>
		/// <param name="Select">True if a selection should be created from the current caret pos to the new pos</param>
		public void MoveAbsoluteEnd(bool Select)
		{
			this.Position.X = Control.Document[Control.Document.Count - 1].Text.Length;
			;
			this.Position.Y = Control.Document.Count - 1;
			RememberXPos();
			CaretMoved(Select);
		}

		#endregion

		#region Get Related info from Caret Position

		/// <summary>
		/// Gets the word that the caret is placed on.
		/// This only applies if the active row is fully parsed.
		/// </summary>
		/// <returns>a Word object from the active row</returns>
		public Word CurrentWord
		{
			get { return this.Control.Document.GetWordFromPos(this.Position); }
		}

		/// <summary>
		/// Gets the word that the caret is placed on.
		/// This only applies if the active row is fully parsed.
		/// </summary>
		/// <returns>a Word object from the active row</returns>
		public Segment CurrentSegment()
		{
			return this.Control.Document.GetSegmentFromPos(this.Position);
		}

		/// <summary>
		/// Returns the row that the caret is placed on
		/// </summary>
		/// <returns>a Row object from the active document</returns>
		public Row CurrentRow
		{
			get { return Control.Document[this.Position.Y]; }
		}

		#endregion

		#region Set Position Methods/Props

		/// <summary>
		/// Sets the position of the caret
		/// </summary>
		/// <param name="pos">Point containing the new x and y positions</param>
		public void SetPos(TextPoint pos)
		{
			this.Position = pos;
			RememberXPos();
		}

		/// <summary>
		/// Gets or Sets the Logical position of the caret.
		/// </summary>
		public TextPoint LogicalPosition
		{
			get
			{
				if (this.Position.X < 0)
					return new TextPoint(0, this.Position.Y);

				Row xtr = this.CurrentRow;
				int x = 0;
				if (xtr == null)
					return new TextPoint(0, 0);

				int max = xtr.Text.Length;

				int Padd = Math.Max(this.Position.X - xtr.Text.Length, 0);
				string PaddStr = new String(' ', Padd);
				string TotStr = xtr.Text + PaddStr;

				foreach (char c in TotStr.ToCharArray(0, this.Position.X))
				{
					if (c == '\t')
					{
						x += Control.TabSize - (x%Control.TabSize);
					}
					else
					{
						x++;
					}
				}
				return new TextPoint(x, this.Position.Y);
			}
			set
			{
				Row xtr = this.CurrentRow;
				int x = 0;
				int xx = 0;
				if (value.X > 0)
				{
					char[] chars = xtr.Text.ToCharArray();

					int i = 0;

					while (x < value.X)
					{
						char c;
						if (i < chars.Length)
							c = chars[i];
						else
							c = ' ';
						xx++;
						if (c == '\t')
						{
							x += Control.TabSize - (x%Control.TabSize);
						}
						else
						{
							x++;
						}
						i++;
					}
				}


				this.Position.Y = value.Y;
				this.Position.X = xx;
			}


		}

		#endregion

		/// <summary>
		/// Gets or Sets the position of the caret.
		/// </summary>
		public TextPoint Position
		{
			get { return _Position; }
			set
			{
				_Position = value;
				_Position.Change += new EventHandler(this.PositionChange);
				OnChange();
			}
		}

		private void PositionChange(object s, EventArgs e)
		{
			OnChange();
		}

		private void OnChange()
		{
			if (Change != null)
				Change(this, null);

		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -