Eclipse Ver3.3のメニューって つかえん。

MenuManagerRendererGUITest.xml と同じメニューをRCPで表示してみると、いろいろ気づきました。
Eclipse Ver3.3のメニューって機能がJFace、SWTより少ないですね。って機能劣化やんEclipseさんw

  • メニューのスタイルがradioやtoggleの場合のデフォルトセレクションの設定がない?! selection="true"に対応する属性がない。

バグのようです。HandlerProxy not setting initialize state 。 FixはVer3.4なのね。orz

  • メニューを無効(灰色)にできない?! visible="false"に対応する属性がない。
  • メニューの表示可否ができない ?! enabled="false"に対応する属性がない。
  • メニューアイコンのdisabledIcon、hoverIconが機能しない。
  • サブメニュを保有するメニューのiconが機能しない。

よく見るのでcommandのスキーマを貼っておきます。

<!ELEMENT command (visibleWhen? , parameter*)>
<!ATTLIST command
commandId     CDATA #REQUIRED
id            CDATA #IMPLIED
mnemonic      CDATA #IMPLIED
icon          CDATA #IMPLIED
disabledIcon  CDATA #IMPLIED
hoverIcon     CDATA #IMPLIED
label         CDATA #IMPLIED
tooltip       CDATA #IMPLIED
helpContextId CDATA #IMPLIED
style         (push|radio|toggle|pulldown) "push"
mode          (FORCE_TEXT) >

Eclipseの実行定義をファイル出力するのもっといい方法

Eclipseの実行定義をファイル出力するid:kompiro さんからコメントを頂きました。

前回はExportで実行定義が出力できるよって書いたんですが、もっと良い方法を教えて頂きました。ありがとうございます。m(_ _)m

こんにちは。
Exportでもいいとは思いますが、
Run -> Run Configuration -> CommonタブにあるSave as を
Shared fileにして、適当なフォルダを設定してみてください。
同様に実行定義を共有することができる上に、更新も変更すればかかるので、お勧めです。

なおこのネタは後で日記にしようと思ってますが、先に日記にしていただいていいっすよ。

Commonタブの画面

id:kompiro さんのブログhttp://d.hatena.ne.jp/kompiro/:Fly me to the GanymedeはいつもEclipse回りを参考にさせてもらっていたので、コメントを頂けるとはびっくり&うれしいです。(^^)

コンソールサーバー

いまさらながら、こんな機能が。

EclipseのちょっとしたTipsだが、Eclipse起動時に-consoleと指定するとOSGiサービスコンソールがたちあがる. さらに-consoleの後に整数を指定するとその番号をポート番号としてコンソールサーバーがたちあがる. するとSystem.outに出力された例外はすべてそのコンソールへ出力できるので、リモートデバッグができる.ちょっとだけ便利ではないですか.

RCPモードのポップアップメニューについて その2

ポップアップメニューについて id:y-komoriさんからコメントを頂きました。ありがとうございます。こちらに転記します。

id:y-komori 2008/06/04 23:57
遅レスですみません・・・とりあえず、ポップアップメニューについて。
おおむね良いと思います。
問題は ViewPart の右上に表示するメニューの定義ですね。id を特殊な値にするという仕様は、使う側にとって忘れがち(「あれ、どのidにすればいいんだっけ?」という感じで・・・)なので、ほかにどうしようもない時以外は避けたいと思います。
のように viewPart 要素に menu 属性を追加するというのはどうでしょうか? tree や table のポップアップメニュー定義と同じ感じで覚えられて良いと思うのですが。

なるほど。了解です。viewPartにmenu属性を追加します。

id:y-komori 2008/06/05 00:06
五月雨ですみません。つづいて、サブメニューを持つメニューのアイコン表示不可について。
これは、Eclipse 本体のメニューを見ても、サブメニューを持ってるメニューでアイコン表示されているものはないですねぇ。Eclipseの仕様なのかしら?
どの段階で仕様になっているのか(SWTレベルでだめ? JFaceでだめ? ・・・)、一度確認したいですね。
Eclipseのメニュー周りは、どうも実装が中途半端な気がします。hoverIcon もJFace レベルで効かないし・・・

そうですね。Eclipse or JFaceの仕様な感じがします。サブメニューのアイコンはペンディングで。

menuのスキーマ

menuがcontrolの子要素にならないようにtrunkを戻しました。
control要素にmenu属性を追加した場合、AbstractControlRendererのsetMenuメソッドでヌルポで落ちます。RCP版ではmenuをRCPがレンダリングするため、MenuManagerRendererを保持していないためですが、MenuManagerRendererがnullならば何もしない分岐を追加してもよいですか。

表示可否の制御

PropertyTesterのエクステンションを使えば任意のロジックで表示可否ができます。UrumaでGenericPropertyTesterを用意し、アクションに@IsMenuShowアノテーションがあるメソッドをコールしようと思います。メソッドバインディングの実装方針ですが、MethodBindingSupportはEventListenerDefを前提にしているので、IsMenuShowDefのように新しいDefを追加するとアブストラクトクラスまですべてIsMenuShowDef用を作らないといけないため、改修とりファクタが大きいですが合わせたほうがよいですか。合わせなくても実装は可能です。現状手元ではひとまず後者で実装しています。

http://d.hatena.ne.jp/y-komori/20080531

SWTとEclipseの両方に対応したTestTool SWTBot

SWTEclipseの両方に対応したTestToolSWTBotがおもしろそう。バージョンも最近1.0がリリースされています。JUnitのようなユニットテストと、操作に基づいた機能テストの両方を行えます。

使い方がなぜかリリースノートに記載されています。

サンプルコードを張っておきます。雰囲気がつかめると思う。

操作系のサンプル

via

package net.sf.swtbot.eclipse.spy;

import net.sf.swtbot.eclipse.finder.SWTEclipseBot;
import net.sf.swtbot.eclipse.finder.widgets.SWTBotEclipseEditor;
import net.sf.swtbot.wait.Conditions;
import net.sf.swtbot.widgets.WidgetNotFoundException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;

/**
 * @author Ketan Padegaonkar &lt;KetanPadegaonkar [at] gmail [dot] com&gt;
 * @version $Id$
 */
public class PlayBackThread extends Thread {

	private static final Log	log	= LogFactory.getLog(PlayBackThread.class);
	/** the e */
	private final Event			e;

	public PlayBackThread(Event e) {
		super("PlayBackThread");
		this.e = e;
	}

	public void run() {
		log.debug("running...");

		try {
			perform();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * @throws WidgetNotFoundException
	 */
	private void perform() throws Exception {
		Display display = e.display;
		SWTEclipseBot bot = new SWTEclipseBot();

		createJavaProject(bot);
		createJavaClass(bot);
		Thread.sleep(1000);
		SWTBotEclipseEditor editor = bot.editor("HelloWorld.java");

		Thread.sleep(1000);
		editor.notifyKeyboardEvent(SWT.CTRL, '.');
		editor.quickfix("Add unimplemented methods");

		editor.navigateTo(7, 0);
		editor.autoCompleteProposal("sys", "sysout - print to standard out");

		editor.typeText("\"Hello World\"");

		editor.navigateTo(3, 0);
		editor.autoCompleteProposal("main", "main - main method");

		editor.typeText("new Thread (new HelloWorld ());");
		if (true)
			return;
		editor.notifyKeyboardEvent(SWT.CTRL, '2');
		editor.notifyKeyboardEvent(SWT.NONE, 'L');
		editor.notifyKeyboardEvent(SWT.NONE, '\n');

		editor.typeText("\n");
		editor.typeText("thread.start();\n");
		editor.typeText("thread.join();");
		editor.quickfix("Add throws declaration");
		editor.notifyKeyboardEvent(SWT.NONE, (char) 27);
		editor.notifyKeyboardEvent(SWT.NONE, '\n');

		editor.notifyKeyboardEvent(SWT.CTRL, 's');

		editor.notifyKeyboardEvent(SWT.ALT | SWT.SHIFT, 'x');
		editor.notifyKeyboardEvent(SWT.NONE, 'j');

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
	}

	/**
	 * @param bot
	 */
	private void createJavaClass(SWTEclipseBot bot) throws Exception {
		bot.menu("File").menu("New").menu("Class").click();
		bot.shell("New Java Class").activate();
		bot.textWithLabel("Name:").setText("HelloWorld");
		bot.textWithLabel("Package:").setText("com.helloworld");
		implementsInterface(bot, "java.lang.Runnable");
		bot.checkBox("Inherited abstract methods").click();
		bot.button("Finish").click();
	}

	/**
	 * @param bot
	 */
	private void implementsInterface(final SWTEclipseBot bot, String interfaceClass) throws Exception {
		bot.button("Add...").click();
		bot.shell("Implemented Interfaces Selection").activate();
		bot.textWithLabel("Choose interfaces:").setText(interfaceClass);
		bot.waitUntil(Conditions.tableHasRows(bot.table(), 1));
		bot.button("OK").click();
		bot.shell("New Java Class").activate();
	}

	/**
	 * @param bot
	 */
	private void createJavaProject(net.sf.swtbot.SWTBot bot) throws Exception {
		bot.menu("File").menu("New").menu("Java Project").click();
		bot.shell("New Java Project").activate();
		bot.textWithLabel("Project name:").setText("MyProject");
		bot.button("Finish").click();
	}
}

ユニット系のサンプル

via

package net.sf.swtbot.widgets;

import net.sf.swtbot.SWTBot;
import net.sf.swtbot.finder.AbstractSWTTestCase;

/**
 * @author Ketan Padegaonkar &lt;KetanPadegaonkar [at] gmail [dot] com&gt;
 * @version $Id$
 */
public class SWTBotButtonTest extends AbstractSWTTestCase {

	private SWTBot	bot;

	public void testFindsButtons() throws Exception {
		assertEquals("One", bot.button("One").getText());
		assertEquals("Select Listeners", bot.button("Select Listeners").getText());
	}

	public void testClicksButtons() throws Exception {
		SWTBotShell shell2 = null;
		try {
			SWTBotButton button = bot.button("Set/Get API");
			button.click();
			shell2 = bot.shell("Button Set/Get API");
			assertNotNull(shell2.widget);
			assertEquals("Button Set/Get API", shell2.getText());
		} finally {
			if ((shell2 != null) && (shell2.widget != null))
				shell2.close();
		}
	}

	public void testFindsBackgroundColor() throws Exception {
		assertNotNull(bot.button("One").backgroundColor());
	}

	public void testFindsForegroundColor() throws Exception {
		assertNotNull(bot.button("One").foregroundColor());
	}

	protected void setUp() throws Exception {
		super.setUp();
		bot = new SWTBot();
		bot.tabItem("Button").activate();
	}

}

参考