//------------------------------------------------------------------------------
// CLASS Node
//------------------------------------------------------------------------------
//
	function Node(id,val,espanso,info,link) {
		this.id = id ;
		this.value = val ;
		this.espanso = espanso ? true : false ;
		this.figli = new Array() ;
		this.selezionato = false ;
		this.info = info ;
		this.link = link ;
	}
	
	Node.prototype.equals = function(node) {
		if(node)
			return this.id==node.id ;
		else
			return false ;
	}
	
	Node.prototype.getHeight = function() {
		var ret = 1 ;
		var i ;
		for(i=0;i<this.figli.length;i++)
			ret = Math.max(ret,1+this.figli[i].getHeight()) ;
		return ret ;
	}
	
	Node.prototype.isAnchestor = function(node) {
		var ret = false ;
		var i ;
		for(i=0;i<this.figli.length;i++) {
			ret = ret || this.figli[i].equals(node) ;
			ret = ret || this.figli[i].isAnchestor(node) ;
		}
		return ret ;
	}

	Node.prototype.setId = function(newid) {
	    this.id = newid ;
	}

//
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
// CLASS Tree
//------------------------------------------------------------------------------
//
// Gestione albero
//
// Francesco Gabbrielli
// v1.0 - 25/03/05
//
//------------------------------------------------------------------------------
//
	function Tree(root,ui) {
		this.root = root ;
		this.ui = ui ;
		this.nodes = new Array() ;
		this.nodes.push(root) ;
		this.removed = new Array() ;

		this.selectListeners = new Array() ;
		this.selectListenerObjects = new Array() ;
		this.expandListeners = new Array() ;
		this.expandListenerObjects = new Array() ;
		this.infoListeners = new Array() ;
		this.infoListenerObjects = new Array() ;
		this.linkListeners = new Array() ;
		this.linkListenerObjects = new Array() ;
		
		this.rootVisible = true ;
		this.selectNode(root.id) ;
		this.active = true ;
	}
	
	Tree.prototype.activate = function() {this.active=true;}
	Tree.prototype.deactivate = function() {this.active=false;}
	
	Tree.prototype.addChild = function(idPadre, node) {
		var padre = this.getNode(idPadre) ;
		if(padre) {
			this.nodes.push(node) ;//salvo il nodo nell'elenco di nodi
			padre.figli.push(node) ;//salvo il nodo nella struttura gerarchica di nodi
			node.padre = padre ;
		}
	}

	Tree.prototype.removeChild = function(id) {
	    var node = this.getNode(id) ;
	    if(node && node.padre) {
		node.padre.figli.remove(node) ;
		this.nodes.remove(node) ;
		this.removed.push(node) ;
	    }
	}

	Tree.prototype.setModified = function(id) {
	    var node = this.getNode(id) ;
	    if(node)
		node.modified = true ;
	}

	Tree.prototype.resetModified = function() {
	    this.removed = new Array() ;
	    var stack = new Array() ;
	    stack.push(this.root) ;
	    var i ;
	    while(stack.length) {
		var node = stack.shift() ;
		node.modified = false ;
		for(i=0;i<node.figli.length;i++)
		    stack.push(node.figli[i]) ;
	    }
	}

	Tree.prototype.addSiblingBefore = function(idSibling, node) {
	    var n = this.getNode(idSibling) ;
	    if(n) {
		this.nodes.push(node) ;
		n.padre.figli.add(n.padre.figli.indexOf(n),node) ;
		node.padre = n.padre ;
	    }
	}
	
	Tree.prototype.getNode = function(id) {
		var ret = null ;
		var i ;
		for(i=0;i<this.nodes.length;i++) {
			if(this.nodes[i].id==id) {
				ret = this.nodes[i] ;
				break ;
			}
		}
		return ret ;
	}
	
	Tree.prototype.getChildren = function(id) {
		var ret = new Array() ;
		var n = this.getNode(id) ;
		if(n)
			ret = n.figli ;
		return ret ;
	}

	Tree.prototype.getParent = function(id) {
	    var n = this.getNode(id) ;
	    return n ? n.padre : null ;
	}
	
	Tree.prototype.getHeight = function() {
		return this.root.getHeight() ;
	}

	Tree.prototype.setRootVisible = function(vis) {
		this.rootVisible = vis ;
	}

	Tree.prototype.isRootVisible = function() {
		return this.rootVisible ;
	}
	
	Tree.prototype.expandNode = function(id) {
		var n = this.getNode(id) ;
		if(n && n.figli.length) {
			n.espanso = !n.espanso ;
			//if(!n.espanso && n.isAnchestor(this.selected))
			//	this.selectNode(id) ;
			this.fireExpansion(n) ;
			this.redraw() ;
		}
	}

	Tree.prototype.expandPathToNode = function(id, expand) {
		var n = this.getNode(id) ;
		while(n) {
		    n.espanso = expand ;
		    n = n.padre ;
		}
		this.redraw() ;
	}
	
	Tree.prototype.selectNode = function(id,noEvents) {
		var n = this.getNode(id) ;
		if(n) {
		 	if(!n.equals(this.selected)) {
				if(this.selected) {
					this.selected.selezionato = false ;//mono-selezione soltanto!!!
					if(this.ui)
						this.ui.select(this.selected) ;
				}
	
				this.selected = n ;
				n.selezionato = true ;
				if(this.ui)
					this.ui.select(n) ;
				if(!noEvents)
				    this.fireSelection(n) ;
			}
		}
	}



	Tree.prototype.getSelectedValue = function() {
	    return this.selected ? this.selected.value : null ;
	}

	Tree.prototype.displayNodeInfo = function(id) {
		var n = this.getNode(id) ;
		if(n)
			this.fireInfo(n) ;
	}

	Tree.prototype.displayLink = function(id) {
		var n = this.getNode(id) ;
		if(n)
			this.fireLink(n) ;
	}

	Tree.prototype.addExpandListener = function(l,obj) {
		this.expandListeners.push(l) ;
		this.expandListenerObjects.push(obj) ;
	}

	Tree.prototype.fireExpansion = function(node) {
		if(this.active)
			for(i=0;i<this.expandListeners.length;i++)
				this.expandListeners[i].call(this.expandListenerObjects[i],node) ;
	}

	
	Tree.prototype.addSelectListener = function(l,obj) {
		this.selectListeners.push(l) ;
		this.selectListenerObjects.push(obj) ;
	}
	
	Tree.prototype.fireSelection = function(node) {
		if(this.active)
			for(i=0;i<this.selectListeners.length;i++)
				this.selectListeners[i].call(this.selectListenerObjects[i],node.value) ;
	}
	
	Tree.prototype.addInfoListener = function(l,obj) {
		this.infoListeners.push(l) ;
		this.infoListenerObjects.push(obj) ;
	}
	
	Tree.prototype.fireInfo = function(node) {
		if(this.active)
			for(i=0;i<this.infoListeners.length;i++)
				this.infoListeners[i].call(this.infoListenerObjects[i],node.info) ;
	}

	Tree.prototype.addLinkListener = function(l,obj) {
		this.linkListeners.push(l) ;
		this.linkListenerObjects.push(obj) ;
	}
	
	Tree.prototype.fireLink = function(node) {
		if(this.active)
			for(i=0;i<this.linkListeners.length;i++)
				this.linkListeners[i].call(this.linkListenerObjects[i],node.value.url) ;
	}

	Tree.prototype.redraw = function() {
		if(this.ui)
			this.ui.draw(this) ;
	}

	Tree.prototype.addInfo = function(id, url) {
		var n = this.getNode(id) ;
		if(n)
			n.info = url ;
	}
//
//------------------------------------------------------------------------------
// FINE CLASS Tree
//------------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// CLASS TreeUI
//-----------------------------------------------------------------------------
//
	function TreeUI(fnTitolo,fnTip,fnContext,layer,imgPiu,imgPiuL,imgMeno,imgMenoL,imgEspandibile,imgEspanso,imgFoglia,imgInfo,imgLink,imgTratto,imgTrattoT,imgTrattoL) {
		this.fnTitolo = fnTitolo ;
		this.fnTip = fnTip ;
		this.fnContext = fnContext ;
		this.layer = layer ;
		this.piu = imgPiu ;
		this.piuL = imgPiuL ;
		this.meno = imgMeno ;
		this.menoL = imgMenoL ;
		this.espandibile = imgEspandibile ;
		this.espanso = imgEspanso ;
		this.foglia = imgFoglia ;
		this.info = imgInfo ;
		this.link = imgLink ;
		this.tratto = imgTratto ;
		this.trattoT = imgTrattoT ;
		this.trattoL = imgTrattoL ;
	}

	
	TreeUI.prototype.draw = function(tree) {
		
                var ret = "<TABLE class='tree_body' cellspacing='0' cellpadding='0' align='left'>" ;
		var h = tree.getHeight() - (tree.isRootVisible() ? 1 : 0) ;
		ret += "<TR>" ;
		for(var i=0;i<h+1;i++)
			ret +="<TD width='1%'></TD>" ;
		ret +="<TD width='90%'></TD></TR>" ;

		if(tree.isRootVisible()) {
			ret += this.nodeHTML(tree.root,0,h,new Array('1')) ;
		} else {
			var i = 0 ;
			var roots = tree.getChildren(tree.root.id) ;
			for(i=0;i<roots.length;i++)
				ret += this.nodeHTML(roots[i],0,h,new Array()) ;
		}

		ret += "</TABLE>" ;
                
		this.layer.innerHTML = ret ;
		var instance = this ;

		var cells = this.layer.getElementsByTagName("TD") ;
		for(i=0;i<cells.length;i++) {
		    if(cells[i].id.substring(0,4)=='ntxt')
			cells[i].oncontextmenu = this.fnContext ;
		}
		
		//espansione nodi
		var imgs = this.layer.getElementsByTagName("IMG") ;
		for(i=0;i<imgs.length;i++) {
			var img = imgs.item(i) ;
			if(img.name) {
				if(img.name.substring(0,4)=='node') {
					img.onclick = function() {
						//Tree.prototype.instance = tree ;
						tree.expandNode(parseInt(this.name.substring(4))) ;
					}
				/*} else if(img.name.substring(0,4)=='rink') {
					img.onclick = function() {
						var nid = parseInt(this.name.substring(4)) ;
						tree.selectNode(nid) ;
						tree.displayLink(nid) ;
					}
				} else if(img.name.substring(1,4)=='ink') {
					img.onclick = function() {
						var nid = parseInt(this.name.substring(4)) ;
						tree.expandNode(nid) ;
						tree.selectNode(nid) ;
					}*/
				/*} else if(img.name.substring(0,4)=='info') {
					img.onclick = function() {
						var nid = parseInt(this.name.substring(4)) ;
						tree.selectNode(nid) ;
						tree.displayNodeInfo(nid) ;
					}*/
				}
			}
		}
		
		//clic sulle voci
		var links = this.layer.getElementsByTagName("A") ;
		for(i=0;i<links.length;i++) {
			var link = links.item(i) ;
			if(link.name.substring(0,4)=='link') {
				link.onclick = function() {
					//Tree.prototype.instance = tree ;
					tree.selectNode(parseInt(this.name.substring(4))) ;
				}
			} else if(link.name.substring(0,4)=='rink') {
				link.onclick = function() {
					var nid = parseInt(this.name.substring(4)) ;
					tree.selectNode(nid) ;
					tree.displayLink(nid) ;
				}
			} else if(link.name.substring(1,4)=='ink') {
				link.onclick = function() {
					var nid = parseInt(this.name.substring(4)) ;
					tree.expandNode(nid) ;
					tree.selectNode(nid) ;
				}
			} else if(link.name.substring(0,4)=='info') {
				link.onclick = function() {
					var nid = parseInt(this.name.substring(4)) ;
					tree.selectNode(nid) ;
					tree.displayNodeInfo(nid) ;
				}
			}
		}
	}
	
	TreeUI.prototype.select = function(node) {
		var l = this.layer.getElementsByTagName("A") ;
		var i ;
		for(i=0;i<l.length;i++)
			if(l.item(i).name=='link'+node.id) {
				l.item(i).parentNode.className = 'tree_item'+(node.selezionato?' tree_selection':'')+(node.modified?' tree_item_modified':'') ;
				break ;
			}
	}
	
	TreeUI.prototype.nodeHTML = function(node,height,total,lastNodes) {
		var ret = "<TR>" ;
		var i ;
		for(i=0;i<height;i++)
			ret += "<TD background='"+(lastNodes[i]?"":this.tratto)+"'><IMG src='"+(lastNodes[i]?"tr.gif":this.tratto)+"'/></TD>" ;
		
		if(node.figli.length) {
			if(node.espanso) {
				ret += "<TD background='"+(lastNodes[height]?"":this.tratto)+"'><IMG name='node"+node.id+"' src='"+(lastNodes[height]?this.menoL:this.meno)+"'/></TD>" ;
				ret += "<TD background='"+this.tratto+"'><IMG name='eink"+node.id+"' src='"+this.espanso+"'/></TD>" ;
			} else {
				ret += "<TD background='"+(lastNodes[height]?"":this.tratto)+"'><IMG name='node"+node.id+"' src='"+(lastNodes[height]?this.piuL:this.piu)+"'/></TD>" ;
				ret += "<TD><IMG name='eink"+node.id+"' src='"+this.espandibile+"'/></TD>" ;
			}
		} else {
			ret += "<TD background='"+(lastNodes[height]?"":this.tratto)+"'><IMG src='"+(lastNodes[height]?this.trattoL:this.trattoT)+"'/></TD>" ;
			ret += "<TD><IMG name='fink"+node.id+"' src='"+this.foglia+"'/></TD>" ;
		}

		ret +=	"<TD"+((total-height)>1 ? " colspan='"+(total-height)+"'" : "")+">"+
					"<TABLE cellspacing='0' cellpadding='0' width='100%'><TR>"+
						"<TD id='ntxt"+node.id+"' class='tree_item"+(node.selezionato?" tree_selection":"")+(node.modified?" tree_item_modified":"")+"'><A href='#' name='link"+node.id+"' title='"+this.fnTip.call(this,node)+"'>"+this.fnTitolo.call(this,node)+"</A>"+
						(
						    node.info
							? (
							    this.info
							    ? "<IMG name='info"+node.id+"' src	='"+this.info+"' onMouseOver='rollOver(this)' onMouseOut='rollOut(this)' alt='Info bibliografica' title='Info bibliografica'/>"
							    : "<SPAN class='tree_link'> <A name='info"+node.id+"'>[Info]</A></SPAN>"
							) : ""
						)
						+
						(
						    node.value.url
							? (
							    this.link
							    ? "<IMG name='rink"+node.id+"' src='"+this.link+"' onMouseOver='rollOver(this)' onMouseOut='rollOut(this)' alt='Risorse correlate' title='Risorse correlate'/>"
							    : "<SPAN class='tree_link'> <A name='rink"+node.id+"'>[Links]</A></SPAN>"
							) : ""
						)
						+
						"</TD>"+
						"<TD class='tree_item'>&nbsp;</TD>"+
					"</TR></TABLE>"+
				"</TD>" ;
		ret += "</TR>" ;
		if(node.espanso) {
			for(i=0;i<node.figli.length;i++) {
				lastNodes[height+1] = (i==node.figli.length-1) ;
				ret += this.nodeHTML(node.figli[i],height+1,total,lastNodes) ;
			}
		}
		return ret ;
	}
//
//------------------------------------------------------------------------------
