syntaxdocument.cs

来自「Fireball.CodeEditor is an source code ed」· CS 代码 · 共 1,880 行 · 第 1/3 页

CS
1,880
字号
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using Fireball.Syntax.SyntaxDocumentParsers;

namespace Fireball.Syntax
{
	/// <summary>
	/// 
	/// </summary>
	public class RowEventArgs : EventArgs
	{
		/// <summary>
		/// 
		/// </summary>
		/// <param name="row"></param>
		public RowEventArgs(Row row)
		{
			this.Row = row;
		}

		/// <summary>
		/// 
		/// </summary>
		public Row Row = null;
	}

	/// <summary>
	/// Parser event handler
	/// </summary>
	public delegate void ParserEventHandler(object sender, RowEventArgs e);

	/// <summary>
	/// 
	/// </summary>
	public delegate void RowEventHandler(object sender, RowEventArgs e);


	/// <summary>
	/// The SyntaxDocument is a component that is responsible for Parsing , Folding , Undo / Redo actions and various text actions.
	/// </summary>
	public class SyntaxDocument : Component, IEnumerable
	{
		#region General declarations

		/// <summary>
		/// List of rows that should be parsed
		/// </summary>
		public RowCollection ParseQueue = new RowCollection();

		/// <summary>
		/// 
		/// </summary>
		public RowCollection KeywordQueue = new RowCollection();

		public FormatRangeCollection FormatRanges = null;

		/// <summary>
		/// List of rows that is not hidden by folding
		/// </summary>
		public RowCollection VisibleRows = new RowCollection();

		private RowCollection mDocument = new RowCollection();

		/// <summary>
		/// Buffer containing undo actions
		/// </summary>
		public UndoBuffer UndoBuffer = new UndoBuffer();

		/// <summary>
		/// The active parser of the document
		/// </summary>
		public IParser Parser = new DefaultParser();

		/// <summary>
		/// For public use only
		/// </summary>
		private bool mIsParsed = true;

		private string mSyntaxFile = "";

		#region PUBLIC PROPERTY UNDOSTEP

		private int _UndoStep;

		public int UndoStep
		{
			get
			{
				if (_UndoStep > this.UndoBuffer.Count)
					_UndoStep = this.UndoBuffer.Count;

				return _UndoStep;
			}
			set { _UndoStep = value; }
		}

		#endregion

		/// <summary>
		/// Tag property , lets the user store custom data in the row.
		/// </summary>
		public object Tag = null;


		/// <summary>
		/// Gets or Sets if folding needs to be recalculated
		/// </summary>
		public bool NeedResetRows = false;

		private bool mModified = false;
		private bool mFolding = true;
		private Container components = null;
		private bool mCaptureMode = false;
		private UndoBlockCollection mCaptureBlock = null;

		/// <summary>
		/// Event that is raised when there is no more rows to parse
		/// </summary>
		public event EventHandler ParsingCompleted;

		public event EventHandler UndoBufferChanged = null;

		/// <summary>
		/// Raised when the parser is active
		/// </summary>
		public event EventHandler Parsing;

		/// <summary>
		/// Raised when the document content is changed
		/// </summary>
		public event EventHandler Change;

		public event RowEventHandler BreakPointAdded;
		public event RowEventHandler BreakPointRemoved;

		public event RowEventHandler BookmarkAdded;
		public event RowEventHandler BookmarkRemoved;

		protected virtual void OnBreakPointAdded(Row r)
		{
			if (BreakPointAdded != null)
				BreakPointAdded(this, new RowEventArgs(r));
		}

		protected virtual void OnBreakPointRemoved(Row r)
		{
			if (BreakPointRemoved != null)
				BreakPointRemoved(this, new RowEventArgs(r));
		}

		protected virtual void OnBookmarkAdded(Row r)
		{
			if (BookmarkAdded != null)
				BookmarkAdded(this, new RowEventArgs(r));
		}

		protected virtual void OnBookmarkRemoved(Row r)
		{
			if (BookmarkRemoved != null)
				BookmarkRemoved(this, new RowEventArgs(r));
		}

		protected virtual void OnUndoBufferChanged()
		{
			if (UndoBufferChanged != null)
				UndoBufferChanged(this, EventArgs.Empty);
		}


		public virtual void InvokeBreakPointAdded(Row r)
		{
			OnBreakPointAdded(r);
		}

		public virtual void InvokeBreakPointRemoved(Row r)
		{
			OnBreakPointRemoved(r);
		}

		public virtual void InvokeBookmarkAdded(Row r)
		{
			OnBookmarkAdded(r);
		}

		public virtual void InvokeBookmarkRemoved(Row r)
		{
			OnBookmarkRemoved(r);
		}


		//public event System.EventHandler CreateParser;

		/// <summary>
		/// Raised when the modified flag has changed
		/// </summary>
		public event EventHandler ModifiedChanged;

		//----------------------------------------------

		/// <summary>
		/// Raised when a row have been parsed
		/// </summary>
		public event ParserEventHandler RowParsed;

		//	public event ParserEventHandler	 RowAdded;
		/// <summary>
		/// Raised when a row have been deleted
		/// </summary>
		public event ParserEventHandler RowDeleted;

		#endregion

		#region PUBLIC PROPERTY MAXUNDOBUFFERSIZE

		/// <summary>
		/// Gets or Sets the Maximum number of entries in the undobuffer
		/// </summary>
		public int MaxUndoBufferSize
		{
			get { return UndoBuffer.MaxSize; }
			set { UndoBuffer.MaxSize = value; }
		}

		#endregion

		#region PUBLIC PROPERTY VERSION

		private long _Version = long.MinValue;

		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public long Version
		{
			get { return _Version; }
			set { _Version = value; }
		}

		#endregion

		/// <summary>
		/// For internal use only
		/// </summary>
		public void ChangeVersion()
		{
			this.Version ++;
			if (this.Version > long.MaxValue - 10)
				this.Version = long.MinValue;
		}

		/// <summary>
		/// Starts an Undo Capture.
		/// This method can be called if you with to collect multiple text operations into one undo action
		/// </summary>
		public void StartUndoCapture()
		{
			mCaptureMode = true;
			mCaptureBlock = new UndoBlockCollection();
		}

		/// <summary>
		/// Ends an Undo capture and pushes the collected actions onto the undostack
		/// <seealso cref="StartUndoCapture"/>
		/// </summary>
		/// <returns></returns>
		public UndoBlockCollection EndUndoCapture()
		{
			mCaptureMode = false;
			AddToUndoList(mCaptureBlock);
			return mCaptureBlock;
		}

		/// <summary>
		/// ReParses the document
		/// </summary>
		public void ReParse()
		{
			this.Text = this.Text;
		}

		/// <summary>
		/// Get or Set the Modified flag
		/// </summary>
		public bool Modified
		{
			get { return mModified; }
			set
			{
				mModified = value;
				OnModifiedChanged();
			}
		}

		/// <summary>
		/// Removes all bookmarks in the document
		/// </summary>
		public void ClearBookmarks()
		{
			foreach (Row r in this)
			{
				r.Bookmarked = false;
			}
			InvokeChange();
		}

		/// <summary>
		/// Removes all breakpoints in the document.
		/// </summary>
		public void ClearBreakpoints()
		{
			foreach (Row r in this)
			{
				r.Breakpoint = false;
			}
			InvokeChange();
		}


		/// <summary>
		/// Get or Set the Name of the Syntaxfile to use
		/// </summary>
		[DefaultValue("")]
		public string SyntaxFile
		{
			get { return mSyntaxFile; }
			set
			{
				mSyntaxFile = value;
				//	this.Parser=new Parser_Default();
				this.Parser.Init(value);
				this.Text = this.Text;
			}
		}

		/// <summary>
		/// Call this method to ensure that a specific row is fully parsed
		/// </summary>
		/// <param name="Row"></param>
		public void EnsureParsed(Row Row)
		{
			this.ParseAll();
			Parser.ParseLine(Row.Index, true);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="container"></param>
		public SyntaxDocument(IContainer container) : this()
		{
			container.Add(this);
			InitializeComponent();
		}

		private void Init()
		{
			Language l = new Language();
			l.MainBlock = new BlockType(l);
			l.MainBlock.MultiLine = true;
			this.Parser.Init(l);
		}

		/// <summary>
		/// Call this method to make the SyntaxDocument raise the Changed event
		/// </summary>
		public void InvokeChange()
		{
			OnChange();
		}

		/// <summary>
		/// Gets or Sets if the document should use folding or not
		/// </summary>
		[DefaultValue(true)]
		public bool Folding
		{
			get { return mFolding; }
			set
			{
				mFolding = value;
				if (!value)
				{
					foreach (Row r in this)
					{
						r.Expanded = true;
					}

				}
				ResetVisibleRows();

				OnChange();
			}
		}

		#region Component Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
		}

		#endregion

		/// <summary>
		/// 
		/// </summary>
		public SyntaxDocument()
		{
			Parser.Document = this;
			Text = "";
			ResetVisibleRows();
			Init();
			this.FormatRanges = new FormatRangeCollection(this);
		}

		/// <summary>
		/// Performs a segment parse on all rows. No Keyword colorizing
		/// </summary>
		public void ParseAll()
		{
			while (ParseQueue.Count > 0)
				ParseSome();

			ParseQueue.Clear();
		}

		/// <summary>
		/// Parses all rows , either a segment parse or a full parse with keyword colorizing
		/// </summary>
		public void ParseAll(bool ParseKeywords)
		{
			this.ParseAll();
			if (ParseKeywords)
			{
				for (int i = 0; i < this.Count; i++)
				{
					if (this[i].RowState != RowState.AllParsed)
						Parser.ParseLine(i, true);
				}
				ParseQueue.Clear();
				KeywordQueue.Clear();
			}


		}

		/// <summary>
		/// Folds all foldable rows
		/// </summary>
		public void FoldAll()
		{
			this.ParseAll(false);
			foreach (Row r in this)
			{
				r.Expanded = false;
			}
			this.ResetVisibleRows();
			this.OnChange();
		}

		/// <summary>
		/// UnFolds all foldable rows
		/// </summary>
		public void UnFoldAll()
		{
			this.ParseAll(false);
			foreach (Row r in this)
			{
				r.Expanded = true;
			}
			this.ResetVisibleRows();
			this.OnChange();
		}


		/// <summary>
		/// Parses a chunk of 1000 rows , this is not thread safe
		/// </summary>
		public void ParseSome()
		{
			this.ParseSome(1000);
		}

		/// <summary>
		/// Parse a chunk of rows, this is not thread safe
		/// </summary>
		/// <param name="RowCount">The number of rows to parse</param>
		public void ParseSome(int RowCount)
		{
			if (this.ParseQueue.Count > 0)
			{
				mIsParsed = false;
				int i = 0;
				while (i < RowCount && this.ParseQueue.Count > 0)
				{
					Row row = this.ParseQueue[0];
					i += ParseRows(row);
				}

				if (this.NeedResetRows)
					this.ResetVisibleRows();

				if (Parsing != null)
					Parsing(this, new EventArgs());
			}
			else
			{
				if (!mIsParsed && !Modified)
				{
					mIsParsed = true;

					foreach (Row r in this)
					{
						if (r.Expansion_StartSegment != null && r.Expansion_EndRow != null)
						{
							if (r.Expansion_StartSegment.Scope.DefaultExpanded == false)
								r.Expanded = false;
						}
					}
					ResetVisibleRows();
					if (ParsingCompleted != null)
						ParsingCompleted(this, new EventArgs());
				}
			}

			if (this.ParseQueue.Count == 0 && this.KeywordQueue.Count > 0)
			{
//				Console.WriteLine (this.KeywordQueue.Count.ToString ());
				int i = 0;
				while (i < RowCount/20 && this.KeywordQueue.Count > 0)
				{
					Row row = this.KeywordQueue[0];
					i += ParseRows(row, true);
				}
			}
		}


		/// <summary>
		/// Gets if the document is fully parsed
		/// </summary>
		[Browsable(false)]
		public bool IsParsed
		{
			get { return mIsParsed; }
		}

		/// <summary>
		/// Returns the row at the specified index
		/// </summary>
		public Row this[int index]
		{
			get
			{
				if (index < 0 || index >= mDocument.Count)
				{
					//	System.Diagnostics.Debugger.Break ();
					return null;
				}
				return mDocument[index];
			}

			set { mDocument[index] = value; }
		}

		/// <summary>
		/// Add a new row with the specified text to the bottom of the document
		/// </summary>
		/// <param name="Text">Text to add</param>
		/// <returns>The row that was added</returns>		
		public Row Add(string Text)
		{
			return Add(Text, true);
		}

		/// <summary>
		/// Add a new row with the specified text to the bottom of the document
		/// </summary>
		/// <param name="Text">Text to add</param>
		/// <param name="StoreUndo">true if and undo action should be added to the undo stack</param>
		/// <returns>The row that was added</returns>
		public Row Add(string Text, bool StoreUndo)
		{
			Row xtl = new Row();
			mDocument.Add(xtl);
			xtl.Document = this;
			xtl.Text = Text;
			return xtl;
		}

		/// <summary>
		/// Insert a text at the specified row index
		/// </summary>
		/// <param name="Text">Text to insert</param>
		/// <param name="index">Row index where the text should be inserted</param>
		/// <returns>The row that was inserted</returns>
		public Row Insert(string Text, int index)
		{
			return Insert(Text, index, true);
		}

		/// <summary>
		/// Insert a text at the specified row index
		/// </summary>
		/// <param name="Text">Text to insert</param>
		/// <param name="index">Row index where the text should be inserted</param>
		/// <param name="StoreUndo">true if and undo action should be added to the undo stack</param>
		/// <returns>The row that was inserted</returns>
		public Row Insert(string Text, int index, bool StoreUndo)
		{
			Row xtl = new Row();
			xtl.Document = this;
			mDocument.Insert(index, xtl);
			xtl.Text = Text;
			if (StoreUndo)
			{
				UndoBlock undo = new UndoBlock();
				undo.Text = Text;
				undo.Position.Y = this.IndexOf(xtl);
				AddToUndoList(undo);
			}

⌨️ 快捷键说明

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