#概要
表題の通り、最近よく見るライブプレビューなアプリをEclipse+Xtextで作ってみました。
準備編は、RCPアプリケーションを構築する際のひっかけポイントを書き残しておけば、次回以降の同じ目に合わなくて済むだろう、ということで書いた次第です。
誰かの役に立てば幸いです。
#開発環境/ツール
-
Eclipse Version 2019-12 (4.14.0)
Eclipse IDE 2019-12 R Packagesから導入。日本語化プラグインは導入していない -
Xtext
Eclipseを起動、メニューHelp -> Install New Software...
を選択
Work with:は2019-12 - http://download.eclipse.org/releases/2019-12
を選択
Modeling
を展開すると出てくる -
Eclipse e4 Tools Developer Resources
-
Eclipse Plug-in Development Environment
途中まではXtextと同じ
General Purpose Tools
を展開すると出てくる
#画面イメージ
準備編を最後までこなしたイメージは以下の感じ。
左側にエクスプローラーのような外観、右上がエディタ領域、右下がプロパティいう構成になっている。
右下はプロパティだけだが、次のステップでプレビューを表示するウィンドウを足す予定。
#開発手順
基本的には、tutorial : eclipse rcp e4 with 3.x views like project explorer, properties, etc.にある手順に従って作業を行えば、画面イメージで示したものが出来上がる。
ただし、今回の環境に合わせてアップデートが必要な箇所がある、コメント欄で逐次追加されているものも必要で全体が見えない、さら記事が英語…、などを考慮して、今回の開発環境に手順をアップデートすることにした。
##プラグインプロジェクトを作成する
File -> New -> Other -> Plug-in Development -> Plug-in Projectを選択
以降の細かい点は以下の通り。
プロジェクトのIDはtest.rcp
Optionsのactivator...はチェックを外す
RichClientはYesを選択
contributors to the UIはチェックする
RCP3.x (minimal)を選択
Finishボタンをクリック後、PackageExplorerでtest.rcp/src/test/rcp/Application.javaなどが生成されていることを確認できればOK。
##test.rcpプラグインにapplication modelファイルを追加する
File -> New -> Eclipse 4 -> Model -> New Application Modelを選択し、ファイル名はApplication.e4xmi
とする。
ファイルの追加先はプラグインのルート直下でよい。
##test.rcpプラグインにProduct定義を追加する
plugin.xmlを開き、
Product定義
<extension id="product_test" point="org.eclipse.core.runtime.products">
<product application="test.rcp.application" name="My Product">
<property name="appName" value="My App"> </property>
<property name="applicationXMI" value="test.rcp/Application.e4xmi"> </property>
</product>
</extension>
##test.rcpプラグインにproduct configurationファイルを追加する
File -> New -> Plug-In Development -> Product Configurationを選択し、ファイル名はtest.rcp.product
とする。
ファイルの追加先はプラグインのルート直下でよい。
##productとapplicationの関連付け
productファイルを開き、Overviewタブで、Productはrcp.test.product_test
を選択する。
Applicationはtest.rcp.application
を選択する。
##test.rcpプラグインの依存関係を更新する
plugin.xmlを開き、Dependenciesタブをクリック
Required Plug-insのAddボタンで、org.eclipse.rcp
とorg.eclipse.emf.common
を追加する。
なお、tutorialにはorg.eclipse.e4.rcpとあるが本環境では見当たらないので、代わりにorg.eclipse.rcpとしている。また、org.eclipse.emf.coreは本環境では含めていない(org.eclipse.emf.commonにマージされた?と推測)。
##EclipseにRun configurationを作る
test.rcpプラグイン -> plugin.xmlのLaunch Debugをクリックする。
クリック後、いろいろなエラーメッセージがConsoleに出たり、ダイアログが出てきてエラーログを見るか?などが尋ねられるが、もろもろキャンセルでOK。
EclipseメニューのRun -> DebugConfigurationを選択し、
のように、Eclipse Applicationの下に、test.rcp.product_test
がエントリされていることを確認できればOK。
##test.rcpのApplication.e4xmiに追記する
test.rcpのApplication.e4xmiを開き、XMIタブをクリックし次のコードで置き換えて保存。
コード
<?xml version="1.0" encoding="UTF-8"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:advanced="http://www.eclipse.org/ui/2010/UIModel/application/ui/advanced" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_VnmacNSzEeGBn6dQ9VPexA" elementId="test.rcp.application" bindingContexts="_VnmacdSzEeGBn6dQ9VPexA">
<children xsi:type="basic:TrimmedWindow" xmi:id="_Vnmah9SzEeGBn6dQ9VPexA" label="My Main Window" iconURI="" width="800" height="600">
<children xsi:type="advanced:PerspectiveStack" xmi:id="_Vnmaj9SzEeGBn6dQ9VPexA" selectedElement="_VnmakNSzEeGBn6dQ9VPexA">
<children xsi:type="advanced:Perspective" xmi:id="_VnmakNSzEeGBn6dQ9VPexA" elementId="test.rcp.perspective" selectedElement="_VnnBgNSzEeGBn6dQ9VPexA" label="My Perspective" iconURI="">
<tags>Perspective</tags>
<tags>categoryTag:General</tags>
<children xsi:type="basic:PartSashContainer" xmi:id="_VnnBgNSzEeGBn6dQ9VPexA" horizontal="true">
<children xsi:type="basic:PartStack" xmi:id="_VnnBgdSzEeGBn6dQ9VPexA" containerData="3400">
<tags>newtablook</tags>
<tags>org.eclipse.e4.primaryNavigationStack</tags>
<children xsi:type="advanced:Placeholder" xmi:id="_QR29cNS2EeGBn6dQ9VPexA" elementId="org.eclipse.ui.navigator.ProjectExplorer" ref="_sS7Q8NS1EeGBn6dQ9VPexA"/>
</children>
<children xsi:type="basic:PartSashContainer" xmi:id="_bTQ1YNS2EeGBn6dQ9VPexA" elementId="" containerData="10000">
<children xsi:type="advanced:Placeholder" xmi:id="_hP-EYNS2EeGBn6dQ9VPexA" elementId="org.eclipse.ui.editorss" ref="_Hmg4kNSjEeGwXp2p959l3w"/>
<children xsi:type="basic:PartStack" xmi:id="_qAHrYNS2EeGBn6dQ9VPexA" elementId="org.eclipse.ui.views.PropertySheetMStack" containerData="3400" selectedElement="_soNH8NS2EeGBn6dQ9VPexA">
<tags>newtablook</tags>
<tags>org.eclipse.e4.secondaryDataStack</tags>
<children xsi:type="advanced:Placeholder" xmi:id="_soNH8NS2EeGBn6dQ9VPexA" elementId="org.eclipse.ui.views.PropertySheet" ref="_WqRGcNS1EeGBn6dQ9VPexA"/>
</children>
</children>
</children>
</children>
</children>
<sharedElements xsi:type="advanced:Area" xmi:id="_Hmg4kNSjEeGwXp2p959l3w" elementId="org.eclipse.ui.editorss">
<children xsi:type="basic:PartStack" xmi:id="_HmhfoNSjEeGwXp2p959l3w" elementId="org.eclipse.e4.primaryDataStack">
<tags>newtablook</tags>
<tags>org.eclipse.e4.primaryDataStack</tags>
<tags>EditorStack</tags>
</children>
</sharedElements>
<sharedElements xsi:type="basic:Part" xmi:id="_WqRGcNS1EeGBn6dQ9VPexA" elementId="org.eclipse.ui.views.PropertySheet" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView" label="Properties" iconURI="platform:/plugin/org.eclipse.ui.views//icons/full/eview16/prop_ps.gif" closeable="true">
<tags>View</tags>
<tags>categoryTag:General</tags>
<menus xmi:id="_HngXENSjEeGwXp2p959l3w" elementId="org.eclipse.ui.views.PropertySheet">
<tags>ViewMenu</tags>
<tags>menuContribution:menu</tags>
</menus>
<toolbar xmi:id="_Hng-INSjEeGwXp2p959l3w" elementId="org.eclipse.ui.views.PropertySheet"/>
</sharedElements>
<sharedElements xsi:type="basic:Part" xmi:id="_sS7Q8NS1EeGBn6dQ9VPexA" elementId="org.eclipse.ui.navigator.ProjectExplorer" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView" label="Project Explorer" iconURI="platform:/plugin/org.eclipse.ui.navigator.resources//icons/full/eview16/resource_persp.gif">
<tags>View</tags>
<tags>categoryTag:General</tags>
<menus xmi:id="_4UXAUNSmEeG-a6zBTyJ-wg" elementId="org.eclipse.ui.navigator.ProjectExplorer">
<tags>ViewMenu</tags>
<tags>menuContribution:menu</tags>
</menus>
<menus xsi:type="menu:PopupMenu" xmi:id="_4VpZwNSmEeG-a6zBTyJ-wg" elementId="org.eclipse.ui.navigator.ProjectExplorer#PopupMenu">
<tags>menuContribution:popup</tags>
<tags>popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu</tags>
</menus>
<toolbar xmi:id="_4UXAUdSmEeG-a6zBTyJ-wg" elementId="org.eclipse.ui.navigator.ProjectExplorer"/>
</sharedElements>
<trimBars xmi:id="_VOV6ANTAEeGTY-uOtVc6Mg" elementId="org.eclipse.ui.main.toolbar"/>
<trimBars xmi:id="_VP1HwNTAEeGTY-uOtVc6Mg" elementId="org.eclipse.ui.trim.status" side="Bottom">
<children xsi:type="menu:ToolControl" xmi:id="_VP1u0NTAEeGTY-uOtVc6Mg" elementId="org.eclipse.ui.StatusLine" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.StandardTrim">
<tags>stretch</tags>
</children>
<children xsi:type="menu:ToolControl" xmi:id="_VQKe8NTAEeGTY-uOtVc6Mg" elementId="org.eclipse.ui.HeapStatus" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.StandardTrim"/>
<children xsi:type="menu:ToolControl" xmi:id="_VQRMoNTAEeGTY-uOtVc6Mg" elementId="org.eclipse.ui.ProgressBar" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.StandardTrim"/>
</trimBars>
</children>
<bindingTables xmi:id="_VnmafNSzEeGBn6dQ9VPexA" bindingContext="_VnmacdSzEeGBn6dQ9VPexA"/>
<rootContext xmi:id="_VnmacdSzEeGBn6dQ9VPexA" elementId="org.eclipse.ui.contexts.dialogAndWindow" name="In Dialog and Windows">
<children xmi:id="_VnmactSzEeGBn6dQ9VPexA" elementId="org.eclipse.ui.contexts.window" name="In Windows"/>
<children xmi:id="_Vnmac9SzEeGBn6dQ9VPexA" elementId="org.eclipse.ui.contexts.dialog" name="In Dialogs"/>
</rootContext>
<descriptors xmi:id="_9E9jYNS4EeGBn6dQ9VPexA" elementId="org.eclipse.ui.navigator.ProjectExplorer" label="Project Explorer" iconURI="platform:/plugin/org.eclipse.ui.navigator.resources//icons/full/eview16/resource_persp.gif" category="org.eclipse.e4.primaryNavigationStack" closeable="true" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView">
<tags>View</tags>
<tags>categoryTag:General</tags>
</descriptors>
<descriptors xmi:id="_W6yT4NSjEeGgKvWHVYtRxQ" elementId="org.eclipse.ui.console.ConsoleView" label="Console" iconURI="platform:/plugin/org.eclipse.ui.console//icons/full/cview16/console_view.gif" allowMultiple="true" category="org.eclipse.e4.secondaryDataStack" closeable="true" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView">
<tags>View</tags>
<tags>categoryTag:General</tags>
</descriptors>
<descriptors xmi:id="_W6ziANSjEeGgKvWHVYtRxQ" elementId="org.eclipse.ui.views.ProgressView" label="Progress" iconURI="platform:/plugin/org.eclipse.ui.ide//icons/full/eview16/pview.gif" category="org.eclipse.e4.secondaryDataStack" closeable="true" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView">
<tags>View</tags>
<tags>categoryTag:General</tags>
</descriptors>
<descriptors xmi:id="_W63zcdSjEeGgKvWHVYtRxQ" elementId="org.eclipse.ui.views.PropertySheet" label="Properties" iconURI="platform:/plugin/org.eclipse.ui.views//icons/full/eview16/prop_ps.gif" allowMultiple="true" category="org.eclipse.e4.secondaryDataStack" closeable="true" contributionURI="bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView">
<tags>View</tags>
<tags>categoryTag:General</tags>
</descriptors>
<addons xmi:id="_VnmadNSzEeGBn6dQ9VPexA" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/>
<addons xmi:id="_VnmaddSzEeGBn6dQ9VPexA" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/>
<addons xmi:id="_VnmadtSzEeGBn6dQ9VPexA" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/>
<addons xmi:id="_Vnmad9SzEeGBn6dQ9VPexA" elementId="org.eclipse.e4.ui.workbench.commands.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.CommandProcessingAddon"/>
<addons xmi:id="_VnmaeNSzEeGBn6dQ9VPexA" elementId="org.eclipse.e4.ui.workbench.contexts.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.ContextProcessingAddon"/>
<addons xmi:id="_VnmaedSzEeGBn6dQ9VPexA" elementId="org.eclipse.e4.ui.workbench.bindings.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench.swt/org.eclipse.e4.ui.workbench.swt.util.BindingProcessingAddon"/>
</application:Application>
##test.rcpプラグインの依存関係を更新する
plugin.xmlを開き、Dependenciesタブをクリック
Required Plug-insのAddボタンで、ProjectExplorerの追加に必要なorg.eclipse.ui.views
、org.eclipse.ui.navigator
とorg.eclipse.ui.navigator.resources
を追加する
##ApplicationWorkbenchAdvisor.javaにProjectExplorerの初期化コードを追加する
initializeメソッドと追加メソッドを以下のようにする。
initializeメソッドと追加メソッドで、ProjectExplorerに表示するフォルダ開閉アイコンの登録をしている。
なお、tutorialと異なるのは、アイコンの拡張子がgifではなくpngである点(昔、gifのライセンスの話があってわざわざ変えた?)。
getDefaultPageInputメソッドは、デフォルトで表示するパスを指定している。
ProjectExplorerの初期化コード
@Override
public void initialize(IWorkbenchConfigurer configurer) {
super.initialize(configurer);
...
// inserted: register workbench adapters
IDE.registerAdapters();
// inserted: register images for rendering explorer view
final String ICONS_PATH = "icons/full/";
final String PATH_OBJECT = ICONS_PATH + "obj16/";
Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);
declareWorkbenchImage(configurer, ideBundle,
IDE.SharedImages.IMG_OBJ_PROJECT, PATH_OBJECT + "prj_obj.png", true);
declareWorkbenchImage(configurer, ideBundle,
IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT + "cprj_obj.png", true);
}
private void declareWorkbenchImage(IWorkbenchConfigurer configurer_p,
Bundle ideBundle, String symbolicName, String path, boolean shared) {
URL url = ideBundle.getEntry(path);
ImageDescriptor desc = ImageDescriptor.createFromURL(url);
configurer_p.declareImage(symbolicName, desc, shared);
}
@Override
public IAdaptable getDefaultPageInput() {
return ResourcesPlugin.getWorkspace().getRoot();
}
##ApplicationWorkbenchWindowAdvisor.javaのウィンドウサイズを変更するコードを削除
デフォルトではウィンドウサイズが400300になってしまうので、preWindowOpenメソッドを以下のようにコードをコメントアウトする。
これにより、Application.e4xmiで指定したウィンドウサイズ800600が上書きされなくなる。
preWindowOpenメソッド
@Override
public void preWindowOpen() {
// IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
// configurer.setInitialSize(new Point(400, 300));
// configurer.setShowCoolBar(false);
// configurer.setShowStatusLine(false);
// configurer.setTitle("Hello RCP"); //$NON-NLS-1$
}
##起動時のウィンドウ構成を初期状態に戻すオプションを追加する
Run -> DebugConfigurationを選択し、
さらに、Eclipse Applicationの下のtest.rcp.product_test
を選択。
Argumentタブをクリック。
Program Arguments内のテキストの末尾に、-clearPersistedState
を追加しておく。
コメント欄でのやり取りに記載されているもの。
##必要なプラグインを追加して、起動する
DebugConfigurationにて、Plug-insタブをクリック。
Launch withはall~ではなく、below~を選択する。
右にあるDeselect Allボタンをクリックして、すべてのプラグインのチェックを外す。
Workspace内のtest.rcpだけにチェックを入れ、Add Required Plug-insボタンをクリック。
画面はいろいろなプラグインにもチェックが入っているのは、無視してほしい。
Validate Plug-insボタンをクリックして、エラーが出ないことを確認して、Debugボタンをクリック。
冒頭で示したウィンドウが現れればOK。
#成果物
以上の作業で生成されたものをGitHubに登録した。
ほぼ素の状態なので、別のアプリを構築したい場合のベースに使えるかも。
#振り返り
E4のみでの開発は断念
本音では、E4だけをつかってすべてを定義したかったのだが、今回は断念した。
ネックになったのは、ProjectExplorerをE4環境で簡単に用意すること。
既存のものを作り直すのはなんとかの再発明だし、試してみたらエラーが解決できない。
結構な時間を使ってググったが、解決につながるいい情報が見つけられなかった。
Eclipse初心者には技術的にも時間的にも厳しいだろうと、ここで諦めた。
誰かご存じの方はいないだろうか…。
clearPersistedStateオプション
デフォルト(オプションを指定しない)では、ユーザ操作によるウィンドウサイズやレイアウト変更などを記憶して、次回起動時にも同じレイアウトで表示してくれる。
指定すると、レイアウトは初期状態で表示される。
開発中はオプションを指定し、リリース後は指定を外す、という方針で当面はいいはず。
ユーザがいじりすぎてしまった場合に備えて、レイアウトを初期状態に戻せる機能をメニューなどに追加することを、以降のステップで検討してみる。