前の関連記事:LibreOffice(31)Pythonマクロをドキュメントファイルに埋め込む
コンポーネントフレームワークは画面表示に関するものです。マクロからメッセージボックスなどを表示させるときに知っている必要があります。知らないことが多くて理解にとても時間がかかってLibreOffice(15)デベロッパーガイド3 コンポーネントコンテクストから2ヶ月程経ってしまいました。
コンポーネントフレームワークはフレーム・コントローラ・モデル・パラダイム(FCM)になっている
デベロッパーガイドでは6 オフィスの開発 Office Developmentに解説があります。
オフィスドキュメントと画面表示とを繋ぐ仕組みはフレームワークAPIといい、それにはコンポーネントフレームワークとディスパッチフレームワークがあります。(6.1.1 概要 OpenOffice.org Application Environment)
マクロで主に使うのはコンポーネントフレームワークの方です。
ここでいう「コンポーネント」はLibreOffice(5)PythonでLibreOfficeが動く仕組み:UNOででてきた「UNOコンポーネント」ではなく、LibreOffice(15)デベロッパーガイド3 コンポーネントコンテクストでできたUNOオブジェクトの「コンポーネント」です。
UNOオブジェクトの「コンポーネント」とはオブジェクトのうちcom.sun.star.lang.XComponentインターフェイスをもっているものを指します。
コンポーネントフレームワークではこれらコンポーネントが相互に作用することによって動作します。
これらのコンポーネントのうち、「フレーム」、「コントローラ」、「モデル」の3つに着目して、これらが連携する仕組みをフレーム・コントローラ・モデル・パラダイム(FCM)といいます。(OpenOffice.org でのフレームコントローラーモデルパラダイム Frame-Controller-Model Paradigm in OpenOffice.org)
モデルとは、ドキュメントデータとそれを変更するメソッドをもったコンポーネントオブジェクト。
コントローラとは、ドキュメント固有の表示のさせ方などを決めるコンポーネントオブジェクト。
Writerのテキスト形式やCalcのスプレッドシート形式にデータを表示させます。
フレームとは、画面に表示されるウィンドウと、コントローラ・モデルの間を取り持つコンポーネントオブジェクト。
FCMでの複数のフレームは階層構造になっている
フレームがFCMの要となり、画面表示はフレーム単位で管理されます。
複数のフレームが存在する場合はこれらは階層構造になっており、これらフレームのルートフレームにあたるものを「デスクトップ」といいますが、デスクトップ自体はモデルやコントローラはもちません。(デスクトップ環境 Desktop Environment)
フレームはコンポーネントウィンドウを表示させるコンテナウィンドウをもつ
フレームには「コンテナウィンドウ」という固有のウィンドウをもっています。(フレーム Frames)
フレーム(フレームコンポーネントオブジェクト)が作成されるとき、com.sun.star.frame.XFrameインターフェイスのinitialize()メソッドでUNOオブジェクトのウィンドウ(com.sun.star.awt.XWindow)が初期化されます。
フレームで初期化されたウィンドウはさらにcom.sun.star.awt.XTopWindowインターフェイス
(2017.8.18追記。これは間違いです。コンテナウィンドウになるにはXTopWindowインターフェイスをもっているウィンドウでないといけません。LibreOffice5(60)ドラッグでリサイズできるsplitterコントロールの例参照。)
コンテナウィンドウだけでは画面に独立に表示されるウィンドウとはなれず、その部分に「表示可能なコンポーネント」を表示させるコンポーネントウィンドウをもたないといけません。
「表示可能なコンポーネント」とは、「フレーム」、「コントローラ」、「モデル」などのUNOのコンポーネントオブジェクトとはまた違うもので、「コントローラ」と「モデル」の組み合わせで成り立つものです。(デスクトップ環境 Desktop Environment)
表示可能なコンポーネントがコンポーネントウィンドウをもっており、このウィンドウがコンテナウィンドウに表示されることにより完全な独立したウィンドウになります。
表示可能なコンポーネントには次の3種類があります。
①モデルとコントローラを備えたオフィスドキュメント。
②文献目録やデータベースブラウザのようにモデルを欠いたもの。
③プレビューウィンドウのようにモデルもコントローラも欠き、コンポーネントウィンドウしかもたないもの。
コントローラをもつ①と②のことをオフィスコンポーネントといいます。
コントローラをもたない③はトリビアルコンポーネントといいます。
実際に画面にコンテナウィンドウとコンポーネントウィンドウがどのように表示されるのかがわからなくて、悩んだのですがOOoBasic/Generic/Window - ...?に出会ってようやく理解できました。
(2018.2.2追記。LibreOffice5.4で調べてみるとContainerWindowにはウィンドウタイトルバーは含まれていませんでした。Calc(64)コンテナウィンドウとコンポーネントウィンドウの位置の取得参照。)
緑の部分と青の部分が ContainerWindow、青の部分が ComponentWindow です。そして、枠がフレームになります。
OOoBasic/Generic/Window - ...?
実際の画面への描画されるのはツールキットが作ったピアオブジェクト
ウインドウ Windowsに書いてあることが理解できなくて困りました。
(2017.7.6追記。Graphical User Interfaces - Apache OpenOffice Wikiの章のThe Toolkit Serviceにいろいろ書いてありました。)
com.sun.star.awt.XWindowインターフェイスをもつUNOのウィンドウオブジェクトがcom.sun.star.awt.XWindowPeerインターフェイスをもつオブジェクトと対になっている根拠がわかりません。
LibreOffice 4.2 SDK APIのInheritance diagramをたどっていってもXWindowとXWindowPeerの接点がみつけられず、デベロッパーガイドのウインドウ・インタフェース Window Interfacesを読んでも納得できません。
「peer」とか「toolkit」でGoogle検索しても理解できる解説に出会えなかったので、画像検索して[Chapter 15] 15.2 The Peer InterfacesのFigure 15.2: Creating a Button Peerをみてようやく理解できました。
画面描画にはマシン固有の機能を使わないといけないのですが、その違いを吸収して同じコマンドを受け付けて画面に描いてくれるのがツールキット。
ツールキットが描いてくれたオブジェクトがピアオブジェクト。
ということでUNOのウィンドウオブジェクトのピアオブジェクトがcom.sun.star.awt.XWindowPeerインターフェイスをもつオブジェクトに相当するということがわかりました。
[Chapter 15] 15.2 The Peer Interfacesはこの本がネット上で公開されているもののようです。
デベロッパーガイドを読むにはJavaの知識が結構必要になりますね。
各オブジェクトの関係図
マクロを書くときにはコンポーネントフレームのオブジェクトを相互に得ないといけないときが多いです。
デベロッパーガイドの相互にフレーム、コントローラーとモデルを得る Getting Frames, Controllers and Models from Each Otherに相互に得るメソッドが図にしてあります。
これを改変してみました。
(2017.8.18追記。マクロで渡される定数XSCRIPTCONTEXTのgetDocument()で返ってくるのはモデルになります。)
(2018.1.3追記。フレームとオフィスコンポーネントの結びつきは交換可能な関係であり、オフィスコンポーネントが入れ替わっても同じフレームとコンポーネントウィンドウが使われます。Calc(55)追加できるリスナー一覧: その7参照。)
オフィスコンポーネントのモデルは共有が可能
オフィスコンポーネントのモデルは共有が可能です。(コントローラー Controllers)
この機能を使うと同じドキュメントファイルを同時に編集することができます。
LibreOffice Calcで試してみます。
まずファイルを1つ開きます。
メニューから、ウィンドウ→新しいウィンドウ。
「無題1」というウィンドウに対して同じ内容の「無題1:2」というウィンドウが開きましたね。
モデルを共有しているだけなのでこれらは違うセルの選択が可能です。
「無題1:2」のセルに入力した内容を確定すると「無題1」に反映されました。
フレームはサブフレームをもてるが使い道がよくわからず
(2017.8.18追記。LibreOffice5(54)Javaの例:GUIを実行するのダイアログにオフィスのドキュメントを表示させる例でサブフレームを使う例がでてきます。モダルダイアログではフレームを扱わなくてもよいですが、モードレスダイアログではフレーム列に追加しないと閉じるボタンが使えないので、フレームを扱うことになります。)
フレームはサブフレームをもてます。(フレーム Frames)
LibreOffice Calcではメニューの、挿入→フレーム。
「参照」でなにかファイルを選択して「OK」とするとその内容がシートの一部に表示されます。
もうひとつのCalcのファイルを挿入してみました。
サブフレームのなかのセルは選択できますが入力はできません。
サブフレームのセルの内容はコピーできました。
サブフレームの移動や大きさの変更はできませんでした。
この機能は使う機会はなさそうですな、、、
もうひとつのCalcのファイルを挿入してみました。
サブフレームのなかのセルは選択できますが入力はできません。
サブフレームのセルの内容はコピーできました。
サブフレームの移動や大きさの変更はできませんでした。
この機能は使う機会はなさそうですな、、、
参考にしたサイト
Apache OpenOffice Developer's Guide - Apache OpenOffice Wiki
PDF版の表紙にOpenOffice.org 3.1 Developer's Guideと書いてあります。
Developer's Guide
OpenOffice Developer's Guideの日本語版。OpenOffice.org 2.0より前のもののようです。
LibreOffice: Namespace List
LibreOffice 4.2 SDK APIの入り口com.sun.star。
OOoBasic/Generic/Window - ...?
デベロッパーガイドをいくら読んでもわからなかったContainerWindowとComponentWindowの関係がここを読んでようやくわかりました。
[Chapter 15] 15.2 The Peer Interfaces
このFigure 15.2: Creating a Button Peerをみてツールキットが何をしているのかがわかりました。
faq/5/451 - OpenOffice.org Q&A
MDIかSDIかはフレームの実装を入れ換えることで変更可能なようですね。
0 件のコメント:
コメントを投稿