blob: 50ded8701cd040e1ed5cb87170840190c57ad6b2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 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.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.provisional.IAsynchronousRequestMonitor;
import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IBaseLabelProvider;
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.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
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.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 FocusAdapter fEditorFocusListener;
private KeyAdapter fEditorKeyListener;
private boolean fPendingFormatViewer;
public AsyncTableRenderingViewer(AbstractAsyncTableRendering rendering, Composite parent, int style) {
super(parent, style);
fRendering = rendering;
getTable().addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
handleTableMouseEvent(e);
}});
createCursor(getTable());
}
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() {
public void keyPressed(KeyEvent e)
{
handleCursorKeyPressed(e);
}
};
fTableCursor.addKeyListener(fCursorKeyAdapter);
fCursorTraverseListener = new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
handleCursorTraverseEvt(e);
}};
fTableCursor.addTraverseListener(fCursorTraverseListener);
fCursorMouseListener = new MouseAdapter() {
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() {
public void widgetDisposed(DisposeEvent e) {
if (fTableCursor == null)
return;
fTableCursor.removeTraverseListener(fCursorTraverseListener);
fTableCursor.removeKeyListener(fCursorKeyAdapter);
fTableCursor.removeMouseListener(fCursorMouseListener);
fTableCursor.removeSelectionListener(fCursorSelectionListener);
}});
fCursorSelectionListener = new SelectionAdapter() {
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)
{
String initialValue = String.valueOf(event.character);
activateCellEditor(initialValue);
return;
}
}
}
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 (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
System.out.println(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$
public IStatus runInUIThread(IProgressMonitor monitor) {
try {
if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
System.out.println(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 (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
{
System.out.println(getRendering() + " set cursor selection, row is " + getTable().getItem(newLocation[0]).getData()); //$NON-NLS-1$
System.out.println(getRendering() + " set cursor selection, model is " + getVirtualContentModel().getElement(newLocation[0])); //$NON-NLS-1$
}
fTableCursor.setSelection(newLocation[0], newLocation[1]);
showTableCursor(true);
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
* @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;
}
protected synchronized void preservingSelection(Runnable updateCode) {
Object oldTopIndexKey = null;
if (getPendingSetTopIndexKey() == null) {
// preserve selection
oldTopIndexKey = getTopIndexKey();
}
else
{
oldTopIndexKey = getPendingSetTopIndexKey();
}
Object oldSelectionKey = null;
try {
if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
{
if (oldTopIndexKey != null)
System.out.println(getRendering() + " preserve top index: " + ((BigInteger)oldTopIndexKey).toString(16)); //$NON-NLS-1$
else
System.out.println("top index key is null, nothing to preserve"); //$NON-NLS-1$
}
if (fPendingSelection != null)
oldSelectionKey = fPendingSelection;
else
oldSelectionKey = getSelectionKey();
if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
{
if (oldTopIndexKey != null)
System.out.println(getRendering() + " preserve selection: " + ((BigInteger)oldSelectionKey).toString(16)); //$NON-NLS-1$
else
System.out.println("selection key is null, nothing to preserve"); //$NON-NLS-1$
}
// perform the update
updateCode.run();
} finally {
if (oldSelectionKey != null)
{
if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
System.out.println(getRendering() + " preserved selection " + ((BigInteger)oldSelectionKey).toString(16)); //$NON-NLS-1$
setSelection(oldSelectionKey);
}
if (getPendingSetTopIndexKey() != null)
{
if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
System.out.println(getRendering() + " finished top index: " + ((BigInteger)oldTopIndexKey).toString(16)); //$NON-NLS-1$
setTopIndex(getPendingSetTopIndexKey());
}
else if (oldTopIndexKey != null)
{
setTopIndex(oldTopIndexKey);
if (AsyncVirtualContentTableViewer.DEBUG_DYNAMIC_LOADING)
System.out.println(getRendering() + " finished top index: " + ((BigInteger)oldTopIndexKey).toString(16)); //$NON-NLS-1$
}
}
}
public void dispose()
{
super.dispose();
if (!fTableCursor.isDisposed())
{
fCursorEditor.dispose();
fTableCursor.removeTraverseListener(fCursorTraverseListener);
fTableCursor.removeKeyListener(fCursorKeyAdapter);
fTableCursor.removeMouseListener(fCursorMouseListener);
}
}
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$
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 prefill it with initial value.
* If initialValue is null, use cell content as initial value
* @param initialValue
*/
private void activateCellEditor(String initialValue) {
int col = fTableCursor.getColumn();
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);
// The cell modifier canModify function always returns false if the edit action
// is not invoked from here. This is to prevent data to be modified when
// the table cursor loses focus from a cell. By default, data will
// be changed in a table when the cell loses focus. This is to workaround
// this default behaviour and only change data when the cell editor
// is activated.
((AsyncTableRenderingCellModifier)cellModifier).setEditActionInvoked(true);
boolean canEdit = cellModifier.canModify(element, (String)property);
((AsyncTableRenderingCellModifier)cellModifier).setEditActionInvoked(false);
if (!canEdit)
return;
// activate based on current cursor position
TextCellEditor selectedEditor = (TextCellEditor)getCellEditors()[col];
if (selectedEditor != null)
{
// The control that will be the editor must be a child of the Table
Text text = (Text)selectedEditor.getControl();
String cellValue = null;
if (initialValue != null)
{
cellValue = initialValue;
}
else
{
cellValue = ((String)value);
}
text.setText(cellValue);
fCursorEditor.horizontalAlignment = SWT.LEFT;
fCursorEditor.grabHorizontal = true;
// Open the text editor in selected column of the selected row.
fCursorEditor.setEditor (text, tableItem, col);
// Assign focus to the text control
selectedEditor.setFocus();
if (initialValue != null)
{
text.clearSelection();
}
text.setFont(JFaceResources.getFont(IInternalDebugUIConstants.FONT_NAME));
// add listeners for the text control
addListeners(text);
// move cursor below text control
fTableCursor.moveBelow(text);
}
}
}
/*
* @param text
*/
private void addListeners(Text text) {
fEditorFocusListener = new FocusAdapter() {
public void focusLost(FocusEvent e)
{
handleTableEditorFocusLost(e);
}
};
text.addFocusListener(fEditorFocusListener);
fEditorKeyListener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
handleKeyEventInEditor(e);
}
};
text.addKeyListener(fEditorKeyListener);
}
private void handleTableEditorFocusLost(FocusEvent event)
{
final FocusEvent e = event;
Display.getDefault().syncExec(new Runnable() {
public void run()
{
try
{
int row = indexOf(fSelectionKey);
int col = fTableCursor.getColumn();
Text text = (Text)e.getSource();
removeListeners(text);
// get new value
String newValue = text.getText();
// modify memory at fRow and fCol
modifyValue(row, col, newValue);
// show cursor after modification is completed
setSelection(fSelectionKey);
fTableCursor.moveAbove(text);
showTableCursor(true);
}
catch (NumberFormatException e1)
{
MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title,
DebugUIMessages.MemoryViewCellModifier_data_is_invalid, null);
}
}
});
}
/**
* @param event
*/
private void handleKeyEventInEditor(KeyEvent event) {
final KeyEvent e = event;
Display.getDefault().asyncExec(new Runnable()
{
public void run()
{
Text text = (Text)e.getSource();
int row = indexOf(fSelectionKey);
int col = fTableCursor.getColumn();
try
{
switch (e.keyCode)
{
case SWT.ARROW_UP :
// move text editor box up one row
if (row-1 < 0)
return;
// modify value for current cell
modifyValue(row, col, text.getText());
row--;
// update cursor location and selection in table
fTableCursor.setSelection(row, col);
handleCursorMoved();
// remove listeners when focus is lost
removeListeners(text);
activateCellEditor(null);
break;
case SWT.ARROW_DOWN :
// move text editor box down one row
if (row+1 >= getTable().getItemCount())
return;
// modify value for current cell
modifyValue(row, col, text.getText());
row++;
// update cursor location and selection in table
fTableCursor.setSelection(row, col);
handleCursorMoved();
// remove traverse listener when focus is lost
removeListeners(text);
activateCellEditor(null);
break;
case 0:
// if user has entered the max number of characters allowed in a cell, move to next cell
// Extra changes will be used as initial value for the next cell
int numCharsPerByte = fRendering.getNumCharsPerByte();
if (numCharsPerByte > 0)
{
if (text.getText().length() > fRendering.getBytesPerColumn()*numCharsPerByte)
{
String newValue = text.getText();
text.setText(newValue.substring(0, fRendering.getBytesPerColumn()*numCharsPerByte));
modifyValue(row, col, text.getText());
// if cursor is at the end of a line, move to next line
if (col >= getNumCol())
{
col = 1;
row++;
}
else
{
// move to next column
row++;
}
// update cursor position and selected address
fTableCursor.setSelection(row, col);
handleCursorMoved();
removeListeners(text);
// activate text editor at next cell
activateCellEditor(newValue.substring(fRendering.getBytesPerColumn()*numCharsPerByte));
}
}
break;
case SWT.ESC:
// if user has pressed escape, do not commit the changes
// that's why "modifyValue" is not called
fTableCursor.setSelection(row, col);
handleCursorMoved();
removeListeners(text);
// cursor needs to have focus to remove focus from cell editor
fTableCursor.setFocus();
break;
default :
numCharsPerByte = fRendering.getNumCharsPerByte();
if (numCharsPerByte > 0)
{
if (text.getText().length()> fRendering.getBytesPerColumn()* numCharsPerByte)
{
String newValue = text.getText();
text.setText(newValue.substring(0,fRendering.getBytesPerColumn()* numCharsPerByte));
modifyValue(row, col, text.getText());
// 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();
removeListeners(text);
activateCellEditor(newValue.substring(fRendering.getBytesPerColumn()*numCharsPerByte));
}
}
break;
}
}
catch (NumberFormatException e1)
{
MemoryViewUtil.openError(DebugUIMessages.MemoryViewCellModifier_failure_title,
DebugUIMessages.MemoryViewCellModifier_data_is_invalid, null);
fTableCursor.setSelection(row, col);
handleCursorMoved();
removeListeners(text);
}
}
});
}
/**
* @param text
*/
private void removeListeners(Text text) {
text.removeFocusListener(fEditorFocusListener);
text.removeKeyListener(fEditorKeyListener);
}
/**
* Modify value and send new value to debug adapter
* @param row
* @param col
* @param newValue
* @throws NumberFormatException
*/
private void modifyValue(int row, int col, String newValue) throws NumberFormatException
{
if (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.
*/
public IBaseLabelProvider getLabelProvider() {
return new ITableLabelProvider() {
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
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 ""; //$NON-NLS-1$
}
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return false;
}
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() {
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);
}
}
public void handlePresentationFailure(IAsynchronousRequestMonitor monitor, IStatus status) {
super.handlePresentationFailure(monitor, status);
}
public void refresh(boolean getContent)
{
if (getContent)
refresh();
else
{
preservingSelection(new Runnable() {
public void run() {
AbstractVirtualContentTableModel model = getVirtualContentModel();
if (model != null)
{
Object[] elements = model.getElements();
model.remove(elements);
model.add(elements);
}
}});
}
}
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.model.viewers.AsynchronousViewer#getModel()
*/
public AsynchronousModel getModel() {
return super.getModel();
}
// TODO: need pluggable model to be truly flexible
protected AbstractVirtualContentTableModel createVirtualContentTableModel() {
return new TableRenderingModel(this);
}
protected void updateComplete(IAsynchronousRequestMonitor 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() {
public void run() {
int[] coordinates = getCoordinatesFromKey(getSelectionKey());
if (coordinates.length > 0)
fTableCursor.setVisible(true);
else
fTableCursor.setVisible(false);
}});
}
}
if (!hasPendingUpdates() && fPendingFormatViewer)
{
formatViewer();
resizeColumnsToPreferredSize();
}
}
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);
}
}
}