home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / xulrunner-1.9.0.14 / chrome / toolkit.jar / content / global / bindings / tree.xml < prev    next >
Encoding:
Extensible Markup Language  |  2008-05-01  |  48.3 KB  |  1,388 lines

  1. <?xml version="1.0"?>
  2.  
  3. <!DOCTYPE bindings [
  4. <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
  5. %globalDTD;
  6. <!ENTITY % treeDTD SYSTEM "chrome://global/locale/tree.dtd">
  7. %treeDTD;
  8. ]>
  9.  
  10. <bindings id="treeBindings"
  11.    xmlns="http://www.mozilla.org/xbl"
  12.    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  13.    xmlns:xbl="http://www.mozilla.org/xbl">
  14.   
  15.   <binding id="tree-base" extends="chrome://global/content/bindings/general.xml#basecontrol">
  16.     <resources>
  17.       <stylesheet src="chrome://global/skin/tree.css"/>
  18.     </resources>
  19.     <implementation>
  20.       <method name="_isAccelPressed">
  21.         <parameter name="aEvent"/>
  22.         <body><![CDATA[
  23.           return aEvent.ctrlKey;
  24.         ]]></body>
  25.       </method>
  26.     </implementation>
  27.   </binding>
  28.  
  29.   <binding id="tree" extends="chrome://global/content/bindings/tree.xml#tree-base">
  30.     <content hidevscroll="true" hidehscroll="true" chromedir="&locale.dir;">
  31.       <children includes="treecols"/>
  32.       <xul:stack class="tree-stack" flex="1">
  33.         <xul:treerows class="tree-rows" flex="1" xbl:inherits="hidevscroll">
  34.           <children/>
  35.         </xul:treerows>
  36.         <xul:textbox anonid="input" class="tree-input" left="0" top="0" hidden="true"/>
  37.       </xul:stack>
  38.       <xul:hbox xbl:inherits="collapsed=hidehscroll">
  39.         <xul:scrollbar orient="horizontal" flex="1" increment="16"/>
  40.         <xul:scrollcorner xbl:inherits="collapsed=hidevscroll"/>
  41.       </xul:hbox>
  42.     </content>
  43.     
  44.     <implementation implements="nsIDOMXULTreeElement, nsIDOMXULMultiSelectControlElement, nsIAccessibleProvider">
  45.  
  46.       <!-- ///////////////// nsIDOMXULTreeElement ///////////////// -->
  47.  
  48.       <property name="columns"
  49.                 onget="return this.treeBoxObject.columns;"/>
  50.  
  51.       <property name="view"
  52.                 onget="return this.treeBoxObject.view;"
  53.                 onset="return this.treeBoxObject.view = val;"/>
  54.  
  55.       <property name="body"
  56.                 onget="return this.treeBoxObject.treeBody;"/>
  57.  
  58.       <property name="editable"
  59.                 onget="return this.getAttribute('editable') == 'true';"
  60.                 onset="if (val) this.setAttribute('editable', 'true');
  61.                        else this.removeAttribute('editable'); return val;"/>
  62.  
  63.       <!-- ///////////////// nsIDOMXULSelectControlElement ///////////////// -->
  64.  
  65.       <!-- ///////////////// nsIDOMXULMultiSelectControlElement ///////////////// -->
  66.  
  67.       <property name="selType"
  68.                 onget="return this.getAttribute('seltype')"
  69.                 onset="this.setAttribute('seltype', val); return val;"/>
  70.  
  71.       <property name="currentIndex"
  72.                 onget="return this.view ? this.view.selection.currentIndex: - 1;"
  73.                 onset="if (this.view) return this.view.selection.currentIndex = val; return val;"/>
  74.  
  75.       <!-- ///////////////// nsIAccessibleProvider ///////////////// -->
  76.  
  77.       <property name="accessibleType" readonly="true">
  78.         <getter>
  79.           <![CDATA[
  80.             return Components.interfaces.nsIAccessibleProvider.XULTree;
  81.           ]]>
  82.         </getter>
  83.       </property>
  84.  
  85.       <property name="treeBoxObject"
  86.                 onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);"
  87.                 readonly="true"/>
  88.       <property name="contentView"
  89.                 onget="return this.view; /*.QueryInterface(Components.interfaces.nsITreeContentView)*/"
  90.                 readonly="true"/>
  91.       <property name="builderView"
  92.                 onget="return this.view; /*.QueryInterface(Components.interfaces.nsIXULTreeBuilder)*/"
  93.                 readonly="true"/>
  94.       <field name="pageUpOrDownMovesSelection">
  95.         true
  96.       </field>
  97.       <property name="enableColumnDrag"
  98.                 onget="return this.hasAttribute('enableColumnDrag');"
  99.                 onset="if (val) this.setAttribute('enableColumnDrag', 'true');
  100.                        else this.removeAttribute('enableColumnDrag'); return val;"/>
  101.  
  102.       <field name="_inputField">null</field>
  103.  
  104.       <property name="inputField" readonly="true">
  105.         <getter><![CDATA[
  106.           if (!this._inputField)
  107.             this._inputField = document.getAnonymousElementByAttribute(this, "anonid", "input");
  108.           return this._inputField;
  109.         ]]></getter>
  110.       </property>
  111.  
  112.       <property name="disableKeyNavigation"
  113.                 onget="return this.hasAttribute('disableKeyNavigation');"
  114.                 onset="if (val) this.setAttribute('disableKeyNavigation', 'true');
  115.                        else this.removeAttribute('disableKeyNavigation'); return val;"/>
  116.  
  117.       <field name="_editingRow">-1</field>
  118.       <field name="_editingColumn">null</field>
  119.  
  120.       <property name="editingRow" readonly="true"
  121.                 onget="return this._editingRow;"/>
  122.       <property name="editingColumn" readonly="true"
  123.                 onget="return this._editingColumn;"/>
  124.  
  125.       <property name="_selectDelay" 
  126.                 onset="this.setAttribute('_selectDelay', val);"
  127.                 onget="return this.getAttribute('_selectDelay') || 50;"/>
  128.       <field name="_columnsDirty">true</field>
  129.       <field name="_lastKeyTime">0</field>
  130.       <field name="_incrementalString">""</field>
  131.  
  132.       <method name="_ensureColumnOrder">
  133.         <body><![CDATA[
  134.           if (!this._columnsDirty)
  135.             return;
  136.  
  137.           if (this.columns) {
  138.             // update the ordinal position of each column to assure that it is
  139.             // an odd number and 2 positions above its next sibling
  140.             var cols = [];
  141.             var i;
  142.             for (var col = this.columns.getFirstColumn(); col; col = col.getNext())
  143.               cols.push(col.element);
  144.             for (i = 0; i < cols.length; ++i)
  145.               cols[i].setAttribute("ordinal", (i*2)+1);
  146.  
  147.             // update the ordinal positions of splitters to even numbers, so that 
  148.             // they are in between columns
  149.             var splitters = this.getElementsByTagName("splitter");
  150.             for (i = 0; i < splitters.length; ++i)
  151.               splitters[i].setAttribute("ordinal", (i+1)*2);
  152.           }
  153.           this._columnsDirty = false;
  154.         ]]></body>
  155.       </method>
  156.  
  157.       <method name="_reorderColumn">
  158.         <parameter name="aColMove"/>
  159.         <parameter name="aColBefore"/>
  160.         <parameter name="aBefore"/>
  161.         <body><![CDATA[
  162.           this._ensureColumnOrder();
  163.  
  164.           var i;
  165.           var cols = [];
  166.           var col = this.columns.getColumnFor(aColBefore);
  167.           if (parseInt(aColBefore.ordinal) < parseInt(aColMove.ordinal)) {
  168.             if (aBefore)
  169.               cols.push(aColBefore);
  170.             for (col = col.getNext(); col.element != aColMove;
  171.                  col = col.getNext())
  172.               cols.push(col.element);
  173.  
  174.             aColMove.ordinal = cols[0].ordinal;
  175.             for (i = 0; i < cols.length; ++i)
  176.               cols[i].ordinal = parseInt(cols[i].ordinal) + 2;
  177.           } else if (aColBefore.ordinal != aColMove.ordinal) {
  178.             if (!aBefore)
  179.               cols.push(aColBefore);
  180.             for (col = col.getPrevious(); col.element != aColMove;
  181.                  col = col.getPrevious())
  182.               cols.push(col.element);
  183.  
  184.             aColMove.ordinal = cols[0].ordinal;
  185.             for (i = 0; i < cols.length; ++i)
  186.               cols[i].ordinal = parseInt(cols[i].ordinal) - 2;
  187.           }
  188.         ]]></body>
  189.       </method>
  190.       
  191.       <method name="_getColumnAtX">
  192.         <parameter name="aX"/>
  193.         <parameter name="aThresh"/>
  194.         <parameter name="aPos"/>
  195.         <body><![CDATA[
  196.           if (aPos) aPos.value = "before";
  197.  
  198.           var col = this.columns.getFirstColumn();
  199.           var lastCol = null;
  200.           var currentX = this.boxObject.x;
  201.           while (col) {
  202.             var cw = col.element.boxObject.width;
  203.             if (cw > 0) {
  204.               currentX += cw;
  205.               if (currentX - (cw * aThresh) > aX)
  206.                 return col.element;
  207.             }
  208.             lastCol = col;
  209.             col = col.getNext();
  210.           }
  211.  
  212.           if (aPos) aPos.value = "after";
  213.           return lastCol.element;
  214.         ]]></body>
  215.       </method>
  216.  
  217.       <method name="changeOpenState">
  218.         <parameter name="row"/>
  219.         <!-- Optional parameter openState == true or false to set. 
  220.              No openState param == toggle -->
  221.         <parameter name="openState"/>
  222.         <body><![CDATA[
  223.           if (row < 0 || !this.view.isContainer(row)) {
  224.             return false;
  225.           }
  226.           if (this.view.isContainerOpen(row) != openState) {
  227.             this.view.toggleOpenState(row);
  228.             if (row == this.currentIndex) {
  229.               // Only fire event when current row is expanded or collapsed
  230.               // because that's all the assistive technology really cares about.
  231.               var event = document.createEvent('Events');
  232.               event.initEvent('OpenStateChange', true, true);
  233.               this.dispatchEvent(event);
  234.             }
  235.             return true;
  236.           }
  237.           return false;
  238.         ]]></body>
  239.       </method>
  240.  
  241.       <property name="_cellSelType">
  242.         <getter>
  243.           <![CDATA[
  244.             var seltype = this.selType;
  245.             if (seltype == "cell" || seltype == "text")
  246.               return seltype;
  247.             return null;
  248.           ]]>
  249.         </getter>
  250.       </property>
  251.  
  252.       <method name="_getNextColumn">
  253.         <parameter name="row"/>
  254.         <parameter name="left"/>
  255.         <body><![CDATA[
  256.           var col = this.view.selection.currentColumn;
  257.           if (col) {
  258.             col = left ? col.getPrevious() : col.getNext();
  259.           }
  260.           else {
  261.             col = this.columns.getKeyColumn();
  262.           }
  263.           while (col && (col.width == 0 || !col.selectable ||
  264.                  !this.view.isSelectable(row, col)))
  265.             col = left ? col.getPrevious() : col.getNext();
  266.           return col;
  267.         ]]></body>
  268.       </method>
  269.  
  270.       <method name="_keyNavigate">
  271.         <parameter name="event"/>
  272.         <body><![CDATA[
  273.           var key = String.fromCharCode(event.charCode).toLowerCase();
  274.           if (event.timeStamp - this._lastKeyTime > 1000)
  275.             this._incrementalString = key;
  276.           else
  277.             this._incrementalString += key;
  278.           this._lastKeyTime = event.timeStamp;
  279.  
  280.           var length = this._incrementalString.length;
  281.           var incrementalString = this._incrementalString;
  282.           var charIndex = 1;
  283.           while (charIndex < length && incrementalString[charIndex] == incrementalString[charIndex - 1])
  284.             charIndex++;
  285.           // If all letters in incremental string are same, just try to match the first one
  286.           if (charIndex == length) {
  287.             length = 1;
  288.             incrementalString = incrementalString.substring(0, length);
  289.           }
  290.  
  291.           var keyCol = this.columns.getKeyColumn();
  292.           var rowCount = this.view.rowCount;
  293.           var start = 1;
  294.  
  295.           var c = this.currentIndex;
  296.           if (length > 1) {
  297.             start = 0;
  298.             if (c < 0)
  299.               c = 0;
  300.           }
  301.  
  302.           for (var i = 0; i < rowCount; i++) {
  303.             var l = (i + start + c) % rowCount;
  304.             var cellText = this.view.getCellText(l, keyCol);
  305.             cellText = cellText.substring(0, length).toLowerCase();
  306.             if (cellText == incrementalString)
  307.               return l;
  308.           }
  309.           return -1;
  310.         ]]></body>
  311.       </method>
  312.  
  313.       <method name="startEditing">
  314.         <parameter name="row"/>
  315.         <parameter name="column"/>
  316.         <body>
  317.           <![CDATA[
  318.             if (row < 0 || row >= this.view.rowCount || !column)
  319.               return;
  320.             if (column.type != Components.interfaces.nsITreeColumn.TYPE_TEXT ||
  321.                 column.cycler || !this.view.isEditable(row, column))
  322.               return;
  323.  
  324.             if (this._editingColumn)
  325.               this.stopEditing();
  326.  
  327.             var input = this.inputField;
  328.  
  329.             var box = this.treeBoxObject;
  330.             box.ensureCellIsVisible(row, column);
  331.  
  332.             var outx = {}, outy = {}, outwidth = {}, outheight = {};
  333.             var coords = box.getCoordsForCellItem(row, column, "text",
  334.                                                   outx, outy, outwidth, outheight);
  335.  
  336.             var style = window.getComputedStyle(input, "");
  337.             var topadj = parseInt(style.borderTopWidth) + parseInt(style.paddingTop);
  338.             input.top = outy.value - topadj;
  339.  
  340.             var left = outx.value;
  341.             input.left = left;
  342.             input.height = outheight.value + topadj +
  343.                            parseInt(style.borderBottomWidth) +
  344.                            parseInt(style.paddingBottom);
  345.  
  346.             coords = box.getCoordsForCellItem(row, column, "cell",
  347.                                               outx, outy, outwidth, outheight);
  348.             input.width = outwidth.value - (left - outx.value);
  349.             input.hidden = false;
  350.  
  351.             input.value = this.view.getCellText(row, column);
  352.             var selectText = function selectText() {
  353.               input.select();
  354.               input.inputField.focus();
  355.             }
  356.             setTimeout(selectText, 0);
  357.  
  358.             this._editingRow = row;
  359.             this._editingColumn = column;
  360.  
  361.             this.setAttribute("editing", "true");
  362.           ]]>
  363.         </body>
  364.       </method>
  365.  
  366.       <method name="stopEditing">
  367.         <parameter name="accept"/>
  368.         <body>
  369.           <![CDATA[
  370.             if (!this._editingColumn)
  371.               return;
  372.  
  373.             var input = this.inputField;
  374.             if (accept) {
  375.               var value = input.value;
  376.               this.view.setCellText(this._editingRow, this._editingColumn, value);
  377.             }
  378.             this._editingRow = -1;
  379.             this._editingColumn = null;
  380.  
  381.             input.hidden = true;
  382.             input.value = "";
  383.             this.removeAttribute("editing");
  384.           ]]>
  385.         </body>
  386.       </method>
  387.  
  388.       <method name="_moveByOffset">
  389.         <parameter name="offset"/>
  390.         <parameter name="edge"/>
  391.         <parameter name="event"/>
  392.         <body>
  393.           <![CDATA[
  394.             if (this._editingColumn || this.view.rowCount == 0)
  395.               return;
  396.  
  397.             if (this._isAccelPressed(event) && this.view.selection.single) {
  398.               this.treeBoxObject.scrollByLines(offset);
  399.               return;
  400.             }
  401.    
  402.             var c = this.currentIndex + offset;
  403.             if (offset > 0 ? c > edge : c < edge) {
  404.               if (this.view.selection.isSelected(edge) && this.view.selection.count <= 1)
  405.                 return;
  406.               c = edge;
  407.             }
  408.    
  409.             var cellSelType = this._cellSelType;
  410.             if (cellSelType) {
  411.               var column = this.view.selection.currentColumn;
  412.               if (!column)
  413.                 return;
  414.    
  415.               while ((offset > 0 ? c <= edge : c >= edge) && !this.view.isSelectable(c, column))
  416.                 c += offset;
  417.               if (offset > 0 ? c > edge : c < edge)
  418.                 return;
  419.             }
  420.    
  421.             if (!this._isAccelPressed(event))
  422.               this.view.selection.timedSelect(c, this._selectDelay);
  423.             else // Ctrl+Up/Down moves the anchor without selecting
  424.               this.currentIndex = c;
  425.             this.treeBoxObject.ensureRowIsVisible(c);
  426.           ]]>
  427.         </body>
  428.       </method>
  429.  
  430.       <method name="_moveByOffsetShift">
  431.         <parameter name="offset"/>
  432.         <parameter name="edge"/>
  433.         <parameter name="event"/>
  434.         <body>
  435.           <![CDATA[
  436.             if (this._editingColumn || this.view.rowCount == 0)
  437.               return;
  438.  
  439.             if (this.view.selection.single) {
  440.               this.treeBoxObject.scrollByLines(offset);
  441.               return;
  442.             }
  443.  
  444.             if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) {
  445.               this.view.selection.timedSelect(0, this._selectDelay);
  446.               return;
  447.             }
  448.       
  449.             var c = this.currentIndex;
  450.             if (c == -1)
  451.                 c = 0;
  452.  
  453.             if (c == edge) {
  454.               if (this.view.selection.isSelected(c))
  455.                 return;
  456.             }
  457.       
  458.             // Extend the selection from the existing pivot, if any
  459.             this.view.selection.rangedSelect(-1, c + offset,
  460.                                              this._isAccelPressed(event));
  461.             this.treeBoxObject.ensureRowIsVisible(c + offset);
  462.  
  463.           ]]>
  464.         </body>
  465.       </method>
  466.  
  467.       <method name="_moveByPage">
  468.         <parameter name="offset"/>
  469.         <parameter name="edge"/>
  470.         <parameter name="event"/>
  471.         <body>
  472.           <![CDATA[
  473.             if (this._editingColumn || this.view.rowCount == 0)
  474.               return;
  475.  
  476.             if (this.pageUpOrDownMovesSelection == this._isAccelPressed(event)) {
  477.                this.treeBoxObject.scrollByPages(offset);
  478.                return;
  479.             }
  480.  
  481.             if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) {
  482.               this.view.selection.timedSelect(0, this._selectDelay);
  483.               return;
  484.             }
  485.  
  486.             var c = this.currentIndex;
  487.             if (c == -1)
  488.               return;
  489.  
  490.             if (c == edge && this.view.selection.isSelected(c)) {
  491.               this.treeBoxObject.ensureRowIsVisible(c);
  492.               return;
  493.             }
  494.             var i = this.treeBoxObject.getFirstVisibleRow();
  495.             var p = this.treeBoxObject.getPageLength();
  496.  
  497.             if (offset > 0) {
  498.               i += p - 1;
  499.               if (c >= i) {
  500.                  i = c + p;
  501.                  this.treeBoxObject.ensureRowIsVisible(i > edge ? edge : i);
  502.               }
  503.               i = i > edge ? edge : i;
  504.  
  505.             } else {
  506.               if (c <= i) {
  507.                  i = c <= p ? 0 : c - p;
  508.                  this.treeBoxObject.ensureRowIsVisible(i);
  509.               }
  510.             }
  511.             this.view.selection.timedSelect(i, this._selectDelay);
  512.           ]]>
  513.         </body>
  514.       </method>
  515.  
  516.       <method name="_moveByPageShift">
  517.         <parameter name="offset"/>
  518.         <parameter name="edge"/>
  519.         <parameter name="event"/>
  520.         <body>
  521.           <![CDATA[
  522.             if (this._editingColumn || this.view.rowCount == 0)
  523.               return;
  524.  
  525.             if (this.view.rowCount == 1 && !this.view.selection.isSelected(0) &&
  526.                 !(this.pageUpOrDownMovesSelection == this._isAccelPressed(event))) {
  527.               this.view.selection.timedSelect(0, this._selectDelay);
  528.               return;
  529.             }
  530.  
  531.             if (this.view.selection.single)
  532.               return;
  533.  
  534.             var c = this.currentIndex;
  535.             if (c == -1)
  536.               return;
  537.             if (c == edge && this.view.selection.isSelected(c)) {
  538.               this.treeBoxObject.ensureRowIsVisible(edge);
  539.               return;
  540.             }
  541.             var i = this.treeBoxObject.getFirstVisibleRow();
  542.             var p = this.treeBoxObject.getPageLength();
  543.  
  544.             if (offset > 0) {
  545.               i += p - 1;
  546.               if (c >= i) {
  547.                  i = c + p;
  548.                  this.treeBoxObject.ensureRowIsVisible(i > edge ? edge : i);
  549.               }
  550.               // Extend the selection from the existing pivot, if any
  551.               this.view.selection.rangedSelect(-1, i > edge ? edge : i, this._isAccelPressed(event));
  552.  
  553.             } else {
  554.  
  555.               if (c <= i) {
  556.                  i = c <= p ? 0 : c - p;
  557.                  this.treeBoxObject.ensureRowIsVisible(i);
  558.               }
  559.               // Extend the selection from the existing pivot, if any
  560.               this.view.selection.rangedSelect(-1, i, this._isAccelPressed(event));
  561.             }
  562.  
  563.           ]]>
  564.         </body>
  565.       </method>
  566.  
  567.       <method name="_moveToEdge">
  568.         <parameter name="edge"/>
  569.         <parameter name="event"/>
  570.         <body>
  571.           <![CDATA[
  572.             if (this._editingColumn || this.view.rowCount == 0)
  573.               return;
  574.  
  575.             if (this.view.selection.isSelected(edge) && this.view.selection.count == 1) {
  576.               this.currentIndex = edge;
  577.               return;
  578.             }
  579.  
  580.             // Normal behaviour is to select the first/last row
  581.             if (!this._isAccelPressed(event))
  582.               this.view.selection.timedSelect(edge, this._selectDelay);
  583.  
  584.             // In a multiselect tree Ctrl+Home/End moves the anchor
  585.             else if (!this.view.selection.single)
  586.               this.currentIndex = edge;
  587.  
  588.             this.treeBoxObject.ensureRowIsVisible(edge);
  589.           ]]>
  590.         </body>
  591.       </method>
  592.  
  593.       <method name="_moveToEdgeShift">
  594.         <parameter name="edge"/>
  595.         <parameter name="event"/>
  596.         <body>
  597.           <![CDATA[
  598.             if (this._editingColumn || this.view.rowCount == 0)
  599.               return;
  600.  
  601.             if (this.view.rowCount == 1 && !this.view.selection.isSelected(0)) {
  602.               this.view.selection.timedSelect(0, this._selectDelay);
  603.               return;
  604.             }
  605.  
  606.             if (this.view.selection.single ||
  607.                 (this.view.selection.isSelected(edge)) && this.view.selection.isSelected(this.currentIndex))
  608.               return;
  609.  
  610.             // Extend the selection from the existing pivot, if any.
  611.             // -1 doesn't work here, so using currentIndex instead
  612.             this.view.selection.rangedSelect(this.currentIndex, edge, this._isAccelPressed(event));
  613.  
  614.             this.treeBoxObject.ensureRowIsVisible(edge);
  615.           ]]>
  616.         </body>
  617.       </method>
  618.     </implementation>
  619.     
  620.     <handlers>
  621.       <handler event="DOMMouseScroll" phase="capturing">
  622.         <![CDATA[
  623.           if (this._editingColumn)
  624.             return;
  625.  
  626.           var rows = event.detail;
  627.           if (rows == NSUIEvent.SCROLL_PAGE_UP)
  628.             this.treeBoxObject.scrollByPages(-1);
  629.           else if (rows == NSUIEvent.SCROLL_PAGE_DOWN)
  630.             this.treeBoxObject.scrollByPages(1);
  631.           else
  632.             this.treeBoxObject.scrollByLines(rows);
  633.         ]]>
  634.       </handler>
  635.       <handler event="select" phase="target"
  636.                action="if (event.originalTarget == this) this.stopEditing(true);"/>
  637.       <handler event="focus">
  638.         <![CDATA[
  639.           this.treeBoxObject.focused = true;
  640.           if (this.currentIndex == -1 && this.view.rowCount > 0) {
  641.             this.currentIndex = this.treeBoxObject.getFirstVisibleRow();
  642.           }
  643.           if (this._cellSelType && !this.view.selection.currentColumn) {
  644.             var col = this._getNextColumn(this.currentIndex, false);
  645.             this.view.selection.currentColumn = col;
  646.           }
  647.         ]]>
  648.       </handler>
  649.       <handler event="blur" action="this.treeBoxObject.focused = false;"/>
  650.       <handler event="blur" phase="capturing"
  651.                action="if (event.originalTarget == this.inputField.inputField) this.stopEditing(true);"/>
  652.       <handler event="keypress" keycode="VK_ENTER">
  653.         <![CDATA[
  654.           if (this._editingColumn) {
  655.             this.stopEditing(true);
  656.             this.focus();
  657.             event.stopPropagation();
  658.           }
  659.           else {
  660.             this.changeOpenState(this.currentIndex);
  661.           }
  662.         ]]>
  663.       </handler>
  664.       <handler event="keypress" keycode="VK_RETURN">
  665.         <![CDATA[
  666.           if (this._editingColumn) {
  667.             this.stopEditing(true);
  668.             this.focus();
  669.             event.stopPropagation();
  670.           }
  671.           else {
  672.             this.changeOpenState(this.currentIndex);
  673.           }
  674.         ]]>
  675.       </handler>
  676.       <handler event="keypress" keycode="VK_ESCAPE">
  677.         <![CDATA[
  678.           if (this._editingColumn) {
  679.             this.stopEditing(false);
  680.             this.focus();
  681.             event.stopPropagation();
  682.           }
  683.         ]]>
  684.       </handler>
  685.       <handler event="keypress" keycode="VK_LEFT">
  686.         <![CDATA[
  687.          if (this._editingColumn)
  688.            return;
  689.  
  690.          var row = this.currentIndex;
  691.          if (row < 0)
  692.            return;
  693.  
  694.          var cellSelType = this._cellSelType;
  695.          var checkContainers = true;
  696.  
  697.          var currentColumn;
  698.          if (cellSelType) {
  699.            currentColumn = this.view.selection.currentColumn;
  700.            if (currentColumn && !currentColumn.primary)
  701.              checkContainers = false;
  702.          }
  703.  
  704.          if (checkContainers) {
  705.            if (this.changeOpenState(this.currentIndex, false))
  706.              return;
  707.            else {
  708.              var parentIndex = this.view.getParentIndex(this.currentIndex);
  709.              if (parentIndex >= 0) {
  710.                if (cellSelType && !this.view.isSelectable(parentIndex, currentColumn)) {
  711.                  return;
  712.                }
  713.                this.view.selection.select(parentIndex);
  714.                this.treeBoxObject.ensureRowIsVisible(parentIndex);
  715.                return;
  716.              }
  717.            }
  718.          }
  719.  
  720.          if (cellSelType) {
  721.            var col = this._getNextColumn(row, true);
  722.            if (col) {
  723.              this.view.selection.currentColumn = col;
  724.              this.treeBoxObject.ensureCellIsVisible(row, col);
  725.            }
  726.          }
  727.         ]]>
  728.       </handler>
  729.       <handler event="keypress" keycode="VK_RIGHT">
  730.         <![CDATA[
  731.          if (this._editingColumn)
  732.            return;
  733.  
  734.           var row = this.currentIndex;
  735.           if (row < 0)
  736.             return;
  737.  
  738.           var cellSelType = this._cellSelType;
  739.           var checkContainers = true;
  740.  
  741.           var currentColumn;
  742.           if (cellSelType) {
  743.             currentColumn = this.view.selection.currentColumn;
  744.             if (currentColumn && !currentColumn.primary)
  745.               checkContainers = false;
  746.           }
  747.  
  748.           if (checkContainers) {
  749.             if (this.changeOpenState(row, true))
  750.               return;
  751.             else {
  752.               var c = row + 1;
  753.               var view = this.view;
  754.               if (c < view.rowCount &&
  755.                   view.getParentIndex(c) == row) {
  756.                 // If already opened, select the first child.
  757.                 // The getParentIndex test above ensures that the children
  758.                 // are already populated and ready.
  759.                 if (cellSelType && !this.view.isSelectable(c , currentColumn)) {
  760.                   var col = this._getNextColumn(c, false);
  761.                   if (col) {
  762.                     this.view.selection.currentColumn = col;
  763.                   }
  764.                 }
  765.                 this.view.selection.timedSelect(c, this._selectDelay);
  766.                 this.treeBoxObject.ensureRowIsVisible(c);
  767.                 return;
  768.               }
  769.             }
  770.           }
  771.  
  772.           if (cellSelType) {
  773.             var col = this._getNextColumn(row, false);
  774.             if (col) {
  775.               this.view.selection.currentColumn = col;
  776.               this.treeBoxObject.ensureCellIsVisible(row, col);
  777.             }
  778.           }
  779.         ]]>
  780.       </handler>
  781.       <handler event="keypress" keycode="VK_UP"
  782.                modifiers="accel any" action="_moveByOffset(-1, 0, event);"/>
  783.       <handler event="keypress" keycode="VK_DOWN"
  784.                modifiers="accel any" action="_moveByOffset(1, this.view.rowCount - 1, event);"/>
  785.       <handler event="keypress" keycode="VK_UP"
  786.                modifiers="accel any, shift" action="_moveByOffsetShift(-1, 0, event);"/>
  787.       <handler event="keypress" keycode="VK_DOWN"
  788.                modifiers="accel any, shift" action="_moveByOffsetShift(1, this.view.rowCount - 1, event);"/>
  789.       <handler event="keypress" keycode="VK_PAGE_UP"
  790.                modifiers="accel any" action="_moveByPage(-1, 0, event);"/>
  791.       <handler event="keypress" keycode="VK_PAGE_DOWN"
  792.                modifiers="accel any" action="_moveByPage(1, this.view.rowCount - 1, event);"/>
  793.       <handler event="keypress" keycode="VK_PAGE_UP"
  794.                modifiers="accel any, shift" action="_moveByPageShift(-1, 0, event);"/>
  795.       <handler event="keypress" keycode="VK_PAGE_DOWN"
  796.                modifiers="accel any, shift" action="_moveByPageShift(1, this.view.rowCount - 1, event);"/>
  797.       <handler event="keypress" keycode="VK_HOME"
  798.                modifiers="accel any" action="_moveToEdge(0, event);"/>
  799.       <handler event="keypress" keycode="VK_END"
  800.                modifiers="accel any" action="_moveToEdge(this.view.rowCount - 1, event);"/>
  801.       <handler event="keypress" keycode="VK_HOME"
  802.                modifiers="accel any, shift" action="_moveToEdgeShift(0, event);"/>
  803.       <handler event="keypress" keycode="VK_END"
  804.                modifiers="accel any, shift" action="_moveToEdgeShift(this.view.rowCount - 1, event);"/>
  805.       <handler event="keypress">
  806.         <![CDATA[
  807.          if (this._editingColumn)
  808.            return;
  809.  
  810.          if (event.charCode == ' '.charCodeAt(0)) {
  811.            var c = this.currentIndex;
  812.            if (!this.view.selection.isSelected(c) ||
  813.                (!this.view.selection.single && this._isAccelPressed(event))) {
  814.              this.view.selection.toggleSelect(c);
  815.            }
  816.          }
  817.          else if (!this.disableKeyNavigation && event.charCode > 0 &&
  818.                   !event.altKey && !this._isAccelPressed(event) &&
  819.                   !event.metaKey && !event.ctrlKey) {
  820.            var l = this._keyNavigate(event);
  821.            if (l >= 0) {
  822.              this.view.selection.timedSelect(l, this._selectDelay);
  823.              this.treeBoxObject.ensureRowIsVisible(l);
  824.            }
  825.           }
  826.          ]]>
  827.       </handler>
  828.     </handlers>    
  829.   </binding>
  830.  
  831.   <binding id="treecols">
  832.     <resources>
  833.       <stylesheet src="chrome://global/skin/tree.css"/>
  834.     </resources>
  835.     <content orient="horizontal">
  836.       <xul:hbox class="tree-scrollable-columns" flex="1">
  837.         <children includes="treecol|splitter"/>
  838.       </xul:hbox>
  839.       <xul:treecolpicker class="treecol-image" fixed="true" xbl:inherits="tooltiptext=pickertooltiptext"/>
  840.     </content>
  841.     <implementation implements="nsIAccessibleProvider">
  842.       <property name="accessibleType" readonly="true">
  843.         <getter>
  844.           <![CDATA[
  845.             return Components.interfaces.nsIAccessibleProvider.XULTreeColumns;
  846.           ]]>
  847.         </getter>
  848.       </property>
  849.     </implementation>
  850.   </binding>
  851.  
  852.   <binding id="treerows" extends="chrome://global/content/bindings/tree.xml#tree-base">
  853.     <content>
  854.       <xul:hbox flex="1" class="tree-bodybox">
  855.         <children/>
  856.       </xul:hbox>
  857.       <xul:scrollbar height="0" minwidth="0" minheight="0" orient="vertical" xbl:inherits="collapsed=hidevscroll"/>
  858.     </content>
  859.     <handlers>
  860.       <handler event="underflow">
  861.         <![CDATA[
  862.           // Scrollport event orientation
  863.           // 0: vertical
  864.           // 1: horizontal
  865.           // 2: both (not used)
  866.           var tree = document.getBindingParent(this);
  867.           if (event.detail == 1)
  868.             tree.setAttribute("hidehscroll", "true");
  869.           else if (event.detail == 0)
  870.             tree.setAttribute("hidevscroll", "true");
  871.           event.stopPropagation();
  872.         ]]>
  873.       </handler>
  874.       <handler event="overflow">
  875.         <![CDATA[
  876.           var tree = document.getBindingParent(this);
  877.           if (event.detail == 1)
  878.             tree.removeAttribute("hidehscroll");
  879.           else if (event.detail == 0)
  880.             tree.removeAttribute("hidevscroll");
  881.           event.stopPropagation();
  882.         ]]>
  883.       </handler>
  884.     </handlers>
  885.   </binding>
  886.  
  887.   <binding id="treebody" extends="chrome://global/content/bindings/tree.xml#tree-base">
  888.     <implementation>
  889.       <constructor>
  890.         if ("_ensureColumnOrder" in this.parentNode)
  891.           this.parentNode._ensureColumnOrder();
  892.       </constructor>
  893.  
  894.       <field name="_lastSelectedRow">
  895.         -1
  896.       </field>
  897.     </implementation>
  898.     <handlers>
  899.       <!-- If there is no modifier key, we select on mousedown, not
  900.            click, so that drags work correctly. -->
  901.       <handler event="mousedown" clickcount="1">
  902.       <![CDATA[
  903.          if (this.parentNode.disabled)
  904.            return;
  905.          if (((!this._isAccelPressed(event) ||
  906.              !this.parentNode.pageUpOrDownMovesSelection) &&
  907.              !event.shiftKey && !event.metaKey) ||
  908.              this.parentNode.view.selection.single) {
  909.            var row = {};
  910.            var col = {};
  911.            var obj = {};
  912.            var b = this.parentNode.treeBoxObject;
  913.            b.getCellAt(event.clientX, event.clientY, row, col, obj);
  914.  
  915.            // save off the last selected row
  916.            this._lastSelectedRow = row.value;
  917.  
  918.            if (row.value == -1)
  919.              return;
  920.  
  921.            if (obj.value == "twisty")
  922.              return;
  923.  
  924.            if (col.value) {
  925.              if (col.value.cycler) {
  926.                b.view.cycleCell(row.value, col.value);
  927.                return;
  928.              } else if (col.value.type == Components.interfaces.nsITreeColumn.TYPE_CHECKBOX) {
  929.                if (this.parentNode.editable && col.value.editable &&
  930.                    b.view.isEditable(row.value, col.value)) {
  931.                  var value = b.view.getCellValue(row.value, col.value);
  932.                  value = value == "true" ? "false" : "true";
  933.                  b.view.setCellValue(row.value, col.value, value);
  934.                  return;
  935.                }
  936.              }
  937.            } 
  938.  
  939.            var cellSelType = this.parentNode._cellSelType;
  940.            if (cellSelType == "text" && obj.value != "text" && obj.value != "image")
  941.              return;
  942.  
  943.            if (cellSelType) {
  944.              if (!col.value.selectable ||
  945.                  !b.view.isSelectable(row.value, col.value)) {
  946.                return;
  947.              }
  948.            }
  949.  
  950.            if (!b.view.selection.isSelected(row.value)) {
  951.              b.view.selection.select(row.value);
  952.              b.ensureRowIsVisible(row.value);
  953.            }
  954.  
  955.            if (cellSelType) {
  956.              b.view.selection.currentColumn = col.value;
  957.            }
  958.          }
  959.       ]]>
  960.       </handler>
  961.  
  962.       <!-- On a click (up+down on the same item), deselect everything
  963.            except this item. -->
  964.       <handler event="click" button="0" clickcount="1">
  965.       <![CDATA[
  966.         if (this.parentNode.disabled)
  967.           return;
  968.         var row = {};
  969.         var col = {};
  970.         var obj = {};
  971.         var b = this.parentNode.treeBoxObject;
  972.         b.getCellAt(event.clientX, event.clientY, row, col, obj);
  973.  
  974.         if (row.value == -1)
  975.           return;
  976.  
  977.         if (obj.value == "twisty") {
  978.           if (b.view.selection.currentIndex >= 0 &&
  979.               b.view.isContainerOpen(row.value)) {
  980.             var parentIndex = b.view.getParentIndex(b.view.selection.currentIndex);
  981.             while (parentIndex >= 0 && parentIndex != row.value)
  982.               parentIndex = b.view.getParentIndex(parentIndex);
  983.             if (parentIndex == row.value) {
  984.               var parentSelectable = true;
  985.               if (this.parentNode._cellSelType) {
  986.                 var currentColumn = b.view.selection.currentColumn;
  987.                 if (!b.view.isSelectable(parentIndex, currentColumn))
  988.                   parentSelectable = false;
  989.               }
  990.               if (parentSelectable)
  991.                 b.view.selection.select(parentIndex);
  992.             }
  993.           }
  994.           this.parentNode.changeOpenState(row.value);
  995.           return;
  996.         }
  997.  
  998.         if (! b.view.selection.single) {
  999.           var augment = this._isAccelPressed(event);
  1000.           if (event.shiftKey) {
  1001.             b.view.selection.rangedSelect(-1, row.value, augment);
  1002.             b.ensureRowIsVisible(row.value);
  1003.             return;
  1004.           }
  1005.           if (augment) {
  1006.             b.view.selection.toggleSelect(row.value);
  1007.             b.ensureRowIsVisible(row.value);
  1008.             b.view.selection.currentIndex = row.value;
  1009.             return;
  1010.           }
  1011.         }
  1012.  
  1013.         /* We want to deselect all the selected items except what was
  1014.           clicked, UNLESS it was a right-click.  We have to do this
  1015.           in click rather than mousedown so that you can drag a
  1016.           selected group of items */
  1017.  
  1018.         if (!col.value) return;
  1019.  
  1020.         // if the last row has changed in between the time we 
  1021.         // mousedown and the time we click, don't fire the select handler.
  1022.         // see bug #92366
  1023.         if (!col.value.cycler && this._lastSelectedRow == row.value &&
  1024.             col.value.type != Components.interfaces.nsITreeColumn.TYPE_CHECKBOX) {
  1025.  
  1026.           var cellSelType = this.parentNode._cellSelType;
  1027.           if (cellSelType == "text" && obj.value != "text" && obj.value != "image")
  1028.             return;
  1029.  
  1030.           if (cellSelType) {
  1031.             if (!col.value.selectable ||
  1032.                 !b.view.isSelectable(row.value, col.value)) {
  1033.               return;
  1034.             }
  1035.           }
  1036.  
  1037.           b.view.selection.select(row.value);  
  1038.           b.ensureRowIsVisible(row.value);
  1039.  
  1040.           if (cellSelType) {
  1041.             b.view.selection.currentColumn = col.value;
  1042.           }
  1043.         }
  1044.       ]]>
  1045.       </handler>
  1046.  
  1047.       <!-- double-click -->
  1048.       <handler event="click" clickcount="2">
  1049.       <![CDATA[
  1050.         if (this.parentNode.disabled)
  1051.           return;
  1052.         var b = this.parentNode.treeBoxObject;
  1053.         var row = b.view.selection.currentIndex;
  1054.          if (row == -1)
  1055.            return;
  1056.   
  1057.           var col = {};
  1058.           var obj = {};
  1059.           b.getCellAt(event.clientX, event.clientY, {}, col, obj);
  1060.   
  1061.           if (this.parentNode.editable)
  1062.             this.parentNode.startEditing(row, col.value);
  1063.  
  1064.           if (!b.view.isContainer(row))
  1065.             return;
  1066.  
  1067.  
  1068.          // Cyclers and twisties respond to single clicks, not double clicks
  1069.          if (col.value && !col.value.cycler && obj.value != "twisty")
  1070.            this.parentNode.changeOpenState(row);
  1071.       ]]>
  1072.       </handler>
  1073.       
  1074.     </handlers>
  1075.   </binding>
  1076.  
  1077.   <binding id="treecol-base" extends="chrome://global/content/bindings/tree.xml#tree-base">
  1078.     <implementation implements="nsIAccessibleProvider">
  1079.       <constructor>
  1080.         this.parentNode.parentNode._columnsDirty = true;
  1081.       </constructor>
  1082.  
  1083.       <property name="accessibleType" readonly="true">
  1084.         <getter>
  1085.           <![CDATA[
  1086.             return Components.interfaces.nsIAccessibleProvider.XULTreeColumnItem;
  1087.           ]]>
  1088.         </getter>
  1089.       </property>
  1090.  
  1091.       <property name="ordinal">
  1092.         <getter><![CDATA[
  1093.           var val = this.getAttribute("ordinal");
  1094.           return "" + (val == "" ? 1 : (val == "0" ? 0 : parseInt(val)));
  1095.         ]]></getter>
  1096.         <setter><![CDATA[
  1097.           this.setAttribute("ordinal", val);
  1098.           return val;
  1099.         ]]></setter>
  1100.       </property>
  1101.       
  1102.       <property name="_previousVisibleColumn">
  1103.         <getter><![CDATA[
  1104.           var sib = this.boxObject.previousSibling;
  1105.           while (sib) {
  1106.             if (sib.localName == "treecol" && sib.boxObject.width > 0 && sib.parentNode == this.parentNode)
  1107.               return sib;
  1108.             sib = sib.boxObject.previousSibling;
  1109.           }
  1110.           return null;
  1111.         ]]></getter>
  1112.       </property>
  1113.  
  1114.       <method name="_onDragMouseMove">
  1115.         <parameter name="aEvent"/>
  1116.         <body><![CDATA[
  1117.           var col = document.treecolDragging;
  1118.           if (!col) return;
  1119.  
  1120.           // determine if we have moved the mouse far enough
  1121.           // to initiate a drag
  1122.           if (col.mDragGesturing) {
  1123.             if (Math.abs(aEvent.clientX - col.mStartDragX) < 5 &&
  1124.                 Math.abs(aEvent.clientY - col.mStartDragY) < 5) {
  1125.               return;
  1126.             } else {
  1127.               col.mDragGesturing = false;
  1128.               col.setAttribute("dragging", "true");
  1129.               window.addEventListener("click", col._onDragMouseClick, true);
  1130.             }
  1131.           }
  1132.                     
  1133.           var pos = {};
  1134.           var targetCol = col.parentNode.parentNode._getColumnAtX(aEvent.clientX, 0.5, pos);
  1135.           
  1136.           // bail if we haven't mousemoved to a different column
  1137.           if (col.mTargetCol == targetCol && col.mTargetDir == pos.value)
  1138.             return;
  1139.  
  1140.           var tree = col.parentNode.parentNode;
  1141.           var sib;
  1142.           var column;
  1143.           if (col.mTargetCol) {
  1144.             // remove previous insertbefore/after attributes
  1145.             col.mTargetCol.removeAttribute("insertbefore");
  1146.             col.mTargetCol.removeAttribute("insertafter");
  1147.             column = tree.columns.getColumnFor(col.mTargetCol);
  1148.             tree.treeBoxObject.invalidateColumn(column);
  1149.             sib = col.mTargetCol._previousVisibleColumn;
  1150.             if (sib) {
  1151.               sib.removeAttribute("insertafter");
  1152.               column = tree.columns.getColumnFor(sib);
  1153.               tree.treeBoxObject.invalidateColumn(column);
  1154.             }
  1155.             col.mTargetCol = null;
  1156.             col.mTargetDir = null;
  1157.           }
  1158.           
  1159.           if (targetCol) {
  1160.             // set insertbefore/after attributes
  1161.             if (pos.value == "after") {
  1162.               targetCol.setAttribute("insertafter", "true");
  1163.             } else {
  1164.               targetCol.setAttribute("insertbefore", "true");
  1165.               sib = targetCol._previousVisibleColumn;
  1166.               if (sib) {
  1167.                 sib.setAttribute("insertafter", "true");
  1168.                 column = tree.columns.getColumnFor(sib);
  1169.                 tree.treeBoxObject.invalidateColumn(column);
  1170.               }
  1171.             }
  1172.             column = tree.columns.getColumnFor(targetCol);
  1173.             tree.treeBoxObject.invalidateColumn(column);
  1174.             col.mTargetCol = targetCol;
  1175.             col.mTargetDir = pos.value;
  1176.           }
  1177.         ]]></body>        
  1178.       </method>
  1179.  
  1180.       <method name="_onDragMouseUp">
  1181.         <parameter name="aEvent"/>
  1182.         <body><![CDATA[
  1183.           var col = document.treecolDragging;
  1184.           if (!col) return;
  1185.           
  1186.           if (!col.mDragGesturing) {
  1187.             if (col.mTargetCol) {
  1188.               // remove insertbefore/after attributes
  1189.               var before = col.mTargetCol.hasAttribute("insertbefore");
  1190.               col.mTargetCol.removeAttribute(before ? "insertbefore" : "insertafter");
  1191.  
  1192.               var sib = col.mTargetCol._previousVisibleColumn;
  1193.               if (before && sib) {
  1194.                 sib.removeAttribute("insertafter");
  1195.               }
  1196.  
  1197.               // Move the column only if it will result in a different column
  1198.               // ordering
  1199.               var move = true;
  1200.  
  1201.               // If this is a before move and the previous visible column is
  1202.               // the same as the column we're moving, don't move
  1203.               if (before && col == sib) {
  1204.                 move = false;
  1205.               }
  1206.               else if (!before && col == col.mTargetCol) {
  1207.                 // If this is an after move and the column we're moving is
  1208.                 // the same as the target column, don't move.
  1209.                 move = false;
  1210.               }
  1211.  
  1212.               if (move) {
  1213.                 col.parentNode.parentNode._reorderColumn(col, col.mTargetCol, before);
  1214.               }
  1215.  
  1216.               // repaint to remove lines
  1217.               col.parentNode.parentNode.treeBoxObject.invalidate();
  1218.   
  1219.               col.mTargetCol = null;
  1220.             }
  1221.           } else
  1222.             col.mDragGesturing = false;
  1223.                     
  1224.           document.treecolDragging = null;
  1225.           col.removeAttribute("dragging");
  1226.           
  1227.           window.removeEventListener("mousemove", col._onDragMouseMove, true);
  1228.           window.removeEventListener("mouseup", col._onDragMouseUp, true);
  1229.           // we have to wait for the click event to fire before removing
  1230.           // cancelling handler
  1231.           var clickHandler = function(handler) { 
  1232.             window.removeEventListener("click", handler, true);
  1233.           };
  1234.           window.setTimeout(clickHandler, 0, col._onDragMouseClick);
  1235.         ]]></body>        
  1236.       </method>
  1237.  
  1238.       <method name="_onDragMouseClick">
  1239.         <parameter name="aEvent"/>
  1240.         <body><![CDATA[
  1241.           // prevent click event from firing after column drag and drop
  1242.           aEvent.stopPropagation();
  1243.           aEvent.preventDefault();
  1244.         ]]></body>        
  1245.       </method>
  1246.     </implementation>
  1247.     
  1248.     <handlers>
  1249.       <handler event="mousedown" button="0"><![CDATA[
  1250.         if (this.parentNode.parentNode.enableColumnDrag) {
  1251.           var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  1252.           var cols = this.parentNode.getElementsByTagNameNS(xulns, "treecol");
  1253.           
  1254.           // only start column drag operation if there are at least 2 visible columns
  1255.           var visible = 0;
  1256.           for (var i = 0; i < cols.length; ++i)
  1257.             if (cols[i].boxObject.width > 0) ++visible;
  1258.             
  1259.           if (visible > 1) {
  1260.             window.addEventListener("mousemove", this._onDragMouseMove, true);
  1261.             window.addEventListener("mouseup", this._onDragMouseUp, true);
  1262.             document.treecolDragging = this;
  1263.             this.mDragGesturing = true;
  1264.             this.mStartDragX = event.clientX;
  1265.             this.mStartDragY = event.clientY;
  1266.           }
  1267.         }
  1268.       ]]></handler>
  1269.       <handler event="click" button="0" phase="target">
  1270.         <![CDATA[
  1271.           if (event.target != event.originalTarget)
  1272.             return;
  1273.  
  1274.           var tree = this.parentNode.parentNode;
  1275.           var column = tree.columns.getColumnFor(this);
  1276.           tree.view.cycleHeader(column);
  1277.         ]]>
  1278.       </handler>
  1279.     </handlers>
  1280.   </binding>
  1281.  
  1282.   <binding id="treecol" extends="chrome://global/content/bindings/tree.xml#treecol-base">
  1283.     <content>
  1284.       <xul:label class="treecol-text" xbl:inherits="crop,value=label" flex="1" crop="right"/>
  1285.       <xul:image class="treecol-sortdirection" xbl:inherits="sortDirection,hidden=hideheader"/>
  1286.     </content>
  1287.   </binding>
  1288.  
  1289.   <binding id="treecol-image" extends="chrome://global/content/bindings/tree.xml#treecol-base">
  1290.     <content>
  1291.       <xul:image class="treecol-icon" xbl:inherits="src"/>
  1292.     </content>
  1293.   </binding>
  1294.  
  1295.   <binding id="columnpicker" display="xul:button"
  1296.            extends="chrome://global/content/bindings/tree.xml#tree-base">
  1297.     <content>
  1298.       <xul:image class="tree-columnpicker-icon"/>
  1299.       <xul:menupopup anonid="popup">
  1300.         <xul:menuseparator anonid="menuseparator"/>
  1301.         <xul:menuitem anonid="menuitem" label="&restoreNaturalOrder.label;"/>
  1302.       </xul:menupopup>
  1303.     </content>
  1304.     
  1305.     <implementation implements="nsIAccessibleProvider">
  1306.       <property name="accessibleType" readonly="true">
  1307.         <getter>
  1308.           return Components.interfaces.nsIAccessibleProvider.XULButton;
  1309.         </getter>
  1310.       </property>
  1311.  
  1312.       <method name="buildPopup">
  1313.         <parameter name="aPopup"/>
  1314.         <body>
  1315.           <![CDATA[
  1316.             // We no longer cache the picker content, remove the old content.
  1317.             while (aPopup.childNodes.length > 2)
  1318.               aPopup.removeChild(aPopup.firstChild);
  1319.  
  1320.             var refChild = aPopup.firstChild;
  1321.  
  1322.             var tree = this.parentNode.parentNode;
  1323.             for (var currCol = tree.columns.getFirstColumn(); currCol;
  1324.                  currCol = currCol.getNext()) {
  1325.               // Construct an entry for each column in the row, unless
  1326.               // it is not being shown.
  1327.               var currElement = currCol.element;
  1328.               if (!currElement.hasAttribute("ignoreincolumnpicker")) {
  1329.                 var popupChild = document.createElement("menuitem");
  1330.                 popupChild.setAttribute("type", "checkbox");
  1331.                 var columnName = currElement.getAttribute("display") ||
  1332.                                  currElement.getAttribute("label");
  1333.                 popupChild.setAttribute("label", columnName);
  1334.                 popupChild.setAttribute("colindex", currCol.index);
  1335.                 if (currElement.getAttribute("hidden") != "true")
  1336.                   popupChild.setAttribute("checked", "true");
  1337.                 if (currCol.primary)
  1338.                   popupChild.setAttribute("disabled", "true");
  1339.                 aPopup.insertBefore(popupChild, refChild);
  1340.               }
  1341.             }
  1342.  
  1343.             var hidden = !tree.enableColumnDrag;
  1344.             const anonids = ["menuseparator", "menuitem"];
  1345.             for (var i = 0; i < anonids.length; i++) {
  1346.               var element = document.getAnonymousElementByAttribute(this, "anonid", anonids[i]);
  1347.               element.hidden = hidden;
  1348.             }
  1349.           ]]>
  1350.         </body>
  1351.       </method>
  1352.     </implementation>
  1353.  
  1354.     <handlers>
  1355.       <handler event="command">
  1356.         <![CDATA[
  1357.           if (event.originalTarget == this) {
  1358.             var popup = document.getAnonymousElementByAttribute(this, "anonid", "popup");
  1359.             this.buildPopup(popup);
  1360.             popup.showPopup(this, -1, -1, "popup", "bottomright", "topright");
  1361.           }
  1362.           else {
  1363.             var tree = this.parentNode.parentNode;
  1364.             tree.stopEditing(true);
  1365.             var menuitem = document.getAnonymousElementByAttribute(this, "anonid", "menuitem");
  1366.             if (event.originalTarget == menuitem) {
  1367.               tree.columns.restoreNaturalOrder();
  1368.               tree._ensureColumnOrder();
  1369.             }
  1370.             else {
  1371.               var colindex = event.originalTarget.getAttribute("colindex");
  1372.               var column = tree.columns[colindex];
  1373.               if (column) {
  1374.                 var element = column.element;
  1375.                 if (element.getAttribute("hidden") == "true")
  1376.                   element.setAttribute("hidden", "false");
  1377.                 else
  1378.                   element.setAttribute("hidden", "true");
  1379.               }
  1380.             }
  1381.           }
  1382.         ]]>
  1383.       </handler>
  1384.     </handlers>
  1385.   </binding>
  1386. </bindings>
  1387.  
  1388.