row.cs
来自「Fireball.CodeEditor is an source code ed」· CS 代码 · 共 1,126 行 · 第 1/2 页
CS
1,126 行
//Original source code coming from Compona.com
/*
* this file was modified for resolve some bugs removed all try catch because it hide some
* bug on the code and because aren't speed safe all modification are copyright of
* <sebastian.faltoni[at]gmail.com> and are under the LGPL licenze
*/
using System.Collections;
using System.Drawing;
namespace Fireball.Syntax
{
/// <summary>
/// Parser state of a row
/// </summary>
public enum RowState
{
/// <summary>
/// the row is not parsed
/// </summary>
NotParsed = 0,
/// <summary>
/// the row is segment parsed
/// </summary>
SegmentParsed = 1,
/// <summary>
/// the row is both segment and keyword parsed
/// </summary>
AllParsed = 2
}
/// <summary>
/// The row class represents a row in a SyntaxDocument
/// </summary>
public sealed class Row : IEnumerable
{
#region General Declarations
private string mText = "";
internal WordCollection mWords = new WordCollection();
public WordCollection FormattedWords = new WordCollection();
/// <summary>
/// Segments that start on this row
/// </summary>
public SegmentCollection StartSegments = new SegmentCollection();
/// <summary>
/// Segments that ends in this row
/// </summary>
public SegmentCollection EndSegments = new SegmentCollection();
/// <summary>
/// The owner document
/// </summary>
public SyntaxDocument Document = null;
/// <summary>
/// The first collapsable segment on this row.
/// </summary>
public Segment StartSegment = null;
/// <summary>
/// The first segment that terminates on this row.
/// </summary>
public Segment EndSegment = null;
/// <summary>
///
/// </summary>
public Segment Expansion_StartSegment = null;
/// <summary>
///
/// </summary>
public Segment Expansion_EndSegment = null;
private RowState _RowState = RowState.NotParsed;
#region PUBLIC PROPERTY BACKCOLOR
private Color _BackColor = Color.Transparent;
public Color BackColor
{
get { return _BackColor; }
set { _BackColor = value; }
}
#endregion
public int Depth
{
get
{
int i = 0;
Segment s = this.StartSegment;
while (s != null)
{
if (s.Scope != null && s.Scope.CauseIndent)
i++;
s = s.Parent;
}
// if (i>0)
// i--;
if (ShouldOutdent)
i--;
return i;
}
}
public bool ShouldOutdent
{
get
{
if (this.StartSegment.EndRow == this)
{
if (this.StartSegment.Scope.CauseIndent)
return true;
}
return false;
}
}
/// <summary>
/// Collection of Image indices assigned to a row.
/// </summary>
/// <example>
/// <b>Add an image to the current row.</b>
/// <code>
/// MySyntaxBox.Caret.CurrentRow.Images.Add(3);
/// </code>
/// </example>
public ImageIndexCollection Images = new ImageIndexCollection();
/// <summary>
/// Object tag for storage of custom user data..
/// </summary>
/// <example>
/// <b>Assign custom data to a row</b>
/// <code>
/// //custom data class
/// class CustomData{
/// public int abc=123;
/// publci string def="abc";
/// }
///
/// ...
///
/// //assign custom data to a row
/// Row MyRow=MySyntaxBox.Caret.CurrentRow;
/// CustomData MyData=new CustomData();
/// MyData.abc=1337;
/// MyRow.Tag=MyData;
///
/// ...
///
/// //read custom data from a row
/// Row MyRow=MySyntaxBox.Caret.CurrentRow;
/// if (MyRow.Tag != null){
/// CustomData MyData=(CustomData)MyRow.Tag;
/// if (MyData.abc==1337){
/// //Do something...
/// }
/// }
///
///
/// </code>
/// </example>
public object Tag = null;
/// <summary>
/// The parse state of this row
/// </summary>
/// <example>
/// <b>Test if the current row is fully parsed.</b>
/// <code>
/// if (MySyntaxBox.Caret.CurrentRow.RowState==RowState.AllParsed)
/// {
/// //do something
/// }
/// </code>
/// </example>
public RowState RowState
{
get { return _RowState; }
set
{
if (value == _RowState)
return;
if (value == RowState.SegmentParsed && !InKeywordQueue)
{
this.Document.KeywordQueue.Add(this);
this.InKeywordQueue = true;
}
if ((value == RowState.AllParsed || value == RowState.NotParsed) && InKeywordQueue)
{
this.Document.KeywordQueue.Remove(this);
this.InKeywordQueue = false;
}
_RowState = value;
}
}
//----Lookuptables-----------------
// public char[] Buffer_Text =null;
// // public char[] Buffer_Separators =null;
//---------------------------------
/// <summary>
/// Returns true if the row is in the owner documents parse queue
/// </summary>
public bool InQueue = false; //is this line in the parseQueue?
/// <summary>
/// Returns true if the row is in the owner documents keyword parse queue
/// </summary>
public bool InKeywordQueue = false; //is this line in the parseQueue?
private bool mBookmarked = false; //is this line bookmarked?
private bool mBreakpoint = false; //Does this line have a breakpoint?
/// <summary>
/// For public use only
/// </summary>
public int Indent = 0; //value indicating how much this line should be indented (c style)
/// <summary>
/// For public use only
/// </summary>
public int Expansion_PixelStart = 0;
/// <summary>
/// For public use only
/// </summary>
public int Expansion_StartChar = 0;
/// <summary>
/// For public use only
/// </summary>
public int Expansion_PixelEnd = 0;
/// <summary>
/// For public use only
/// </summary>
public int Expansion_EndChar = 0;
#endregion
public void Clear()
{
mWords = new WordCollection();
}
/// <summary>
/// If the row is hidden inside a collapsed segment , call this method to make the collapsed segments expanded.
/// </summary>
public void EnsureVisible()
{
if (this.RowState == RowState.NotParsed)
return;
Segment seg = this.StartSegment;
while (seg != null)
{
seg.Expanded = true;
seg = seg.Parent;
}
this.Document.ResetVisibleRows();
}
/// <summary>
/// Gets or Sets if this row has a bookmark or not.
/// </summary>
public bool Bookmarked
{
get { return mBookmarked; }
set
{
mBookmarked = value;
if (value)
Document.InvokeBookmarkAdded(this);
else
Document.InvokeBookmarkRemoved(this);
Document.InvokeChange();
}
}
/// <summary>
/// Gets or Sets if this row has a breakpoint or not.
/// </summary>
public bool Breakpoint
{
get { return mBreakpoint; }
set
{
mBreakpoint = value;
if (value)
Document.InvokeBreakPointAdded(this);
else
Document.InvokeBreakPointRemoved(this);
Document.InvokeChange();
}
}
public Word Add(string text)
{
Word xw = new Word();
xw.Row = this;
xw.Text = text;
mWords.Add(xw);
return xw;
}
/// <summary>
/// Returns the number of words in the row.
/// (this only applied if the row is fully parsed)
/// </summary>
public int Count
{
get { return mWords.Count; }
}
/// <summary>
/// Gets or Sets the text of the row.
/// </summary>
public string Text
{
get { return mText; }
set
{
bool ParsePreview = false;
if (mText != value)
{
ParsePreview = true;
this.Document.Modified = true;
}
mText = value;
if (Document != null)
{
if (ParsePreview)
{
Document.Parser.ParsePreviewLine(Document.IndexOf(this));
this.Document.OnApplyFormatRanges(this);
}
AddToParseQueue();
}
}
}
/// <summary>
/// Adds this row to the parse queue
/// </summary>
public void AddToParseQueue()
{
if (!InQueue)
Document.ParseQueue.Add(this);
InQueue = true;
this.RowState = RowState.NotParsed;
}
/// <summary>
/// Assigns a new text to the row.
/// </summary>
/// <param name="Text"></param>
public void SetText(string Text)
{
this.Document.StartUndoCapture();
TextPoint tp = new TextPoint(0, this.Index);
TextRange tr = new TextRange();
tr.FirstColumn = 0;
tr.FirstRow = tp.Y;
tr.LastColumn = this.Text.Length;
tr.LastRow = tp.Y;
this.Document.StartUndoCapture();
//delete the current line
this.Document.PushUndoBlock(UndoAction.DeleteRange, this.Document.GetRange(tr), tr.FirstColumn, tr.FirstRow);
//alter the text
this.Document.PushUndoBlock(UndoAction.InsertRange, Text, tp.X, tp.Y);
this.Text = Text;
this.Document.EndUndoCapture();
this.Document.InvokeChange();
}
/*private char[] GetSeparatorBuffer(string text, string separators)
{
char[] buff = text.ToCharArray();
for (int i = 0; i < text.Length; i++)
{
char c = buff[i];
if (separators.IndexOf(c) >= 0)
buff[i] = ' ';
else
buff[i] = '.';
}
return buff;
}*/
/// <summary>
/// Call this method to make all words match the case of their patterns.
/// (this only applies if the row is fully parsed)
/// </summary>
public void MatchCase()
{
string s = "";
foreach (Word w in mWords)
{
s = s + w.Text;
}
mText = s;
}
/// <summary>
/// Get the Word enumerator for this row
/// </summary>
/// <returns></returns>
public IEnumerator GetEnumerator()
{
return mWords.GetEnumerator();
}
/// <summary>
/// Return the Word object at the specified index.
/// </summary>
public Word this[int index]
{
get
{
if (index >= 0)
return (Word) mWords[index];
else
return new Word();
}
}
/// <summary>
/// Force a segment parse on the row.
/// </summary>
public void Parse()
{
Document.ParseRow(this);
}
/// <summary>
/// Forces the parser to parse this row directly
/// </summary>
/// <param name="ParseKeywords">true if keywords and operators should be parsed</param>
public void Parse(bool ParseKeywords)
{
Document.ParseRow(this, ParseKeywords);
}
public void SetExpansionSegment()
{
this.Expansion_StartSegment = null;
this.Expansion_EndSegment = null;
foreach (Segment s in this.StartSegments)
{
if (!this.EndSegments.Contains(s))
{
this.Expansion_StartSegment = s;
break;
}
}
foreach (Segment s in this.EndSegments)
{
if (!this.StartSegments.Contains(s))
{
this.Expansion_EndSegment = s;
break;
}
}
if (this.Expansion_EndSegment != null)
this.Expansion_StartSegment = null;
}
/// <summary>
/// Returns the whitespace string at the begining of this row.
/// </summary>
/// <returns>a string containing the whitespace at the begining of this row</returns>
public string GetLeadingWhitespace()
{
string s = mText;
int i = 0;
s = s.Replace(" ", " ");
for (i = 0; i < s.Length; i++)
{
if (s.Substring(i, 1) == " ")
{
}
else
{
break;
}
}
return mText.Substring(0, i);
}
public int StartWordIndex
{
get
{
if (this.Expansion_StartSegment == null)
return 0;
// if (this.Expansion_StartSegment.StartRow != this)
// return 0;
Word w = this.Expansion_StartSegment.StartWord;
int i = 0;
foreach (Word wo in this)
{
if (wo == w)
break;
i += wo.Text.Length;
}
return i;
}
}
public Word FirstNonWsWord
{
get
{
foreach (Word w in this)
{
if (w.Type == WordType.xtWord)
return w;
}
return null;
}
}
public string GetVirtualLeadingWhitespace()
{
int i = this.StartWordIndex;
string ws = "";
foreach (char c in this.Text)
{
if (c == '\t')
ws += c;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?