LibreOffice5(19)イベント駆動する拡張機能のJavaの例:AsyncJob.oxt その3

2016-01-03

旧ブログ

t f B! P L

前の関連記事:LibreOffice5(18)拡張機能python-tokencounter-calc-addin.oxtをリモートデバッグする


Addons.xcuはイベント駆動の定義ではなくて、LibreOfficeにメニューを追加してその項目からJobs.xcuで定義したジョブを呼び出しています。

Addons.xcuでメニュー項目を定義する


oor:name="AddonMenu"の下のノードで各メニュー項目を定義します。

oor:name="AddonMenu"の下のノードで定義したメニュー項目はツール→アドオンのサブメニューに出現します。

Framework/Article/Addon Menu Toolbar Merging - Apache OpenOffice Wikiの方法を使うと任意の場所に項目を追加できるようです。

メニュー項目の出現順はAddons.xcuに書いた順番ではなくメニュー項目の定義名(メニュータイトルではない)でソートされます。
<?xml version='1.0' encoding='UTF-8'?>
<!-- アドオンに関する定義をしていることを示す。 -->
<oor:component-data oor:name="Addons" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <node oor:name="AddonUI"><!-- アドオンのユーザーインターフェイスを定義していることを示す。 -->
        <node oor:name="AddonMenu"><!-- ツール→アドオン、のサブメニューの項目。 -->
            <node oor:name="myAsyncJobAlias" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
                <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
                    <value>vnd.sun.star.job:alias=AsyncJob</value><!-- ジョブのエイリアスでコマンドを指定。 -->
                </prop>
                <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
                    <value xml:lang="en-US">AsyncJob (ALIAS)...</value><!-- メニュー項目英語表示。 -->
                    <value xml:lang="ja">AsyncJob (エイリアス) ...</value><!-- メニュー項目日本語表示。 -->
                </prop>
                <prop oor:name="Target" oor:type="xs:string"><!-- ターゲットフレーム。 -->
                    <value>_self</value>
                </prop>
            </node>
            <node oor:name="myAsyncJobEvent" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
                <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
                    <value>vnd.sun.star.job:event=onMyOwnJobEvent</value><!-- イベント名でコマンドを指定。 -->
                </prop>
                <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
                    <value xml:lang="en-US">AsyncJob (EVENT)...</value><!-- メニュー項目英語表示。 -->
                    <value xml:lang="ja">AsyncJob (イベント) ...</value><!-- メニュー項目日本語表示。 -->
                </prop>
                <prop oor:name="Target" oor:type="xs:string">
                    <value>_self</value><!-- ターゲットフレーム。 -->
                </prop>
            </node>
            <node oor:name="myAsyncJobService" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
                <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
                    <value>vnd.sun.star.job:service=com.sun.star.comp.framework.java.services.AsyncJob</value><!-- サービス名(実装名)でコマンドを指定。 -->
                </prop>
                <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
                    <value xml:lang="en-US">AsyncJob (SERVICE)...</value><!-- メニュー項目英語表示。 -->
                    <value xml:lang="ja">AsyncJob (サービス) ...</value><!-- メニュー項目日本語表示。 -->
                </prop>
                <prop oor:name="Target" oor:type="xs:string"><!-- ターゲットフレーム。 -->
                    <value>_self</value>
                </prop>
            </node>
        </node>
    </node>
</oor:component-data>

Menus - Apache OpenOffice Wikiにノードの各プロパティの解説があります。

それぞれのメニュー項目からそれぞれ違った方法でJobs.xcuで定義したジョブを呼び出しています。

オリジナルのAddons.xcuではImageIdentifierでOpenOffice内部のアイコン画像を呼び出しているようですが、LibreOfficeでの指定方法がわかりませんでしたのでこのプロパティは削除しました。(openoffice - framework dev - [framework-dev] Private images numbers参照。)

png画像の指定方法などはImages for Toolbars and Menus - Apache OpenOffice Wikiにありました。

<value xml:lang="x-no-translate"></value>の値についてもデベロッパーガイドに記載部位を見つけられなかったので削除しました。

Titleプロパティの値でxml:lang="ja"を指定すると日本語版では優先されて表示されるようです。

ja版がなくてen-US版だけにするとen-US版が表示されました。

Targetプロパティの値で_blankを指定するとメニュー項目がグレイになって選択できなくなりました。

Addons.xcuでジョブを呼び出している3つの方法


Using the vnd.sun.star.jobs: URL Schema - Apache OpenOffice Wiki

AsyncJob.oxtで追加されるメニュー項目はすべて同じ実装を呼び出していますがそれぞれ呼び出し方が違います。

イベント名で呼び出す方法

ツール→アドオン→AsyncJob(イベント)、を実行した場合のコマンドURLはvnd.sun.star.job:event=onMyOwnJobEventになっています。

これでLibreOffice5(17)イベント駆動する拡張機能のJavaの例:AsyncJob.oxt その2のJobs.xcuの22行目のイベントonMyOwnJobEventが呼ばれてそのサブノードのジョブリストのサブノードのAsycJobジョブが呼びだされます。

AsycJobジョブはJobs.xcuの5行目で定義されていてそのSerivceプロパティの値のcom.sun.star.comp.framework.java.services.AsyncJobが呼ばれてそのあとはAsycJob.javaの__getComponentFactoryメソッドで実装名からUNOサービスcom.sun.star.task.AsyncJobがインスタンス化されてそのcom.sun.star.task.XAsyncJobインターフェイスのexecuteAsync()メソッドが実行されます。

このAsycJob.javaの__getComponentFactoryメソッドが実行する下りは単なる私の推測であって解説は見つけられませんでした。(LibreOffice(67)Writing UNO componentsのThumbs Exampleその3にでてきた__getServiceFactory() メソッドと同じようなもの?)

メニュー呼び出し

コマンドURLの呼び出し

イベントの呼び出し(ここまでAddons.xcuで設定)

イベント名からエイリアスの呼び出し

エイリアス名からサービス(実装名)の呼び出し(ここまでJobs.xcuで設定)

com.sun.star.task.AsyncJobサービスのexecuteAsync()メソッドを実行(AsyncJob.javaで実装)

とりあえずこういう流れのようです。

(2018.4.28追記。エイリアスとはコンポーネントスキーマノードでいうとoor:name="Jobs"のセットノードの子ノードのグループノードの属性oor:nameの値のことです。)

エイリアス名で呼び出す方法

ツール→アドオン→AsyncJob(エイリアス)、を実行した場合のコマンドURLはvnd.sun.star.job:alias=AsyncJobになっています。

メニュー呼び出し

コマンドURLの呼び出し

エイリアスの呼び出し(ここまでAddons.xcuで設定)

エイリアス名からサービス(実装名)の呼び出し(ここまでJobs.xcuで設定)

com.sun.star.task.AsyncJobサービスのexecuteAsync()メソッドを実行(AsyncJob.javaで実装)

イベント名で呼び出す段階が省略されました。

サービス名で呼び出す方法

ツール→アドオン→AsyncJob(サービス)、を実行した場合のコマンドURLはvnd.sun.star.job:service=com.sun.star.comp.framework.java.services.AsyncJobになっています。

メニュー呼び出し

コマンドURLの呼び出し

サービス(実装名)の呼び出し(ここまでAddons.xcuで設定)

com.sun.star.task.AsyncJobサービスのexecuteAsync()メソッドを実行(AsyncJob.javaで実装)

イベントもエイリアスも使わず直接サービスを呼び出しています。

Jobs.xcuを使っていないのでJobs.xcuを削除してmanifest.xmlも修正してoxtファイルを作りなおして実行してみましたが問題なく動作しました。


Jobs.xcuで定義して渡していた引数は当然渡せていません。

com.sun.star.task.JobExecutorサービスのtrigger()メソッドでイベント名でジョブを呼び出す


trigger()メソッドcom.sun.star.task.XJobExecutorインターフェイスのメソッドで、com.sun.star.task.JobExecutorサービスがもつインターフェイスになります。

trigger()メソッドは引数にイベント名を渡せます。

イベント名を渡すことでジョブが実行できます。

linuxBean14.04(88)LibreOffice5をIPython Notebookから操作するで設定したIPython Notebookからtrigger()メソッドでAsyncJob.oxtのJobs.xcuで定義したonMyOwnJobEventイベントを呼び出してみます。
In [1]:
import unopy
XSCRIPTCONTEXT = unopy.connect()
if not XSCRIPTCONTEXT:
    print("Failed to connect.")
    import sys
    sys.exit(0)
In [2]:
ctx = XSCRIPTCONTEXT.getComponentContext()
smgr = ctx.getServiceManager()
In [3]:
obj = smgr.createInstanceWithContext("com.sun.star.task.JobExecutor", ctx)
In [4]:
obj.trigger("onMyOwnJobEvent")
これで次のメッセージボックスが表示されました。


ちゃんとイベント名からcom.sun.star.comp.framework.java.services.AsyncJobサービスの実装を実行できました。

EnvTypeがEXECUTORになっているので再度メッセージボックスを表示させようと思うと拡張機能マネージャーで再度AsyncJob.oxtを登録し直さないといけません。

こうなるのは単にAsyncJob.javaでcom.sun.star.task.XAsyncJobインターフェイスのexecuteAsync()メソッドを実装するときにそのようにプログラミングしているからという理由だけです。

executeAsync()メソッドの引数のlArgsでフレームを取得できていないのでjava7のjavax.swing.JOptionPaneのshowMessageDialog()メソッドでメッセージボックスが表示されています。

これも単にAsyncJob.javaでそうプログラミングされているからという理由です。

LibreOffice5(6)既存インターフェイスを継承してPythonスクリプトをUNOコンポーネント化する例:その1com.sun.star.task.XJobExecutorインターフェイスを継承してtrigger()メソッドを実装している例をみているときは「トリガー」の意味がよくわかりませんでしたが、今回ようやくわかりました。

OOoPython/UNOComponent - ...?に書いてあるようにtrigger()メソッドをコマンドURLで呼び出してみます。

service:com.sun.star.task.JobExecutor?onMyOwnJobEvent

これでcom.sun.star.task.JobExecutorサービスのtrigger()メソッドの引数にonMyOwnJobEventが渡されて実行できるとのことです。

Addons.xcuの<node oor:name="AddonMenu">ノードの下のメニュー項目のノードに以下を追加してAsyncJob.oxtを作成しなおしました。
            <node oor:name="myAsyncJobTrigger" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
                <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
                    <value>service:com.sun.star.task.JobExecutor?onMyOwnJobEvent</value>
                </prop>
                <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
                    <value xml:lang="en-US">AsyncJob (Trigger)...</value><!-- メニュー項目英語表示。 -->
                    <value xml:lang="ja">AsyncJob (トリガー) ...</value><!-- メニュー項目日本語表示。 -->
                </prop>
                <prop oor:name="Target" oor:type="xs:string"><!-- ターゲットフレーム。 -->
                    <value>_self</value>
                </prop>
            </node>

追加されたAsyncJob(トリガー)を実行します。


trigger("onMyOwnJobEvent")と同様の結果を得られました。

Addons.xcuでジョブを呼び出す方法のうちイベント名で呼び出す方法とはイベントを呼び出すコマンドURLの書式が異なります。

vnd.sun.star.job:event=onMyOwnJobEvent

これで呼び出すとEnvTypeがDISPATCHになります。

service:com.sun.star.task.JobExecutor?onMyOwnJobEvent

これで呼び出すとEnvTypeがEXECUTORになります。

それぞれジョブの実装の引数が異なります。

Writerだけに出現するサブメニューを作ってみる

<?xml version='1.0' encoding='UTF-8'?>
<!-- アドオンに関する定義をしていることを示す。 -->
<oor:component-data oor:name="Addons" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <node oor:name="AddonUI"><!-- アドオンのユーザーインターフェイスを定義していることを示す。 -->
        <node oor:name="AddonMenu"><!-- ツール→アドオン、のサブメニューの項目。 -->
            <node oor:name="myAsyncJobAlias" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
                <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
                    <value>vnd.sun.star.job:alias=AsyncJob</value><!-- ジョブのエイリアスでコマンドを指定。 -->
                </prop>
                <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
                    <value xml:lang="en-US">AsyncJob (ALIAS)...</value><!-- メニュー項目英語表示。 -->
                    <value xml:lang="ja">AsyncJob (エイリアス) ...</value><!-- メニュー項目日本語表示。 -->
                </prop>
                <prop oor:name="Target" oor:type="xs:string"><!-- ターゲットフレーム。 -->
                    <value>_self</value>
                </prop>
            </node>
   <node oor:name="myAsyncJob_submenu" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
    <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
     <value xml:lang="en-US">Submenu...</value><!-- メニュー項目英語表示。 -->
     <value xml:lang="ja">サブメニュー ...</value><!-- メニュー項目日本語表示。 -->
    </prop>
    <prop oor:name="Context" oor:type="xs:string">
     <value>com.sun.star.text.TextDocument</value><!-- Writerでのみ表示。 -->
    </prop>
    <node oor:name="Submenu"><!-- サブメニュー項目。 -->
     <node oor:name="myAsyncJobEvent" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
      <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
       <value>vnd.sun.star.job:event=onMyOwnJobEvent</value><!-- イベント名でコマンドを指定。 -->
      </prop>
      <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
       <value xml:lang="en-US">AsyncJob (EVENT)...</value><!-- メニュー項目英語表示。 -->
       <value xml:lang="ja">AsyncJob (イベント) ...</value><!-- メニュー項目日本語表示。 -->
      </prop>
      <prop oor:name="Target" oor:type="xs:string">
       <value>_self</value><!-- ターゲットフレーム。 -->
      </prop>
     </node>
     <node oor:name="myAsyncJobService" oor:op="replace"><!-- メニュー項目の重複しない名前。この名前でソートされる。 -->
      <prop oor:name="URL" oor:type="xs:string"><!-- コマンドURLを指定する。 -->
       <value>vnd.sun.star.job:service=com.sun.star.comp.framework.java.services.AsyncJob</value><!-- サービス名(実装名)でコマンドを指定。 -->
      </prop>
      <prop oor:name="Title" oor:type="xs:string"><!-- メニュー項目表示名。 -->
       <value xml:lang="en-US">AsyncJob (SERVICE)...</value><!-- メニュー項目英語表示。 -->
       <value xml:lang="ja">AsyncJob (サービス) ...</value><!-- メニュー項目日本語表示。 -->
      </prop>
      <prop oor:name="Target" oor:type="xs:string"><!-- ターゲットフレーム。 -->
       <value>_self</value>
      </prop>
     </node>
    </node>
   </node>
        </node>
    </node>
</oor:component-data>
18行目のメニュー項目の定義のContextプロパティの値にcom.sun.star.text.TextDocumentを入れたのでその項目はWirterでしか表示されません。

さらにそのメニュウ項目の定義のノードのサブノードにサブメニューのノードを作成しました。


Writerでツール→アドオン、の項目をみるとサブメニューが作成されていることがわかります。

xcuファイルではノードの階層構造が重要とわかりました。

参考にしたサイト


Menus - Apache OpenOffice Wiki
固定の場所にアドオンメニュー項目を追加する方法。

Framework/Article/Addon Menu Toolbar Merging - Apache OpenOffice Wiki
メニューバーとツールバーの任意の場所にをアドオンメニュー項目を追加する方法(未確認)。

openoffice - framework dev - [framework-dev] Private images numbers
AsyncJob.oxtのAddons.xcuで使用されているメニューアイコンの指定方法は古いようです。

Images for Toolbars and Menus - Apache OpenOffice Wiki
メニューアイコンの指定方法。

Using the vnd.sun.star.jobs: URL Schema - Apache OpenOffice Wiki
コマンドURLでジョブを呼び出す3つの方法。

OOoPython/UNOComponent - ...?
service:com.sun.star.task.JobExecutor?イベント名 でもジョブを呼び出せます。

次の関連記事:LibreOffice5(20)Anaconda3のtkinterモジュールを使う

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ