/*******************************************************************************
 * Copyright (c) 2006, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.debug.internal.ui.views.memory.renderings;

import java.math.BigInteger;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.ui.DebugUIMessages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.memory.provisional.AbstractAsyncTableRendering;
import org.eclipse.debug.internal.ui.viewers.AbstractUpdatePolicy;
import org.eclipse.debug.internal.ui.viewers.AsynchronousModel;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IStatusMonitor;
import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableCursor;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.progress.UIJob;

public class AsyncTableRenderingViewer extends AsyncVirtualContentTableViewer {

	private AbstractAsyncTableRendering fRendering;

	// selection keys
	private Object fPendingSelection;
	private Object fSelectionKey;

	// cursor and associated listeners
	private TableCursor fTableCursor;
	private KeyAdapter fCursorKeyAdapter;
	private TraverseListener fCursorTraverseListener;
	private MouseAdapter fCursorMouseListener;
	private SelectionAdapter fCursorSelectionListener;

	// cursor editor and associated listeners
	private TableEditor fCursorEditor;
	private KeyAdapter fEditorKeyListener;
	private CellEditorListener fCellEditorListener;

	private class CellEditorListener implements ICellEditorListener {

		private CellEditor fEditor;
		private int fRow;
		private int fCol;

		public CellEditorListener(int row, int col, CellEditor editor) {
			fEditor = editor;
			fRow = row;
			fCol = col;
		}

		@Override
		public void applyEditorValue() {
			fEditor.removeListener(this);
			modifyValue(fRow, fCol, fEditor.getValue());
		}

		@Override
		public void cancelEditor() {
			fEditor.removeListener(this);
		}

		@Override
		public void editorValueChanged(boolean oldValidState,
				boolean newValidState) {
		}

		public int getRow()
		{
			return fRow;
		}

		public int getCol()
		{
			return fCol;
		}
	}

	private boolean fPendingFormatViewer;


	public AsyncTableRenderingViewer(AbstractAsyncTableRendering rendering, Composite parent, int style) {
		super(parent, style);
		fRendering = rendering;

		getTable().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent e) {
				handleTableMouseEvent(e);
			}});

		createCursor(getTable());
	}

	@Override
	public AbstractUpdatePolicy createUpdatePolicy() {
		return new AsyncTableRenderingUpdatePolicy();
	}

	public AbstractAsyncTableRendering getRendering()
	{
		return fRendering;
	}

	private void createCursor(Table table)
	{
		fTableCursor = new TableCursor(table, SWT.NONE);

		Display display = fTableCursor.getDisplay();

		// set up cursor color
		fTableCursor.setBackground(display.getSystemColor(SWT.COLOR_LIST_SELECTION));
		fTableCursor.setForeground(display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));

		fTableCursor.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));

		fCursorKeyAdapter = new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e)
			 {
			 	handleCursorKeyPressed(e);
			 }
		};

		fTableCursor.addKeyListener(fCursorKeyAdapter);

		fCursorTraverseListener = new TraverseListener() {
			@Override
			public void keyTraversed(TraverseEvent e) {
				handleCursorTraverseEvt(e);
			}};

		fTableCursor.addTraverseListener(fCursorTraverseListener);

		fCursorMouseListener = new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent e) {
				handleCursorMouseEvent(e);
			}};
		fTableCursor.addMouseListener(fCursorMouseListener);

		// cursor may be disposed before disposed is called
		// remove listeners whenever the cursor is disposed
		fTableCursor.addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(DisposeEvent e) {
				if (fTableCursor == null)
					return;
				fTableCursor.removeTraverseListener(fCursorTraverseListener);
				fTableCursor.removeKeyListener(fCursorKeyAdapter);
				fTableCursor.removeMouseListener(fCursorMouseListener);
				fTableCursor.removeSelectionListener(fCursorSelectionListener);
			}});

		fCursorSelectionListener = new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						handleCursorMoved();
					}
				};
		fTableCursor.addSelectionListener(fCursorSelectionListener);
		fCursorEditor = new TableEditor (getTable());
	}

	private void handleCursorKeyPressed(KeyEvent event)
	{
		if (event.character == '\r' && event.getSource() instanceof TableCursor)
		{
			activateCellEditor(null);
			return;
		}

		if (MemoryViewUtil.isValidEditEvent(event.keyCode))
		{
			// activate edit as soon as user types something at the cursor
			if (event.getSource() instanceof TableCursor)
			{
				int col = fTableCursor.getColumn();
				if (getCellEditors()[col] instanceof TextCellEditor)
				{
					String initialValue = String.valueOf(event.character);
					activateCellEditor(initialValue);
				}
			}
		}
	}

	private void handleCursorMouseEvent(MouseEvent e){
		if (e.button == 1)
		{
			int col = fTableCursor.getColumn();
			if (col > 0 && col <= (getNumCol()))
				activateCellEditor(null);
		}
	}

	private void handleCursorTraverseEvt(TraverseEvent e){
		if (fTableCursor.getRow() == null)
			return;

		Table table = (Table)fTableCursor.getParent();
		int row = table.indexOf(fTableCursor.getRow());
		int col = fTableCursor.getColumn();
		if (col == getNumCol() && e.keyCode == SWT.ARROW_RIGHT)
		{
			if (row + 1>= table.getItemCount())
			{
				return;
			}

			row = row +1;
			col = 0;
			fTableCursor.setSelection(row, col);
		}
		if (col <= 1 && e.keyCode == SWT.ARROW_LEFT)
		{
			if (row-1 < 0)
			{
				return;
			}

			row = row - 1;
			col = getNumCol()+1;
			fTableCursor.setSelection(row, col);
		}

		handleCursorMoved();
	}

	/**
	 * Update selected address.
	 * Load more memory if required.
	 */
	private void handleCursorMoved()
	{
		fSelectionKey = getSelectionKeyFromCursor();
		fPendingSelection = null;

		if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
			DebugUIPlugin.trace(Thread.currentThread().getName() + " cursor moved selection is: " + ((BigInteger)fSelectionKey).toString(16)); //$NON-NLS-1$
		}
		// now check to see if the cursor is approaching buffer limit
		handleScrollBarSelection();
		fireSelectionChanged(fSelectionKey);
	}

	private int getNumCol() {

		int bytesPerLine = fRendering.getBytesPerLine();
		int columnSize = fRendering.getBytesPerColumn();

		return bytesPerLine/columnSize;
	}

	/**
	 * Sets the cursor at the specified address
	 * @param key selection key
	 */
	public void setSelection(Object key)
	{
		fPendingSelection = key;
		attemptSetKeySelection();
	}

	public Object getSelectionKey()
	{
		return fSelectionKey;
	}

	private synchronized void attemptSetKeySelection()
	{
		if (fPendingSelection != null) {
            doAttemptSetKeySelection(fPendingSelection);
		}

	}

	synchronized private Object doAttemptSetKeySelection(final Object key)
	{
		if (getBufferTopKey() == null || getBufferEndKey() == null)
			return key;

		// calculate selected row address
		int[] location = getCoordinatesFromKey(key);
		if(location.length == 0)
		{
			return key;
		}

		UIJob uiJob = new UIJob("Set Cursor Selection"){ //$NON-NLS-1$

			@Override
			public IStatus runInUIThread(IProgressMonitor monitor) {
				try {
					if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
						DebugUIPlugin.trace(getRendering() + " set cursor selection " + ((BigInteger)key).toString(16)); //$NON-NLS-1$
					}
					if (fPendingSelection != null && fPendingSelection != key)
						return Status.OK_STATUS;

					if (fTableCursor.isDisposed())
						return Status.OK_STATUS;

					// by the time this is called, the location may not be valid anymore
					int[] newLocation = getCoordinatesFromKey(key);
					if (newLocation.length == 0)
					{
						Object selectionKey = getSelectionKey();
						fPendingSelection = selectionKey;
						return Status.OK_STATUS;
					}

					fSelectionKey = key;
					fPendingSelection = null;

					if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
						DebugUIPlugin.trace(getRendering() + " set cursor selection, row is " + getTable().getItem(newLocation[0]).getData()); //$NON-NLS-1$
						DebugUIPlugin.trace(getRendering() + " set cursor selection, model is " + getVirtualContentModel().getElement(newLocation[0])); //$NON-NLS-1$
					}

					fTableCursor.setSelection(newLocation[0], newLocation[1]);
					showTableCursor(true);

					// show the column for the selection
					getTable().showColumn(getTable().getColumn(newLocation[1]));

					int topIndex = getTable().getTopIndex();
					Object topKey = getVirtualContentModel().getKey(topIndex);
					setTopIndexKey(topKey);


				} catch (RuntimeException e) {

					// by the time this is called, the selection may no longer
					// get the latest selection and try to set selection again
					Object selectionKey = getSelectionKey();
					fPendingSelection = selectionKey;
					doAttemptSetKeySelection(selectionKey);
				}
				return Status.OK_STATUS;
			}};

		uiJob.setSystem(true);
		uiJob.schedule();

		return null;
	}

	/**
	 *
	 * @param key the element
	 * @return the coordinates of the key
	 * Element[0] is the row index
	 * Element[1] is the column index
	 */
	private int[] getCoordinatesFromKey(Object key)
	{
		final int row = indexOf(key);

		if (row == -1)
		{
			return new int[0];
		}

		Object element = getVirtualContentModel().getElement(row);
		final int col = columnOf(element, key);

		if (col == -1)
		{
			return new int[0];
		}
		return new int[]{row, col};
	}

	private Object getSelectionKeyFromCursor()
	{
		int idx = getTable().indexOf(fTableCursor.getRow());
		int col = fTableCursor.getColumn();

		return getVirtualContentModel().getKey(idx, col);
	}

	private Object getBufferTopKey()
	{
		return getKey(0);
	}

	private Object getBufferEndKey()
	{
		AbstractVirtualContentTableModel model = getVirtualContentModel();

		if (model != null)
			return getKey(model.getElements().length-1);
		return null;
	}

	public int indexOf(Object key)
	{
		int idx = -1;
		AbstractVirtualContentTableModel model = getVirtualContentModel();
		if (model != null)
			idx = model.indexOfKey(key);
		return idx;
	}

	private int columnOf(Object element, Object key)
	{
		int idx = -1;
		AbstractVirtualContentTableModel model = getVirtualContentModel();
		if (model != null)
		{
			idx = model.columnOf(element, key);
		}
		return idx;
	}

	public Object getKey(int index)
	{
		AbstractVirtualContentTableModel model = getVirtualContentModel();
		if (model != null)
		{
			Object key = model.getKey(index);
			return key;
		}
		return null;
	}

	public Object getKey(int row, int col)
	{
		AbstractVirtualContentTableModel model = getVirtualContentModel();
		if (model != null)
			return model.getKey(row, col);
		return null;
	}


	@Override
	protected synchronized void preservingSelection(Runnable updateCode) {
		Object oldTopIndexKey = null;

		if (getPendingSetTopIndexKey() == null) {
			// preserve selection
			oldTopIndexKey = getTopIndexKey();
		}
		else
		{
			oldTopIndexKey = getPendingSetTopIndexKey();
		}
		Object oldSelectionKey = null;
		try {
			if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING)
			{
				if (oldTopIndexKey != null) {
					DebugUIPlugin.trace(getRendering() + " preserve top index: " + ((BigInteger)oldTopIndexKey).toString(16)); //$NON-NLS-1$
				}
				else {
					DebugUIPlugin.trace("top index key is null, nothing to preserve"); //$NON-NLS-1$
				}
			}

			if (fPendingSelection != null)
				oldSelectionKey = fPendingSelection;
			else
				oldSelectionKey = getSelectionKey();

			if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING)
			{
				if (oldTopIndexKey != null) {
					DebugUIPlugin.trace(getRendering() + " preserve selection: " + ((BigInteger)oldSelectionKey).toString(16)); //$NON-NLS-1$
				}
				else {
					DebugUIPlugin.trace("selection key is null, nothing to preserve"); //$NON-NLS-1$
				}
			}

			// perform the update
			updateCode.run();

		} finally {

			if (oldSelectionKey != null)
			{
				if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
					DebugUIPlugin.trace(getRendering() + " preserved selection " + ((BigInteger)oldSelectionKey).toString(16)); //$NON-NLS-1$
				}
				setSelection(oldSelectionKey);
			}

			if (getPendingSetTopIndexKey() != null)
			{
				if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
					if (oldTopIndexKey != null) {
						DebugUIPlugin.trace(getRendering() + " finished top index: " + ((BigInteger)oldTopIndexKey).toString(16)); //$NON-NLS-1$
					}
				}
				setTopIndex(getPendingSetTopIndexKey());
			}
			else if (oldTopIndexKey != null)
			{
				setTopIndex(oldTopIndexKey);

				if (DebugUIPlugin.DEBUG_DYNAMIC_LOADING) {
					DebugUIPlugin.trace(getRendering() + " finished top index: " + ((BigInteger)oldTopIndexKey).toString(16)); //$NON-NLS-1$
				}
			}
		}
	}

	@Override
	public void dispose()
	{
		super.dispose();

		if (fTableCursor != null && !fTableCursor.isDisposed())
		{
			fCursorEditor.dispose();
			fCursorEditor = null;

			fTableCursor.removeTraverseListener(fCursorTraverseListener);
			fTableCursor.removeKeyListener(fCursorKeyAdapter);
			fTableCursor.removeMouseListener(fCursorMouseListener);
			fTableCursor.removeSelectionListener(fCursorSelectionListener);

			fTableCursor.dispose();
			fTableCursor = null;
		}
	}

	public void showTableCursor(final boolean show)
	{

		Display display = DebugUIPlugin.getDefault().getWorkbench().getDisplay();
		if (Thread.currentThread() == display.getThread())
		{
			if (!fTableCursor.isDisposed())
			{
				if (fTableCursor.isVisible() != show)
					fTableCursor.setVisible(show);
			}
		}
		else
		{
			UIJob job = new UIJob("show table cursor"){ //$NON-NLS-1$

				@Override
				public IStatus runInUIThread(IProgressMonitor monitor) {
					if (!fTableCursor.isDisposed())
					{
						if (fTableCursor.isVisible() != show)
							fTableCursor.setVisible(show);
					}
					return Status.OK_STATUS;
				}};

			job.setSystem(true);
			job.schedule();
		}
	}

	private void handleTableMouseEvent(MouseEvent e) {
		// figure out new cursor position based on here the mouse is pointing
		TableItem[] tableItems = getTable().getItems();
		TableItem selectedRow = null;
		int colNum = -1;
		int numCol = getColumnProperties().length;

		for (int j=0; j<tableItems.length; j++)
		{
			TableItem item = tableItems[j];
			if (item.getData() != null)
			{
				for (int i=0; i<numCol; i++)
				{
					Rectangle bound = item.getBounds(i);
					if (bound.contains(e.x, e.y))
					{
						colNum = i;
						selectedRow = item;
						break;
					}
				}
			}
			if (colNum >= 0)
				break;
		}

		// if column position cannot be determined, return
		if (colNum < 1)
			return;

		// handle user mouse click onto table
		// move cursor to new position
		if (selectedRow != null)
		{
			int row = getTable().indexOf(selectedRow);
			showTableCursor(true);
			fTableCursor.setSelection(row, colNum);

			// manually call this since we don't get an event when
			// the table cursor changes selection.
			handleCursorMoved();

			fTableCursor.setFocus();
		}
	}

	/**
	 * Activate cell editor and pre-fill it with initial value.
	 * If initialValue is null, use cell content as initial value
	 * @param initialValue the initial value for the cell editor
	 */
	private void activateCellEditor(String initialValue) {

		final int col = fTableCursor.getColumn();
		final int row = indexOf(fSelectionKey);

		if (row < 0)
			return;

		// do not allow user to edit address column
		if (col == 0 || col > getNumCol()) {
			return;
		}

		ICellModifier cellModifier = null;

		cellModifier = getCellModifier();

		TableItem tableItem = getTable().getItem(row);

		Object element = tableItem.getData();

		if (element != null) {
			Object property = getColumnProperties()[col];
			Object value = cellModifier.getValue(element, (String) property);
			boolean canEdit = cellModifier
					.canModify(element, (String) property);

			if (!canEdit)
				return;

			CellEditor editor = getCellEditors()[col];
			if (editor != null) {
				// The control that will be the editor must be a child of the
				// Table
				Control control = editor.getControl();

				Object cellValue = null;

				if (initialValue != null) {
					cellValue = initialValue;
				} else {
					cellValue = value;
				}

				editor.setValue(cellValue);

				fCursorEditor.horizontalAlignment = SWT.LEFT;
				fCursorEditor.grabHorizontal = true;

				// Open the editor editor in selected column of the selected
				// row.
				fCursorEditor.setEditor(control, tableItem, col);

				// Assign focus to the editor control
				editor.setFocus();

				if (initialValue != null && control instanceof Text) {
					((Text) control).clearSelection();
				}

				control.setFont(JFaceResources
						.getFont(IInternalDebugUIConstants.FONT_NAME));

				// add listeners for the editor control
				addListeners(control);

				fCellEditorListener = new CellEditorListener(row, col, editor);
				editor.addListener(fCellEditorListener);

				// move cursor below editor control
				fTableCursor.moveBelow(control);
			}
		}
	}

	private void deactivateEditor(CellEditor editor)
	{
		removeListeners(editor.getControl());
		fTableCursor.moveAbove(editor.getControl());
		fTableCursor.setFocus();
	}

	/*
	 * @param editor
	 */
	private void addListeners(Control control) {

		fEditorKeyListener = new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				handleKeyEventInEditor(e);
			}
		};

		control.addKeyListener(fEditorKeyListener);
	}

	/**
	 * @param event the key event
	 */
	private void handleKeyEventInEditor(KeyEvent event) {

		final KeyEvent e = event;
		Display.getDefault().asyncExec(new Runnable()
		{
			@Override
			public void run()
			{
				Object obj = e.getSource();
				if (obj instanceof Control)
				{
					Control control = (Control)obj;
					int row = fCellEditorListener.getRow();
					int col = fCellEditorListener.getCol();

					try
					{
						switch (e.keyCode)
						{
							case 0:
								doHandleKeyEvent(row, col);
								break;
							case SWT.ESC:
								cancelEditing(row, col);
								break;
							default :
								doHandleKeyEvent(row, col);
							break;
						}
					}
					catch (NumberFormatException e1)
					{
						MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title,
							DebugUIMessages.MemoryViewCellModifier_data_is_invalid, null);

						fTableCursor.setSelection(row, col);
						handleCursorMoved();

						removeListeners(control);
					}
				}
			}
		});
	}

	private void doHandleKeyEvent(int row, int col)
	{
		int numCharsPerByte = fRendering.getNumCharsPerByte();
		if (numCharsPerByte > 0)
		{
			Object value = getCellEditors()[col].getValue();
			if (getCellEditors()[col] instanceof TextCellEditor && value instanceof String)
			{
				String str = (String)value;

				if (str.length() > fRendering.getBytesPerColumn()*numCharsPerByte)
				{
					String newValue = str;

					CellEditor editor = getCellEditors()[col];
					editor.setValue(newValue.substring(0,fRendering.getBytesPerColumn()* numCharsPerByte));

					// We want to call modify value here to avoid race condition.
					// Relying on the editor event to modify the cell may introduce a race condition since
					// we try to activate another cell editor in this method.  If we happen to use same cell
					// editor in the next activation, the value of the editor may be incorrect when the listener gets the event.
					// We may write the wrong value in that case.  Calling modify here allows us to capture the value
					// now and send that to the model.
					fCellEditorListener.cancelEditor();
					deactivateEditor(editor);
					modifyValue(fCellEditorListener.getRow(), fCellEditorListener.getCol(), editor.getValue());

					// if cursor is at the end of a line, move to next line
					if (col >= getNumCol())
					{
						col = 1;
						row++;
					}
					else
					{
						col++;
					}

					fTableCursor.setSelection(row, col);
					handleCursorMoved();

					activateCellEditor(newValue.substring(fRendering.getBytesPerColumn()*numCharsPerByte));
				}
			}
		}
	}

	private void cancelEditing(int row, int col)
	{
		// if user has pressed escape, do not commit the changes
		// remove listener to avoid getting notified on the modify value
		fCellEditorListener.cancelEditor();
		deactivateEditor(getCellEditors()[col]);

		fTableCursor.setSelection(row, col);
		handleCursorMoved();

		// cursor needs to have focus to remove focus from cell editor
		fTableCursor.setFocus();
	}

	/**
	 * @param control the control to remove the default key listener from
	 */
	private void removeListeners(Control control) {

		control.removeKeyListener(fEditorKeyListener);
	}

	/**
	 * Modify value and send new value to debug adapter
	 * @param row the row
	 * @param col the column
	 * @param newValue the new value
	 * @throws NumberFormatException if trying to set a number value fails
	 */
	private void modifyValue(int row, int col, Object newValue) throws NumberFormatException
	{
		if (newValue instanceof String && ((String)newValue).length() == 0)
		{
			// do not do anything if user has not entered anything
			return;
		}

		if (row >= 0 && row < getTable().getItemCount())
		{
			TableItem tableItem = getTable().getItem(row);

			Object property = getColumnProperties()[col];
			getCellModifier().modify(tableItem, (String)property, newValue);
		}
	}

	public TableCursor getCursor()
	{
		return fTableCursor;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.viewers.ContentViewer#getLabelProvider()
	 * Implemented minimum to work with PrintTableRendering action.
	 * This is not a real table labe provider, only goes to the table
	 * to get the text at the specified row and column.
	 */
	@Override
	public IBaseLabelProvider getLabelProvider() {
		return new ITableLabelProvider() {

			@Override
			public Image getColumnImage(Object element, int columnIndex) {
				return null;
			}

			@Override
			public String getColumnText(Object element, int columnIndex) {
				int idx = getVirtualContentModel().indexOfElement(element);
				if (idx >= 0 )
				{
					TableItem item = getTable().getItem(idx);
					return item.getText(columnIndex);
				}
				return IInternalDebugCoreConstants.EMPTY_STRING;
			}

			@Override
			public void addListener(ILabelProviderListener listener) {
			}

			@Override
			public void dispose() {
			}

			@Override
			public boolean isLabelProperty(Object element, String property) {
				return false;
			}

			@Override
			public void removeListener(ILabelProviderListener listener) {
			}};
	}

	public void formatViewer()
	{
		if (getModel() == null || !hasPendingUpdates())
			doFormatViewer();
		else
			// do not format in the middle of an update
			// set pending update and will format when update is completed
			fPendingFormatViewer = true;
	}

	/**
	 *
	 */
	private void doFormatViewer() {
		fPendingFormatViewer = false;
		preservingSelection(new Runnable() {

			@Override
			public void run() {
				// causes the content of the table viewer to be replaced
				// without asking content adapter for content
				AbstractVirtualContentTableModel model = getVirtualContentModel();
				if (model != null)
				{
					model.handleViewerChanged();
				}
			}});
	}

	private void fireSelectionChanged(Object selectionKey)
	{
		if (selectionKey != null)
		{
			SelectionChangedEvent evt = new SelectionChangedEvent(this, new StructuredSelection(selectionKey));
			fireSelectionChanged(evt);
		}
	}

	@Override
	public void handlePresentationFailure(IStatusMonitor monitor, IStatus status) {
		super.handlePresentationFailure(monitor, status);
	}

	@Override
	public void refresh(boolean getContent)
	{
		if (getContent)
			refresh();
		else
		{
			preservingSelection(new Runnable() {

				@Override
				public void run() {
					AbstractVirtualContentTableModel model = getVirtualContentModel();
					if (model != null)
					{
						Object[] elements = model.getElements();
						model.remove(elements);
						model.add(elements);
					}
				}});
		}
	}

	@Override
	protected void tableTopIndexSetComplete() {

		if (!fTableCursor.isDisposed())
		{
			// TODO:  work around swt bug, must force a table cursor redraw after top index is changed
			// BUG 130130
			int[] coordinates = getCoordinatesFromKey(getSelectionKey());
			if (coordinates.length > 0)
				fTableCursor.setVisible(true);
			else
				fTableCursor.setVisible(false);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.AsynchronousViewer#getModel()
	 */
	@Override
	public AsynchronousModel getModel() {
		return super.getModel();
	}

	// TODO:  need pluggable model to be truly flexible
	@Override
	protected AbstractVirtualContentTableModel createVirtualContentTableModel() {
		return new TableRenderingModel(this);
	}

	@Override
	protected void updateComplete(IStatusMonitor monitor) {
		super.updateComplete(monitor);

		if (!hasPendingUpdates() && !fTableCursor.isDisposed())
		{
			attemptSetKeySelection();
			fTableCursor.redraw();

			// if the viewer has pending top index, then more updates will come in
			// and the cursor should not be redrawn yet.
			if (!hasPendingSetTopIndex())
			{
				preservingSelection(new Runnable() {

					@Override
					public void run() {

						int[] coordinates = getCoordinatesFromKey(getSelectionKey());
						if (coordinates.length > 0)
							fTableCursor.setVisible(true);
						else
							fTableCursor.setVisible(false);
					}});
			}
		}

		if (!hasPendingUpdates() && fPendingFormatViewer)
		{
			formatViewer();
			resizeColumnsToPreferredSize();
		}
	}

	@Override
	protected void clear(Widget item) {
		super.clear(item);

		// this table viewer assumes that #getData will return null
		// set data to null when clearing an item.
		// only visible item will get SET DATA event again and at that time
		// the viewer would set the data back.
		if (item instanceof TableItem)
		{
			item.setData(null);
		}
	}
}
