How to navigate down with enter key in SWT TableViewer
I have a TableViewer
and want the selection to go down one cell when I press the enter key, much like in MS Excel. I implemented my own CellNavigationStrategy
with the following findSelectedCell
.
public ViewerCell findSelectedCell(ColumnViewer viewer,
ViewerCell currentSelectedCell, Event event) {
if (event.type == ColumnViewerEditorActivationEvent.KEY_PRESSED) {
if (event.keyCode == SWT.CR
|| event.keyCode == SWT.KEYPAD_CR) {
ViewerCell nextCell = currentSelectedCell
.getNeighbor(ViewerCell.BELOW, false);
return nextCell;
}
}
return null;
}
This works pretty well as long as I have ViewerCell.LEFT
or ViewerCell.RIGHT
.
When I try ViewerCell.ABOVE
or ViewerCell.BELOW
nextCell
is actually set to the
cell above or below, but in the GUI the selection stays at currentSelectedCell
.
The API-Documentation for findSelectedCell says:
Returns:
the cell which is highlighted next or null if the default implementation is taken. E.g. it's fairly impossible to react on PAGE_DOWN requests
I do not understand what that sentence means. Can anyone exlain to me why it 开发者_开发知识库is not possible to set the selection to a cell below or above?
When I try ViewerCell.ABOVE or ViewerCell.BELOW nextCell is actually set to the cell above or below, but in the GUI the selection stays at currentSelectedCell.
You have to explicitly set the current selection after the KEY_PRESSED
event. Now there are two ways to do it.
v.getTable().showColumn(v.getTable().getColumn(nextCell.getColumnIndex()));
where is thetable viewer
object. Now this approach normally works with the simple keys likeSWT.ARROW_DOWN
,SWT.ARROW_UP
etc. But carriage return i.e.SWT.CR
usually has some special meaning like submitting a form, pressing a default button on the composite etc. I haven't checked thoroughly but my gut feeling says it is handled by some other handler and hence you lose focus.- For
SWT.CR
use this:v.getTable().setSelection(((TableItem)nextCell.getItem()));
Also you have to override the CellNavigationStrategy.isNavigationEvent()
, otherwise SWT.CR
and SWT.KEYPAD_CR
would be ignored. For example:
@Override
public boolean isNavigationEvent(ColumnViewer viewer, Event event) {
return event.keyCode == SWT.CR || event.keyCode == SWT.KEYPAD_CR;
}
I do not understand what that sentence means.
It means that if you are going to use the default implementation of CellNavigationStrategy
, which is shipped with JFace then it is not possible to handle the SWT.PAGE_DOWN
key press event. The reason is that it is not handled in CellNavigationStrategy.isNavigationEvent()
(see its implementation for more details).
See the full working code below:
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.*;
public class CellNavTest {
public CellNavTest(Shell shell)
{
final TableViewer v = new TableViewer(shell, SWT.BORDER | SWT.FULL_SELECTION);
v.setContentProvider(new MyContentProvider());
TableViewerColumn column = new TableViewerColumn(v, SWT.NONE);
column.getColumn().setWidth(200);
column.getColumn().setText("Givenname");
column.getColumn().setMoveable(true);
column.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
return ((Person) element).givenname;
}
});
column = new TableViewerColumn(v, SWT.NONE);
column.getColumn().setWidth(200);
column.getColumn().setText("Surname");
column.getColumn().setMoveable(true);
column.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
return ((Person) element).surname;
}
});
column = new TableViewerColumn(v, SWT.NONE);
column.getColumn().setWidth(200);
column.getColumn().setText("E-Mail");
column.getColumn().setMoveable(true);
column.setLabelProvider(new ColumnLabelProvider() {
public String getText(Object element) {
return ((Person) element).email;
}
});
CellNavigationStrategy naviStrat = new CellNavigationStrategy()
{
@Override
public boolean isNavigationEvent(ColumnViewer viewer, Event event) {
return event.keyCode == SWT.CR || event.keyCode == SWT.KEYPAD_CR;
}
public ViewerCell findSelectedCell(ColumnViewer viewer, ViewerCell currentSelectedCell, Event event)
{
if (event.type == ColumnViewerEditorActivationEvent.KEY_PRESSED) {
if (event.keyCode == SWT.CR || event.keyCode == SWT.KEYPAD_CR)
{
ViewerCell nextCell = currentSelectedCell.getNeighbor(ViewerCell.BELOW, false);
if(nextCell != null)
{
/*
* START
* Shows the column. If the column is already showing in the receiver, this method simply returns.
* Otherwise, the columns are scrolled until the column is visible. So when you press enter it will just
* return the same column index and hence as per javadoc it will just return.
*/
//System.out.println(nextCell.getColumnIndex());
//v.getTable().showColumn(v.getTable().getColumn(nextCell.getColumnIndex()));
/*
* END
*/
if(nextCell.getItem() instanceof TableItem)
v.getTable().setSelection(((TableItem)nextCell.getItem()));
}
return nextCell;
}
}
return null;
}
};
new TableViewerFocusCellManager(v, new FocusCellOwnerDrawHighlighter(v), naviStrat);
Person[] model = createModel();
v.setInput(model);
v.getTable().setLinesVisible(true);
v.getTable().setHeaderVisible(true);
}
private Person[] createModel() {
Person[] elements = new Person[4];
elements[0] = new Person("Tom", "Schindl",
"tom.schindl@bestsolution.at", "M");
elements[1] = new Person("Boris", "Bokowski",
"Boris_Bokowski@ca.ibm.com","M");
elements[2] = new Person("Tod", "Creasey", "Tod_Creasey@ca.ibm.com","M");
elements[3] = new Person("Wayne", "Beaton", "wayne@eclipse.org","M");
return elements;
}
/**
* @param args
*/
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
new CellNavTest(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
class MyContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
return (Person[]) inputElement;
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
class Person {
public String givenname;
public String surname;
public String email;
public String gender;
public Person(String givenname, String surname, String email, String gender) {
this.givenname = givenname;
this.surname = surname;
this.email = email;
this.gender = gender;
}
}
精彩评论