Écrit par Neil Deakin.
Traduit par Alain B. (17/07/2005).
Page originale :
http://www.xulplanet.com/tutorials/xulqa/q_treebview.html
Neil Rashbrook a fourni un exemple complet utilisant une vue d'arbre personnalisée sur un site distant, avec des niveaux hiérarchiques.
Voir<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window width="500" height="500"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<tree class="plain focusring" seltype="single" selstyle="primary" flex="1">
<treecols>
<treecol primary="true" flex="1" label="Nombre" id="number"/>
<splitter class="tree-splitter"/>
<treecol flex="1" label="Carré" id="square"/>
<splitter class="tree-splitter"/>
<treecol flex="1" label="Cube" id="cube"/>
</treecols>
<treechildren/>
</tree>
<script><![CDATA[
function nsTreeView() {}
nsTreeView.prototype = {
/* déboggage */
get wrappedJSObject() { return this; },
/* nsISupports */
QueryInterface : function QueryInterface(aIID)
{
if (Components.interfaces.nsIClassInfo.equals(aIID))
return nsTreeView.prototype;
if (Components.interfaces.nsITreeView.equals(aIID) ||
Components.interfaces.nsISupportsWeakReference.equals(aIID) ||
Components.interfaces.nsISupports.equals(aIID))
return this;
throw 0x80004002; // Components.results.NS_NOINTERFACE;
},
/* nsIClassInfo */
getInterfaces: function getInterfaces(count) {
count.value = 4;
return [Components.interfaces.nsITreeView,
Components.interfaces.nsIClassInfo,
Components.interfaces.nsISupportsWeakReference,
Components.interfaces.nsISupports];
},
getHelperForLanguage: function getHelperForLanguage(language) { return null; },
get contractID() { return null; },
get classDescription() { return "nsTreeView"; },
get classID() { return null; },
get implementationLanguage() { return Components.interfaces.nsIProgrammimgLanguage.JAVASCRIPT; },
get flags() { return Components.interfaces.nsIClassInfo.DOM_OBJECT; },
/* nsITreeView */
get rowCount() { return this._subtreeItems.length; },
selection: null,
getRowProperties: function getRowProperties(index, prop) { },
getCellProperties: function getCellProperties(index, column, prop) { },
getColumnProperties: function getColumnProperties(column, elem, prop) { },
isContainer: function isContainer(index) {
if (index in this._subtreeItems)
return this._subtreeItems[index]._childItems.length;
throw 0x8000FFFF; // Components.results.NS_ERROR_UNEXPECTED;
},
isContainerOpen: function isContainerOpen(index) { return this._subtreeItems[index]._open; },
isContainerEmpty: function isContainerEmpty(index) { return false; },
isSeparator: function isSeparator(index) { return false; },
isSorted: function isSorted() { return false; },
// d&d n'est pas encore implémenté !
canDropOn: function canDropOn(index) { return false; },
canDropBeforeAfter: function canDropBeforeAfter(index, before) { return false; },
drop: function drop(index, orientation) { },
getParentIndex: function getParentIndex(index) {
return this.getIndexOfItem(this._subtreeItems[index]._parentItem);
},
hasNextSibling: function hasNextSibling(index, after) { return this._subtreeItems[index]._hasNext; },
getLevel: function getLevel(index) {
if (index in this._subtreeItems) {
var level = 0;
for (var item = this._subtreeItems[index]; item._parentItem != this; ++level)
item = item._parentItem;
return level;
}
throw 0x8000FFFF; // Components.results.NS_ERROR_UNEXPECTED;
},
getImageSrc: function getImageSrc(index, column) { },
getProgressMode : function getProgressMode(index,column) { },
getCellValue: function getCellValue(index, column) { },
getCellText: function getCellText(index, column) {
if (index in this._subtreeItems)
return this._subtreeItems[index][column];
throw 0x8000FFFF; // Components.results.NS_ERROR_UNEXPECTED;
},
setTree: function setTree(treeBox) { this._treeBox = treeBox; if (!treeBox) this.selection = null; },
cycleHeader: function cycleHeader(col, elem) { },
selectionChanged: function selectionChanged() { },
cycleCell: function cycleCell(index, column) { },
isEditable: function isEditable(index, column) { return false; },
performAction: function performAction(action) { },
performActionOnCell: function performActionOnCell(action, index, column) { },
toggleOpenState: function toggleOpenState(index) { this._subtreeItems[index].toggleState(); },
/* Méthodes utiles */
getChildCount: function getChildCount() { return this._childItems.length; },
getIndexOfItem: function getIndexOfItem(item) {
if (!item)
throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
var index = -1;
while (item != this) {
var parent = item._parentItem;
if (!parent)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
for (var i = 0; (tmp = parent._childItems[i]) != item; ++i)
if (tmp._open)
index += tmp._subtreeItems.length;
index += i + 1;
item = parent;
}
return index;
},
getIndexOfChild: function getIndexOfChild(item) {
if (!item)
throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
if (item._parentItem != this)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
for (var i = 0; i < this._childItems.length; ++i)
if (this._childItems.length[i] == item)
return i;
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
},
getItemAtIndex: function getItemAtIndex(index) {
index = parseInt(index) || 0;
if (index < 0 || index >= this._subtreeItems.length)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
return this._subtreeItems[index];
},
getChildAtIndex: function getChildAtIndex(index) {
index = parseInt(index) || 0;
if (index < 0 || index >= this._childItems.length)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
return this._childItems[index];
},
selectItem: function selectItem(item) {
for (var parent = item.parentItem(); parent != this; parent = parent.parentItem())
if (!parent)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
else if (!parent.isOpen())
parent.toggleState();
var index = this.getIndexOfItem(item);
this.selection.select(index);
this._treeBox.ensureRowIsVisible(index);
},
invalidateRow: function invalidate() {
var offset = -1;
var parent;
for (var item = this; parent = item._parentItem; item = parent) {
offset += item._getOffset();
if (parent._treeBox)
parent._treeBox.invalidateRow(offset);
if (!parent._open)
break;
}
},
invalidatePrimaryCell: function invalidatePrimaryCell() {
var offset = -1;
var parent;
for (var item = this; parent = item._parentItem; item = parent) {
offset += item._getOffset();
if (parent._treeBox)
parent._treeBox.invalidatePrimaryCell(offset);
if (!parent._open)
break;
}
},
invalidateCell: function invalidateCell(column) {
var offset = -1;
var parent;
for (var item = this; parent = item._parentItem; item = parent) {
offset += item._getOffset();
if (parent._treeBox)
parent._treeBox.invalidateCell(offset);
if (!parent._open)
break;
}
},
toggleState: function toggleState() {
this._open = !this._open;
if (this._subtreeItems.length && this._parentItem)
if (this._open)
this._parentItem._itemExpanded(this._getOffset(), this._subtreeItems);
else
this._parentItem._itemCollapsed(this._getOffset(), this._subtreeItems.length);
},
removeItem: function removeItem(item) {
if (!item)
throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
if (item._parentItem != this)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
var change = 1;
if (item._open)
change += item._subtreeItems.length;
var offset = 0;
var tmp;
for (var i = 0; (tmp = this._childItems[i]) != item; ++i)
if (tmp._open)
offset += tmp._subtreeItems.length;
offset += i;
this._childItems.splice(i, 1);
if (i)
this._childItems[i - 1]._hasNext = item._hasNext;
item._hasNext = false;
this._subtreeItems.splice(offset, change);
if (this._treeBox)
this._treeBox.rowCountChanged(offset, -change);
if (this._parentItem)
this._parentItem._itemCollapsed(offset + this._getOffset(),
this._open ? change : 0, this._childItems.length);
item._parentItem = null;
},
appendItem: function appendItem(item) {
this.insertItem(item, this._childItems.length);
},
insertItem: function insertItem(item, index) {
if (!item)
throw 0x80004003; // Components.results.NS_ERROR_NULL_POINTER;
var length = this._childItems.length;
index = parseInt(index) || 0;
if (index < 0 || index > length)
throw 0x80004005; // Components.results.NS_ERROR_FAILURE;
if (item._parentItem)
item._parentItem.removeItem(item);
item._parentItem = this;
var newItems = [item];
var offset = index;
if (!length)
this._childItems = newItems;
else {
this._childItems.splice(index, 0, item);
if (index == length) {
this._childItems[length - 1]._hasNext = true;
offset = this._subtreeItems.length;
} else {
item._hasNext = true;
for (var i = 0; i < index; ++i)
if (this._childItems[i]._open)
offset += this._childItems[i]._subtreeItems.length;
}
}
if (item._open)
newItems = newItems.concat(item._subtreeItems);
this._subtreeItems = this._subtreeItems.splice(0, offset).concat(newItems).
concat(this._subtreeItems);
if (this._treeBox)
this._treeBox.rowCountChanged(offset, newItems.length);
if (this._parentItem && (this._open || !length))
this._parentItem._itemExpanded(offset + this._getOffset(), this._open ? newItems : [], length);
},
parentItem: function parentItem() {
return this._parentItem;
},
isOpen: function isOpen() {
return this._open;
},
/* Méthodes pour aider */
_itemExpanded: function _itemExpanded(offset, newItems, notwisty) {
this._subtreeItems = this._subtreeItems.splice(0, offset).concat(newItems).
concat(this._subtreeItems);
if (this._treeBox) {
this._treeBox.rowCountChanged(offset, newItems.length);
if (offset && !notwisty)
this._treeBox.invalidatePrimaryCell(offset - 1);
}
if (this._open && this._parentItem)
this._parentItem._itemExpanded(offset + this._getOffset(), newItems);
},
_itemCollapsed: function _itemCollapsed(offset, change, notwisty) {
this._subtreeItems.splice(offset, change);
if (this._treeBox) {
this._treeBox.rowCountChanged(offset, -change);
if (offset && !notwisty)
this._treeBox.invalidatePrimaryCell(offset - 1);
}
if (this._open && this._parentItem)
this._parentItem._itemCollapsed(offset + this._getOffset(), change);
},
_getOffset: function _getOffset() {
var offset = 1;
var tmp;
for (var i = 0; (tmp = this._parentItem._childItems[i]) != this; ++i)
if (tmp._open)
offset += tmp._subtreeItems.length;
return offset + i;
},
/* Valeurs par défaut */
_parentItem: null,
_hasNext: false,
_childItems: [],
_subtreeItems: [],
_open: false,
_treeBox: null
};
function Item(parent, value) {
this.number = value;
this.square = value * value;
this.cube = value * value * value;
parent.appendItem(this);
}
Item.prototype = new nsTreeView();
var fib = [2, 1];
while (fib[0] < 2500)
fib.unshift(fib[0] + fib[1]);
var levels = [new nsTreeView()];
var i = 0;
var interval = setInterval(nextIndex, 1);
function nextIndex() {
var j = ++i, k = 0;
for (var l = 0; j; l++)
if (fib[l] <= j) {
k++;
j -= fib[l];
}
levels[k] = new Item(levels[k - 1], i);
if (i < 4180)
window.status = i;
else {
window.status = "";
clearInterval(interval);
}
}
window.onload = function onload() {
document.documentElement.firstChild.view = levels[0];
dump(document.documentElement.firstChild.view + "\n");
}
]]></script>
</window>
Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™
sont des marques de la fondation Mozilla.