How to navigate down with enter key in SWT TableViewer
Asked Answered
A

1

2

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?

Arm answered 16/9, 2011 at 11:42 Comment(0)
A
3

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.

  1. v.getTable().showColumn(v.getTable().getColumn(nextCell.getColumnIndex())); where is the table viewer object. Now this approach normally works with the simple keys like SWT.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.
  2. 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",
                "[email protected]", "M");
        elements[1] = new Person("Boris", "Bokowski",
                "[email protected]","M");
        elements[2] = new Person("Tod", "Creasey", "[email protected]","M");
        elements[3] = new Person("Wayne", "Beaton", "[email protected]","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;
    }

}
Acquaintance answered 28/9, 2011 at 20:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.