2017年8月26日土曜日

30: ディスパッチメカニズムにUNOコマンドを送る

<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>

本文 START

他の方法ではLibreOfficeまたはApache OpenOfficeの外からアクセスできない一部の機能を呼び出す方法を知る

LibreOfficeまたはApache OpenOfficeの外からすべての機能が呼び出せるわけではない

-Hypothesizer

これまで、UNO拡張機能からいくつかの機能を呼んできたが、すべての機能がUNO拡張機能やスタンドアロンのUNOプログラムから呼べるわけではない。

-Rebutter

知っている。あるUNOオブジェクトに属する機能を呼ぶためには、そのUNOオブジェクトへの参照(厳密に言えば、そのUNOオブジェクトのUNOプロキシへの参照)を得なければならないが、その参照を得られるという保証はない。

-Hypothesizer

我々は、以下のプロセスで、UNOオブジェクトへの参照を得ることができる。

コンポーネントコンテキストを得る。コンポーネントコンテキストに格納されたUNOオブジェクト(グローバルUNOサービスマネージャーはその一つ)を得る。グローバルUNOサービスマネージャーからUNOオブジェクトを得る。既にリファレンスを得ているUNOオブジェクトのメソッドの戻り値や出力引数としてUNOオブジェクトを得る。既にリファレンスを得ているUNOオブジェクトのプロパティとしてUNOオブジェクトを得る。

-Rebutter

UNOオブジェクトは、戻りstruct値のメンバーや出力struct引数のメンバーなどとしても得られるが、それは言うまでもないだろう。

-Hypothesizer

このプロセスで露出されないUNOオブジェクトは、LibreOfficeやApache OpenOfficeの外からはアクセスできない。

-Rebutter

勿論。それに、機能は、UNOコンポーネントのメソッドとして実装されてすらいないかもしれない。

-Hypothesizer

そう。LibreOfficeはほとんどがC++で実装されており、すべてのC++クラスがUNOコンポーネントだというわけではない。

-Rebutter

したがって、呼びたいが呼べないという機能が一部あり得る。

「ディスパッチ」というメカニズムがある

-Hypothesizer

しかし、一部の機能を呼べる別のメカニズムがあって、これが、ディスパッチメカニズムだ。

-Rebutter

それはどんなものなのか?

-Hypothesizer

あらかじめ定められたコマンド群があって、これらはそれぞれのURLによって識別され、それらのうちの1つを、そのURLとそのコマンドに特有のいくつかの引数を指定することで呼ぶことができる。

-Rebutter

それらのコマンドは、すべて呼ぶことができるのか?

-Hypothesizer

その保証はない。コマンドを呼ぶための引数として必要なUNOオブジェクトへのリファレンスを得られないかもしれないし、コマンドが正常に呼ばれるために満たされなければならない何らかの特別な条件があるかもしれない。

-Rebutter

特別な条件?

-Hypothesizer

例えば、コマンドを呼ぶ時に、あるダイアログウィンドウが開いていなければならないかもしれない。

-Rebutter

ふーむ . . .

-Hypothesizer

それはただ私が思いついた例というにすぎない。実際にはそんなケースはないかもしれない。

-Rebutter

ははあ . . .

そうしたURLやその引数はどうすれば知ることができるのか?

-Hypothesizer

それが問題だ。. . . それを包括的に説明する文書は私には見つけられなかった。

-Rebutter

ふーむ。

-Hypothesizer

今のところ、私の最良の方法は、LibreOfficeのソースコードを見ることだ。どこをどう見るべきなのかというのが次の問題だが、今はそれには立ち入らないことにする。

-Rebutter

オーケー。

-Hypothesizer

マクロを記録することで、コマンドを呼ぶ一部の例を見ることができるが、それらは、常に完全だとは言えない。

-Rebutter

どのように不完全であり得るのか。

-Hypothesizer

例えば、ドキュメントをPDFファイルとしてエクスポートする時、PDFファイルに署名することができるが、記録されたマクロはPDFファイルに署名しない。

-Rebutter

それでは、一部の引数はただ省かれるのか?

-Hypothesizer

または、一部の引数には値がセットされない。

-Rebutter

なるほど。それで、実際には、どうすればコマンドを呼べるのか?

-Hypothesizer

'com.sun.star.frame.DispatchHelper'というグローバルUNOサービスがあり、このUNOサービスのインスタンスをグローバルUNOサービスマネージャーから生成することができる。このインスタンスのUNOコンポーネントはUNOインターフェース、'com.sun.star.frame.XDispatchHelper'を実装しており、このUNOインターフェースには'executeDispatch'というメソッドがあり、このメソッドは、ディスパッチプロバイダ、コマンドURL、コマンド引数を受け取る。

-Rebutter

ディスパッチプロバイダというのは何だ?

-Hypothesizer

コマンドは神秘として実行されるわけではなく、ある実体が受け取って対処するが、私の理解では、この実体がディスパッチプロバイダだ。

-Rebutter

ディスパッチプロバイダはどのように得られるのか?

-Hypothesizer

それはもちろんコマンドによって違うが、今我々が関心を持つほとんどのケースでは、ドキュメントを格納しているフレームがディスパッチプロバイダだ。

-Rebutter

そのフレームはどのように得られるのか?

-Hypothesizer

フレームは、ドキュメントのコントローラーから、コントローラーが実装する'com.sun.star.frame.XController'UNOインターフェースを使って得られる。

-Rebutter

なるほど。

-Hypothesizer

結局、以下のサンプルコードを書いた。ここで、 'componentContext'は'com.sun.star.uno.XComponentContext'のコンポーネントコンテキスト(それをどのように得たかを知るには、この以前の記事を参照)、'l_currentSpreadSheetsDocumentModel'は'com.sun.star.frame.XModel'のスプレッドシートドキュメントUNOオブジェクト(それをどのように得たかを知るには、この以前の記事を参照)。

@ Source Code
import com.sun.star.frame.XFrame;
import com.sun.star.frame.XController;
import com.sun.star.frame.XDispatchHelper;
import com.sun.star.frame.XDispatchProvider;
import com.sun.star.beans.PropertyValue;

  XDispatchHelper l_dispatchHelperInXDispatchHelper = (XDispatchHelper) UnoRuntime.queryInterface (XDispatchHelper .class, componentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.DispatchHelper", componentContext));
  XController l_controllerInXController = (XController) UnoRuntime.queryInterface (XController.class, l_currentSpreadSheetsDocumentModel.getCurrentController ());
  l_frameInXDispatchProvider = (XDispatchProvider) UnoRuntime.queryInterface (XDispatchProvider.class, l_controllerInXController.getFrame ());
  PropertyValue [] l_commandProperties = new PropertyValue [1];
  l_commandProperties [0] = new PropertyValue ();
  l_commandProperties [0].Name = "ToPoint";
  l_commandProperties [0].Value = "$B$2";
  l_dispatchHelperInXDispatchHelper.executeDispatch (l_frameInXDispatchProvider, ".uno:GoToCell", "", 0, l_commandProperties);
-Rebutter

このコマンドは何だ?

-Hypothesizer

これは、セルのカレント位置をB2セルに移動するコマンドだ。

-Rebutter

それは、セルを選択するのとは違うのか?

-Hypothesizer

違う、少なくとも、見た目の上で。セルが選択されたとき、セルには色がつくが、セルがただカレントのときはセルには色がつかない。

-Rebutter

うーむ、それは微妙な違いだ。

-Hypothesizer

それに、スプレッドシートドキュメントをPDFファイルとしてエクスポートするとき、選択されたセルは選択箇所として認識されるが、ただのカレントセルはそうではない。

-Rebutter

「選択箇所として認識される」というのはどういう意味なのか?

-Hypothesizer

スプレッドシートドキュメントをPDFファイルとしてエクスポートするとき、ドキュメント内の選択された箇所のみをエクスポートすることができる。

-Rebutter

なるほど。

本文 END

<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>