/*
* Copyright (C) SQL Explorer Development Team
*
* 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.plugin.views;
import net.sourceforge.sqlexplorer.Messages;
import net.sourceforge.sqlexplorer.history.SQLHistory;
import net.sourceforge.sqlexplorer.history.SQLHistoryChangedListener;
import net.sourceforge.sqlexplorer.history.SQLHistoryElement;
import net.sourceforge.sqlexplorer.history.SQLHistoryLabelProvider;
import net.sourceforge.sqlexplorer.history.SQLHistorySearchListener;
import net.sourceforge.sqlexplorer.history.actions.OpenInEditorAction;
import net.sourceforge.sqlexplorer.history.actions.RemoveFromHistoryAction;
import net.sourceforge.sqlexplorer.history.actions.SQLHistoryActionGroup;
import net.sourceforge.sqlexplorer.plugin.SQLExplorerPlugin;
import net.sourceforge.sqlexplorer.util.TextUtil;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
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.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;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
/**
* SQL History view shows all succesfully executed sql statements. The list of
* statements remains persistent between sessions.
*
* @modified Davy Vanherbergen
*/
public class SQLHistoryView extends ViewPart implements SQLHistoryChangedListener {
private Text _searchBox;
private Table _table;
private TableViewer _tableViewer;
private Label _tipLabelText;
private Point _tipPosition;
private Shell _tipShell;
private Widget _tipWidget;
/*
* (non-Javadoc)
*
* @see net.sourceforge.sqlexplorer.plugin.SqlHistoryChangedListener#changed()
*/
public void changed() {
_tableViewer.getTable().getDisplay().asyncExec(new Runnable() {
public void run() {
SQLHistory history = SQLExplorerPlugin.getDefault().getSQLHistory();
_tableViewer.setItemCount(history.getEntryCount());
_tableViewer.refresh();
}
});
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
public void createPartControl(final Composite parent) {
// MOD gdbu 2011-4-29 bug : 20960
SQLHistory tem_history = SQLExplorerPlugin.getDefault().getSQLHistory();
final SQLHistory history = tem_history == null ? new SQLHistory() : tem_history;
// ~20960
history.sort(1, SWT.DOWN);
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, SQLExplorerPlugin.PLUGIN_ID + ".SQLHistoryView");//$NON-NLS-1$
history.addListener(this);
Composite composite = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.marginLeft = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 2;
layout.marginWidth = 0;
layout.marginHeight = 0;
composite.setLayout(layout);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// add search box
_searchBox = new Text(composite, SWT.BORDER);
_searchBox.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
_searchBox.setText(Messages.getString("SQLHistoryView.SearchText"));//$NON-NLS-1$
_searchBox.selectAll();
SQLHistorySearchListener searchListener = new SQLHistorySearchListener(history);
_searchBox.addModifyListener(searchListener);
_searchBox.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
Text searchbox = (Text) e.widget;
if (searchbox.getText() != null
&& searchbox.getText().equals(Messages.getString("SQLHistoryView.SearchText"))) {
searchbox.setText("");
}
}
});
_tableViewer = new TableViewer(composite, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION | SWT.MULTI
| SWT.VIRTUAL);
getSite().setSelectionProvider(_tableViewer);
_table = _tableViewer.getTable();
_table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
_table.setHeaderVisible(true);
_table.setLinesVisible(true);
_table.setItemCount(history.getEntryCount());
_tableViewer.setLabelProvider(new SQLHistoryLabelProvider());
_tableViewer.setContentProvider(new IStructuredContentProvider() {
public void dispose() {
}
public Object[] getElements(Object inputElement) {
return SQLExplorerPlugin.getDefault().getSQLHistory().toArray();
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
});
_tableViewer.setInput(history);
// 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;
}
sortColumn = _table.getSortColumn();
TableColumn[] cols = _table.getColumns();
for (int i = 0; i < cols.length; i++) {
if (cols[i] == sortColumn) {
history.sort(i, dir);
break;
}
}
// update data displayed in table
_table.setSortDirection(dir);
_tableViewer.refresh();
}
};
String[] columnLabels = new String[] {Messages.getString("SQLHistoryView.Column.SQL"),
Messages.getString("SQLHistoryView.Column.Time"),
Messages.getString("SQLHistoryView.Column.Connection"),
Messages.getString("SQLHistoryView.Column.Executions")};
_tableViewer.setColumnProperties(columnLabels);
// add all column headers to our table
for (int i = 0; i < columnLabels.length; i++) {
// add column header
TableColumn column = new TableColumn(_table, SWT.LEFT);
column.setText(columnLabels[i]);
column.setMoveable(false);
column.setResizable(true);
column.addListener(SWT.Selection, sortListener);
}
_tableViewer.refresh();
// add sizing weights to the different columns
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnWeightData(7, 150));
tableLayout.addColumnData(new ColumnWeightData(2, 120));
tableLayout.addColumnData(new ColumnWeightData(1, 50));
tableLayout.addColumnData(new ColumnWeightData(1, 50));
_table.setLayout(tableLayout);
_table.layout();
// redraw table if view is resized
parent.addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
super.controlResized(e);
// reset weights in case of view resizing
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnWeightData(7, 150));
tableLayout.addColumnData(new ColumnWeightData(2, 120));
tableLayout.addColumnData(new ColumnWeightData(1, 50));
tableLayout.addColumnData(new ColumnWeightData(1, 50));
_table.setLayout(tableLayout);
}
});
// create action bar
final IToolBarManager toolBarMgr = getViewSite().getActionBars().getToolBarManager();
final SQLHistoryActionGroup actionGroup = new SQLHistoryActionGroup(this, history, _tableViewer, toolBarMgr);
_tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
actionGroup.refresh();
toolBarMgr.update(true);
}
});
// add context menus
final MenuManager menuMgr = new MenuManager("#HistoryPopupMenu");
menuMgr.setRemoveAllWhenShown(true);
Menu historyContextMenu = menuMgr.createContextMenu(_table);
_table.setMenu(historyContextMenu);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
toolBarMgr.markDirty();
actionGroup.fillContextMenu(manager);
}
});
// also add action as default when an entry is doubleclicked.
final OpenInEditorAction openInEditorAction = new OpenInEditorAction();
openInEditorAction.setTableViewer(_tableViewer);
openInEditorAction.setView(this);
_tableViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
openInEditorAction.run();
}
});
// add remove action on delete key
final RemoveFromHistoryAction removeFromHistoryAction = new RemoveFromHistoryAction();
removeFromHistoryAction.setTableViewer(_tableViewer);
_table.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
// delete entry
if (e.keyCode == SWT.DEL) {
removeFromHistoryAction.run();
}
}
});
// Set multi-line tooltip
final Display display = parent.getDisplay();
_tipShell = new Shell(parent.getShell(), SWT.ON_TOP);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
gridLayout.marginWidth = 2;
gridLayout.marginHeight = 2;
_tipShell.setLayout(gridLayout);
_tipShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
_tipLabelText = new Label(_tipShell, SWT.WRAP | SWT.LEFT);
_tipLabelText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
_tipLabelText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
GridData gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
_tipLabelText.setLayoutData(gridData);
_table.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
if (_tipShell.isVisible()) {
_tipShell.setVisible(false);
_tipWidget = null;
}
}
});
_table.addMouseTrackListener(new MouseTrackAdapter() {
public void mouseExit(MouseEvent e) {
if (_tipShell.isVisible())
_tipShell.setVisible(false);
_tipWidget = null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
*/
public void mouseHover(MouseEvent event) {
Point pt = new Point(event.x, event.y);
Widget widget = event.widget;
TableItem tableItem = null;
if (widget instanceof Table) {
Table table = (Table) widget;
widget = table.getItem(pt);
}
if (widget instanceof TableItem) {
tableItem = (TableItem) widget;
}
if (widget == null) {
_tipShell.setVisible(false);
_tipWidget = null;
return;
}
if (widget == _tipWidget)
return;
_tipWidget = widget;
_tipPosition = _table.toDisplay(pt);
SQLHistoryElement sqlString = (SQLHistoryElement) tableItem.getData();
String text = TextUtil.getWrappedText(sqlString.getRawSQLString());
if (text == null || text.equals("")) {
_tipWidget = null;
return;
}
// Set off the table tooltip as we provide our own
_table.setToolTipText("");
_tipLabelText.setText(text);
_tipShell.pack();
setHoverLocation(_tipShell, _tipPosition, _tipLabelText.getBounds().height);
_tipShell.setVisible(true);
}
});
_tableViewer.setSelection(null);
composite.layout();
parent.layout();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart#dispose()
*/
public void dispose() {
super.dispose();
SQLExplorerPlugin.getDefault().getSQLHistory().removeListener(this);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.IWorkbenchPart#setFocus()
*/
public void setFocus() {
// set focus to the search box
_searchBox.setFocus();
}
/**
* Sets the location for a hovering shell
*
* @param shell the object that is to hover
* @param position the position of a widget to hover over
* @return the top-left location for a hovering box
*/
private void setHoverLocation(Shell shell, Point position, int labelHeight) {
Rectangle displayBounds = shell.getDisplay().getBounds();
Rectangle shellBounds = shell.getBounds();
shellBounds.x = Math.max(Math.min(position.x, displayBounds.width - shellBounds.width), 0);
shellBounds.y = Math.max(Math.min(position.y + 10, displayBounds.height - shellBounds.height), 0);
if (shellBounds.y + labelHeight + 10 > displayBounds.height) {
shellBounds.y = Math.max(position.y - labelHeight - 10, 0);
}
shell.setBounds(shellBounds);
}
}