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