AvalonEdit的最新版本是SharpDevelop項目的一部分。有關AvalonEdit的詳細信息,請訪問www.avalonedit.net. 介紹 ICSharpCode。AvalonEdit是一個基於wpf的文本編輯器,是我為SharpDevelop 4.0編寫的。它是用來替代ICSharpCode的。TextEditor,但應該是: 可擴展,易於使用,更擅長處理大型文件 可擴展的意思是我希望銳化開發插件能夠添加功能到文本編輯器。例如,一個插件應該允許在注釋中插入圖片——這樣,你就可以把類圖這樣的東西直接放到源代碼中! 容易使用,我指的是編程API。它應該只是工作™。例如,這意味着如果更改文檔文本,編輯器應該自動重新繪制,而不必調用Invalidate()。而且,如果你做錯了什么,你應該得到一個有意義的異常,而不是損壞狀態,然后崩潰在一個不相關的位置。 更好地處理大文件意味着編輯器應該能夠處理大文件(例如mscorlib XML文檔文件,7mb, 74100 LOC),即使啟用了像折疊(代碼崩潰)這樣的特性。 使用的代碼 編輯器的主要類是ICSharpCode.AvalonEdit.TextEditor。你可以使用它就像一個普通的WPF文本框: 隱藏,復制Code
<avalonEdit:TextEditorxmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"Name="textEditor"FontFamily="Consolas"SyntaxHighlighting="C#"FontSize="10pt"/>
AvalonEdit內置了語法高亮顯示定義:NET, Boo, Coco/R語法,c++, c#, HTML, Java, JavaScript,補丁文件,PHP, TeX, VB和XML。 如果您需要更多的AvalonEdit,而不僅僅是一個語法高亮顯示的簡單文本框,那么您首先必須了解更多關於AvalonEdit的架構。 體系結構 正如您在這個依賴關系圖中看到的,AvalonEdit由幾個子名稱空間組成,它們有干凈地分隔的作業。大多數名稱空間都有一種“main”類。 ICSharpCode.AvalonEdit。各種實用工具類。文本模型ICSharpCode.AvalonEdit。可擴展的視圖到文檔ICSharpCode.AvalonEdit。控制文本編輯(例如,插入符號,選擇,處理用戶輸入)。允許代碼崩潰ICSharpCode.AvalonEdit。高亮:HighlightingManager -高亮引擎icsharpcode . avalonedit .高亮。XML語法高亮顯示定義支持。ICSharpCode.AvalonEdit xshd文件)。顯示代碼完成的下拉列表。AvalonEdit: TextEditor -主要的控制,把它一起 這是TextEditor控件的可視化樹: 理解AvalonEdit是一個具有三層的復合控件是很重要的:TextEditor(主控件),TextArea(編輯),TextView(渲染)。雖然主控件為常見任務提供了一些方便的方法,但對於大多數高級特性,您必須直接使用內部控件。你可以使用textEditor訪問它們。或textEditor.TextArea.TextView文本區域。 文檔(文本模型) 模型的主要類是ICSharpCode.AvalonEdit.Document.TextDocument。基本上,文檔是一個帶有事件的StringBuilder。但是,文檔名稱空間還包含一些對使用文本編輯器的應用程序有用的特性。 在文本編輯器中,所有三個控件(TextEditor, TextArea, TextView)都有一個指向TextDocument實例的文檔屬性。您可以更改文檔屬性,以將編輯器綁定到另一個文檔。可以將兩個編輯器實例綁定到同一個文檔;您可以使用此特性創建分屏視圖。 以下是簡化后的TextDocument定義: 隱藏,復制Code
public sealed class TextDocument : ITextSource { public event EventHandler<DocumentChangeEventArgs> Changing; public event EventHandler<DocumentChangeEventArgs> Changed; public event EventHandler TextChanged; public IList<DocumentLine> Lines { get; } public DocumentLine GetLineByNumber(int number); public DocumentLine GetLineByOffset(int offset); public TextLocation GetLocation(int offset); public int GetOffset(int line, int column); public char GetCharAt(int offset); public string GetText(int offset, int length); public void Insert(int offset, string text); public void Remove(int offset, int length); public void Replace(int offset, int length, string text); public string Text { get; set; } public int LineCount { get; } public int TextLength { get; } public UndoStack UndoStack { get; } }
在AvalonEdit中,進入文檔的索引稱為偏移量。 偏移量通常表示兩個字符之間的位置。文檔開始處的第一個偏移量為0;文檔中第一個字符之后的偏移量為1。最后一個有效偏移量是document。文本長度,表示文檔的結束。這與。net字符串或StringBuilder類中方法使用的“index”參數完全相同。 偏移量很容易使用,但有時您需要行/列對來代替。AvalonEdit為這些定義了一個名為TextLocation的結構。 該文檔提供方法GetLocation和GetOffset,以便在偏移量和textlocation之間進行轉換。這些都是建立在DocumentLine類之上的便利方法。 TextDocument。Lines集合為文檔中的每一行包含一個DocumentLine實例。此集合對用戶代碼是只讀的,並會自動更新以反映當前文檔內容。 呈現 在整個“文檔”部分中,沒有提到可擴展性。文本呈現基礎設施現在必須通過完全可擴展來彌補這一點。 ICSharpCode.AvalonEdit.Rendering。TextView類是heart AvalonEdit。它負責將文檔顯示在屏幕上。 為了以一種可擴展的方式做到這一點,TextView使用了它自己的一種模型:VisualLine。只為文檔的可見部分創建可視線條。 渲染過程是這樣的: 管道中的最后一步是轉換到一個或多個System.Windows.Media.TextFormatting。TextLine實例。然后WPF負責實際的文本渲染。 “元素生成器”、“線路轉換器”和“背景渲染器”是擴展點;可以在編輯器中添加他們的自定義實現到TextView來實現額外的功能。 編輯 TextArea類處理用戶輸入並執行適當的操作。插入符號和選擇內容都由文本區域控制。 您可以通過修改文本區域來定制文本區域。DefaultInputHandler通過在其中添加新的或替換現有的WPF輸入綁定。你也可以設置文本區域。ActiveInputHandler切換到與默認值不同的值,以將文本區域切換到另一種模式。您可以使用它來實現“增量搜索”特性,甚至一個VI仿真器。 文本區域有LeftMargins屬性——使用它將控件添加到文本視圖的左側,這些控件看起來像是在滾動查看器中,但實際上並不滾動。AbstractMargin基類包含一些有用的代碼,用於檢測邊框何時從文本視圖附加/分離;或活動文檔更改時。然而,你並不是被迫使用它;任何UIElement都可以用作邊距。 折疊 折疊(代碼折疊)是作為編輯器的擴展實現的。它可以在單獨的程序集中實現,而不必修改AvalonEdit代碼。VisualLineElementGenerator負責處理文本文檔中的折疊部分,而自定義邊框繪制加號和減號按鈕。 您可以單獨使用相關的類;但是,為了讓它更容易使用,靜態FoldingManager。安裝方法將自動創建和注冊所需的部件。 剩下要做的就是定期調用FoldingManager。使用要提供的折疊列表進行更新。你可以自己計算這個列表,或者你可以使用一個內置的折疊策略來幫你完成。 以下是啟用折疊所需的完整代碼: 隱藏,復制Code
foldingManager = FoldingManager.Install(textEditor.TextArea);
foldingStrategy = new XmlFoldingStrategy();
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);
如果您希望在文本更改時更新折疊標記,則必須重復折疊策略。UpdateFoldings定期調用。 目前,只有XmlFoldingStrategy內置於AvalonEdit中。本文的示例應用程序還包含使用{和}進行折疊的BraceFoldingStrategy。但是,它是一個非常簡單的實現,不能正確處理字符串或注釋中的{和}。 語法高亮顯示 AvalonEdit中的高亮顯示引擎是在類documententhighlighter中實現的。高亮顯示是采用DocumentLine並通過為該行的不同部分分配顏色為其構造HighlightedLine實例的過程。 HighlightingColorizer類是高亮顯示和呈現之間的唯一鏈接。它使用了一個documententhighlighter來實現一個行轉換器,該轉換器在渲染過程中將高亮顯示應用到可視的線條上。 除了這個調用之外,語法突出顯示獨立於呈現的名稱空間。為了幫助突出顯示引擎的其他潛在用途,HighlightedLine類具有ToHtml方法來生成語法突出顯示的HTML源代碼。 突出顯示規則是使用“可擴展語法突出顯示定義”(.xshd)文件定義的。以下是c#子集的完整高亮定義: 隱藏,收縮,復制Code
<SyntaxDefinitionname="C#"xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> <Colorname="Comment"foreground="Green"/> <Colorname="String"foreground="Blue"/> <!-- This is the main ruleset. --> <RuleSet> <Spancolor="Comment"begin="//"/> <Spancolor="Comment"multiline="true"begin="/\*"end="\*/"/> <Spancolor="String"> <Begin>"</Begin> <End>"</End> <RuleSet> <!-- nested span for escape sequences --> <Spanbegin="\\"end="."/> </RuleSet> </Span> <KeywordsfontWeight="bold"foreground="Blue"> <Word>if</Word> <Word>else</Word> <!-- ... --> </Keywords> <!-- Digits --> <Ruleforeground="DarkBlue"> \b0[xX][0-9a-fA-F]+ # hex number | \b ( \d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent </Rule> </RuleSet> </SyntaxDefinition>
突出顯示引擎與“span”和“rules”一起工作,每個“span”和“rules”都有指定的顏色。在XSHD格式中,顏色可以被引用(color="Comment"),也可以被直接指定(fontWeight="bold" foreground="Blue")。 span由兩個正則表達式組成(begin+end);而規則只是帶有顏色的單個正則表達式。& lt; Keywords>元素只是一個很好的語法,用來定義匹配一組單詞的高亮顯示規則;在內部,單個正則表達式將用於整個關鍵字列表。 突出顯示引擎首先分析span:每當begin regex匹配某些文本時,該span就被推到堆棧上。只要當前span的結束正則表達式匹配某些文本,就會從堆棧中彈出span。 每個span都有一個與之關聯的嵌套規則集,默認情況下為空。這就是為什么關鍵字不會在注釋內突出顯示:span的空規則集在那里是活動的,因此關鍵字規則不會被應用。 這個特性也用於字符串span中:當遇到反斜杠時,嵌套的span將匹配,后面的字符將被嵌套的span(的結束正則表達式使用。匹配任何字符)。這確保\" does不是表示弦跨度的末端;但是“\\”仍然存在。 高亮顯示引擎的偉大之處在於,它只按需高亮顯示,以增量方式工作,但即使對於大型代碼文件,通常也只需要幾個KB的內存。 按需意味着當一個文檔被打開時,只有最初可見的行會被突出顯示。當用戶向下滾動時,高亮顯示將從上次停止的位置繼續。如果用戶快速滾動,以至於第一個可見的行遠遠低於最后一個突出顯示的行,那么突出顯示引擎仍然必須處理中間的所有行——其中可能有注釋開始。但是,它將只掃描該區域以查看span堆棧中的更改;高亮顯示規則將不會被測試。 活動跨越的堆棧存儲在每一行的開頭。如果用戶向上滾動,進入視圖的行可以立即突出顯示,因為必要的上下文(span堆棧)仍然可用。 遞增的意思是,即使文檔發生了更改,存儲的span堆棧也將盡可能重用。如果用戶鍵入/*,從理論上講,這將導致整個文件的其余部分以注釋的顏色突出顯示。但是,因為引擎是按需工作的,它將只更新當前可見區域內的span堆棧,並保持“高亮顯示狀態在X行和X+1行之間不一致”的通知,其中X是可見區域的最后一行。現在,如果用戶向下滾動,高亮顯示狀態就會更新,“不一致”的通知就會向下移動。但通常情況下,用戶會繼續輸入,然后只在幾行之后輸入*/。現在,可見區域的高亮顯示狀態將恢復為正常的“只有主規則集在活動span的堆棧上”。當用戶現在滾動到帶有“不一致”標記的行以下時,引擎將注意到舊堆棧和新堆棧是相同的,並將刪除“不一致”標記。這允許重用在用戶鍵入/*之前緩存的存儲span堆棧。 盡管活動跨越的堆棧可能在行內頻繁變化,但從一行的開頭到下一行的開頭很少變化。對於大多數語言,這樣的更改只發生在多行注釋的開始和結束處。突出顯示引擎通過將span堆棧列表存儲在一個特殊的數據結構(ICSharpCode.AvalonEdit.Utils.CompressingTreeList)來利用這個屬性。突出顯示引擎的內存使用量與跨度堆棧變化的數量成線性關系;而不是總行數。這允許突出顯示引擎僅使用少量內存就可以存儲大代碼文件的span堆棧,特別是在像c#這樣的語言中,//或///序列比/* */注釋更流行。 代碼自動完成 AvalonEdit帶有一個代碼完成下拉窗口。你只需要處理文本輸入事件,以確定何時你想要顯示窗口;所有UI都已經為您完成了。 以下是如何使用它: 隱藏,收縮,復制Code
// in the constructor: textEditor.TextArea.TextEntering += textEditor_TextArea_TextEntering; textEditor.TextArea.TextEntered += textEditor_TextArea_TextEntered; } CompletionWindow completionWindow; void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) { if (e.Text == ".") { // Open code completion after the user has pressed dot: completionWindow = new CompletionWindow(textEditor.TextArea); IList<ICompletionData> data = completionWindow.CompletionList.CompletionData; data.Add(new MyCompletionData("Item1")); data.Add(new MyCompletionData("Item2")); data.Add(new MyCompletionData("Item3")); completionWindow.Show(); completionWindow.Closed += delegate { completionWindow = null; }; } } void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e) { if (e.Text.Length > 0 && completionWindow != null) { if (!char.IsLetterOrDigit(e.Text[0])) { // Whenever a non-letter is typed while the completion window is open, // insert the currently selected element. completionWindow.CompletionList.RequestInsertion(e); } } // Do not set e.Handled=true. // We still want to insert the character that was typed. }
這段代碼將打開代碼完成窗口。”。默認情況下,CompletionWindow只處理按Tab鍵和Enter鍵來插入當前選擇的項目。當鍵像'時也要使它完整。'或';',我們附加另一個處理程序到TextEntering事件,並告訴完成窗口插入選定的項目。 CompletionWindow實際上不會有焦點-相反,它劫持WPF鍵盤輸入事件在文本區域,並通過它的列表框傳遞。這允許同時使用鍵盤和編輯器中的常規輸入選擇完成列表中的條目。 為了完整性,這里是實現MyCompletionData類使用在上面的代碼: 隱藏,收縮,復制Code
/// Implements AvalonEdit ICompletionData interface to provide the entries in the /// completion drop down. public class MyCompletionData : ICompletionData { public MyCompletionData(string text) { this.Text = text; } public System.Windows.Media.ImageSource Image { get { return null; } } public string Text { get; private set; } // Use this property if you want to show a fancy UIElement in the list. public object Content { get { return this.Text; } } public object Description { get { return "Description for " + this.Text; } } public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) { textArea.Document.Replace(completionSegment, this.Text); } }
顯示的內容和描述都可以是WPF中可以接受的任何內容,包括定制的uielement。除了簡單地插入文本之外,還可以在完整方法中實現自定義邏輯。insertionRequestEventArgs可以幫助決定用戶想要的插入類型——取決於插入是如何被觸發的,它是TextCompositionEventArgs、KeyEventArgs或MouseEventArgs的實例。 歷史 2008年6月14日:夏普開發團隊切換到夏普開發4作為他們開發夏普開發的IDE;AvalonEdit開始得到真正用於workOctober 4, 2009:本文首先發表在代碼ProjectJune 13, 2010:更新下載AvalonEdit 4.0.0.5950 (SharpDevelop 4.0 Beta 1) 9月13日,2011:更新下載AvalonEdit 4.1.0.7916 (SharpDevelop 4.1 RC),大量的bug修復,改善Performance 現在針對。net 4.0, 5月12日2012:更新下載AvalonEdit 4.2.0.8783 (SharpDevelop 4.2),添加SearchPanel添加支持虛擬space 一些bugfixesMarch 3, 2013:更新下載AvalonEdit 4.3.0.9390 (SharpDevelop 4.3)添加支持輸入法編輯器(IME)固定的一個主要缺陷,有時造成“InvalidOperationException:試圖建立視覺線從倒塌的線”當更新現有的褶皺。2013年4月2日:更新下載AvalonEdit 4.3.1.9430 (SharpDevelop 4.3.1)修復了一個IME支持上的錯誤——如果它被另一個WPF控件禁用,上一個版本就不能正確地重新啟用IME。 注意:雖然我的示例代碼是根據MIT許可提供的,但是ICSharpCode。AvalonEdit本身是根據GNU LGPL. 本文轉載於:http://www.diyabc.com/frontweb/news382.html