カスタムツリービューの基本的な使い方(その2~追加・削除)

その1ではデータをツリー表示するだけであったが、その2ではデータを追加・削除してツリーの表示へ反映させる。

fruits.xul

まず、追加・削除するためのボタンを xul:tree 要素の上側へ配置する。

    <hbox>
        <button label="Add" oncommand="addFruit();" />
        <button label="Delete" oncommand="deleteFruits();" />
    </hbox>

fruits.js

fruits.xul へ追加した各ボタンを押下したときに呼び出される2つの関数を定義する。
addFruit 関数は新たに追加する果物の名前を入力するためのプロンプトを表示し、入力が確定すると後述の FruitsTreeView#appendItem メソッドで実際のデータ追加処理を行う。

function addFruit() {
    var name = window.prompt("Enter fruit name.", "", "Add Fruit");
    if (!name)
        return;
    gFruitsTreeView.appendItem(name);
}

deleteFruits 関数は現在選択しているツリーの行番号を後述の FruitsTreeView#selectedIndexes プロパティから取得し、各行のデータを FruitsTreeView#removeItemAt メソッドで実際に削除する。なお、行番号のズレを防ぐため、削除は下側の行から順に行う。

function deleteFruits() {
    var indexes = gFruitsTreeView.selectedIndexes;
    indexes.reverse();
    indexes.forEach(function(index) {
        gFruitsTreeView.removeItemAt(index);
    });
}

FruitsTreeView.prototype へ appendItem メソッドを追加する。
このメソッドは、引数 aName の名前を持つアイテムをデータ _data へ追加し、 nsITreeBoxObject.rowCountChanged を呼び出すことでツリー表示を更新する。
ついでに新しく追加された列を自動的に選択してフォーカスする。

    /**
     * @param String aName The name of the new item.
     */
    appendItem: function(aName) {
        this._data.push(aName);
        var newIndex = this.rowCount - 1;
        this._treeBoxObject.rowCountChanged(newIndex, 1);
        // select the new item now
        this.selection.select(newIndex);
        this._treeBoxObject.ensureRowIsVisible(newIndex);
        this._treeBoxObject.treeBody.focus();
    },

FruitsTreeView クラスへ、現在選択している行番号を配列として取得するための読み込み専用プロパティ selectedIndexes を追加する。
ツリー上の選択は nsITreeView#selection プロパティから nsITreeSelection 型オブジェクトとして取得できる。
今回ツリーは複数選択を許可しているため、選択範囲を意識する必要がある。ちなみに <tree seltype=”single”> とすれば複数選択を不許可にできる。

    /**
     * readonly property to get selected row indexes as array.
     */
    get selectedIndexes() {
        var ret = [];
        var sel = this.selection;    // nsITreeSelection
        for (var rc = 0; rc < sel.getRangeCount(); rc++) {
            var start = {}, end = {};
            sel.getRangeAt(rc, start, end);
            for (var idx = start.value; idx <= end.value; idx++) {
                ret.push(idx);
            }
        }
        return ret;
    },

FruitsTreeView.prototype へ removeItemAt メソッドを追加する。
このメソッドは、引数 aRow の行番号に対応するアイテムをデータ _data から削除し、 nsITreeBoxObject.rowCountChanged を呼び出すことでツリー表示を更新する。
ついでに現在の選択状態を解除する。

    /**
     * @param Number aIndex The row index where we want to remove.
     */
    removeItemAt: function(aIndex) {
        this._data.splice(aIndex, 1);
        this._treeBoxObject.rowCountChanged(aIndex, -1);
        this.selection.clearSelection();
    },

関連記事

TOP

TOP