AvalonEditドキュメントの和訳 原文:AvalonEditドキュメント
ようこそ
AvalonEditは、WPFに基づく拡張可能なテキスト・エディタです。
WPFのRichTextBoxは、非常に強力ですが、コード・エディタとして使用しようとすると、すぐにその限界に突き当ります。:効率的な構文の強調表示を記述することが難しいです。そして、あなたは、標準のRichTextBoxで、コードの折りたたみなどの機能を実際に実装することはできません。
問題は以下の通りです:RichTextBoxは、リッチ・ドキュメントを編集します。対照的に、AvalonEditは、単純に、テキストを編集します。
しかしながら、AvalonEditは、テキスト文書の表示方法について多くの可能性を提供します。-それで、テキスト・カラーのようなものが、ユーザーによって制御されないコード・エディタに遥かに適しています。しかし、代わりにテキスト(構文強調表示)に依存します。
AvalonEditは、SharpDevelop IDEのために記述されました。これは、私たちの以前のWindows Formに基づくテキストエディタ(ICSharpCode.TextEditor)を置き換えます。
使用法
エディタのメイン・クラスは、ICSharpCode.AvalonEdit.TextEditorです。あなたは、それを通常のWPF TextBoxのように扱うことができます。:
Xml
<avalonEdit:TextEditor
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
Name="textEditor"
SyntaxHighlighting="C#"
FontFamily="Consolas"
FontSize="10pt"/>
システム要件
AvalonEditには、2つのバージョンがあります。-通常のものは、.NET Framework 4.0以上を必要とします。;しかし、また、私たちは、.NET 3.5 SP1のための修正版も提供しています。AvalonEditをコンパイルするには、C#4.0コンパイラが必要です。(SharpDevelop 4.x、あるいは、Visual Studio 2010)。
AvalonEditは、FullTrustを必要とし、XBAPとして実行されません。
サンプル・アプリケーション
SharpDevelopソース・コードのダウンロードにおいて、あなたは、SharpDevelop\samples\AvalonEdit.Sampleに、小さなサンプル・アプリケーションを見つけるでしょう。
Code Projectの記事
The Code Project article
サンプル・アプリケーションに基づいたCode Projectの記事があります。:http://www.codeproject.com/KB/edit/AvalonEdit.aspxしかしながら、その記事の資料のほとんどが、このヘルプファイルに含まれています。
アーキテクチャ
Architecture
この依存関係グラフでわかるように、AvalonEditは、仕事をそれほどきれいに切り離した、いくつかのサブ名前空間から構成されています。名前空間のほとんどは、一種の'main'クラスを持っています。
ここに、TextEditorコントロールのビジュアル・ツリーがあります。
AvalonEditが、3つのレイヤーを持つ複合コントロールであることを理解することが重要です。:TextEditor(メイン・コントロール)、TextArea(編集)、TextView(レンダリング)。
メイン・コントロールは、共通のタスクのためのいくつかの便利なメソッドを提供しますが、 最も先進的な機能のために、あなたは、内部のコントロールを直接操作する必要があります。 あなたは、textEditor.TextAreaやtextEditor.TextArea.TextViewを用いて、アクセスすることができます。
座標系
Coordinate Systems
テキストエディタは、いくつかの異なる座標系を使用します。ここに、それらの説明があります。
オフセット
Offset
オフセットは、通常、2つの文字の間の位置を表現します。ドキュメントの始点の最初のオフセットは、0です;ドキュメント内の最初のcharの後のオフセットは、1です。最後の有効なオフセットは、文書の終わりを表すdocument.TextLengthです。これは、.NET String、あるいは、StringBuilderクラスのメソッドによって使用されるインデックス・パラメータとまったく同じです。
TextLocation
ICSharpCode.AvalonEdit.Document.TextLocation構造体は、行/列のペアを表します。線分と列は、1から数えられます。
この文書は、オフセットとTextLocationsの間で変換するために、メソッドTextDocument.GetLocation(Int32)とTextDocument.GetOffset(TextLocation)を提供します。
TextAnchor
あなたが、テキスト・エディタで作業している場合、あなたは、おそらく、オフセットを格納する必要がありますが、そのオフセットの前に、テキストが挿入されるたびに、自動的に調整する問題にぶつかるでしょう。
もちろん!あなたは、TextDocument.Changedイベントを聞き取ることができました。そして、オフセットを変換するために、DocumentChangeEventArgs上で、GetNewOffsetを呼び出しますが、それは面倒です。;特に、あなたのオブジェクトが短命であるとき、そして、あなたは、適切な時点で、イベント・ハンドラの登録を解除する必要があります。
テキストのアンカー・オブジェクトは、Offsetを格納します。しかし、オフセットの前に、テキストが挿入/削除されるとき、オフセットを、自動的に更新します。
はるかに簡単な解決策は、ICSharpCode.AvalonEdit.Document.TextAnchorクラスを使用することです。詳細については、そのクラスのドキュメントをご覧ください。
RelativeTextOffset
文書内のオフセットですが、VisualLineの開始オフセットとの相対的なオフセットです。
相対的なテキストのオフセットは、外観の行に、ドキュメントのオフセットを格納するために使用されます。
あなたは、VisualLine.FirstDocumentLine.Offsetを追加/削除することによって、相対的にテキストのオフセットとドキュメントのオフセットの間で変換することができます。
VisualColumn
VisualLine内の位置を指定する整数値
テキストは、外観の行の長さを持っているだけでなく、他のVisualLineElementsも使用できます。 VisualColumnは、それぞれの外観の行を0から数えています。
例えば、タブ・マーカーは、2つの外観の列(マーカーとタブ・スペース)を取得します。改行マーカーは、1つの外観の列を取得します。;折り畳みのマーカーは、1つの外観の列だけを取得しますが、文書のテキストの方が長くなっています。
外観の列と相対なテキストのオフセットを変換するために、VisualLine.GetVisualColumn(Int32)とVisualLine.GetRelativeOffset(Int32)メソッドを使用します。
備考:
VisualColumnとテキストの列を混同しないでください。VisualColumnは、0で始まり、テキストの列は、1で始まります。テキストは、2つの座標系(例えば、タブ・マーカー、折り畳み)で、異なる長さを持つかもしれません。
TextViewPosition
Line、Column、VisualColumnは、3つの組になります。
ICSharpCode.AvalonEdit.TextViewPosition構造体は、暗黙的に、TextLocationに変換することができます。しかし、0のDocumentLengthを持つVisualLineElementsが、使用されているとき、挿入記号の位置を正確に保持するために、必要な追加のVisualColumnの情報を持っています。
VisualTop
double値は、デバイスに依存しないピクセルで測定された、文書の一番上から行の一番上までの距離を指定します。
VisualTopは、VisualPositionのYコンポーネントと同等です。
VisualPosition
Point値(double X,Y)は、文書の左上角から、デバイスに依存しないピクセルで測定された要素の位置を指定します。
VisualPositionをTextView内の(マウスの)位置に変換するために、単純に、TextView.ScrollOffsetを減算、あるいは、加算します。
テキスト・レンダリング
この文書は、TextViewクラスが、テキストに、どのように、レンダリングするか、そして、あなたが、テキスト・エディタに新しい機能を追加するために、テキスト・レンダリングのプロセスを、どのように、拡張できるかを説明します。
ICSharpCode.AvalonEdit.Rendering.TextViewクラスは、文書を画面に表示する処理を行う、AvalonEditの心臓部です。
これを拡張可能な方法で行うために、TextViewは、独自の種類のモデルを使用します。:VisualLine。行の表示は、文書の見える部分だけ作成されます。
レンダリング工程は、次のようになります。:
「要素ジェネレーター」、「線形変成器」と「背景レンダラー」は、拡張ポイントです。;それらのカスタム実装をTextViewに追加して、エディタに追加機能を実装することができます。
VisualLinesの寿命
Lifetime of VisualLines
文書の見える部分ために、VisualLinesだけが、作成されます。たくさんの動作は、それらの作成を起動することができます。しかし、最も一般には、作成は、TextViewのMeasureOverrideメソッドによって行われます。TextViewが、測定されるとき、それは、見える領域で、最初のドキュメントの行を決定する、高さツリーを使用します。続いて、それは、最初の行のために、VisualLineを構築し、測定します。そして、表示される領域が、満たされるまで、以下の行で繰り返します。
TextViewは、VisualLinesをキャッシュに格納します-ユーザーが、下にスクロールするとき、Viewにやって来るVisualLinesだけが、作成され、残りは、再利用されます。VisualLineキャッシュは、Redrawメソッド・ファミリーを使用して、手作業で、無効することができます。;さらに、たくさんの動作は、自動で、無効化を引き起します。:
- 文書の変更により、影響を受けたVisualLinesが、無効になります。
- ワードラップが、有効にされる場合、TextViewの幅の変更は、すべてのVisualLinesを無効にします。
- テキストエディタの設定(ワードラップ、フォントサイズなど)を変更すると、すべてのVisualLinesが無効になります。
- スクロールの後、表示領域をそのままにするVisualLinesは、廃棄されます。
一般に、また、あなたが、外部データを利用するテキスト・エディタ拡張機能(BackgroundRenderer、VisualLineElementGeneratorやVisualLineTransformer)を書き込む場合だけ、手作業で、無効にする必要があります。-その場合、あなたの外部データが、変更されたとき、あなたは、VisualLineを再作成する必要があることを、テキストエディタに通知する必要があります。
備考:
あなたのテキスト・エディタ拡張機能によって使用される外部データを変更する場合、VisualLineを無効にするために、TextView.Redraw()を呼び出します。
VisualLinesを無効にしても、すぐに行が再作成されることはありません!それよりも、テキストビューが、次に再測定されると、VisualLineが再作成されます。WPFの測定の間、通常、DispatcherPriority.Renderで発生します。また、TextViewは、それに比べてより低い優先順位で、再描画をサポートしています。例えば、ユーザーが、テキストのViewが再描画するより速く入力する場合、複数の入力動作のために、1つだけ再描画するため、通常のテキストの挿入は、背景優先で、再描画を生じます。
備考:
TextViewは、あなたに、無効な行を返すことはありません。しかし、あなたは、有効な外観の行が利用できない場合に出会う可能性があります。
この場合、何が発生するかは、あなたが呼び出しているメソッドに依存します。-自動的に、新しい外観の行が、作成される、nullが返される、あるいは、あなたが、VisualLinesInvalidExceptionを取得するかもしれません。
あなたは、可視域内ですべてのVisualLinesを作成する、テキスト・ビューを作成するために、TextView.EnsureVisualLines()を呼び出すことができます。
外観の行要素を構築する
Building visual line elements
例えば、行は、テキスト"Hello, World"が含まれます。ユーザーは、"ShowSpaces"を有効にしました。 それで、テキスト・エディタは、スペースの代わりに小さな点を表示する必要があります。
この場合、SingleCharacterElementGeneratorは、空白文字のために"SpaceTextElement"を作成するShowSpacesのための役割を果たします。他のどのジェネレーターも行に、興味を持っていないため、 残りの文字列"Hello,"、そして、"World"は、VisualLineText要素で表示されます。
外観の行の要素を変換する
Transforming visual line elements
その後、IVisualLineTransformerを使用して、生成された行の要素を変更します。Transformerは、要素を追加してはいけません。しかし、例えば、要素の一部だけ色付けするために、それらは、既存の要素を分割するかもしれません。要素を分割(あるいは、何らかの形で要素のコレクションを変更)するとき、VisualColumn、VisualLine、RelativeTextOffset、およびDocumentLengthプロパティが、正しく維持されるように注意する必要があります。
ColorizingTransformer基底クラスは、分割のために、ヘルパー・メソッドを提供します。それで、派生クラスは、単純に「その色で、このセクションに色をつける」と言うことができます。
DocumentColorizingTransformerは、ColorizingTransformerを拡張し、さらにDocumentLineごとに強調表示することができます。(外観の行の要素で直接動作する代わりに)テキストセグメントに色をつけます。
TextLinesを構築する
Constructing TextLines
外観の行の要素を構築した後に、外観の行のためのTextLinesは、構築されます。ワードラップが、アクティブであるとき、あるいは、特別な外観の行の要素が、改行を強制するとき、外観の行は、複数のテキスト行に、結果として生じる場合があります。テキスト行の構築:テキスト行の構築は、WPFのTextFormatterによって行われます。WPF TextFormatterが、単語の折り返しなどを処理している間、VisualLineTextSourceは、外観の行の要素を取得する、そして、それから、WPF TextRunsを構築する場合があります。VisualLineElementsは、それらの全て、あるいは、一部の長さのTextRunを生成するために、要求されます。TextViewが、外観の行のインラインUI要素を測定することに注意します。
レンダリングの残りの部分
Rest of the Rendering
見える領域が満たされたあと、TextViewは、ドキュメントの行に、測定された高さの格納された高さを更新します。この方法では、スクロールは、単語の折り返しが考慮されます。構築されたテキスト行は、配置、そして、レンダリング段階のために、格納されます。さて、ついに、測定ステップが完了しました。
WPFの配置ステップは、あまり多くの作業を必要としません。:それは、まさに、テキスト内のそれらの位置に、インラインUI要素を配置します。
実際のレンダリングは、TextViewではなく、さまざまなレイヤーで、直接行われます。
これらは、あらかじめ定義されたレイヤーです。:
- 背景層:ビジュアル要素に関連付けられた背景色をレンダリングします。
- 選択層:選択範囲の背景をレンダリングします。
- テキスト層:Measureステップで作成されたTextLinesをレンダリングします。AvalonEdit 4.1以降では、TextLayerは、テキストを描画するために、子要素を使用します。:それぞれのVisualLineのために、1つのDrawingVisual
- テキストの層の直後に、どんなインラインUI要素でも、まるで、それらが別々の層であるように、配置されます。
- 挿入記号の層:点滅する挿入記号をレンダリングします
また、TextView.InsertLayer(UIElement、KnownLayer、LayerInsertionPosition)メソッドを使用して、TextViewに、新しい層を挿入することもできます。これは、Zオーダーを完全に制御しているとき、カスタム対話的コンポーネントをエディタに追加できます。
構文の強調表示
Syntax Highlighting
おそらく、テキストエディタの最も重要な機能は、構文の強調表示です。
AvalonEditは、柔軟なテキスト・レンダリングのモデルを持っています。テキスト・レンダリング参照、テキスト・レンダリング拡張機能のポイントは、「外観の行の変換」のサポートです。それは、「外観要素ジェネレーター」によって構築された後に、外観の行の表示を変更することができます。 構文の強調表示の目的のために、役に立つ実装された基底クラスIVisualLineTransformerは、DocumentColorizingTransformerです。完全な、ユーザー定義した構文の強調表示を、どのように、記述するかについては、そのクラスのドキュメントを調べて下さい。この記事では、XMLに基づいた組み込みの強調表示エンジンについてのみ説明します。
強調表示エンジン
The highlighting engine
AvalonEditの強調表示エンジンは、クラスDocumentHighlighterで実装されています。強調表示は、色を行の別のセクションに割り当てることによって、DocumentLineを取得して、それに対するHighlightedLineインスタンスを構築するプロセスです。HighlightedLineは、単純な(おそらくネストされた)強調されたテキストのセクションのリストです。
HighlightingColorizerクラスは、強調表示とレンダリングの間の唯一のリンクです。それは、ライン・トランスレータを実装するDocumentHighlighterを使用します。それは、レンダリング工程の外観の行の強調表示に適用されます。
この一回の呼び出しを除いて、構文の強調表示は、rendering名前空間とは独立しています。強調表示エンジンの他の潜在的な使用法の役に立てるために、HighlightedLineクラスは、構文強調されたHTMLソース・コードを作成するために、メソッドToHtml()を持っています。
強調表示エンジンで、文書を強調するために使用する強調表示の規則は、次のクラスによって、記述されます。:
- HighlightingRuleSet
強調表示規則は、色を持つ正規表現です。その色を使用する正規表現の一致を強調表示します。
- HighlightingSpan
範囲は、2つの正規表現(StartとEnd)、色と子のルール・セットから構成されています。StartとEnd式の間の領域は、与えられた色を割り当てられます。そして、その範囲内で、子のルールのルール・セットの規則が、適用されます。子ルールセットにもHighlightingSpansがある場合、入れ子になったコメントや他の埋め込まれた1つの言語のような強調表示構造を可能にする、入れ子にすることができます。
- HighlightingRule
強調表示規則は、色を持つ正規表現です。その色を使用する正規表現の一致を強調表示します。
- HighlightingColor
強調表示の色は、単なる色ではありません:それは、前景色、フォントの太さとフォントスタイルから構成されています。
強調表示エンジンは、最初にspansを分析することで動作します。:beginの正規表現が、いくつかのテキストに一致するたびに、そのspanは、スタックにプッシュされます。現在のspanのend正規表現が、いくつかのテキストに一致するたびに、spanは、スタックからポップされます。
各々のspanは、それに関連付けられた入れ子になった規則設定を持っています。それは、既定では、空です。そういうわけで、キーワードは、コメントの中では強調されません。:spanの空のルール・セットは、キーワード規則は、適用さないため、そこでは、アクティブです。
この機能は、同様に、文字列spanでも使用されます。:入れ子になった範囲は、一致する場合があります。バックスラッシュに遭遇した場合、そして、バックスラッシュに続く文字は、入れ子になった範囲のendの正規表現で利用されます(.は、いずれかを文字と一致します)。これは、\ "が、文字列範囲の終わりを示さないことを保証します。;しかし、\\"は、依然としてそうです。
強調表示エンジンの素晴らしい点は、それがオンデマンドだけで、強調されることです。段階的に動作します。そして、大規模なコードファイルであっても、通常は、数KBのメモリしか必要としません。
オンデマンドは、文書が開かれているときを示しています。最初に表示された行だけが、強調表示されます。ユーザーが、下にスクロールするとき、強調表示は、最後に停止した場所から継続します。 ユーザーが、速くスクロールする場合、そのため、最初に表示される行は、最後に強調された行のはるか下にあります。続いて、強調表示エンジンは、まだ、その間、処理するために、すべての行を持っています。?そこから、コメントが始まる場合があります。しかしながら、それは、spanスタック内で、変更するために、その領域を走査するだけです。;強調表示規則は、検証されません。
アクティブなスパンのスタックは、すべての行の開始時先頭に格納されます。ユーザーが、スクロールを元に戻す場合、必要なコンテキスト(spanスタック)が、まだ、利用できるため、見える行は、すぐに、強調することができます。
段階的に、文書が変更される場合でも、示しています。格納されたスパン・スタックは、できるだけ再利用されます。ユーザーが、/*を入力する場合、それは、理論的には、全体のファイルの残りが、コメントの色で強調表示されます。しかしながら、エンジンが、要求に応じて動作するため、それは、現在表示される領域内の範囲のスタックだけを更新し、通知を保持します。'強調表示の状態は、行Xと行 X+1の間で一貫していません'、Xは、見える領域の最終行の場所です。次に、ユーザーが、下にスクロールする場合、強調表示の状態は更新されます。そして、'一貫性のない'通知が下に移動されます。しかし、通常、ユーザーは、入力を続け、数行後に */ と入力します。次に、見える領域の強調表示の状態は、通常の'メイン・ルール・セットだけが、アクティブなスパンのスタック'に戻ります。 ユーザーが、現在、'一貫性のない'目印で行で下にスクロールするとき、エンジンは、古いスタックと新しいスタックが同一であることを警告します。そして、'一貫性がない'目印を削除します。これは、ユーザーが入力した/*の前の、キャッシュされた格納されたspanスタックを再利用できます。
アクティブなスパンのスタックが、行内で、頻繁に変更されますが、それは、めったに、1つの行の始まりから、次の行の始まりに、変更しません。ほとんどの言語では、そのような変更は、複数行コメントの始点と終端でのみ発生します。強調表示エンジンは、範囲スタックのリストを特別なデータ構造(CompressingTreeList<T>)に格納することによって、このプロパティを利用します。強調表示エンジンのメモリー使用状況は、spanスタックの変更の数に比例します。;行の合計数ではなく。これは、強調表示エンジンが、少しのメモリだけを使用して、大きなコード・ファイルのためのspanスタックを格納できます。特に、C#のような言語では、//や///のシーケンスが、/* */コメントより人気があります。
XMLの強調表示定義
XML highlighting definitions
AvalonEditは、XML構文の強調表示定義(.xshdファイル)をサポートしています。
AvalonEditのソース・コードで、あなたは、ファイルICSharpCode.AvalonEdit\Highlighting\Resources\ModeV2.xsdを見つけることができます。これは、.xshdファイル形式のためのXMLスキーマーです。;あなたは、それを、XMLエディタで、xshdファイルのためのコードを補完するために使用することができます。
ここに、C#のサブセットの強調表示の例の定義があります。
Xml
<SyntaxDefinition name="C#"
xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008">
<Color name="Comment" foreground="Green" />
<Color name="String" foreground="Blue" />
<!-- This is the main ruleset. -->
<RuleSet>
<Span color="Comment" begin="//" />
<Span color="Comment" multiline="true" begin="/\*" end="\*/" />
<Span color="String">
<Begin>"</Begin>
<End>"</End>
<RuleSet>
<!-- nested span for escape sequences -->
<Span begin="\\" end="." />
</RuleSet>
</Span>
<Keywords fontWeight="bold" foreground="Blue">
<Word>if</Word>
<Word>else</Word>
<!-- ... -->
</Keywords>
<!-- Digits -->
<Rule foreground="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>
ICSharpCode.TextEditor XMLの強調表示定義
ICSharpCode.TextEditor XML highlighting definitions
ICSharpCode.TextEditor(AvalonEditの前身)では、異なるバージョンのXSHDファイル形式が使用されていました。AvalonEditは、XML名前空間を使用してフォーマット間の違いを検出します。:新しい形式は、xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"を使用しますが、古い形式ではXML名前空間は使用しません。
AvalonEditは、その以前のフォーマットで記述された.xshdファイルを読み込むことができます。そして、さらに、自動的に、それらを新しいフォーマットに変換します。しかしながら、以前のファイル形式のすべての構文が、AvalonEditによってサポートされるというわけではありません。
// convert from old .xshd format to new format
XshdSyntaxDefinition xshd;
using (XmlTextReader reader = new XmlTextReader("input.xshd")) {
xshd = HighlightingLoader.LoadXshd(reader);
}
using (XmlTextWriter writer = new XmlTextWriter("output.xshd", System.Text.Encoding.UTF8)) {
writer.Formatting = Formatting.Indented;
new SaveXshdVisitor(writer).WriteDefinition(xshd);
}
強調表示の情報をプログラム上で呼び出す
Programmatically accessing highlighting information
先に述べたように、強調表示エンジンは、各行の先頭に"スパンスタック"しか格納しません。この情報は、GetSpanStack(Int32)メソッドを使用して取得できます。:
C#
bool isInComment = documentHighlighter.GetSpanStack(1).Any(
s => s.SpanColor != null && s.SpanColor.Name == "Comment");
// returns true if the end of line 1 (=start of line 2) is inside a multiline comment
範囲は、それらの色を使用して識別できます。この目的のために、色の名前は、構文定義で使用する必要があります。
行の内側のさらに詳細な結果については、強調表示アルゴリズムを、その行に対して実行する必要があります。:
C#
int off = document.GetOffset(7, 22);
HighlightedLine result = documentHighlighter.HighlightLine(document.GetLineByNumber(7));
bool isInComment = result.Sections.Any(
s => s.Offset <= off && s.Offset+s.Length >= off
&& s.Color.Name == "Comment");
折り畳み
Folding
あなたのアプリケーションでFoldingを使用する方法
How to use Folding in your application
折り畳み(コードの折り畳み)は、エディタへの拡張機能として実装されています。それは、AvalonEditコードを修正する必要がない、別々のアセンブリで実装することができます。VisualLineElementGeneratorは、テキスト文書の折り畳まれたセクションを処理します。そして、カスタム・マージンは、正負ボタンを描画します。
あなたは、別々に関連したクラスを使用できます。;しかし、それを少し使いやすくするために、静的FoldingManager.Install(TextArea)メソッドは、自動的に、必要な部分を作成して、登録します。
あなたのために残されているのは、あなたが提供したい折り畳みのリストでFoldingManager.UpdateFoldings(IEnumerable<NewFolding>, Int32)を定期的に呼び出すことです。 あなたは、自分で、そのリストを計算することができます。あるいは、あなたは、組み込みの折りたたみ戦略を使って、それを実行することができます。
ここに、折り畳みを有効にするために必要とされる完全なコードがあります。:
C#
foldingManager = FoldingManager.Install(textEditor.TextArea);
foldingStrategy = new XmlFoldingStrategy();
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);
テキストが変更されるとき、あなたが、折り畳みマーカーを更新したい場合、あなたは、定期的にfoldingStrategy.UpdateFoldings呼び出しを繰り返す必要があります。
FoldingManagerは、どのように動作するか
How the FoldingManager works
FoldingManagerは、折り畳みのリストを保持します。FoldMarginは、それらの折り畳みを表示し、折り畳み/展開のためのUIを提供します。
折り畳まれた折り畳みは、折り畳まれたテキストのセクション全体にわたる、行要素を作成するために、FoldingElementGeneratorを引き起します。他の行の折り畳みの終端の後に、継続するために、折り畳みの始点が含まれている、外観の行のためのテキスト生成を引き起こします。
折り畳みの存在下でスクロールが、適切に動作することを保証するために、折り畳まれた領域の内の行は、使用してはいけません。外観の行を生成するための、開始行として、これは、行の高さを、すべて行を0に設定することによって行われます。多数の行の高さを効率的に設定する、そして、以前の高さに戻ってサポートするために、折り畳みが、折り畳まれていないとき、CollapsedLineSectionが、使用されます。
コード補完機能
Code Completion
AvalonEditには、コード補完ドロップ・ダウン・ウィンドウが付属しています。あなたは、決定するテキストの入力イベントだけを処理する必要があります。あなたが、ウィンドウを表示したいとき、;すべてのUIは、既に、あなたのために行われています。
コード補完ウィンドウの使用法
Usage of the Code Completion Window
C#
// 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.
// e.Handled = trueを設定しないでください。
// We still want to insert the character that was typed.
// 私たちは、まだ、入力された文字を挿入することを望みます。
}
'.'が押されるたびに、このコードは、コード補完機能ウィンドウを開きます。既定では、CompletionWindowは、現在選択された項目を挿入するために、TabやEnterのような、キー入力だけを処理します。また、それを完全に作成するために、'.' や ';'のようなキーが押されるとき、私たちは、他のハンドラをTextEnteringイベントに添付します。そして、選択した項目を挿入するために、ウィンドウの補完を伝えます。
CompletionWindowには、実際には、フォーカスがありません。-その代わりに、それは、テキストの領域上で、WPFのキーボード入力イベントを乗っ取ります。そして、エディタで、同時に、キーボードと通常の入力を使用して、それらをListBoxに渡します。これは、補完リストで入力を選択できます。
ここに、上記のコードで使用されている、MyCompletionDataクラスの実装があります。
C#
/// Implements AvalonEdit ICompletionData interface to provide the entries in the
/// completion drop down.
/// 補完ドロップ・ダウンで項目を提供するために、
/// AvalonEdit ICompletionDataインターフェイスを実装します。
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.
// 補完ドロップ・ダウンで項目を提供するために、
// AvalonEdit ICompletionDataインターフェイスを実装します。
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);
}
}
あなたが、リストで、意匠を凝らしたUIElementを表示したい場合、このプロパティを使用します。
表示れるコンテンツと説明の両方は、カスタムUIElementを含む、WPFで受け入れ可能なコンテンツである場合があります。あなたが、単純にテキストを挿入する以上のことをしたい場合、あなたは、Completeメソッドでカスタム・ロジックの実装もするかもしれません。insertionRequestEventArgsは、ユーザーが、どの種類の挿入を望むか、決定するために、役に立てることができます。-挿入がどのようにトリガされたかに応じて、それは、TextCompositionEventArgs、KeyEventArgsやMouseEventArgsのインスタンスです。
C#のためのコード補完機能
Code Completion for C#
完全なC#コード補完は、AvalonEditの領域ではありません。あなたのデータ型システムで、C#パーサ、C#データ型システム、そして、C#式を解決する機能が必要です。
あなたが、SharpDevelopで、これがどのように処理されるか学びたい場合、以下を参照して下さい: SharpDevelopのコード補完機能