#author("2021-12-14T02:32:35+00:00","","")
// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents

**テキストエディタを作る。 [#r1c4624c]
本丸のエディタを作ってみました。テキストファイル内で、%%と%%に囲まれた場所だけをハイライトするテキストエディタを作ってみました。

***TextEditorクラスのサブクラスを作る [#q8b4fa87]
 import org.eclipse.ui.editors.text.TextEditor;
 
 public class ScriptEditor extends TextEditor {
   private ColorManager colorManager; <-Colorクラスを管理するユーティリティクラス
   public ScriptEditor() {
     super();
     colorManager = new ColorManager(); ↓後述
     setSourceViewerConfiguration(new ScriptConfiguration(colorManager));
     setDocumentProvider(new ScriptDocumentProvider());
                                  ↑後述
   }
 
   public void dispose() {
     colorManager.dispose();
     super.dispose();
   }
 
 }

*** org.eclipse.jface.text.rules.RuleBasedPartitionScanner のサブクラスを作成する。 [#d5fba67d]
このクラスは、どのようにドキュメント(エディタが編集するテキスト)のパーティションを切るかを設定します。後に、ScriptDocumentProviderクラス内で呼び出されます。

 package nu.mine.kino.plugin.script.editors;
 
 import org.eclipse.jface.text.rules.IPredicateRule;
 import org.eclipse.jface.text.rules.IToken;
 import org.eclipse.jface.text.rules.MultiLineRule;
 import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
 import org.eclipse.jface.text.rules.Token;
 
 public class ScriptPartitionScanner extends RuleBasedPartitionScanner {
   public static final String SCRIPT_VAR = "__script_var";
   public ScriptPartitionScanner() {
     IToken var = new Token(SCRIPT_VAR);
     IPredicateRule[] rules = new IPredicateRule[1];
     // rules[1] = new TagRule(tag);
     rules[0] = new MultiLineRule("%%", "%%", var);
     setPredicateRules(rules);
   }
 }
これで、%% から %%で囲まれた場所は、SCRIPT_VARというパーティションであるという設定ができました。


*** org.eclipse.ui.editors.text.FileDocumentProvider のサブクラスを作成する。[#f2f4b9e4]
ScriptEditorの処理でsetDocumentProviderの引数に指定されたScriptDocumentProvider はFileDocumentProviderを拡張しています。このクラスでFileDocumentProvider#IDocument createDocument(Object element) throws CoreException を Overrideします。そのメソッド内でIDocumentPartitionerの実装クラスを設定しています。
 protected IDocument createDocument(Object element) throws CoreException {
   logger.debug("createDocument(Object) - start");
 
   IDocument document = super.createDocument(element);
   if (document != null) {
     IDocumentPartitioner partitioner = new FastPartitioner(
         new ScriptPartitionScanner(), <-さっき作ったヤツ
         new String[] { ScriptPartitionScanner.SCRIPT_VAR });
     partitioner.connect(document);
     document.setDocumentPartitioner(partitioner);
   }
 
   logger.debug("createDocument(Object) - end");
   return document;
 }

***org.eclipse.jface.text.source.SourceViewerConfiguration のサブクラスを作る [#ca436f62]
SourceViewerConfiguration#public IPresentationReconciler getPresentationReconciler をOverride します。

 public IPresentationReconciler getPresentationReconciler(
     ISourceViewer sourceViewer) {
   logger.debug("getPresentationReconciler(ISourceViewer) - start");
 
   PresentationReconciler reconciler = new PresentationReconciler();
 
   Color color = colorManager.getColor(IScriptColorConstants.SCRIPT_VAR);
   TextAttribute attribute = new TextAttribute(color);
   SingleTokenScanner singleTokenScanner = new SingleTokenScanner(
       attribute);
 
   DefaultDamagerRepairer dr = new DefaultDamagerRepairer(
       singleTokenScanner);
   reconciler.setDamager(dr, ScriptPartitionScanner.SCRIPT_VAR);
   reconciler.setRepairer(dr, ScriptPartitionScanner.SCRIPT_VAR);
 
   logger.debug("getPresentationReconciler(ISourceViewer) - end");
   return reconciler;
 }
ここまでで、SCRIPT_VARというパーティション(ここは%%〜%%内という区画(パーティション)でした)にDefaultDamagerRepairer というダメージャ、リペアラが設定されました。このDefaultDamagerRepairerにはSingleTokenScanner というスキャナを渡してあります。このスキャナは下記の通り。。

 private class SingleTokenScanner extends BufferedRuleBasedScanner {
   public SingleTokenScanner(TextAttribute attribute) {
     setDefaultReturnToken(new Token(attribute));
   }
 }
ちなみに他のクラスはこんな感じ。

 public interface IScriptColorConstants {
   RGB SCRIPT_VAR = new RGB(255, 0, 0); <-赤。
 }

 public class ColorManager {
   protected Map fColorTable = new HashMap(10);
   public void dispose() {
     Iterator e = fColorTable.values().iterator();
     while (e.hasNext())
       ((Color) e.next()).dispose();
   }
 
   public Color getColor(RGB rgb) {
     Color color = (Color) fColorTable.get(rgb);
     if (color == null) {
       color = new Color(Display.getCurrent(), rgb);
       fColorTable.put(rgb, color);
     }
     return color;
   }
 }

実際にEclipseでこのプラグインを実行してテキストファイルを開いてみると、%%〜%%内だけが赤字になっています。でもこれだとその外、つまりSCRIPT_VARのパーティション外の箇所にダメージャ・リペアラが設定されていないため、そこにダメージャ・リペアラを設定します。この、定義したパーティション以外の箇所はIDocument.DEFAULT_CONTENT_TYPE という名前がついています。よってgetPresentationReconcilerメソッド内に以下の記述を追加します。
 Color defaultColor = colorManager
     .getColor(IScriptColorConstants.DEFAULT);
 TextAttribute defaultAttr = new TextAttribute(defaultColor);
 dr = new DefaultDamagerRepairer(new SingleTokenScanner(defaultAttr));
 reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
 reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);


** アウトラインを使う [#d12c3305]
[[プロパティシートを使う>Eclipse/プラグイン開発のTIPS集/プロパティシートを使う]]のと同様に、TextEditorのサブクラスのgetAdapterメソッドをOverrideします。
 public Object getAdapter(Class adapter) {
   if (IContentOutlinePage.class.equals(adapter)) {
     if (fOutlinePage == null) {
       fOutlinePage = new ScriptContentOutlinePage(
           getDocumentProvider(), this);
       if (getEditorInput() != null) {
         fOutlinePage.setInput(getEditorInput());
       }
       fOutlinePage.addSelectionChangedListener(this);
     }
     return fOutlinePage;
   }
   return super.getAdapter(adapter);
 }

ScriptContentOutlinePageはIContentOutlinePageをimplementsしたクラスです。

** TIPS集 [#xb55af55]
***あるテキストを選択状態にする。 [#y6efd2aa]
例えば、アウトラインでクリックした箇所にカーソルを移動して、そこを選択状態にしたい場合((Eclipseではアウトラインのメソッドをクリックすると、そのメソッドに遷移して、メソッド名が選択状態になりますね))
- 処理をTextEditorのサブクラスでやる場合

protectedな下記のメソッドが使用できます。
 ISelection selection = event.getSelection();
 if (!selection.isEmpty()) {
     int start =  開始位置
     int length = 長さ
     getSourceViewer().getTextWidget().setSelectionRange(start,
             length);
 }

他に、
 getSourceViewer().getTextWidget().setSelection(start,start + length);
や
 ISourceViewer sourceViewer = getSourceViewer();
 StyledText textWidget = getSourceViewer().getTextWidget();
 try {
     textWidget.setRedraw(false);
     sourceViewer.revealRange(start, length);
     sourceViewer.setSelectedRange(start, length);
 } finally {
     textWidget.setRedraw(true);
 }



- 処理をTextEditorのサブクラスではないものでやる場合

publicな下記のメソッドを使用します。
 ITextEditor#selectAndReveal(int start, int length);





*** アクティブなエディタへの参照の取得 [#uf7ea3d1]
 // ワークベンチの取得
 IWorkbench workbench = PlatformUI.getWorkbench();
 IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
 
 //アクティブなエディタの取得
 IEditorPart editor = window.getActivePage().getActiveEditor();
 AbstractTextEditor aEditor = (AbstractTextEditor) editor;

*** エディタ内のドキュメントを取得 [#o1b1fa35]
 IDocument document =
   aEditor.getDocumentProvider().getDocument(editor.getEditorInput());





** 関連リンク [#sf5a98b6]
-[[このサイト内のサンプルソースのCVS:http://www.masatom.in/cgi-bin/viewvc.cgi/nu.mine.kino.plugin.script/?root=cvs]]
-[[SourceViewerを使用するドキュメントの分割と構文強調表示:http://www13.plala.or.jp/observe/JFace/jfaceSourceViewer.html]]
-[[自作エディタの定義:http://yoichiro.cocolog-nifty.com/eclipse/2004/05/post.html]]
-[[作って覚えるEclipseプラグイン(3)テキストエディタプラグインの実装:http://www.atmarkit.co.jp/fjava/rensai3/eclipsepde03/eclipsepde03_2.html]]
-[[Eclipse エディタ調査報告書:http://staff.aist.go.jp/y-ichisugi/mj/2003/editor/eclipse_editor.html]]



----
この記事は
#vote(おもしろかった[19],そうでもない[0])
#vote(おもしろかった[20],そうでもない[0])
-JavaEditorで使用するパーティション名があるクラス: org.eclipse.jdt.internal.ui.text.JavaPartitionScanner -- [[きの]] &new{2006-02-08 08:48:45 (水)};
-何故か、他のクラスでITextEditor#setHighlightRange してたら、コンフリクトするのか選択状態にならなかった。同じメソッド内でシーケンシャルに処理すると大丈夫なんだけど。 -- [[きの]] &new{2006-02-09 20:10:46 (木)};
-つうかそもそもselectAndRevealだけでハイライトも変わるんだね。 -- [[きの]] &new{2006-02-09 20:11:29 (木)};
-XMLBuddyをプラグインでインポートして、オラオラってソース読んでたんですけど。。。 -- [[きの]] &new{2006-02-09 20:12:19 (木)};
-パーティション切るときにTokenに指定する引数と、スキャナで更にハイライトするときなどに指定するTokenの引数の違いがようわからん。。。 -- [[きの]] &new{2006-02-12 01:37:14 (日)};

#topicpath


SIZE(10){現在のアクセス:&counter;}

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS