/* * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata * * Portions of this software were developed by the Unidata Program at the * University Corporation for Atmospheric Research. * * Access and use of this software shall impose the following obligations * and understandings on the user. The user is granted the right, without * any fee or cost, to use, copy, modify, alter, enhance and distribute * this software, and any derivative works thereof, and its supporting * documentation for any purpose whatsoever, provided that this entire * notice appears in all copies of the software, derivative works and * supporting documentation. Further, UCAR requests that the user credit * UCAR/Unidata in any publications that result from the use of this * software or in any product that includes this software. The names UCAR * and/or Unidata, however, may not be used in any advertising or publicity * to endorse or promote any products or commercial entity unless specific * written permission is obtained from UCAR/Unidata. The user also * understands that UCAR/Unidata is not obligated to provide the user with * any support, consulting, training or assistance of any kind with regard * to the use, operation and performance of this software nor to provide * the user with any updates, revisions, new versions or "bug fixes." * * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. */ package thredds.ui.catalog; import thredds.client.catalog.*; import ucar.util.prefs.PreferencesExt; import ucar.util.prefs.XMLStore; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.Formatter; //import thredds.catalog.ui.tools.CatalogSearcher; /** * A Swing widget for THREDDS clients that combines a CatalogChooser, and optionally a QueryChooser * PropertyChangeEvent events are thrown to notify you of various * user actions; see addPropertyChangeListener. * <p/> * You can use the ThreddsDatasetChooser: * <ol> * <li> add the components into your own JTabbedPanel. * <li> wrapped in a JDialog for popping up * <li> as a standalone application through its main() method * </ol> * Example: * <pre> * datasetChooser = new ThreddsDatasetChooser( prefs, tabbedPane); * datasetChooser.addPropertyChangeListener( new java.beans.PropertyChangeListener() { * public void propertyChange( java.beans.PropertyChangeEvent e) { * if (e.getPropertyName().equals("Dataset")) { * thredds.catalog.InvDataset ds = (thredds.catalog.InvDataset) e.getNewValue(); * setDataset( ds); * } * } * } * }); * </pre> * <p/> * To use as popup dialog box: * <pre> * ThreddsDatasetChooser datasetChooser = new ThreddsDatasetChooser( prefs, null); * JDialog datasetChooserDialog = datasetChooser.makeDialog("Open THREDDS dataset", true); * datasetChooserDialog.show(); * </pre> * <p/> * When using as a standalone application, the default behavior is to write the dataURLs of the * selections to standard out. Copy main() and make changes as needed. * <pre> * java -classpath clientUI.jar;... thredds.catalog.ui.ThreddsDatasetChooser * </pre> * * @author John Caron */ public class ThreddsDatasetChooser extends JPanel { private final static String FRAME_SIZE = "FrameSize"; private CatalogChooser catalogChooser; private JTabbedPane tabbedPane; private boolean doResolve = false; // shoul we resolve Resolver datasets? private boolean pipeOut = true; // send results to standard out private boolean messageOut = false; // send results to popup message private JFrame frame; // need for popup messages private boolean debugResolve = false; /** * Usual Constructor. * Create a CatalogChooser and a QueryChooser widget, add them to a JTabbedPane. * * @param prefs persistent storage, may be null * @param tabs add panels to this JTabbedPane, may be null if you are using as Dialog. */ public ThreddsDatasetChooser(PreferencesExt prefs, JTabbedPane tabs) { this(prefs, tabs, null, false, false, false); } /** * General Constructor. * Create a CatalogChooser and a QueryChooser widget, add them to a JTabbedPane. * Optionally write to stdout and/or pop up event messsages. * * @param prefs persistent storage * @param tabs add to this JTabbedPane * @param frame best if non-null when messageOutP = true, otherwise null * @param pipeOutput send selection message to System.out * @param messageOutput send selection to popup message */ public ThreddsDatasetChooser(PreferencesExt prefs, JTabbedPane tabs, JFrame frame, boolean pipeOutput, boolean messageOutput, boolean addDqc) { this.frame = frame; this.pipeOut = pipeOutput; this.messageOut = messageOutput; // create the catalog chooser PreferencesExt node = (prefs == null) ? null : (PreferencesExt) prefs.node("catChooser"); catalogChooser = new CatalogChooser(node, true, true, true); catalogChooser.addPropertyChangeListener(new java.beans.PropertyChangeListener() { public void propertyChange(java.beans.PropertyChangeEvent e) { if (e.getPropertyName().equals("InvAccess")) { firePropertyChangeEvent(e); return; } // see if this dataset is really a qc if (e.getPropertyName().equals("Dataset") || e.getPropertyName().equals("CoordSys") || e.getPropertyName().equals("File")) { firePropertyChangeEvent(e); } } }); // the overall UI tabbedPane = (tabs == null) ? new JTabbedPane(JTabbedPane.TOP) : tabs; tabbedPane.addTab("Catalog Chooser", catalogChooser); tabbedPane.setSelectedComponent(catalogChooser); setLayout(new BorderLayout()); add(tabbedPane, BorderLayout.CENTER); } /** * If you want resolver datasets to be resolved (default false). * If true, may throw "Datasets" event. * * @param doResolve */ public void setDoResolve(boolean doResolve) { this.doResolve = doResolve; } /** * Get the component CatalogChooser */ public CatalogChooser getCatalogChooser() { return catalogChooser; } /** * save the state */ public void save() { catalogChooser.save(); } /** * Fires a PropertyChangeEvent: * <ul> * <li> propertyName = "Dataset" or "File", getNewValue() = InvDataset chosen. * <li> propertyName = "Datasets", getNewValue() = InvDataset[] chosen. This can only happen if * you have set doResolve = true, and the resolved dataset is a list of datasets. * <li> propertyName = "InvAccess" getNewValue() = InvAccess chosen. * </ul> */ private void firePropertyChangeEvent(PropertyChangeEvent event) { // System.out.println("firePropertyChangeEvent "+((InvDatasetImpl)ds).dump()); if (pipeOut) pipeEvent(event); if (messageOut) messageEvent(event); firePropertyChange(event.getPropertyName(), event.getOldValue(), event.getNewValue()); } private void messageEvent(java.beans.PropertyChangeEvent e) { Formatter buff = new Formatter(); buff.format("Event propertyName = %s", e.getPropertyName()); Object newValue = e.getNewValue(); if (newValue != null) buff.format(", class = %s", newValue.getClass().getName()); buff.format("%n"); if (e.getPropertyName().equals("Dataset")) { showDatasetInfo(buff, (thredds.client.catalog.Dataset) e.getNewValue()); } else if (e.getPropertyName().equals("Datasets")) { Object[] ds = (Object[]) e.getNewValue(); buff.format(" element class = %s%n", ds[0].getClass().getName()); for (int i = 0; i < ds.length; i++) if (ds[i] instanceof Dataset) showDatasetInfo(buff, (Dataset) ds[i]); } JOptionPane.showMessageDialog(frame, buff); } private void pipeEvent(java.beans.PropertyChangeEvent e) { Formatter buff = new Formatter(); if (e.getPropertyName().equals("Dataset")) { getAccessURLs(buff, (Dataset) e.getNewValue()); } else if (e.getPropertyName().equals("Datasets")) { Object[] ds = (Object[]) e.getNewValue(); for (int i = 0; i < ds.length; i++) if (ds[i] instanceof Dataset) getAccessURLs(buff, (Dataset) ds[i]); } System.out.println(buff); } private void getAccessURLs(Formatter buff, Dataset ds) { for (Access ac : ds.getAccess()) buff.format("%s %s %n", ac.getStandardUrlName(), ac.getService().getType()); } private void showDatasetInfo(Formatter buff, thredds.client.catalog.Dataset ds) { buff.format(" Dataset = %s", ds.getName()); buff.format(", dataType = %s%n", ds.getFeatureType()); for (Access ac : ds.getAccess()) { buff.format(" service = %s, url = %s%n", ac.getService().getType(), ac.getStandardUrlName()); //System.out.println(" url = "+ac.getStandardUrlName()); } } /** * Wrap this in a JDialog component. * * @param parent put dialog on top of this, may be null * @param title dialog window title * @param modal is modal */ public JDialog makeDialog(JFrame parent, String title, boolean modal) { return new Dialog(frame, title, modal); } private class Dialog extends JDialog { private Dialog(JFrame frame, String title, boolean modal) { super(frame, title, modal); // L&F may change UIManager.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals("lookAndFeel")) SwingUtilities.updateComponentTreeUI(ThreddsDatasetChooser.Dialog.this); } }); // add a dismiss button JButton dismissButton = new JButton("Dismiss"); //buttPanel.add(dismissButton, null); dismissButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { setVisible(false); } }); // add it to contentPane Container cp = getContentPane(); cp.setLayout(new BorderLayout()); cp.add(ThreddsDatasetChooser.this, BorderLayout.CENTER); pack(); } } /** * Standalone application. * * @param args recognized values: * <ul> <li> -usePopup to popup messages </ul> */ public static void main(String args[]) { boolean usePopup = false; for (int i = 0; i < args.length; i++) { if (args[i].equals("-usePopup")) usePopup = true; } try { store = XMLStore.createFromFile("ThreddsDatasetChooser", null); p = store.getPreferences(); } catch (IOException e) { System.out.println("XMLStore Creation failed " + e); } // put it together in a JFrame final JFrame frame = new JFrame("Thredds Dataset Chooser"); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { chooser.save(); Rectangle bounds = frame.getBounds(); p.putBeanObject(FRAME_SIZE, bounds); try { store.save(); } catch (IOException ioe) { ioe.printStackTrace(); } System.exit(0); } }); chooser = new ThreddsDatasetChooser(p, null, frame, true, usePopup, false); chooser.setDoResolve(true); // frame.getContentPane().add(chooser); Rectangle bounds = (Rectangle) p.getBean(FRAME_SIZE, new Rectangle(50, 50, 800, 450)); frame.setBounds(bounds); frame.pack(); frame.setBounds(bounds); frame.setVisible(true); } private static ThreddsDatasetChooser chooser; private static PreferencesExt p; private static XMLStore store; }