/*
* Copyright (c) 2008, SQL Power Group Inc.
*
* This file is part of SQL Power Library.
*
* SQL Power Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* SQL Power 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.swingui.db;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import org.apache.log4j.Logger;
import ca.sqlpower.sql.DataSourceCollection;
import ca.sqlpower.sql.DatabaseListChangeEvent;
import ca.sqlpower.sql.DatabaseListChangeListener;
import ca.sqlpower.sql.JDBCDataSource;
import ca.sqlpower.sql.Olap4jDataSource;
import ca.sqlpower.sql.SPDataSource;
import ca.sqlpower.swingui.Messages;
import ca.sqlpower.swingui.SPSUtils;
import ca.sqlpower.swingui.table.CleanupTableModel;
import ca.sqlpower.swingui.table.EditableJTable;
import com.jgoodies.forms.builder.ButtonStackBuilder;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.debug.FormDebugPanel;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
/**
* The database connection manager is a GUI facility for managing a DataSourceCollection.
* It allows users to add, edit, and delete database connection specs.
*/
public class DatabaseConnectionManager {
private static Logger logger = Logger.getLogger(DatabaseConnectionManager.class);
public static final Icon DB_ICON = new ImageIcon(DatabaseConnectionManager.class.getClassLoader().getResource("ca/sqlpower/swingui/db/connection-db-16.png"));
public static final Icon OLAP_DB_ICON = new ImageIcon(DatabaseConnectionManager.class.getClassLoader().getResource("ca/sqlpower/swingui/db/connection-olap-16.png"));
/**
* A property key that can be set with a value for any additional actions passed into the
* DatabaseConnectionManager constructor. If you set the Action to have a value of Boolean.TRUE
* with this key, then the DatabaseConnectionManager will disable the corresponding button
* it creates in the GUI for that action.
*/
public static final String DISABLE_IF_NO_CONNECTION_SELECTED = "disableIfNoConnectionSelected"; //$NON-NLS-1$
/**
* A property key that can be set with a value for any additional actions passed into the
* DatabaseConnectionManager constructor. This property can be set to SwingConstants values of
* CENTER, TOP, or BOTTOM to define the text to be placed at the center, top, or bottom of it's button.
*/
public static final String VERTICAL_TEXT_POSITION = "verticalTextPosition"; //$NON-NLS-1$
/**
* A property key that can be set with a value for any additional actions passed into the
* DatabaseConnectionManager constructor. This property can be set to a default height
* for the button.
*/
public static final String ADDITIONAL_BUTTON_HEIGHT = "additionalButtonHeight"; //$NON-NLS-1$
/**
* A property key that can be set with a value for any additional actions passed into the
* DatabaseConnectionManager constructor. This property can be set to SwingConstants values of
* LEFT, RIGHT, CENTER, LEADING, or TRAILING.
*/
public static final String HORIZONTAL_TEXT_POSITION = "horizontalTextPosition";
/**
* The GUI panel. Lives inside the dialog {@link #d}.
*/
private final JPanel panel;
/**
* The Dialog that contains all the GUI;
*/
private JDialog d;
/**
* The current owner of the dialog. Gets updated in the showDialog() method.
*/
private Window currentOwner;
private final DataSourceDialogFactory dsDialogFactory;
private final DataSourceTypeDialogFactory dsTypeDialogFactory;
/**
* This tracks the icon currently placed in the table of connections to the
* left of each database connection. Changing this icon will change the icon
* displayed in the table. This defaults to an orange database icon.
*/
private Icon dbIcon = DB_ICON;
private final Action jdbcDriversAction = new AbstractAction(Messages.getString("DatabaseConnectionManager.jdbcDriversActionName")){ //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
// Was previously: dsTypeDialogFactory.showDialog((d != null) ? d : DatabaseConnectionManager.this.currentOwner);
// However, this caused a bug where a ghost dialog was created after the jdbcDialog
// was closed. The jdbcDialog is now owned by a different window, and this dialog can be selected out from under
// it. This was the only way of having the jdbcDialog maintain its state between closings.
dsTypeDialogFactory.showDialog(DatabaseConnectionManager.this.currentOwner);
}
};
/**
* This action will create a new data source and allow the user to decide
* what kind of data source to create as well as allow the user to define
* data source properties.
*/
private class NewConnectionAction extends AbstractAction {
/**
* This component is used to define the position where the popup will
* appear. It should be the same position where the given component is.
*/
private final JComponent parentComponent;
public NewConnectionAction(String name, JComponent parentComponent) {
super(name);
this.parentComponent = parentComponent;
}
public void actionPerformed(ActionEvent e) {
if (creatableDSTypes.size() > 1) {
final JPopupMenu dsTypeMenu = new JPopupMenu();
dsTypeMenu.setLocation(parentComponent.getLocationOnScreen());
Iterator<Class<? extends SPDataSource>> iterator = creatableDSTypes.iterator();
while (iterator.hasNext()) {
final Class<? extends SPDataSource> dsType = iterator.next();
AbstractAction newDSAction = new AbstractAction(SPDataSource.getUserFriendlyName(dsType) + "...") {
public void actionPerformed(ActionEvent e) {
showNewDSDialog(dsType);
}
};
JMenuItem dsItem = new JMenuItem(newDSAction);
if (dsType.equals(JDBCDataSource.class)) {
dsItem.setIcon(DB_ICON);
} else if (dsType.equals(Olap4jDataSource.class)) {
dsItem.setIcon(OLAP_DB_ICON);
}
dsTypeMenu.add(dsItem);
}
dsTypeMenu.show(parentComponent, 0, 0);
} else {
Iterator<Class<? extends SPDataSource>> iterator = creatableDSTypes.iterator();
Class<? extends SPDataSource> dsTypeToCreate = iterator.next();
showNewDSDialog(dsTypeToCreate);
}
}
public void showNewDSDialog(Class<? extends SPDataSource> dsTypeToCreate) {
if (dsTypeToCreate.equals(JDBCDataSource.class)) {
final JDBCDataSource ds = new JDBCDataSource(getPlDotIni());
Runnable onOk = new Runnable() {
public void run() {
dsCollection.addDataSource(ds);
dsTable.updateUI();
}
};
dsDialogFactory.showDialog((d != null) ? d : DatabaseConnectionManager.this.currentOwner, ds, onOk);
} else if (dsTypeToCreate.equals(Olap4jDataSource.class)) {
final Olap4jDataSource ds = new Olap4jDataSource(getPlDotIni());
Runnable onOk = new Runnable() {
public void run() {
dsCollection.addDataSource(ds);
dsTable.updateUI();
}
};
dsDialogFactory.showDialog((d != null) ? d : DatabaseConnectionManager.this.currentOwner, ds, getPlDotIni(), onOk);
} else {
throw new IllegalStateException("Cannot make a new data source of type " + dsTypeToCreate);
}
}
}
private final Action editDatabaseConnectionAction = new AbstractAction(Messages.getString("DatabaseConnectionManager.editDbConnectionActionName")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
int selectedRow = dsTable.getSelectedRow();
if (selectedRow == -1) {
return;
}
final SPDataSource ds = (SPDataSource) dsTable.getValueAt(selectedRow,0);
if (ds instanceof JDBCDataSource) {
JDBCDataSource jdbcDS = (JDBCDataSource) ds;
Runnable onOk = createOnOk(ds);
dsDialogFactory.showDialog((d != null) ? d : DatabaseConnectionManager.this.currentOwner, jdbcDS, onOk);
} else if (ds instanceof Olap4jDataSource) {
Olap4jDataSource jdbcDS = (Olap4jDataSource) ds;
Runnable onOk = createOnOk(ds);
dsDialogFactory.showDialog((d != null) ? d : DatabaseConnectionManager.this.currentOwner, jdbcDS, getPlDotIni(), onOk);
} else {
throw new IllegalStateException("Unknown SPDataSource type in the connection manager. Type is " + ds.getClass());
}
}
private Runnable createOnOk(final SPDataSource ds) {
Runnable onOk = new Runnable() {
public void run() {
try {
for (int i = 0; i < dsTable.getRowCount(); i++) {
if (dsTable.getValueAt(i, 0) == ds) {
dsTable.setRowSelectionInterval(i, i);
dsTable.scrollRectToVisible(dsTable.getCellRect(i, 0, true));
dsTable.repaint();
break;
}
}
} catch (Exception ex) {
SPSUtils.showExceptionDialogNoReport(
(d != null) ? d : DatabaseConnectionManager.this.currentOwner,
"Unexpected exception while editing a database connection.", //$NON-NLS-1$
ex);
}
}
};
return onOk;
}
};
private final Action removeDatabaseConnectionAction = new AbstractAction(Messages.getString("DatabaseConnectionManager.removeDbConnectionActionName")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
int selectedRow = dsTable.getSelectedRow();
if (selectedRow == -1) {
return;
}
SPDataSource dbcs = (SPDataSource) dsTable.getValueAt(selectedRow,0);
int option = JOptionPane.showConfirmDialog(
(d != null) ? d : DatabaseConnectionManager.this.currentOwner,
Messages.getString("DatabaseConnectionManager.deleteDbConnectionConfirmation", dbcs.getName()), //$NON-NLS-1$
Messages.getString("DatabaseConnectionManager.removeButton"), //$NON-NLS-1$
JOptionPane.YES_NO_OPTION);
if (option != JOptionPane.YES_OPTION) {
return;
}
dsCollection.removeDataSource(dbcs);
dsTable.clearSelection();
for (JButton b : additionalActionButtons) {
Object disableValue = b.getAction().getValue(DISABLE_IF_NO_CONNECTION_SELECTED);
if (disableValue instanceof Boolean && disableValue.equals(Boolean.TRUE)) {
b.setEnabled(false);
}
}
removeDatabaseConnectionAction.setEnabled(false);
editDatabaseConnectionAction.setEnabled(false);
dsTable.repaint();
}
};
private final Action closeAction = new AbstractAction(Messages.getString("DatabaseConnectionManager.closeActionName")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
d.dispose();
}
};
/**
* The table that contains the list of all data sources in the
* user's collection of data sources.
*/
private JTable dsTable;
/**
* The data source collection of the session context this connection
* manager belongs to.
*/
private final DataSourceCollection<SPDataSource> dsCollection;
private List<JButton> additionalActionButtons = new ArrayList<JButton>();
/**
* This list contains all of the classes that are able to be created from
* the new button.
*/
private List<Class<? extends SPDataSource>> creatableDSTypes;
/**
* Creates a new database connection manager with the default data source
* and data source type dialog factories.
*
* @param dsCollection The data source collection to manage
*/
public DatabaseConnectionManager(DataSourceCollection<SPDataSource> dsCollection) {
this(dsCollection,
new DefaultDataSourceDialogFactory(),
new DefaultDataSourceTypeDialogFactory(dsCollection),
(List<Action>) Collections.EMPTY_LIST);
}
/**
* This constructor allows defining a parent window to start and gives the option to hide the
* close button. The main purpose of using this constructor would be to make a db connection
* manager that is to be placed in another panel.
*/
public DatabaseConnectionManager(DataSourceCollection<SPDataSource> dsCollection, DataSourceDialogFactory dsDialogFactory,
DataSourceTypeDialogFactory dsTypeDialogFactory, List<Action> additionalActions, List<JComponent> additionalComponents, Window owner, boolean showCloseButton) {
this(dsCollection, dsDialogFactory, dsTypeDialogFactory,
additionalActions, additionalComponents, owner, showCloseButton,
new ArrayList<Class<? extends SPDataSource>>(Collections.singleton((Class<? extends SPDataSource>) JDBCDataSource.class)));
}
/**
* Using this constructor over the other available constructors allows
* defining a connection manager that can create {@link SPDataSource} types
* other than the default {@link JDBCDataSource} type. If a constructor is
* used other then this one only new {@link JDBCDataSource} types will be
* able to be constructed although any {@link SPDataSource} type in the list
* will be editable.
*/
public DatabaseConnectionManager(DataSourceCollection<SPDataSource> dsCollection, DataSourceDialogFactory dsDialogFactory,
DataSourceTypeDialogFactory dsTypeDialogFactory, List<Action> additionalActions,
List<JComponent> additionalComponents, Window owner, boolean showCloseButton,
List<Class<? extends SPDataSource>> dsTypes) {
this.dsCollection = dsCollection;
this.dsDialogFactory = dsDialogFactory;
this.dsTypeDialogFactory = dsTypeDialogFactory;
logger.debug("Window owner is " + owner);
currentOwner = owner;
panel = createPanel(additionalActions, additionalComponents, showCloseButton, Messages.getString("DatabaseConnectionManager.availableDbConnections"));
creatableDSTypes = new ArrayList<Class<? extends SPDataSource>>(dsTypes);
}
/**
* Creates a new database connection manager with the default set of action buttons, plus
* those supplied in the given list.
*/
public DatabaseConnectionManager(DataSourceCollection<SPDataSource> dsCollection, DataSourceDialogFactory dsDialogFactory,
DataSourceTypeDialogFactory dsTypeDialogFactory, List<Action> additionalActions) {
this(dsCollection, dsDialogFactory, dsTypeDialogFactory, additionalActions, new ArrayList<JComponent>(), null, true);
}
/**
* Creates a new database connection manager with the default set of action buttons.
*
* @param dsCollection The data source collection to manage
* @param dsDialogFactory The factory that this manager will use to create all DataSource editor dialogs.
*/
@SuppressWarnings("unchecked")
public DatabaseConnectionManager(DataSourceCollection dsCollection, DataSourceDialogFactory dsDialogFactory,
DataSourceTypeDialogFactory dsTypeDialogFactory) {
this(dsCollection, dsDialogFactory, dsTypeDialogFactory, Collections.EMPTY_LIST);
}
/**
* Makes sure this database connection manager is visible,
* focused, and in a dialog owned by the given owner.
*
* @param owner the Frame or Dialog that should own the
* DatabaseConnectionManager dialog.
*/
public void showDialog(Window owner) {
if (d != null && d.isVisible() && currentOwner == owner) {
d.setVisible(true); // even if the dialog is already visible, this brings it to the front and gives it focus
d.requestFocus(); // this will rob focus from the previous focus owner
return;
}
if (d != null) {
d.dispose();
}
if (panel.getParent() != null) {
panel.getParent().remove(panel);
}
if (owner instanceof Dialog) {
d = new JDialog((Dialog) owner);
} else if (owner instanceof Frame) {
d = new JDialog((Frame) owner);
} else {
throw new IllegalArgumentException(
"Owner has to be a Frame or Dialog. You provided a " + //$NON-NLS-1$
(owner == null ? null : owner.getClass().getName()));
}
currentOwner = owner;
d.setTitle(Messages.getString("DatabaseConnectionManager.dialogTitle")); //$NON-NLS-1$
d.getContentPane().add(panel);
d.pack();
d.setLocationRelativeTo(owner);
SPSUtils.makeJDialogCancellable(d, closeAction);
d.setVisible(true);
d.requestFocus();
}
/**
* Closes the current dialog. It is safe to call this even if the dialog is not visible.
*/
public void closeDialog() {
if (d != null) {
d.dispose();
}
}
public void setDbIcon(Icon dbIcon) {
this.dbIcon = dbIcon;
}
/**
* This method returns the main panel in the database connection manager and additionally sets the dialog to be one
* that can be passed in. This is required for loading a project when a data source cannot be found. Wabit needs
* to pop up a window giving the user an option to skip the datasource, select a datasource or cancel the load
* and therefore this method can be used to create the proper panel and give it the proper parent so that it can
* then pop up dialogs.
*/
public JPanel createPanelStandalone(List<Action> additionalActions, List<JComponent> additionalComponents, boolean showCloseButton, String message, JDialog owner) {
d = owner;
return createPanel(additionalActions, additionalComponents, showCloseButton, message);
}
private JPanel createPanel(List<Action> additionalActions, List<JComponent> additionalComponents, boolean showCloseButton, String message) {
FormLayout layout = new FormLayout(
"6dlu, fill:min(160dlu;default):grow, 6dlu, pref, 6dlu", // columns //$NON-NLS-1$
" 6dlu,10dlu,6dlu,fill:min(180dlu;default):grow,10dlu"); // rows //$NON-NLS-1$
layout.setColumnGroups(new int [][] { {1,3,5}});
CellConstraints cc = new CellConstraints();
PanelBuilder pb;
JPanel p = logger.isDebugEnabled() ? new FormDebugPanel(layout) : new JPanel(layout);
pb = new PanelBuilder(layout,p);
pb.setDefaultDialogBorder();
pb.add(new JLabel(message), cc.xyw(2, 2, 3)); //$NON-NLS-1$
TableModel tm = new ConnectionTableModel(dsCollection);
dsTable = new EditableJTable(tm);
dsTable.setTableHeader(null);
dsTable.setShowGrid(false);
dsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
dsTable.addMouseListener(new DSTableMouseListener());
dsTable.setDefaultRenderer(SPDataSource.class, new ConnectionTableCellRenderer());
JScrollPane sp = new JScrollPane(dsTable);
sp.getViewport().setBackground(dsTable.getBackground());
pb.add(sp, cc.xy(2, 4));
ButtonStackBuilder bsb = new ButtonStackBuilder();
JButton newButton = new JButton();
AbstractAction newDatabaseConnectionAction = new NewConnectionAction(Messages.getString("DatabaseConnectionManager.newDbConnectionActionName"), newButton); //$NON-NLS-1$
newButton.setAction(newDatabaseConnectionAction);
bsb.addGridded(newButton);
bsb.addRelatedGap();
bsb.addGridded(new JButton(editDatabaseConnectionAction));
bsb.addRelatedGap();
bsb.addGridded(new JButton(removeDatabaseConnectionAction));
removeDatabaseConnectionAction.setEnabled(false);
editDatabaseConnectionAction.setEnabled(false);
bsb.addUnrelatedGap();
JButton jdbcDriversButton = new JButton(jdbcDriversAction);
bsb.addGridded(jdbcDriversButton);
for (Action a : additionalActions) {
bsb.addUnrelatedGap();
JButton b = new JButton(a);
Object disableValue = a.getValue(DISABLE_IF_NO_CONNECTION_SELECTED);
if (disableValue instanceof Boolean && disableValue.equals(Boolean.TRUE)) {
b.setEnabled(false);
}
Object heightValue = a.getValue(ADDITIONAL_BUTTON_HEIGHT);
if (heightValue instanceof Integer ) {
b.setPreferredSize(new Dimension((int) b.getPreferredSize().getWidth(), (Integer) heightValue));
}
Object verticalTextPos = a.getValue(VERTICAL_TEXT_POSITION);
if (verticalTextPos instanceof Integer) {
Integer verticalTextInt = (Integer) verticalTextPos;
if (verticalTextInt == SwingConstants.TOP || verticalTextInt == SwingConstants.BOTTOM || verticalTextInt == SwingConstants.CENTER) {
b.setVerticalTextPosition(verticalTextInt);
}
}
Object horizontalTextPos = a.getValue(HORIZONTAL_TEXT_POSITION);
if (horizontalTextPos instanceof Integer) {
Integer horizontalTextInt = (Integer) horizontalTextPos;
if (horizontalTextInt == SwingConstants.LEFT || horizontalTextInt == SwingConstants.RIGHT || horizontalTextInt == SwingConstants.CENTER
|| horizontalTextInt == SwingConstants.LEADING || horizontalTextInt == SwingConstants.TRAILING) {
b.setHorizontalTextPosition(horizontalTextInt);
}
}
additionalActionButtons.add(b);
bsb.addFixed(b);
}
for (JComponent comp : additionalComponents) {
bsb.addUnrelatedGap();
bsb.addFixed(comp);
}
if (showCloseButton) {
bsb.addUnrelatedGap();
bsb.addGridded(new JButton(closeAction));
}
pb.add(bsb.getPanel(), cc.xy(4,4));
return pb.getPanel();
}
private static class ConnectionTableModel extends AbstractTableModel implements CleanupTableModel {
private final DatabaseListChangeListener databaseListChangeListener = new DatabaseListChangeListener(){
public void databaseAdded(DatabaseListChangeEvent e) {
fireTableDataChanged();
}
public void databaseRemoved(DatabaseListChangeEvent e) {
fireTableDataChanged();
}
};
private final DataSourceCollection<SPDataSource> dsCollection;
public ConnectionTableModel(DataSourceCollection<SPDataSource> dsCollection) {
super();
this.dsCollection = dsCollection;
dsCollection.addDatabaseListChangeListener(databaseListChangeListener);
}
public int getRowCount() {
return dsCollection.getConnections().size();
}
public int getColumnCount() {
return 1;
}
@Override
public String getColumnName(int columnIndex) {
return Messages.getString("DatabaseConnectionManager.connectionName"); //$NON-NLS-1$
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return SPDataSource.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return dsCollection.getConnections().get(rowIndex);
}
public void cleanup() {
dsCollection.removeDatabaseListChangeListener(databaseListChangeListener);
}
}
private class ConnectionTableCellRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component comp = new DefaultTableCellRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (comp instanceof JLabel) {
if (value instanceof JDBCDataSource) {
((JLabel) comp).setIcon(dbIcon);
} else if (value instanceof Olap4jDataSource) {
((JLabel) comp).setIcon(OLAP_DB_ICON);
}
}
return comp;
}
}
public DataSourceCollection<SPDataSource> getPlDotIni() {
return dsCollection;
}
private class DSTableMouseListener implements MouseListener {
/**
* Updates the state of all buttons when a database connection is clicked on
* @param evt Mouse event
*/
private void updateAllButtonStates(MouseEvent evt) {
for (JButton b : additionalActionButtons) {
Object disableValue = b.getAction().getValue(DISABLE_IF_NO_CONNECTION_SELECTED);
if (disableValue instanceof Boolean && disableValue.equals(Boolean.TRUE)) {
if (getSelectedConnection() == null) {
b.setEnabled(false);
} else {
b.setEnabled(true);
}
}
}
if (getSelectedConnection() == null) {
removeDatabaseConnectionAction.setEnabled(false);
editDatabaseConnectionAction.setEnabled(false);
} else {
removeDatabaseConnectionAction.setEnabled(true);
editDatabaseConnectionAction.setEnabled(true);
}
}
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() == 2) {
editDatabaseConnectionAction.actionPerformed(null);
}
}
public void mousePressed(MouseEvent evt) {
updateAllButtonStates(evt);
}
public void mouseReleased(MouseEvent evt) {
updateAllButtonStates(evt);
}
public void mouseEntered(MouseEvent e) {
// we don't care
}
public void mouseExited(MouseEvent e) {
// we don't care
}
}
/**
* Returns the first selected spdatasource object from the list.
* Returns null if there are not any selected data sources
*/
public SPDataSource getSelectedConnection() {
int selectedRow = dsTable.getSelectedRow();
if (selectedRow == -1) {
return null;
}
return (SPDataSource) dsTable.getValueAt(selectedRow,0);
}
/**
* This will return the database connection manager as a panel
* so it can be placed in other panels rather than appearing
* in its own window.
*/
public JPanel getPanel() {
return panel;
}
}