viewerをビューに配置していくときに、最後に必ずと言っていいほど記述する、 getSite().registerContextMenu(menuMgr, viewer); について、コンテキストメニューを外部に公開するときは必ず書くんですよね、と適当に理解していたのですが、ちゃんと調べてみました。ちなみにここにもまとめてありますが、このregisterContextMenu?を記述すると指定したメニューをビューのIDで外部に公開しますよという意味になります。 スニペット*1として、こうやっときゃいいやってのはわかったんだけど、なんとなくスッキリしない。 ということで、viewerのところの引数をいろいろ変えてみて、どのような挙動をするのかテストしてみました。 設定 †上のように二つのviewerをビューに貼り付けて色々やってみる。 action1,action2はActionのanonymousクラス。。またviewer2は、setSelectionProvider?の記述により「このビューのSelectionProvider?はviewer2だよ」と宣言している。 SelectionProvider?から値をとってみる †
結果 †
当たり前ですね。getSite().setSelectionProvider?(viewer2)しているので「このビューのSelectionProvider?から選択してるものちょうだい」といった場合、viewer2で選択されているものが取得できるわけですね。 つぎにregisterContextMenu?してからやってみる †次に、 getSite().registerContextMenu(getSite().getId(), menuMgr, viewer1); してみる*2。特に挙動は変わらず。registする作業はプログラマティカルに追加したアクションには関係ないのかな*3??? 拡張ポイントのばあい †次に、拡張ポイントでポップアップを追加する。 </viewerContribution> <viewerContribution id="nu.mine.kino.plugin.samples.rcp.viewerContribution3" targetID="nu.mine.kino.plugin.samples.views.ProviderSampleView"> <action ↑これはviewのIDではなく、 これ↓です。ねんのため registerContextMenu(getSite().getId(), menuMgr, viewer1); class="nu.mine.kino.plugin.samples.rcp.Action5" icon="icons/sample.gif" id="nu.mine.kino.plugin.samples.rcp.action5" label="アクション5" menubarPath="additions"/> </viewerContribution> IViewActionDelegate?の実装クラスAction5を public class Action5 implements IViewActionDelegate { private ISelection selection; private IViewPart view; public void init(IViewPart view) { this.view = view; } public void run(IAction action) { System.out.println("selectionからとってみる"); System.out.println(selection.getClass().getName()); System.out.println(selection); } public void selectionChanged(IAction action, ISelection selection) { this.selection = selection; System.out.println("selectionからとってみる"); System.out.println(selection.getClass().getName()); System.out.println(selection); } } とすると。。。 結果1 †まず getSite().registerContextMenu?(getSite().getId(), menuMgr, viewer1);を呼ばない場合、いくら拡張ポイントでtargetID指定で追加してもこのターゲットIDでコンテキストを登録していないので、ポップアップにアクションが追加されません。合掌。 次に getSite().registerContextMenu(getSite().getId(), menuMgr, viewer1); をしてからやってみると。。。 結果2 †なんと selectionからとってみる org.eclipse.jface.viewers.StructuredSelection [viewer1:b] となった。おもしろいのはビュー側で getSite().setSelectionProvider(viewer2); として「このビューのSelectionProvider?はviewer2だよ」と宣言しているにも関わらず、IViewActionDelegate?の実装クラスselectionChangedには、viewer2ではなくviewer1が渡ってきているのだ。なるほど、 getSite().registerContextMenu(getSite().getId(), menuMgr, viewer1); の意味はこのコンテキストメニュー(menuMgr)をgetSite().getId()というtargetIDで公開するよ、そのときのSelectionProvider?(selectionChangedの引数selectionを作るヤツ)はviewer1ですよという意味なんですね。 ではつぎに getSite().registerContextMenu(getSite().getId(), menuMgr, viewer2); とした場合はどうなるか。この例はviewer2をregisterContextMenu?しているので、拡張ポイントたちに対するSelectionProvider?はviewer2となり、IViewActionDelegate?の実装クラスはviewer2をリスンすることになります*4。でも、このメニューmenuMgrはviewerの方にセットされているので、アクション自体はviewer1に表示される。つまりviewer2をクリックするとselectionChangedが呼ばれるけど、viewer1のポップアップメニューに追加されるというわけわかんないことになります。こんなコトする必要はないですけど、仕組みはよく理解できました。 よってスニペットとしては getSite().registerContextMenu(getSite().getId(), menuMgr, getSite().getSelectionProvder()); よりも getSite().registerContextMenu(getSite().getId(), menuMgr, viewer1); のようにmenuMgrを追加したviewerを第3引数に設定するのが間違いがないかなあ、という結論になりました。だってこのビューのSelectionProvider?がmenuMgrを追加したビューワではない可能性があるからね。 ところで第三引数にnullをセットすると、拡張ポイントに対するSelectionProvider?がnullなので、selectionChangedは呼ばれんだろうと思ったのですが、メニューからそのアクションを選択したとき、なぜかselectionChangedが呼ばれ、空の*5selectionがセットされていた。ナゾだ。。actionインスタンスの方はViewPluginAction?というdelegateだ。。これ以上深追いはいいや。。。 現在のアクセス:15173 |