Calc(53)追加できるリスナー一覧: その5

2017-12-31

旧ブログ

t f B! P L
前回作成したListenersForCalc.odsを使ってCalcドキュメントの操作で発火するリスナーについて調べていきます。今回はドキュメントを開いてウィンドウをの大きさを変更するところまでです。

前の関連記事:Calc(52)追加できるリスナー一覧: その4


「文書を開いた時」からドキュメントを開くまで


ListenersForCalc.odsでは「文書を開いた時」でマクロを起動しているのでそれ以後のリスナーの発火の結果を取得していることになります。

Windows10でエクスプローラーでListenersForCalc.odsをダブルクリックして開きましたがログファイルの出力はありませんでした。

Calc(48)ドキュメントイベントを調べるで調べたように、ここまででマクロを実行させたいときは、ツール→カスタマイズ、イベント、で「文書を有効化した時」(OnFocus)、「ビューの作成時」(OnViewCreated)、「文書を開いた時」(OnLoad)のいずれかにマクロを登録すればよいはずです。

「文書を有効化した時」(OnFocus)はドキュメントウィンドウの切り替えだけでイベントが発生してしまうので、ドキュメントを開いている間に1回だけ実行したいときは「文書を開いた時」(OnLoad)にマクロを登録するのが最善と思われます。

XBorderResizeListenerのborderWidthsChanged()メソッド


コントローラーにつけたXBorderResizeListenerのborderWidthsChanged()メソッドはドキュメントの(通常でいう)ウィンドウ(コンポーネントフレームワークでいうコンテナウィンドウ)の大きさを変更すると発火しました。

でもたまにウィンドウの大きさをいじっていないのに発火するときがありました。

borderWidthsChanged()メソッドはXInterface型(つまり何らかのUNOのインターフェイスをもっているオブジェクト)とBorderWidths Structの2つの引数をとります。

コントローラーにつけたborderWidthsChanged()メソッドの第1引数にはコントローラーが入っていました。

第2引数のBorderWidths StructのアトリビュートにはLeft 37、Top 15、Right 15、 Bottom 15が入っていました。

この値はそれぞれの方向の境界からの相対距離を表しているようですが、ウィンドウの大きさに関係なく常に同じ値でした。

BorderWidths Structの値を画面上で実測して調べたところ、これはコンポーネントウィンドウの外枠からの相対距離とわかりました。

コンポーネントウィンドウはLibreOffice(32)デベロッパーガイド4:コンポーネントフレームワークでやったようにフレームの中のモデルを表示している部分です。


Calcのコンポーネントウィンドウはこの部分に該当するようです。

行インデックスの幅が37ドット、列インデックスの高さが15ドット、垂直スクロールバーの幅が15ドット、水平スクロールバーの高さが15ドット、になっていました。
(上記はlinuxBean14.04の場合で、Windows10ではそれぞれ33、18、17、17になっていました。)
class BorderResizeListener(unohelper.Base, XBorderResizeListener):
 def __init__(self, dirpath, name):
  self.args = dirpath, name 
 def borderWidthsChanged(self, obj, borderwidths):
  dirpath, name = self.args
  if obj.supportsService("com.sun.star.sheet.SpreadsheetView"):  # objがコントローラーの時。
   cellrangeaddressconversion = obj.getModel().createInstance("com.sun.star.table.CellRangeAddressConversion")  # ドキュメントからCellRangeAddressConversionを取得。
   cellrangeaddressconversion.Address = obj.getVisibleRange()  # 表示されているセル範囲のCellRangeAddressを取得。
   txt = "Visible Range: {}".format(cellrangeaddressconversion.PersistentRepresentation)  # 表示されているセル範囲の文字列アドレスの取得。
  else:
   txt = "Top: {}, Left: {}, Right: {}, Bottom: {}, Object: {}".format(borderwidths.Top, borderwidths.Left, borderwidths.Right, borderwidths.Bottom, obj)
  methodname = "_".join((name, inspect.currentframe().f_code.co_name))
  createLog(dirpath, methodname, txt) 
 def disposing(self, eventobject):
  pass  
BorderResizeListenerのborderWidthsChanged()メソッドを変更して第1引数にコントローラーが入っていたときは表示しているセルの範囲をログファイルに出力するようにしました。

「表示されているセル」とはつまり「コンポーネントウィンドウに収まる範囲のセル」という意味のようで、水平スクロールバーの後ろに隠れているセル範囲も含まれていました。

スクロールバーのスクロールを感知したいときはスクロールバーコントロールを取得できるのなら、それにリスナーを追加することでできそうです(LibreOffice5(84)Javaの例:GUIをPythonにする その9参照)。

しかしLibreOffice5(58)モードレスダイアログの例をPythonに翻訳する:その4のMVCパラダイムの図を見るとウィンドウからコントロールを取得するのはできないのかもしれません。

次の関連記事:Calc(54)追加できるリスナー一覧: その6

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ