/* * 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.ExplorerException; import net.sourceforge.sqlexplorer.Messages; import net.sourceforge.sqlexplorer.plugin.SQLExplorerPlugin; import net.sourceforge.sqlexplorer.plugin.views.DataPreviewView; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableCursor; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.IWorkbenchPage; /** * @author Davy Vanherbergen * */ public class DataSetTable { /** * Create a new table element for a resultset in a given composite. * * @param composite canvas to draw table on * @param dataSet content of table * @param info text displayed in bottem left corner under table */ public DataSetTable(Composite parent, final DataSet dataSet, String info) throws Exception { final Composite composite = new Composite(parent, SWT.FILL); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginLeft = 0; layout.horizontalSpacing = 0; layout.verticalSpacing = 2; layout.marginWidth = 0; layout.marginHeight = 0; GridData gridData = new GridData(GridData.FILL_BOTH); gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; composite.setLayout(layout); composite.setLayoutData(gridData); // check column labels & types DataSet.Column[] columns = dataSet.getColumns(); String[] columnLabels = new String[columns.length]; for (int i = 0; i < columnLabels.length; i++) columnLabels[i] = columns[i].getCaption(); if (columnLabels == null || columnLabels.length == 0) throw new Exception(Messages.getString("DataSetTable.errorInvalid")); // create table structure final TableViewer tableViewer = new TableViewer(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.VIRTUAL); final Table table = tableViewer.getTable(); tableViewer.setColumnProperties(columnLabels); table.setItemCount(dataSet.getRows().length); // create listener for sorting Listener sortListener = new Listener() { public void handleEvent(Event e) { // determine new sort column and direction TableColumn sortColumn = table.getSortColumn(); TableColumn currentColumn = (TableColumn) e.widget; int dir = table.getSortDirection(); if (sortColumn == currentColumn) { dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; } else { table.setSortColumn(currentColumn); dir = SWT.UP; } // sort the data based on column and direction dataSet.sort(((Integer) currentColumn.getData("orignalColumnIndex")).intValue(), dir);//$NON-NLS-1$ // update data displayed in table table.setSortDirection(dir); table.clearAll(); } }; GridData tGridData = new GridData(); tGridData.horizontalSpan = 2; tGridData.grabExcessHorizontalSpace = true; tGridData.grabExcessVerticalSpace = true; tGridData.horizontalAlignment = SWT.FILL; tGridData.verticalAlignment = SWT.FILL; table.setLayoutData(tGridData); GridLayout tlayout = new GridLayout(); tlayout.numColumns = 2; tlayout.marginLeft = 0; table.setLayout(tlayout); table.setHeaderVisible(true); table.setLinesVisible(true); // store dataset for use in actions table.setData(dataSet); // add all column headers to our table for (int i = 0; i < columns.length; i++) { DataSet.Column colDef = columns[i]; // add column header TableColumn column = new TableColumn(table, colDef.isRightJustify() ? SWT.RIGHT : SWT.LEFT); column.setText(colDef.getCaption()); column.setMoveable(true); column.setResizable(true); column.addListener(SWT.Selection, sortListener); column.setData("orignalColumnIndex", new Integer(i));//$NON-NLS-1$ } tableViewer.setContentProvider(new DataSetTableContentProvider()); tableViewer.setLabelProvider(new DataSetTableLabelProvider()); tableViewer.setInput(dataSet); // add status bar labels Label infoLabel = new Label(composite, SWT.NULL); infoLabel.setText(info); infoLabel.setLayoutData(new GridData(SWT.LEFT, SWT.NULL, true, false)); final Label positionLabel = new Label(composite, SWT.NULL); positionLabel.setText("");//$NON-NLS-1$ positionLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.NULL, true, false)); // create a TableCursor to navigate around the table final TableCursor cursor = new TableCursor(table, SWT.NONE); cursor.setBackground(table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION)); cursor.setForeground(table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); cursor.setLayout(new FillLayout()); cursor.setVisible(false); cursor.addSelectionListener(new SelectionAdapter() { // when the TableEditor is over a cell, select the corresponding row in // the table public void widgetSelected(SelectionEvent e) { table.setSelection(new TableItem[] {cursor.getRow()}); cursor.setVisible(true); // update label with row/column position positionLabel.setText(Messages.getString("DatabaseDetailView.Tab.RowPrefix") + " " + (table.indexOf(cursor.getRow()) + 1) + Messages.getString("DatabaseDetailView.Tab.ColumnPrefix") + " " + (cursor.getColumn() + 1)); //$NON-NLS-2$ $NON-NLS-4$ positionLabel.getParent().layout(); positionLabel.redraw(); // Show the preview IWorkbenchPage page = SQLExplorerPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage(); if (page != null) { DataPreviewView view = (DataPreviewView)page.findView(DataPreviewView.class.getName()); if (view != null) { TableItem row = cursor.getRow(); int column = cursor.getColumn(); DataSetRow dsRow = (DataSetRow)row.getData(); Object obj = dsRow.getRawObjectValue(column); try { view.previewData(null, obj); }catch(ExplorerException ex) { SQLExplorerPlugin.error(ex.getMessage(), ex); } } } } }); // add resize listener for cursor, to stop cursor from // taking strange shapes after being table is resized cursor.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { if (cursor != null) { if (cursor.getRow() == null) { cursor.setVisible(false); } else { cursor.layout(); cursor.redraw(); cursor.setVisible(true); } } } }); table.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { Table t = (Table) e.widget; if (t.getItemCount() != 0) { cursor.setVisible(true); } } }); // refresh tab on F5, copy cell on CTRL-C, etc KeyListener keyListener = new DataSetTableKeyListener(parent, table, cursor); cursor.addKeyListener(keyListener); table.addKeyListener(keyListener); // add context menu to table & cursor final DataSetTableActionGroup actionGroup = new DataSetTableActionGroup(table, cursor); MenuManager menuManager = new MenuManager("DataSetTableContextMenu");//$NON-NLS-1$ menuManager.setRemoveAllWhenShown(true); Menu contextMenu = menuManager.createContextMenu(table); tableViewer.getControl().setMenu(contextMenu); cursor.setMenu(contextMenu); menuManager.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { actionGroup.fillContextMenu(manager); } }); tableViewer.getTable().pack(); for (TableColumn column : tableViewer.getTable().getColumns()) column.pack(); } }