/* ===================================================================================================
 * gridControl
 * ===================================================================================================
 */

/// fullName: gibt die id des div-Elements an, das das grid-Control enthaelt.
gridControl = function(fullName)
{
	var control = getControl(fullName);
	if (! control)	return null;
	if (control.gridControl) return control.gridControl;
	
	this.element = control;
	this.layout          = null;

	this.headerSpace     = xmlCreateElement(this.element,         "div", null, "gridHeaderSpace");
	//this.headerContainer = xmlCreateElement(this.headerSpace,     "div", null, "gridHeaderContainer");
	this.headerContainer = xmlCreateElement(this.headerSpace,     "table", null, "gridHeaderContainer");
	//this.headerRow   	 = xmlCreateElement(this.headerContainer, "div", null, "gridHeaderRow");
	this.headerRow   	 = xmlCreateElement(this.headerContainer, "hr", null, "gridHeaderRow");

	this.bodySpace       = xmlCreateElement(this.element,         "div", null, "gridBodySpace");
	//this.bodyContainer   = xmlCreateElement(this.bodySpace,       "div", null, "gridBodyContainer");
	this.bodyContainer   = xmlCreateElement(this.bodySpace,       "table", null, "gridBodyContainer");

	this.menuSpace 		 = xmlCreateElement(this.element,         "div", null, "gridMenuSpace"); 
	gridControl_addToolImage(this, this.menuSpace, "menu");

	this.toolSpace 		 = xmlCreateElement(this.element,         "div", null, "gridToolSpace"); 
	var ts1 = xmlCreateElement(this.toolSpace, "div", null, "gridToolSpacePart"); 
	gridControl_addToolImage(this, ts1, "page_top");
	gridControl_addToolImage(this, ts1, "page_up");
	var ts2 = xmlCreateElement(this.toolSpace, "div", null, "gridToolSpacePart"); 
	gridControl_addToolImage(this, ts2, "page_down");
	gridControl_addToolImage(this, ts2, "page_bottom");

	this.selectedRow = -1;
	this.selectedColumn = -1;

	this.composeId = function(row, col)
	{
		return this.element.id + "$" + row.toString() + (col && (col > 0) ? "$" + col.toString() : "");
	};

	this.setFocusItem = function(nextItem, bAlignTop)
	{
		if (nextItem)
		{
			if (typeof(bAlignTop) !== 'undefined')
			{
				rectParent = this.bodySpace.getBoundingClientRect();
				rectItem = nextItem.getBoundingClientRect();
				if (rectItem.bottom > rectParent.bottom) 
					nextItem.scrollIntoView(false);
				if (rectItem.top < rectParent.top) 
					nextItem.scrollIntoView(true);
			}
			nextItem.focus();
		}
	};
	
	this.clear = function()
	{
		this.headerRow.innerHTML = "";
		this.bodyContainer.innerHTML = "";
		this.layout = null;
	    this.selectedRow = -1;
	    this.selectedColumn = -1;
	};
	
    // ------------------------------------------------------------ columns

	this.getColumns = function()
	{
		return this.headerRow.children;
	};

	this.selectColumn = function(columnNumber)
	{
		this.selectedColumn = columnNumber;
	};
	
	this.getSelectedColumnId = function(bAlternate)
	{
		if (this.selectedColumn > 0) 
			return this.selectedColumn;
		if (bAlternate)
		{
			var col = this.headerRow.firstElementChild;
			if (col) return col.number;
		}
		return -1;
	};

	this.markColumn = function(number, unmarkOthers)
	{
		var cols = this.getColumns();
		var len = cols.length;
		for (var i = 0; i < len; i++)
		{
			if (cols[i].number == number)
				cols[i].setAttribute("marked", "true");
			else if (unmarkOthers && cols[i].getAttribute("marked"))
				cols[i].removeAttribute("marked");
		}
	}
	
	this.getSelectedColumn = function()
	{
		var id = this.getSelectedColumnId(true);
		var columns = this.layout.columns;
		var len = columns.length;
		for (var i = 0; i < len; i++)
		{
			var column = columns[i];
			if (column.number == id)
				return column;
		}
		return null;
	};

    // ------------------------------------------------------------ rows
	
	this.getRows = function()
	{
		return this.bodyContainer.children;
	};

	this.clearRows = function()
	{
		this.bodyContainer.innerHTML = "";
	    this.selectedRow = -1;
	};
	
	this.selectRow = function(rowId, bSetFocus)
	{
		var bSendOnChange = this.selectedRow != rowId;
		this.selectedRow = rowId;
		gridControl_markSelectedRow(this);

		if (bSendOnChange)
		{
			gridControl_raiseEvent(this.element.id, "onChange", rowId);
		}

		var row = this.getSelectedRow();
		if (row)
		{
			if (bSetFocus)
			{
				var rowIdToSelect = row.rowId;
				var column = this.getSelectedColumnId(true);
				var nextId = this.composeId(rowIdToSelect, column);
				var nextItem = document.getElementById(nextId);
				if (nextItem) nextItem.focus();
			}
			else
			{
				row.scrollIntoView();
			}
		}
	};
	
	this.deleteRow = function(rowId)
	{
		var row = document.getElementById(this.element.id + "$" + rowId.toString());
		if (row) row.remove();  //alert("deleteRow " + rowId);
	};

	/// liefert das div-Element der aktuellen Zeile
	this.getSelectedRow = function()
	{
		return document.getElementById(this.element.id + "$" + this.selectedRow.toString());
	};
	
	this.getRowByRowId = function(rowId)
	{
		return document.getElementById(this.element.id + "$" + rowId.toString());
	};

	/// Gibt die erste Zeile des Grids zurueck
	this.getFirstRow = function()
	{
		var rows = this.getRows();
		return rows.length > 0 ? rows[0] : null;
	};

	this.createHeaderRow = function()
	{
		this.headerRow.innerHTML = "";
		var columns = this.layout.columns;
		var len = columns.length;
		for (var i = 0; i < len; i++)
		{
			var column = columns[i];
			//var gridCol = xmlCreateElement(this.headerRow, "div", "", "gridHeaderCell");
			var gridCol = xmlCreateElement(this.headerRow, "td", "", "gridHeaderCell");
			var columnWidth = parseIntEx(column.width) * metrics.unitWidth;
			gridCol.style.width = columnWidth.toString() + "px";
			gridCol.style.minWidth = columnWidth.toString() + "px";
			gridCol.style.maxWidth = columnWidth.toString() + "px";
			gridCol.style.opacity = parseInt(column.enabled) ? "0.9" : "0.6";
			gridCol.title = column.toolTip ? column.toolTip : column.inputType;
			gridCol.id = this.element.id + "$column" + column.number.toString();
			gridCol.number = column.number;
			gridCol.index = i;
			gridCol.innerText = column.label;
			gridCol.setAttribute("onclick", "return gridControl_handleHdrClick(this);");
		}
	};

	/// Erstellt eine neue Datenzeile fuer das Control.
	/// Die neue Zeile wird dabei noch nicht dem bodyContainer-Element hinzugefuegt.
	this.createRow = function(rowDescriptor)
	{
		//var row = document.createElement("div");
		var row = document.createElement("tr");
		row.setAttribute("class", "gridBodyRow");
		row.rowId = rowDescriptor.rowId;
		row.RecId = rowDescriptor.RecId;
		row.id = this.element.id + "$" + row.rowId.toString();

		var rowData = rowDescriptor.data;
		
		var columns = this.layout.columns;
		var len = columns.length;
		for (var i = 0; i < len; i++)
		{
			var column = columns[i];
			var cell = xmlCreateElement(row, "div", "", "gridBodyCell");
			var columnWidth = parseIntEx(column.width) * metrics.unitWidth;
			cell.id = row.id + "$" + column.number.toString();
			cell.style.width = columnWidth.toString() + "px";
			cell.style.minWidth = columnWidth.toString() + "px";
			cell.style.maxWidth = columnWidth.toString() + "px";
			cell.number = column.number;
			cell.index = i;
			
			var dataIndex = "C" + column.number.toString();
			var cellText = rowData && (typeof rowData[dataIndex] != "undefined")
				? rowData[dataIndex]
				: column.label + "-" + row.rowId.toString();
			control_setup(cell, column, cellText);
		}
		return row;
	};
	
	/// Aktualisiert eine Datenzeile des Controls.
	this.updateRow = function(row, rowDescriptor)
	{
		row.RecId = rowDescriptor.RecId;

		var rowData = rowDescriptor.data;
		var columns = this.layout.columns;
		var len = columns.length;
		for (var i = 0; i < len; i++)
		{
			var column = columns[i];
			var cell = document.getElementById(this.composeId(row.rowId, column.number));
			if (cell)
			{
				var dataIndex = "C" + column.number.toString();
				var cellText = rowData && (typeof rowData[dataIndex] != "undefined")
					? rowData[dataIndex]
					: column.label + "-" + row.rowId.toString();
				control_setText(cell, cellText);
			}
		}
	};

	// ------------------------------------------------------------ misc
	
	this.hasFocus = function()
	{
		if (!document.hasFocus()) return false;
		var e = document.activeElement;
		while (e != null)
		{
			if (e == this.bodyContainer) return true;
			e = e.parentElement;
		}
		return false;
	};

	this.setFocus = function()
	{
		var row = this.getSelectedRow();
		if (row)
		{
			var rowIdToToSelect = row.rowId;
			var column = this.getSelectedColumnId(true);
			var nextId = this.composeId(rowIdToSelect, column);
			var nextItem = document.getElementById(nextId);
			if (nextItem) nextItem.focus();
		}
		else
		{
			this.bodyContainer.focus();
		}
	};

	this.getLineHeight = function()
	{
		return 25;
	};

	this.getToolSpaceWidth = function()
	{
		return metrics.gridControl_toolSpaceWidth * metrics.unitWidth;
	};

	this.calcLinesPerPage = function()
	{
		var result = Math.round(this.bodySpace.offsetHeight / this.getLineHeight(), 0);
		return result < 2 ? 2 : result;
	};

	this.element.gridControl = this;
	this.element.onAfterResize = function(element)
	{
		gridControl_OnAfterResize(element.gridControl);
	};
	gridControl_OnAfterResize(this);

	var theGrid = this;
	addControlEvent(this.element,  "keydown", function(event) { gridControl_onKeyDown(theGrid, event); });
	addControlEvent(this.bodySpace,"scroll",  function(event) { gridControl_onBodyScroll(theGrid, event); });

	return this;
};

/// jsonParameters
/// { fullControlName: <string>,
///   columns: [ <columnDescriptor>, ... ]
/// }
function gridControl_Initialize(jsonParameters)
{
	//alert(jsonParameters);
	var P = JSON.parse(jsonParameters);
	var grid = new gridControl(P.fullControlName);
	grid.layout = P;
	grid.createHeaderRow();
	//gridControl_InitHeader(grid);
}

function gridControl_Update(jsonParameters)
{
	//alert(jsonParameters);
	var P = JSON.parse(jsonParameters);
	var grid = gridControl(P.fullControlName);
	grid.clear();
	grid.layout = P;
	grid.createHeaderRow();
	//gridControl_InitHeader(grid);
}


function getGridControlFromCell(cell)
{
	var cellId = cell.id;
    return gridControl(cellId.split('$')[0]);
}

function gridControl_OnAfterResize(grid)
{
	if (typeof grid == 'string') grid = gridControl(grid);

	var myCy = parseInt(grid.element.offsetHeight);
	var myCx = parseInt(grid.element.offsetWidth);

	var y = grid.headerSpace.offsetHeight;
	var cy = myCy - y;
	var cxToolSpace = grid.getToolSpaceWidth();
	var cxBodySpace = myCx - cxToolSpace;

	grid.headerSpace.style.width = cxBodySpace.toString() + "px";

	grid.bodySpace.style.width = cxBodySpace.toString() + "px";
	grid.bodySpace.style.top = y.toString() + "px";
	grid.bodySpace.style.height = cy.toString() + "px";
	
	grid.menuSpace.style.left = (cxBodySpace - getScrollbarWidth()).toString() + "px";
	grid.menuSpace.style.width = (cxToolSpace + getScrollbarWidth()).toString() + "px";
	grid.menuSpace.style.top = "0";
	grid.menuSpace.style.height = y.toString() + "px";
	
	grid.toolSpace.style.left = cxBodySpace.toString() + "px";
	grid.toolSpace.style.width = cxToolSpace.toString() + "px";
	grid.toolSpace.style.top = y.toString() + "px";
	grid.toolSpace.style.height = cy.toString() + "px";
}

function gridControl_onBodyScroll(grid, event)
{
	//alert("gridControl_onBodyScroll-1");
	var newLeft = grid.bodySpace.scrollLeft;
	var elementToScroll = grid.headerContainer.firstElementChild;
	elementToScroll.style.left = (-newLeft).toString() + "px";
	elementToScroll.style.position = "relative";
	//alert("gridControl_onBodyScroll-4");
}

function gridControl_addToolImage(grid, part, imgName)
{
	var img = xmlCreateElement(part, "img");
	img.src = "icon24_" + imgName + ".png";
	img.alt = imgName;
	img.title = imgName;
	img.onclick = function() { gridControl_handleToolCommand(grid, imgName); };
}

async function gridControl_markSelectedRow(grid)
{
	var rows = grid.getRows();
	if (rows)
	{
		var selectedRow = grid.selectedRow;
		var len = rows.length;
		for (var i = 0; i < len; i++)
		{
			var row = rows[i];
			var cls = getBaseClassName(row);
			if (row.rowId == selectedRow)
				row.setAttribute("class", cls + " gridSelectedBodyRow");
			else
				row.setAttribute("class", cls);
		}
	}
}

/// Navigationstasten und spezielle Tasten filtern
function gridControl_onKeyDown(grid, event)
{
	if (typeof grid == 'string') grid = gridControl(grid);

	switch (event.key)
	{
		case "ArrowUp":
		case "ArrowDown":
		case "PageUp":
		case "PageDown":
		case "F2":
		case "F3":
		case "F4":
			event.preventDefault();
			gridControl_handleSpecialKey(grid, event.key);
			break;

		case "End":
		case "Home":
		case "Delete":
		case "Insert":
			if (event.ctrlKey)
			{
				event.preventDefault();
				gridControl_handleSpecialKey(grid, event.key);
			}
			break;
	}
}

/// jsonParameters
/// { fullControlName: <string>,
///   dropExisting: <integer>
///   setFocus: <integer>
///   beforeId: <string>
///   rowIdToSelect: <string>
///   rowsToInsert: [ <rowDescriptor>, ... ]
///   rowsToAppend: [ <rowDescriptor>, ... ]
///   rowsToRemove: [ <rowDescriptor>, ... ]
///   rowsToUpdate: [ <rowDescriptor>, ... ]
/// }
function gridControl_modifyRows(jsonParameters)
{
	var P = parseParameters(jsonParameters);
	//alert(JSON.stringify(P));
	var grid = gridControl(P.fullControlName);
	var bSetFocus = grid.hasFocus() || (P.setFocus && parseIntEx(P.setFocus));
	var toSelect = "";

	// remove all existing ?
	if (P.dropExisting && parseInt(P.dropExisting))
	{
		grid.clearRows();
	}

	// insert rows ?
	var rowsToInsert = P.rowsToInsert;
	if (rowsToInsert)
	{
		var fromId = P.beforeId;
		var rowFrom = fromId ? grid.getRowByRowId(fromId) : grid.getFirstRow();
		var len = rowsToInsert.length;
		for (var i = 0; i < len; i++)
		{	
			var newGridRow = grid.createRow(rowsToInsert[i]);
			grid.bodyContainer.insertBefore(newGridRow, rowFrom);
			if (rowsToInsert[i].selected && parseInt(rowsToInsert[i].selected))
				toSelect = newGridRow.rowId;
		}
	}

	// append new rows ?
    var rowsToAppend = P.rowsToAppend;
	if (rowsToAppend)
	{
		var len = rowsToAppend.length;
		for (var i = 0; i < len; i++)
		{	
			var newGridRow = grid.createRow(rowsToAppend[i]);
			grid.bodyContainer.appendChild(newGridRow);
			if (rowsToAppend[i].selected && parseInt(rowsToAppend[i].selected))
				toSelect = newGridRow.rowId;
		}
	}

	// remove rows exlicit ?
    var rowsToRemove = P.rowsToRemove;
	if (rowsToRemove)
	{
		var len = rowsToRemove.length;
		for (var i = 0; i < len; i++)
			grid.deleteRow(rowsToRemove[i].rowId);
	}

	// update existings rows ?
    var rowsToUpdate = P.rowsToUpdate;
	if (rowsToUpdate)
	{
		var len = rowsToUpdate.length;
		for (var i = 0; i < len; i++)
		{	
			var gridRow = grid.getRowByRowId(rowsToUpdate[i].rowId);
			if (gridRow)
			{
				grid.updateRow(gridRow, rowsToUpdate[i]);
				if (rowsToUpdate[i].selected && parseInt(rowsToUpdate[i].selected))
					toSelect = gridRow.rowId;
			}
		}
	}

	// select explicit by rowId ?
	if (typeof P.rowIdToSelect == "string")
	{
		toSelect = P.rowIdToSelect;
	}

	// select row to active
	if (toSelect != "") 
	{
		// alert("select " + toSelect);
		grid.selectRow(toSelect, bSetFocus);
	}
	// nur Focus setzen
	else if (bSetFocus)
	{
		grid.setFocus();
	}
}

/// jsonParameters
/// { fullControlName: <string>,
///   number: <integer>
///   unmarkOthers: <integer>
/// }
function gridControl_markColumn(jsonParameters)
{
	var P = parseParameters(jsonParameters);
	var grid = gridControl(P.fullControlName);
	grid.markColumn(P.number, parseIntEx(P.unmarkOthers));
}

/// jsonParameters
/// { fullControlName: <string>,
///   rowId <string>
///   setFocus <integer>
/// }
function gridControl_selectRow(jsonParameters)
{
	var P = parseParameters(jsonParameters);
	P.rowIdToSelect = P.rowId;
	gridControl_modifyRows(P);
}

/// jsonParameters
/// { fullControlName: <string>,
/// }
function gridControl_setFocus(jsonParameters)
{
	var P = JSON.parse(jsonParameters);
	var grid = gridControl(P.fullControlName);
	grid.setFocus();
}

/// wird von einem untergeordneten Control aufgerufen
function gridControl_cellNotify(cell, eventName, data)
{
	var cellId = cell.id;
	var gridId = cellId.split('$')[0];
    var grid = gridControl(gridId);
	var row = cell.parentElement;
	var rowId = row.rowId;
	var columnNumber = cell.number;

	switch (eventName)
	{
	case "onSetFocus":
		if ((grid.selectedRow != rowId) || (grid.selectedColumn != columnNumber))
		{
			if (grid.selectedRow != rowId)
			{
				grid.selectRow(rowId, true);
				// gridControl_raiseEvent(gridId, "onChange", rowNumber, columnNumber, data);
			}
			if (grid.selectedColumn != columnNumber)
			{
				grid.selectColumn(columnNumber);
				gridControl_raiseEvent(gridId, "onColumnChange", rowId, columnNumber, data);
			}
		}
		break;
	}

	gridControl_raiseEvent(gridId, eventName, rowId, columnNumber, data);
}

/// wird aufgerufen, wenn eine Navigationstaste im gridControl eingegeben wurde.
function gridControl_handleSpecialKey(grid, key)
{
	switch(key)
	{
		case "ArrowUp":
			gridControl_rowsUp(grid, 1);
			break;
		case "ArrowDown":
			gridControl_rowsDown(grid, 1);
			break;
		case "PageUp":
			gridControl_rowsUp(grid, grid.calcLinesPerPage() - 1);
			break;
		case "PageDown":
			gridControl_rowsDown(grid, grid.calcLinesPerPage() - 1);
			break;
		case "Home":
			gridControl_goTop(grid);
			break;
		case "End":
			gridControl_goBottom(grid);
			break;
		case "F2":
			gridControl_raiseEvent(grid.element.id, "Search", grid.selectedRow, grid.selectedColumn);
			break;
		case "F3":
			gridControl_raiseEvent(grid.element.id, "Insert", grid.selectedRow, grid.selectedColumn);
			break;
		case "F4":
			gridControl_raiseEvent(grid.element.id, "onProperties", grid.selectedRow, grid.selectedColumn);
			break;
		default:
			gridControl_raiseEvent(grid.element.id, key, grid.selectedRow, grid.selectedColumn);
			break;
	}
}

function gridControl_handleHdrClick(cell)
{
	var cellId = cell.id;
	var gridId = cellId.split('$')[0];
	gridControl_raiseEvent(gridId, "onHdrClick", 0, cell.number);
}

function gridControl_handleToolCommand(grid, command)
{
	switch(command)
	{
		case "page_up":
			gridControl_rowsUp(grid, grid.calcLinesPerPage() - 1);
			break;
		case "page_down":
			gridControl_rowsDown(grid, grid.calcLinesPerPage() - 1);
			break;
		case "page_top":
			gridControl_goTop(grid);
			break;
		case "page_bottom":
			gridControl_goBottom(grid);
			break;
		case "rec_search":
			gridControl_raiseEvent(grid.element.id, "Search", grid.selectedRow, grid.selectedColumn);
			break;
		case "rec_properties":
			gridControl_raiseEvent(grid.element.id, "Properties", grid.selectedRow, grid.selectedColumn);
			break;
		case "rec_insert":
			gridControl_raiseEvent(grid.element.id, "Insert", grid.selectedRow, grid.selectedColumn);
			break;
		case "rec_delete":
			gridControl_raiseEvent(grid.element.id, "Delete", grid.selectedRow, grid.selectedColumn);
			break;
		case "menu":
			gridControl_showMenu(grid);
			break;
		default:
			gridControl_raiseEvent(grid.element.id, command, grid.selectedRow, grid.selectedColumn);
			break;
	}
}

/// Zeilen nach unten rollen
function gridControl_rowsDown(grid, n)
{
	var row = grid.getSelectedRow();
	var column = grid.getSelectedColumnId(true);
	if (!row) return;

	var rowIdToSelect = row.rowId;
	var nextRow = row.nextElementSibling;
	while (nextRow && (n > 0))
	{
		--n;
		rowIdToSelect = nextRow.rowId;
		nextRow = nextRow.nextElementSibling;
	}

	if (rowIdToSelect != row.rowId)
	{
		var nextId = grid.composeId(rowIdToSelect, column);
		var nextItem = document.getElementById(nextId);
		grid.setFocusItem(nextItem, false);
	}
	if (n > 0)
	{
		gridControl_notifyNeedData(grid, "down", row.rowId, column, n);
	}
}

/// Zeilen nach oben rollen
function gridControl_rowsUp(grid, n)
{
	var row = grid.getSelectedRow();
	var column = grid.getSelectedColumnId(true);
	if (!row) return;

	var rowIdToSelect = row.rowId;
	var nextRow = row.previousElementSibling;
	while (nextRow && (n > 0))
	{
		--n;
		rowIdToSelect = nextRow.rowId;
		nextRow = nextRow.previousElementSibling;
	}

	if (rowIdToSelect != row.rowId)
	{
		var nextId = grid.composeId(rowIdToSelect, column);
		var nextItem = document.getElementById(nextId);
		grid.setFocusItem(nextItem, true);
	}
	if (n > 0)
	{
		gridControl_notifyNeedData(grid, "up", row.rowId, column, n);
	}
}

/// Erste Zeile auswählen
function gridControl_goTop(grid)
{
	var row = grid.getSelectedRow();
	var column = grid.getSelectedColumnId(true);

	var nextRow = grid.bodyContainer.firstElementChild;
	if (nextRow)
	{
		var nextId = grid.composeId(nextRow.rowId, column);
		var nextItem = document.getElementById(nextId);
		grid.setFocusItem(nextItem, true);
	}
	gridControl_notifyNeedData(grid, "top", grid.selectedRow, column, grid.calcLinesPerPage());
}

/// Letzte Zeile auswählen
function gridControl_goBottom(grid)
{
	var row = grid.getSelectedRow();
	var column = grid.getSelectedColumnId(true);

	var nextRow = grid.bodyContainer.lastElementChild;
	if (nextRow)
	{
		var nextId = grid.composeId(nextRow.rowId, column);
		var nextItem = document.getElementById(nextId);
		grid.setFocusItem(nextItem, false);
	}
	gridControl_notifyNeedData(grid, "bottom", grid.selectedRow, column, grid.calcLinesPerPage());
}

/// sendet eine allgemeine Nachricht vom gridControl an den Host
function gridControl_raiseEvent(gridId, eventName, rowId, columnNumber, data)
{
	var msg = 
	{ msg:     eventName, 
	  control: gridId, 
	  rowId:   rowId, 
	  column:  columnNumber 
	};
	if (data) msg.data = data;
	raiseControlEvent(msg);
}

/// benachrichtigt den Host, dass Datenzeilen gelesen werden sollen.
function gridControl_notifyNeedData(grid, direction, rowId, columnNumber, count)
{
	var msg = 
	{ msg:       "NeedRows", 
	  control:   grid.element.id, 
	  rowId:     rowId, 
	  column:    columnNumber, 
	  direction: direction,
	  count:     count
	};
	raiseControlEvent(msg);
}

function gridControl_showMenu(grid)
{
	var col = grid.getSelectedColumn();
    var options = parseIntEx(col.properties) ? "101 Eigenschaften;" : "101 -Eigenschaften;"
    options += parseIntEx(col.print) ? "104 Drucken;" : "104 -Drucken;"
    options += "-;"
    options += parseIntEx(col.insert) ? "102 Neu;" : "102 -Neu;"
    options += parseIntEx(col.delete) ? "103 Entfernen;" : "103 -Entfernen;"
    options += "-;"
    options += "105 Design"

	runPopupMenu(-1, -1, options, function(nChoice)
	{
		switch(nChoice)
		{
			case 101:
				gridControl_handleToolCommand(grid, "rec_properties");
				break;
			case 102:
				gridControl_handleToolCommand(grid, "rec_insert");
				break;
			case 103:
				gridControl_handleToolCommand(grid, "rec_delete");
				break;
			case 104:
				gridControl_handleToolCommand(grid, "Print");
				break;
			case 105:
				gridControl_handleToolCommand(grid, "Design");
				break;
		}
	});
}
