RCPを使用したスタンドアロンGEFアプリケーション

今回は、Eclipse3.0で導入されたRCPを使用した、スタンドアロン・GEFアプリケーションの作成を行います。

■今回作成するアプリケーションの概要

Eclipseバージョン3.0では、RCPが導入されたために、これまで面倒だったスタンドアロン・GEFアプリケーションの作成が簡単にできるようになりました。そこで、今回はRCPを使用したスタンドアロン・GEFアプリケーションの作成を行いたいと思います。まず、スタンドアロンとして動作させるGEFアプリケーションは、GEFでHelloWorldで作成したアプリケーションを使用します。次に、これをGEF3.0でも動作するようにし、最終的にはRCPアプリケーションとしてスタンドアロンで動作させることが出来るようにします。

■GEF3.0への移植

まず最初に今回作成するアプリケーションに必要なものを揃えてください。

Eclipseバージョン3.0
GEFバージョン3.0
HelloWorldアプリケーション(第10回のもの:GEF10.zip)

次に、GEF10.zipを適当なディレクトリに展開し、Eclipse3.0のワークスペースにインポートしてください。すると、必要なプラグインが見つからないために幾つかのエラーがProblemsビューに表示されます。そこで、必要なプラグインにorg.eclipse.ui.viewsとorg.eclipse.core.runtimeを追加します。まず、plugin.xmlファイルをダブルクリックしてプラグイン・マニフェスト・エディタを開き、Dependencies(依存性)ページを表示してください。次に、Addボタンを押下し、Plug-in Selectionダイアログを表示し、リストの中から、org.eclipse.ui.viewsを選択してOKを押下してください。又、同様にしてorg.eclipse.core.runtimeを追加してください。

これで、幾つかの警告が残ってはいるものの、バージョン3.0でも動作するようになったので、ランタイム・ワークベンチを起動して確認してみます。まず、ランタイム・ワークベンチの起動構成を作成していない場合は、EclipseのメニューからRun→Run...と選択して、Runダイアログを表示してください。次に、ダイアログの左側のツリー・コントロールからRun-time Workbenchを選択し、Newボタンをクリックしてください。次に、ダイアログの右側のNameエディット・コントロールに追加された起動構成(New_configuration)の名前として、’ランタイムワークベンチ’と入力して、Runボタンをクリックしてください。

これで、ランタイム・ワークベンチが起動されるはずです。ランタイム・ワークベンチが起動されたら、適当なプロジェクトを作成し、そのプロジェクトにhello.worldという名前のファイルを作成してください。以下のように、HelloWorldEditorが起動されれば成功です。

これで、Eclipse3.0でも一応動作するようになりました。しかし、まだ8つほど警告が残っているので、次にこれを解消することにします。まず、MyContributorクラスを以下のように書き換えてください。

リスト1:MyContributor.java
package gef.example.helloworld;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.ui.actions.ActionBarContributor;
import org.eclipse.gef.ui.actions.AlignmentRetargetAction;
import org.eclipse.gef.ui.actions.DeleteRetargetAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.actions.RedoRetargetAction;
import org.eclipse.gef.ui.actions.UndoRetargetAction;
import org.eclipse.gef.ui.actions.ZoomComboContributionItem;
import org.eclipse.gef.ui.actions.ZoomInRetargetAction;
import org.eclipse.gef.ui.actions.ZoomOutRetargetAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.ui.actions.ActionFactory;

public class MyContributor extends ActionBarContributor {
  ...
  public void contributeToToolBar(IToolBarManager toolBarManager) {
    // 削除アクションの追加
    toolBarManager.add(getActionRegistry().getAction(
        ActionFactory.DELETE.getId()));

    // 元に戻すアクションの追加
    toolBarManager.add(getActionRegistry().getAction(
        ActionFactory.UNDO.getId()));

    // やり直しアクションの追加
    toolBarManager.add(getActionRegistry().getAction(
        ActionFactory.REDO.getId()));

    toolBarManager.add(new Separator());
    // 水平方向の整列アクションの追加
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ALIGN_LEFT));
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ALIGN_CENTER));
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ALIGN_RIGHT));
    toolBarManager.add(new Separator());
    // 垂直方向の整列アクションの追加
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ALIGN_TOP));
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ALIGN_MIDDLE));
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ALIGN_BOTTOM));

    toolBarManager.add(new Separator());
    // ツールバーに拡大・縮小アクションを追加
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ZOOM_IN));
    toolBarManager.add(getActionRegistry().getAction(
        GEFActionConstants.ZOOM_OUT));

    // 倍率を直接指定するコンボ・ボックスの追加
    toolBarManager.add(new ZoomComboContributionItem(getPage()));
  }
  ...
}

ここでは、削除アクション、及び元に戻す、やり直しアクションのIDの取得方法を変更しています。これは、直接GEFに変更があったわけではなく、Eclipse本体(IWorkbenchActionConstantsインターフェイス)の変更によるものです。又、どのアクションを書き換えるのかを確認するためには、GEFActionConstantsインターフェイスのAPIドキュメントと、IWorkbenchActionConstantsインターフェイスのAPIドキュメントを参照してください(Deprecated. in 3.0.となっているものをドキュメントの指示に従って書き換えます)。

次に、HelloWorldEditorクラスを以下のように書き換えてください。

リスト2:HelloWorldEditor.java
package gef.example.helloworld;

import gef.example.helloworld.dnd.MyFileDragSourceListener;
import gef.example.helloworld.dnd.MyFileDropTargetListener;
import gef.example.helloworld.editparts.MyEditPartFactory;
import gef.example.helloworld.model.ArrowConnectionModel;
import gef.example.helloworld.model.ContentsModel;
import gef.example.helloworld.model.HelloModel;
import gef.example.helloworld.model.LineConnectionModel;
import gef.example.helloworld.tools.FileMoveToolEntry;

import java.util.ArrayList;
import java.util.EventObject;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.gef.editparts.ScalableRootEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.palette.ConnectionCreationToolEntry;
import org.eclipse.gef.palette.CreationToolEntry;
import org.eclipse.gef.palette.MarqueeToolEntry;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteGroup;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.SelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.requests.SimpleFactory;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.AlignmentAction;
import org.eclipse.gef.ui.actions.DirectEditAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.actions.ZoomInAction;
import org.eclipse.gef.ui.actions.ZoomOutAction;
import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.TransferDragSourceListener;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.actions.ActionFactory;

public class HelloWorldEditor extends GraphicalEditorWithPalette {
  ...
  protected void initializeGraphicalViewer() {
    GraphicalViewer viewer = getGraphicalViewer();

    // DropTargetListenerの設定
    viewer
        .addDropTargetListener((TransferDropTargetListener) new MyFileDropTargetListener(
            viewer));
    // DragSourceListenerの設定
    viewer
        .addDragSourceListener((TransferDragSourceListener) new MyFileDragSourceListener(
            viewer));

    // 最上位のモデルの設定
    ContentsModel parent = new ContentsModel();

    HelloModel child1 = new HelloModel();
    // 制約の設定
    child1.setConstraint(new Rectangle(0, 0, -1, -1));
    parent.addChild(child1);

    HelloModel child2 = new HelloModel();
    child2.setConstraint(new Rectangle(30, 30, -1, -1));
    parent.addChild(child2);

    HelloModel child3 = new HelloModel();
    child3.setConstraint(new Rectangle(10, 80, 80, 50));
    parent.addChild(child3);

    viewer.setContents(parent);

  }
  ...
  protected void configureGraphicalViewer() {
    super.configureGraphicalViewer();

    GraphicalViewer viewer = getGraphicalViewer();

    // ズーム可能なビューを作成するRootEditPartの設定
    ScalableRootEditPart rootEditPart = new ScalableRootEditPart();
    viewer.setRootEditPart(rootEditPart);

    // ZoomManagerの取得
    ZoomManager manager = rootEditPart.getZoomManager();

    // ズームレベルの設定
    double[] zoomLevels = new double[] { 0.25, 0.5, 0.75, 1.0, 1.5, 2.0,
        2.5, 3.0, 4.0, 5.0, 10.0, 20.0 };
    manager.setZoomLevels(zoomLevels);

    // ズーム レベル コントリビューションの設定
    ArrayList zoomContributions = new ArrayList();
    zoomContributions.add(ZoomManager.FIT_ALL);
    zoomContributions.add(ZoomManager.FIT_HEIGHT);
    zoomContributions.add(ZoomManager.FIT_WIDTH);
    manager.setZoomLevelContributions(zoomContributions);

    // 拡大アクションの作成と登録
    IAction action = new ZoomInAction(manager);
    getActionRegistry().registerAction(action);
    // 縮小アクションの作成と登録
    action = new ZoomOutAction(manager);
    getActionRegistry().registerAction(action);

    // EditPartFactoryの作成と設定
    viewer.setEditPartFactory(new MyEditPartFactory());

    // キー・ハンドラの作成
    KeyHandler keyHandler = new KeyHandler();

    // DELキーと削除アクションを結びつける
    keyHandler.put(KeyStroke.getPressed(SWT.DEL, 127, 0),
        getActionRegistry().getAction(ActionFactory.DELETE.getId()));

    // F2キーとDirectEditActionを結びつける
    keyHandler.put(KeyStroke.getPressed(SWT.F2, 0), getActionRegistry()
        .getAction(GEFActionConstants.DIRECT_EDIT));

    // グラフィカル・ビューワにキー・ハンドラを設定
    getGraphicalViewer().setKeyHandler(
        new GraphicalViewerKeyHandler(getGraphicalViewer())
            .setParent(keyHandler));
  }
  ...
}

ここでは、リスト1と同様に削除アクションのIDを取得する方法を変更し、ドラッグ・ソース・リスナとドロップ・ターゲット・リスナをJFaceの、TransferDragSourceListenerとTransferDropTargetListenerにキャストしています。以前のバージョンのGEFでは、ドラッグ・ソース・リスナにGEFのorg.eclipse.gef.dnd.TransferDragSourceListenerインターフェイスをインプリメントしたクラスを使用していましたが、GEF3.0からは、JFaceに用意されている同名のorg.eclipse.jface.util.TransferDragSourceListenerインターフェイスをインプリメントしたクラスを使用するように変更されています。現状では、ドラッグ・ソース・リスナ・クラスとして使用した、AbstractTransferDragSourceListenerクラスは、これら2つのインターフェイスをインプリメントしているので、ここではキャストするだけで済みます(ドロップ・ターゲット・リスナのほうも同様です)。

さて、後はHelloworldPluginクラスを3.0用に変更すれば、警告はなくなるはずですが、それだけでは、うまくいきません。これは、後述するとして、まずはHelloworldPluginクラスを以下のように変更してください。

リスト3:HelloworldPlugin.java
package gef.example.helloworld;

import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * The main plugin class to be used in the desktop.
 */
public class HelloworldPlugin extends AbstractUIPlugin {
  ...
  // コンストラクタを引数無しのものに変更
  public HelloworldPlugin() {
    super(); // super(descriptor)から変更
    plugin = this;
    try {
      resourceBundle = ResourceBundle
          .getBundle("gef.example.helloworld.HelloworldPluginResources");
    } catch (MissingResourceException x) {
      resourceBundle = null;
    }
  }
  ...
}

これで、プロジェクトから全ての警告が消えたはずです。しかし、前述の通りこの段階で実行したとしてもエラーが表示されるだけで、エディタを起動することが出来ません。これは、Eclipse3.0からプラグインのロードの方法が変更されているからです。上記コードのように、引数無しのコンストラクタを使用するAbstractUIPluginクラスのサブクラスを動作させるためには、プラグイン・マニフェスト・ファイルを変更する必要があります。これは、GEFアプリケーション以外のものでも同様です(詳細は、EclipseのヘルプからPlatform Plug-in Developer Guide→3.0 Plug-in Migration Guide→Incompatibilitiesの第1項目を参照してください)。それでは、plugin.xmlファイルを以下のように変更してください。

リスト4:plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin
   id="gef.example.helloworld"
   name="Helloworld プラグイン"
   version="1.0.0"
   provider-name=""
   class="gef.example.helloworld.HelloworldPlugin">

   <runtime>
      <library name="helloworld.jar"/>
   </runtime>
   <requires>
      <import plugin="org.eclipse.core.resources"/>
      <import plugin="org.eclipse.ui"/>
      <import plugin="org.eclipse.gef"/>
      <import plugin="org.eclipse.ui.views"/>
      <import plugin="org.eclipse.core.runtime"/>
   </requires>

   <extension
         point="org.eclipse.ui.editors">
      <editor
            name="Hello World Editor"
            default="true"
            icon="example.gif"
            filenames="hello.world"
            contributorClass="gef.example.helloworld.MyContributor"
            class="gef.example.helloworld.HelloWorldEditor"
            id="gef.example.helloworld.editor1">
      </editor>
   </extension>

</plugin>

ここで追加したのは、上記コードで青色で表示されている一行だけです。この一行を追加するだけで、引数無しのコンストラクタを持つプラグイン・クラスを使用することができるようになります。それでは、ランタイム・ワークベンチを起動して確認してみてください。今度は、エディタが表示されるはずです。

■RCPアプリケーションとして動作するようにする

さて、これでHelloWorldアプリケーションをEclipse3.0で動作させることが出来るようになったので、次にこのアプリケーションをRCPアプリケーションに変換し、スタンドアロンで動作するようにします。

それでは、まずRCPアプリケーションに必要なクラスを入れるためのパッケージとしてgef.example.helloworld.rcpというパッケージを作成してください。次に、プラグイン・マニフェスト・エディタでplugin.xmlファイルを開いて、Extensionsページを表示してください。次に、Addボタンを押下し、New Extensionダイアログを表示して、拡張ポイントのリストからorg.eclipse.core.runtime.applicationsを選択して、OKを押下してください。又、同様にして、拡張ポイント:org.eclipse.ui.perspectivesも追加してください。

次に、追加した拡張ポイント:org.eclipse.core.runtime.applicationsを選択し、マニフェスト・エディタの右ペインのIdプロパティにHelloWorldRCPAppと入力してください。次に、追加した拡張ポイントを右クリックして、コンテキスト・メニューからNew→applicationと選択してください。次に、追加されたapplicationを右クリックして、コンテキスト・メニューからNew→runと選択してください。次に、マニフェスト・エディタの右ペインでclassをクリックして、Java属性エディタを表示してください。Java属性エディタが表示されたら、パッケージにgef.example.helloworld.rcpを指定し、クラス名にHelloWorldRCPAppと入力してOKを押下してください。

次に、マニフェスト・エディタで追加した拡張ポイント:org.eclipse.ui.perspectivesを右クリックして、コンテキスト・メニューからNew→perspectiveと選択して下さい。次に、マニフェスト・エディタの右ペインで追加したパースペクティブのプロパティを以下のように指定してください。

プロパティ
id gef.example.helloworld.myPerspective
name Hello World パースペクティブ
class gef.example.helloworld.rcp.MyPerspectiveFactory (Java属性エディタでクラスを作成)
icon example.gif
fixed true

さて、これでマニフェスト・ファイルの編集は終了です。これまでの作業でプラグイン・マニフェスト・ファイル(plugin.xml)は以下のようになっているはずです。

リスト5:plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin
   id="gef.example.helloworld"
   name="Helloworld プラグイン"
   version="1.0.0"

   class="gef.example.helloworld.HelloworldPlugin">

   <runtime>
      <library name="helloworld.jar"/>
   </runtime>
   <requires>
      <import plugin="org.eclipse.core.resources"/>
      <import plugin="org.eclipse.ui"/>
      <import plugin="org.eclipse.gef"/>
      <import plugin="org.eclipse.ui.views"/>
      <import plugin="org.eclipse.core.runtime"/>
   </requires>


   <extension
         point="org.eclipse.ui.editors">
      <editor
            name="Hello World Editor"
            default="true"
            icon="example.gif"
            filenames="hello.world"
            contributorClass="gef.example.helloworld.MyContributor"
            class="gef.example.helloworld.HelloWorldEditor"
            id="gef.example.helloworld.editor1">
      </editor>
   </extension>
   <extension
         id="HelloWorldRCPApp"
         point="org.eclipse.core.runtime.applications">
      <application>
         <run class="gef.example.helloworld.rcp.HelloWorldRCPApp"/>
      </application>
   </extension>
   <extension
         point="org.eclipse.ui.perspectives">
      <perspective
            class="gef.example.helloworld.rcp.MyPerspectiveFactory"
            icon="example.gif" 
            fixed="true"
            name="HelloWorld パースペクティブ"
            id="gef.example.helloworld.myPerspective"/>
   </extension>

</plugin>

又、今回はエディタのみを使用し、ビューを使用しません。パースペクティブ・ファクトリは、デフォルトでエディタ領域を表示するだけのレイアウトを行うようになっているので、作成したパースペクティブ・ファクトリ・クラス(MyPerspectiveFactory)では、何もしなくて結構です。

リスト6:MyPerspectiveFactory.java
package gef.example.helloworld.rcp;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class MyPerspectiveFactory implements IPerspectiveFactory {

  public void createInitialLayout(IPageLayout layout) {
  }
}

次に、ワークベンチ・アドバイザーを作成します。まず、パッケージ gef.example.helloworld.rcpにスーパークラスにorg.eclipse.ui.application.WorkbenchAdvisorを指定して、MyWorkbenchAdvisorという名前のクラスを作成して以下のように記述してください。

リスト7:MyWorkbenchAdvisor.java
package gef.example.helloworld.rcp;

import org.eclipse.ui.application.WorkbenchAdvisor;

public class MyWorkbenchAdvisor extends WorkbenchAdvisor {

  public String getInitialWindowPerspectiveId() {
    return "gef.example.helloworld.myPerspective";
  }
  
}

ここでは、アプリケーションを起動したときに使用するパースペクティブのIDとして、マニフェスト・ファイルに追加したパースペクティブのIDを返すようにしています。

次に、先程作成したRCPアプリケーションのメイン・クラスであるHelloWorldRCPAppクラスを以下のように変更してください。

リスト8:HelloWorldRCPApp.java
package gef.example.helloworld.rcp;

import org.eclipse.core.runtime.IPlatformRunnable;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.application.WorkbenchAdvisor;

public class HelloWorldRCPApp implements IPlatformRunnable {

  public Object run(Object args) throws Exception {
    WorkbenchAdvisor workbenchAdvisor = new MyWorkbenchAdvisor();
    Display display = PlatformUI.createDisplay();
    try {
      int returnCode = PlatformUI.createAndRunWorkbench(display,
          workbenchAdvisor);
      if (returnCode == PlatformUI.RETURN_RESTART) {
        return IPlatformRunnable.EXIT_RESTART;
      } else {
        return IPlatformRunnable.EXIT_OK;
      }
    } finally {
      display.dispose();
    }
  }
}

これで、一応RCPアプリケーションとして動作するようになりましたが、このアプリケーションはhello.worldというファイルをエディタへの入力として渡さなければ動かないので、次に、ファイルを開くためのアクションを作成します。又、そのアクションで作成する、エディタ入力(IEditorInput)も併せて作成します。

まずは、エディタ入力から作成します。パッケージgef.example.helloworld.rcpHelloWorldEditorInputというクラスを作成して以下のように記述してください。この時、インプリメントするインターフェイスにはorg.eclipse.ui.IPathEditorInputを指定してください。又、エディタ入力クラスでは、2つのエディタ入力が同じものかどうかを調べるために、equalsメソッドを使用するので、HelloWorldEditorInputクラスでもequalsメソッドとhashCodeメソッドをオーバーライドしてください。

リスト9:HelloWorldEditorInput.java
package gef.example.helloworld.rcp;

import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.PlatformUI;

public class HelloWorldEditorInput implements IPathEditorInput {
  private IPath path;

  public HelloWorldEditorInput(IPath path) {
    this.path = path;
  }

  public IPath getPath() {
    return path;
  }

  public boolean exists() {
    return path.toFile().exists();
  }

  public ImageDescriptor getImageDescriptor() {
    return PlatformUI.getWorkbench().getEditorRegistry()
        .getImageDescriptor(path.toString());
  }

  public String getName() {
    return path.toString();
  }

  public IPersistableElement getPersistable() {
    return null;
  }

  public String getToolTipText() {
    return path.makeRelative().toString();
  }

  public Object getAdapter(Class adapter) {
    return null;
  }

  public int hashCode() {
    return path.hashCode();
  }

  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (!(obj instanceof HelloWorldEditorInput))
      return false;
    HelloWorldEditorInput other = (HelloWorldEditorInput) obj;
    return path.equals(other.path);
  }
}

次に、ファイルを開くためのアクションを作成します。それでは、パッケージgef.example.helloworld.rcpに、スーパークラスにorg.eclipse.jface.action.Actionを指定して、OpenActionというクラスを作成し、以下のように記述してください。又、このアクションのアイコン・イメージとして、以下のファイルをパッケージgef.example.helloworld.rcpにインポートしておいてください。

open.gif
リスト10:OpenAction.java
package gef.example.helloworld.rcp;

import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;

public class OpenAction extends Action {

  private IWorkbenchWindow workbenchWindow;

  public OpenAction() {
    setImageDescriptor(ImageDescriptor.createFromFile(OpenAction.class,
        "open.gif"));
  }

  public void dispose() {
    workbenchWindow = null;
  }

  public void run() {
    String path = openFileDialog();
    if (path != null) {
      IEditorInput input = new HelloWorldEditorInput(new Path(path));

      IWorkbenchPage page = workbenchWindow.getActivePage();

      try {
        page.openEditor(input, "gef.example.helloworld.editor1");
      } catch (PartInitException e) {
        e.printStackTrace();
      }
    }
  }

  public void setWorkbenchWindow(IWorkbenchWindow window) {
    workbenchWindow = window;
  }

  private String openFileDialog() {
    FileDialog dialog = new FileDialog(workbenchWindow.getShell(), SWT.OPEN);
    dialog.setText("開く");
    dialog.setFilterExtensions(new String[] { "hello.world" });
    return dialog.open();
  }
}

次に、このアクションをRCPアプリケーションのツールバーに追加するために、MyWorkbenchAdvisorクラスで、fillActionBarsメソッドと、postShutdownメソッドをオーバーライドしてください。

リスト11:MyWorkbenchAdvisor.java
package gef.example.helloworld.rcp;

import org.eclipse.jface.action.ICoolBarManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;

public class MyWorkbenchAdvisor extends WorkbenchAdvisor {
  private OpenAction openAction = new OpenAction();

  public String getInitialWindowPerspectiveId() {
    return "gef.example.helloworld.myPerspective";
  }

  // オーバーライド
  public void fillActionBars(IWorkbenchWindow window,
      IActionBarConfigurer configurer, int flags) {
    // クールバーの取得
    ICoolBarManager coolbar = configurer.getCoolBarManager();
    ToolBarManager toolBar = new ToolBarManager(SWT.FLAT);
    // アクションの追加
    openAction.setWorkbenchWindow(window);
    toolBar.add(openAction);
    coolbar.add(toolBar);
    // 元に戻す、やり直しアクションの登録
    configurer.registerGlobalAction(ActionFactory.UNDO.create(window));
    configurer.registerGlobalAction(ActionFactory.REDO.create(window));
  }

  // オーバーライド
  public void postShutdown() {
    // アクションの破棄
    openAction.dispose();
    super.postShutdown();
  }
}

ここでは、ワークベンチ・ウィンドウのクールバーに開くアクションを追加し、元に戻す、及びやり直しアクションをグローバル・アクションとして登録しています。これは、アクセラレータを使用するために必要です。又、アプリケーションが終了された時に、アクションの破棄も行っています。

これで、HelloWorldアプリケーションをRCPアプリケーションとして動作させることが出来るようになったので、実行して確認してみます。それでは、EclipseのメニューからRun→Run...と選択して、Runダイアログを表示してください。次に、ダイアログの左側のツリー・コントロールからRun-time Workbenchを選択し、Newボタンをクリックしてください。次に、ダイアログの右側のArgumentsページのNameに、起動構成を識別するための任意の名前を入力して、次にProgram to RunグループのRun an applicationコンボ・ボックスから gef.example.helloworld.HelloWorldRCPAppを選択して下さい。次に、Plug-insページを表示し、3つのオプションからChoose plug-ins and fragments to launch from the listを選択し、一度Deselect Allボタンをクリックして全てのチェックを外してから、gef.example.helloworldにチェックを入れて、次にAdd Required Plug-insボタンを押下して下さい。これで実行に必要なプラグインだけがチェックされているはずです。次に、RunダイアログのRunボタンを押下してアプリケーションを実行してください。アプリケーションが起動したら、ツールバーにある開くアクションを押下して、ファイル選択ダイアログを表示し、hello.worldというファイルを選択して開いてください。以下のようにHelloWorldEditorが起動されれば成功です。

■まとめ

今回は、GEF2.1.3で作成したGEFアプリケーションを、GEFバージョン3.0とEclipseバージョン3.0を使用してRCPアプリケーションに変換してスタンドアロンで動作するようにしました。Eclipse3.0では、既存のプラグインを今回行ったのと同様の方法で、簡単にスタンドアロン・アプリケーションに変換することができるようになりました。又、今回はバージョン2.1.3用のプラグインを3.0用に手作業で変換しましたが、これはプロジェクトを選択して、右クリックし、メニューからPDE Tools→Migrate to 3.0と選択することでも行えます(こちらのほうが簡単です)。

■参考文献

■関連ページ