/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ui.common.table;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
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.Item;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
/**
* DoubleClickTableViewer is a hack into TableViewer that changes it's hard-coded single-click to edit behavior into double-click
* to edit. It works by intercepting the CellModifier and wrapping it with a DoubleClickCellModifier, which basically disables
* cell editing unless a double-click occurs. Then this class hooks up a double-click mouse listener to the table and directly
* calls editElement on the TableViewer.
*
* @since 8.0
*/
public class DoubleClickTableViewer extends TableViewer {
boolean editEnabled = false;
private Table tableControl;
/**
* Construct an instance of DoubleClickTableViewer.
*
* @param parent
* @param style
*/
public DoubleClickTableViewer( Composite parent,
int style ) {
super(parent, style);
}
/**
* @see org.eclipse.jface.viewers.ContentViewer#hookControl(org.eclipse.swt.widgets.Control)
*/
@Override
protected void hookControl( Control control ) {
super.hookControl(control);
// hook up a double-click listener
tableControl = (Table)control;
tableControl.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick( MouseEvent e ) {
activateEdit(e);
}
});
}
protected void activateEdit( MouseEvent e ) {
// calculate the column from the mouse location
int columnToEdit;
int columns = tableControl.getColumnCount();
if (columns == 0) {
// If no TableColumn, Table acts as if it has a single column
// which takes the whole width.
columnToEdit = 0;
} else {
columnToEdit = -1;
Item[] selection = tableControl.getSelection();
if (selection.length != 1) return;
TableItem tableItem = (TableItem)selection[0];
for (int i = 0; i < columns; i++) {
Rectangle bounds = tableItem.getBounds(i);
if (bounds.contains(e.x, e.y)) {
columnToEdit = i;
break;
}
}
if (columnToEdit == -1) {
return;
}
}
// allow the DoubleClickCellModifier to edit the value
this.editEnabled = true;
// call editElement directly on the TableViewer
renameInline(columnToEdit);
}
public void renameInline( int columnToEdit ) {
// call editElement directly on the TableViewer
IStructuredSelection selection = (IStructuredSelection)super.getSelection();
Object element = selection.getFirstElement();
this.editEnabled = true;
super.editElement(element, columnToEdit);
// disable the DoubleClickCellModifier's canModify method once the cell editor is finished
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
editEnabled = false;
}
});
}
/**
* @see org.eclipse.jface.viewers.TableViewer#setCellModifier(org.eclipse.jface.viewers.ICellModifier)
*/
@Override
public void setCellModifier( ICellModifier modifier ) {
super.setCellModifier(new DoubleClickCellModifier(modifier));
}
/**
* DoubleClickCellModifier is a wrapper for a real ICellModifier that answers false to canModify when a single-click occurs on
* the table. This is necessary to disable the single-click-to-edit behavior that is hard-coded into TableViewer.
*/
class DoubleClickCellModifier implements ICellModifier {
private ICellModifier delegate;
public DoubleClickCellModifier( ICellModifier modifier ) {
delegate = modifier;
}
@Override
public boolean canModify( Object element,
String property ) {
// check the outer class
if (editEnabled) {
// check the delegate
return delegate.canModify(element, property);
}
return false;
}
@Override
public Object getValue( Object element,
String property ) {
return delegate.getValue(element, property);
}
@Override
public void modify( Object element,
String property,
Object value ) {
delegate.modify(element, property, value);
}
}
}