<?xml version="1.0"?>

<bindings id="treeBindings"
   xmlns="http://www.mozilla.org/xbl"
   xmlns:html="http://www.w3.org/1999/xhtml"
   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  
  <binding id="treeitem">
    <interface>
      <method name="toggleOpenState">
        <body>
          <![CDATA[
            if ((this.getAttribute('container') == 'true') &&
                 (this.getAttribute('empty') != 'true')) {
               if (this.getAttribute('open') == 'true')
                 this.removeAttribute('open');
               else this.setAttribute('open', 'true');
            }
          ]]>
        </body>
      </method>
     <method name="open">
       <body>
          <![CDATA[
            if ((this.getAttribute('container') == 'true') &&
                 (this.getAttribute('empty') != 'true')) {
               if (this.getAttribute('open') != 'true')
                 this.setAttribute('open', 'true');
            }
          ]]>
        </body>
     </method>
     <method name="close">
       <body>
          <![CDATA[
            if ((this.getAttribute('container') == 'true') &&
                 (this.getAttribute('empty') != 'true')) {
               if (this.getAttribute('open') == 'true')
                 this.removeAttribute('open');
            }
          ]]>
        </body>
     </method>    
   </interface>
  </binding>     

  <binding id="treecell-indented-folder">
    <content autostretch="never">
      <xul:treeindentation/>
      <xul:image class="tree-cell-twisty" twisty="true" allowevents="true"/>
      <xul:image class="tree-cell-primary-icon" inherits="src"/>
      <xul:text class="tree-cell-text" inherits="crop,value,align" flex="1" crop="right"/>
    </content>
  </binding>
  
  <binding id="treecell-indented-leaf">
    <content autostretch="never">
      <xul:treeindentation/>
      <xul:image class="tree-cell-primary-icon" inherits="src"/>
      <xul:text class="tree-cell-text" inherits="crop,value,align" flex="1" crop="right"/>
    </content>
  </binding>

  <binding id="treecell">
    <content autostretch="never">
      <xul:text class="tree-cell-text" inherits="crop,value,align" flex="1" crop="right"/>
    </content>
  </binding>

  <binding id="treecell-align-right">
    <content autostretch="never">
      <xul:spring flex="5"/>
      <xul:text class="tree-cell-text" inherits="crop,value,align" flex="1" crop="right"/>
    </content>
  </binding>

  <binding id="treecell-iconic">
    <content autostretch="never">
      <xul:image class="tree-cell-icon" inherits="src"/>
      <xul:text class="tree-cell-text" inherits="crop,value,align" flex="1" crop="right"/>
    </content>
  </binding>

  <binding id="treecell-image">
    <content autostretch="never">
      <xul:image class="tree-cell-image" inherits="src"/>
    </content>
  </binding>
 
  <binding id="treecell-header">
    <content autostretch="never">
      <xul:image class="tree-header-image" inherits="src"/>
      <xul:text class="tree-header-text" inherits="crop,value" flex="1" crop="right"/>
      <xul:image class="tree-header-sortdirection"/>
    </content>
  </binding>
  
  <binding id="tree">
    <content>
      <children/>
      <xul:treerows class="tree-container-treerows">
        <children includes="treehead,treechildren"/>
      </xul:treerows> 
    </content>
    <interface>
      <property name="treeBoxObject"
                onget="return this.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);"
                readonly="true"/>
      <method name="getNextItem">
        <argument name="startItem"/>
        <argument name="delta"/>
        <body>
          return this.treeBoxObject.getNextItem(startItem, delta);
        </body>
      </method>
      <method name="getPreviousItem">
        <argument name="startItem"/>
        <argument name="delta"/>
        <body>
          return this.treeBoxObject.getPreviousItem(startItem, delta);
        </body>
      </method>
      <method name="getIndexOfItem">
        <argument name="item"/>
        <body>
          return this.treeBoxObject.getIndexOfItem(item);
        </body>
      </method>
      <method name="getItemAtIndex">
        <argument name="index"/>
        <body>
          return this.treeBoxObject.getItemAtIndex(index);
        </body>
      </method>
      <method name="ensureIndexIsVisible">
        <argument name="index"/>
        <body>
          return this.treeBoxObject.ensureIndexIsVisible(index);
        </body>
      </method>
      <method name="ensureElementIsVisible">
        <argument name="element"/>
        <body>
          return this.ensureIndexIsVisible(this.treeBoxObject.getIndexOfItem(element));
        </body>
      </method>
      <method name="scrollToIndex">
        <argument name="index"/>
        <body>
          return this.treeBoxObject.scrollToIndex(index);
        </body>
      </method>
      <method name="getNumberOfVisibleRows">
        <body>
          return this.treeBoxObject.getNumberOfVisibleRows();
        </body>
      </method>
      <method name="getIndexOfFirstVisibleRow">
        <body>
          return this.treeBoxObject.getIndexOfFirstVisibleRow();
        </body>
      </method>
    </interface>
    <handlers>
      <handler type="keypress" keycode="vk_enter">
        <![CDATA[
         if (event.target != this || selectedItems.length != 1)
           return;
         this.selectedItems[0].toggleOpenState();
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_return">
        <![CDATA[
         if (event.target != this || selectedItems.length != 1)
           return;
         this.selectedItems[0].toggleOpenState();
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_left">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
         this.selectedItems[0].close(); 
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_right">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
         this.selectedItems[0].open();
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_up">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
         var n = this.getPreviousItem(this.selectedItems[0], 1);
         if (n) {
           this.ensureIndexIsVisible(this.getIndexOfItem(this.selectedItems[0])-1);
           this.selectItem(n);
         }
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_down">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
         var n = this.getNextItem(this.selectedItems[0], 1);
         if (n) {
           this.ensureIndexIsVisible(this.getIndexOfItem(this.selectedItems[0])+1);
           this.selectItem(n);
         }
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_page_up">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
	 var i = this.getIndexOfFirstVisibleRow();
         var v = this.getNumberOfVisibleRows() - 1;
	 dump("IndexOfFirstVisibleRow: "+i+" NumberOfVisibleRows: "+v+"\n");
         var n = this.getPreviousItem(this.selectedItems[0], v);
         if (n) {
	   this.scrollToIndex(i-v);
           this.selectItem(n);
	 }
	 else {
	   this.scrollToIndex(0);
	   if ( i==0 )
             this.selectItem(this.getItemAtIndex(0));
	   else 
             this.selectItem(this.getItemAtIndex(this.getIndexOfItem(this.selectedItems[0]) - i));
	 }
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_page_down">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
	   return;
	 var i = this.getIndexOfFirstVisibleRow();
         var v = this.getNumberOfVisibleRows() - 1;
	 dump("IndexOfFirstVisibleRow: "+i+" NumberOfVisibleRows: "+v+"\n");
         var n = this.getNextItem(this.selectedItems[0], v);
         if (n) {
           this.scrollToIndex(i+v);
           this.selectItem(n);
         }
	 else {
	   var e = this.getElementsByTagName("treechildren");
	   var e = e[0].lastChild;
	   this.selectItem(e);
	 }
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_home">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
	 this.scrollToIndex(0);
         this.selectItem(this.getItemAtIndex(0));
        ]]>
      </handler>
      <handler type="keypress" keycode="vk_end">
        <![CDATA[
         if (event.target != this || this.selectedItems.length != 1)
           return;
	 var e = this.getElementsByTagName("treechildren");
	 var e = e[0].lastChild;
         var v = this.getNumberOfVisibleRows();
	 var i = this.getIndexOfItem(e)-v;
	 if ( i < 0 )
	   i=0;
	 this.scrollToIndex(i);
	 this.selectItem(e);
        ]]>
      </handler>
    </handlers>    
  </binding>

  <binding id="treerows">
    <content flex="1"/>
    <handlers>
      <!-- If there is no modifier key, we select on mousedown, not
           click, so that drags work correctly. -->
      <handler type="mousedown" shift="false" control="false">
      <![CDATA[
         if (event.target.localName == 'treecell') {
           var isSelected = event.target.parentNode.parentNode.getAttribute("selected");
           if (!isSelected) {
             parentNode.selectItem(event.target.parentNode.parentNode);
           }
           parentNode.currentItem = event.target.parentNode.parentNode;
         }
      ]]>
      </handler>

      <!-- On a click (up+down on the same item), deselect everything
           except this item. -->
      <handler type="click" shift="false" control="false">
      <![CDATA[
         if (event.target.localName == 'treecell') {
           var selectedItems = parentNode.selectedItems;
           var i = 0;
           while (i < selectedItems.length) {
             if (selectedItems[i] != event.target.parentNode.parentNode)
               parentNode.removeItemFromSelection(selectedItems[i]);
             else
               i++;
            }
         }
      ]]>
      </handler>

      <handler type="click" shift="false" control="true">
      <![CDATA[
         if (event.target.localName == 'treecell') {
           parentNode.toggleItemSelection(event.target.parentNode.parentNode);
           parentNode.currentItem = event.target.parentNode.parentNode;
         }
      ]]>
      </handler>

      <handler type="click" shift="true" control="false">
      <![CDATA[
         if (event.target.localName == 'treecell') {
           parentNode.selectItemRange(null, event.target.parentNode.parentNode);
           parentNode.currentItem = event.target.parentNode.parentNode;
          }
      ]]>
      </handler>
      <handler type="click" shift="false" control="false" clickcount="2">
      <![CDATA[
         if (event.target.localName == 'treecell') {
           var n = event.target.parentNode.parentNode;
           n.toggleOpenState();
         }
      ]]>
      </handler>
      <handler type="click" shift="false" control="false">
      <![CDATA[
         if (event.target.getAttribute('twisty') == 'true') {
           var n = event.target.parentNode.parentNode.parentNode;
           n.toggleOpenState();
         }
      ]]>
      </handler>
      
    </handlers>
  </binding>
 
  
              
  <binding id="listbox" extends="xul:tree">
    <content>
      <xul:cols>
        <xul:col flex="1"/>
      </xul:cols>
      <xul:treerows>
        <xul:treerows>
          <children includes="listhead"/>
          <xul:treechildren>
            <children/>
          </xul:treechildren>
        </xul:treerows>
      </xul:treerows> 
    </content>    
  </binding>

  <binding id="listhead" extends="xul:treehead">
    <content>
      <xul:treerow>
        <xul:treecell inherits="value" class="listcell-header"/>
      </xul:treerow>
    </content>
  </binding>

  <binding id="listitem" extends="xul:treeitem">
    <content>
      <xul:treerow>
        <xul:treecell inherits="value" class="listcell-text"/>
      </xul:treerow>
    </content>
  </binding>

</bindings>

