home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 May / PCWorld_2003-05_cd.bin / Komunik / phoenix / chrome / toolkit.jar / content / global / widgets / tree.xml < prev    next >
Extensible Markup Language  |  2002-11-10  |  38KB  |  1,072 lines

  1. <?xml version="1.0"?>
  2.  
  3. <bindings id="treeBindings"
  4.    xmlns="http://www.mozilla.org/xbl"
  5.    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  6.    xmlns:xbl="http://www.mozilla.org/xbl">
  7.   
  8.   <binding id="tree-base">
  9.     <resources>
  10.       <stylesheet src="chrome://global/skin/tree.css"/>
  11.     </resources>
  12.   </binding>
  13.  
  14.   <binding id="tree" extends="chrome://global/content/bindings/tree.xml#tree-base">
  15.     <content>
  16.       <children includes="treecols"/>
  17.       <xul:treerows class="tree-rows" flex="1">
  18.         <children/>
  19.       </xul:treerows>
  20.     </content>
  21.     
  22.     <implementation implements="nsIAccessibleProvider">
  23.       <constructor>
  24.         this.addEventListener("DOMMouseScroll", this._handleMouseScroll, true);
  25. #ifdef XP_MAC
  26.         this.pageUpOrDownMovesSelection = false;
  27. #endif
  28.       </constructor>
  29.  
  30.       <!-- ///////////////// nsIAccessibleProvider ///////////////// -->
  31.  
  32.       <property name="accessible">
  33.         <getter>
  34.           <![CDATA[
  35.             var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
  36.             return accService.createXULTreeAccessible(this);
  37.           ]]>
  38.         </getter>
  39.       </property>
  40.  
  41.       <property name="treeBoxObject"
  42.                 onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);"
  43.                 readonly="true"/>
  44.       <property name="view"
  45.                 onget="return this.treeBoxObject.view;"
  46.                 onset="return this.treeBoxObject.view=val;"/>
  47.       <property name="contentView"
  48.                 onget="return this.view.QueryInterface(Components.interfaces.nsITreeContentView);"
  49.                 readonly="true"/>
  50.       <property name="builderView"
  51.                 onget="return this.view.QueryInterface(Components.interfaces.nsIXULTreeBuilder);"
  52.                 readonly="true"/>
  53.       <property name="currentIndex"
  54.                 onget="return this.treeBoxObject.selection.currentIndex;"
  55.                 onset="return this.treeBoxObject.selection.currentIndex=val;"/>
  56.       <field name="pageUpOrDownMovesSelection">
  57.         true
  58.       </field>
  59.       <field name="selectionHead">
  60.         -1
  61.       </field>
  62.       <field name="selectionTail">
  63.         -1
  64.       </field>
  65.       <property name="singleSelection"
  66.                 onget="return this.getAttribute('seltype') == 'single'"
  67.                 readonly="true"/>
  68.  
  69.       <property name="enableColumnDrag"
  70.                 onget="return this.hasAttribute('enableColumnDrag');"
  71.                 onset="if (val) this.setAttribute('enableColumnDrag', 'true');
  72.                        else this.removeAttribute('enableColumnDrag'); return val;"/>
  73.  
  74.       <property name="firstOrdinalColumn">
  75.         <getter><![CDATA[
  76.           var cols = this.firstChild;
  77.           while (cols && cols.localName != "treecols")
  78.             cols = cols.nextSibling;
  79.  
  80.           if (cols)
  81.             return cols.boxObject.firstChild;
  82.           else
  83.             return null;
  84.         ]]></getter>
  85.       </property>
  86.  
  87.       <property name="disableKeyNavigation"
  88.                 onget="return this.hasAttribute('disableKeyNavigation');"
  89.                 onset="if (val) this.setAttribute('disableKeyNavigation', 'true');
  90.                        else this.removeAttribute('disableKeyNavigation'); return val;"/>
  91.       
  92.       <property name="_selectDelay" 
  93.                 onset="this.setAttribute('_selectDelay', val);"
  94.                 onget="return this.getAttribute('_selectDelay') || 50;"/>
  95.       <field name="_columnsDirty">true</field>
  96.       <field name="_handleMouseScroll">
  97.       <![CDATA[
  98.         ({
  99.           subject: this,
  100.           handleEvent: function(aEvent)
  101.           {
  102.             var rows = aEvent.detail;
  103.             if (rows == NSUIEvent.SCROLL_PAGE_UP)
  104.               this.subject.treeBoxObject.scrollByPages(-1);
  105.             else if (rows == NSUIEvent.SCROLL_PAGE_DOWN)
  106.               this.subject.treeBoxObject.scrollByPages(1);
  107.             else
  108.               this.subject.treeBoxObject.scrollByLines(aEvent.detail);
  109.           }
  110.         })
  111.       ]]>
  112.       </field>
  113.       <field name="_lastKeyTime">0</field>
  114.       <field name="_incrementalString">""</field>
  115.  
  116.       <method name="_ensureColumnOrder">
  117.         <body><![CDATA[
  118.           if (this._columnsDirty) {
  119.             // update the ordinal position of each column to assure that it is
  120.             // an odd number and 2 positions above it's next sibling
  121.             var col = this.firstOrdinalColumn;
  122.             var cols = [];
  123.             while (col) {
  124.               if (col.localName == "treecol" && col.parentNode.parentNode == this)
  125.                 cols[cols.length] = col;
  126.               col = col.boxObject.nextSibling;
  127.             }
  128.             var i;
  129.             for (i = 0; i < cols.length; ++i)
  130.               cols[i].setAttribute("ordinal", (i*2)+1);
  131.               
  132.             // update the ordinal positions of splitters to even numbers, so that 
  133.             // they are in between columns
  134.             var splitters = this.getElementsByTagName("splitter");
  135.             for (i = 0; i < splitters.length; ++i)
  136.               splitters[i].setAttribute("ordinal", (i+1)*2);
  137.             
  138.             this._columnsDirty = false;
  139.           }
  140.         ]]></body>
  141.       </method>
  142.  
  143.       <method name="_reorderColumn">
  144.         <parameter name="aColMove"/>
  145.         <parameter name="aColBefore"/>
  146.         <parameter name="aBefore"/>
  147.         <body><![CDATA[
  148.           this._ensureColumnOrder();
  149.           
  150.           var cols = [];
  151.           var col;
  152.           if (aColBefore.ordinal < aColMove.ordinal) {
  153.             col = aColBefore;
  154.             while (col) {
  155.               if (col.localName == "treecol")
  156.                 cols.push(col);
  157.               col = col.boxObject.nextSibling;
  158.               if (col == aColMove)  
  159.                 break;
  160.             }
  161.  
  162.             aColMove.ordinal = aColBefore.ordinal;
  163.             var i;
  164.             for (i = 0; i < cols.length; ++i)
  165.               cols[i].ordinal += 2;
  166.           } else {
  167.             col = aColMove.boxObject.nextSibling;
  168.             while (col) {
  169.               if (col.localName == "treecol")
  170.                 cols.push(col);
  171.               col = col.boxObject.nextSibling;
  172.               if (col == aColBefore && aBefore)
  173.                 break;
  174.             }
  175.  
  176.             aColMove.ordinal = aBefore ? aColBefore.ordinal-2 : aColBefore.ordinal;
  177.  
  178.             for (i = 0; i < cols.length; ++i)
  179.               cols[i].ordinal -= 2;
  180.           }
  181.         ]]></body>
  182.       </method>
  183.       
  184.       <method name="_getColumnAtX">
  185.         <parameter name="aX"/>
  186.         <parameter name="aThresh"/>
  187.         <parameter name="aPos"/>
  188.         <body><![CDATA[
  189.           if (aPos) aPos.value = "before";
  190.  
  191.           var col = this.firstOrdinalColumn;
  192.           var lastCol = null;
  193.           var currentX = this.boxObject.x;
  194.           while (col) {
  195.             if (col.localName == "treecol" && col.parentNode.parentNode == this) {
  196.               var cw = col.boxObject.width;
  197.               if (cw > 0) {
  198.                 currentX += cw;
  199.                 if (currentX - (cw*aThresh) > aX)
  200.                   return col;
  201.               }
  202.               lastCol = col;
  203.             }
  204.             col = col.boxObject.nextSibling;
  205.           }
  206.  
  207.           if (aPos) aPos.value = "after";
  208.           return lastCol;
  209.         ]]></body>
  210.       </method>
  211.  
  212.     </implementation>
  213.     
  214.     <handlers>
  215.       <handler event="focus" action="this.treeBoxObject.focused = true;"/>
  216.       <handler event="blur" action="this.treeBoxObject.focused = false;"/>
  217.   
  218.       <handler event="dragenter" action="this.treeBoxObject.onDragEnter(event);"/>
  219.       <handler event="dragexit" action="this.treeBoxObject.onDragExit(event);"/>
  220.       <handler event="dragover" action="this.treeBoxObject.onDragOver(event);"/>
  221.       <handler event="dragdrop" action="this.treeBoxObject.onDragDrop(event);"/>
  222.  
  223.       <handler event="keypress" keycode="vk_enter">
  224.         <![CDATA[
  225.          if (this.currentIndex == -1)
  226.            return;
  227.          if (this.treeBoxObject.view.isContainer(this.currentIndex))
  228.            this.treeBoxObject.view.toggleOpenState(this.currentIndex);
  229.         ]]>
  230.       </handler>
  231.       <handler event="keypress" keycode="vk_return">
  232.         <![CDATA[
  233.          if (this.currentIndex == -1)
  234.            return;
  235.          if (this.treeBoxObject.view.isContainer(this.currentIndex))
  236.            this.treeBoxObject.view.toggleOpenState(this.currentIndex);
  237.         ]]>
  238.       </handler>
  239.       <handler event="keypress" keycode="vk_left">
  240.         <![CDATA[
  241.          if (this.currentIndex == -1)
  242.            return;
  243.          if (this.treeBoxObject.view.isContainer(this.currentIndex) &&
  244.              this.treeBoxObject.view.isContainerOpen(this.currentIndex)) {
  245.            this.treeBoxObject.view.toggleOpenState(this.currentIndex);
  246.          }
  247.          else {
  248.            var parentIndex = this.treeBoxObject.view.getParentIndex(this.currentIndex);
  249.            if (parentIndex >= 0) {
  250.              this.treeBoxObject.selection.select(parentIndex);
  251.              this.treeBoxObject.ensureRowIsVisible(parentIndex);
  252.            }
  253.          }
  254.         ]]>
  255.       </handler>
  256.       <handler event="keypress" keycode="vk_right">
  257.         <![CDATA[
  258.          if (this.currentIndex == -1)
  259.            return;
  260.          if (this.treeBoxObject.view.isContainer(this.currentIndex)) {
  261.            if (!this.treeBoxObject.view.isContainerOpen(this.currentIndex))
  262.              this.treeBoxObject.view.toggleOpenState(this.currentIndex);
  263.          }
  264.         ]]>
  265.       </handler>
  266.       <handler event="keypress" keycode="vk_up">
  267.         <![CDATA[
  268.          var c = this.currentIndex;
  269.          if (c == -1 || c == 0)
  270.            return;
  271.          this.selectionHead = -1;
  272.          this.selectionTail = -1;
  273.          this.treeBoxObject.selection.timedSelect(c-1, this._selectDelay);
  274.          this.treeBoxObject.ensureRowIsVisible(c-1);
  275.         ]]>
  276.       </handler>
  277.       <handler event="keypress" keycode="vk_down">
  278.         <![CDATA[
  279.          var c = this.currentIndex;
  280.          try { if (c+1 == this.treeBoxObject.view.rowCount)
  281.            return;
  282.          } catch (e) {}
  283.          this.selectionHead = -1;
  284.          this.selectionTail = -1;
  285.          this.treeBoxObject.selection.timedSelect(c+1, this._selectDelay);
  286.          this.treeBoxObject.ensureRowIsVisible(c+1);
  287.         ]]>
  288.       </handler>
  289.       <handler event="keypress" keycode="vk_up" modifiers="shift">
  290.         <![CDATA[
  291.          if (this.singleSelection)
  292.            return;
  293.          var c = this.currentIndex;
  294.          if (c == -1 || c == 0)
  295.            return;
  296.          if (c == this.selectionTail) {
  297.            if (this.selectionHead < this.selectionTail) {
  298.              this.treeBoxObject.selection.toggleSelect(c);
  299.              this.currentIndex = c - 1;
  300.            }
  301.            else {
  302.              this.treeBoxObject.selection.toggleSelect(c - 1);
  303.            }
  304.          }
  305.          else {
  306.            this.treeBoxObject.selection.clearSelection();
  307.            this.selectionHead = c;
  308.            this.treeBoxObject.selection.rangedSelect(c, c - 1, true);
  309.          }
  310.          this.selectionTail = c - 1;
  311.          this.treeBoxObject.ensureRowIsVisible(c - 1);
  312.         ]]>
  313.       </handler>
  314.       <handler event="keypress" keycode="vk_down" modifiers="shift">
  315.         <![CDATA[
  316.          if (this.singleSelection)
  317.            return;
  318.          var c = this.currentIndex;
  319.          try { if (c+1 == this.treeBoxObject.view.rowCount)
  320.            return;
  321.          } catch (e) {}
  322.          if (c == this.selectionTail) {
  323.            if (this.selectionHead > this.selectionTail) {
  324.              this.treeBoxObject.selection.toggleSelect(c);
  325.              this.currentIndex = c + 1;
  326.            }
  327.            else
  328.              this.treeBoxObject.selection.toggleSelect(c + 1);
  329.          }
  330.          else {
  331.            this.treeBoxObject.selection.clearSelection();
  332.            this.selectionHead = c;
  333.            this.treeBoxObject.selection.rangedSelect(c, c + 1, true);
  334.          }
  335.          this.selectionTail = c + 1;
  336.          this.treeBoxObject.ensureRowIsVisible(c + 1);
  337.         ]]>
  338.       </handler>
  339.       <handler event="keypress" keycode="vk_up" modifiers="control">
  340.         <![CDATA[
  341.          var c = this.currentIndex;
  342.          if (c == -1 || c == 0)
  343.            return;
  344.          this.currentIndex = c-1;
  345.          this.treeBoxObject.ensureRowIsVisible(c-1);
  346.         ]]>
  347.       </handler>
  348.       <handler event="keypress" keycode="vk_down" modifiers="control">
  349.         <![CDATA[
  350.          var c = this.currentIndex;
  351.          try { if (c+1 == this.treeBoxObject.view.rowCount)
  352.            return;
  353.          } catch (e) {}
  354.          this.currentIndex = c+1;
  355.          this.treeBoxObject.ensureRowIsVisible(c+1);
  356.         ]]>
  357.       </handler>
  358.       <handler event="keypress" keycode="vk_page_up">
  359.         <![CDATA[
  360.          if (! this.pageUpOrDownMovesSelection) {
  361.            this.treeBoxObject.scrollByPages(-1);
  362.            return;
  363.          }
  364.          var c = this.currentIndex;
  365.          if (c == 0)
  366.            return;
  367.          this.selectionHead = -1;
  368.          this.selectionTail = -1;
  369.          var f = this.treeBoxObject.getFirstVisibleRow();
  370.          var i = 0;
  371.          if (f > 0) {
  372.            var p = this.treeBoxObject.getPageCount();
  373.            if (f - p >= 0)
  374.              i = c - p;
  375.            else
  376.              i = c - f;
  377.            this.treeBoxObject.scrollByPages(-1);
  378.          }
  379.          this.treeBoxObject.selection.timedSelect(i, this._selectDelay);
  380.         ]]>
  381.       </handler>
  382.       <handler event="keypress" keycode="vk_page_down">
  383.         <![CDATA[
  384.          if (! this.pageUpOrDownMovesSelection) {
  385.            this.treeBoxObject.scrollByPages(1);
  386.            return;
  387.          }
  388.          var c = this.currentIndex;
  389.          var l = this.treeBoxObject.view.rowCount - 1;
  390.          if (c == l)
  391.            return;
  392.          this.selectionHead = -1;
  393.          this.selectionTail = -1;
  394.          var f = this.treeBoxObject.getFirstVisibleRow();
  395.          var p = this.treeBoxObject.getPageCount();
  396.          var i = l;
  397.          var lastTopRowIndex = l - p;
  398.          if (f <= lastTopRowIndex) {
  399.            if (f + p <= lastTopRowIndex)
  400.              i = c + p;
  401.            else
  402.              i = lastTopRowIndex + c - f + 1;
  403.            this.treeBoxObject.scrollByPages(1);
  404.          }
  405.          this.treeBoxObject.selection.timedSelect(i, this._selectDelay);
  406.         ]]>
  407.       </handler>
  408.       <handler event="keypress" keycode="vk_page_up" modifiers="shift">
  409.         <![CDATA[
  410.          if (this.singleSelection)
  411.            return;
  412.          var c = this.currentIndex;
  413.          if (c == 0)
  414.            return;
  415.          var f = this.treeBoxObject.getFirstVisibleRow();
  416.          var i = 0;
  417.          if (f > 0) {
  418.            var p = this.treeBoxObject.getPageCount();
  419.            if (f - p >= 0)
  420.              i = c - p;
  421.            else
  422.              i = c - f;
  423.            this.treeBoxObject.scrollByPages(-1);
  424.          }
  425.          if (c == this.selectionTail) {
  426.            if (this.selectionHead < this.selectionTail) {
  427.              if (i < this.selectionHead) {
  428.                this.treeBoxObject.selection.clearRange(c, this.selectionHead + 1);
  429.                this.treeBoxObject.selection.rangedSelect(this.selectionHead - 1, i, true);
  430.              }
  431.              else {
  432.                this.treeBoxObject.selection.clearRange(c, i + 1);
  433.                this.currentIndex = i;
  434.              }
  435.            }
  436.            else
  437.              this.treeBoxObject.selection.rangedSelect(c - 1, i, true);
  438.          }
  439.          else {
  440.            this.treeBoxObject.selection.clearSelection();
  441.            this.selectionHead = c;
  442.            this.treeBoxObject.selection.rangedSelect(c, i, true);
  443.          }
  444.          this.selectionTail = i;
  445.         ]]>
  446.       </handler>
  447.       <handler event="keypress" keycode="vk_page_down" modifiers="shift">
  448.         <![CDATA[
  449.          if (this.singleSelection)
  450.            return;
  451.          var c = this.currentIndex;
  452.          var l = this.treeBoxObject.view.rowCount - 1;
  453.          if (c == l)
  454.            return;
  455.          var f = this.treeBoxObject.getFirstVisibleRow();
  456.          var p = this.treeBoxObject.getPageCount();
  457.          var i = l;
  458.          var lastTopRowIndex = l - p;
  459.          if (f <= lastTopRowIndex) {
  460.            if (f + p <= lastTopRowIndex)
  461.              i = c + p;
  462.            else
  463.              i = lastTopRowIndex + c - f + 1;
  464.            this.treeBoxObject.scrollByPages(1);
  465.          }
  466.          if (c == this.selectionTail) {
  467.            if (this.selectionHead > this.selectionTail) {
  468.              if (i > this.selectionHead) {
  469.                this.treeBoxObject.selection.clearRange(c, this.selectionHead - 1);
  470.                this.treeBoxObject.selection.rangedSelect(this.selectionHead + 1, i, true);
  471.              }
  472.              else {
  473.                this.treeBoxObject.selection.clearRange(c, i - 1);
  474.                this.currentIndex = i;
  475.              }
  476.            }
  477.            else
  478.              this.treeBoxObject.selection.rangedSelect(c + 1, i, true);
  479.          }
  480.          else {
  481.            this.treeBoxObject.selection.clearSelection();
  482.            this.selectionHead = c;
  483.            this.treeBoxObject.selection.rangedSelect(c, i, true);
  484.          }
  485.          this.selectionTail = i;
  486.         ]]>
  487.       </handler>
  488.       <handler event="keypress" keycode="vk_page_up" modifiers="control">
  489.         <![CDATA[
  490.          var c = this.currentIndex;
  491.          if (c == 0)
  492.            return;
  493.          var f = this.treeBoxObject.getFirstVisibleRow();
  494.          var i = 0;
  495.          if (f > 0) {
  496.            var p = this.treeBoxObject.getPageCount();
  497.            if (f - p >= 0)
  498.              i = c - p;
  499.            else
  500.              i = c - f;
  501.            this.treeBoxObject.scrollByPages(-1);
  502.          }
  503.          this.currentIndex = i;
  504.         ]]>
  505.       </handler>
  506.       <handler event="keypress" keycode="vk_page_down" modifiers="control">
  507.         <![CDATA[
  508.          var c = this.currentIndex;
  509.          var l = this.treeBoxObject.view.rowCount - 1;
  510.          if (c == l)
  511.            return;
  512.          var f = this.treeBoxObject.getFirstVisibleRow();
  513.          var p = this.treeBoxObject.getPageCount();
  514.          var i = l;
  515.          var lastTopRowIndex = l - p;
  516.          if (f <= lastTopRowIndex) {
  517.            if (f + p <= lastTopRowIndex)
  518.              i = c + p;
  519.            else
  520.              i = lastTopRowIndex + c - f + 1;
  521.            this.treeBoxObject.scrollByPages(1);
  522.          }
  523.          this.currentIndex = i;
  524.         ]]>
  525.       </handler>
  526.       <handler event="keypress" keycode="vk_home">
  527.         <![CDATA[
  528.          if (this.currentIndex == 0)
  529.            return;
  530.          this.selectionHead = -1;
  531.          this.selectionTail = -1;
  532.          this.treeBoxObject.selection.select(0);
  533.          this.treeBoxObject.ensureRowIsVisible(0);
  534.         ]]>
  535.       </handler>
  536.       <handler event="keypress" keycode="vk_end">
  537.         <![CDATA[
  538.          var l = this.treeBoxObject.view.rowCount - 1;
  539.          if (this.currentIndex == l)
  540.            return;
  541.          this.selectionHead = -1;
  542.          this.selectionTail = -1;
  543.          this.treeBoxObject.selection.select(l);
  544.          this.treeBoxObject.ensureRowIsVisible(l);
  545.         ]]>
  546.       </handler>
  547.       <handler event="keypress" keycode="vk_home" modifiers="shift">
  548.         <![CDATA[
  549.          if (this.singleSelection)
  550.            return;
  551.          var c = this.currentIndex;
  552.          if (c == 0)
  553.            return;
  554.          if (c != this.selectionTail) {
  555.            this.treeBoxObject.selection.clearSelection();
  556.            this.selectionHead = c;
  557.          }
  558.          this.treeBoxObject.selection.rangedSelect(c, 0, true);
  559.          this.selectionTail = 0;
  560.          this.treeBoxObject.ensureRowIsVisible(0);
  561.         ]]>
  562.       </handler>
  563.       <handler event="keypress" keycode="vk_end" modifiers="shift">
  564.         <![CDATA[
  565.          if (this.singleSelection)
  566.            return;
  567.          var c = this.currentIndex;
  568.          var l = this.treeBoxObject.view.rowCount - 1;
  569.          if (c == l)
  570.            return;
  571.          if (c != this.selectionTail) {
  572.            this.treeBoxObject.selection.clearSelection();
  573.            this.selectionHead = c;
  574.          }
  575.          this.treeBoxObject.selection.rangedSelect(c, l, true);
  576.          this.selectionTail = l;
  577.          this.treeBoxObject.ensureRowIsVisible(l);
  578.         ]]>
  579.       </handler>
  580.       <handler event="keypress" keycode="vk_home" modifiers="control">
  581.         <![CDATA[
  582.          if (this.currentIndex == 0)
  583.            return;
  584.          this.currentIndex = 0;
  585.          this.treeBoxObject.ensureRowIsVisible(0);
  586.         ]]>
  587.       </handler>
  588.       <handler event="keypress" keycode="vk_end" modifiers="control">
  589.         <![CDATA[
  590.          var l = this.treeBoxObject.view.rowCount - 1;
  591.          if (this.currentIndex == l)
  592.            return;
  593.          this.currentIndex = l;
  594.          this.treeBoxObject.ensureRowIsVisible(l);
  595.         ]]>
  596.       </handler>
  597.       <handler event="keypress">
  598.         <![CDATA[
  599.          var c = this.currentIndex;
  600.          if (event.keyCode == ' '.charCodeAt(0)) {
  601.            if (!this.treeBoxObject.selection.isSelected(c))
  602.              this.treeBoxObject.selection.toggleSelect(c);
  603.          }
  604.          else if (!this.disableKeyNavigation && event.charCode > 0 &&
  605.                   !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey) {
  606.            var key = String.fromCharCode(event.charCode);
  607.            key = key.toLowerCase();
  608.            if (event.timeStamp - this._lastKeyTime > 1000)
  609.              this._incrementalString = key;
  610.            else {
  611.              if (this._incrementalString.length != 1 || this._incrementalString.charAt(0) != key.charAt(0))
  612.                this._incrementalString += key;
  613.            }
  614.            this._lastKeyTime = event.timeStamp;
  615.            
  616.            var primarycol = this.treeBoxObject.getKeyColumnIndex();
  617.            var colID = this.treeBoxObject.getColumnID(primarycol);
  618.            var rowCount = this.treeBoxObject.view.rowCount;
  619.            var start = 1;
  620.            
  621.            if (this._incrementalString.length > 1) {
  622.              start = 0;
  623.              if (c < 0)
  624.                c = 0;
  625.            }
  626.  
  627.            for (var i = 0; i < rowCount; i++) {
  628.              var l = (i + start + c) % rowCount;
  629.              var cellText = this.treeBoxObject.view.getCellText(l, colID);
  630.              cellText = cellText.toLowerCase();
  631.              if (cellText.search(this._incrementalString) == 0) {
  632.                this.selectionHead = -1;
  633.                this.selectionTail = -1;
  634.                this.treeBoxObject.selection.timedSelect(l, this._selectDelay);
  635.                this.treeBoxObject.ensureRowIsVisible(l);
  636.                break;
  637.              }
  638.            }
  639.           }
  640.          ]]>
  641.       </handler>
  642.     </handlers>    
  643.   </binding>
  644.  
  645.   <binding id="treecols" extends="chrome://global/content/bindings/tree.xml#tree-base">
  646.     <content>
  647.       <children includes="treecol|splitter"/>
  648.       <xul:treecolpicker class="treecol-image" fixed="true" ordinal="2147483647"/>
  649.     </content>
  650.     <implementation implements="nsIAccessibleProvider">
  651.       <property name="accessible">
  652.         <getter>
  653.           <![CDATA[
  654.             var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
  655.             return accService.createXULTreeColumnsAccessible(this);
  656.           ]]>
  657.         </getter>
  658.       </property>
  659.     </implementation>
  660.   </binding>
  661.  
  662.   <binding id="treerows" extends="chrome://global/content/bindings/tree.xml#tree-base">
  663.     <content>
  664.       <xul:hbox flex="1" class="tree-bodybox">
  665.         <children/>
  666.       </xul:hbox>
  667.       <xul:scrollbar height="0" minwidth="0" minheight="0" orient="vertical" class="tree-scrollbar" collapsed="true"/>
  668.     </content>
  669.     <handlers>
  670.       <handler event="underflow">
  671.         <![CDATA[
  672.           document.getAnonymousNodes(this)[1].collapsed = true;
  673.           event.preventBubble();
  674.         ]]>
  675.       </handler>
  676.       <handler event="overflow">
  677.         <![CDATA[
  678.           document.getAnonymousNodes(this)[1].collapsed = false;
  679.           event.preventBubble();
  680.         ]]>
  681.       </handler>
  682.     </handlers>
  683.   </binding>
  684.  
  685.   <binding id="treebody" extends="chrome://global/content/bindings/tree.xml#tree-base">
  686.     <implementation>
  687.       <constructor>
  688.         if ("_ensureColumnOrder" in this.parentNode)
  689.           this.parentNode._ensureColumnOrder();
  690.       </constructor>
  691.  
  692.       <field name="_lastSelectedRow">
  693.         -1
  694.       </field>
  695.     </implementation>
  696.     <handlers>
  697.       <!-- If there is no modifier key, we select on mousedown, not
  698.            click, so that drags work correctly. -->
  699.       <handler event="mousedown">
  700.       <![CDATA[
  701.          if ((!event.ctrlKey && !event.shiftKey && !event.metaKey) ||
  702.              this.parentNode.singleSelection) {
  703.            var row = {};
  704.            var col = {};
  705.            var obj = {};
  706.            var b = this.parentNode.treeBoxObject;
  707.            b.getCellAt(event.clientX, event.clientY, row, col, obj);
  708.  
  709.            // save off the last selected row
  710.            this._lastSelectedRow = row.value;
  711.  
  712.            if (row.value == -1)
  713.              return;
  714.  
  715.            if (col.value && obj.value != "twisty") {
  716.              var column = document.getElementById(col.value);
  717.              var cycler = column.hasAttribute('cycler');
  718.  
  719.              if (cycler)
  720.                b.view.cycleCell(row.value, col.value);
  721.              else
  722.                  if (!b.selection.isSelected(row.value)) {
  723.                  b.selection.select(row.value);
  724.                  b.ensureRowIsVisible(row.value);
  725.                }
  726.            }
  727.          }
  728.       ]]>
  729.       </handler>
  730.  
  731.       <!-- On a click (up+down on the same item), deselect everything
  732.            except this item. -->
  733.       <handler event="click">
  734.       <![CDATA[
  735.         if (event.button != 0) return;
  736.         var row = {};
  737.         var col = {};
  738.         var obj = {};
  739.         var b = this.parentNode.treeBoxObject;
  740.         b.getCellAt(event.clientX, event.clientY, row, col, obj);
  741.  
  742.         if (row.value == -1)
  743.           return;
  744.  
  745.         if (obj.value == "twisty") {
  746.           if (b.selection.currentIndex >= 0 &&
  747.               b.view.isContainerOpen(row.value)) {
  748.             var parentIndex = b.view.getParentIndex(b.selection.currentIndex);
  749.             while (parentIndex >= 0 && parentIndex != row.value)
  750.               parentIndex = b.view.getParentIndex(parentIndex);
  751.             if (parentIndex == row.value)
  752.               b.selection.select(parentIndex);
  753.           }
  754.           b.view.toggleOpenState(row.value);
  755.           return;
  756.         }
  757.  
  758.         if (! this.parentNode.singleSelection) {
  759.           var augment = event.ctrlKey || event.metaKey;
  760.           if (event.shiftKey) {
  761.             b.selection.rangedSelect(-1, row.value, augment);
  762.             b.ensureRowIsVisible(row.value);
  763.             return;
  764.           }
  765.           if (augment) {
  766.             b.selection.toggleSelect(row.value);
  767.             b.ensureRowIsVisible(row.value);
  768.             b.selection.currentIndex = row.value;
  769.             return;
  770.           }
  771.         }
  772.  
  773.         /* We want to deselect all the selected items except what was
  774.           clicked, UNLESS it was a right-click.  We have to do this
  775.           in click rather than mousedown so that you can drag a
  776.           selected group of items */
  777.  
  778.         if (!col.value) return;
  779.         var column = document.getElementById(col.value);
  780.         var cycler = column.hasAttribute('cycler');
  781.  
  782.         // if the last row has changed in between the time we 
  783.         // mousedown and the time we click, don't fire the select handler.
  784.         // see bug #92366
  785.         if (!cycler && this._lastSelectedRow == row.value) {
  786.           b.selection.select(row.value);  
  787.           b.ensureRowIsVisible(row.value);
  788.         }
  789.       ]]>
  790.       </handler>
  791.  
  792.       <!-- double-click -->
  793.       <handler event="click" clickcount="2">
  794.       <![CDATA[
  795.            var row = {};
  796.            var col = {};
  797.            var obj = {};
  798.            var b = this.parentNode.treeBoxObject;
  799.            b.getCellAt(event.clientX, event.clientY, row, col, obj);
  800.  
  801.            if (row.value == -1)
  802.              return;
  803.  
  804.            var column = document.getElementById(col.value);
  805.            var cycler = column.hasAttribute('cycler');
  806.  
  807.            if (!cycler && obj.value != "twisty" && b.view.isContainer(row.value))
  808.              b.view.toggleOpenState(row.value);
  809.       ]]>
  810.       </handler>
  811.       
  812.     </handlers>
  813.   </binding>
  814.  
  815.   <binding id="treecol-base" extends="chrome://global/content/bindings/tree.xml#tree-base">
  816.     <implementation>
  817.       <constructor>
  818.         this.parentNode.parentNode._columnsDirty = true;
  819.       </constructor>
  820.  
  821.       <property name="ordinal">
  822.         <getter><![CDATA[
  823.           var val = this.getAttribute("ordinal");
  824.           return val == "" ? 1 : (val == "0" ? 0 : parseInt(val));
  825.         ]]></getter>
  826.         <setter><![CDATA[
  827.           this.setAttribute("ordinal", val);
  828.         ]]></setter>
  829.       </property>
  830.       
  831.       <property name="_previousVisibleColumn">
  832.         <getter><![CDATA[
  833.           var sib = this.boxObject.previousSibling;
  834.           while (sib) {
  835.             if (sib.localName == "treecol" && sib.boxObject.width > 0 && sib.parentNode == this.parentNode)
  836.               return sib;
  837.             sib = sib.boxObject.previousSibling;
  838.           }
  839.           return null;
  840.         ]]></getter>
  841.       </property>
  842.  
  843.       <method name="onDragMouseMove">
  844.         <parameter name="aEvent"/>
  845.         <body><![CDATA[
  846.           var col = document.treecolDragging;
  847.           if (!col) return;
  848.  
  849.           // determine if we have moved the mouse far enough
  850.           // to initiate a drag
  851.           if (col.mDragGesturing) {
  852.             if (Math.abs(aEvent.clientX - col.mStartDragX) < 5 &&
  853.                 Math.abs(aEvent.clientY - col.mStartDragY) < 5) {
  854.               return;
  855.             } else {
  856.               col.mDragGesturing = false;
  857.               col.setAttribute("dragging", "true");
  858.               window.addEventListener("click", col.onDragMouseClick, true);
  859.             }
  860.           }
  861.                     
  862.           var pos = {};
  863.           var targetCol = col.parentNode.parentNode._getColumnAtX(aEvent.clientX, 0.5, pos);
  864.           
  865.           // bail if we haven't mousemoved to a different column
  866.           if (col.mTargetCol == targetCol && col.mTargetDir == pos.value)
  867.             return;
  868.  
  869.           var tree = col.parentNode.parentNode;
  870.           var sib;
  871.           if (col.mTargetCol) {
  872.             // remove previous insertbefore/after attributes
  873.             col.mTargetCol.removeAttribute("insertbefore");
  874.             col.mTargetCol.removeAttribute("insertafter");
  875.             tree.treeBoxObject.invalidateColumn(col.mTargetCol.id);
  876.             sib = col.mTargetCol._previousVisibleColumn;
  877.             if (sib) {
  878.               sib.removeAttribute("insertafter");
  879.               tree.treeBoxObject.invalidateColumn(sib.id);
  880.             }
  881.             col.mTargetCol = null;
  882.             col.mTargetDir = null;
  883.           }
  884.           
  885.           if (targetCol) {
  886.             // set insertbefore/after attributes
  887.             if (pos.value == "after") {
  888.               targetCol.setAttribute("insertafter", "true");
  889.             } else {
  890.               targetCol.setAttribute("insertbefore", "true");
  891.               sib = targetCol._previousVisibleColumn;
  892.               if (sib) {
  893.                 sib.setAttribute("insertafter", "true");
  894.                 tree.treeBoxObject.invalidateColumn(sib.id);
  895.               }
  896.             }
  897.             tree.treeBoxObject.invalidateColumn(targetCol.id);
  898.             col.mTargetCol = targetCol;
  899.             col.mTargetDir = pos.value;
  900.           }
  901.         ]]></body>        
  902.       </method>
  903.  
  904.       <method name="onDragMouseUp">
  905.         <parameter name="aEvent"/>
  906.         <body><![CDATA[
  907.           var col = document.treecolDragging;
  908.           if (!col) return;
  909.           
  910.           if (!col.mDragGesturing) {
  911.             if (col.mTargetCol) {
  912.               // remove insertbefore/after attributes
  913.               var before = col.mTargetCol.hasAttribute("insertbefore");
  914.               col.mTargetCol.removeAttribute(before ? "insertbefore" : "insertafter");
  915.               if (before) {
  916.                 var sib = col.mTargetCol._previousVisibleColumn;
  917.                 if (sib)
  918.                   sib.removeAttribute("insertafter");
  919.               }
  920.                           
  921.               // move the column
  922.               if (col != col.mTargetCol)
  923.                 col.parentNode.parentNode._reorderColumn(col, col.mTargetCol, before);
  924.             
  925.               // repaint to remove lines
  926.               col.parentNode.parentNode.treeBoxObject.invalidate();
  927.   
  928.               col.mTargetCol = null;
  929.             }
  930.           } else
  931.             col.mDragGesturing = false;
  932.                     
  933.           document.treecolDragging = null;
  934.           col.removeAttribute("dragging");
  935.           
  936.           window.removeEventListener("mousemove", col.onDragMouseMove, true);
  937.           window.removeEventListener("mouseup", col.onDragMouseUp, true);
  938.           // we have to wait for the click event to fire before removing
  939.           // cancelling handler
  940.           var clickHandler = function(handler) { 
  941.             window.removeEventListener("click", handler, true);
  942.           };
  943.           window.setTimeout(clickHandler, 0, col.onDragMouseClick);
  944.         ]]></body>        
  945.       </method>
  946.  
  947.       <method name="onDragMouseClick">
  948.         <parameter name="aEvent"/>
  949.         <body><![CDATA[
  950.           // prevent click event from firing after column drag and drop
  951.           aEvent.preventBubble();
  952.           aEvent.preventDefault();
  953.         ]]></body>        
  954.       </method>
  955.     </implementation>
  956.     
  957.     <handlers>
  958.       <handler event="mousedown" button="0"><![CDATA[
  959.         if (this.parentNode.parentNode.enableColumnDrag) {
  960.           var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  961.           var cols = this.parentNode.getElementsByTagNameNS(xulns, "treecol");
  962.           
  963.           // only start column drag operation if there are at least 2 visible columns
  964.           var visible = 0;
  965.           for (var i = 0; i < cols.length; ++i)
  966.             if (cols[i].boxObject.width > 0) ++visible;
  967.             
  968.           if (visible > 1) {
  969.             window.addEventListener("mousemove", this.onDragMouseMove, false);
  970.             window.addEventListener("mouseup", this.onDragMouseUp, false);
  971.             document.treecolDragging = this;
  972.             this.mDragGesturing = true;
  973.             this.mStartDragX = event.clientX;
  974.             this.mStartDragY = event.clientY;
  975.           }
  976.         }
  977.       ]]></handler>
  978.     </handlers>
  979.   </binding>
  980.  
  981.   <binding id="treecol" extends="chrome://global/content/bindings/tree.xml#treecol-base">
  982.     <content>
  983.       <xul:label class="treecol-text" xbl:inherits="crop,value=label" flex="1" crop="right"/>
  984.       <xul:image class="treecol-sortdirection" xbl:inherits="sortDirection"/>
  985.     </content>
  986.     <implementation implements="nsIAccessibleProvider">
  987.       <property name="accessible">
  988.         <getter>
  989.           <![CDATA[
  990.             var accService = Components.classes["@mozilla.org/accessibilityService;1"].getService(Components.interfaces.nsIAccessibilityService);
  991.             return accService.createXULTreeColumnitemAccessible(this);
  992.           ]]>
  993.         </getter>
  994.       </property>
  995.     </implementation>
  996.  
  997.     <handlers>
  998.       <handler event="click" button="0" action="if (event.originalTarget == this) { this.parentNode.parentNode.treeBoxObject.view.cycleHeader(this.id, this); }"/>
  999.     </handlers>
  1000.   </binding>
  1001.  
  1002.   <binding id="treecol-image" extends="chrome://global/content/bindings/tree.xml#treecol-base">
  1003.     <content>
  1004.       <xul:image class="treecol-icon" xbl:inherits="src"/>
  1005.     </content>
  1006.     <handlers>
  1007.       <handler event="click" button="0" action="this.parentNode.parentNode.treeBoxObject.view.cycleHeader(this.id, this)"/>
  1008.     </handlers>
  1009.   </binding>
  1010.  
  1011.   <binding id="columnpicker" display="xul:button"
  1012.            extends="chrome://global/content/bindings/tree.xml#tree-base">
  1013.     <content>
  1014.       <xul:image class="tree-columnpicker-icon"/>
  1015.       <xul:menupopup anonid="popup"/>
  1016.     </content>
  1017.     
  1018.     <implementation>
  1019.       <method name="buildPopup">
  1020.         <parameter name="aPopup"/>
  1021.         <body>
  1022.           <![CDATA[
  1023.             // we no longer cache the picker content.
  1024.             // remove the old content
  1025.             while (aPopup.hasChildNodes())
  1026.               aPopup.removeChild(aPopup.lastChild);
  1027.  
  1028.             for (var currCol = this.parentNode.firstChild; currCol; currCol = currCol.nextSibling) {
  1029.               // Construct an entry for each column in the row, unless
  1030.               // it is not being shown
  1031.               if (currCol.localName == "treecol" && !currCol.hasAttribute("ignoreincolumnpicker")) {
  1032.                 var popupChild = document.createElement("menuitem");
  1033.                 popupChild.setAttribute("type", "checkbox");
  1034.                 var columnName = currCol.getAttribute("display") || currCol.getAttribute("label");
  1035.                 popupChild.setAttribute("label", columnName);
  1036.                 popupChild.setAttribute("colid", currCol.id);
  1037.                 if (currCol.getAttribute("hidden") != "true")
  1038.                   popupChild.setAttribute("checked", "true");
  1039.                 if (currCol.getAttribute("primary") == "true")
  1040.                   popupChild.setAttribute("disabled", "true");
  1041.                 aPopup.appendChild(popupChild);
  1042.               }
  1043.             }
  1044.           ]]>
  1045.         </body>
  1046.       </method>
  1047.     </implementation>
  1048.  
  1049.     <handlers>
  1050.       <handler event="command">
  1051.         <![CDATA[
  1052.           if (event.originalTarget == this) {
  1053.             var popup = document.getAnonymousElementByAttribute(this, "anonid", "popup");
  1054.             this.buildPopup(popup);
  1055.             popup.showPopup(this, -1, -1, "popup", "bottomright", "topright");
  1056.           } else {
  1057.             var colid = event.originalTarget.getAttribute("colid");
  1058.             var colNode = document.getElementById(colid);
  1059.             if (colNode) {
  1060.               if (colNode.getAttribute("hidden") == "true")
  1061.                 colNode.setAttribute("hidden", "false");
  1062.               else
  1063.                 colNode.setAttribute("hidden", "true");
  1064.             }
  1065.           }
  1066.         ]]>
  1067.       </handler>
  1068.     </handlers>
  1069.   </binding>
  1070. </bindings>
  1071.  
  1072.