All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.ac.starlink.table.gui.TableSaveChooser Maven / Gradle / Ivy

package uk.ac.starlink.table.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import uk.ac.starlink.connect.FilestoreChooser;
import uk.ac.starlink.table.MultiStarTableWriter;
import uk.ac.starlink.table.StarTable;
import uk.ac.starlink.table.StarTableOutput;
import uk.ac.starlink.table.StarTableWriter;

/**
 * Dialog which permits a user to save one or more {@link StarTable}s in a
 * place and format of choice.  It should be able to provide suitable dialogs
 * for all the supported table types; in particular it includes a filestore
 * browser and special JDBC connection dialog.
 *
 * 

The usual way to use this is to implement {@link #getTables} to * provide the table which will be saved, and then call * {@link #showSaveDialog}. * * @author Mark Taylor (Starlink) */ public abstract class TableSaveChooser extends JPanel { private final JComboBox formatSelector_; private final JComponent[] activeComponents_; private final FilestoreChooser filestoreChooser_; private final List activeActionList_; private final Action[] tsdActions_; private StarTableOutput sto_; private JDialog dialog_; private JProgressBar progBar_; private SaveWorker worker_; /** * Constructs a saver with a default StarTableOutput and save dialogues. */ public TableSaveChooser() { this( new StarTableOutput(), new TableSaveDialog[] { new FilestoreTableSaveDialog(), new SystemTableSaveDialog(), } ); } /** * Constructs a saver with a given StarTableOutput and save dialogues. * * @param sto output marshaller * @param saveDialogs array of save dialogues to use */ public TableSaveChooser( StarTableOutput sto, TableSaveDialog[] saveDialogs ) { super( new BorderLayout() ); Border emptyBorder = BorderFactory.createEmptyBorder( 5, 5, 5, 5 ); Box actionBox = Box.createVerticalBox(); actionBox.setBorder( emptyBorder ); add( actionBox, BorderLayout.CENTER ); /* Prepare a list of components which can be enabled/disabled. */ List activeList = new ArrayList(); activeActionList_ = new ArrayList(); /* Construct and place format selector. */ JComponent formatBox = Box.createHorizontalBox(); formatBox.add( new JLabel( "Output Format: " ) ); formatSelector_ = new JComboBox() { public Dimension getMaximumSize() { return getPreferredSize(); } }; formatSelector_.setEditable( true ); formatBox.add( formatSelector_ ); activeList.add( formatSelector_ ); formatBox.setAlignmentX( LEFT_ALIGNMENT ); actionBox.add( formatBox ); setTableOutput( sto ); /* Construct and place location text entry field. */ final JTextField locField = new JTextField( 25 ); Action locAction = new AbstractAction( "OK" ) { public void actionPerformed( ActionEvent evt ) { submitLocation( locField.getText() ); } }; activeActionList_.add( locAction ); JComponent locBox = Box.createHorizontalBox(); locField.addActionListener( locAction ); locBox.add( new JLabel( "Location: " ) ); locBox.add( locField ); activeList.add( locField ); Dimension locSize = locBox.getPreferredSize(); locSize.width = 1024; locBox.setMaximumSize( locSize ); locBox.setAlignmentX( LEFT_ALIGNMENT ); locBox.add( Box.createHorizontalStrut( 5 ) ); locBox.add( new JButton( locAction ) ); actionBox.add( Box.createVerticalStrut( 5 ) ); actionBox.add( locBox ); /* Get a filestore chooser. If one of the dialogues we are using * is suitable, use that, otherwise just use a dummy one. */ FilestoreTableSaveDialog fsd = null; for ( int i = 0; fsd == null && i < saveDialogs.length; i++ ) { if ( saveDialogs[ i ] instanceof FilestoreTableSaveDialog ) { fsd = (FilestoreTableSaveDialog) saveDialogs[ i ]; } } if ( fsd == null ) { fsd = new FilestoreTableSaveDialog(); } filestoreChooser_ = fsd.getChooser(); /* Prepare buttons for each dialogue type. */ List buttList = new ArrayList(); List tsdActionList = new ArrayList(); for ( TableSaveDialog tsd : saveDialogs ) { Action tsdAction = createSaveDialogAction( tsd ); tsdActionList.add( tsdAction ); buttList.add( new JButton( tsdAction ) ); } JButton[] buttons = buttList.toArray( new JButton[ 0 ] ); tsdActions_ = tsdActionList.toArray( new Action[ 0 ] ); int nopt = buttons.length; /* Position buttons. */ int buttw = 0; for ( int i = 0; i < nopt; i++ ) { buttw = Math.max( buttw, buttons[ i ].getPreferredSize().width ); } JComponent dialogBox = Box.createVerticalBox(); for ( int i = 0; i < nopt; i++ ) { Dimension max = buttons[ i ].getMaximumSize(); max.width = buttw; buttons[ i ].setMaximumSize( max ); if ( i > 0 ) { dialogBox.add( Box.createVerticalStrut( 5 ) ); } dialogBox.add( buttons[ i ] ); } JPanel dialogLine = new JPanel( new FlowLayout( FlowLayout.RIGHT, 0, 0 ) ); dialogLine.add( dialogBox ); dialogLine.setAlignmentX( LEFT_ALIGNMENT ); actionBox.add( Box.createVerticalStrut( 10 ) ); actionBox.add( dialogLine ); /* Store list of components that can be enabled/disabled. */ activeComponents_ = activeList.toArray( new JComponent[ 0 ] ); } /** * Returns the FilestoreChooser, if any, used by this save dialogue. * * @return chooser */ FilestoreChooser getFilestoreChooser() { return filestoreChooser_; } /** * Sets the StarTableOutput object which this saver uses to do the * actual writing of the StarTables. * * @param sto the new StarTableOutput to use */ public void setTableOutput( StarTableOutput sto ) { sto_ = sto; formatSelector_.setModel( makeFormatBoxModel( sto, false ) ); } /** * Returns the StarTableOutput object which this saver uses to * do the actual writing of the StarTables. * * @return sto the StarTableOutput object */ public StarTableOutput getTableOutput() { return sto_; } /** * Returns the selector which chooses table output formats. * It may be replaced. * * @return format selector */ public JComboBox getFormatSelector() { return formatSelector_; } /** * Obtains the tables to write. This must be implemented by * concrete subclasses. * * @return table to write */ public abstract StarTable[] getTables(); /** * Sets the progress bar that will be used by this chooser. * Should be called before the component is displayed to the user. * * @param progBar progress bar for displaying save progress */ public void setProgressBar( JProgressBar progBar ) { progBar_ = progBar; } /** * Returns a progress bar to use for progress display when saving * directly from this chooser (not from one of the sub-dialogues). * * @return progress bar for display */ private JProgressBar getProgressBar() { return progBar_ == null ? new JProgressBar() : progBar_; } /** * Returns actions which correspond to the save dialogues this * saver is using. Each action is the result of an earlier call * to {@link #createSaveDialogAction}. * * @return array of actions which will trigger a particular save dialogue */ public Action[] getSaveDialogActions() { return tsdActions_; } /** * Called when the table has been written. */ public void done() { if ( dialog_ != null ) { dialog_.dispose(); } filestoreChooser_.refreshList(); } /** * Cancels the current operation - either the user interaction or * the saving of a table. */ private void cancel() { if ( worker_ != null ) { worker_.cancel(); worker_ = null; setEnabled( true ); } else if ( dialog_ != null ) { dialog_.dispose(); dialog_ = null; } } /** * Pops up a modal dialogue which interacts with the user to save * the tables returned by {@link #getTables}. * * @param parent parent component */ public void showSaveDialog( Component parent ) { dialog_ = createDialog( parent ); setProgressBar( new JProgressBar() ); dialog_.getContentPane().add( progBar_, BorderLayout.SOUTH ); setEnabled( true ); dialog_.pack(); dialog_.setVisible( true ); dialog_ = null; setProgressBar( null ); } public void setEnabled( boolean isEnabled ) { if ( isEnabled != isEnabled() ) { for ( JComponent c : activeComponents_ ) { c.setEnabled( isEnabled ); } for ( Action act : activeActionList_ ) { act.setEnabled( isEnabled ); } } super.setEnabled( isEnabled ); } /** * Returns the currently selected format string. * * @return format label */ public String getSelectedFormat() { return (String) formatSelector_.getSelectedItem(); } /** * Sets the currently selected format string. * * @param format format label */ public void setSelectedFormat( String format ) { formatSelector_.setSelectedItem( format ); } /** * Creates a dialogue which can be used for user interaction. * * @param parent parent component */ public JDialog createDialog( Component parent ) { /* Locate parent's frame. */ Frame frame = null; if ( parent != null ) { frame = parent instanceof Frame ? (Frame) parent : (Frame) SwingUtilities.getAncestorOfClass( Frame.class, parent ); } /* Create a new dialogue. */ final JDialog dialog = new JDialog( frame, "Save Table", true ); dialog.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE ); Container pane = new JPanel( new BorderLayout() ); dialog.getContentPane().setLayout( new BorderLayout() ); dialog.getContentPane().add( pane, BorderLayout.CENTER ); /* Place this component in it. */ pane.setLayout( new BorderLayout() ); pane.add( this, BorderLayout.CENTER ); /* Place a little icon. */ Box iconBox = Box.createVerticalBox(); iconBox.add( Box.createVerticalGlue() ); iconBox.add( new JLabel( UIManager .getIcon( "OptionPane.questionIcon" ) ) ); iconBox.add( Box.createVerticalGlue() ); iconBox.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); pane.add( iconBox, BorderLayout.WEST ); /* Place a cancel button. */ Action cancelAction = new AbstractAction( "Cancel" ) { public void actionPerformed( ActionEvent evt ) { cancel(); } }; Box cancelBox = Box.createHorizontalBox(); cancelBox.add( Box.createHorizontalGlue() ); cancelBox.add( new JButton( cancelAction ) ); cancelBox.add( Box.createHorizontalGlue() ); cancelBox.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); pane.add( cancelBox, BorderLayout.SOUTH ); /* Position. */ dialog.setLocationRelativeTo( parent ); return dialog; } /** * Returns an action which will result in the given save dialogue being * posted to allow the user to save this chooser's current table. * This method is invoked in the constructor, hence is declared final. * * @param tsd save dialogue * @return action to post tsd */ public final Action createSaveDialogAction( final TableSaveDialog tsd ) { final TableSaveChooser chooser = this; Action tsdAction = new AbstractAction( tsd.getName() ) { public void actionPerformed( ActionEvent evt ) { if ( tsd.showSaveDialog( chooser, chooser.getTableOutput(), chooser.formatSelector_.getModel(), chooser.getTables() ) ) { chooser.done(); } } }; tsdAction.putValue( Action.SHORT_DESCRIPTION, tsd.getDescription() ); tsdAction.putValue( Action.SMALL_ICON, tsd.getIcon() ); tsdAction.setEnabled( tsd.isAvailable() ); if ( tsdAction.isEnabled() ) { activeActionList_.add( tsdAction ); } return tsdAction; } /** * Called when the user has entered a filename in the main text box, * indicating that this is the location under which to save it. * * @param loc save location */ private void submitLocation( final String loc ) { final StarTableOutput sto = getTableOutput(); final String format = getSelectedFormat(); worker_ = new SaveWorker( getProgressBar(), getTables(), loc ) { protected void attemptSave( StarTable[] tables ) throws IOException { sto.writeStarTables( tables, loc, format ); } protected void done( boolean success ) { if ( success ) { TableSaveChooser.this.done(); } worker_ = null; setEnabled( true ); } }; setEnabled( false ); worker_.invoke(); } /** * Constructs a ComboBoxModel containing an entry for each of the * known output formats. * * @param sto output marshaller * @param multi true if multiple tables might be used, * false if only a single table will be written * @return format combo box model */ public static ComboBoxModel makeFormatBoxModel( StarTableOutput sto, boolean multi ) { DefaultComboBoxModel model = new DefaultComboBoxModel<>(); model.addElement( StarTableOutput.AUTO_HANDLER ); for ( StarTableWriter handler : sto.getHandlers() ) { if ( ! multi || handler instanceof MultiStarTableWriter ) { model.addElement( handler.getFormatName() ); } } for( String extra : getExtraWriterNames( multi ) ) { model.addElement( extra ); } return model; } /** * Returns a selection of output handler specifications that can be * offered to the user alongside the default-configuration ones. * * @param multi true if multiple tables might be used, * false if only a single table will be written * @return example/useful writer specifications including config options */ public static String[] getExtraWriterNames( boolean multi ) { List list = new ArrayList<>(); list.add( "votable(format=BINARY)" ); list.add( "votable(format=BINARY2)" ); if ( ! multi ) { list.add( "csv(header=false)" ); list.add( "ecsv(delimiter=comma)" ); list.add( "latex(standalone=true)" ); }; list.add( "html(standalone=true)" ); return list.toArray( new String[ 0 ] ); } /** Testing purposes only. */ public static void main( String[] args ) { final int nrow = Integer.parseInt( args[ 0 ] ); final uk.ac.starlink.table.ColumnStarTable tab = new uk.ac.starlink.table.ColumnStarTable() { public long getRowCount() { return (long) nrow; } }; tab.addColumn( new uk.ac.starlink.table.ColumnData( new uk.ac.starlink.table.ColumnInfo( "index", Integer.class, null ) ) { public Object readValue( long irow ) { return new Integer( (int) ( irow + 1 ) ); } } ); new TableSaveChooser() { public StarTable[] getTables() { return new StarTable[] { tab }; } }.showSaveDialog( null ); System.exit( 0 ); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy