Bw.Widgets.List = 
{
	superclassName: "Bw.Widgets.Widget",
	selfclassName: "Bw.Widgets.List",
	
	create: function (record, rowValue, columns, src, multi, header, height, width)
	{
		var obj = document.createElement ('div');
		
		obj.setAttribute ("record", record);
		obj.setAttribute ("rowValue", rowValue);
		obj.setAttribute ("multi", multi);
		obj.setAttribute ("showHeader", header);
		
		if (src) obj.setAttribute ("src", src);
		if (height) obj.style.height = height + "px";
		if (width) obj.style.width = width + "px";

		for (var i = 0; i < columns.length; i++)
		{
			obj.appendChild (columns[i]);
		}
		
		Bw.Core.bootstrap (obj, "Bw.Widgets.List");
		
		return obj;
	},
	
	initialize: function ()
	{
		Bw.Widgets.Widget.initialize.call(this);
				
		this.columns = [];
		this.selection = [];
		this.naturalOrder = [];
		this.sortedOrder = [];
		this.sortedOrder._list = this;
		this.sortOrder = 0;
		this.sortedColumnIndex = -1;
		
		this.primarySelection = null;
		this.headerHeight = 0;
		this.header = null;
		this.list = null;
		this.headerTable = null;
		this.listTable = null;
		
		var att = this.getAttribute ("multi");
		this.multi = (att == null || att == 'false') ? false : true;
		
		att = this.getAttribute ("sortable");
		this.sortable = (att == null || att == 'true') ? true : false;
		
		this.record = this.getAttribute ("record");
		this.rowValue = this.getAttribute ("rowValue");
		this.onselect = this.getAttribute ("onselect");
		this.onaction = this.getAttribute ("onaction");
		this.onupdate = this.getAttribute ("onupdate");
		
		var sortedColDir = 0;
		var sortedColIndex = this.getAttribute ("sortedBy");
		if (sortedColIndex != null)
		{
			sortedColDir = (sortedColIndex.indexOf("-") == 0) ? 1 : 2;
			sortedColIndex = Math.abs (parseInt (sortedColIndex, 10));
		}
		
		this.initColumns();
		
		this.draw();
		
		var self = this;
		this.onclick = function (e) { return self.mouseClicked (Bw.getEvent(e)); };
		this.ondblclick = function (e) { return self.mouseDoubleClicked (Bw.getEvent(e)); };
		this.onmousemove = function (e) { return self.mouseMoved (Bw.getEvent(e)); };
		this.onmousedown = function (e) { return self.mousePressed (Bw.getEvent(e)); };
		this.onmouseup = function (e) { return self.mouseReleased (Bw.getEvent(e)); };
		this.onkeydown = function (e) { return self.keyPressed (Bw.getEvent(e)); };
		//this.onkeypress = function (e) { return false; };

		if (this.header)
		{
			this.list.onscroll = function () { self.header.scrollLeft = self.list.scrollLeft; };
		}
		
		var sortcb = function ()
		{
			if (sortedColIndex == null) return;
			self.sort (sortedColIndex, sortedColDir);
			
		};
		
		att = this.getAttribute ("src");
		if (att != null)
		{
			setTimeout (function () { self.appendXML (att, sortcb, true); }, 10);
		}
		else
		{
			this.layout(true);
			sortcb();
		}
		
		return false;

	},
	
	draw: function ()
	{
		with (this.style)
		{
			overflow = "hidden";
			cursor = "default";
			MozUserInput = "enabled";
			MozUserFocus = "normal";
		}
		
		this.tabIndex = 0;
		
		att = this.getAttribute ("showHeader");
		if (att == null || att == 'true')
		{
			this.drawHeader();
		}
		
		this.drawList();
	},
	
	appendXML: function (src, cb, initial)
	{
		this.insertXML (src, cb, null, initial);
	},

	insertXML: function (src, cb, beforeRow, initial)
	{
		var m = src;
		
		if (typeof m == "string")
		{
			var q = Bw.IO.Query.create ();
			q.setNoCache();
			
			var self = this;
			q.get (src, function () { self._asyncInsert (q.getMessage(), cb, beforeRow, initial); } );
		}
		else
		{
			this._asyncInsert (m, cb, beforeRow, initial);
		}
	},
	
	_asyncInsert: function (source, cb, beforeRow, initial)
	{
		this.message = source;
		
		this.drawRows (source, beforeRow);
		
		if (this.sortedColumnIndex != -1) {
			this.sort (this.sortedColumnIndex, this.sortOrder);
		}
		
		if (beforeRow) {
			this.scrollToRow (beforeRow);
		}
		
		if (initial)
		{
			this.layout (initial);
			if (!document.all) Bw.Util.forceRedraw (this);
		}
		
		if (cb) cb();
	},
	
	
	initColumns: function ()
	{
		var curr = this.firstChild;
		while (curr != null)
		{
			this.removeChild (curr);
			
			if (curr.className == "Bw.Widgets.List.Column")
			{
				var col = Bw.Widgets.List.Column.create (this);
				col.setName (curr.getAttribute ("name"));
				var s = curr.getAttribute ("size");
				if (typeof s == "string")
				{
					col.setSize (curr.getAttribute ("size"));
				}
				col.setAlign (curr.getAttribute ("align"));
				col.loadRenderCode (curr.getAttribute ("render"));
				
				this.columns.push (col);
			}
			
			curr = this.firstChild;
		}
	},
	
	
	drawHeader: function ()
	{
		var h = document.createElement ("div");
		h.className = "bwheader";

		with (h.style)
		{
			overflow="hidden";
		}
		
		this.appendChild (h);
		this.header = h;
		
		var ht = document.createElement ("table");
		with (ht.style)
		{
			tableLayout = "fixed";
			borderCollapse = "collapse";
		}
		
		this.headerTable = ht;

		var tb = document.createElement ("tbody");
		ht.appendChild (tb);
		
		h.appendChild (ht);
		
		var tr = document.createElement ("tr");
		tb.appendChild (tr);
		
		var l = this.columns.length;
		for (var i = 0; i < l; i++)
		{
			var col = this.columns[i];
			var td = document.createElement ("td");
			td.columnIndex = i;
			
			with (td.style)
			{
				padding = "0px";
			}
		
			var d = document.createElement ("div");
			d.className="bwcolumn";
			with (d.style)
			{
				whiteSpace = "nowrap";
				textAlign = col.align;
				overflow = "hidden";
			}
			td.appendChild (d);
			
			var a = Bw.Widgets.Label.create (col.name);
			d.appendChild (a);
			
			a = Bw.Widgets.StockIcon.create ("asc");
			with (a.style)
			{
				visibility="hidden";
				paddingTop = "3px";
			}
			d.appendChild (a);
			
			tr.appendChild (td);
		}
	},
	
	
	drawList: function ()
	{
		var l = document.createElement ("div");
		l.style.overflow = "auto";
		l.className="bwlist";
		
		var lt = document.createElement ("table");
		
		lt.style.tableLayout="fixed";
		lt.style.borderCollapse="collapse";
		
		var cg = document.createElement ("colgroup");
		var len = this.columns.length;
		for (var i = 0; i < len; i++)
		{
			var c = document.createElement("col");
			cg.appendChild (c);
			this.columns[i].colPtr = c;
		}
		
		var tb = document.createElement ("tbody");
		lt.appendChild (cg);
		lt.appendChild (tb);
		l.appendChild (lt);
		this.appendChild (l);

		this.listTable = lt;
		this.list = l;
	},

	
	drawRows: function (source, beforeRow)
	{
		var b = this.listTable.tBodies[0];
		
		var append = (beforeRow == null);
		var insertRow = (append) ? null : beforeRow;
		var rowIndex = (append) ? b.rows.length : beforeRow.rowIndex;
		var rows = [];
		
		var cols = this.columns;
		var clen = cols.length;
		
		var c = source.getNodes (this.record);
		var l = c.length;
		
		var m = document.createElement ("tr");
		m.vAlign="middle";
		m.style.verticalAlign="middle";
		
		for (var i = 0; i < clen; i++)
		{
			var td = document.createElement ("td");
			td.style.overflow="hidden";
			td.align = cols[i].align;
			m.appendChild (td);
		}
		
		this.applyRowStyle (m, rowIndex);
		
		for (var r = 0; r < l; r++) 
		{
			var tr = m.cloneNode (true);
			
			rows.push (tr);
			
			if (this.rowValue != null) {
				tr.value = Bw.Xml.Helpers.getNodeValue (source.getNode (this.rowValue, c[r]));
			}
			
			var tds = tr.childNodes;
			for (var i = 0; i < clen; i++)
			{
				var col = cols[i];
				var td = tds[i];
				
				var w = col.cellContent (c[r]);
				w.style.overflow="hidden";
				td.appendChild (w);
				
				td.onselectstart = function(){ return typeof window.event.srcElement.editable!='undefined';};
			}
			
			if ((r%2) != 0) {
				this.applyRowStyle (tr, rowIndex, true);
			}
			
			if (append) {
				b.appendChild (tr);
			} else {
				b.insertBefore (tr, insertRow);
			}

			insertRow = tr.nextSibling;
			rowIndex++;
		}
		
		this.sortedOrder = this.sortedOrder.concat (rows);
		
		if (append) {
			this.naturalOrder = this.naturalOrder.concat (rows);
		}
		else
		{
			var i = this.naturalOrder.lookup (beforeRow);
			var a1 = this.naturalOrder.slice (0, i);
			var a2 = this.naturalOrder.slice (i);
			this.naturalOrder = a1.concat (rows, a2);
			
			var c = beforeRow;
			while (c != null)
			{
				this.applyRowStyle (c, c.rowIndex, true);
				c = c.nextSibling;
			}
			
			this.drawSelection();
		}
	},
	
	drawSelection: function ()
	{
		var s = this.selection;
		for (var i = 0; i < s.length; i++) {
			s[i].className="bwrowSelected";
		}
	},
	
	applyRowStyle: function (r, i, excludingCells)
	{
		var s = ((i%2) == 0) ? "bwrowEven" : "bwrowOdd";
		var c = r.childNodes;
		var l = c.length;
		
		r.className = s;
		
		if (!excludingCells)
		{
			for (var j = 0; j < l; j++)
			{
				if (this.sortOrder != 0 && j == this.sortedColumnIndex) {
					c[j].className="bwsorted";
				} else {
					c[j].className="";
				}
			}
		}
	},
	
	layout: function (initial)
	{
		var h = this.offsetHeight - 2;
		if (this.header)
		{
			this.headerHeight = this.header.offsetHeight;
			h -= this.headerHeight;
		}
		
		if (h > 0) this.list.style.height = h + 'px';
				
		var ow = this.offsetWidth;
		if (ow > 0)
		{	
			/*if (document.all)*/ ow -= 2;
			var cw = this.list.clientWidth;
		
			this.columnLayout (initial);
		
			this.list.style.width = ow + 'px';
			this.listTable.style.width = cw + 'px';

			if (this.header)
			{
				this.header.style.width = ow + 'px';
				this.headerTable.style.width = cw + "px";
			}
		}
	},
	
	columnLayout: function (initial)
	{
		var l = this.columns.length;
		for (var i = 0; i < l; i++)
		{
			var h;
			if (this.header)
			{
				h = this.headerTable.tBodies[0].rows[0].cells[i];
			}
			
			if (initial) this.computeSize();
			
			var w = (initial || !this.header) ? this.columns[i].size: h.offsetWidth;
			if (typeof w != 'undefined')
			{
				if (this.header) h.style.width = w + 'px';
				this.columns[i].colPtr.style.width = w + "px";
			}
			
		}
	},
	
	computeSize: function ()
	{
		var cw = this.list.clientWidth;
		var dw = 0;
		var nd = 0;
				
		var l = this.columns.length;
		for (var i = 0; i < l; i++)
		{
			var s = this.columns[i].size;
			if (s >= 0)
			{
				dw += s;
				nd++;
			}
		}
		
		cw -= dw;
		nd = l - nd;
		for (var i = 0; i < l; i++)
		{
			var c = this.columns[i];
			var s = c.size;
			if (s < 0)
			{
				c.size = Math.round (cw / nd);
			}			
		}
	},
	
	
	keyPressed: function (event)
	{
		var key = event.keyCode;
		var rows = this.listTable.tBodies[0].rows;
		var row = (this.selection.length != 0) ? this.selection[this.selection.length-1] : null;
		var rowsPerPage = Math.floor ((this.list.clientHeight - this.headerHeight) / rows[0].offsetHeight);
		var last = rows.length - 1;

		switch (key)
		{
			case 38:
				row = (row != null) ? row.previousSibling : rows[0];
				break;
			case 40:
				row = (row != null) ? row.nextSibling : rows[0];
				break;
			case 33:
				var i = 0;
				if (row != null) {
					i = (row.rowIndex - rowsPerPage);
					if (i < 0) i = 0;
				}
				row = rows[i];
				break;
			case 34:
				var i = 0;
				if (row != null) {
					i = (row.rowIndex + rowsPerPage);
					if (i > last) i = last;
				}
				row = rows[i];
				break;
			case 36:
				row = rows[0];
				break;
			case 35:
				row = rows[last];
				break;
			case 13:
				Bw.Util.call (this, this.onaction);
				/*this.scrollToRow (row);*/
				return;
			default:
				return true;
		}
		
		if (row)
		{
			this.rowSelect (row, event);
			this.scrollToRow (row);
		}

		return false;
	},

	mouseClicked: function (event)
	{
		if (this.targetColumn != null) {
			return true;
		}

		var target = event.target;
		
		if (Bw.Util.findParentElement (target, "DIV", "bwheader") != null)
		{
			if (target.nodeName != "TD") {
				target = Bw.Util.findParentElement (target, "TD");
			}
			
			if (target != null && this.sortable) {
				this.columnSort (target.cellIndex);
			}
		}
		
		return true;
	},

	mouseDoubleClicked: function (event)
	{
		if (this.onaction == null) {
			return true;
		}
		
		if (this.targetColumn != null) {
			return true;
		}

		var target = event.target;
		var row = Bw.Util.findParentElement (target, "TR");
		if (row != null && Bw.Util.findParentElement (row, "DIV", "bwlist") != null) {
			return Bw.Util.call (this, this.onaction);
		}

		return true;
	},

	mousePressed: function (event)
	{		
		if (this.focus) this.focus();
		
		if (this.targetColumn == null)
		{
			var target = event.target;
			var row = Bw.Util.findParentElement (target, "TR");
			if (row != null && Bw.Util.findParentElement (row, "DIV", "bwlist") != null) {
				this.rowSelect (row, event);
			}
			return true;
		}
		
		this.lastX = (event.pageX)?event.pageX:event.x;
		this.lastX += this.list.scrollLeft;
		this.resizing = true;
	
		if (this.setCapture) {
			this.setCapture();
		}
	},

	mouseReleased: function (event)
	{
		this.resizing = false;
		
		if (this.releaseCapture) {
			this.releaseCapture();
		}
		return true;
	},

	mouseMoved: function (event)
	{
		var target = event.target;
		var x = (event.pageX)?event.pageX:event.x;
		x += this.list.scrollLeft;
		
		if (this.resizing)
		{
			var o = x - this.lastX;
			var w = this.targetColumnWidth + o;
			if (w <= 16)
			{
				return;
			}

			var w1 = w + "px";
			var w2 = (this.targetTableWidth + o) + "px";
			
			this.targetColumn.style.width = w1;
			
			this.columns[this.targetColumn.cellIndex].colPtr.style.width = w1;
						
			this.headerTable.style.width = w2;
			this.listTable.style.width = w2;
		}
		else if (Bw.Util.findParentElement (target, "DIV", "bwheader") != null)
		{
			if (target.nodeName != "TD") {
				target = Bw.Util.findParentElement (target, "TD");
			}
			if (target != null) {
				this.handleColumnHeaders (target, x);
			}
		}
		else
		{
			this.style.cursor = "default";
			this.targetColumn = null;
		}
	},

	handleColumnHeaders: function (target, x)
	{
		var prev = target.previousSibling;
		var next = target.nextSibling;
		var left = Bw.Util.getElementLeftPosition (target);
		var right = left + target.offsetWidth;
		
		this.resizing = false;
		
		if (prev && x <= (left + 7)) {
			this.style.cursor = "e-resize";
			this.targetColumn = prev;
			this.targetColumnWidth = prev.offsetWidth;
			this.targetTableWidth = this.headerTable.offsetWidth;
		}
		else if (x >= (right - 7)) {
			this.style.cursor = "e-resize";
			this.targetColumn = target;
			this.targetColumnWidth = target.offsetWidth;
			this.targetTableWidth = this.headerTable.offsetWidth;
		}
		else {
			this.style.cursor = "default";
			this.targetColumn = null;
		}
	},

	columnSort: function (col)
	{
		var pc = this.sortedColumnIndex;
		var order = this.sortOrder;
		if (col != pc) {
			order = 0;
		}
		
		order = (++order % 3);
		
		this.sort (col, order);
		
		var s = this.selection;
		var l = s.length;
		if (l > 0) {
			this.scrollToRow (s[l-1]);
		}
	},

	sort: function (col, order, excludingCell)
	{
		var h = this.headerTable.tBodies[0].rows[0].childNodes;
		var b = this.listTable.tBodies[0];
		var l = b.rows.length;
		var pc = this.sortedColumnIndex;
		var ic, s;
		
		if (col != pc && pc != -1)
		{
			ic = h[pc].firstChild.firstChild.nextSibling;
			ic.style.visibility="hidden";
			h[pc].firstChild.className = "bwcolumn";
		}
		
		this.sortOrder = order;
		this.sortedColumnIndex = col;
		
		ic = h[col].firstChild.firstChild.nextSibling;
		if (this.sortOrder != 0) 
		{
			var asc = (this.sortOrder == 1);
			h[col].firstChild.className = "bwcolumn bwsorted";
			ic.style.visibility="visible";
			ic.setSource (asc ? "asc" : "desc");
			
			var _this = this;
			this.sortedOrder.sort (function (a,b){return _this._compare(a,b);});
			
			s = this.sortedOrder;
		}
		else
		{
			h[col].firstChild.className = "bwcolumn";
			ic.style.visibility="hidden";
			s = this.naturalOrder;
		}
		
		this.listTable.removeChild (b);	
		for (var i = 0; i < l; i++)
		{
			var r = s[i];
			b.removeChild (r);
			this.applyRowStyle (r, i, excludingCell);
			b.appendChild (r);
		}
		this.listTable.appendChild (b);	
		
		this.drawSelection ();
	},

	_compare: function (a, b)
	{
		var i = this.sortedColumnIndex;
		a = this.getCellValue (a, i);
		b = this.getCellValue (b, i);
		if (a.toUpperCase && b.toUpperCase)
		{
			a = a.toUpperCase();
			b = b.toUpperCase();
		}
		
		var r;
		if (a > b) r = 1;
		else if (a < b) r = -1;
		else r = 0;

		if (this.sortOrder == 2) r = -r;
		
		return r;
	},

	deselectAll: function ()
	{
		var l = this.selection.length;
		for (var i = 0; i < l; i++) {
			this.deselect (this.selection[0]);
		}
	},

	deselect: function (row)
	{
		if (!row) return;

		var c = row.childNodes;
		var l = c.length;
		
		var i = this.selection.lookup (row);
		if (i == -1) return;
		
		this.selection.splice (i, 1);
		
		var r = row.rowIndex;
		this.applyRowStyle (row, r);
	},

	selectRowByValue: function (value)
	{
		var rows = this.listTable.tBodies[0].rows;
		var l = rows.length;
		for (var i = 0; i < l; i++)
		{
			var r = rows[i];
			if (r.value == value) {
				this.rowSelect (r);
				this.scrollToRow (r);
				return;
			}
		}
	},

	select: function (row)
	{
		var c = row.childNodes;
		var l = c.length;
		
		var i = this.selection.lookup (row);
		if (i != -1) return;
		
		this.selection.push (row);

		this.drawSelection();
	},

	rowSelect: function (row, e)
	{
		var r = this.selection.lookup (row);
		
		if (e && e.ctrlKey)
		{
			if (r == -1) {
				if (!this.multi && this.selection.length != 0) {
					this.deselect (this.selection[0]);
				}
				
				this.select (row);
				this.primarySelection = row;
			} else {
				this.deselect (row);
				if (this.selection.length == 0) {
					this.primarySelection = null;
				}
			}
		}
		else if (this.multi && e && e.shiftKey && this.primarySelection != null)
		{
			var last = this.primarySelection;
			this.deselectAll();
			
			var i1 = last.rowIndex;
			var i2 = row.rowIndex;
			if (i1 < i2) {
				for (var i = i1; i <= i2; i++) {
					this.select (this.listTable.tBodies[0].rows[i]);
				}
			} else {
				for (var i = i1; i >= i2; i--) {
					this.select (this.listTable.tBodies[0].rows[i]);
				}
			}
		}
		else
		{
			this.deselectAll();
			this.select (row);
			this.primarySelection = row;
		}
		
		Bw.Util.call (this, this.onselect);
	},

	getSelection: function ()
	{
		return this.selection;
	},

	getCellValue: function (row, colIndex)
	{
		var c = this.getCellWidget (row, colIndex);
		return (c) ? c.getValue() : null;
	},
	
	setCellValue: function (row, colIndex, value)
	{
		var c = this.getCellWidget (row, colIndex);
		if (c) c.setValue (value);
	},
	
	getCell: function (row, colIndex)
	{
		return (row) ? row.childNodes[colIndex] : null;
	},
	
	getCellWidget: function (row, colIndex)
	{
		var c = this.getCell (row, colIndex);
		return (c) ? c.firstChild : null;
	},
	
	getRow: function (i)
	{
		var rows = this.listTable.tBodies[0].rows;
		return (i < 0 || i >= rows.length) ? null : rows[i];
	},

	removeSelection: function ()
	{
		var s = this.selection;
		while (s.length > 0) {
			this.remove (s[0], true);
		}
		
		var r = this.listTable.tBodies[0].rows;
		for (var i = 0; i < r.length; i++) {
			this.applyRowStyle (r[i], i, true);
		}
		
	},

	remove: function (row, freeze)
	{
		var i;
		
		row.parentNode.removeChild (row);
		
		if (!freeze)
		{
			var next = row.nextSibling;
			i = row.rowIndex;
			while (next != null)
			{
				this.applyRowStyle (next, i, true);
				i++;
				next = next.nextSibling;
			}
		}

		i = this.selection.lookup (row);
		this.selection.splice (i, 1);

		i = this.naturalOrder.lookup (row);
		this.naturalOrder.splice (i, 1);
		
		i = this.sortedOrder.lookup (row);
		this.sortedOrder.splice (i, 1);
	},

	clear: function ()
	{
		var b = this.listTable.tBodies[0];
		
		var c;	
		while ((c = b.firstChild) != null)
		{
			b.removeChild (c);
		}
	
		this.selection = [];
		this.naturalOrder = [];
		this.sortedOrder = [];
	},

	getValue: function ()
	{
		var s = this.selection;
		var l = s.length;
		if (l == 0) {
			return null;
		}

		return s[l-1].value;
	},

	getLength: function ()
	{
		return this.listTable.tBodies[0].rows.length;
	},

	cellFocused: function (widget)
	{
		var td = widget.parentNode;
		var row = td.parentNode;
		this.deselectAll();
		this.rowSelect (row);
	},

	cellUpdated: function (widget)
	{
		var td = widget.parentNode;
		var i = td.cellIndex;
		var row = td.parentNode;
		
		if (this.sortedColumnIndex == i) {
			this.sort (i, this.sortOrder);
			this.scrollToRow (row);
		}
		
		if (this.onupdate)
		{
			this.updatedRow = row;
			this.updatedCellIndex = i;
			Bw.Util.call (this, this.onupdate);
		}
	},

	scrollToRow: function (row)
	{
		if (row.offsetTop < this.list.scrollTop) {
			this.list.scrollTop = row.offsetTop;
		}
		else if ((row.offsetTop + row.offsetHeight) > (this.list.scrollTop + this.list.clientHeight - this.headerHeight)) {
			this.list.scrollTop = row.offsetTop - this.list.clientHeight + this.headerHeight + row.offsetHeight;
		}
	}
};

Bw.Widgets.List.Column =
{
	
	superclassName: null,
	selfclassName: "Bw.Widgets.List.Column",
	
	ERROR: "Invalid column specification",
	
	create: function (list)
	{
		var obj = new Object();
		obj.list = list;
		
		Bw.Core.bootstrap (obj, this);
		
		return obj;
	},
	
	initialize: function ()
	{
		this.name = null;
		//this.size = null;
		this.code = null;
	},
	
	setAlign: function (s)
	{
		this.align = (s) ? s : "left";
	},

	setSize: function (s)
	{
		this.size = s;
	},

	setName: function (n)
	{
		this.name = n;
	},

	loadRenderCode: function (c)
	{
		var s = c;
		
		var p1 = s.indexOf ('(');
		if (p1 < 0) {
			throw this.ERROR;
		}
		var p2 = s.indexOf (')');
		if (p2 < 0) {
			throw this.ERROR;
		}
		
		var code = "return " + s.substring (0, p1) + ".create(" ;
		
		s = s.substring (p1+1, p2);
		var l = s.length;
		var i = 0;
		while (l > 0)
		{
			p1 = s.indexOf (',');
			if (p1 < 0) {
				p1 = l;
			}
			
			var d = s.substring (0, p1);
			
			if (i++ > 0) {
				code += ',';
			}
			
			if (d.indexOf ("'") == 0) {
				code += d;
			} else {
				code += ("Bw.Xml.Helpers.getNodeValue(Bw.Xml.Helpers.getNode(s, '" + d + "', false))");
			}
			
			s = s.substring (p1+1, l);
			l = s.length;
		}
				
		this.code = new Function ("s", code + ");");
	},

	cellContent: function (src)
	{
		var r = this.code (src);
		with (r.style)
		{
			whiteSpace = "nowrap";
			overflow = "hidden";
		}
				
		if (r.editable)
		{
			var self = this;
			r.onupdate = function(){self.list.cellUpdated(this);};
			r.onfocus = function(){self.list.cellFocused(this);};
		}
		
		return r;
	}
};

