gecko-dev/toolkit/content/widgets/tree.xml

1011 строки
35 KiB
XML

<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE bindings [
<!ENTITY % treeDTD SYSTEM "chrome://global/locale/tree.dtd">
%treeDTD;
]>
<bindings id="treeBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="tree" extends="chrome://global/content/bindings/general.xml#basecontrol">
<content hidevscroll="true" hidehscroll="true" clickthrough="never">
<children includes="treecols"/>
<xul:stack class="tree-stack" flex="1">
<xul:treerows class="tree-rows" flex="1" xbl:inherits="hidevscroll">
<children/>
</xul:treerows>
<xul:textbox anonid="input" class="tree-input" left="0" top="0" hidden="true"/>
</xul:stack>
<xul:hbox xbl:inherits="collapsed=hidehscroll">
<xul:scrollbar orient="horizontal" flex="1" increment="16" style="position:relative; z-index:2147483647;"
oncontextmenu="event.stopPropagation(); event.preventDefault();"
onclick="event.stopPropagation(); event.preventDefault();"
ondblclick="event.stopPropagation();"
oncommand="event.stopPropagation();"/>
<xul:scrollcorner xbl:inherits="collapsed=hidevscroll"
oncontextmenu="event.stopPropagation(); event.preventDefault();"
onclick="event.stopPropagation(); event.preventDefault();"
ondblclick="event.stopPropagation();"
oncommand="event.stopPropagation();"/>
</xul:hbox>
</content>
<implementation implements="nsIDOMXULMultiSelectControlElement">
<property name="columns"
onget="return this.treeBoxObject.columns;"/>
<property name="view"
onget="return this.treeBoxObject.view"
onset="return this.treeBoxObject.view = val;"/>
<property name="body"
onget="return this.treeBoxObject.treeBody;"/>
<property name="editable"
onget="return this.getAttribute('editable') == 'true';"
onset="if (val) this.setAttribute('editable', 'true');
else this.removeAttribute('editable'); return val;"/>
<!-- ///////////////// nsIDOMXULSelectControlElement ///////////////// -->
<!-- ///////////////// nsIDOMXULMultiSelectControlElement ///////////////// -->
<property name="selType"
onget="return this.getAttribute('seltype')"
onset="this.setAttribute('seltype', val); return val;"/>
<property name="currentIndex"
onget="return this.view ? this.view.selection.currentIndex: - 1;"
onset="if (this.view) return this.view.selection.currentIndex = val; return val;"/>
<property name="treeBoxObject"
onget="return this.boxObject;"
readonly="true"/>
<field name="pageUpOrDownMovesSelection">
!/Mac/.test(navigator.platform)
</field>
<property name="keepCurrentInView"
onget="return (this.getAttribute('keepcurrentinview') == 'true');"
onset="if (val) this.setAttribute('keepcurrentinview', 'true');
else this.removeAttribute('keepcurrentinview'); return val;"/>
<property name="enableColumnDrag"
onget="return this.hasAttribute('enableColumnDrag');"
onset="if (val) this.setAttribute('enableColumnDrag', 'true');
else this.removeAttribute('enableColumnDrag'); return val;"/>
<field name="_inputField">null</field>
<property name="inputField" readonly="true">
<getter><![CDATA[
if (!this._inputField)
this._inputField = document.getAnonymousElementByAttribute(this, "anonid", "input");
return this._inputField;
]]></getter>
</property>
<property name="disableKeyNavigation"
onget="return this.hasAttribute('disableKeyNavigation');"
onset="if (val) this.setAttribute('disableKeyNavigation', 'true');
else this.removeAttribute('disableKeyNavigation'); return val;"/>
<field name="_editingRow">-1</field>
<field name="_editingColumn">null</field>
<property name="editingRow" readonly="true"
onget="return this._editingRow;"/>
<property name="editingColumn" readonly="true"
onget="return this._editingColumn;"/>
<property name="_selectDelay"
onset="this.setAttribute('_selectDelay', val);"
onget="return this.getAttribute('_selectDelay') || 50;"/>
<field name="_columnsDirty">true</field>
<field name="_lastKeyTime">0</field>
<field name="_incrementalString">""</field>
<field name="_touchY">-1</field>
<method name="_ensureColumnOrder">
<body><![CDATA[
if (!this._columnsDirty)
return;
if (this.columns) {
// update the ordinal position of each column to assure that it is
// an odd number and 2 positions above its next sibling
var cols = [];
var i;
for (var col = this.columns.getFirstColumn(); col; col = col.getNext())
cols.push(col.element);
for (i = 0; i < cols.length; ++i)
cols[i].setAttribute("ordinal", (i * 2) + 1);
// update the ordinal positions of splitters to even numbers, so that
// they are in between columns
var splitters = this.getElementsByTagName("splitter");
for (i = 0; i < splitters.length; ++i)
splitters[i].setAttribute("ordinal", (i + 1) * 2);
}
this._columnsDirty = false;
]]></body>
</method>
<method name="_reorderColumn">
<parameter name="aColMove"/>
<parameter name="aColBefore"/>
<parameter name="aBefore"/>
<body><![CDATA[
this._ensureColumnOrder();
var i;
var cols = [];
var col = this.columns.getColumnFor(aColBefore);
if (parseInt(aColBefore.ordinal) < parseInt(aColMove.ordinal)) {
if (aBefore)
cols.push(aColBefore);
for (col = col.getNext(); col.element != aColMove;
col = col.getNext())
cols.push(col.element);
aColMove.ordinal = cols[0].ordinal;
for (i = 0; i < cols.length; ++i)
cols[i].ordinal = parseInt(cols[i].ordinal) + 2;
} else if (aColBefore.ordinal != aColMove.ordinal) {
if (!aBefore)
cols.push(aColBefore);
for (col = col.getPrevious(); col.element != aColMove;
col = col.getPrevious())
cols.push(col.element);
aColMove.ordinal = cols[0].ordinal;
for (i = 0; i < cols.length; ++i)
cols[i].ordinal = parseInt(cols[i].ordinal) - 2;
}
]]></body>
</method>
<method name="_getColumnAtX">
<parameter name="aX"/>
<parameter name="aThresh"/>
<parameter name="aPos"/>
<body><![CDATA[
var isRTL = document.defaultView.getComputedStyle(this)
.direction == "rtl";
if (aPos)
aPos.value = isRTL ? "after" : "before";
var columns = [];
var col = this.columns.getFirstColumn();
while (col) {
columns.push(col);
col = col.getNext();
}
if (isRTL)
columns.reverse();
var currentX = this.boxObject.x;
var adjustedX = aX + this.treeBoxObject.horizontalPosition;
for (var i = 0; i < columns.length; ++i) {
col = columns[i];
var cw = col.element.boxObject.width;
if (cw > 0) {
currentX += cw;
if (currentX - (cw * aThresh) > adjustedX)
return col.element;
}
}
if (aPos)
aPos.value = isRTL ? "before" : "after";
return columns.pop().element;
]]></body>
</method>
<method name="changeOpenState">
<parameter name="row"/>
<!-- Optional parameter openState == true or false to set.
No openState param == toggle -->
<parameter name="openState"/>
<body><![CDATA[
if (row < 0 || !this.view.isContainer(row)) {
return false;
}
if (this.view.isContainerOpen(row) != openState) {
this.view.toggleOpenState(row);
if (row == this.currentIndex) {
// Only fire event when current row is expanded or collapsed
// because that's all the assistive technology really cares about.
var event = document.createEvent("Events");
event.initEvent("OpenStateChange", true, true);
this.dispatchEvent(event);
}
return true;
}
return false;
]]></body>
</method>
<method name="_keyNavigate">
<parameter name="event"/>
<body><![CDATA[
var key = String.fromCharCode(event.charCode).toLowerCase();
if (event.timeStamp - this._lastKeyTime > 1000)
this._incrementalString = key;
else
this._incrementalString += key;
this._lastKeyTime = event.timeStamp;
var length = this._incrementalString.length;
var incrementalString = this._incrementalString;
var charIndex = 1;
while (charIndex < length && incrementalString[charIndex] == incrementalString[charIndex - 1])
charIndex++;
// If all letters in incremental string are same, just try to match the first one
if (charIndex == length) {
length = 1;
incrementalString = incrementalString.substring(0, length);
}
var keyCol = this.columns.getKeyColumn();
var rowCount = this.view.rowCount;
var start = 1;
var c = this.currentIndex;
if (length > 1) {
start = 0;
if (c < 0)
c = 0;
}
for (var i = 0; i < rowCount; i++) {
var l = (i + start + c) % rowCount;
var cellText = this.view.getCellText(l, keyCol);
cellText = cellText.substring(0, length).toLowerCase();
if (cellText == incrementalString)
return l;
}
return -1;
]]></body>
</method>
<method name="startEditing">
<parameter name="row"/>
<parameter name="column"/>
<body>
<![CDATA[
if (!this.editable)
return false;
if (row < 0 || row >= this.view.rowCount || !column)
return false;
if (column.type != window.TreeColumn.TYPE_TEXT &&
column.type != window.TreeColumn.TYPE_PASSWORD)
return false;
if (column.cycler || !this.view.isEditable(row, column))
return false;
// Beyond this point, we are going to edit the cell.
if (this._editingColumn)
this.stopEditing();
var input = this.inputField;
var box = this.treeBoxObject;
box.ensureCellIsVisible(row, column);
// Get the coordinates of the text inside the cell.
var textRect = box.getCoordsForCellItem(row, column, "text");
// Get the coordinates of the cell itself.
var cellRect = box.getCoordsForCellItem(row, column, "cell");
// Calculate the top offset of the textbox.
var style = window.getComputedStyle(input);
var topadj = parseInt(style.borderTopWidth) + parseInt(style.paddingTop);
input.top = textRect.y - topadj;
// The leftside of the textbox is aligned to the left side of the text
// in LTR mode, and left side of the cell in RTL mode.
var left, widthdiff;
if (style.direction == "rtl") {
left = cellRect.x;
widthdiff = cellRect.x - textRect.x;
} else {
left = textRect.x;
widthdiff = textRect.x - cellRect.x;
}
input.left = left;
input.height = textRect.height + topadj +
parseInt(style.borderBottomWidth) +
parseInt(style.paddingBottom);
input.width = cellRect.width - widthdiff;
input.hidden = false;
input.value = this.view.getCellText(row, column);
input.select();
input.inputField.focus();
this._editingRow = row;
this._editingColumn = column;
this.setAttribute("editing", "true");
box.invalidateCell(row, column);
return true;
]]>
</body>
</method>
<method name="stopEditing">
<parameter name="accept"/>
<body>
<![CDATA[
if (!this._editingColumn)
return;
var input = this.inputField;
var editingRow = this._editingRow;
var editingColumn = this._editingColumn;
this._editingRow = -1;
this._editingColumn = null;
if (accept) {
var value = input.value;
this.view.setCellText(editingRow, editingColumn, value);
}
input.hidden = true;
input.value = "";
this.removeAttribute("editing");
]]>
</body>
</method>
<method name="_moveByOffset">
<parameter name="offset"/>
<parameter name="edge"/>
<parameter name="event"/>
<body>
<![CDATA[
event.preventDefault();
if (this.view.rowCount == 0)
return;
if (event.getModifierState("Accel") && this.view.selection.single) {
this.treeBoxObject.scrollByLines(offset);
return;
}
var c = this.currentIndex + offset;
if (offset > 0 ? c > edge : c < edge) {
if (this.view.selection.isSelected(edge) && this.view.selection.count <= 1)
return;
c = edge;
}
if (!event.getModifierState("Accel"))
this.view.selection.timedSelect(c, this._selectDelay);
else // Ctrl+Up/Down moves the anchor without selecting
this.currentIndex = c;
this.treeBoxObject.ensureRowIsVisible(c);
]]>
</body>
</method>
<method name="_moveByOffsetShift">
<parameter name="offset"/>
<parameter name="edge"/>
<parameter name="event"/>
<body>
<![CDATA[
event.preventDefault();
if (this.view.rowCount == 0)
return;
if (this.view.selection.single) {
this.treeBoxObject.scrollByLines(offset);
return;
}
if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) {
this.view.selection.timedSelect(0, this._selectDelay);
return;
}
var c = this.currentIndex;
if (c == -1)
c = 0;
if (c == edge) {
if (this.view.selection.isSelected(c))
return;
}
// Extend the selection from the existing pivot, if any
this.view.selection.rangedSelect(-1, c + offset,
event.getModifierState("Accel"));
this.treeBoxObject.ensureRowIsVisible(c + offset);
]]>
</body>
</method>
<method name="_moveByPage">
<parameter name="offset"/>
<parameter name="edge"/>
<parameter name="event"/>
<body>
<![CDATA[
event.preventDefault();
if (this.view.rowCount == 0)
return;
if (this.pageUpOrDownMovesSelection == event.getModifierState("Accel")) {
this.treeBoxObject.scrollByPages(offset);
return;
}
if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) {
this.view.selection.timedSelect(0, this._selectDelay);
return;
}
var c = this.currentIndex;
if (c == -1)
return;
if (c == edge && this.view.selection.isSelected(c)) {
this.treeBoxObject.ensureRowIsVisible(c);
return;
}
var i = this.treeBoxObject.getFirstVisibleRow();
var p = this.treeBoxObject.getPageLength();
if (offset > 0) {
i += p - 1;
if (c >= i) {
i = c + p;
this.treeBoxObject.ensureRowIsVisible(i > edge ? edge : i);
}
i = i > edge ? edge : i;
} else if (c <= i) {
i = c <= p ? 0 : c - p;
this.treeBoxObject.ensureRowIsVisible(i);
}
this.view.selection.timedSelect(i, this._selectDelay);
]]>
</body>
</method>
<method name="_moveByPageShift">
<parameter name="offset"/>
<parameter name="edge"/>
<parameter name="event"/>
<body>
<![CDATA[
event.preventDefault();
if (this.view.rowCount == 0)
return;
if (this.view.rowCount == 1 && !this.view.selection.isSelected(0) &&
!(this.pageUpOrDownMovesSelection == event.getModifierState("Accel"))) {
this.view.selection.timedSelect(0, this._selectDelay);
return;
}
if (this.view.selection.single)
return;
var c = this.currentIndex;
if (c == -1)
return;
if (c == edge && this.view.selection.isSelected(c)) {
this.treeBoxObject.ensureRowIsVisible(edge);
return;
}
var i = this.treeBoxObject.getFirstVisibleRow();
var p = this.treeBoxObject.getPageLength();
if (offset > 0) {
i += p - 1;
if (c >= i) {
i = c + p;
this.treeBoxObject.ensureRowIsVisible(i > edge ? edge : i);
}
// Extend the selection from the existing pivot, if any
this.view.selection.rangedSelect(-1, i > edge ? edge : i, event.getModifierState("Accel"));
} else {
if (c <= i) {
i = c <= p ? 0 : c - p;
this.treeBoxObject.ensureRowIsVisible(i);
}
// Extend the selection from the existing pivot, if any
this.view.selection.rangedSelect(-1, i, event.getModifierState("Accel"));
}
]]>
</body>
</method>
<method name="_moveToEdge">
<parameter name="edge"/>
<parameter name="event"/>
<body>
<![CDATA[
event.preventDefault();
if (this.view.rowCount == 0)
return;
if (this.view.selection.isSelected(edge) && this.view.selection.count == 1) {
this.currentIndex = edge;
return;
}
// Normal behaviour is to select the first/last row
if (!event.getModifierState("Accel"))
this.view.selection.timedSelect(edge, this._selectDelay);
// In a multiselect tree Ctrl+Home/End moves the anchor
else if (!this.view.selection.single)
this.currentIndex = edge;
this.treeBoxObject.ensureRowIsVisible(edge);
]]>
</body>
</method>
<method name="_moveToEdgeShift">
<parameter name="edge"/>
<parameter name="event"/>
<body>
<![CDATA[
event.preventDefault();
if (this.view.rowCount == 0)
return;
if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) {
this.view.selection.timedSelect(0, this._selectDelay);
return;
}
if (this.view.selection.single ||
(this.view.selection.isSelected(edge)) && this.view.selection.isSelected(this.currentIndex))
return;
// Extend the selection from the existing pivot, if any.
// -1 doesn't work here, so using currentIndex instead
this.view.selection.rangedSelect(this.currentIndex, edge, event.getModifierState("Accel"));
this.treeBoxObject.ensureRowIsVisible(edge);
]]>
</body>
</method>
<method name="_handleEnter">
<parameter name="event"/>
<body><![CDATA[
if (this._editingColumn) {
this.stopEditing(true);
this.focus();
return true;
}
return this.changeOpenState(this.currentIndex);
]]></body>
</method>
</implementation>
<handlers>
<handler event="touchstart">
<![CDATA[
function isScrollbarElement(target) {
return (target.localName == "thumb" || target.localName == "slider")
&& target.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
}
if (event.touches.length > 1 || isScrollbarElement(event.touches[0].target)) {
// Multiple touch points detected, abort. In particular this aborts
// the panning gesture when the user puts a second finger down after
// already panning with one finger. Aborting at this point prevents
// the pan gesture from being resumed until all fingers are lifted
// (as opposed to when the user is back down to one finger).
// Additionally, if the user lands on the scrollbar don't use this
// code for scrolling, instead allow gecko to handle scrollbar
// interaction normally.
this._touchY = -1;
} else {
this._touchY = event.touches[0].screenY;
}
]]>
</handler>
<handler event="touchmove">
<![CDATA[
if (event.touches.length == 1 &&
this._touchY >= 0) {
var deltaY = this._touchY - event.touches[0].screenY;
var lines = Math.trunc(deltaY / this.treeBoxObject.rowHeight);
if (Math.abs(lines) > 0) {
this.treeBoxObject.scrollByLines(lines);
deltaY -= lines * this.treeBoxObject.rowHeight;
this._touchY = event.touches[0].screenY + deltaY;
}
event.preventDefault();
}
]]>
</handler>
<handler event="touchend">
<![CDATA[
this._touchY = -1;
]]>
</handler>
<handler event="MozMousePixelScroll">
<![CDATA[
if (!(this.getAttribute("allowunderflowscroll") == "true" &&
this.getAttribute("hidevscroll") == "true"))
event.preventDefault();
]]>
</handler>
<handler event="DOMMouseScroll">
<![CDATA[
if (!(this.getAttribute("allowunderflowscroll") == "true" &&
this.getAttribute("hidevscroll") == "true"))
event.preventDefault();
if (this._editingColumn)
return;
if (event.axis == event.HORIZONTAL_AXIS)
return;
var rows = event.detail;
if (rows == UIEvent.SCROLL_PAGE_UP)
this.treeBoxObject.scrollByPages(-1);
else if (rows == UIEvent.SCROLL_PAGE_DOWN)
this.treeBoxObject.scrollByPages(1);
else
this.treeBoxObject.scrollByLines(rows);
]]>
</handler>
<handler event="MozSwipeGesture" preventdefault="true">
<![CDATA[
// Figure out which row to show
let targetRow = 0;
// Only handle swipe gestures up and down
switch (event.direction) {
case event.DIRECTION_DOWN:
targetRow = this.view.rowCount - 1;
// Fall through for actual action
case event.DIRECTION_UP:
this.treeBoxObject.ensureRowIsVisible(targetRow);
break;
}
]]>
</handler>
<handler event="select" phase="target"
action="if (event.originalTarget == this) this.stopEditing(true);"/>
<handler event="focus">
<![CDATA[
this.treeBoxObject.focused = true;
if (this.currentIndex == -1 && this.view.rowCount > 0) {
this.currentIndex = this.treeBoxObject.getFirstVisibleRow();
}
]]>
</handler>
<handler event="blur" action="this.treeBoxObject.focused = false;"/>
<handler event="blur" phase="capturing"
action="if (event.originalTarget == this.inputField.inputField) this.stopEditing(true);"/>
<handler event="keydown" keycode="VK_RETURN">
if (this._handleEnter(event)) {
event.stopPropagation();
event.preventDefault();
}
</handler>
<handler event="keydown" keycode="VK_ESCAPE">
<![CDATA[
if (this._editingColumn) {
this.stopEditing(false);
this.focus();
event.stopPropagation();
event.preventDefault();
}
]]>
</handler>
<handler event="keydown" keycode="VK_LEFT">
<![CDATA[
if (this._editingColumn)
return;
var row = this.currentIndex;
if (row < 0)
return;
if (this.changeOpenState(this.currentIndex, false)) {
event.preventDefault();
return;
}
var parentIndex = this.view.getParentIndex(this.currentIndex);
if (parentIndex >= 0) {
this.view.selection.select(parentIndex);
this.treeBoxObject.ensureRowIsVisible(parentIndex);
event.preventDefault();
}
]]>
</handler>
<handler event="keydown" keycode="VK_RIGHT">
<![CDATA[
if (this._editingColumn)
return;
var row = this.currentIndex;
if (row < 0)
return;
if (this.changeOpenState(row, true)) {
event.preventDefault();
return;
}
var c = row + 1;
var view = this.view;
if (c < view.rowCount &&
view.getParentIndex(c) == row) {
// If already opened, select the first child.
// The getParentIndex test above ensures that the children
// are already populated and ready.
this.view.selection.timedSelect(c, this._selectDelay);
this.treeBoxObject.ensureRowIsVisible(c);
event.preventDefault();
}
]]>
</handler>
<handler event="keydown" keycode="VK_UP" modifiers="accel any">
<![CDATA[
if (this._editingColumn)
return;
this._moveByOffset(-1, 0, event);
]]>
</handler>
<handler event="keydown" keycode="VK_DOWN" modifiers="accel any">
<![CDATA[
if (this._editingColumn)
return;
this._moveByOffset(1, this.view.rowCount - 1, event);
]]>
</handler>
<handler event="keydown" keycode="VK_UP" modifiers="accel any, shift">
<![CDATA[
if (this._editingColumn)
return;
this._moveByOffsetShift(-1, 0, event);
]]>
</handler>
<handler event="keydown" keycode="VK_DOWN" modifiers="accel any, shift">
<![CDATA[
if (this._editingColumn)
return;
this._moveByOffsetShift(1, this.view.rowCount - 1, event);
]]>
</handler>
<handler event="keydown" keycode="VK_PAGE_UP" modifiers="accel any">
<![CDATA[
if (this._editingColumn)
return;
this._moveByPage(-1, 0, event);
]]>
</handler>
<handler event="keydown" keycode="VK_PAGE_DOWN" modifiers="accel any">
<![CDATA[
if (this._editingColumn)
return;
this._moveByPage(1, this.view.rowCount - 1, event);
]]>
</handler>
<handler event="keydown" keycode="VK_PAGE_UP" modifiers="accel any, shift">
<![CDATA[
if (this._editingColumn)
return;
this._moveByPageShift(-1, 0, event);
]]>
</handler>
<handler event="keydown" keycode="VK_PAGE_DOWN" modifiers="accel any, shift">
<![CDATA[
if (this._editingColumn)
return;
this._moveByPageShift(1, this.view.rowCount - 1, event);
]]>
</handler>
<handler event="keydown" keycode="VK_HOME" modifiers="accel any">
<![CDATA[
if (this._editingColumn)
return;
this._moveToEdge(0, event);
]]>
</handler>
<handler event="keydown" keycode="VK_END" modifiers="accel any">
<![CDATA[
if (this._editingColumn)
return;
this._moveToEdge(this.view.rowCount - 1, event);
]]>
</handler>
<handler event="keydown" keycode="VK_HOME" modifiers="accel any, shift">
<![CDATA[
if (this._editingColumn)
return;
this._moveToEdgeShift(0, event);
]]>
</handler>
<handler event="keydown" keycode="VK_END" modifiers="accel any, shift">
<![CDATA[
if (this._editingColumn)
return;
this._moveToEdgeShift(this.view.rowCount - 1, event);
]]>
</handler>
<handler event="keypress">
<![CDATA[
if (this._editingColumn)
return;
if (event.charCode == " ".charCodeAt(0)) {
var c = this.currentIndex;
if (!this.view.selection.isSelected(c) ||
(!this.view.selection.single && event.getModifierState("Accel"))) {
this.view.selection.toggleSelect(c);
event.preventDefault();
}
} else if (!this.disableKeyNavigation && event.charCode > 0 &&
!event.altKey && !event.getModifierState("Accel") &&
!event.metaKey && !event.ctrlKey) {
var l = this._keyNavigate(event);
if (l >= 0) {
this.view.selection.timedSelect(l, this._selectDelay);
this.treeBoxObject.ensureRowIsVisible(l);
}
event.preventDefault();
}
]]>
</handler>
</handlers>
</binding>
<binding id="treerows" extends="chrome://global/content/bindings/general.xml#basecontrol">
<content>
<xul:hbox flex="1" class="tree-bodybox">
<children/>
</xul:hbox>
<xul:scrollbar height="0" minwidth="0" minheight="0" orient="vertical" xbl:inherits="collapsed=hidevscroll" style="position:relative; z-index:2147483647;"
oncontextmenu="event.stopPropagation(); event.preventDefault();"
onclick="event.stopPropagation(); event.preventDefault();"
ondblclick="event.stopPropagation();"
oncommand="event.stopPropagation();"/>
</content>
<handlers>
<handler event="underflow">
<![CDATA[
// Scrollport event orientation
// 0: vertical
// 1: horizontal
// 2: both (not used)
var tree = document.getBindingParent(this);
if (event.detail == 1)
tree.setAttribute("hidehscroll", "true");
else if (event.detail == 0)
tree.setAttribute("hidevscroll", "true");
event.stopPropagation();
]]>
</handler>
<handler event="overflow">
<![CDATA[
var tree = document.getBindingParent(this);
if (event.detail == 1)
tree.removeAttribute("hidehscroll");
else if (event.detail == 0)
tree.removeAttribute("hidevscroll");
event.stopPropagation();
]]>
</handler>
</handlers>
</binding>
<binding id="columnpicker" display="xul:button"
extends="chrome://global/content/bindings/general.xml#basecontrol">
<content>
<xul:image class="tree-columnpicker-icon"/>
<xul:menupopup anonid="popup">
<xul:menuseparator anonid="menuseparator"/>
<xul:menuitem anonid="menuitem" label="&restoreColumnOrder.label;"/>
</xul:menupopup>
</content>
<implementation>
<method name="buildPopup">
<parameter name="aPopup"/>
<body>
<![CDATA[
// We no longer cache the picker content, remove the old content.
while (aPopup.childNodes.length > 2)
aPopup.firstChild.remove();
var refChild = aPopup.firstChild;
var tree = this.parentNode.parentNode;
for (var currCol = tree.columns.getFirstColumn(); currCol;
currCol = currCol.getNext()) {
// Construct an entry for each column in the row, unless
// it is not being shown.
var currElement = currCol.element;
if (!currElement.hasAttribute("ignoreincolumnpicker")) {
var popupChild = document.createElement("menuitem");
popupChild.setAttribute("type", "checkbox");
var columnName = currElement.getAttribute("display") ||
currElement.getAttribute("label");
popupChild.setAttribute("label", columnName);
popupChild.setAttribute("colindex", currCol.index);
if (currElement.getAttribute("hidden") != "true")
popupChild.setAttribute("checked", "true");
if (currCol.primary)
popupChild.setAttribute("disabled", "true");
aPopup.insertBefore(popupChild, refChild);
}
}
var hidden = !tree.enableColumnDrag;
const anonids = ["menuseparator", "menuitem"];
for (var i = 0; i < anonids.length; i++) {
var element = document.getAnonymousElementByAttribute(this, "anonid", anonids[i]);
element.hidden = hidden;
}
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="command">
<![CDATA[
if (event.originalTarget == this) {
var popup = document.getAnonymousElementByAttribute(this, "anonid", "popup");
this.buildPopup(popup);
popup.openPopup(this, "after_end");
} else {
var tree = this.parentNode.parentNode;
tree.stopEditing(true);
var menuitem = document.getAnonymousElementByAttribute(this, "anonid", "menuitem");
if (event.originalTarget == menuitem) {
tree.columns.restoreNaturalOrder();
this.removeAttribute("ordinal");
tree._ensureColumnOrder();
} else {
var colindex = event.originalTarget.getAttribute("colindex");
var column = tree.columns[colindex];
if (column) {
var element = column.element;
if (element.getAttribute("hidden") == "true")
element.setAttribute("hidden", "false");
else
element.setAttribute("hidden", "true");
}
}
}
]]>
</handler>
</handlers>
</binding>
</bindings>