xfy.memo

xfy technology についての備忘録です。

2006 年 10 月のアーカイブ

2006 年 10 月 1 日 DocBook 用のボキャブラリコンポーネント (要素の種類の変更)

要素を増やせるようになったので、今度は要素の種類を変更できるようにします。

現時点でのボキャブラリコンポーネントの外部仕様

DocBook 用のボキャブラリコンポーネントとして、下記の機能を実装します。

要素の種類を変更する

パラグラフをプログラムリストに、プログラムリストをパラグラフに、それぞれ変更できるようにします。前回の要素の分割処理とは異なり、これらの処理はコンテキストメニューから行うことにします。コンテキストメニューの項目からは、下記のコマンド (後述) を呼び出します。

    :
<xvcd:vocabulary match="db:article" call-template="root" name="db:article">
  <ui:ui xmlns:ui="http://xmlns.xfy.com/ui" version="1.0">
    <ui:context-menu>
      <ui:menu-item label="パラグラフ" command="to-para"/>
      <ui:menu-item label="プログラムリスト" command="to-programlisting"/>
    </ui:context-menu>
  </ui:ui>
</xvcd:vocabulary>
    :

この XVCD スクリプトを XML 文書に適用すると、次のようにコンテキストメニューが表示されるようになります (が、コマンドが未定義なので、コンテキストメニューの項目は非活性状態になっています)。

スクリーンショット (PNG 形式、約 44KB)

次に、コンテキストメニューから呼び出されるコマンドを定義します。このコマンド中で、処理対象の要素 (= カレット位置の要素) の内容を新しい要素にコピーし、その要素で処理対象の要素を置き換えます。といっても、 XVCD には要素を置き換えるためのコマンドインストラクションが用意されていないので、要素の挿入 (xvcd:insert 要素) と要素の削除 (xvcd:delete 要素) とで代替します。

    :
<xvcd:command name="to-para">
  <inst:variable name="programlisting"
    select="xvcd:caret-node()/ancestor-or-self::db:programlisting[1]"/>

  <xvcd:insert ref="$programlisting" position="before">
    <xvcd:element name="para" namespace="{namespace-uri($programlisting)}">
      <xvcd:copy-of select="$programlisting/child::node()"/>
    </xvcd:element>
  </xvcd:insert>
  <xvcd:delete select="$programlisting"/>
</xvcd:command>
    :
メモ

新しい要素の挿入位置は、処理対象の要素の直前 (position="before") が良いようです。処理対象の要素の直後に挿入すると (position="after")、処理対象の要素を削除した際にカレットが消えて (どこかへいって ?) しまいます。

同様に、 to-programlisting コマンドも定義します。

    :
<xvcd:command name="to-programlisting">
  <inst:variable name="para"
    select="xvcd:caret-node()/ancestor-or-self::db:para[1]"/>

  <xvcd:insert ref="$para" position="before">
    <xvcd:element name="programlisting" namespace="{namespace-uri($para)}">
      <xvcd:copy-of select="$para/child::node()"/>
    </xvcd:element>
  </xvcd:insert>
  <xvcd:delete select="$para"/>
</xvcd:command>
    :

この XVCD スクリプトを XML 文書に適用すると、次のように要素の種類を変更できるようになります。

スクリーンショット (PNG 形式、約 40KB)

UI の改善

処理対象がパラグラフの場合、コンテキストメニューから選べるのは [プログラムリスト] だけであるべきです。同様に、処理対象がプログラムリストの場合、コンテキストメニューから選べるのは [パラグラフ] だけであるべきです。処理対象の要素に応じてコンテキストメニューの項目の状態 (活性、非活性) が変わるよう、 UI を改善します。

XVCD では、 xvcd:command 要素の enabled 属性値または要素の内容に応じて UI の活性、非活性が切り替わります。ここでは後者の方法を採り、 xvcd:command 要素中の inst:variable 要素を inst:for-each 要素に置き換えることにします。

    :
<xvcd:command name="to-para">
  <inst:for-each select="xvcd:caret-node()/ancestor-or-self::db:programlisting[1]">
    <xvcd:insert ref="." position="before">
      <xvcd:element name="para" namespace="{namespace-uri()}">
        <xvcd:copy-of select="child::node()"/>
      </xvcd:element>
    </xvcd:insert>
    <xvcd:delete select="."/>
  </inst:for-each>
</xvcd:command>

<xvcd:command name="to-programlisting">
  <inst:for-each select="xvcd:caret-node()/ancestor-or-self::db:para[1]">
    <xvcd:insert ref="." position="before">
      <xvcd:element name="programlisting" namespace="{namespace-uri()}">
        <xvcd:copy-of select="child::node()"/>
      </xvcd:element>
    </xvcd:insert>
    <xvcd:delete select="."/>
  </inst:for-each>
</xvcd:command>
    :
メモ

inst:for-each 要素内では処理対象の要素がカレントノードになるので、 xvcd:insert 要素の ref 属性値や xvcd:delete 要素の select 属性値などの XPath 表記が簡潔になります。

この XVCD スクリプトを XML 文書に適用すると、次のようにコンテキストメニューの項目の活性、非活性が切り替わります。

スクリーンショット (PNG 形式、約 40KB)

リファクタリング

例によって記述の重複を避けるために、 inst:for-each 要素の内容を別コマンド (コマンド名: replace-element) として切り出します。

    :
<xvcd:command name="replace-element">
  <inst:param name="target"/>
  <inst:param name="with"/>

  <xvcd:insert ref="$target" position="before" select="$with"/>
  <xvcd:delete select="$target"/>
</xvcd:command>
    :

replace-element コマンドにはパラメータが二つ備わっています (パラメータ名: targetwith)。このコマンドを呼び出す際は、処理対象 (= 置き換え対象) の要素を target パラメータに、新しい要素を with パラメータに、それぞれ指定して呼び出します。

    :
<xvcd:command name="to-para">
  <inst:for-each select="xvcd:caret-node()/ancestor-or-self::db:programlisting[1]">
    <inst:call name="replace-element">
      <inst:with-param name="target" select="."/>
      <inst:with-param name="with">
        <xvcd:element name="para" namespace="{namespace-uri()}">
          <xvcd:copy-of select="child::node()"/>
        </xvcd:element>
      </inst:with-param>
    </inst:call>
  </inst:for-each>
</xvcd:command>

<xvcd:command name="to-programlisting">
  <inst:for-each select="xvcd:caret-node()/ancestor-or-self::db:para[1]">
    <inst:call name="replace-element">
      <inst:with-param name="target" select="."/>
      <inst:with-param name="with">
        <xvcd:element name="programlisting" namespace="{namespace-uri()}">
          <xvcd:copy-of select="child::node()"/>
        </xvcd:element>
      </inst:with-param>
    </inst:call>
  </inst:for-each>
</xvcd:command>
    :

まとめ

現時点での XVCD スクリプトです。

2006 年 10 月 5 日 xfy Personal Client 1.0 のメニューは、 Mac OS メニューバーに組み込めない ?

下記の情報を参考に、 xfy Personal Client 1.0 のメニューを Mac OS メニューバーに組み込んでみました。

2004-11-20 xfy メモ - KENZ

http://d.hatena.ne.jp/KENZ/20041120#p1

結果

xfy Basic Edition 1.0 では正しく組み込まれましたが、 xfy Personal Client 1.0 (xfy Basic Edition 1.3) では正しく組み込まれませんでした。残念…… (パラメータの指定が間違っているのかもしれません)

xfy Basic Edition 1.0 での結果
コマンドライン
$ java -Dapple.laf.useScreenMenuBar=true \
> -jar xfy_combo_pack_051114/bin/xfyBasicEdition.jar
実行結果

スクリーンショット (PNG 形式、約 36KB)

xfy Personal Client 1.0 での結果
コマンドライン
$ java -Dapple.laf.useScreenMenuBar=true \
> -jar xfy-be1_3-060810/bin/xfyClient.jar
実行結果

スクリーンショット (PNG 形式、約 52KB)

2006 年 10 月 30 日 xfy Personal Client 1.0 のメニューを、 Mac OS メニューバーに組み込めました

先のエントリーで上手くいかなかった Mac OS X メニューバーへの組み込みの件についてフォーラムにポストしたところ、 (動作保証外ですが) 対策方法を教えていただきました。

対策方法を試した結果

xfy Personal Client 1.0 では、 JVM を再起動しているそうです。この JVM の再起動を抑止することで、 java コマンドのパラメータが有効になるとのことでした。

xfy Personal Client 1.0 での結果
コマンドライン
$ java -Dapple.laf.useScreenMenuBar=true \
> -Dcom.xfy.startup.XfyStartup.without-jvm-restart=true \
> -jar xfy-be1_3-060810/bin/xfyClient.jar
実行結果

スクリーンショット (PNG 形式、約 52KB)

それにしても、なぜ JVM を再起動しているのでしょう……


Powered by Movable Type 3.2-ja-2

Copyright © 2005, 2006 Shin All rights reserved.