このセクションでは、さらに高度なツリーの機能について見ていきます。
階層ツリー
ツリー要素は、ファイルマネージャやブラウザのブックマーク一覧に見られるような、階層を持ったリストの作成に利用することもできます。 このためにツリービューには、項目が位置しているツリー階層を指定するための関数がいくつかあります。 ツリーに置かれた各項目には、0 から始まる (階層の) レベルが設定されています。 ツリーの最上位にある項目のレベルは 0 で、その子項目のレベルが 1 、さらにその子項目のレベルは 2 といった具合に設定されることになります。 ツリーは、行部分の描画内容を確定するために、ビューに対して各項目のレベルを問い合わせます。
ツリーでは、親項目の開閉状態を示すアイコンや、親子間を結ぶ線の描画を行うとともに、行の描画では階層レベルに応じたインデントも行ってくれます。 ただし、このために、ビュー側では必要な行のレベルを記録しておく必要があります。 この処理は、しばしば非常にややこしくなりますが、 幸い、組み込みのコンテントツリービューは、こういった難しい処理はすべて引き受けてくれます。
入れ子の行を作成するために必要なことは、2 つめの treechildren
要素を、親となる treeitem
要素の中に加えることだけです。 あとは、加えた treechildren
の中に項目を加えるだけで、その項目の子となる行を加えていくことができます。 なお、内側の treechildren
要素を treerow
要素の中に置くのは正しい記述ではないため動作しません。 必ず treeitem
の中に置くようにしてください。
この手順を繰り返せば、深く入れ子になったツリーを作成することができます。 つまり、treeitem
要素には、 treerow
要素による (その項目自身の内容と対応する) 単一の行の宣言と、 treechildren
要素による複数の子項目の宣言を含むことができるということです。
また、これ以外に階層が正しく動作するために必要なことが 2 つあります。 まず、子を持つ treeitem
要素に対して、コンテナであることを明示しておく必要があります。 これは、以下のように container
属性を使用して設定します。
<treeitem container="true" />
これにより、利用者が treeitem
要素に該当する列をクリックすることで、内部の行を開閉することができるようになります。 子の行を、最初から開いた状態にしておくには open
属性を設定します。 利用者が、親項目を開閉する操作をしたとき、項目の開閉状態を切り替えるためにビューの toggleOpenState()
関数が呼び出されることになります。 コンテントツリービューでは、この関数の処理によって open
属性への状態の反映が行われます。
次に、最初の列 (treecol
) に primary
属性を設定することが必要です。 これによって、行が開閉可能かどうかを示す「+ 記号」や「小さな三角形」といったアイコンが最初の列にあるセルの先頭に付加され、 子の行はインデントされて表示されるようになります。 なお、primary
を設定した列は、利用者が列右端のドロップダウンリストで非表示にする操作ができないことに注意してください。
階層ツリーの例
階層ツリーの簡単な例を、以下に示します。
<tree rows="6"> <treecols> <treecol id="firstname" label="First Name" primary="true" flex="3" /> <treecol id="lastname" label="Last Name" flex="7" /> </treecols> <treechildren> <treeitem container="true" open="true"> <treerow> <treecell label="Guys" /> </treerow> <treechildren> <treeitem> <treerow> <treecell label="Bob" /> <treecell label="Carpenter" /> </treerow> </treeitem> <treeitem> <treerow> <treecell label="Jerry" /> <treecell label="Hodge" /> </treerow> </treeitem> </treechildren> </treeitem> </treechildren> </tree>
この例によって、階層ツリーが作成されています。 画像から、最初の行の先頭に小さな「+」または「-」記号が表示されているのがわかると思います。 これは子の行が存在することを示していて、しばしば 「ツイスティ」と呼ばれます。 利用者は、その行をクリックすることでリストを開閉することができます。 また、子の行はインデントされています。 なお、親の「Guys」の行は、単に子の行をまとめるためにのみ存在するので、列は 1 つしか必要としません。
外側の treeitem
要素は、treerow
要素と treechildren
要素を 1 つずつ含んでいます。 前者は親の行のためのデータを作成し、後者は子の項目を含みます。
同様にすることで、行の入れ子を深くすることもできます。 子を含む行には container
属性を設定する必要があることを覚えておいてください。 単に子の行が存在するかどうかだけでは、コンテナとして扱うべきかを判断するのに十分ではないため、 子の行の存在の有無にかかわらず、コンテナとして扱うべき行に container
属性を設定する仕様になっています。 例えば、ファイルが存在しない空のディレクトリは、ファイルではなくコンテナとして扱われるべきだろうということです。
ツリーの列の詳細
ツリー追加可能な属性に enableColumnDrag
があります (注:名前に大文字が混じっています)。 この値を true
に設定すると、利用者が列の見出しをドラッグすることで、列を並び替えることが可能になります。
また、利用者が列の幅を変更したいと思うケースも多いはずです。 それを実現するには splitter
要素を、各 treecol
要素の間に加えます。 これにより、小さなノッチが各列の見出しの間に表示され、 利用者はこれをドラッグして列の幅を変えることができるようになります。 なお、スタイルクラス tree-splitter
を指定することで、このノッチを隠した外観にすることも可能です。 この場合も機能に影響はないため、依然として列幅を変更することは可能です。
列幅の下限と上限は、それぞれ minwidth
と maxwidth
属性で設定することができます。
列の true
にすると、列は非表示がデフォルトになります。 このときも、利用者は見出し行の端にあるドロップダウンリストからその列を選択することで、その列を表示するように変更できます。
列の状態を保存する
詳細は後のセクションで説明する予定ですが、 XUL の全ての要素は、 persist
属性を設定することでセッション終了時に要素の状態を保存できるため、 これを利用することで、列の状態をセッション間で保存することが可能です。 つまり、利用者が列のレイアウトを自分の好みで変更したとき、その内容を自動的に保存して、次回の表示時に再現するように指定できます。 このためには、以下の例で示すように、いくつかの属性を保存する必要があります。
<tree enableColumnDrag="true" flex="1"> <treecols> <treecol id="runner" label="Runner" flex="2" persist="width ordinal hidden" /> <splitter class="tree-splitter" /> <treecol id="city" label="Home City" flex="2" persist="width ordinal hidden" /> <splitter class="tree-splitter" /> <treecol id="starttime" label="Start Time" flex="1" persist="width ordinal hidden" /> <splitter class="tree-splitter" /> <treecol id="endtime" label="End Time" flex="1" persist="width ordinal hidden" /> </treecols> <treechildren> <treeitem> <treerow> <treecell label="Joshua Granville" /> <treecell label="Vancouver" /> <treecell label="7:06:00" /> <treecell label="9:10:26" /> </treerow> </treeitem> <treeitem> <treerow> <treecell label="Robert Valhalla" /> <treecell label="Seattle" /> <treecell label="7:08:00" /> <treecell label="9:15:51" /> </treerow> </treeitem> </treechildren> </tree>
永続性 (persist) を持たせることで保存する必要があるのは、以下の 3 つの属性になります。
次のセクションでは、ツリーで選択されている項目の取得と設定について見ていきます。