/*
 * $Id: xbTreeNode.js,v 1.9 2003/09/14 21:22:27 bc Exp $
 *
 */

// tree data structure modeled after the W3C DOM Node object.

/* ***** BEGIN LICENSE BLOCK *****
 * The contents of this file are subject to the Mozilla Public License Version 
 * 1.1 (the "License"); you may not use this file except in compliance with 
 * the License. You may obtain a copy of the License at 
 * http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Bob Clary code.
 *
 * The Initial Developer of the Original Code is
 * Bob Clary.
 * Portions created by the Initial Developer are Copyright (C) 2000
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Bob Clary <http://bclary.com/>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 * 
 ***** END LICENSE BLOCK ***** */

_classes.registerClass('xbTreeNode');

function xbTreeNode()
{
  _classes.defineClass('xbTreeNode', _prototype_func);

  this.init();

  function _prototype_func()
  {
    xbTreeNode.prototype.parentNode      = null;
    xbTreeNode.prototype.firstChild      = null;
    xbTreeNode.prototype.lastChild      = null;
    xbTreeNode.prototype.childNodes      = null;
    xbTreeNode.prototype.previousSibling  = null;
    xbTreeNode.prototype.nextSibling    = null;
    

    xbTreeNode.prototype.init = init;
    function init()
    {
      this.parentMethod('init');
      this.childNodes = new xbArray();    
    };
    
    xbTreeNode.prototype.destroy = destroy;
    function destroy()
    {
      if (this.childNodes)
        this.childNodes.destroy();
       /* 
      this.parentNode      = null;
      this.firstChild      = null;
      this.lastChild      = null;
      this.previousSibling  = null;
      this.nextSibling    = null;
      this.childNodes      = null;
      */
      delete this.parentNode;
      delete this.firstChild;
      delete this.lastChild;
      delete this.previousSibling;
      delete this.nextSibling;
      delete this.childNodes;
      
      this.parentMethod('destroy');
    }
    
    xbTreeNode.prototype.appendChild = appendChild;
    function appendChild(newChild)
    {
      var oldLastChild = this.lastChild;
      
      this.childNodes.push(newChild);

      if (!this.firstChild)
        this.firstChild = newChild;
          
      if (this.lastChild)
        this.lastChild.nextSibling = newChild;
          
      this.lastChild = newChild;
          
      newChild.parentNode = this;
      newChild.previousSibling = oldLastChild;
      newChild.nextSibling     = null;
      
      return newChild;
    }
    
    xbTreeNode.prototype.insertBefore = insertBefore;
    function insertBefore(newChild, refChild)
    {
      if (!refChild)
      {
        this.appendChild(newChild);
        return newChild;
      }

      var parentNode = newChild.parentNode;
      if (parentNode)
      {
        parentNode.removeChild(newChild);
      }
        
      var ok            = false;
      var tmpChildNodes = new xbArray();
    
      while (this.childNodes.length > 0)
      {
        var tmpChild = this.childNodes.shift();
        if (tmpChild == refChild)
        {
          tmpChildNodes.push(newChild);
          newChild.nextSibling = refChild;
          newChild.previousSibling = refChild.previousSibling;
          refChild.previousSibling = newChild;
          newChild.parentNode = this;
          ok = true;
        }
        tmpChildNodes.push(tmpChild);
      }

      if (!ok)
        throw(new xbException('Not found Error', 'TreeNode.js', 'insertBefore'));
        
      this.childNodes = tmpChildNodes;
      this.firstChild = this.childNodes.item(0);
      this.lastChild = this.childNodes.item(this.childNodes.length-1);
    
      return newChild;
    }
    
    xbTreeNode.prototype.removeChild = removeChild;
    function removeChild(oldChild)
    {
      var ok = false;
      var tmpChildNodes = new xbArray();
    
      while (this.childNodes.length > 0)
      {
        var tmpChild = this.childNodes.shift();
        if (tmpChild == oldChild)
        {
          if (oldChild.nextSibling)
            oldChild.nextSibling.previousSibling = oldChild.previousSibling;
            
          if (oldChild.previousSibling)
            oldChild.previousSibling.nextSibling = oldChild.nextSibling;
        
          ok = true;
        }
        else
          tmpChildNodes.push(tmpChild);
      }
      
      if (!ok)
        throw(new xbException('Not found Error', 'TreeNode.js', 'removeChild'));

        
      this.childNodes     = tmpChildNodes;

      if (this.childNodes.length == 0)
      {
        this.firstChild = null;
        this.lastChild  = null;
      }
      else
      {
        this.firstChild = this.childNodes.item(0);
        this.lastChild = this.childNodes.item(this.childNodes.length-1);
      }
      
      oldChild.parentNode = null;
      oldChild.previousSibling = null;
      oldChild.nextSibling = null;
    
      return oldChild;
    }
    
    xbTreeNode.prototype.replaceChild = replaceChild;
    function replaceChild(newChild, oldChild)
    {
      var tmpChildNodes = new xbArray();
    
      if (!newChild)
      {
        this.removeChild(oldChild);
        return oldChild;
      }
      
      var parentNode = newChild.parentNode;
      if (parentNode)
      {
        parentNode.removeChild(newChild);
      }
        
      var ok = false;
      
      while (this.childNodes.length > 0)
      {
        var tmpChild = this.childNodes.shift();
        if (tmpChild == oldChild)
        {
          newChild.nextSibling = oldChild.nextSibling;
          newChild.previousSibling = oldChild.previousSibling;
          if (newChild.nextSibling)
            newChild.nextSibling.previousSibling = newChild;
          if (newChild.previousSibling)
            newChild.previousSibling.nextSibling = newChild;

          tmpChildNodes.push(newChild);
          ok = true;
        }
        else
          tmpChildNodes.push(tmpChild);
      }
      
      if (!ok)
        throw(new xbException('Not found Error', 'TreeNode.js', 'replaceChild'));

        
      this.childNodes = tmpChildNodes;
      this.firstChild = this.childNodes.item(0);
      this.lastChild  = this.childNodes.item(this.childNodes.length-1);
      
      oldChild.parentNode = null;
    
      return oldChild;
    }
    
    xbTreeNode.prototype.getRoot = getRoot;
    function getRoot()
    {
      var root = this;
      
      while (root.parentNode)
        root = root.parentNode;
        
      return root;
    }
  }
}
// eof: xbTreeNode.js
//</SCRIPT>

