package com.vividsolutions.jump.workbench.ui.plugin.datastore;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.task.TaskMonitor;
import com.vividsolutions.jump.util.LangUtil;
import com.vividsolutions.jump.workbench.WorkbenchContext;
import com.vividsolutions.jump.workbench.datastore.ConnectionDescriptor;
import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.plugin.ThreadedBasePlugIn;
import com.vividsolutions.jump.workbench.ui.task.TaskMonitorManager;
public class AddDatastoreLayerPanel extends ConnectionPanel {
private JTextArea whereTextArea = null;
private JComboBox geometryAttributeComboBox = null;
private JComboBox datasetComboBox = null;
private Map connectionDescriptorToDatasetNamesMap = new HashMap();
private JCheckBox cachingCheckBox = null;
// dummy constructor for JBuilder - do not use!!!
public AddDatastoreLayerPanel() {
super( null );
}
public AddDatastoreLayerPanel( WorkbenchContext context ) {
super( context );
initialize();
getConnectionComboBox().addActionListener(
new ActionListener() {
public void actionPerformed( ActionEvent e ) {
getDatasetComboBox().setSelectedItem( null );
}
} );
}
public static Object runInKillableThread( final String description,
WorkbenchContext context, final Block block ) {
final Object[] result = new Object[]{null};
// ThreadedBasePlugIn displays a dialog that the user can
// use to kill the thread by pressing the close button
// [Jon Aquino 2005-03-14]
AbstractPlugIn.toActionListener(
new ThreadedBasePlugIn() {
public String getName() {
return description;
}
public boolean execute( PlugInContext context ) throws Exception {
return true;
}
public void run( TaskMonitor monitor, PlugInContext context )
throws Exception {
monitor.report( description );
result[0] = block.yield();
}
}, context, new TaskMonitorManager() ).actionPerformed( null );
return result[0];
}
public String getDatasetName() {
return datasetComboBox.getSelectedItem() != null ? ( ( String ) datasetComboBox.getSelectedItem() ).trim()
: null;
}
public String getGeometryAttributeName() {
return geometryAttributeComboBox.getSelectedItem() != null ? ( ( String ) geometryAttributeComboBox.getSelectedItem() ).trim()
: null;
}
public String getWhereClause() {
return getWhereClauseProper().toLowerCase().startsWith( "where" ) ? getWhereClauseProper()
.substring( "where".length() ).trim()
: getWhereClauseProper();
}
public String getWhereClauseProper() {
return whereTextArea.getText().trim();
}
public boolean isCaching() {
return getCachingCheckBox().isSelected();
}
public void setCaching( boolean caching ) {
getCachingCheckBox().setSelected( caching );
}
public String validateInput() {
if ( super.validateInput() != null ) {
return super.validateInput();
}
if ( ( ( String ) LangUtil.ifNull( getDatasetName(), "" ) ).length() == 0 ) {
return I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Required-field-missing-Dataset");
}
if ( ( ( String ) LangUtil.ifNull( getGeometryAttributeName(), "" ) ).length() == 0 ) {
return I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Required-field-missing-Geometry");
}
return null;
}
private JTextArea getWhereTextArea() {
if ( whereTextArea == null ) {
whereTextArea = new JTextArea();
}
return whereTextArea;
}
private JComboBox getDatasetComboBox() {
if ( datasetComboBox == null ) {
datasetComboBox = new JComboBox();
datasetComboBox.setPreferredSize( new Dimension( MAIN_COLUMN_WIDTH,
( int ) datasetComboBox.getPreferredSize().getHeight() ) );
datasetComboBox.setEditable( true );
datasetComboBox.addActionListener(
new ActionListener() {
public void actionPerformed( ActionEvent e ) {
populateGeometryAttributeComboBox();
if ( geometryAttributeComboBox.getItemCount() > 0 ) {
geometryAttributeComboBox.setSelectedIndex( 0 );
}
}
} );
// Populate the dataset combobox only if the user pushes the
// drop-down button, as it requires a time-consuming query.
// The user can also simply type in the datset name. If they
// inadvertently press the drop-down button, they can press
// the X button on the progress dialog to kill the thread.
// [Jon Aquino 2005-03-14]
addSafePopupListener( datasetComboBox,
new Block() {
public Object yield() throws Exception {
populateDatasetComboBox();
return null;
}
} );
}
return datasetComboBox;
}
private JComboBox getGeometryAttributeComboBox() {
if ( geometryAttributeComboBox == null ) {
geometryAttributeComboBox = new JComboBox();
geometryAttributeComboBox.setPreferredSize( new Dimension(
MAIN_COLUMN_WIDTH, ( int ) geometryAttributeComboBox.getPreferredSize().getHeight() ) );
geometryAttributeComboBox.setEditable( true );
addSafePopupListener( geometryAttributeComboBox,
new Block() {
public Object yield() throws Exception {
populateGeometryAttributeComboBox();
return null;
}
} );
}
return geometryAttributeComboBox;
}
private JCheckBox getCachingCheckBox() {
if ( cachingCheckBox == null ) {
cachingCheckBox = new JCheckBox();
cachingCheckBox.setText( I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Cache-features"));
String s1= I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Prevents-unnecessary-queries-to-the-datastore");
String s2= I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.The-recommended-setting-is-to-leave-this-checked");
cachingCheckBox.setToolTipText( "<html>"+ s1 + "<br>"+s2+"</html>" );
cachingCheckBox.setSelected( true );
}
return cachingCheckBox;
}
private void populateGeometryAttributeComboBox() {
if ( getConnectionDescriptor() == null ) {
return;
}
if ( getDatasetName() == null ) {
return;
}
if ( getDatasetName().length() == 0 ) {
return;
}
try {
String selectedGeometryAttributeName = getGeometryAttributeName();
geometryAttributeComboBox.setModel( new DefaultComboBoxModel(
sortByString( geometryAttributeNames( getDatasetName(),
getConnectionDescriptor() ) ) ) );
geometryAttributeComboBox.setSelectedItem( selectedGeometryAttributeName );
} catch ( Exception e ) {
getContext().getErrorHandler().handleThrowable( e );
geometryAttributeComboBox.setModel( new DefaultComboBoxModel() );
}
}
private void populateDatasetComboBox() {
if ( getConnectionDescriptor() == null ) {
return;
}
try {
String selectedDatasetName = getDatasetName();
datasetComboBox.setModel( new DefaultComboBoxModel(
sortByString( datasetNames( getConnectionDescriptor() ) ) ) );
datasetComboBox.setSelectedItem( selectedDatasetName );
} catch ( Exception e ) {
getContext().getErrorHandler().handleThrowable( e );
datasetComboBox.setModel( new DefaultComboBoxModel() );
}
}
private String[] geometryAttributeNames( final String datasetName,
final ConnectionDescriptor connectionDescriptor ) throws Exception {
// Prompt for a password outside the ThreadedBasePlugIn thread,
// which is not the GUI thread. [Jon Aquino 2005-03-16]
new PasswordPrompter().getOpenConnection( connectionManager(),
connectionDescriptor, this );
// Retrieve the dataset names using a ThreadedBasePlugIn, so
// that the user can kill the thread if desired
// [Jon Aquino 2005-03-16]
return ( String[] ) runInKillableThread(
I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Retrieving-list-of-geometry-attributes"), getContext(),
new Block() {
public Object yield() throws Exception {
try {
return new PasswordPrompter().getOpenConnection(
connectionManager(), connectionDescriptor,
AddDatastoreLayerPanel.this ).getMetadata()
.getGeometryAttributeNames( datasetName );
} catch ( Exception e ) {
// Can get here if dataset name is not found in the
// datastore [Jon Aquino 2005-03-16]
e.printStackTrace( System.err );
return new String[]{};
}
}
} );
}
private String[] datasetNames(
final ConnectionDescriptor connectionDescriptor ) throws Exception {
if ( !connectionDescriptorToDatasetNamesMap.containsKey( connectionDescriptor ) ) {
// Prompt for a password outside the ThreadedBasePlugIn thread,
// which is not the GUI thread. [Jon Aquino 2005-03-11]
new PasswordPrompter().getOpenConnection( connectionManager(),
connectionDescriptor, this );
// Retrieve the dataset names using a ThreadedBasePlugIn, so
// that the user can kill the thread if desired
// [Jon Aquino 2005-03-11]
String[] datasetNames = ( String[] ) runInKillableThread(
I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Retrieving-list-of-datasets"), getContext(),
new Block() {
public Object yield() throws Exception {
return new PasswordPrompter().getOpenConnection(
connectionManager(), connectionDescriptor,
AddDatastoreLayerPanel.this ).getMetadata()
.getDatasetNames();
}
} );
// Don't cache the dataset array if it is empty, as a problem
// likely occurred. [Jon Aquino 2005-03-14]
if ( datasetNames.length != 0 ) {
connectionDescriptorToDatasetNamesMap.put( connectionDescriptor,
datasetNames );
}
}
return ( String[] ) connectionDescriptorToDatasetNamesMap.get( connectionDescriptor );
}
private void initialize() {
JScrollPane sp = new JScrollPane( getWhereTextArea() );
sp.setPreferredSize( new Dimension( MAIN_COLUMN_WIDTH, 100 ) );
addRow( I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Dataset"), getDatasetComboBox(), null, false );
addRow( I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Geometry"), getGeometryAttributeComboBox(), null, false );
addRow( I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Where"), sp, null, true );
addRow( I18N.get("jump.workbench.ui.plugin.datastore.AddDatastoreLayerPanel.Caching"), getCachingCheckBox(), null, false );
}
/**
* Workaround for undesirable Java 1.5 behaviour: after showing a dialog in
* the #popupMenuWillBecomeVisible event handler, the combobox popup would
* not hide.
*
* @param comboBox The feature to be added to the SafePopupListener
* attribute
* @param listener The feature to be added to the SafePopupListener
* attribute
*/
private void addSafePopupListener( final JComboBox comboBox,
final Block listener ) {
comboBox.addPopupMenuListener(
new PopupMenuListener() {
private boolean ignoringPopupEvent = false;
public void popupMenuCanceled( PopupMenuEvent e ) { }
public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) { }
public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {
if ( ignoringPopupEvent ) {
ignoringPopupEvent = false;
return;
}
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
comboBox.hidePopup();
try {
listener.yield();
} catch ( Exception e ) {
throw new RuntimeException( e );
} finally {
ignoringPopupEvent = true;
comboBox.showPopup();
}
}
} );
}
} );
}
public static interface Block {
public Object yield() throws Exception;
}
}// @jve:decl-index=0:visual-constraint="10,10"