home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0"?>
-
- <!DOCTYPE bindings [
- <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
- %globalDTD;
- <!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-base" extends="chrome://global/content/bindings/general.xml#basecontrol">
- <resources>
- <stylesheet src="chrome://global/skin/tree.css"/>
- </resources>
- <implementation>
- <method name="_isAccelPressed">
- <parameter name="aEvent"/>
- <body><![CDATA[
- return aEvent.ctrlKey;
- ]]></body>
- </method>
- </implementation>
- </binding>
-
- <binding id="tree" extends="chrome://global/content/bindings/tree.xml#tree-base">
- <content hidevscroll="true" hidehscroll="true" chromedir="&locale.dir;">
- <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"/>
- <xul:scrollcorner xbl:inherits="collapsed=hidevscroll"/>
- </xul:hbox>
- </content>
-
- <implementation implements="nsIDOMXULTreeElement, nsIDOMXULMultiSelectControlElement, nsIAccessibleProvider">
-
- <!-- ///////////////// nsIDOMXULTreeElement ///////////////// -->
-
- <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;"/>
-
- <!-- ///////////////// nsIAccessibleProvider ///////////////// -->
-
- <property name="accessibleType" readonly="true">
- <getter>
- <![CDATA[
- return Components.interfaces.nsIAccessibleProvider.XULTree;
- ]]>
- </getter>
- </property>
-
- <property name="treeBoxObject"
- onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);"
- readonly="true"/>
- <property name="contentView"
- onget="return this.view; /*.QueryInterface(Components.interfaces.nsITreeContentView)*/"
- readonly="true"/>
- <property name="builderView"
- onget="return this.view; /*.QueryInterface(Components.interfaces.nsIXULTreeBuilder)*/"
- readonly="true"/>
- <field name="pageUpOrDownMovesSelection">
- true
- </field>
- <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>
-
- <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[
- if (aPos) aPos.value = "before";
-
- var col = this.columns.getFirstColumn();
- var lastCol = null;
- var currentX = this.boxObject.x;
- while (col) {
- var cw = col.element.boxObject.width;
- if (cw > 0) {
- currentX += cw;
- if (currentX - (cw * aThresh) > aX)
- return col.element;
- }
- lastCol = col;
- col = col.getNext();
- }
-
- if (aPos) aPos.value = "after";
- return lastCol.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>
-
- <property name="_cellSelType">
- <getter>
- <![CDATA[
- var seltype = this.selType;
- if (seltype == "cell" || seltype == "text")
- return seltype;
- return null;
- ]]>
- </getter>
- </property>
-
- <method name="_getNextColumn">
- <parameter name="row"/>
- <parameter name="left"/>
- <body><![CDATA[
- var col = this.view.selection.currentColumn;
- if (col) {
- col = left ? col.getPrevious() : col.getNext();
- }
- else {
- col = this.columns.getKeyColumn();
- }
- while (col && (col.width == 0 || !col.selectable ||
- !this.view.isSelectable(row, col)))
- col = left ? col.getPrevious() : col.getNext();
- return col;
- ]]></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 (row < 0 || row >= this.view.rowCount || !column)
- return;
- if (column.type != Components.interfaces.nsITreeColumn.TYPE_TEXT ||
- column.cycler || !this.view.isEditable(row, column))
- return;
-
- if (this._editingColumn)
- this.stopEditing();
-
- var input = this.inputField;
-
- var box = this.treeBoxObject;
- box.ensureCellIsVisible(row, column);
-
- var outx = {}, outy = {}, outwidth = {}, outheight = {};
- var coords = box.getCoordsForCellItem(row, column, "text",
- outx, outy, outwidth, outheight);
-
- var style = window.getComputedStyle(input, "");
- var topadj = parseInt(style.borderTopWidth) + parseInt(style.paddingTop);
- input.top = outy.value - topadj;
-
- var left = outx.value;
- input.left = left;
- input.height = outheight.value + topadj +
- parseInt(style.borderBottomWidth) +
- parseInt(style.paddingBottom);
-
- coords = box.getCoordsForCellItem(row, column, "cell",
- outx, outy, outwidth, outheight);
- input.width = outwidth.value - (left - outx.value);
- input.hidden = false;
-
- input.value = this.view.getCellText(row, column);
- var selectText = function selectText() {
- input.select();
- input.inputField.focus();
- }
- setTimeout(selectText, 0);
-
- this._editingRow = row;
- this._editingColumn = column;
-
- this.setAttribute("editing", "true");
- ]]>
- </body>
- </method>
-
- <method name="stopEditing">
- <parameter name="accept"/>
- <body>
- <![CDATA[
- if (!this._editingColumn)
- return;
-
- var input = this.inputField;
- if (accept) {
- var value = input.value;
- this.view.setCellText(this._editingRow, this._editingColumn, value);
- }
- this._editingRow = -1;
- this._editingColumn = null;
-
- input.hidden = true;
- input.value = "";
- this.removeAttribute("editing");
- ]]>
- </body>
- </method>
-
- <method name="_moveByOffset">
- <parameter name="offset"/>
- <parameter name="edge"/>
- <parameter name="event"/>
- <body>
- <![CDATA[
- if (this._editingColumn || this.view.rowCount == 0)
- return;
-
- if (this._isAccelPressed(event) && 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;
- }
-
- var cellSelType = this._cellSelType;
- if (cellSelType) {
- var column = this.view.selection.currentColumn;
- if (!column)
- return;
-
- while ((offset > 0 ? c <= edge : c >= edge) && !this.view.isSelectable(c, column))
- c += offset;
- if (offset > 0 ? c > edge : c < edge)
- return;
- }
-
- if (!this._isAccelPressed(event))
- 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[
- if (this._editingColumn || 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,
- this._isAccelPressed(event));
- this.treeBoxObject.ensureRowIsVisible(c + offset);
-
- ]]>
- </body>
- </method>
-
- <method name="_moveByPage">
- <parameter name="offset"/>
- <parameter name="edge"/>
- <parameter name="event"/>
- <body>
- <![CDATA[
- if (this._editingColumn || this.view.rowCount == 0)
- return;
-
- if (this.pageUpOrDownMovesSelection == this._isAccelPressed(event)) {
- 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[
- if (this._editingColumn || this.view.rowCount == 0)
- return;
-
- if (this.view.rowCount == 1 && !this.view.selection.isSelected(0) &&
- !(this.pageUpOrDownMovesSelection == this._isAccelPressed(event))) {
- 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, this._isAccelPressed(event));
-
- } 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, this._isAccelPressed(event));
- }
-
- ]]>
- </body>
- </method>
-
- <method name="_moveToEdge">
- <parameter name="edge"/>
- <parameter name="event"/>
- <body>
- <![CDATA[
- if (this._editingColumn || 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 (!this._isAccelPressed(event))
- 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[
- if (this._editingColumn || 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, this._isAccelPressed(event));
-
- this.treeBoxObject.ensureRowIsVisible(edge);
- ]]>
- </body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="DOMMouseScroll" phase="capturing">
- <![CDATA[
- if (this._editingColumn)
- return;
-
- var rows = event.detail;
- if (rows == NSUIEvent.SCROLL_PAGE_UP)
- this.treeBoxObject.scrollByPages(-1);
- else if (rows == NSUIEvent.SCROLL_PAGE_DOWN)
- this.treeBoxObject.scrollByPages(1);
- else
- this.treeBoxObject.scrollByLines(rows);
- ]]>
- </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();
- }
- if (this._cellSelType && !this.view.selection.currentColumn) {
- var col = this._getNextColumn(this.currentIndex, false);
- this.view.selection.currentColumn = col;
- }
- ]]>
- </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="keypress" keycode="VK_ENTER">
- <![CDATA[
- if (this._editingColumn) {
- this.stopEditing(true);
- this.focus();
- event.stopPropagation();
- }
- else {
- this.changeOpenState(this.currentIndex);
- }
- ]]>
- </handler>
- <handler event="keypress" keycode="VK_RETURN">
- <![CDATA[
- if (this._editingColumn) {
- this.stopEditing(true);
- this.focus();
- event.stopPropagation();
- }
- else {
- this.changeOpenState(this.currentIndex);
- }
- ]]>
- </handler>
- <handler event="keypress" keycode="VK_ESCAPE">
- <![CDATA[
- if (this._editingColumn) {
- this.stopEditing(false);
- this.focus();
- event.stopPropagation();
- }
- ]]>
- </handler>
- <handler event="keypress" keycode="VK_LEFT">
- <![CDATA[
- if (this._editingColumn)
- return;
-
- var row = this.currentIndex;
- if (row < 0)
- return;
-
- var cellSelType = this._cellSelType;
- var checkContainers = true;
-
- var currentColumn;
- if (cellSelType) {
- currentColumn = this.view.selection.currentColumn;
- if (currentColumn && !currentColumn.primary)
- checkContainers = false;
- }
-
- if (checkContainers) {
- if (this.changeOpenState(this.currentIndex, false))
- return;
- else {
- var parentIndex = this.view.getParentIndex(this.currentIndex);
- if (parentIndex >= 0) {
- if (cellSelType && !this.view.isSelectable(parentIndex, currentColumn)) {
- return;
- }
- this.view.selection.select(parentIndex);
- this.treeBoxObject.ensureRowIsVisible(parentIndex);
- return;
- }
- }
- }
-
- if (cellSelType) {
- var col = this._getNextColumn(row, true);
- if (col) {
- this.view.selection.currentColumn = col;
- this.treeBoxObject.ensureCellIsVisible(row, col);
- }
- }
- ]]>
- </handler>
- <handler event="keypress" keycode="VK_RIGHT">
- <![CDATA[
- if (this._editingColumn)
- return;
-
- var row = this.currentIndex;
- if (row < 0)
- return;
-
- var cellSelType = this._cellSelType;
- var checkContainers = true;
-
- var currentColumn;
- if (cellSelType) {
- currentColumn = this.view.selection.currentColumn;
- if (currentColumn && !currentColumn.primary)
- checkContainers = false;
- }
-
- if (checkContainers) {
- if (this.changeOpenState(row, true))
- return;
- else {
- 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.
- if (cellSelType && !this.view.isSelectable(c , currentColumn)) {
- var col = this._getNextColumn(c, false);
- if (col) {
- this.view.selection.currentColumn = col;
- }
- }
- this.view.selection.timedSelect(c, this._selectDelay);
- this.treeBoxObject.ensureRowIsVisible(c);
- return;
- }
- }
- }
-
- if (cellSelType) {
- var col = this._getNextColumn(row, false);
- if (col) {
- this.view.selection.currentColumn = col;
- this.treeBoxObject.ensureCellIsVisible(row, col);
- }
- }
- ]]>
- </handler>
- <handler event="keypress" keycode="VK_UP"
- modifiers="accel any" action="_moveByOffset(-1, 0, event);"/>
- <handler event="keypress" keycode="VK_DOWN"
- modifiers="accel any" action="_moveByOffset(1, this.view.rowCount - 1, event);"/>
- <handler event="keypress" keycode="VK_UP"
- modifiers="accel any, shift" action="_moveByOffsetShift(-1, 0, event);"/>
- <handler event="keypress" keycode="VK_DOWN"
- modifiers="accel any, shift" action="_moveByOffsetShift(1, this.view.rowCount - 1, event);"/>
- <handler event="keypress" keycode="VK_PAGE_UP"
- modifiers="accel any" action="_moveByPage(-1, 0, event);"/>
- <handler event="keypress" keycode="VK_PAGE_DOWN"
- modifiers="accel any" action="_moveByPage(1, this.view.rowCount - 1, event);"/>
- <handler event="keypress" keycode="VK_PAGE_UP"
- modifiers="accel any, shift" action="_moveByPageShift(-1, 0, event);"/>
- <handler event="keypress" keycode="VK_PAGE_DOWN"
- modifiers="accel any, shift" action="_moveByPageShift(1, this.view.rowCount - 1, event);"/>
- <handler event="keypress" keycode="VK_HOME"
- modifiers="accel any" action="_moveToEdge(0, event);"/>
- <handler event="keypress" keycode="VK_END"
- modifiers="accel any" action="_moveToEdge(this.view.rowCount - 1, event);"/>
- <handler event="keypress" keycode="VK_HOME"
- modifiers="accel any, shift" action="_moveToEdgeShift(0, event);"/>
- <handler event="keypress" keycode="VK_END"
- modifiers="accel any, shift" action="_moveToEdgeShift(this.view.rowCount - 1, event);"/>
- <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 && this._isAccelPressed(event))) {
- this.view.selection.toggleSelect(c);
- }
- }
- else if (!this.disableKeyNavigation && event.charCode > 0 &&
- !event.altKey && !this._isAccelPressed(event) &&
- !event.metaKey && !event.ctrlKey) {
- var l = this._keyNavigate(event);
- if (l >= 0) {
- this.view.selection.timedSelect(l, this._selectDelay);
- this.treeBoxObject.ensureRowIsVisible(l);
- }
- }
- ]]>
- </handler>
- </handlers>
- </binding>
-
- <binding id="treecols">
- <resources>
- <stylesheet src="chrome://global/skin/tree.css"/>
- </resources>
- <content orient="horizontal">
- <xul:hbox class="tree-scrollable-columns" flex="1">
- <children includes="treecol|splitter"/>
- </xul:hbox>
- <xul:treecolpicker class="treecol-image" fixed="true" xbl:inherits="tooltiptext=pickertooltiptext"/>
- </content>
- <implementation implements="nsIAccessibleProvider">
- <property name="accessibleType" readonly="true">
- <getter>
- <![CDATA[
- return Components.interfaces.nsIAccessibleProvider.XULTreeColumns;
- ]]>
- </getter>
- </property>
- </implementation>
- </binding>
-
- <binding id="treerows" extends="chrome://global/content/bindings/tree.xml#tree-base">
- <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"/>
- </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="treebody" extends="chrome://global/content/bindings/tree.xml#tree-base">
- <implementation>
- <constructor>
- if ("_ensureColumnOrder" in this.parentNode)
- this.parentNode._ensureColumnOrder();
- </constructor>
-
- <field name="_lastSelectedRow">
- -1
- </field>
- </implementation>
- <handlers>
- <!-- If there is no modifier key, we select on mousedown, not
- click, so that drags work correctly. -->
- <handler event="mousedown" clickcount="1">
- <![CDATA[
- if (this.parentNode.disabled)
- return;
- if (((!this._isAccelPressed(event) ||
- !this.parentNode.pageUpOrDownMovesSelection) &&
- !event.shiftKey && !event.metaKey) ||
- this.parentNode.view.selection.single) {
- var row = {};
- var col = {};
- var obj = {};
- var b = this.parentNode.treeBoxObject;
- b.getCellAt(event.clientX, event.clientY, row, col, obj);
-
- // save off the last selected row
- this._lastSelectedRow = row.value;
-
- if (row.value == -1)
- return;
-
- if (obj.value == "twisty")
- return;
-
- if (col.value) {
- if (col.value.cycler) {
- b.view.cycleCell(row.value, col.value);
- return;
- } else if (col.value.type == Components.interfaces.nsITreeColumn.TYPE_CHECKBOX) {
- if (this.parentNode.editable && col.value.editable &&
- b.view.isEditable(row.value, col.value)) {
- var value = b.view.getCellValue(row.value, col.value);
- value = value == "true" ? "false" : "true";
- b.view.setCellValue(row.value, col.value, value);
- return;
- }
- }
- }
-
- var cellSelType = this.parentNode._cellSelType;
- if (cellSelType == "text" && obj.value != "text" && obj.value != "image")
- return;
-
- if (cellSelType) {
- if (!col.value.selectable ||
- !b.view.isSelectable(row.value, col.value)) {
- return;
- }
- }
-
- if (!b.view.selection.isSelected(row.value)) {
- b.view.selection.select(row.value);
- b.ensureRowIsVisible(row.value);
- }
-
- if (cellSelType) {
- b.view.selection.currentColumn = col.value;
- }
- }
- ]]>
- </handler>
-
- <!-- On a click (up+down on the same item), deselect everything
- except this item. -->
- <handler event="click" button="0" clickcount="1">
- <![CDATA[
- if (this.parentNode.disabled)
- return;
- var row = {};
- var col = {};
- var obj = {};
- var b = this.parentNode.treeBoxObject;
- b.getCellAt(event.clientX, event.clientY, row, col, obj);
-
- if (row.value == -1)
- return;
-
- if (obj.value == "twisty") {
- if (b.view.selection.currentIndex >= 0 &&
- b.view.isContainerOpen(row.value)) {
- var parentIndex = b.view.getParentIndex(b.view.selection.currentIndex);
- while (parentIndex >= 0 && parentIndex != row.value)
- parentIndex = b.view.getParentIndex(parentIndex);
- if (parentIndex == row.value) {
- var parentSelectable = true;
- if (this.parentNode._cellSelType) {
- var currentColumn = b.view.selection.currentColumn;
- if (!b.view.isSelectable(parentIndex, currentColumn))
- parentSelectable = false;
- }
- if (parentSelectable)
- b.view.selection.select(parentIndex);
- }
- }
- this.parentNode.changeOpenState(row.value);
- return;
- }
-
- if (! b.view.selection.single) {
- var augment = this._isAccelPressed(event);
- if (event.shiftKey) {
- b.view.selection.rangedSelect(-1, row.value, augment);
- b.ensureRowIsVisible(row.value);
- return;
- }
- if (augment) {
- b.view.selection.toggleSelect(row.value);
- b.ensureRowIsVisible(row.value);
- b.view.selection.currentIndex = row.value;
- return;
- }
- }
-
- /* We want to deselect all the selected items except what was
- clicked, UNLESS it was a right-click. We have to do this
- in click rather than mousedown so that you can drag a
- selected group of items */
-
- if (!col.value) return;
-
- // if the last row has changed in between the time we
- // mousedown and the time we click, don't fire the select handler.
- // see bug #92366
- if (!col.value.cycler && this._lastSelectedRow == row.value &&
- col.value.type != Components.interfaces.nsITreeColumn.TYPE_CHECKBOX) {
-
- var cellSelType = this.parentNode._cellSelType;
- if (cellSelType == "text" && obj.value != "text" && obj.value != "image")
- return;
-
- if (cellSelType) {
- if (!col.value.selectable ||
- !b.view.isSelectable(row.value, col.value)) {
- return;
- }
- }
-
- b.view.selection.select(row.value);
- b.ensureRowIsVisible(row.value);
-
- if (cellSelType) {
- b.view.selection.currentColumn = col.value;
- }
- }
- ]]>
- </handler>
-
- <!-- double-click -->
- <handler event="click" clickcount="2">
- <![CDATA[
- if (this.parentNode.disabled)
- return;
- var b = this.parentNode.treeBoxObject;
- var row = b.view.selection.currentIndex;
- if (row == -1)
- return;
-
- var col = {};
- var obj = {};
- b.getCellAt(event.clientX, event.clientY, {}, col, obj);
-
- if (this.parentNode.editable)
- this.parentNode.startEditing(row, col.value);
-
- if (!b.view.isContainer(row))
- return;
-
-
- // Cyclers and twisties respond to single clicks, not double clicks
- if (col.value && !col.value.cycler && obj.value != "twisty")
- this.parentNode.changeOpenState(row);
- ]]>
- </handler>
-
- </handlers>
- </binding>
-
- <binding id="treecol-base" extends="chrome://global/content/bindings/tree.xml#tree-base">
- <implementation implements="nsIAccessibleProvider">
- <constructor>
- this.parentNode.parentNode._columnsDirty = true;
- </constructor>
-
- <property name="accessibleType" readonly="true">
- <getter>
- <![CDATA[
- return Components.interfaces.nsIAccessibleProvider.XULTreeColumnItem;
- ]]>
- </getter>
- </property>
-
- <property name="ordinal">
- <getter><![CDATA[
- var val = this.getAttribute("ordinal");
- return "" + (val == "" ? 1 : (val == "0" ? 0 : parseInt(val)));
- ]]></getter>
- <setter><![CDATA[
- this.setAttribute("ordinal", val);
- return val;
- ]]></setter>
- </property>
-
- <property name="_previousVisibleColumn">
- <getter><![CDATA[
- var sib = this.boxObject.previousSibling;
- while (sib) {
- if (sib.localName == "treecol" && sib.boxObject.width > 0 && sib.parentNode == this.parentNode)
- return sib;
- sib = sib.boxObject.previousSibling;
- }
- return null;
- ]]></getter>
- </property>
-
- <method name="_onDragMouseMove">
- <parameter name="aEvent"/>
- <body><![CDATA[
- var col = document.treecolDragging;
- if (!col) return;
-
- // determine if we have moved the mouse far enough
- // to initiate a drag
- if (col.mDragGesturing) {
- if (Math.abs(aEvent.clientX - col.mStartDragX) < 5 &&
- Math.abs(aEvent.clientY - col.mStartDragY) < 5) {
- return;
- } else {
- col.mDragGesturing = false;
- col.setAttribute("dragging", "true");
- window.addEventListener("click", col._onDragMouseClick, true);
- }
- }
-
- var pos = {};
- var targetCol = col.parentNode.parentNode._getColumnAtX(aEvent.clientX, 0.5, pos);
-
- // bail if we haven't mousemoved to a different column
- if (col.mTargetCol == targetCol && col.mTargetDir == pos.value)
- return;
-
- var tree = col.parentNode.parentNode;
- var sib;
- var column;
- if (col.mTargetCol) {
- // remove previous insertbefore/after attributes
- col.mTargetCol.removeAttribute("insertbefore");
- col.mTargetCol.removeAttribute("insertafter");
- column = tree.columns.getColumnFor(col.mTargetCol);
- tree.treeBoxObject.invalidateColumn(column);
- sib = col.mTargetCol._previousVisibleColumn;
- if (sib) {
- sib.removeAttribute("insertafter");
- column = tree.columns.getColumnFor(sib);
- tree.treeBoxObject.invalidateColumn(column);
- }
- col.mTargetCol = null;
- col.mTargetDir = null;
- }
-
- if (targetCol) {
- // set insertbefore/after attributes
- if (pos.value == "after") {
- targetCol.setAttribute("insertafter", "true");
- } else {
- targetCol.setAttribute("insertbefore", "true");
- sib = targetCol._previousVisibleColumn;
- if (sib) {
- sib.setAttribute("insertafter", "true");
- column = tree.columns.getColumnFor(sib);
- tree.treeBoxObject.invalidateColumn(column);
- }
- }
- column = tree.columns.getColumnFor(targetCol);
- tree.treeBoxObject.invalidateColumn(column);
- col.mTargetCol = targetCol;
- col.mTargetDir = pos.value;
- }
- ]]></body>
- </method>
-
- <method name="_onDragMouseUp">
- <parameter name="aEvent"/>
- <body><![CDATA[
- var col = document.treecolDragging;
- if (!col) return;
-
- if (!col.mDragGesturing) {
- if (col.mTargetCol) {
- // remove insertbefore/after attributes
- var before = col.mTargetCol.hasAttribute("insertbefore");
- col.mTargetCol.removeAttribute(before ? "insertbefore" : "insertafter");
-
- var sib = col.mTargetCol._previousVisibleColumn;
- if (before && sib) {
- sib.removeAttribute("insertafter");
- }
-
- // Move the column only if it will result in a different column
- // ordering
- var move = true;
-
- // If this is a before move and the previous visible column is
- // the same as the column we're moving, don't move
- if (before && col == sib) {
- move = false;
- }
- else if (!before && col == col.mTargetCol) {
- // If this is an after move and the column we're moving is
- // the same as the target column, don't move.
- move = false;
- }
-
- if (move) {
- col.parentNode.parentNode._reorderColumn(col, col.mTargetCol, before);
- }
-
- // repaint to remove lines
- col.parentNode.parentNode.treeBoxObject.invalidate();
-
- col.mTargetCol = null;
- }
- } else
- col.mDragGesturing = false;
-
- document.treecolDragging = null;
- col.removeAttribute("dragging");
-
- window.removeEventListener("mousemove", col._onDragMouseMove, true);
- window.removeEventListener("mouseup", col._onDragMouseUp, true);
- // we have to wait for the click event to fire before removing
- // cancelling handler
- var clickHandler = function(handler) {
- window.removeEventListener("click", handler, true);
- };
- window.setTimeout(clickHandler, 0, col._onDragMouseClick);
- ]]></body>
- </method>
-
- <method name="_onDragMouseClick">
- <parameter name="aEvent"/>
- <body><![CDATA[
- // prevent click event from firing after column drag and drop
- aEvent.stopPropagation();
- aEvent.preventDefault();
- ]]></body>
- </method>
- </implementation>
-
- <handlers>
- <handler event="mousedown" button="0"><![CDATA[
- if (this.parentNode.parentNode.enableColumnDrag) {
- var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
- var cols = this.parentNode.getElementsByTagNameNS(xulns, "treecol");
-
- // only start column drag operation if there are at least 2 visible columns
- var visible = 0;
- for (var i = 0; i < cols.length; ++i)
- if (cols[i].boxObject.width > 0) ++visible;
-
- if (visible > 1) {
- window.addEventListener("mousemove", this._onDragMouseMove, true);
- window.addEventListener("mouseup", this._onDragMouseUp, true);
- document.treecolDragging = this;
- this.mDragGesturing = true;
- this.mStartDragX = event.clientX;
- this.mStartDragY = event.clientY;
- }
- }
- ]]></handler>
- <handler event="click" button="0" phase="target">
- <![CDATA[
- if (event.target != event.originalTarget)
- return;
-
- var tree = this.parentNode.parentNode;
- var column = tree.columns.getColumnFor(this);
- tree.view.cycleHeader(column);
- ]]>
- </handler>
- </handlers>
- </binding>
-
- <binding id="treecol" extends="chrome://global/content/bindings/tree.xml#treecol-base">
- <content>
- <xul:label class="treecol-text" xbl:inherits="crop,value=label" flex="1" crop="right"/>
- <xul:image class="treecol-sortdirection" xbl:inherits="sortDirection,hidden=hideheader"/>
- </content>
- </binding>
-
- <binding id="treecol-image" extends="chrome://global/content/bindings/tree.xml#treecol-base">
- <content>
- <xul:image class="treecol-icon" xbl:inherits="src"/>
- </content>
- </binding>
-
- <binding id="columnpicker" display="xul:button"
- extends="chrome://global/content/bindings/tree.xml#tree-base">
- <content>
- <xul:image class="tree-columnpicker-icon"/>
- <xul:menupopup anonid="popup">
- <xul:menuseparator anonid="menuseparator"/>
- <xul:menuitem anonid="menuitem" label="&restoreNaturalOrder.label;"/>
- </xul:menupopup>
- </content>
-
- <implementation implements="nsIAccessibleProvider">
- <property name="accessibleType" readonly="true">
- <getter>
- return Components.interfaces.nsIAccessibleProvider.XULButton;
- </getter>
- </property>
-
- <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.removeChild(aPopup.firstChild);
-
- 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.showPopup(this, -1, -1, "popup", "bottomright", "topright");
- }
- else {
- var tree = this.parentNode.parentNode;
- tree.stopEditing(true);
- var menuitem = document.getAnonymousElementByAttribute(this, "anonid", "menuitem");
- if (event.originalTarget == menuitem) {
- tree.columns.restoreNaturalOrder();
- 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>
-
-