/* * Copyright (C) 2006 Davy Vanherbergen * dvanherbergen@users.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package net.sourceforge.sqlexplorer.dataset; import net.sourceforge.sqlexplorer.Messages; import net.sourceforge.sqlexplorer.plugin.SQLExplorerPlugin; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableCursor; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; 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.KeyListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; /** * Provides keyboard features for DataSetTable: * <ul> * <li>F5: refresh table</li> * <li>CTRL-C: copy active cell</li> * <li>CTRL-F: column name finder assistant (use F3 to skip to next match) </li> * </ul> * * @author Davy Vanherbergen */ public class DataSetTableKeyListener implements KeyListener { protected static final Log _logger = LogFactory.getLog(DataSetTableKeyListener.class); // private IDetailTab _tab = null; private Composite _parent = null; private Table _table = null; private TableCursor _cursor = null; private Shell _popup = null; private static final int CTRL_C = 3; private static final int CTRL_F = 6; private static final int ENTER = 13; private String _lastNameSearched = null; private int _lastColumnIndex = 0; /** * Create new keylistener * * @param parent * @param table * @param cursor * @param tab */ public DataSetTableKeyListener(Composite parent, Table table, TableCursor cursor) { _table = table; _parent = parent; _cursor = cursor; } /* * (non-Javadoc) * * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) */ public void keyPressed(KeyEvent e) { //_logger.fatal(Integer.toString((int)e.character)); switch (e.character) { case CTRL_C: // copy cell content to clipboard try { Clipboard clipBoard = SQLExplorerPlugin.getDefault().getConnectionsView().getClipboard(); TextTransfer textTransfer = TextTransfer.getInstance(); TableItem[] items = _table.getSelection(); if (items == null || items.length == 0) { return; } int columnIndex = _cursor.getColumn(); clipBoard.setContents(new Object[] {items[0].getText(columnIndex)}, new Transfer[] {textTransfer}); } catch (Exception ex) { SQLExplorerPlugin.error(Messages.getString("CopyColumnNameAction.error"), ex); } break; case CTRL_F: // column name typeahead createPopup(); break; } } /* * (non-Javadoc) * * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) */ public void keyReleased(KeyEvent e) { switch (e.keyCode) { case SWT.F5: // refresh tab /*if (_tab != null) { _tab.refresh(); } disposePopup(); // refresh SQL Results try { Object o = _parent.getData("parenttab"); if (o != null) { SQLExecution sqlExec = (SQLExecution) ((TabItem)o).getData(); if (sqlExec != null) { sqlExec.startExecution(); } } } catch (Exception e1) { SQLExplorerPlugin.error("Error refreshing", e1); }*/ break; case SWT.ESC: disposePopup(); break; } } /** * Display column finder popup */ private void createPopup() { _lastNameSearched = null; // recycle old popup if (_popup != null && !_popup.isDisposed()) { if (!_popup.isVisible()) { _popup.open(); } return; } // find out where to put the popup on screen Point popupLocation = _table.toDisplay(10, 40); // create new shell _popup = new Shell(_parent.getShell(), SWT.BORDER | SWT.ON_TOP); _popup.setBackground(_parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); _popup.setForeground(_parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); _popup.setSize(250, 50); _popup.setLocation(popupLocation); _popup.setLayout(new GridLayout()); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; // add 'find:' label Label label = new Label(_popup, SWT.NULL); label.setText(Messages.getString("DataSetTable.PopUp.Find")); label.setBackground(_parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); // add input field for search text final Text input = new Text(_popup, SWT.SINGLE | SWT.FILL); input.setLayoutData(gridData); input.setBackground(_parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); // scroll columns whenever something is typed in input field. input.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { Text t = (Text) e.widget; String text = t.getText(); // locate column and show if found if (jumpToColumn(text)) { input.setForeground(_parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); } else { // give some subtle feedback to user that column doesn't exist.. input.setForeground(_parent.getDisplay().getSystemColor(SWT.COLOR_RED)); } } }); // add listener so that we can jump to next column match when // user hits enter.. input.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.character == ENTER) { // scroll to next match if (jumpToColumn(null)) { input.setForeground(_parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); } else { // give some subtle feedback to user that column doesn't exist.. input.setForeground(_parent.getDisplay().getSystemColor(SWT.COLOR_RED)); } } } }); // close popup when user is no longer in inputfield input.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { disposePopup(); } }); // activate popup _popup.open(); _popup.forceActive(); } /** * Close column finder popup; */ private void disposePopup() { if (_popup != null && !_popup.isDisposed()) { _popup.close(); _popup.dispose(); _popup = null; } } /** * Jump to next availabel column with header name. * If the same name is processed again, we jump to * the next column with the same name. If no further columns * are available, we jump to first available column again. * * @param name of column to jump to. * @return true if a matching column was found */ private boolean jumpToColumn(String name) { String text = null; if (name != null) { // use input to find column text = name.toLowerCase().trim(); _lastNameSearched = text; _lastColumnIndex = 0; } else { // use previous name to search text = _lastNameSearched; _lastColumnIndex += 1; } if (text == null) { text = "";//$NON-NLS-1$ } TableColumn[] columns = _table.getColumns(); if (columns == null || _lastColumnIndex >= columns.length) { // no columns or we searched them all.. _lastColumnIndex = 0; return false; } boolean columnFound = false; // find column for (int i = _lastColumnIndex; i < columns.length; i++) { TableColumn column = columns[i]; if (column.getText().toLowerCase().startsWith(text)) { columnFound = true; // first scroll all the way to right _table.showColumn(columns[columns.length - 1]); // now back to the column we want, this way it should be // the first column visible in most cases _table.showColumn(column); // move cursor to found column if (_table.getItemCount() > 0) { _cursor.setSelection(0, i); _cursor.setVisible(true); } // store column index so we can pickup where we left of // in case of repeated search _lastColumnIndex = i; break; } } // reset search to start from start again if (!columnFound) { _lastColumnIndex = 0; } return columnFound; } }