package bndtools.editor.common; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.widgets.Table; /** * Well ... the JFace <CODE>TableViewer<CODE> class does not provide * text celleditor keyboard support like if TAB is pressed in a column, * the focus does not go into the next column etc., * * After observing JDT method signature refactoring widget which does the * desired keyboard support, a generic utility listener has been developed * on the same lines. * * Usage goes as ... * * <P><PRE><CODE> * * TableViewer tblViewer = new TableViewer(SWT.SINGLE | SWT.FULL_SELECTION | SWT.| SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER) * ... * CellEditor[] cellEditors = ... * ... * tblViewer.setCellEditors(cellEditors); * * TableViewerKeyBoardSupporter supporter = new TableViewerKeyBoardSupporter(tblViewer); * supporter.startSupport(); * * </CODE></PRE></P> */ public class TableViewerKeyBoardSupporter { protected TableViewer fTableViewer = null; public TableViewerKeyBoardSupporter(TableViewer tableViewer) { fTableViewer = tableViewer; } /** * After the cell editors have been set on tableviewer, this method should be called to start giving keyboard * support. */ public void startSupport() { /* add table key listener */ getTable().addKeyListener(new TableKeyListener(this)); /* add table traverse listener */ getTable().addTraverseListener(new TableTraverseListener(this)); /* add table-textcelleditors key and traverse listeners */ CellEditor[] cellEditors = fTableViewer.getCellEditors(); if (cellEditors != null) { for (int colIndex = 0; colIndex < cellEditors.length; colIndex++) { CellEditor cellEditor = cellEditors[colIndex]; if (cellEditor != null) { // cellEditor.getControl().addKeyListener(new // CellEditorKeyListener(this, cellEditor, colIndex)); cellEditor.getControl().addTraverseListener(new CellEditorTraverseListener(this, cellEditor, colIndex)); } } } } protected TableViewer getTableViewer() { return fTableViewer; } protected Table getTable() { return fTableViewer.getTable(); } protected int nextColumn(int column) { return (column >= getTable().getColumnCount() - 1) ? 0 : column + 1; } protected int prevColumn(int column) { return (column <= 0) ? getTable().getColumnCount() - 1 : column - 1; } protected void editColumnOrNextPossible(final int column) { Object selectedElem = getSelectedElement(); if (selectedElem == null) return; int nextColumn = column; do { fTableViewer.editElement(selectedElem, nextColumn); if (fTableViewer.isCellEditorActive()) return; nextColumn = nextColumn(nextColumn); } while (nextColumn != column); } protected void editColumnOrPrevPossible(int column) { Object selectedElem = getSelectedElement(); if (selectedElem == null) return; int prevColumn = column; do { fTableViewer.editElement(selectedElem, prevColumn); if (fTableViewer.isCellEditorActive()) return; prevColumn = prevColumn(prevColumn); } while (prevColumn != column); } private Object getSelectedElement() { IStructuredSelection selection = (IStructuredSelection) fTableViewer.getSelection(); if (selection == null || selection.isEmpty()) return null; return selection.getFirstElement(); } } class CellEditorKeyListener extends KeyAdapter { private TableViewerKeyBoardSupporter fKeyBoardSupporter = null; private CellEditor fEditor = null; private int fEditorColumn = -1; public CellEditorKeyListener(TableViewerKeyBoardSupporter keyBoardSupporter, CellEditor editor, int editorColumn) { fKeyBoardSupporter = keyBoardSupporter; fEditor = editor; fEditorColumn = editorColumn; } @Override public void keyPressed(KeyEvent e) { if (e.stateMask == SWT.MOD1 || e.stateMask == SWT.MOD2) { if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN) { // allow starting multi-selection even if in edit mode fEditor.deactivate(); e.doit = false; return; } } if (e.stateMask != SWT.NONE) return; switch (e.keyCode) { case SWT.ARROW_DOWN : e.doit = false; int nextRow = fKeyBoardSupporter.getTable().getSelectionIndex() + 1; if (nextRow >= fKeyBoardSupporter.getTable().getItemCount()) break; fKeyBoardSupporter.getTable().setSelection(nextRow); fKeyBoardSupporter.editColumnOrPrevPossible(fEditorColumn); break; case SWT.ARROW_UP : e.doit = false; int prevRow = fKeyBoardSupporter.getTable().getSelectionIndex() - 1; if (prevRow < 0) break; fKeyBoardSupporter.getTable().setSelection(prevRow); fKeyBoardSupporter.editColumnOrPrevPossible(fEditorColumn); break; case SWT.F2 : e.doit = false; fEditor.deactivate(); break; default : break; } } } class CellEditorTraverseListener implements TraverseListener { private TableViewerKeyBoardSupporter fKeyBoardSupporter = null; private CellEditor fEditor = null; private int fEditorColumn = -1; public CellEditorTraverseListener(TableViewerKeyBoardSupporter keyBoardSupporter, CellEditor editor, int editorColumn) { fKeyBoardSupporter = keyBoardSupporter; fEditor = editor; fEditorColumn = editorColumn; } /* * (non-Javadoc) * @see org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse.swt. events.TraverseEvent) */ public void keyTraversed(TraverseEvent e) { switch (e.detail) { case SWT.TRAVERSE_TAB_NEXT : fKeyBoardSupporter.editColumnOrNextPossible(fKeyBoardSupporter.nextColumn(fEditorColumn)); e.detail = SWT.TRAVERSE_NONE; break; case SWT.TRAVERSE_TAB_PREVIOUS : fKeyBoardSupporter.editColumnOrPrevPossible(fKeyBoardSupporter.prevColumn(fEditorColumn)); e.detail = SWT.TRAVERSE_NONE; break; case SWT.TRAVERSE_ESCAPE : fKeyBoardSupporter.getTableViewer().cancelEditing(); e.detail = SWT.TRAVERSE_NONE; break; case SWT.TRAVERSE_RETURN : fEditor.deactivate(); e.detail = SWT.TRAVERSE_NONE; break; default : break; } } } class TableTraverseListener implements TraverseListener { private TableViewerKeyBoardSupporter fKeyBoardSupporter = null; public TableTraverseListener(TableViewerKeyBoardSupporter keyBoardSupporter) { fKeyBoardSupporter = keyBoardSupporter; } /* * (non-Javadoc) * @see org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse.swt. events.TraverseEvent) */ public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_RETURN && e.stateMask == SWT.NONE) { fKeyBoardSupporter.editColumnOrNextPossible(0); e.detail = SWT.TRAVERSE_NONE; } } } class TableKeyListener extends KeyAdapter { private TableViewerKeyBoardSupporter fKeyBoardSupporter = null; public TableKeyListener(TableViewerKeyBoardSupporter keyBoardSupporter) { fKeyBoardSupporter = keyBoardSupporter; } /* * (non-Javadoc) * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events. KeyEvent) */ @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.F2 && e.stateMask == SWT.NONE) { fKeyBoardSupporter.editColumnOrNextPossible(0); e.doit = false; } } }